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