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