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