    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}