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