    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}