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