Conversion.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.lang3;

  18. import java.util.UUID;

  19. /**
  20.  * Static methods to convert a type into another, with endianness and bit ordering awareness.
  21.  *
  22.  * <p>
  23.  * The methods names follow a naming rule:<br>
  24.  * {@code <source type>[source endianness][source bit ordering]To<destination type>[destination endianness][destination bit ordering]}
  25.  * </p>
  26.  * <p>
  27.  * Source/destination type fields is one of the following:
  28.  * </p>
  29.  * <ul>
  30.  * <li>binary: an array of booleans</li>
  31.  * <li>byte or byteArray</li>
  32.  * <li>int or intArray</li>
  33.  * <li>long or longArray</li>
  34.  * <li>hex: a String containing hexadecimal digits (lowercase in destination)</li>
  35.  * <li>hexDigit: a Char containing a hexadecimal digit (lowercase in destination)</li>
  36.  * <li>uuid</li>
  37.  * </ul>
  38.  * <p>
  39.  * Endianness field: little-endian is the default, in this case the field is absent. In case of
  40.  * big-endian, the field is "Be".<br> Bit ordering: Lsb0 is the default, in this case the field
  41.  * is absent. In case of Msb0, the field is "Msb0".
  42.  * </p>
  43.  * <p>
  44.  * Example: intBeMsb0ToHex convert an int with big-endian byte order and Msb0 bit order into its
  45.  * hexadecimal string representation
  46.  * </p>
  47.  * <p>
  48.  * Most of the methods provide only default encoding for destination, this limits the number of
  49.  * ways to do one thing. Unless you are dealing with data from/to outside of the JVM platform,
  50.  * you should not need to use "Be" and "Msb0" methods.
  51.  * </p>
  52.  * <p>
  53.  * Development status: work on going, only a part of the little-endian, Lsb0 methods implemented
  54.  * so far.
  55.  * </p>
  56.  *
  57.  * @since 3.2
  58.  */
  59. public class Conversion {

  60.     private static final boolean[] TTTT = {true, true, true, true};
  61.     private static final boolean[] FTTT = {false, true, true, true};
  62.     private static final boolean[] TFTT = {true, false, true, true};
  63.     private static final boolean[] FFTT = {false, false, true, true};
  64.     private static final boolean[] TTFT = {true, true, false, true};
  65.     private static final boolean[] FTFT = {false, true, false, true};
  66.     private static final boolean[] TFFT = {true, false, false, true};
  67.     private static final boolean[] FFFT = {false, false, false, true};
  68.     private static final boolean[] TTTF = {true, true, true, false};
  69.     private static final boolean[] FTTF = {false, true, true, false};
  70.     private static final boolean[] TFTF = {true, false, true, false};
  71.     private static final boolean[] FFTF = {false, false, true, false};
  72.     private static final boolean[] TTFF = {true, true, false, false};
  73.     private static final boolean[] FTFF = {false, true, false, false};
  74.     private static final boolean[] TFFF = {true, false, false, false};
  75.     private static final boolean[] FFFF = {false, false, false, false};

  76.     /**
  77.      * Converts the first 4 bits of a binary (represented as boolean array) in big-endian Msb0
  78.      * bit ordering to a hexadecimal digit.
  79.      *
  80.      * <p>
  81.      * (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
  82.      * to '4'
  83.      * </p>
  84.      *
  85.      * @param src the binary to convert
  86.      * @return a hexadecimal digit representing the selected bits
  87.      * @throws IllegalArgumentException if {@code src} is empty
  88.      * @throws NullPointerException if {@code src} is {@code null}
  89.      */
  90.     public static char binaryBeMsb0ToHexDigit(final boolean[] src) {
  91.         return binaryBeMsb0ToHexDigit(src, 0);
  92.     }

  93.     /**
  94.      * Converts a binary (represented as boolean array) in big-endian Msb0 bit ordering to a
  95.      * hexadecimal digit.
  96.      *
  97.      * <p>
  98.      * (1, 0, 0, 0) with srcPos = 0 is converted as follow: '8' (1, 0, 0, 0, 0, 0, 0, 0,
  99.      * 0, 0, 0, 1, 0, 1, 0, 0) with srcPos = 2 is converted to '5'
  100.      * </p>
  101.      *
  102.      * @param src the binary to convert
  103.      * @param srcPos the position of the lsb to start the conversion
  104.      * @return a hexadecimal digit representing the selected bits
  105.      * @throws IllegalArgumentException if {@code src} is empty
  106.      * @throws NullPointerException if {@code src} is {@code null}
  107.      * @throws IndexOutOfBoundsException if {@code srcPos} is outside the array.
  108.      */
  109.     public static char binaryBeMsb0ToHexDigit(final boolean[] src, final int srcPos) {
  110.         // JDK 9: Objects.checkIndex(int index, int length)
  111.         if (Integer.compareUnsigned(srcPos, src.length) >= 0) {
  112.             // Throw the correct exception
  113.             if (src.length == 0) {
  114.                 throw new IllegalArgumentException("Cannot convert an empty array.");
  115.             }
  116.             throw new IndexOutOfBoundsException(srcPos + " is not within array length " + src.length);
  117.         }
  118.         // Little-endian bit 0 position
  119.         final int pos = src.length - 1 - srcPos;
  120.         if (3 <= pos && src[pos - 3]) {
  121.             if (src[pos - 2]) {
  122.                 if (src[pos - 1]) {
  123.                     return src[pos] ? 'f' : 'e';
  124.                 }
  125.                 return src[pos] ? 'd' : 'c';
  126.             }
  127.             if (src[pos - 1]) {
  128.                 return src[pos] ? 'b' : 'a';
  129.             }
  130.             return src[pos] ? '9' : '8';
  131.         }
  132.         if (2 <= pos && src[pos - 2]) {
  133.             if (src[pos - 1]) {
  134.                 return src[pos] ? '7' : '6';
  135.             }
  136.             return src[pos] ? '5' : '4';
  137.         }
  138.         if (1 <= pos && src[pos - 1]) {
  139.             return src[pos] ? '3' : '2';
  140.         }
  141.         return src[pos] ? '1' : '0';
  142.     }

  143.     /**
  144.      * Converts binary (represented as boolean array) into a byte using the default (little
  145.      * endian, Lsb0) byte and bit ordering.
  146.      *
  147.      * @param src the binary to convert
  148.      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
  149.      *            conversion
  150.      * @param dstInit initial value of the destination byte
  151.      * @param dstPos the position of the lsb, in bits, in the result byte
  152.      * @param nBools the number of booleans to convert
  153.      * @return a byte containing the selected bits
  154.      * @throws NullPointerException if {@code src} is {@code null}
  155.      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 8}
  156.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
  157.      */
  158.     public static byte binaryToByte(final boolean[] src, final int srcPos, final byte dstInit, final int dstPos,
  159.             final int nBools) {
  160.         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
  161.             return dstInit;
  162.         }
  163.         if (nBools - 1 + dstPos >= 8) {
  164.             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 8");
  165.         }
  166.         byte out = dstInit;
  167.         for (int i = 0; i < nBools; i++) {
  168.             final int shift = i + dstPos;
  169.             final int bits = (src[i + srcPos] ? 1 : 0) << shift;
  170.             final int mask = 0x1 << shift;
  171.             out = (byte) (out & ~mask | bits);
  172.         }
  173.         return out;
  174.     }

  175.     /**
  176.      * Converts binary (represented as boolean array) to a hexadecimal digit using the default
  177.      * (Lsb0) bit ordering.
  178.      *
  179.      * <p>
  180.      * (1, 0, 0, 0) is converted as follow: '1'
  181.      * </p>
  182.      *
  183.      * @param src the binary to convert
  184.      * @return a hexadecimal digit representing the selected bits
  185.      * @throws IllegalArgumentException if {@code src} is empty
  186.      * @throws NullPointerException if {@code src} is {@code null}
  187.      */
  188.     public static char binaryToHexDigit(final boolean[] src) {
  189.         return binaryToHexDigit(src, 0);
  190.     }

  191.     /**
  192.      * Converts binary (represented as boolean array) to a hexadecimal digit using the default
  193.      * (Lsb0) bit ordering.
  194.      *
  195.      * <p>
  196.      * (1, 0, 0, 0) is converted as follow: '1'
  197.      * </p>
  198.      *
  199.      * @param src the binary to convert
  200.      * @param srcPos the position of the lsb to start the conversion
  201.      * @return a hexadecimal digit representing the selected bits
  202.      * @throws IllegalArgumentException if {@code src} is empty
  203.      * @throws NullPointerException if {@code src} is {@code null}
  204.      */
  205.     public static char binaryToHexDigit(final boolean[] src, final int srcPos) {
  206.         if (src.length == 0) {
  207.             throw new IllegalArgumentException("Cannot convert an empty array.");
  208.         }
  209.         if (src.length > srcPos + 3 && src[srcPos + 3]) {
  210.             if (src[srcPos + 2]) {
  211.                 if (src[srcPos + 1]) {
  212.                     return src[srcPos] ? 'f' : 'e';
  213.                 }
  214.                 return src[srcPos] ? 'd' : 'c';
  215.             }
  216.             if (src[srcPos + 1]) {
  217.                 return src[srcPos] ? 'b' : 'a';
  218.             }
  219.             return src[srcPos] ? '9' : '8';
  220.         }
  221.         if (src.length > srcPos + 2 && src[srcPos + 2]) {
  222.             if (src[srcPos + 1]) {
  223.                 return src[srcPos] ? '7' : '6';
  224.             }
  225.             return src[srcPos] ? '5' : '4';
  226.         }
  227.         if (src.length > srcPos + 1 && src[srcPos + 1]) {
  228.             return src[srcPos] ? '3' : '2';
  229.         }
  230.         return src[srcPos] ? '1' : '0';
  231.     }

  232.     /**
  233.      * Converts binary (represented as boolean array) to a hexadecimal digit using the Msb0 bit
  234.      * ordering.
  235.      *
  236.      * <p>
  237.      * (1, 0, 0, 0) is converted as follow: '8'
  238.      * </p>
  239.      *
  240.      * @param src the binary to convert
  241.      * @return a hexadecimal digit representing the selected bits
  242.      * @throws IllegalArgumentException if {@code src} is empty, {@code src.length < 4} or
  243.      *             {@code src.length > 8}
  244.      * @throws NullPointerException if {@code src} is {@code null}
  245.      */
  246.     public static char binaryToHexDigitMsb0_4bits(final boolean[] src) {
  247.         return binaryToHexDigitMsb0_4bits(src, 0);
  248.     }

  249.     /**
  250.      * Converts binary (represented as boolean array) to a hexadecimal digit using the Msb0 bit
  251.      * ordering.
  252.      *
  253.      * <p>
  254.      * (1, 0, 0, 0) is converted as follow: '8' (1, 0, 0, 1, 1, 0, 1, 0) with srcPos = 3 is converted
  255.      * to 'D'
  256.      * </p>
  257.      *
  258.      * @param src the binary to convert
  259.      * @param srcPos the position of the lsb to start the conversion
  260.      * @return a hexadecimal digit representing the selected bits
  261.      * @throws IllegalArgumentException if {@code src} is empty, {@code src.length > 8} or
  262.      *             {@code src.length - srcPos < 4}
  263.      * @throws NullPointerException if {@code src} is {@code null}
  264.      */
  265.     public static char binaryToHexDigitMsb0_4bits(final boolean[] src, final int srcPos) {
  266.         if (src.length > 8) {
  267.             throw new IllegalArgumentException("src.length>8: src.length=" + src.length);
  268.         }
  269.         if (src.length - srcPos < 4) {
  270.             throw new IllegalArgumentException("src.length-srcPos<4: src.length=" + src.length + ", srcPos=" + srcPos);
  271.         }
  272.         if (src[srcPos + 3]) {
  273.             if (src[srcPos + 2]) {
  274.                 if (src[srcPos + 1]) {
  275.                     return src[srcPos] ? 'f' : '7';
  276.                 }
  277.                 return src[srcPos] ? 'b' : '3';
  278.             }
  279.             if (src[srcPos + 1]) {
  280.                 return src[srcPos] ? 'd' : '5';
  281.             }
  282.             return src[srcPos] ? '9' : '1';
  283.         }
  284.         if (src[srcPos + 2]) {
  285.             if (src[srcPos + 1]) {
  286.                 return src[srcPos] ? 'e' : '6';
  287.             }
  288.             return src[srcPos] ? 'a' : '2';
  289.         }
  290.         if (src[srcPos + 1]) {
  291.             return src[srcPos] ? 'c' : '4';
  292.         }
  293.         return src[srcPos] ? '8' : '0';
  294.     }

  295.     /**
  296.      * Converts binary (represented as boolean array) into an int using the default (little
  297.      * endian, Lsb0) byte and bit ordering.
  298.      *
  299.      * @param src the binary to convert
  300.      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
  301.      *            conversion
  302.      * @param dstInit initial value of the destination int
  303.      * @param dstPos the position of the lsb, in bits, in the result int
  304.      * @param nBools the number of booleans to convert
  305.      * @return an int containing the selected bits
  306.      * @throws NullPointerException if {@code src} is {@code null}
  307.      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 32}
  308.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
  309.      */
  310.     public static int binaryToInt(final boolean[] src, final int srcPos, final int dstInit, final int dstPos,
  311.             final int nBools) {
  312.         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
  313.             return dstInit;
  314.         }
  315.         if (nBools - 1 + dstPos >= 32) {
  316.             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 32");
  317.         }
  318.         int out = dstInit;
  319.         for (int i = 0; i < nBools; i++) {
  320.             final int shift = i + dstPos;
  321.             final int bits = (src[i + srcPos] ? 1 : 0) << shift;
  322.             final int mask = 0x1 << shift;
  323.             out = out & ~mask | bits;
  324.         }
  325.         return out;
  326.     }

  327.     /**
  328.      * Converts binary (represented as boolean array) into a long using the default (little
  329.      * endian, Lsb0) byte and bit ordering.
  330.      *
  331.      * @param src the binary to convert
  332.      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
  333.      *            conversion
  334.      * @param dstInit initial value of the destination long
  335.      * @param dstPos the position of the lsb, in bits, in the result long
  336.      * @param nBools the number of booleans to convert
  337.      * @return a long containing the selected bits
  338.      * @throws NullPointerException if {@code src} is {@code null}
  339.      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 64}
  340.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
  341.      */
  342.     public static long binaryToLong(final boolean[] src, final int srcPos, final long dstInit, final int dstPos,
  343.             final int nBools) {
  344.         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
  345.             return dstInit;
  346.         }
  347.         if (nBools - 1 + dstPos >= 64) {
  348.             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 64");
  349.         }
  350.         long out = dstInit;
  351.         for (int i = 0; i < nBools; i++) {
  352.             final int shift = i + dstPos;
  353.             final long bits = (src[i + srcPos] ? 1L : 0) << shift;
  354.             final long mask = 0x1L << shift;
  355.             out = out & ~mask | bits;
  356.         }
  357.         return out;
  358.     }

  359.     /**
  360.      * Converts binary (represented as boolean array) into a short using the default (little
  361.      * endian, Lsb0) byte and bit ordering.
  362.      *
  363.      * @param src the binary to convert
  364.      * @param srcPos the position in {@code src}, in boolean unit, from where to start the
  365.      *            conversion
  366.      * @param dstInit initial value of the destination short
  367.      * @param dstPos the position of the lsb, in bits, in the result short
  368.      * @param nBools the number of booleans to convert
  369.      * @return a short containing the selected bits
  370.      * @throws NullPointerException if {@code src} is {@code null}
  371.      * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 16}
  372.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
  373.      */
  374.     public static short binaryToShort(final boolean[] src, final int srcPos, final short dstInit, final int dstPos,
  375.             final int nBools) {
  376.         if (src.length == 0 && srcPos == 0 || 0 == nBools) {
  377.             return dstInit;
  378.         }
  379.         if (nBools - 1 + dstPos >= 16) {
  380.             throw new IllegalArgumentException("nBools-1+dstPos is greater or equal to than 16");
  381.         }
  382.         short out = dstInit;
  383.         for (int i = 0; i < nBools; i++) {
  384.             final int shift = i + dstPos;
  385.             final int bits = (src[i + srcPos] ? 1 : 0) << shift;
  386.             final int mask = 0x1 << shift;
  387.             out = (short) (out & ~mask | bits);
  388.         }
  389.         return out;
  390.     }

  391.     /**
  392.      * Converts an array of byte into an int using the default (little-endian, Lsb0) byte and bit
  393.      * ordering.
  394.      *
  395.      * @param src the byte array to convert
  396.      * @param srcPos the position in {@code src}, in byte unit, from where to start the
  397.      *            conversion
  398.      * @param dstInit initial value of the destination int
  399.      * @param dstPos the position of the lsb, in bits, in the result int
  400.      * @param nBytes the number of bytes to convert
  401.      * @return an int containing the selected bits
  402.      * @throws NullPointerException if {@code src} is {@code null}
  403.      * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 32}
  404.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
  405.      */
  406.     public static int byteArrayToInt(final byte[] src, final int srcPos, final int dstInit, final int dstPos,
  407.             final int nBytes) {
  408.         if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
  409.             return dstInit;
  410.         }
  411.         if ((nBytes - 1) * 8 + dstPos >= 32) {
  412.             throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greater or equal to than 32");
  413.         }
  414.         int out = dstInit;
  415.         for (int i = 0; i < nBytes; i++) {
  416.             final int shift = i * 8 + dstPos;
  417.             final int bits = (0xff & src[i + srcPos]) << shift;
  418.             final int mask = 0xff << shift;
  419.             out = out & ~mask | bits;
  420.         }
  421.         return out;
  422.     }

  423.     /**
  424.      * Converts an array of byte into a long using the default (little-endian, Lsb0) byte and
  425.      * bit ordering.
  426.      *
  427.      * @param src the byte array to convert
  428.      * @param srcPos the position in {@code src}, in byte unit, from where to start the
  429.      *            conversion
  430.      * @param dstInit initial value of the destination long
  431.      * @param dstPos the position of the lsb, in bits, in the result long
  432.      * @param nBytes the number of bytes to convert
  433.      * @return a long containing the selected bits
  434.      * @throws NullPointerException if {@code src} is {@code null}
  435.      * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 64}
  436.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
  437.      */
  438.     public static long byteArrayToLong(final byte[] src, final int srcPos, final long dstInit, final int dstPos,
  439.             final int nBytes) {
  440.         if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
  441.             return dstInit;
  442.         }
  443.         if ((nBytes - 1) * 8 + dstPos >= 64) {
  444.             throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greater or equal to than 64");
  445.         }
  446.         long out = dstInit;
  447.         for (int i = 0; i < nBytes; i++) {
  448.             final int shift = i * 8 + dstPos;
  449.             final long bits = (0xffL & src[i + srcPos]) << shift;
  450.             final long mask = 0xffL << shift;
  451.             out = out & ~mask | bits;
  452.         }
  453.         return out;
  454.     }

  455.     /**
  456.      * Converts an array of byte into a short using the default (little-endian, Lsb0) byte and
  457.      * bit ordering.
  458.      *
  459.      * @param src the byte array to convert
  460.      * @param srcPos the position in {@code src}, in byte unit, from where to start the
  461.      *            conversion
  462.      * @param dstInit initial value of the destination short
  463.      * @param dstPos the position of the lsb, in bits, in the result short
  464.      * @param nBytes the number of bytes to convert
  465.      * @return a short containing the selected bits
  466.      * @throws NullPointerException if {@code src} is {@code null}
  467.      * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 16}
  468.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
  469.      */
  470.     public static short byteArrayToShort(final byte[] src, final int srcPos, final short dstInit, final int dstPos,
  471.             final int nBytes) {
  472.         if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
  473.             return dstInit;
  474.         }
  475.         if ((nBytes - 1) * 8 + dstPos >= 16) {
  476.             throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greater or equal to than 16");
  477.         }
  478.         short out = dstInit;
  479.         for (int i = 0; i < nBytes; i++) {
  480.             final int shift = i * 8 + dstPos;
  481.             final int bits = (0xff & src[i + srcPos]) << shift;
  482.             final int mask = 0xff << shift;
  483.             out = (short) (out & ~mask | bits);
  484.         }
  485.         return out;
  486.     }

  487.     /**
  488.      * Converts bytes from an array into a UUID using the default (little-endian, Lsb0) byte and
  489.      * bit ordering.
  490.      *
  491.      * @param src the byte array to convert
  492.      * @param srcPos the position in {@code src} where to copy the result from
  493.      * @return a UUID
  494.      * @throws NullPointerException if {@code src} is {@code null}
  495.      * @throws IllegalArgumentException if array does not contain at least 16 bytes beginning
  496.      *             with {@code srcPos}
  497.      */
  498.     public static UUID byteArrayToUuid(final byte[] src, final int srcPos) {
  499.         if (src.length - srcPos < 16) {
  500.             throw new IllegalArgumentException("Need at least 16 bytes for UUID");
  501.         }
  502.         return new UUID(byteArrayToLong(src, srcPos, 0, 0, 8), byteArrayToLong(src, srcPos + 8, 0, 0, 8));
  503.     }

  504.     /**
  505.      * Converts a byte into an array of boolean using the default (little-endian, Lsb0) byte and
  506.      * bit ordering.
  507.      *
  508.      * @param src the byte to convert
  509.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  510.      * @param dst the destination array
  511.      * @param dstPos the position in {@code dst} where to copy the result
  512.      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
  513.      *            the width of the input (from srcPos to msb)
  514.      * @return {@code dst}
  515.      * @throws NullPointerException if {@code dst} is {@code null}
  516.      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 8}
  517.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
  518.      */
  519.     public static boolean[] byteToBinary(final byte src, final int srcPos, final boolean[] dst, final int dstPos,
  520.             final int nBools) {
  521.         if (0 == nBools) {
  522.             return dst;
  523.         }
  524.         if (nBools - 1 + srcPos >= 8) {
  525.             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 8");
  526.         }
  527.         for (int i = 0; i < nBools; i++) {
  528.             final int shift = i + srcPos;
  529.             dst[dstPos + i] = (0x1 & src >> shift) != 0;
  530.         }
  531.         return dst;
  532.     }

  533.     /**
  534.      * Converts a byte into an array of Char using the default (little-endian, Lsb0) byte and
  535.      * bit ordering.
  536.      *
  537.      * @param src the byte to convert
  538.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  539.      * @param dstInit the initial value for the result String
  540.      * @param dstPos the position in {@code dst} where to copy the result
  541.      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
  542.      *            width of the input (from srcPos to msb)
  543.      * @return {@code dst}
  544.      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 8}
  545.      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
  546.      */
  547.     public static String byteToHex(final byte src, final int srcPos, final String dstInit, final int dstPos,
  548.             final int nHexs) {
  549.         if (0 == nHexs) {
  550.             return dstInit;
  551.         }
  552.         if ((nHexs - 1) * 4 + srcPos >= 8) {
  553.             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 8");
  554.         }
  555.         final StringBuilder sb = new StringBuilder(dstInit);
  556.         int append = sb.length();
  557.         for (int i = 0; i < nHexs; i++) {
  558.             final int shift = i * 4 + srcPos;
  559.             final int bits = 0xF & src >> shift;
  560.             if (dstPos + i == append) {
  561.                 ++append;
  562.                 sb.append(intToHexDigit(bits));
  563.             } else {
  564.                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
  565.             }
  566.         }
  567.         return sb.toString();
  568.     }

  569.     /**
  570.      * Converts a hexadecimal digit into binary (represented as boolean array) using the Msb0
  571.      * bit ordering.
  572.      *
  573.      * <p>
  574.      * '1' is converted as follow: (0, 0, 0, 1)
  575.      * </p>
  576.      *
  577.      * @param hexDigit the hexadecimal digit to convert
  578.      * @return a boolean array with the binary representation of {@code hexDigit}
  579.      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
  580.      */
  581.     public static boolean[] hexDigitMsb0ToBinary(final char hexDigit) {
  582.         switch (hexDigit) {
  583.         case '0':
  584.             return FFFF.clone();
  585.         case '1':
  586.             return FFFT.clone();
  587.         case '2':
  588.             return FFTF.clone();
  589.         case '3':
  590.             return FFTT.clone();
  591.         case '4':
  592.             return FTFF.clone();
  593.         case '5':
  594.             return FTFT.clone();
  595.         case '6':
  596.             return FTTF.clone();
  597.         case '7':
  598.             return FTTT.clone();
  599.         case '8':
  600.             return TFFF.clone();
  601.         case '9':
  602.             return TFFT.clone();
  603.         case 'a':// fall through
  604.         case 'A':
  605.             return TFTF.clone();
  606.         case 'b':// fall through
  607.         case 'B':
  608.             return TFTT.clone();
  609.         case 'c':// fall through
  610.         case 'C':
  611.             return TTFF.clone();
  612.         case 'd':// fall through
  613.         case 'D':
  614.             return TTFT.clone();
  615.         case 'e':// fall through
  616.         case 'E':
  617.             return TTTF.clone();
  618.         case 'f':// fall through
  619.         case 'F':
  620.             return TTTT.clone();
  621.         default:
  622.             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
  623.         }
  624.     }

  625.     /**
  626.      * Converts a hexadecimal digit into an int using the Msb0 bit ordering.
  627.      *
  628.      * <p>
  629.      * '1' is converted to 8
  630.      * </p>
  631.      *
  632.      * @param hexDigit the hexadecimal digit to convert
  633.      * @return an int equals to {@code hexDigit}
  634.      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
  635.      */
  636.     public static int hexDigitMsb0ToInt(final char hexDigit) {
  637.         switch (hexDigit) {
  638.         case '0':
  639.             return 0x0;
  640.         case '1':
  641.             return 0x8;
  642.         case '2':
  643.             return 0x4;
  644.         case '3':
  645.             return 0xC;
  646.         case '4':
  647.             return 0x2;
  648.         case '5':
  649.             return 0xA;
  650.         case '6':
  651.             return 0x6;
  652.         case '7':
  653.             return 0xE;
  654.         case '8':
  655.             return 0x1;
  656.         case '9':
  657.             return 0x9;
  658.         case 'a':// fall through
  659.         case 'A':
  660.             return 0x5;
  661.         case 'b':// fall through
  662.         case 'B':
  663.             return 0xD;
  664.         case 'c':// fall through
  665.         case 'C':
  666.             return 0x3;
  667.         case 'd':// fall through
  668.         case 'D':
  669.             return 0xB;
  670.         case 'e':// fall through
  671.         case 'E':
  672.             return 0x7;
  673.         case 'f':// fall through
  674.         case 'F':
  675.             return 0xF;
  676.         default:
  677.             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
  678.         }
  679.     }

  680.     /**
  681.      * Converts a hexadecimal digit into binary (represented as boolean array) using the default
  682.      * (Lsb0) bit ordering.
  683.      *
  684.      * <p>
  685.      * '1' is converted as follow: (1, 0, 0, 0)
  686.      * </p>
  687.      *
  688.      * @param hexDigit the hexadecimal digit to convert
  689.      * @return a boolean array with the binary representation of {@code hexDigit}
  690.      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
  691.      */
  692.     public static boolean[] hexDigitToBinary(final char hexDigit) {
  693.         switch (hexDigit) {
  694.         case '0':
  695.             return FFFF.clone();
  696.         case '1':
  697.             return TFFF.clone();
  698.         case '2':
  699.             return FTFF.clone();
  700.         case '3':
  701.             return TTFF.clone();
  702.         case '4':
  703.             return FFTF.clone();
  704.         case '5':
  705.             return TFTF.clone();
  706.         case '6':
  707.             return FTTF.clone();
  708.         case '7':
  709.             return TTTF.clone();
  710.         case '8':
  711.             return FFFT.clone();
  712.         case '9':
  713.             return TFFT.clone();
  714.         case 'a':// fall through
  715.         case 'A':
  716.             return FTFT.clone();
  717.         case 'b':// fall through
  718.         case 'B':
  719.             return TTFT.clone();
  720.         case 'c':// fall through
  721.         case 'C':
  722.             return FFTT.clone();
  723.         case 'd':// fall through
  724.         case 'D':
  725.             return TFTT.clone();
  726.         case 'e':// fall through
  727.         case 'E':
  728.             return FTTT.clone();
  729.         case 'f':// fall through
  730.         case 'F':
  731.             return TTTT.clone();
  732.         default:
  733.             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
  734.         }
  735.     }

  736.     /**
  737.      * Converts a hexadecimal digit into an int using the default (Lsb0) bit ordering.
  738.      *
  739.      * <p>
  740.      * '1' is converted to 1
  741.      * </p>
  742.      *
  743.      * @param hexDigit the hexadecimal digit to convert
  744.      * @return an int equals to {@code hexDigit}
  745.      * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
  746.      */
  747.     public static int hexDigitToInt(final char hexDigit) {
  748.         final int digit = Character.digit(hexDigit, 16);
  749.         if (digit < 0) {
  750.             throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
  751.         }
  752.         return digit;
  753.     }

  754.     /**
  755.      * Converts a hexadecimal string into a byte using the default (little-endian, Lsb0) byte and
  756.      * bit ordering.
  757.      *
  758.      * @param src the hexadecimal string to convert
  759.      * @param srcPos the position in {@code src}, in Char unit, from where to start the
  760.      *            conversion
  761.      * @param dstInit initial value of the destination byte
  762.      * @param dstPos the position of the lsb, in bits, in the result byte
  763.      * @param nHex the number of Chars to convert
  764.      * @return a byte containing the selected bits
  765.      * @throws IllegalArgumentException if {@code (nHex-1)*4+dstPos >= 8}
  766.      */
  767.     public static byte hexToByte(final String src, final int srcPos, final byte dstInit, final int dstPos,
  768.             final int nHex) {
  769.         if (0 == nHex) {
  770.             return dstInit;
  771.         }
  772.         if ((nHex - 1) * 4 + dstPos >= 8) {
  773.             throw new IllegalArgumentException("(nHex-1)*4+dstPos is greater than or equal to 8");
  774.         }
  775.         byte out = dstInit;
  776.         for (int i = 0; i < nHex; i++) {
  777.             final int shift = i * 4 + dstPos;
  778.             final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
  779.             final int mask = 0xf << shift;
  780.             out = (byte) (out & ~mask | bits);
  781.         }
  782.         return out;
  783.     }

  784.     /**
  785.      * Converts an array of Char into an int using the default (little-endian, Lsb0) byte and bit
  786.      * ordering.
  787.      *
  788.      * @param src the hexadecimal string to convert
  789.      * @param srcPos the position in {@code src}, in Char unit, from where to start the
  790.      *            conversion
  791.      * @param dstInit initial value of the destination int
  792.      * @param dstPos the position of the lsb, in bits, in the result int
  793.      * @param nHex the number of Chars to convert
  794.      * @return an int containing the selected bits
  795.      * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 32}
  796.      */
  797.     public static int hexToInt(final String src, final int srcPos, final int dstInit, final int dstPos, final int nHex) {
  798.         if (0 == nHex) {
  799.             return dstInit;
  800.         }
  801.         if ((nHex - 1) * 4 + dstPos >= 32) {
  802.             throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 32");
  803.         }
  804.         int out = dstInit;
  805.         for (int i = 0; i < nHex; i++) {
  806.             final int shift = i * 4 + dstPos;
  807.             final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
  808.             final int mask = 0xf << shift;
  809.             out = out & ~mask | bits;
  810.         }
  811.         return out;
  812.     }

  813.     /**
  814.      * Converts an array of Char into a long using the default (little-endian, Lsb0) byte and
  815.      * bit ordering.
  816.      *
  817.      * @param src the hexadecimal string to convert
  818.      * @param srcPos the position in {@code src}, in Char unit, from where to start the
  819.      *            conversion
  820.      * @param dstInit initial value of the destination long
  821.      * @param dstPos the position of the lsb, in bits, in the result long
  822.      * @param nHex the number of Chars to convert
  823.      * @return a long containing the selected bits
  824.      * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 64}
  825.      */
  826.     public static long hexToLong(final String src, final int srcPos, final long dstInit, final int dstPos,
  827.             final int nHex) {
  828.         if (0 == nHex) {
  829.             return dstInit;
  830.         }
  831.         if ((nHex - 1) * 4 + dstPos >= 64) {
  832.             throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 64");
  833.         }
  834.         long out = dstInit;
  835.         for (int i = 0; i < nHex; i++) {
  836.             final int shift = i * 4 + dstPos;
  837.             final long bits = (0xfL & hexDigitToInt(src.charAt(i + srcPos))) << shift;
  838.             final long mask = 0xfL << shift;
  839.             out = out & ~mask | bits;
  840.         }
  841.         return out;
  842.     }

  843.     /**
  844.      * Converts an array of Char into a short using the default (little-endian, Lsb0) byte and
  845.      * bit ordering.
  846.      *
  847.      * @param src the hexadecimal string to convert
  848.      * @param srcPos the position in {@code src}, in Char unit, from where to start the
  849.      *            conversion
  850.      * @param dstInit initial value of the destination short
  851.      * @param dstPos the position of the lsb, in bits, in the result short
  852.      * @param nHex the number of Chars to convert
  853.      * @return a short containing the selected bits
  854.      * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 16}
  855.      */
  856.     public static short hexToShort(final String src, final int srcPos, final short dstInit, final int dstPos,
  857.             final int nHex) {
  858.         if (0 == nHex) {
  859.             return dstInit;
  860.         }
  861.         if ((nHex - 1) * 4 + dstPos >= 16) {
  862.             throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 16");
  863.         }
  864.         short out = dstInit;
  865.         for (int i = 0; i < nHex; i++) {
  866.             final int shift = i * 4 + dstPos;
  867.             final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
  868.             final int mask = 0xf << shift;
  869.             out = (short) (out & ~mask | bits);
  870.         }
  871.         return out;
  872.     }

  873.     /**
  874.      * Converts an array of int into a long using the default (little-endian, Lsb0) byte and bit
  875.      * ordering.
  876.      *
  877.      * @param src the int array to convert
  878.      * @param srcPos the position in {@code src}, in int unit, from where to start the
  879.      *            conversion
  880.      * @param dstInit initial value of the destination long
  881.      * @param dstPos the position of the lsb, in bits, in the result long
  882.      * @param nInts the number of ints to convert
  883.      * @return a long containing the selected bits
  884.      * @throws IllegalArgumentException if {@code (nInts-1)*32+dstPos >= 64}
  885.      * @throws NullPointerException if {@code src} is {@code null}
  886.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nInts > src.length}
  887.      */
  888.     public static long intArrayToLong(final int[] src, final int srcPos, final long dstInit, final int dstPos,
  889.             final int nInts) {
  890.         if (src.length == 0 && srcPos == 0 || 0 == nInts) {
  891.             return dstInit;
  892.         }
  893.         if ((nInts - 1) * 32 + dstPos >= 64) {
  894.             throw new IllegalArgumentException("(nInts-1)*32+dstPos is greater or equal to than 64");
  895.         }
  896.         long out = dstInit;
  897.         for (int i = 0; i < nInts; i++) {
  898.             final int shift = i * 32 + dstPos;
  899.             final long bits = (0xffffffffL & src[i + srcPos]) << shift;
  900.             final long mask = 0xffffffffL << shift;
  901.             out = out & ~mask | bits;
  902.         }
  903.         return out;
  904.     }

  905.     /**
  906.      * Converts an int into an array of boolean using the default (little-endian, Lsb0) byte and
  907.      * bit ordering.
  908.      *
  909.      * @param src the int to convert
  910.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  911.      * @param dst the destination array
  912.      * @param dstPos the position in {@code dst} where to copy the result
  913.      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
  914.      *            the width of the input (from srcPos to msb)
  915.      * @return {@code dst}
  916.      * @throws NullPointerException if {@code dst} is {@code null}
  917.      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 32}
  918.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
  919.      */
  920.     public static boolean[] intToBinary(final int src, final int srcPos, final boolean[] dst, final int dstPos,
  921.             final int nBools) {
  922.         if (0 == nBools) {
  923.             return dst;
  924.         }
  925.         if (nBools - 1 + srcPos >= 32) {
  926.             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 32");
  927.         }
  928.         for (int i = 0; i < nBools; i++) {
  929.             final int shift = i + srcPos;
  930.             dst[dstPos + i] = (0x1 & src >> shift) != 0;
  931.         }
  932.         return dst;
  933.     }

  934.     /**
  935.      * Converts an int into an array of byte using the default (little-endian, Lsb0) byte and bit
  936.      * ordering.
  937.      *
  938.      * @param src the int to convert
  939.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  940.      * @param dst the destination array
  941.      * @param dstPos the position in {@code dst} where to copy the result
  942.      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
  943.      *            width of the input (from srcPos to msb)
  944.      * @return {@code dst}
  945.      * @throws NullPointerException if {@code dst} is {@code null}
  946.      * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 32}
  947.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
  948.      */
  949.     public static byte[] intToByteArray(final int src, final int srcPos, final byte[] dst, final int dstPos,
  950.             final int nBytes) {
  951.         if (0 == nBytes) {
  952.             return dst;
  953.         }
  954.         if ((nBytes - 1) * 8 + srcPos >= 32) {
  955.             throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greater or equal to than 32");
  956.         }
  957.         for (int i = 0; i < nBytes; i++) {
  958.             final int shift = i * 8 + srcPos;
  959.             dst[dstPos + i] = (byte) (0xff & src >> shift);
  960.         }
  961.         return dst;
  962.     }

  963.     /**
  964.      * Converts an int into an array of Char using the default (little-endian, Lsb0) byte and bit
  965.      * ordering.
  966.      *
  967.      * @param src the int to convert
  968.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  969.      * @param dstInit the initial value for the result String
  970.      * @param dstPos the position in {@code dst} where to copy the result
  971.      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
  972.      *            width of the input (from srcPos to msb)
  973.      * @return {@code dst}
  974.      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 32}
  975.      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
  976.      */
  977.     public static String intToHex(final int src, final int srcPos, final String dstInit, final int dstPos,
  978.             final int nHexs) {
  979.         if (0 == nHexs) {
  980.             return dstInit;
  981.         }
  982.         if ((nHexs - 1) * 4 + srcPos >= 32) {
  983.             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 32");
  984.         }
  985.         final StringBuilder sb = new StringBuilder(dstInit);
  986.         int append = sb.length();
  987.         for (int i = 0; i < nHexs; i++) {
  988.             final int shift = i * 4 + srcPos;
  989.             final int bits = 0xF & src >> shift;
  990.             if (dstPos + i == append) {
  991.                 ++append;
  992.                 sb.append(intToHexDigit(bits));
  993.             } else {
  994.                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
  995.             }
  996.         }
  997.         return sb.toString();
  998.     }

  999.     /**
  1000.      * Converts the 4 lsb of an int to a hexadecimal digit.
  1001.      *
  1002.      * <p>
  1003.      * 0 returns '0'
  1004.      * </p>
  1005.      * <p>
  1006.      * 1 returns '1'
  1007.      * </p>
  1008.      * <p>
  1009.      * 10 returns 'A' and so on...
  1010.      * </p>
  1011.      *
  1012.      * @param nibble the 4 bits to convert
  1013.      * @return a hexadecimal digit representing the 4 lsb of {@code nibble}
  1014.      * @throws IllegalArgumentException if {@code nibble < 0} or {@code nibble > 15}
  1015.      */
  1016.     public static char intToHexDigit(final int nibble) {
  1017.         final char c = Character.forDigit(nibble, 16);
  1018.         if (c == Character.MIN_VALUE) {
  1019.             throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble);
  1020.         }
  1021.         return c;
  1022.     }

  1023.     /**
  1024.      * Converts the 4 lsb of an int to a hexadecimal digit encoded using the Msb0 bit ordering.
  1025.      *
  1026.      * <p>
  1027.      * 0 returns '0'
  1028.      * </p>
  1029.      * <p>
  1030.      * 1 returns '8'
  1031.      * </p>
  1032.      * <p>
  1033.      * 10 returns '5' and so on...
  1034.      * </p>
  1035.      *
  1036.      * @param nibble the 4 bits to convert
  1037.      * @return a hexadecimal digit representing the 4 lsb of {@code nibble}
  1038.      * @throws IllegalArgumentException if {@code nibble < 0} or {@code nibble > 15}
  1039.      */
  1040.     public static char intToHexDigitMsb0(final int nibble) {
  1041.         switch (nibble) {
  1042.         case 0x0:
  1043.             return '0';
  1044.         case 0x1:
  1045.             return '8';
  1046.         case 0x2:
  1047.             return '4';
  1048.         case 0x3:
  1049.             return 'c';
  1050.         case 0x4:
  1051.             return '2';
  1052.         case 0x5:
  1053.             return 'a';
  1054.         case 0x6:
  1055.             return '6';
  1056.         case 0x7:
  1057.             return 'e';
  1058.         case 0x8:
  1059.             return '1';
  1060.         case 0x9:
  1061.             return '9';
  1062.         case 0xA:
  1063.             return '5';
  1064.         case 0xB:
  1065.             return 'd';
  1066.         case 0xC:
  1067.             return '3';
  1068.         case 0xD:
  1069.             return 'b';
  1070.         case 0xE:
  1071.             return '7';
  1072.         case 0xF:
  1073.             return 'f';
  1074.         default:
  1075.             throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble);
  1076.         }
  1077.     }

  1078.     /**
  1079.      * Converts an int into an array of short using the default (little-endian, Lsb0) byte and
  1080.      * bit ordering.
  1081.      *
  1082.      * @param src the int to convert
  1083.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1084.      * @param dst the destination array
  1085.      * @param dstPos the position in {@code dst} where to copy the result
  1086.      * @param nShorts the number of shorts to copy to {@code dst}, must be smaller or equal to
  1087.      *            the width of the input (from srcPos to msb)
  1088.      * @return {@code dst}
  1089.      * @throws NullPointerException if {@code dst} is {@code null}
  1090.      * @throws IllegalArgumentException if {@code (nShorts-1)*16+srcPos >= 32}
  1091.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nShorts > dst.length}
  1092.      */
  1093.     public static short[] intToShortArray(final int src, final int srcPos, final short[] dst, final int dstPos,
  1094.             final int nShorts) {
  1095.         if (0 == nShorts) {
  1096.             return dst;
  1097.         }
  1098.         if ((nShorts - 1) * 16 + srcPos >= 32) {
  1099.             throw new IllegalArgumentException("(nShorts-1)*16+srcPos is greater or equal to than 32");
  1100.         }
  1101.         for (int i = 0; i < nShorts; i++) {
  1102.             final int shift = i * 16 + srcPos;
  1103.             dst[dstPos + i] = (short) (0xffff & src >> shift);
  1104.         }
  1105.         return dst;
  1106.     }

  1107.     /**
  1108.      * Converts a long into an array of boolean using the default (little-endian, Lsb0) byte and
  1109.      * bit ordering.
  1110.      *
  1111.      * @param src the long to convert
  1112.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1113.      * @param dst the destination array
  1114.      * @param dstPos the position in {@code dst} where to copy the result
  1115.      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
  1116.      *            the width of the input (from srcPos to msb)
  1117.      * @return {@code dst}
  1118.      * @throws NullPointerException if {@code dst} is {@code null}
  1119.      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 64}
  1120.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
  1121.      */
  1122.     public static boolean[] longToBinary(final long src, final int srcPos, final boolean[] dst, final int dstPos,
  1123.             final int nBools) {
  1124.         if (0 == nBools) {
  1125.             return dst;
  1126.         }
  1127.         if (nBools - 1 + srcPos >= 64) {
  1128.             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 64");
  1129.         }
  1130.         for (int i = 0; i < nBools; i++) {
  1131.             final int shift = i + srcPos;
  1132.             dst[dstPos + i] = (0x1 & src >> shift) != 0;
  1133.         }
  1134.         return dst;
  1135.     }

  1136.     /**
  1137.      * Converts a long into an array of byte using the default (little-endian, Lsb0) byte and
  1138.      * bit ordering.
  1139.      *
  1140.      * @param src the long to convert
  1141.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1142.      * @param dst the destination array
  1143.      * @param dstPos the position in {@code dst} where to copy the result
  1144.      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
  1145.      *            width of the input (from srcPos to msb)
  1146.      * @return {@code dst}
  1147.      * @throws NullPointerException if {@code dst} is {@code null}
  1148.      * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 64}
  1149.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
  1150.      */
  1151.     public static byte[] longToByteArray(final long src, final int srcPos, final byte[] dst, final int dstPos,
  1152.             final int nBytes) {
  1153.         if (0 == nBytes) {
  1154.             return dst;
  1155.         }
  1156.         if ((nBytes - 1) * 8 + srcPos >= 64) {
  1157.             throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greater or equal to than 64");
  1158.         }
  1159.         for (int i = 0; i < nBytes; i++) {
  1160.             final int shift = i * 8 + srcPos;
  1161.             dst[dstPos + i] = (byte) (0xff & src >> shift);
  1162.         }
  1163.         return dst;
  1164.     }

  1165.     /**
  1166.      * Converts a long into an array of Char using the default (little-endian, Lsb0) byte and
  1167.      * bit ordering.
  1168.      *
  1169.      * @param src the long to convert
  1170.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1171.      * @param dstInit the initial value for the result String
  1172.      * @param dstPos the position in {@code dst} where to copy the result
  1173.      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
  1174.      *            width of the input (from srcPos to msb)
  1175.      * @return {@code dst}
  1176.      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 64}
  1177.      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
  1178.      */
  1179.     public static String longToHex(final long src, final int srcPos, final String dstInit, final int dstPos,
  1180.             final int nHexs) {
  1181.         if (0 == nHexs) {
  1182.             return dstInit;
  1183.         }
  1184.         if ((nHexs - 1) * 4 + srcPos >= 64) {
  1185.             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 64");
  1186.         }
  1187.         final StringBuilder sb = new StringBuilder(dstInit);
  1188.         int append = sb.length();
  1189.         for (int i = 0; i < nHexs; i++) {
  1190.             final int shift = i * 4 + srcPos;
  1191.             final int bits = (int) (0xF & src >> shift);
  1192.             if (dstPos + i == append) {
  1193.                 ++append;
  1194.                 sb.append(intToHexDigit(bits));
  1195.             } else {
  1196.                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
  1197.             }
  1198.         }
  1199.         return sb.toString();
  1200.     }

  1201.     /**
  1202.      * Converts a long into an array of int using the default (little-endian, Lsb0) byte and bit
  1203.      * ordering.
  1204.      *
  1205.      * @param src the long to convert
  1206.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1207.      * @param dst the destination array
  1208.      * @param dstPos the position in {@code dst} where to copy the result
  1209.      * @param nInts the number of ints to copy to {@code dst}, must be smaller or equal to the
  1210.      *            width of the input (from srcPos to msb)
  1211.      * @return {@code dst}
  1212.      * @throws NullPointerException if {@code dst} is {@code null} and {@code nInts > 0}
  1213.      * @throws IllegalArgumentException if {@code (nInts-1)*32+srcPos >= 64}
  1214.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nInts > dst.length}
  1215.      */
  1216.     public static int[] longToIntArray(final long src, final int srcPos, final int[] dst, final int dstPos,
  1217.             final int nInts) {
  1218.         if (0 == nInts) {
  1219.             return dst;
  1220.         }
  1221.         if ((nInts - 1) * 32 + srcPos >= 64) {
  1222.             throw new IllegalArgumentException("(nInts-1)*32+srcPos is greater or equal to than 64");
  1223.         }
  1224.         for (int i = 0; i < nInts; i++) {
  1225.             final int shift = i * 32 + srcPos;
  1226.             dst[dstPos + i] = (int) (0xffffffff & src >> shift);
  1227.         }
  1228.         return dst;
  1229.     }

  1230.     /**
  1231.      * Converts a long into an array of short using the default (little-endian, Lsb0) byte and
  1232.      * bit ordering.
  1233.      *
  1234.      * @param src the long to convert
  1235.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1236.      * @param dst the destination array
  1237.      * @param dstPos the position in {@code dst} where to copy the result
  1238.      * @param nShorts the number of shorts to copy to {@code dst}, must be smaller or equal to
  1239.      *            the width of the input (from srcPos to msb)
  1240.      * @return {@code dst}
  1241.      * @throws NullPointerException if {@code dst} is {@code null}
  1242.      * @throws IllegalArgumentException if {@code (nShorts-1)*16+srcPos >= 64}
  1243.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nShorts > dst.length}
  1244.      */
  1245.     public static short[] longToShortArray(final long src, final int srcPos, final short[] dst, final int dstPos,
  1246.             final int nShorts) {
  1247.         if (0 == nShorts) {
  1248.             return dst;
  1249.         }
  1250.         if ((nShorts - 1) * 16 + srcPos >= 64) {
  1251.             throw new IllegalArgumentException("(nShorts-1)*16+srcPos is greater or equal to than 64");
  1252.         }
  1253.         for (int i = 0; i < nShorts; i++) {
  1254.             final int shift = i * 16 + srcPos;
  1255.             dst[dstPos + i] = (short) (0xffff & src >> shift);
  1256.         }
  1257.         return dst;
  1258.     }

  1259.     /**
  1260.      * Converts an array of short into an int using the default (little-endian, Lsb0) byte and
  1261.      * bit ordering.
  1262.      *
  1263.      * @param src the short array to convert
  1264.      * @param srcPos the position in {@code src}, in short unit, from where to start the
  1265.      *            conversion
  1266.      * @param dstInit initial value of the destination int
  1267.      * @param dstPos the position of the lsb, in bits, in the result int
  1268.      * @param nShorts the number of shorts to convert
  1269.      * @return an int containing the selected bits
  1270.      * @throws NullPointerException if {@code src} is {@code null}
  1271.      * @throws IllegalArgumentException if {@code (nShorts-1)*16+dstPos >= 32}
  1272.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nShorts > src.length}
  1273.      */
  1274.     public static int shortArrayToInt(final short[] src, final int srcPos, final int dstInit, final int dstPos,
  1275.             final int nShorts) {
  1276.         if (src.length == 0 && srcPos == 0 || 0 == nShorts) {
  1277.             return dstInit;
  1278.         }
  1279.         if ((nShorts - 1) * 16 + dstPos >= 32) {
  1280.             throw new IllegalArgumentException("(nShorts-1)*16+dstPos is greater or equal to than 32");
  1281.         }
  1282.         int out = dstInit;
  1283.         for (int i = 0; i < nShorts; i++) {
  1284.             final int shift = i * 16 + dstPos;
  1285.             final int bits = (0xffff & src[i + srcPos]) << shift;
  1286.             final int mask = 0xffff << shift;
  1287.             out = out & ~mask | bits;
  1288.         }
  1289.         return out;
  1290.     }

  1291.     /**
  1292.      * Converts an array of short into a long using the default (little-endian, Lsb0) byte and
  1293.      * bit ordering.
  1294.      *
  1295.      * @param src the short array to convert
  1296.      * @param srcPos the position in {@code src}, in short unit, from where to start the
  1297.      *            conversion
  1298.      * @param dstInit initial value of the destination long
  1299.      * @param dstPos the position of the lsb, in bits, in the result long
  1300.      * @param nShorts the number of shorts to convert
  1301.      * @return a long containing the selected bits
  1302.      * @throws NullPointerException if {@code src} is {@code null}
  1303.      * @throws IllegalArgumentException if {@code (nShorts-1)*16+dstPos >= 64}
  1304.      * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nShorts > src.length}
  1305.      */
  1306.     public static long shortArrayToLong(final short[] src, final int srcPos, final long dstInit, final int dstPos,
  1307.             final int nShorts) {
  1308.         if (src.length == 0 && srcPos == 0 || 0 == nShorts) {
  1309.             return dstInit;
  1310.         }
  1311.         if ((nShorts - 1) * 16 + dstPos >= 64) {
  1312.             throw new IllegalArgumentException("(nShorts-1)*16+dstPos is greater or equal to than 64");
  1313.         }
  1314.         long out = dstInit;
  1315.         for (int i = 0; i < nShorts; i++) {
  1316.             final int shift = i * 16 + dstPos;
  1317.             final long bits = (0xffffL & src[i + srcPos]) << shift;
  1318.             final long mask = 0xffffL << shift;
  1319.             out = out & ~mask | bits;
  1320.         }
  1321.         return out;
  1322.     }

  1323.     /**
  1324.      * Converts a short into an array of boolean using the default (little-endian, Lsb0) byte
  1325.      * and bit ordering.
  1326.      *
  1327.      * @param src the short to convert
  1328.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1329.      * @param dst the destination array
  1330.      * @param dstPos the position in {@code dst} where to copy the result
  1331.      * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
  1332.      *            the width of the input (from srcPos to msb)
  1333.      * @return {@code dst}
  1334.      * @throws NullPointerException if {@code dst} is {@code null}
  1335.      * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 16}
  1336.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
  1337.      */
  1338.     public static boolean[] shortToBinary(final short src, final int srcPos, final boolean[] dst, final int dstPos,
  1339.             final int nBools) {
  1340.         if (0 == nBools) {
  1341.             return dst;
  1342.         }
  1343.         if (nBools - 1 + srcPos >= 16) {
  1344.             throw new IllegalArgumentException("nBools-1+srcPos is greater or equal to than 16");
  1345.         }
  1346.         assert nBools - 1 < 16 - srcPos;
  1347.         for (int i = 0; i < nBools; i++) {
  1348.             final int shift = i + srcPos;
  1349.             dst[dstPos + i] = (0x1 & src >> shift) != 0;
  1350.         }
  1351.         return dst;
  1352.     }

  1353.     /**
  1354.      * Converts a short into an array of byte using the default (little-endian, Lsb0) byte and
  1355.      * bit ordering.
  1356.      *
  1357.      * @param src the short to convert
  1358.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1359.      * @param dst the destination array
  1360.      * @param dstPos the position in {@code dst} where to copy the result
  1361.      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
  1362.      *            width of the input (from srcPos to msb)
  1363.      * @return {@code dst}
  1364.      * @throws NullPointerException if {@code dst} is {@code null}
  1365.      * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 16}
  1366.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
  1367.      */
  1368.     public static byte[] shortToByteArray(final short src, final int srcPos, final byte[] dst, final int dstPos,
  1369.             final int nBytes) {
  1370.         if (0 == nBytes) {
  1371.             return dst;
  1372.         }
  1373.         if ((nBytes - 1) * 8 + srcPos >= 16) {
  1374.             throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greater or equal to than 16");
  1375.         }
  1376.         for (int i = 0; i < nBytes; i++) {
  1377.             final int shift = i * 8 + srcPos;
  1378.             dst[dstPos + i] = (byte) (0xff & src >> shift);
  1379.         }
  1380.         return dst;
  1381.     }

  1382.     /**
  1383.      * Converts a short into an array of Char using the default (little-endian, Lsb0) byte and
  1384.      * bit ordering.
  1385.      *
  1386.      * @param src the short to convert
  1387.      * @param srcPos the position in {@code src}, in bits, from where to start the conversion
  1388.      * @param dstInit the initial value for the result String
  1389.      * @param dstPos the position in {@code dst} where to copy the result
  1390.      * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
  1391.      *            width of the input (from srcPos to msb)
  1392.      * @return {@code dst}
  1393.      * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 16}
  1394.      * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
  1395.      */
  1396.     public static String shortToHex(final short src, final int srcPos, final String dstInit, final int dstPos,
  1397.             final int nHexs) {
  1398.         if (0 == nHexs) {
  1399.             return dstInit;
  1400.         }
  1401.         if ((nHexs - 1) * 4 + srcPos >= 16) {
  1402.             throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greater or equal to than 16");
  1403.         }
  1404.         final StringBuilder sb = new StringBuilder(dstInit);
  1405.         int append = sb.length();
  1406.         for (int i = 0; i < nHexs; i++) {
  1407.             final int shift = i * 4 + srcPos;
  1408.             final int bits = 0xF & src >> shift;
  1409.             if (dstPos + i == append) {
  1410.                 ++append;
  1411.                 sb.append(intToHexDigit(bits));
  1412.             } else {
  1413.                 sb.setCharAt(dstPos + i, intToHexDigit(bits));
  1414.             }
  1415.         }
  1416.         return sb.toString();
  1417.     }

  1418.     /**
  1419.      * Converts UUID into an array of byte using the default (little-endian, Lsb0) byte and bit
  1420.      * ordering.
  1421.      *
  1422.      * @param src the UUID to convert
  1423.      * @param dst the destination array
  1424.      * @param dstPos the position in {@code dst} where to copy the result
  1425.      * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
  1426.      *            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 nBytes > 16}
  1430.      * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
  1431.      */
  1432.     public static byte[] uuidToByteArray(final UUID src, final byte[] dst, final int dstPos, final int nBytes) {
  1433.         if (0 == nBytes) {
  1434.             return dst;
  1435.         }
  1436.         if (nBytes > 16) {
  1437.             throw new IllegalArgumentException("nBytes is greater than 16");
  1438.         }
  1439.         longToByteArray(src.getMostSignificantBits(), 0, dst, dstPos, Math.min(nBytes, 8));
  1440.         if (nBytes >= 8) {
  1441.             longToByteArray(src.getLeastSignificantBits(), 0, dst, dstPos + 8, nBytes - 8);
  1442.         }
  1443.         return dst;
  1444.     }

  1445.     /**
  1446.      * Constructs a new instance.
  1447.      *
  1448.      * @deprecated Will be removed in 4.0.0.
  1449.      */
  1450.     @Deprecated
  1451.     public Conversion() {
  1452.         // empty
  1453.     }
  1454. }