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