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