View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import java.util.UUID;
20  
21  /**
22   * Static methods to convert a type into another, with endianness and bit ordering awareness.
23   *
24   * <p>
25   * The methods names follow a naming rule:<br>
26   * {@code <source type>[source endianness][source bit ordering]To<destination type>[destination endianness][destination bit ordering]}
27   * </p>
28   * <p>
29   * Source/destination type fields is one of the following:
30   * </p>
31   * <ul>
32   * <li>binary: an array of booleans</li>
33   * <li>byte or byteArray</li>
34   * <li>int or intArray</li>
35   * <li>long or longArray</li>
36   * <li>hex: a String containing hexadecimal digits (lowercase in destination)</li>
37   * <li>hexDigit: a Char containing a hexadecimal digit (lowercase in destination)</li>
38   * <li>uuid</li>
39   * </ul>
40   * <p>
41   * Endianness field: little-endian is the default, in this case the field is absent. In case of
42   * big-endian, the field is "Be".<br> Bit ordering: Lsb0 is the default, in this case the field
43   * is absent. In case of Msb0, the field is "Msb0".
44   * </p>
45   * <p>
46   * Example: intBeMsb0ToHex convert an int with big-endian byte order and Msb0 bit order into its
47   * hexadecimal string representation
48   * </p>
49   * <p>
50   * Most of the methods provide only default encoding for destination, this limits the number of
51   * ways to do one thing. Unless you are dealing with data from/to outside of the JVM platform,
52   * you should not need to use "Be" and "Msb0" methods.
53   * </p>
54   * <p>
55   * Development status: work on going, only a part of the little-endian, Lsb0 methods implemented
56   * so far.
57   * </p>
58   *
59   * @since 3.2
60   */
61  public class Conversion {
62  
63      private static final boolean[] TTTT = {true, true, true, true};
64      private static final boolean[] FTTT = {false, true, true, true};
65      private static final boolean[] TFTT = {true, false, true, true};
66      private static final boolean[] FFTT = {false, false, true, true};
67      private static final boolean[] TTFT = {true, true, false, true};
68      private static final boolean[] FTFT = {false, true, false, true};
69      private static final boolean[] TFFT = {true, false, false, true};
70      private static final boolean[] FFFT = {false, false, false, true};
71      private static final boolean[] TTTF = {true, true, true, false};
72      private static final boolean[] FTTF = {false, true, true, false};
73      private static final boolean[] TFTF = {true, false, true, false};
74      private static final boolean[] FFTF = {false, false, true, false};
75      private static final boolean[] TTFF = {true, true, false, false};
76      private static final boolean[] FTFF = {false, true, false, false};
77      private static final boolean[] TFFF = {true, false, false, false};
78      private static final boolean[] FFFF = {false, false, false, false};
79  
80      /**
81       * Converts the first 4 bits of a binary (represented as boolean array) in big-endian Msb0
82       * bit ordering to a hexadecimal digit.
83       *
84       * <p>
85       * (1, 0, 0, 0) is converted as follow: '8' (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0) is converted
86       * to '4'
87       * </p>
88       *
89       * @param src the binary to convert
90       * @return a hexadecimal digit representing the selected bits
91       * @throws IllegalArgumentException if {@code src} is empty
92       * @throws NullPointerException if {@code src} is {@code null}
93       */
94      public static char binaryBeMsb0ToHexDigit(final boolean[] src) {
95          return binaryBeMsb0ToHexDigit(src, 0);
96      }
97  
98      /**
99       * Converts a binary (represented as boolean array) in big-endian Msb0 bit ordering to a
100      * hexadecimal digit.
101      *
102      * <p>
103      * (1, 0, 0, 0) with srcPos = 0 is converted as follow: '8' (1, 0, 0, 0, 0, 0, 0, 0,
104      * 0, 0, 0, 1, 0, 1, 0, 0) with srcPos = 2 is converted to '5'
105      * </p>
106      *
107      * @param src the binary to convert
108      * @param srcPos the position of the lsb to start the conversion
109      * @return a hexadecimal digit representing the selected bits
110      * @throws IllegalArgumentException if {@code src} is empty
111      * @throws NullPointerException if {@code src} is {@code null}
112      * @throws IndexOutOfBoundsException if {@code srcPos} is outside the array.
113      */
114     public static char binaryBeMsb0ToHexDigit(final boolean[] src, final int srcPos) {
115         // JDK 9: Objects.checkIndex(int index, int length)
116         if (Integer.compareUnsigned(srcPos, src.length) >= 0) {
117             // Throw the correct exception
118             if (src.length == 0) {
119                 throw new IllegalArgumentException("Cannot convert an empty array.");
120             }
121             throw new IndexOutOfBoundsException(srcPos + " is not within array length " + src.length);
122         }
123         // Little-endian bit 0 position
124         final int pos = src.length - 1 - srcPos;
125         if (3 <= pos && src[pos - 3]) {
126             if (src[pos - 2]) {
127                 if (src[pos - 1]) {
128                     return src[pos] ? 'f' : 'e';
129                 }
130                 return src[pos] ? 'd' : 'c';
131             }
132             if (src[pos - 1]) {
133                 return src[pos] ? 'b' : 'a';
134             }
135             return src[pos] ? '9' : '8';
136         }
137         if (2 <= pos && src[pos - 2]) {
138             if (src[pos - 1]) {
139                 return src[pos] ? '7' : '6';
140             }
141             return src[pos] ? '5' : '4';
142         }
143         if (1 <= pos && src[pos - 1]) {
144             return src[pos] ? '3' : '2';
145         }
146         return src[pos] ? '1' : '0';
147     }
148 
149     /**
150      * Converts binary (represented as boolean array) into a byte using the default (little
151      * endian, Lsb0) byte and bit ordering.
152      *
153      * @param src the binary to convert
154      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
155      *            conversion
156      * @param dstInit initial value of the destination byte
157      * @param dstPos the position of the lsb, in bits, in the result byte
158      * @param nBools the number of booleans to convert
159      * @return a byte containing the selected bits
160      * @throws NullPointerException if {@code src} is {@code null}
161      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 8}
162      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
163      */
164     public static byte binaryToByte(final boolean[] src, final int srcPos, final byte dstInit, final int dstPos,
165             final int nBools) {
166         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
167             return dstInit;
168         }
169         if (nBools - 1 + dstPos >= 8) {
170             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 8");
171         }
172         byte out = dstInit;
173         for (int i = 0; i < nBools; i++) {
174             final int shift = i + dstPos;
175             final int bits = (src[i + srcPos] ? 1 : 0) << shift;
176             final int mask = 0x1 << shift;
177             out = (byte) (out & ~mask | bits);
178         }
179         return out;
180     }
181 
182     /**
183      * Converts binary (represented as boolean array) to a hexadecimal digit using the default
184      * (Lsb0) bit ordering.
185      *
186      * <p>
187      * (1, 0, 0, 0) is converted as follow: '1'
188      * </p>
189      *
190      * @param src the binary to convert
191      * @return a hexadecimal digit representing the selected bits
192      * @throws IllegalArgumentException if {@code src} is empty
193      * @throws NullPointerException if {@code src} is {@code null}
194      */
195     public static char binaryToHexDigit(final boolean[] src) {
196         return binaryToHexDigit(src, 0);
197     }
198 
199     /**
200      * Converts binary (represented as boolean array) to a hexadecimal digit using the default
201      * (Lsb0) bit ordering.
202      *
203      * <p>
204      * (1, 0, 0, 0) is converted as follow: '1'
205      * </p>
206      *
207      * @param src the binary to convert
208      * @param srcPos the position of the lsb to start the conversion
209      * @return a hexadecimal digit representing the selected bits
210      * @throws IllegalArgumentException if {@code src} is empty
211      * @throws NullPointerException if {@code src} is {@code null}
212      */
213     public static char binaryToHexDigit(final boolean[] src, final int srcPos) {
214         if (src.length == 0) {
215             throw new IllegalArgumentException("Cannot convert an empty array.");
216         }
217         if (src.length > srcPos + 3 && src[srcPos + 3]) {
218             if (src[srcPos + 2]) {
219                 if (src[srcPos + 1]) {
220                     return src[srcPos] ? 'f' : 'e';
221                 }
222                 return src[srcPos] ? 'd' : 'c';
223             }
224             if (src[srcPos + 1]) {
225                 return src[srcPos] ? 'b' : 'a';
226             }
227             return src[srcPos] ? '9' : '8';
228         }
229         if (src.length > srcPos + 2 && src[srcPos + 2]) {
230             if (src[srcPos + 1]) {
231                 return src[srcPos] ? '7' : '6';
232             }
233             return src[srcPos] ? '5' : '4';
234         }
235         if (src.length > srcPos + 1 && src[srcPos + 1]) {
236             return src[srcPos] ? '3' : '2';
237         }
238         return src[srcPos] ? '1' : '0';
239     }
240 
241     /**
242      * Converts binary (represented as boolean array) to a hexadecimal digit using the Msb0 bit
243      * ordering.
244      *
245      * <p>
246      * (1, 0, 0, 0) is converted as follow: '8'
247      * </p>
248      *
249      * @param src the binary to convert
250      * @return a hexadecimal digit representing the selected bits
251      * @throws IllegalArgumentException if {@code src} is empty, {@code src.length < 4} or
252      *             {@code src.length > 8}
253      * @throws NullPointerException if {@code src} is {@code null}
254      */
255     public static char binaryToHexDigitMsb0_4bits(final boolean[] src) {
256         return binaryToHexDigitMsb0_4bits(src, 0);
257     }
258 
259     /**
260      * Converts binary (represented as boolean array) to a hexadecimal digit using the Msb0 bit
261      * ordering.
262      *
263      * <p>
264      * (1, 0, 0, 0) is converted as follow: '8' (1, 0, 0, 1, 1, 0, 1, 0) with srcPos = 3 is converted
265      * to 'D'
266      * </p>
267      *
268      * @param src the binary to convert
269      * @param srcPos the position of the lsb to start the conversion
270      * @return a hexadecimal digit representing the selected bits
271      * @throws IllegalArgumentException if {@code src} is empty, {@code src.length > 8} or
272      *             {@code src.length - srcPos < 4}
273      * @throws NullPointerException if {@code src} is {@code null}
274      */
275     public static char binaryToHexDigitMsb0_4bits(final boolean[] src, final int srcPos) {
276         if (src.length > 8) {
277             throw new IllegalArgumentException("src.length>8: src.length=" + src.length);
278         }
279         if (src.length - srcPos < 4) {
280             throw new IllegalArgumentException("src.length-srcPos<4: src.length=" + src.length + ", srcPos=" + srcPos);
281         }
282         if (src[srcPos + 3]) {
283             if (src[srcPos + 2]) {
284                 if (src[srcPos + 1]) {
285                     return src[srcPos] ? 'f' : '7';
286                 }
287                 return src[srcPos] ? 'b' : '3';
288             }
289             if (src[srcPos + 1]) {
290                 return src[srcPos] ? 'd' : '5';
291             }
292             return src[srcPos] ? '9' : '1';
293         }
294         if (src[srcPos + 2]) {
295             if (src[srcPos + 1]) {
296                 return src[srcPos] ? 'e' : '6';
297             }
298             return src[srcPos] ? 'a' : '2';
299         }
300         if (src[srcPos + 1]) {
301             return src[srcPos] ? 'c' : '4';
302         }
303         return src[srcPos] ? '8' : '0';
304     }
305 
306     /**
307      * Converts binary (represented as boolean array) into an int using the default (little
308      * endian, Lsb0) byte and bit ordering.
309      *
310      * @param src the binary to convert
311      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
312      *            conversion
313      * @param dstInit initial value of the destination int
314      * @param dstPos the position of the lsb, in bits, in the result int
315      * @param nBools the number of booleans to convert
316      * @return an int containing the selected bits
317      * @throws NullPointerException if {@code src} is {@code null}
318      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 32}
319      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
320      */
321     public static int binaryToInt(final boolean[] src, final int srcPos, final int dstInit, final int dstPos,
322             final int nBools) {
323         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
324             return dstInit;
325         }
326         if (nBools - 1 + dstPos >= 32) {
327             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 32");
328         }
329         int out = dstInit;
330         for (int i = 0; i < nBools; i++) {
331             final int shift = i + dstPos;
332             final int bits = (src[i + srcPos] ? 1 : 0) << shift;
333             final int mask = 0x1 << shift;
334             out = out & ~mask | bits;
335         }
336         return out;
337     }
338 
339     /**
340      * Converts binary (represented as boolean array) into a long using the default (little
341      * endian, Lsb0) byte and bit ordering.
342      *
343      * @param src the binary to convert
344      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
345      *            conversion
346      * @param dstInit initial value of the destination long
347      * @param dstPos the position of the lsb, in bits, in the result long
348      * @param nBools the number of booleans to convert
349      * @return a long containing the selected bits
350      * @throws NullPointerException if {@code src} is {@code null}
351      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 64}
352      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
353      */
354     public static long binaryToLong(final boolean[] src, final int srcPos, final long dstInit, final int dstPos,
355             final int nBools) {
356         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
357             return dstInit;
358         }
359         if (nBools - 1 + dstPos >= 64) {
360             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 64");
361         }
362         long out = dstInit;
363         for (int i = 0; i < nBools; i++) {
364             final int shift = i + dstPos;
365             final long bits = (src[i + srcPos] ? 1L : 0) << shift;
366             final long mask = 0x1L << shift;
367             out = out & ~mask | bits;
368         }
369         return out;
370     }
371 
372     /**
373      * Converts binary (represented as boolean array) into a short using the default (little
374      * endian, Lsb0) byte and bit ordering.
375      *
376      * @param src the binary to convert
377      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
378      *            conversion
379      * @param dstInit initial value of the destination short
380      * @param dstPos the position of the lsb, in bits, in the result short
381      * @param nBools the number of booleans to convert
382      * @return a short containing the selected bits
383      * @throws NullPointerException if {@code src} is {@code null}
384      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 16}
385      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
386      */
387     public static short binaryToShort(final boolean[] src, final int srcPos, final short dstInit, final int dstPos,
388             final int nBools) {
389         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
390             return dstInit;
391         }
392         if (nBools - 1 + dstPos >= 16) {
393             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 16");
394         }
395         short out = dstInit;
396         for (int i = 0; i < nBools; i++) {
397             final int shift = i + dstPos;
398             final int bits = (src[i + srcPos] ? 1 : 0) << shift;
399             final int mask = 0x1 << shift;
400             out = (short) (out & ~mask | bits);
401         }
402         return out;
403     }
404 
405     /**
406      * Converts an array of byte into an int using the default (little-endian, Lsb0) byte and bit
407      * ordering.
408      *
409      * @param src the byte array to convert
410      * @param srcPos the position in {@code src}, in byte unit, from where to start the
411      *            conversion
412      * @param dstInit initial value of the destination int
413      * @param dstPos the position of the lsb, in bits, in the result int
414      * @param nBytes the number of bytes to convert
415      * @return an int containing the selected bits
416      * @throws NullPointerException if {@code src} is {@code null}
417      * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 32}
418      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
419      */
420     public static int byteArrayToInt(final byte[] src, final int srcPos, final int dstInit, final int dstPos,
421             final int nBytes) {
422         if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
423             return dstInit;
424         }
425         if ((nBytes - 1) * 8 + dstPos >= 32) {
426             throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greater or equal to than 32");
427         }
428         int out = dstInit;
429         for (int i = 0; i < nBytes; i++) {
430             final int shift = i * 8 + dstPos;
431             final int bits = (0xff & src[i + srcPos]) << shift;
432             final int mask = 0xff << shift;
433             out = out & ~mask | bits;
434         }
435         return out;
436     }
437 
438     /**
439      * Converts an array of byte into a long using the default (little-endian, Lsb0) byte and
440      * bit ordering.
441      *
442      * @param src the byte array to convert
443      * @param srcPos the position in {@code src}, in byte unit, from where to start the
444      *            conversion
445      * @param dstInit initial value of the destination long
446      * @param dstPos the position of the lsb, in bits, in the result long
447      * @param nBytes the number of bytes to convert
448      * @return a long containing the selected bits
449      * @throws NullPointerException if {@code src} is {@code null}
450      * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 64}
451      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
452      */
453     public static long byteArrayToLong(final byte[] src, final int srcPos, final long dstInit, final int dstPos,
454             final int nBytes) {
455         if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
456             return dstInit;
457         }
458         if ((nBytes - 1) * 8 + dstPos >= 64) {
459             throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greater or equal to than 64");
460         }
461         long out = dstInit;
462         for (int i = 0; i < nBytes; i++) {
463             final int shift = i * 8 + dstPos;
464             final long bits = (0xffL & src[i + srcPos]) << shift;
465             final long mask = 0xffL << shift;
466             out = out & ~mask | bits;
467         }
468         return out;
469     }
470 
471     /**
472      * Converts an array of byte into a short using the default (little-endian, Lsb0) byte and
473      * bit ordering.
474      *
475      * @param src the byte array to convert
476      * @param srcPos the position in {@code src}, in byte unit, from where to start the
477      *            conversion
478      * @param dstInit initial value of the destination short
479      * @param dstPos the position of the lsb, in bits, in the result short
480      * @param nBytes the number of bytes to convert
481      * @return a short containing the selected bits
482      * @throws NullPointerException if {@code src} is {@code null}
483      * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 16}
484      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
485      */
486     public static short byteArrayToShort(final byte[] src, final int srcPos, final short dstInit, final int dstPos,
487             final int nBytes) {
488         if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
489             return dstInit;
490         }
491         if ((nBytes - 1) * 8 + dstPos >= 16) {
492             throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greater or equal to than 16");
493         }
494         short out = dstInit;
495         for (int i = 0; i < nBytes; i++) {
496             final int shift = i * 8 + dstPos;
497             final int bits = (0xff & src[i + srcPos]) << shift;
498             final int mask = 0xff << shift;
499             out = (short) (out & ~mask | bits);
500         }
501         return out;
502     }
503 
504     /**
505      * Converts bytes from an array into a UUID using the default (little-endian, Lsb0) byte and
506      * bit ordering.
507      *
508      * @param src the byte array to convert
509      * @param srcPos the position in {@code src} where to copy the result from
510      * @return a UUID
511      * @throws NullPointerException if {@code src} is {@code null}
512      * @throws IllegalArgumentException if array does not contain at least 16 bytes beginning
513      *             with {@code srcPos}
514      */
515     public static UUID byteArrayToUuid(final byte[] src, final int srcPos) {
516         if (src.length - srcPos < 16) {
517             throw new IllegalArgumentException("Need at least 16 bytes for UUID");
518         }
519         return new UUID(byteArrayToLong(src, srcPos, 0, 0, 8), byteArrayToLong(src, srcPos + 8, 0, 0, 8));
520     }
521 
522     /**
523      * Converts a byte into an array of boolean using the default (little-endian, Lsb0) byte and
524      * bit ordering.
525      *
526      * @param src the byte to convert
527      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
528      * @param dst the destination array
529      * @param dstPos the position in {@code dst} where to copy the result
530      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
531      *            the width of the input (from srcPos to msb)
532      * @return {@code dst}
533      * @throws NullPointerException if {@code dst} is {@code null}
534      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 8}
535      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
536      */
537     public static boolean[] byteToBinary(final byte src, final int srcPos, final boolean[] dst, final int dstPos,
538             final int nBools) {
539         if (0 == nBools) {
540             return dst;
541         }
542         if (nBools - 1 + srcPos >= 8) {
543             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 8");
544         }
545         for (int i = 0; i < nBools; i++) {
546             final int shift = i + srcPos;
547             dst[dstPos + i] = (0x1 & src >> shift) != 0;
548         }
549         return dst;
550     }
551 
552     /**
553      * Converts a byte into an array of Char using the default (little-endian, Lsb0) byte and
554      * bit ordering.
555      *
556      * @param src the byte to convert
557      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
558      * @param dstInit the initial value for the result String
559      * @param dstPos the position in {@code dst} where to copy the result
560      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
561      *            width of the input (from srcPos to msb)
562      * @return {@code dst}
563      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 8}
564      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
565      */
566     public static String byteToHex(final byte src, final int srcPos, final String dstInit, final int dstPos,
567             final int nHexs) {
568         if (0 == nHexs) {
569             return dstInit;
570         }
571         if ((nHexs - 1) * 4 + srcPos >= 8) {
572             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 8");
573         }
574         final StringBuilder sb = new StringBuilder(dstInit);
575         int append = sb.length();
576         for (int i = 0; i < nHexs; i++) {
577             final int shift = i * 4 + srcPos;
578             final int bits = 0xF & src >> shift;
579             if (dstPos + i == append) {
580                 ++append;
581                 sb.append(intToHexDigit(bits));
582             } else {
583                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
584             }
585         }
586         return sb.toString();
587     }
588 
589     /**
590      * Converts a hexadecimal digit into binary (represented as boolean array) using the Msb0
591      * bit ordering.
592      *
593      * <p>
594      * '1' is converted as follow: (0, 0, 0, 1)
595      * </p>
596      *
597      * @param hexDigit the hexadecimal digit to convert
598      * @return a boolean array with the binary representation of {@code hexDigit}
599      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
600      */
601     public static boolean[] hexDigitMsb0ToBinary(final char hexDigit) {
602         switch (hexDigit) {
603         case '0':
604             return FFFF.clone();
605         case '1':
606             return FFFT.clone();
607         case '2':
608             return FFTF.clone();
609         case '3':
610             return FFTT.clone();
611         case '4':
612             return FTFF.clone();
613         case '5':
614             return FTFT.clone();
615         case '6':
616             return FTTF.clone();
617         case '7':
618             return FTTT.clone();
619         case '8':
620             return TFFF.clone();
621         case '9':
622             return TFFT.clone();
623         case 'a':// fall through
624         case 'A':
625             return TFTF.clone();
626         case 'b':// fall through
627         case 'B':
628             return TFTT.clone();
629         case 'c':// fall through
630         case 'C':
631             return TTFF.clone();
632         case 'd':// fall through
633         case 'D':
634             return TTFT.clone();
635         case 'e':// fall through
636         case 'E':
637             return TTTF.clone();
638         case 'f':// fall through
639         case 'F':
640             return TTTT.clone();
641         default:
642             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
643         }
644     }
645 
646     /**
647      * Converts a hexadecimal digit into an int using the Msb0 bit ordering.
648      *
649      * <p>
650      * '1' is converted to 8
651      * </p>
652      *
653      * @param hexDigit the hexadecimal digit to convert
654      * @return an int equals to {@code hexDigit}
655      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
656      */
657     public static int hexDigitMsb0ToInt(final char hexDigit) {
658         switch (hexDigit) {
659         case '0':
660             return 0x0;
661         case '1':
662             return 0x8;
663         case '2':
664             return 0x4;
665         case '3':
666             return 0xC;
667         case '4':
668             return 0x2;
669         case '5':
670             return 0xA;
671         case '6':
672             return 0x6;
673         case '7':
674             return 0xE;
675         case '8':
676             return 0x1;
677         case '9':
678             return 0x9;
679         case 'a':// fall through
680         case 'A':
681             return 0x5;
682         case 'b':// fall through
683         case 'B':
684             return 0xD;
685         case 'c':// fall through
686         case 'C':
687             return 0x3;
688         case 'd':// fall through
689         case 'D':
690             return 0xB;
691         case 'e':// fall through
692         case 'E':
693             return 0x7;
694         case 'f':// fall through
695         case 'F':
696             return 0xF;
697         default:
698             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
699         }
700     }
701 
702     /**
703      * Converts a hexadecimal digit into binary (represented as boolean array) using the default
704      * (Lsb0) bit ordering.
705      *
706      * <p>
707      * '1' is converted as follow: (1, 0, 0, 0)
708      * </p>
709      *
710      * @param hexDigit the hexadecimal digit to convert
711      * @return a boolean array with the binary representation of {@code hexDigit}
712      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
713      */
714     public static boolean[] hexDigitToBinary(final char hexDigit) {
715         switch (hexDigit) {
716         case '0':
717             return FFFF.clone();
718         case '1':
719             return TFFF.clone();
720         case '2':
721             return FTFF.clone();
722         case '3':
723             return TTFF.clone();
724         case '4':
725             return FFTF.clone();
726         case '5':
727             return TFTF.clone();
728         case '6':
729             return FTTF.clone();
730         case '7':
731             return TTTF.clone();
732         case '8':
733             return FFFT.clone();
734         case '9':
735             return TFFT.clone();
736         case 'a':// fall through
737         case 'A':
738             return FTFT.clone();
739         case 'b':// fall through
740         case 'B':
741             return TTFT.clone();
742         case 'c':// fall through
743         case 'C':
744             return FFTT.clone();
745         case 'd':// fall through
746         case 'D':
747             return TFTT.clone();
748         case 'e':// fall through
749         case 'E':
750             return FTTT.clone();
751         case 'f':// fall through
752         case 'F':
753             return TTTT.clone();
754         default:
755             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
756         }
757     }
758 
759     /**
760      * Converts a hexadecimal digit into an int using the default (Lsb0) bit ordering.
761      *
762      * <p>
763      * '1' is converted to 1
764      * </p>
765      *
766      * @param hexDigit the hexadecimal digit to convert
767      * @return an int equals to {@code hexDigit}
768      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
769      */
770     public static int hexDigitToInt(final char hexDigit) {
771         final int digit = Character.digit(hexDigit, 16);
772         if (digit < 0) {
773             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
774         }
775         return digit;
776     }
777 
778     /**
779      * Converts a hexadecimal string into a byte using the default (little-endian, Lsb0) byte and
780      * bit ordering.
781      *
782      * @param src the hexadecimal string to convert
783      * @param srcPos the position in {@code src}, in Char unit, from where to start the
784      *            conversion
785      * @param dstInit initial value of the destination byte
786      * @param dstPos the position of the lsb, in bits, in the result byte
787      * @param nHex the number of Chars to convert
788      * @return a byte containing the selected bits
789      * @throws IllegalArgumentException if {@code (nHex-1)*4+dstPos >= 8}
790      */
791     public static byte hexToByte(final String src, final int srcPos, final byte dstInit, final int dstPos,
792             final int nHex) {
793         if (0 == nHex) {
794             return dstInit;
795         }
796         if ((nHex - 1) * 4 + dstPos >= 8) {
797             throw new IllegalArgumentException("(nHex-1)*4+dstPos is greater than or equal to 8");
798         }
799         byte out = dstInit;
800         for (int i = 0; i < nHex; i++) {
801             final int shift = i * 4 + dstPos;
802             final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
803             final int mask = 0xf << shift;
804             out = (byte) (out & ~mask | bits);
805         }
806         return out;
807     }
808 
809     /**
810      * Converts an array of Char into an int using the default (little-endian, Lsb0) byte and bit
811      * ordering.
812      *
813      * @param src the hexadecimal string to convert
814      * @param srcPos the position in {@code src}, in Char unit, from where to start the
815      *            conversion
816      * @param dstInit initial value of the destination int
817      * @param dstPos the position of the lsb, in bits, in the result int
818      * @param nHex the number of Chars to convert
819      * @return an int containing the selected bits
820      * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 32}
821      */
822     public static int hexToInt(final String src, final int srcPos, final int dstInit, final int dstPos, final int nHex) {
823         if (0 == nHex) {
824             return dstInit;
825         }
826         if ((nHex - 1) * 4 + dstPos >= 32) {
827             throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 32");
828         }
829         int out = dstInit;
830         for (int i = 0; i < nHex; i++) {
831             final int shift = i * 4 + dstPos;
832             final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
833             final int mask = 0xf << shift;
834             out = out & ~mask | bits;
835         }
836         return out;
837     }
838 
839     /**
840      * Converts an array of Char into a long using the default (little-endian, Lsb0) byte and
841      * bit ordering.
842      *
843      * @param src the hexadecimal string to convert
844      * @param srcPos the position in {@code src}, in Char unit, from where to start the
845      *            conversion
846      * @param dstInit initial value of the destination long
847      * @param dstPos the position of the lsb, in bits, in the result long
848      * @param nHex the number of Chars to convert
849      * @return a long containing the selected bits
850      * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 64}
851      */
852     public static long hexToLong(final String src, final int srcPos, final long dstInit, final int dstPos,
853             final int nHex) {
854         if (0 == nHex) {
855             return dstInit;
856         }
857         if ((nHex - 1) * 4 + dstPos >= 64) {
858             throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 64");
859         }
860         long out = dstInit;
861         for (int i = 0; i < nHex; i++) {
862             final int shift = i * 4 + dstPos;
863             final long bits = (0xfL & hexDigitToInt(src.charAt(i + srcPos))) << shift;
864             final long mask = 0xfL << shift;
865             out = out & ~mask | bits;
866         }
867         return out;
868     }
869 
870     /**
871      * Converts an array of Char into a short using the default (little-endian, Lsb0) byte and
872      * bit ordering.
873      *
874      * @param src the hexadecimal string to convert
875      * @param srcPos the position in {@code src}, in Char unit, from where to start the
876      *            conversion
877      * @param dstInit initial value of the destination short
878      * @param dstPos the position of the lsb, in bits, in the result short
879      * @param nHex the number of Chars to convert
880      * @return a short containing the selected bits
881      * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 16}
882      */
883     public static short hexToShort(final String src, final int srcPos, final short dstInit, final int dstPos,
884             final int nHex) {
885         if (0 == nHex) {
886             return dstInit;
887         }
888         if ((nHex - 1) * 4 + dstPos >= 16) {
889             throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 16");
890         }
891         short out = dstInit;
892         for (int i = 0; i < nHex; i++) {
893             final int shift = i * 4 + dstPos;
894             final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
895             final int mask = 0xf << shift;
896             out = (short) (out & ~mask | bits);
897         }
898         return out;
899     }
900 
901     /**
902      * Converts an array of int into a long using the default (little-endian, Lsb0) byte and bit
903      * ordering.
904      *
905      * @param src the int array to convert
906      * @param srcPos the position in {@code src}, in int unit, from where to start the
907      *            conversion
908      * @param dstInit initial value of the destination long
909      * @param dstPos the position of the lsb, in bits, in the result long
910      * @param nInts the number of ints to convert
911      * @return a long containing the selected bits
912      * @throws IllegalArgumentException if {@code (nInts-1)*32+dstPos >= 64}
913      * @throws NullPointerException if {@code src} is {@code null}
914      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nInts > src.length}
915      */
916     public static long intArrayToLong(final int[] src, final int srcPos, final long dstInit, final int dstPos,
917             final int nInts) {
918         if (src.length == 0 && srcPos == 0 || 0 == nInts) {
919             return dstInit;
920         }
921         if ((nInts - 1) * 32 + dstPos >= 64) {
922             throw new IllegalArgumentException("(nInts-1)*32+dstPos is greater or equal to than 64");
923         }
924         long out = dstInit;
925         for (int i = 0; i < nInts; i++) {
926             final int shift = i * 32 + dstPos;
927             final long bits = (0xffffffffL & src[i + srcPos]) << shift;
928             final long mask = 0xffffffffL << shift;
929             out = out & ~mask | bits;
930         }
931         return out;
932     }
933 
934     /**
935      * Converts an int into an array of boolean using the default (little-endian, Lsb0) byte and
936      * bit ordering.
937      *
938      * @param src the int to convert
939      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
940      * @param dst the destination array
941      * @param dstPos the position in {@code dst} where to copy the result
942      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
943      *            the width of the input (from srcPos to msb)
944      * @return {@code dst}
945      * @throws NullPointerException if {@code dst} is {@code null}
946      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 32}
947      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
948      */
949     public static boolean[] intToBinary(final int src, final int srcPos, final boolean[] dst, final int dstPos,
950             final int nBools) {
951         if (0 == nBools) {
952             return dst;
953         }
954         if (nBools - 1 + srcPos >= 32) {
955             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 32");
956         }
957         for (int i = 0; i < nBools; i++) {
958             final int shift = i + srcPos;
959             dst[dstPos + i] = (0x1 & src >> shift) != 0;
960         }
961         return dst;
962     }
963 
964     /**
965      * Converts an int into an array of byte using the default (little-endian, Lsb0) byte and bit
966      * ordering.
967      *
968      * @param src the int to convert
969      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
970      * @param dst the destination array
971      * @param dstPos the position in {@code dst} where to copy the result
972      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
973      *            width of the input (from srcPos to msb)
974      * @return {@code dst}
975      * @throws NullPointerException if {@code dst} is {@code null}
976      * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 32}
977      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
978      */
979     public static byte[] intToByteArray(final int src, final int srcPos, final byte[] dst, final int dstPos,
980             final int nBytes) {
981         if (0 == nBytes) {
982             return dst;
983         }
984         if ((nBytes - 1) * 8 + srcPos >= 32) {
985             throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greater or equal to than 32");
986         }
987         for (int i = 0; i < nBytes; i++) {
988             final int shift = i * 8 + srcPos;
989             dst[dstPos + i] = (byte) (0xff & src >> shift);
990         }
991         return dst;
992     }
993 
994     /**
995      * Converts an int into an array of Char using the default (little-endian, Lsb0) byte and bit
996      * ordering.
997      *
998      * @param src the int to convert
999      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1000      * @param dstInit the initial value for the result String
1001      * @param dstPos the position in {@code dst} where to copy the result
1002      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
1003      *            width of the input (from srcPos to msb)
1004      * @return {@code dst}
1005      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 32}
1006      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
1007      */
1008     public static String intToHex(final int src, final int srcPos, final String dstInit, final int dstPos,
1009             final int nHexs) {
1010         if (0 == nHexs) {
1011             return dstInit;
1012         }
1013         if ((nHexs - 1) * 4 + srcPos >= 32) {
1014             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 32");
1015         }
1016         final StringBuilder sb = new StringBuilder(dstInit);
1017         int append = sb.length();
1018         for (int i = 0; i < nHexs; i++) {
1019             final int shift = i * 4 + srcPos;
1020             final int bits = 0xF & src >> shift;
1021             if (dstPos + i == append) {
1022                 ++append;
1023                 sb.append(intToHexDigit(bits));
1024             } else {
1025                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
1026             }
1027         }
1028         return sb.toString();
1029     }
1030 
1031     /**
1032      * Converts the 4 lsb of an int to a hexadecimal digit.
1033      *
1034      * <p>
1035      * 0 returns '0'
1036      * </p>
1037      * <p>
1038      * 1 returns '1'
1039      * </p>
1040      * <p>
1041      * 10 returns 'A' and so on...
1042      * </p>
1043      *
1044      * @param nibble the 4 bits to convert
1045      * @return a hexadecimal digit representing the 4 lsb of {@code nibble}
1046      * @throws IllegalArgumentException if {@code nibble < 0} or {@code nibble > 15}
1047      */
1048     public static char intToHexDigit(final int nibble) {
1049         final char c = Character.forDigit(nibble, 16);
1050         if (c == Character.MIN_VALUE) {
1051             throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble);
1052         }
1053         return c;
1054     }
1055 
1056     /**
1057      * Converts the 4 lsb of an int to a hexadecimal digit encoded using the Msb0 bit ordering.
1058      *
1059      * <p>
1060      * 0 returns '0'
1061      * </p>
1062      * <p>
1063      * 1 returns '8'
1064      * </p>
1065      * <p>
1066      * 10 returns '5' and so on...
1067      * </p>
1068      *
1069      * @param nibble the 4 bits to convert
1070      * @return a hexadecimal digit representing the 4 lsb of {@code nibble}
1071      * @throws IllegalArgumentException if {@code nibble < 0} or {@code nibble > 15}
1072      */
1073     public static char intToHexDigitMsb0(final int nibble) {
1074         switch (nibble) {
1075         case 0x0:
1076             return '0';
1077         case 0x1:
1078             return '8';
1079         case 0x2:
1080             return '4';
1081         case 0x3:
1082             return 'c';
1083         case 0x4:
1084             return '2';
1085         case 0x5:
1086             return 'a';
1087         case 0x6:
1088             return '6';
1089         case 0x7:
1090             return 'e';
1091         case 0x8:
1092             return '1';
1093         case 0x9:
1094             return '9';
1095         case 0xA:
1096             return '5';
1097         case 0xB:
1098             return 'd';
1099         case 0xC:
1100             return '3';
1101         case 0xD:
1102             return 'b';
1103         case 0xE:
1104             return '7';
1105         case 0xF:
1106             return 'f';
1107         default:
1108             throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble);
1109         }
1110     }
1111 
1112     /**
1113      * Converts an int into an array of short using the default (little-endian, Lsb0) byte and
1114      * bit ordering.
1115      *
1116      * @param src the int to convert
1117      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1118      * @param dst the destination array
1119      * @param dstPos the position in {@code dst} where to copy the result
1120      * @param nShorts the number of shorts to copy to {@code dst}, must be smaller or equal to
1121      *            the width of the input (from srcPos to msb)
1122      * @return {@code dst}
1123      * @throws NullPointerException if {@code dst} is {@code null}
1124      * @throws IllegalArgumentException if {@code (nShorts-1)*16+srcPos >= 32}
1125      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nShorts > dst.length}
1126      */
1127     public static short[] intToShortArray(final int src, final int srcPos, final short[] dst, final int dstPos,
1128             final int nShorts) {
1129         if (0 == nShorts) {
1130             return dst;
1131         }
1132         if ((nShorts - 1) * 16 + srcPos >= 32) {
1133             throw new IllegalArgumentException("(nShorts-1)*16+srcPos is greater or equal to than 32");
1134         }
1135         for (int i = 0; i < nShorts; i++) {
1136             final int shift = i * 16 + srcPos;
1137             dst[dstPos + i] = (short) (0xffff & src >> shift);
1138         }
1139         return dst;
1140     }
1141 
1142     /**
1143      * Converts a long into an array of boolean using the default (little-endian, Lsb0) byte and
1144      * bit ordering.
1145      *
1146      * @param src the long to convert
1147      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1148      * @param dst the destination array
1149      * @param dstPos the position in {@code dst} where to copy the result
1150      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
1151      *            the width of the input (from srcPos to msb)
1152      * @return {@code dst}
1153      * @throws NullPointerException if {@code dst} is {@code null}
1154      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 64}
1155      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
1156      */
1157     public static boolean[] longToBinary(final long src, final int srcPos, final boolean[] dst, final int dstPos,
1158             final int nBools) {
1159         if (0 == nBools) {
1160             return dst;
1161         }
1162         if (nBools - 1 + srcPos >= 64) {
1163             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 64");
1164         }
1165         for (int i = 0; i < nBools; i++) {
1166             final int shift = i + srcPos;
1167             dst[dstPos + i] = (0x1 & src >> shift) != 0;
1168         }
1169         return dst;
1170     }
1171 
1172     /**
1173      * Converts a long into an array of byte using the default (little-endian, Lsb0) byte and
1174      * bit ordering.
1175      *
1176      * @param src the long to convert
1177      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1178      * @param dst the destination array
1179      * @param dstPos the position in {@code dst} where to copy the result
1180      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
1181      *            width of the input (from srcPos to msb)
1182      * @return {@code dst}
1183      * @throws NullPointerException if {@code dst} is {@code null}
1184      * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 64}
1185      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
1186      */
1187     public static byte[] longToByteArray(final long src, final int srcPos, final byte[] dst, final int dstPos,
1188             final int nBytes) {
1189         if (0 == nBytes) {
1190             return dst;
1191         }
1192         if ((nBytes - 1) * 8 + srcPos >= 64) {
1193             throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greater or equal to than 64");
1194         }
1195         for (int i = 0; i < nBytes; i++) {
1196             final int shift = i * 8 + srcPos;
1197             dst[dstPos + i] = (byte) (0xff & src >> shift);
1198         }
1199         return dst;
1200     }
1201 
1202     /**
1203      * Converts a long into an array of Char using the default (little-endian, Lsb0) byte and
1204      * bit ordering.
1205      *
1206      * @param src the long to convert
1207      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1208      * @param dstInit the initial value for the result String
1209      * @param dstPos the position in {@code dst} where to copy the result
1210      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
1211      *            width of the input (from srcPos to msb)
1212      * @return {@code dst}
1213      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 64}
1214      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
1215      */
1216     public static String longToHex(final long src, final int srcPos, final String dstInit, final int dstPos,
1217             final int nHexs) {
1218         if (0 == nHexs) {
1219             return dstInit;
1220         }
1221         if ((nHexs - 1) * 4 + srcPos >= 64) {
1222             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 64");
1223         }
1224         final StringBuilder sb = new StringBuilder(dstInit);
1225         int append = sb.length();
1226         for (int i = 0; i < nHexs; i++) {
1227             final int shift = i * 4 + srcPos;
1228             final int bits = (int) (0xF & src >> shift);
1229             if (dstPos + i == append) {
1230                 ++append;
1231                 sb.append(intToHexDigit(bits));
1232             } else {
1233                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
1234             }
1235         }
1236         return sb.toString();
1237     }
1238 
1239     /**
1240      * Converts a long into an array of int using the default (little-endian, Lsb0) byte and bit
1241      * ordering.
1242      *
1243      * @param src the long to convert
1244      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1245      * @param dst the destination array
1246      * @param dstPos the position in {@code dst} where to copy the result
1247      * @param nInts the number of ints to copy to {@code dst}, must be smaller or equal to the
1248      *            width of the input (from srcPos to msb)
1249      * @return {@code dst}
1250      * @throws NullPointerException if {@code dst} is {@code null} and {@code nInts > 0}
1251      * @throws IllegalArgumentException if {@code (nInts-1)*32+srcPos >= 64}
1252      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nInts > dst.length}
1253      */
1254     public static int[] longToIntArray(final long src, final int srcPos, final int[] dst, final int dstPos,
1255             final int nInts) {
1256         if (0 == nInts) {
1257             return dst;
1258         }
1259         if ((nInts - 1) * 32 + srcPos >= 64) {
1260             throw new IllegalArgumentException("(nInts-1)*32+srcPos is greater or equal to than 64");
1261         }
1262         for (int i = 0; i < nInts; i++) {
1263             final int shift = i * 32 + srcPos;
1264             dst[dstPos + i] = (int) (0xffffffff & src >> shift);
1265         }
1266         return dst;
1267     }
1268 
1269     /**
1270      * Converts a long into an array of short using the default (little-endian, Lsb0) byte and
1271      * bit ordering.
1272      *
1273      * @param src the long to convert
1274      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1275      * @param dst the destination array
1276      * @param dstPos the position in {@code dst} where to copy the result
1277      * @param nShorts the number of shorts to copy to {@code dst}, must be smaller or equal to
1278      *            the width of the input (from srcPos to msb)
1279      * @return {@code dst}
1280      * @throws NullPointerException if {@code dst} is {@code null}
1281      * @throws IllegalArgumentException if {@code (nShorts-1)*16+srcPos >= 64}
1282      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nShorts > dst.length}
1283      */
1284     public static short[] longToShortArray(final long src, final int srcPos, final short[] dst, final int dstPos,
1285             final int nShorts) {
1286         if (0 == nShorts) {
1287             return dst;
1288         }
1289         if ((nShorts - 1) * 16 + srcPos >= 64) {
1290             throw new IllegalArgumentException("(nShorts-1)*16+srcPos is greater or equal to than 64");
1291         }
1292         for (int i = 0; i < nShorts; i++) {
1293             final int shift = i * 16 + srcPos;
1294             dst[dstPos + i] = (short) (0xffff & src >> shift);
1295         }
1296         return dst;
1297     }
1298 
1299     /**
1300      * Converts an array of short into an int using the default (little-endian, Lsb0) byte and
1301      * bit ordering.
1302      *
1303      * @param src the short array to convert
1304      * @param srcPos the position in {@code src}, in short unit, from where to start the
1305      *            conversion
1306      * @param dstInit initial value of the destination int
1307      * @param dstPos the position of the lsb, in bits, in the result int
1308      * @param nShorts the number of shorts to convert
1309      * @return an int containing the selected bits
1310      * @throws NullPointerException if {@code src} is {@code null}
1311      * @throws IllegalArgumentException if {@code (nShorts-1)*16+dstPos >= 32}
1312      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nShorts > src.length}
1313      */
1314     public static int shortArrayToInt(final short[] src, final int srcPos, final int dstInit, final int dstPos,
1315             final int nShorts) {
1316         if (src.length == 0 && srcPos == 0 || 0 == nShorts) {
1317             return dstInit;
1318         }
1319         if ((nShorts - 1) * 16 + dstPos >= 32) {
1320             throw new IllegalArgumentException("(nShorts-1)*16+dstPos is greater or equal to than 32");
1321         }
1322         int out = dstInit;
1323         for (int i = 0; i < nShorts; i++) {
1324             final int shift = i * 16 + dstPos;
1325             final int bits = (0xffff & src[i + srcPos]) << shift;
1326             final int mask = 0xffff << shift;
1327             out = out & ~mask | bits;
1328         }
1329         return out;
1330     }
1331 
1332     /**
1333      * Converts an array of short into a long using the default (little-endian, Lsb0) byte and
1334      * bit ordering.
1335      *
1336      * @param src the short array to convert
1337      * @param srcPos the position in {@code src}, in short unit, from where to start the
1338      *            conversion
1339      * @param dstInit initial value of the destination long
1340      * @param dstPos the position of the lsb, in bits, in the result long
1341      * @param nShorts the number of shorts to convert
1342      * @return a long containing the selected bits
1343      * @throws NullPointerException if {@code src} is {@code null}
1344      * @throws IllegalArgumentException if {@code (nShorts-1)*16+dstPos >= 64}
1345      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nShorts > src.length}
1346      */
1347     public static long shortArrayToLong(final short[] src, final int srcPos, final long dstInit, final int dstPos,
1348             final int nShorts) {
1349         if (src.length == 0 && srcPos == 0 || 0 == nShorts) {
1350             return dstInit;
1351         }
1352         if ((nShorts - 1) * 16 + dstPos >= 64) {
1353             throw new IllegalArgumentException("(nShorts-1)*16+dstPos is greater or equal to than 64");
1354         }
1355         long out = dstInit;
1356         for (int i = 0; i < nShorts; i++) {
1357             final int shift = i * 16 + dstPos;
1358             final long bits = (0xffffL & src[i + srcPos]) << shift;
1359             final long mask = 0xffffL << shift;
1360             out = out & ~mask | bits;
1361         }
1362         return out;
1363     }
1364 
1365     /**
1366      * Converts a short into an array of boolean using the default (little-endian, Lsb0) byte
1367      * and bit ordering.
1368      *
1369      * @param src the short to convert
1370      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1371      * @param dst the destination array
1372      * @param dstPos the position in {@code dst} where to copy the result
1373      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
1374      *            the width of the input (from srcPos to msb)
1375      * @return {@code dst}
1376      * @throws NullPointerException if {@code dst} is {@code null}
1377      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 16}
1378      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
1379      */
1380     public static boolean[] shortToBinary(final short src, final int srcPos, final boolean[] dst, final int dstPos,
1381             final int nBools) {
1382         if (0 == nBools) {
1383             return dst;
1384         }
1385         if (nBools - 1 + srcPos >= 16) {
1386             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 16");
1387         }
1388         assert nBools - 1 < 16 - srcPos;
1389         for (int i = 0; i < nBools; i++) {
1390             final int shift = i + srcPos;
1391             dst[dstPos + i] = (0x1 & src >> shift) != 0;
1392         }
1393         return dst;
1394     }
1395 
1396     /**
1397      * Converts a short into an array of byte using the default (little-endian, Lsb0) byte and
1398      * bit ordering.
1399      *
1400      * @param src the short to convert
1401      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1402      * @param dst the destination array
1403      * @param dstPos the position in {@code dst} where to copy the result
1404      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
1405      *            width of the input (from srcPos to msb)
1406      * @return {@code dst}
1407      * @throws NullPointerException if {@code dst} is {@code null}
1408      * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 16}
1409      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
1410      */
1411     public static byte[] shortToByteArray(final short src, final int srcPos, final byte[] dst, final int dstPos,
1412             final int nBytes) {
1413         if (0 == nBytes) {
1414             return dst;
1415         }
1416         if ((nBytes - 1) * 8 + srcPos >= 16) {
1417             throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greater or equal to than 16");
1418         }
1419         for (int i = 0; i < nBytes; i++) {
1420             final int shift = i * 8 + srcPos;
1421             dst[dstPos + i] = (byte) (0xff & src >> shift);
1422         }
1423         return dst;
1424     }
1425 
1426     /**
1427      * Converts a short into an array of Char using the default (little-endian, Lsb0) byte and
1428      * bit ordering.
1429      *
1430      * @param src the short to convert
1431      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
1432      * @param dstInit the initial value for the result String
1433      * @param dstPos the position in {@code dst} where to copy the result
1434      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
1435      *            width of the input (from srcPos to msb)
1436      * @return {@code dst}
1437      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 16}
1438      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
1439      */
1440     public static String shortToHex(final short src, final int srcPos, final String dstInit, final int dstPos,
1441             final int nHexs) {
1442         if (0 == nHexs) {
1443             return dstInit;
1444         }
1445         if ((nHexs - 1) * 4 + srcPos >= 16) {
1446             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 16");
1447         }
1448         final StringBuilder sb = new StringBuilder(dstInit);
1449         int append = sb.length();
1450         for (int i = 0; i < nHexs; i++) {
1451             final int shift = i * 4 + srcPos;
1452             final int bits = 0xF & src >> shift;
1453             if (dstPos + i == append) {
1454                 ++append;
1455                 sb.append(intToHexDigit(bits));
1456             } else {
1457                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
1458             }
1459         }
1460         return sb.toString();
1461     }
1462 
1463     /**
1464      * Converts UUID into an array of byte using the default (little-endian, Lsb0) byte and bit
1465      * ordering.
1466      *
1467      * @param src the UUID to convert
1468      * @param dst the destination array
1469      * @param dstPos the position in {@code dst} where to copy the result
1470      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
1471      *            width of the input (from srcPos to msb)
1472      * @return {@code dst}
1473      * @throws NullPointerException if {@code dst} is {@code null}
1474      * @throws IllegalArgumentException if {@code nBytes > 16}
1475      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
1476      */
1477     public static byte[] uuidToByteArray(final UUID src, final byte[] dst, final int dstPos, final int nBytes) {
1478         if (0 == nBytes) {
1479             return dst;
1480         }
1481         if (nBytes > 16) {
1482             throw new IllegalArgumentException("nBytes is greater than 16");
1483         }
1484         longToByteArray(src.getMostSignificantBits(), 0, dst, dstPos, Math.min(nBytes, 8));
1485         if (nBytes >= 8) {
1486             longToByteArray(src.getLeastSignificantBits(), 0, dst, dstPos + 8, nBytes - 8);
1487         }
1488         return dst;
1489     }
1490 
1491     /**
1492      * Constructs a new instance.
1493      *
1494      * @deprecated Will be removed in 4.0.0.
1495      */
1496     @Deprecated
1497     public Conversion() {
1498         // empty
1499     }
1500 }