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