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