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 an array of char using the default (little-endian, LSB0) byte and bit ordering. 518 * 519 * @param src The byte to convert. 520 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 521 * @param dstInit The initial value for the result String. 522 * @param dstPos The position in {@code dst} where to copy the result. 523 * @param nHexs The number of chars to copy to {@code dst}, must be smaller or equal to the width of the input (from srcPos to MSB). 524 * @return {@code dst}. 525 * @throws IllegalArgumentException Thrown if {@code (nHexs - 1) * 4 + srcPos >= 8}. 526 * @throws StringIndexOutOfBoundsException Thrown if {@code dst.init.length() < dstPos}. 527 */ 528 public static String byteToHex(final byte src, final int srcPos, final String dstInit, final int dstPos, final int nHexs) { 529 if (0 == nHexs) { 530 return dstInit; 531 } 532 if (((long) nHexs - 1) * 4 + srcPos >= Byte.SIZE) { 533 throw new IllegalArgumentException("(nHexs - 1) * 4 + srcPos >= 8"); 534 } 535 final StringBuilder sb = new StringBuilder(dstInit); 536 int append = sb.length(); 537 for (int i = 0; i < nHexs; i++) { 538 final int shift = i * 4 + srcPos; 539 final int bits = 0xF & src >> shift; 540 if (dstPos + i == append) { 541 ++append; 542 sb.append(intToHexDigit(bits)); 543 } else { 544 sb.setCharAt(dstPos + i, intToHexDigit(bits)); 545 } 546 } 547 return sb.toString(); 548 } 549 550 /** 551 * Converts a hexadecimal digit into binary (represented as boolean array) using the MSB0 bit ordering. 552 * 553 * <p> 554 * '1' is converted as follow: (0, 0, 0, 1). 555 * </p> 556 * 557 * @param hexChar The hexadecimal digit to convert. 558 * @return A boolean array with the binary representation of {@code hexDigit}. 559 * @throws IllegalArgumentException Thrown if {@code hexDigit} is not a hexadecimal digit. 560 */ 561 public static boolean[] hexDigitMsb0ToBinary(final char hexChar) { 562 switch (hexChar) { 563 case '0': 564 return FFFF.clone(); 565 case '1': 566 return FFFT.clone(); 567 case '2': 568 return FFTF.clone(); 569 case '3': 570 return FFTT.clone(); 571 case '4': 572 return FTFF.clone(); 573 case '5': 574 return FTFT.clone(); 575 case '6': 576 return FTTF.clone(); 577 case '7': 578 return FTTT.clone(); 579 case '8': 580 return TFFF.clone(); 581 case '9': 582 return TFFT.clone(); 583 case 'a':// fall through 584 case 'A': 585 return TFTF.clone(); 586 case 'b':// fall through 587 case 'B': 588 return TFTT.clone(); 589 case 'c':// fall through 590 case 'C': 591 return TTFF.clone(); 592 case 'd':// fall through 593 case 'D': 594 return TTFT.clone(); 595 case 'e':// fall through 596 case 'E': 597 return TTTF.clone(); 598 case 'f':// fall through 599 case 'F': 600 return TTTT.clone(); 601 default: 602 throw new IllegalArgumentException("Cannot convert '" + hexChar + "' to a hexadecimal digit"); 603 } 604 } 605 606 /** 607 * Converts a hexadecimal digit into an int using the MSB0 bit ordering. 608 * 609 * <p> 610 * '1' is converted to 8. 611 * </p> 612 * 613 * @param hexChar The hexadecimal digit to convert. 614 * @return An int equals to {@code hexDigit}. 615 * @throws IllegalArgumentException Thrown if {@code hexDigit} is not a hexadecimal digit. 616 */ 617 public static int hexDigitMsb0ToInt(final char hexChar) { 618 switch (hexChar) { 619 case '0': 620 return 0x0; 621 case '1': 622 return 0x8; 623 case '2': 624 return 0x4; 625 case '3': 626 return 0xC; 627 case '4': 628 return 0x2; 629 case '5': 630 return 0xA; 631 case '6': 632 return 0x6; 633 case '7': 634 return 0xE; 635 case '8': 636 return 0x1; 637 case '9': 638 return 0x9; 639 case 'a':// fall through 640 case 'A': 641 return 0x5; 642 case 'b':// fall through 643 case 'B': 644 return 0xD; 645 case 'c':// fall through 646 case 'C': 647 return 0x3; 648 case 'd':// fall through 649 case 'D': 650 return 0xB; 651 case 'e':// fall through 652 case 'E': 653 return 0x7; 654 case 'f':// fall through 655 case 'F': 656 return 0xF; 657 default: 658 throw new IllegalArgumentException("Cannot convert '" + hexChar + "' to a hexadecimal digit"); 659 } 660 } 661 662 /** 663 * Converts a hexadecimal digit into binary (represented as boolean array) using the default (LSB0) bit ordering. 664 * 665 * <p> 666 * '1' is converted as follow: (1, 0, 0, 0). 667 * </p> 668 * 669 * @param hexChar The hexadecimal digit to convert. 670 * @return A boolean array with the binary representation of {@code hexDigit}. 671 * @throws IllegalArgumentException Thrown if {@code hexDigit} is not a hexadecimal digit. 672 */ 673 public static boolean[] hexDigitToBinary(final char hexChar) { 674 switch (hexChar) { 675 case '0': 676 return FFFF.clone(); 677 case '1': 678 return TFFF.clone(); 679 case '2': 680 return FTFF.clone(); 681 case '3': 682 return TTFF.clone(); 683 case '4': 684 return FFTF.clone(); 685 case '5': 686 return TFTF.clone(); 687 case '6': 688 return FTTF.clone(); 689 case '7': 690 return TTTF.clone(); 691 case '8': 692 return FFFT.clone(); 693 case '9': 694 return TFFT.clone(); 695 case 'a':// fall through 696 case 'A': 697 return FTFT.clone(); 698 case 'b':// fall through 699 case 'B': 700 return TTFT.clone(); 701 case 'c':// fall through 702 case 'C': 703 return FFTT.clone(); 704 case 'd':// fall through 705 case 'D': 706 return TFTT.clone(); 707 case 'e':// fall through 708 case 'E': 709 return FTTT.clone(); 710 case 'f':// fall through 711 case 'F': 712 return TTTT.clone(); 713 default: 714 throw new IllegalArgumentException("Cannot convert '" + hexChar + "' to a hexadecimal digit"); 715 } 716 } 717 718 /** 719 * Converts a hexadecimal digit into an int using the default (LSB0) bit ordering. 720 * 721 * <p> 722 * '1' is converted to 1. 723 * </p> 724 * 725 * @param hexChar The hexadecimal digit to convert. 726 * @return An int equals to {@code hexDigit}. 727 * @throws IllegalArgumentException Thrown if {@code hexDigit} is not a hexadecimal digit. 728 */ 729 public static int hexDigitToInt(final char hexChar) { 730 if (!CharUtils.isHex(hexChar)) { 731 throw new IllegalArgumentException("Cannot convert '" + hexChar + "' to a hexadecimal digit"); 732 } 733 return Character.digit(hexChar, 16); 734 } 735 736 /** 737 * Converts a hexadecimal string into a byte using the default (little-endian, LSB0) byte and bit ordering. 738 * 739 * @param src The hexadecimal string to convert. 740 * @param srcPos The position in {@code src}, in char unit, from where to start the conversion. 741 * @param dstInit initial value of the destination byte. 742 * @param dstPos The position of the LSB, in bits, in the result byte. 743 * @param nHex The number of Chars to convert. 744 * @return A byte containing the selected bits. 745 * @throws IllegalArgumentException Thrown if {@code (nHex-1)*4+dstPos >= 8}. 746 */ 747 public static byte hexToByte(final String src, final int srcPos, final byte dstInit, final int dstPos, final int nHex) { 748 if (0 == nHex) { 749 return dstInit; 750 } 751 if (((long) nHex - 1) * 4 + dstPos >= Byte.SIZE) { 752 throw new IllegalArgumentException("(nHex - 1) * 4 + dstPos >= 8"); 753 } 754 byte out = dstInit; 755 for (int i = 0; i < nHex; i++) { 756 final int shift = i * 4 + dstPos; 757 final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift; 758 final int mask = 0xf << shift; 759 out = (byte) (out & ~mask | bits); 760 } 761 return out; 762 } 763 764 /** 765 * Converts an array of char into an int using the default (little-endian, LSB0) byte and bit ordering. 766 * 767 * @param src The hexadecimal string to convert. 768 * @param srcPos The position in {@code src}, in char unit, from where to start the conversion. 769 * @param dstInit initial value of the destination int. 770 * @param dstPos The position of the LSB, in bits, in the result int. 771 * @param nHex The number of chars to convert. 772 * @return An int containing the selected bits. 773 * @throws IllegalArgumentException Thrown if {@code (nHexs - 1) * 4 + dstPos >= 32}. 774 */ 775 public static int hexToInt(final String src, final int srcPos, final int dstInit, final int dstPos, final int nHex) { 776 if (0 == nHex) { 777 return dstInit; 778 } 779 if (((long) nHex - 1) * 4 + dstPos >= Integer.SIZE) { 780 throw new IllegalArgumentException("(nHexs - 1) * 4 + dstPos >= 32"); 781 } 782 int out = dstInit; 783 for (int i = 0; i < nHex; i++) { 784 final int shift = i * 4 + dstPos; 785 final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift; 786 final int mask = 0xf << shift; 787 out = out & ~mask | bits; 788 } 789 return out; 790 } 791 792 /** 793 * Converts an array of char into a long using the default (little-endian, LSB0) byte and bit ordering. 794 * 795 * @param src The hexadecimal string to convert. 796 * @param srcPos The position in {@code src}, in char unit, from where to start the conversion. 797 * @param dstInit initial value of the destination long. 798 * @param dstPos The position of the LSB, in bits, in the result long. 799 * @param nHex The number of chars to convert. 800 * @return A long containing the selected bits. 801 * @throws IllegalArgumentException Thrown if {@code (nHexs - 1) * 4 + dstPos >= 64}. 802 */ 803 public static long hexToLong(final String src, final int srcPos, final long dstInit, final int dstPos, final int nHex) { 804 if (0 == nHex) { 805 return dstInit; 806 } 807 if (((long) nHex - 1) * 4 + dstPos >= Long.SIZE) { 808 throw new IllegalArgumentException("(nHexs - 1) * 4 + dstPos >= 64"); 809 } 810 long out = dstInit; 811 for (int i = 0; i < nHex; i++) { 812 final int shift = i * 4 + dstPos; 813 final long bits = (0xfL & hexDigitToInt(src.charAt(i + srcPos))) << shift; 814 final long mask = 0xfL << shift; 815 out = out & ~mask | bits; 816 } 817 return out; 818 } 819 820 /** 821 * Converts an array of char into a short using the default (little-endian, LSB0) byte and bit ordering. 822 * 823 * @param src The hexadecimal string to convert. 824 * @param srcPos The position in {@code src}, in char unit, from where to start the conversion. 825 * @param dstInit initial value of the destination short. 826 * @param dstPos The position of the LSB, in bits, in the result short. 827 * @param nHex The number of chars to convert. 828 * @return A short containing the selected bits. 829 * @throws IllegalArgumentException Thrown if {@code (nHexs - 1) * 4 + dstPos >= 16}. 830 */ 831 public static short hexToShort(final String src, final int srcPos, final short dstInit, final int dstPos, final int nHex) { 832 if (0 == nHex) { 833 return dstInit; 834 } 835 if (((long) nHex - 1) * 4 + dstPos >= Short.SIZE) { 836 throw new IllegalArgumentException("(nHexs - 1) * 4 + dstPos >= 16"); 837 } 838 short out = dstInit; 839 for (int i = 0; i < nHex; i++) { 840 final int shift = i * 4 + dstPos; 841 final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift; 842 final int mask = 0xf << shift; 843 out = (short) (out & ~mask | bits); 844 } 845 return out; 846 } 847 848 /** 849 * Converts an array of int into a long using the default (little-endian, LSB0) byte and bit ordering. 850 * 851 * @param src The int array to convert. 852 * @param srcPos The position in {@code src}, in int unit, from where to start the conversion. 853 * @param dstInit initial value of the destination long. 854 * @param dstPos The position of the LSB, in bits, in the result long. 855 * @param nInts The number of ints to convert. 856 * @return A long containing the selected bits. 857 * @throws IllegalArgumentException Thrown if {@code (nInts - 1) * 32 + dstPos >= 64}. 858 * @throws NullPointerException Thrown if {@code src} is {@code null}. 859 * @throws ArrayIndexOutOfBoundsException Thrown if {@code srcPos + nInts > src.length}. 860 */ 861 public static long intArrayToLong(final int[] src, final int srcPos, final long dstInit, final int dstPos, final int nInts) { 862 if (src.length == 0 && srcPos == 0 || 0 == nInts) { 863 return dstInit; 864 } 865 if (((long) nInts - 1) * Integer.SIZE + dstPos >= Long.SIZE) { 866 throw new IllegalArgumentException("(nInts - 1) * 32 + dstPos >= 64"); 867 } 868 long out = dstInit; 869 for (int i = 0; i < nInts; i++) { 870 final int shift = i * Integer.SIZE + dstPos; 871 final long bits = (0xffffffffL & src[i + srcPos]) << shift; 872 final long mask = 0xffffffffL << shift; 873 out = out & ~mask | bits; 874 } 875 return out; 876 } 877 878 /** 879 * Converts an int into an array of boolean using the default (little-endian, LSB0) byte and bit ordering. 880 * 881 * @param src The int to convert. 882 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 883 * @param dst The destination array. 884 * @param dstPos The position in {@code dst} where to copy the result. 885 * @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). 886 * @return {@code dst}. 887 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 888 * @throws IllegalArgumentException Thrown if {@code nBools - 1 + srcPos >= 32}. 889 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nBools > dst.length}. 890 */ 891 public static boolean[] intToBinary(final int src, final int srcPos, final boolean[] dst, final int dstPos, final int nBools) { 892 if (0 == nBools) { 893 return dst; 894 } 895 if ((long) nBools - 1 + srcPos >= Integer.SIZE) { 896 throw new IllegalArgumentException("nBools - 1 + srcPos >= 32"); 897 } 898 for (int i = 0; i < nBools; i++) { 899 final int shift = i + srcPos; 900 dst[dstPos + i] = (0x1 & src >> shift) != 0; 901 } 902 return dst; 903 } 904 905 /** 906 * Converts an int into an array of byte using the default (little-endian, LSB0) byte and bit ordering. 907 * 908 * @param src The int to convert. 909 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 910 * @param dst The destination array. 911 * @param dstPos The position in {@code dst} where to copy the result. 912 * @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). 913 * @return {@code dst}. 914 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 915 * @throws IllegalArgumentException Thrown if {@code (nBytes - 1) * 8 + srcPos >= 32}. 916 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nBytes > dst.length}. 917 */ 918 public static byte[] intToByteArray(final int src, final int srcPos, final byte[] dst, final int dstPos, final int nBytes) { 919 if (0 == nBytes) { 920 return dst; 921 } 922 if (((long) nBytes - 1) * Byte.SIZE + srcPos >= Integer.SIZE) { 923 throw new IllegalArgumentException("(nBytes - 1) * 8 + srcPos >= 32"); 924 } 925 for (int i = 0; i < nBytes; i++) { 926 final int shift = i * Byte.SIZE + srcPos; 927 dst[dstPos + i] = (byte) (0xff & src >> shift); 928 } 929 return dst; 930 } 931 932 /** 933 * Converts an int into an array of char using the default (little-endian, LSB0) byte and bit ordering. 934 * 935 * @param src The int to convert. 936 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 937 * @param dstInit The initial value for the result String. 938 * @param dstPos The position in {@code dst} where to copy the result. 939 * @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). 940 * @return {@code dst}. 941 * @throws IllegalArgumentException Thrown if {@code (nHexs - 1) * 4 + srcPos >= 32}. 942 * @throws StringIndexOutOfBoundsException Thrown if {@code dst.init.length() < dstPos}. 943 */ 944 public static String intToHex(final int src, final int srcPos, final String dstInit, final int dstPos, final int nHexs) { 945 if (0 == nHexs) { 946 return dstInit; 947 } 948 if (((long) nHexs - 1) * 4 + srcPos >= Integer.SIZE) { 949 throw new IllegalArgumentException("(nHexs - 1) * 4 + srcPos >= 32"); 950 } 951 final StringBuilder sb = new StringBuilder(dstInit); 952 int append = sb.length(); 953 for (int i = 0; i < nHexs; i++) { 954 final int shift = i * 4 + srcPos; 955 final int bits = 0xF & src >> shift; 956 if (dstPos + i == append) { 957 ++append; 958 sb.append(intToHexDigit(bits)); 959 } else { 960 sb.setCharAt(dstPos + i, intToHexDigit(bits)); 961 } 962 } 963 return sb.toString(); 964 } 965 966 /** 967 * Converts the 4 LSB of an int to a hexadecimal digit. 968 * 969 * <p> 970 * 0 returns '0' 971 * </p> 972 * <p> 973 * 1 returns '1' 974 * </p> 975 * <p> 976 * 10 returns 'A' and so on... 977 * </p> 978 * 979 * @param nibble The 4 bits to convert. 980 * @return A hexadecimal digit representing the 4 LSB of {@code nibble}. 981 * @throws IllegalArgumentException Thrown if {@code nibble < 0} or {@code nibble > 15}. 982 */ 983 public static char intToHexDigit(final int nibble) { 984 final char c = Character.forDigit(nibble, 16); 985 if (c == Character.MIN_VALUE) { 986 throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble); 987 } 988 return c; 989 } 990 991 /** 992 * Converts the 4 LSB of an int to a hexadecimal digit encoded using the MSB0 bit ordering. 993 * 994 * <p> 995 * 0 returns '0' 996 * </p> 997 * <p> 998 * 1 returns '8' 999 * </p> 1000 * <p> 1001 * 10 returns '5' and so on... 1002 * </p> 1003 * 1004 * @param nibble The 4 bits to convert. 1005 * @return A hexadecimal digit representing the 4 LSB of {@code nibble}. 1006 * @throws IllegalArgumentException Thrown if {@code nibble < 0} or {@code nibble > 15}. 1007 */ 1008 public static char intToHexDigitMsb0(final int nibble) { 1009 switch (nibble) { 1010 case 0x0: 1011 return '0'; 1012 case 0x1: 1013 return '8'; 1014 case 0x2: 1015 return '4'; 1016 case 0x3: 1017 return 'c'; 1018 case 0x4: 1019 return '2'; 1020 case 0x5: 1021 return 'a'; 1022 case 0x6: 1023 return '6'; 1024 case 0x7: 1025 return 'e'; 1026 case 0x8: 1027 return '1'; 1028 case 0x9: 1029 return '9'; 1030 case 0xA: 1031 return '5'; 1032 case 0xB: 1033 return 'd'; 1034 case 0xC: 1035 return '3'; 1036 case 0xD: 1037 return 'b'; 1038 case 0xE: 1039 return '7'; 1040 case 0xF: 1041 return 'f'; 1042 default: 1043 throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble); 1044 } 1045 } 1046 1047 /** 1048 * Converts an int into an array of short using the default (little-endian, LSB0) byte and bit ordering. 1049 * 1050 * @param src The int to convert. 1051 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1052 * @param dst The destination array. 1053 * @param dstPos The position in {@code dst} where to copy the result. 1054 * @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). 1055 * @return {@code dst}. 1056 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 1057 * @throws IllegalArgumentException Thrown if {@code (nShorts - 1) * 16 + srcPos >= 32}. 1058 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nShorts > dst.length}. 1059 */ 1060 public static short[] intToShortArray(final int src, final int srcPos, final short[] dst, final int dstPos, final int nShorts) { 1061 if (0 == nShorts) { 1062 return dst; 1063 } 1064 if (((long) nShorts - 1) * Short.SIZE + srcPos >= Integer.SIZE) { 1065 throw new IllegalArgumentException("(nShorts - 1) * 16 + srcPos >= 32"); 1066 } 1067 for (int i = 0; i < nShorts; i++) { 1068 final int shift = i * Short.SIZE + srcPos; 1069 dst[dstPos + i] = (short) (0xffff & src >> shift); 1070 } 1071 return dst; 1072 } 1073 1074 /** 1075 * Converts a long into an array of boolean using the default (little-endian, LSB0) byte and bit ordering. 1076 * 1077 * @param src The long to convert. 1078 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1079 * @param dst The destination array. 1080 * @param dstPos The position in {@code dst} where to copy the result. 1081 * @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). 1082 * @return {@code dst}. 1083 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 1084 * @throws IllegalArgumentException Thrown if {@code nBools - 1 + srcPos >= 64}. 1085 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nBools > dst.length}. 1086 */ 1087 public static boolean[] longToBinary(final long src, final int srcPos, final boolean[] dst, final int dstPos, final int nBools) { 1088 if (0 == nBools) { 1089 return dst; 1090 } 1091 if ((long) nBools - 1 + srcPos >= Long.SIZE) { 1092 throw new IllegalArgumentException("nBools - 1 + srcPos >= 64"); 1093 } 1094 for (int i = 0; i < nBools; i++) { 1095 final int shift = i + srcPos; 1096 dst[dstPos + i] = (0x1 & src >> shift) != 0; 1097 } 1098 return dst; 1099 } 1100 1101 /** 1102 * Converts a long into an array of byte using the default (little-endian, LSB0) byte and bit ordering. 1103 * 1104 * @param src The long to convert. 1105 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1106 * @param dst The destination array. 1107 * @param dstPos The position in {@code dst} where to copy the result. 1108 * @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). 1109 * @return {@code dst}. 1110 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 1111 * @throws IllegalArgumentException Thrown if {@code (nBytes - 1) * 8 + srcPos >= 64}. 1112 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nBytes > dst.length}. 1113 */ 1114 public static byte[] longToByteArray(final long src, final int srcPos, final byte[] dst, final int dstPos, final int nBytes) { 1115 if (0 == nBytes) { 1116 return dst; 1117 } 1118 if (((long) nBytes - 1) * Byte.SIZE + srcPos >= Long.SIZE) { 1119 throw new IllegalArgumentException("(nBytes - 1) * 8 + srcPos >= 64"); 1120 } 1121 for (int i = 0; i < nBytes; i++) { 1122 final int shift = i * Byte.SIZE + srcPos; 1123 dst[dstPos + i] = (byte) (0xff & src >> shift); 1124 } 1125 return dst; 1126 } 1127 1128 /** 1129 * Converts a long into an array of char using the default (little-endian, LSB0) byte and bit ordering. 1130 * 1131 * @param src The long to convert. 1132 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1133 * @param dstInit The initial value for the result String. 1134 * @param dstPos The position in {@code dst} where to copy the result. 1135 * @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). 1136 * @return {@code dst}. 1137 * @throws IllegalArgumentException Thrown if {@code (nHexs - 1) * 4 + srcPos >= 64}. 1138 * @throws StringIndexOutOfBoundsException Thrown if {@code dst.init.length() < dstPos}. 1139 */ 1140 public static String longToHex(final long src, final int srcPos, final String dstInit, final int dstPos, final int nHexs) { 1141 if (0 == nHexs) { 1142 return dstInit; 1143 } 1144 if (((long) nHexs - 1) * 4 + srcPos >= Long.SIZE) { 1145 throw new IllegalArgumentException("(nHexs - 1) * 4 + srcPos >= 64"); 1146 } 1147 final StringBuilder sb = new StringBuilder(dstInit); 1148 int append = sb.length(); 1149 for (int i = 0; i < nHexs; i++) { 1150 final int shift = i * 4 + srcPos; 1151 final int bits = (int) (0xF & src >> shift); 1152 if (dstPos + i == append) { 1153 ++append; 1154 sb.append(intToHexDigit(bits)); 1155 } else { 1156 sb.setCharAt(dstPos + i, intToHexDigit(bits)); 1157 } 1158 } 1159 return sb.toString(); 1160 } 1161 1162 /** 1163 * Converts a long into an array of int using the default (little-endian, LSB0) byte and bit ordering. 1164 * 1165 * @param src The long to convert. 1166 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1167 * @param dst The destination array. 1168 * @param dstPos The position in {@code dst} where to copy the result. 1169 * @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). 1170 * @return {@code dst}. 1171 * @throws NullPointerException Thrown if {@code dst} is {@code null} and {@code nInts > 0}. 1172 * @throws IllegalArgumentException Thrown if {@code (nInts - 1) * 32 + srcPos >= 64}. 1173 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nInts > dst.length}. 1174 */ 1175 public static int[] longToIntArray(final long src, final int srcPos, final int[] dst, final int dstPos, final int nInts) { 1176 if (0 == nInts) { 1177 return dst; 1178 } 1179 if (((long) nInts - 1) * Integer.SIZE + srcPos >= Long.SIZE) { 1180 throw new IllegalArgumentException("(nInts - 1) * 32 + srcPos >= 64"); 1181 } 1182 for (int i = 0; i < nInts; i++) { 1183 final int shift = i * Integer.SIZE + srcPos; 1184 dst[dstPos + i] = (int) (0xffffffff & src >> shift); 1185 } 1186 return dst; 1187 } 1188 1189 /** 1190 * Converts a long into an array of short using the default (little-endian, LSB0) byte and bit ordering. 1191 * 1192 * @param src The long to convert. 1193 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1194 * @param dst The destination array. 1195 * @param dstPos The position in {@code dst} where to copy the result. 1196 * @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). 1197 * @return {@code dst}. 1198 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 1199 * @throws IllegalArgumentException Thrown if {@code (nShorts - 1) * 16 + srcPos >= 64}. 1200 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nShorts > dst.length}. 1201 */ 1202 public static short[] longToShortArray(final long src, final int srcPos, final short[] dst, final int dstPos, final int nShorts) { 1203 if (0 == nShorts) { 1204 return dst; 1205 } 1206 if (((long) nShorts - 1) * Short.SIZE + srcPos >= Long.SIZE) { 1207 throw new IllegalArgumentException("(nShorts - 1) * 16 + srcPos >= 64"); 1208 } 1209 for (int i = 0; i < nShorts; i++) { 1210 final int shift = i * Short.SIZE + srcPos; 1211 dst[dstPos + i] = (short) (0xffff & src >> shift); 1212 } 1213 return dst; 1214 } 1215 1216 /** 1217 * Converts an array of short into an int using the default (little-endian, LSB0) byte and bit ordering. 1218 * 1219 * @param src The short array to convert. 1220 * @param srcPos The position in {@code src}, in short unit, from where to start the conversion. 1221 * @param dstInit initial value of the destination int. 1222 * @param dstPos The position of the LSB, in bits, in the result int. 1223 * @param nShorts The number of shorts to convert. 1224 * @return An int containing the selected bits. 1225 * @throws NullPointerException Thrown if {@code src} is {@code null}. 1226 * @throws IllegalArgumentException Thrown if {@code (nShorts - 1) * 16 + dstPos >= 32}. 1227 * @throws ArrayIndexOutOfBoundsException Thrown if {@code srcPos + nShorts > src.length}. 1228 */ 1229 public static int shortArrayToInt(final short[] src, final int srcPos, final int dstInit, final int dstPos, final int nShorts) { 1230 if (src.length == 0 && srcPos == 0 || 0 == nShorts) { 1231 return dstInit; 1232 } 1233 if (((long) nShorts - 1) * Short.SIZE + dstPos >= Integer.SIZE) { 1234 throw new IllegalArgumentException("(nShorts - 1) * 16 + dstPos >= 32"); 1235 } 1236 int out = dstInit; 1237 for (int i = 0; i < nShorts; i++) { 1238 final int shift = i * Short.SIZE + dstPos; 1239 final int bits = (0xffff & src[i + srcPos]) << shift; 1240 final int mask = 0xffff << shift; 1241 out = out & ~mask | bits; 1242 } 1243 return out; 1244 } 1245 1246 /** 1247 * Converts an array of short into a long using the default (little-endian, LSB0) byte and bit ordering. 1248 * 1249 * @param src The short array to convert. 1250 * @param srcPos The position in {@code src}, in short unit, from where to start the conversion. 1251 * @param dstInit initial value of the destination long. 1252 * @param dstPos The position of the LSB, in bits, in the result long. 1253 * @param nShorts The number of shorts to convert. 1254 * @return A long containing the selected bits. 1255 * @throws NullPointerException Thrown if {@code src} is {@code null}. 1256 * @throws IllegalArgumentException Thrown if {@code (nShorts - 1) * 16 + dstPos >= 64}. 1257 * @throws ArrayIndexOutOfBoundsException Thrown if {@code srcPos + nShorts > src.length}. 1258 */ 1259 public static long shortArrayToLong(final short[] src, final int srcPos, final long dstInit, final int dstPos, final int nShorts) { 1260 if (src.length == 0 && srcPos == 0 || 0 == nShorts) { 1261 return dstInit; 1262 } 1263 if (((long) nShorts - 1) * Short.SIZE + dstPos >= Long.SIZE) { 1264 throw new IllegalArgumentException("(nShorts - 1) * 16 + dstPos >= 64"); 1265 } 1266 long out = dstInit; 1267 for (int i = 0; i < nShorts; i++) { 1268 final int shift = i * Short.SIZE + dstPos; 1269 final long bits = (0xffffL & src[i + srcPos]) << shift; 1270 final long mask = 0xffffL << shift; 1271 out = out & ~mask | bits; 1272 } 1273 return out; 1274 } 1275 1276 /** 1277 * Converts a short into an array of boolean using the default (little-endian, LSB0) byte and bit ordering. 1278 * 1279 * @param src The short to convert. 1280 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1281 * @param dst The destination array. 1282 * @param dstPos The position in {@code dst} where to copy the result. 1283 * @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). 1284 * @return {@code dst}. 1285 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 1286 * @throws IllegalArgumentException Thrown if {@code nBools - 1 + srcPos >= 16}. 1287 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nBools > dst.length}. 1288 */ 1289 public static boolean[] shortToBinary(final short src, final int srcPos, final boolean[] dst, final int dstPos, final int nBools) { 1290 if (0 == nBools) { 1291 return dst; 1292 } 1293 if ((long) nBools - 1 + srcPos >= Short.SIZE) { 1294 throw new IllegalArgumentException("nBools - 1 + srcPos >= 16"); 1295 } 1296 assert nBools - 1 < Short.SIZE - srcPos; 1297 for (int i = 0; i < nBools; i++) { 1298 final int shift = i + srcPos; 1299 dst[dstPos + i] = (0x1 & src >> shift) != 0; 1300 } 1301 return dst; 1302 } 1303 1304 /** 1305 * Converts a short into an array of byte using the default (little-endian, LSB0) byte and bit ordering. 1306 * 1307 * @param src The short to convert. 1308 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1309 * @param dst The destination array. 1310 * @param dstPos The position in {@code dst} where to copy the result. 1311 * @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). 1312 * @return {@code dst}. 1313 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 1314 * @throws IllegalArgumentException Thrown if {@code (nBytes - 1) * 8 + srcPos >= 16}. 1315 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nBytes > dst.length}. 1316 */ 1317 public static byte[] shortToByteArray(final short src, final int srcPos, final byte[] dst, final int dstPos, final int nBytes) { 1318 if (0 == nBytes) { 1319 return dst; 1320 } 1321 if (((long) nBytes - 1) * Byte.SIZE + srcPos >= Short.SIZE) { 1322 throw new IllegalArgumentException("(nBytes - 1) * 8 + srcPos >= 16"); 1323 } 1324 for (int i = 0; i < nBytes; i++) { 1325 final int shift = i * Byte.SIZE + srcPos; 1326 dst[dstPos + i] = (byte) (0xff & src >> shift); 1327 } 1328 return dst; 1329 } 1330 1331 /** 1332 * Converts a short into an array of char using the default (little-endian, LSB0) byte and bit ordering. 1333 * 1334 * @param src The short to convert. 1335 * @param srcPos The position in {@code src}, in bits, from where to start the conversion. 1336 * @param dstInit The initial value for the result String. 1337 * @param dstPos The position in {@code dst} where to copy the result. 1338 * @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). 1339 * @return {@code dst}. 1340 * @throws IllegalArgumentException Thrown if {@code (nHexs - 1) * 4 + srcPos >= 16}. 1341 * @throws StringIndexOutOfBoundsException Thrown if {@code dst.init.length() < dstPos}. 1342 */ 1343 public static String shortToHex(final short src, final int srcPos, final String dstInit, final int dstPos, final int nHexs) { 1344 if (0 == nHexs) { 1345 return dstInit; 1346 } 1347 if (((long) nHexs - 1) * 4 + srcPos >= Short.SIZE) { 1348 throw new IllegalArgumentException("(nHexs - 1) * 4 + srcPos >= 16"); 1349 } 1350 final StringBuilder sb = new StringBuilder(dstInit); 1351 int append = sb.length(); 1352 for (int i = 0; i < nHexs; i++) { 1353 final int shift = i * 4 + srcPos; 1354 final int bits = 0xF & src >> shift; 1355 if (dstPos + i == append) { 1356 ++append; 1357 sb.append(intToHexDigit(bits)); 1358 } else { 1359 sb.setCharAt(dstPos + i, intToHexDigit(bits)); 1360 } 1361 } 1362 return sb.toString(); 1363 } 1364 1365 /** 1366 * Converts UUID into an array of byte using the default (little-endian, LSB0) byte and bit ordering. 1367 * 1368 * @param src The UUID to convert. 1369 * @param dst The destination array. 1370 * @param dstPos The position in {@code dst} where to copy the result. 1371 * @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). 1372 * @return {@code dst}. 1373 * @throws NullPointerException Thrown if {@code dst} is {@code null}. 1374 * @throws IllegalArgumentException Thrown if {@code nBytes > 16}. 1375 * @throws ArrayIndexOutOfBoundsException Thrown if {@code dstPos + nBytes > dst.length}. 1376 */ 1377 public static byte[] uuidToByteArray(final UUID src, final byte[] dst, final int dstPos, final int nBytes) { 1378 if (0 == nBytes) { 1379 return dst; 1380 } 1381 if (nBytes > 16) { 1382 throw new IllegalArgumentException("nBytes > 16"); 1383 } 1384 longToByteArray(src.getMostSignificantBits(), 0, dst, dstPos, Math.min(nBytes, 8)); 1385 if (nBytes >= 8) { 1386 longToByteArray(src.getLeastSignificantBits(), 0, dst, dstPos + 8, nBytes - 8); 1387 } 1388 return dst; 1389 } 1390 1391 /** 1392 * Constructs a new instance. 1393 * 1394 * @deprecated Will be removed in 4.0.0. 1395 */ 1396 @Deprecated 1397 public Conversion() { 1398 // empty 1399 } 1400}