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