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