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