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