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