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