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