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