Coverage Summary for Class: ByteUtil (org.ethereum.util)

Class Class, % Method, % Line, %
ByteUtil 100% (1/1) 36.2% (17/47) 32.9% (70/213)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20 package org.ethereum.util; 21  22 import org.bouncycastle.util.encoders.Hex; 23 import org.ethereum.db.ByteArrayWrapper; 24  25 import javax.annotation.Nonnull; 26 import javax.annotation.Nullable; 27 import java.math.BigInteger; 28 import java.nio.ByteBuffer; 29 import java.util.Arrays; 30 import java.util.HashSet; 31 import java.util.Objects; 32 import java.util.Set; 33  34 public class ByteUtil { 35  36  private ByteUtil() { 37  } 38  39  public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 40  private static final byte[] ZERO_BYTE_ARRAY = new byte[]{0}; 41  42  /** 43  * Creates a copy of bytes and appends b to the end of it 44  */ 45  public static byte[] appendByte(byte[] bytes, byte b) { 46  byte[] result = Arrays.copyOf(bytes, bytes.length + 1); 47  result[result.length - 1] = b; 48  return result; 49  } 50  51  public static byte[] cloneBytes(byte[] bytes) { 52  if (bytes == null) { 53  return EMPTY_BYTE_ARRAY; 54  } 55  56  return Arrays.copyOf(bytes, bytes.length); 57  } 58  59  /** 60  * Adds leading zeros to a {@code src} byte array to have at least {@code len} length. 61  * 62  * @param src a source byte array 63  * @param len the minimum length of the final byte array with leading zeros. 64  * @return byte array with leading zeros. 65  */ 66  public static byte[] toBytesWithLeadingZeros(byte[] src, int len) { 67  if (len < 0) { 68  throw new IllegalArgumentException("len"); 69  } 70  71  if (src == null || len <= src.length) { 72  return src; 73  } 74  75  byte[] dest = new byte[len]; 76  int start = len - src.length; 77  System.arraycopy(src, 0, dest, start, src.length); 78  79  return dest; 80  } 81  82  /** 83  * The regular {@link java.math.BigInteger#toByteArray()} method isn't quite what we often need: 84  * it appends a leading zero to indicate that the number is positive and may need padding. 85  * 86  * @param b the integer to format into a byte array 87  * @param numBytes the desired size of the resulting byte array 88  * @return numBytes byte long array. 89  */ 90  public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { 91  if (b == null) { 92  return EMPTY_BYTE_ARRAY; 93  } 94  byte[] bytes = new byte[numBytes]; 95  byte[] biBytes = b.toByteArray(); 96  int start = (biBytes.length == numBytes + 1) ? 1 : 0; 97  int length = Math.min(biBytes.length, numBytes); 98  System.arraycopy(biBytes, start, bytes, numBytes - length, length); 99  return bytes; 100  } 101  102  /** 103  * Omitting sign indication byte. 104  * <br><br> 105  * Instead of {@link org.bouncycastle.util.BigIntegers#asUnsignedByteArray(BigInteger)} 106  * <br>we use this custom method to avoid an empty array in case of BigInteger.ZERO 107  * 108  * @param value - any big integer number. A <code>null</code>-value will return <code>null</code> 109  * @return A byte array without a leading zero byte if present in the signed encoding. 110  * BigInteger.ZERO will return an array with length 1 and byte-value 0. 111  */ 112  public static byte[] bigIntegerToBytes(BigInteger value) { 113  if (value == null) { 114  return EMPTY_BYTE_ARRAY; 115  } 116  117  byte[] data = value.toByteArray(); 118  119  if (data.length != 1 && data[0] == 0) { 120  byte[] tmp = new byte[data.length - 1]; 121  System.arraycopy(data, 1, tmp, 0, tmp.length); 122  data = tmp; 123  } 124  return data; 125  } 126  127  /** 128  * Parses fixed number of bytes starting from {@code offset} in {@code input} array. 129  * If {@code input} has not enough bytes return array will be right padded with zero bytes. 130  * I.e. if {@code offset} is higher than {@code input.length} then zero byte array of length {@code len} will be returned 131  */ 132  public static byte[] parseBytes(byte[] input, int offset, int len) { 133  134  if (offset >= input.length || len == 0) { 135  return EMPTY_BYTE_ARRAY; 136  } 137  138  byte[] bytes = new byte[len]; 139  System.arraycopy(input, offset, bytes, 0, Math.min(input.length - offset, len)); 140  return bytes; 141  } 142  143  /** 144  * Parses 32-bytes word from given input. 145  * Uses {@link #parseBytes(byte[], int, int)} method, 146  * thus, result will be right-padded with zero bytes if there is not enough bytes in {@code input} 147  * 148  * @param idx an index of the word starting from {@code 0} 149  */ 150  public static byte[] parseWord(byte[] input, int idx) { 151  return parseBytes(input, 32 * idx, 32); 152  } 153  154  /** 155  * Parses 32-bytes word from given input. 156  * Uses {@link #parseBytes(byte[], int, int)} method, 157  * thus, result will be right-padded with zero bytes if there is not enough bytes in {@code input} 158  * 159  * @param idx an index of the word starting from {@code 0} 160  * @param offset an offset in {@code input} array to start parsing from 161  */ 162  public static byte[] parseWord(byte[] input, int offset, int idx) { 163  return parseBytes(input, offset + 32 * idx, 32); 164  } 165  166  /** 167  * Returns the amount of nibbles that match each other from 0 ... 168  * amount will never be larger than smallest input 169  * 170  * @param a - first input 171  * @param b - second input 172  * @return Number of bytes that match 173  */ 174  public static int matchingNibbleLength(byte[] a, byte[] b) { 175  int i = 0; 176  int length = a.length < b.length ? a.length : b.length; 177  while (i < length) { 178  if (a[i] != b[i]) { 179  return i; 180  } 181  i++; 182  } 183  return i; 184  } 185  186  /** 187  * Converts a long value into a byte array. 188  * 189  * @param val - long value to convert 190  * @return <code>byte[]</code> of length 8, representing the long value 191  */ 192  public static byte[] longToBytes(long val) { 193  return ByteBuffer.allocate(8).putLong(val).array(); 194  } 195  196  /** 197  * Converts a long value into a byte array. 198  * 199  * @param val - long value to convert 200  * @return decimal value with leading byte that are zeroes striped 201  */ 202  public static byte[] longToBytesNoLeadZeroes(long val) { 203  204  // todo: improve performance by while strip numbers until (long >> 8 == 0) 205  byte[] data = ByteBuffer.allocate(8).putLong(val).array(); 206  207  return stripLeadingZeroes(data); 208  } 209  210  /** 211  * Converts int value into a byte array. 212  * 213  * @param val - int value to convert 214  * @return <code>byte[]</code> of length 4, representing the int value 215  */ 216  public static byte[] intToBytes(int val){ 217  return ByteBuffer.allocate(4).putInt(val).array(); 218  } 219  220  /** 221  * Converts a int value into a byte array. 222  * 223  * @param val - int value to convert 224  * @return value with leading byte that are zeroes striped 225  */ 226  public static byte[] intToBytesNoLeadZeroes(int val){ 227  228  if (val == 0) { 229  return EMPTY_BYTE_ARRAY; 230  } 231  232  int lenght = 0; 233  234  int tmpVal = val; 235  while (tmpVal != 0){ 236  tmpVal = tmpVal >>> 8; 237  ++lenght; 238  } 239  240  byte[] result = new byte[lenght]; 241  242  int index = result.length - 1; 243  while(val != 0){ 244  245  result[index] = (byte)(val & 0xFF); 246  val = val >>> 8; 247  index -= 1; 248  } 249  250  return result; 251  } 252  253  /** 254  * Converts a byte-array into a hex String.<br> 255  * Works similar to {@link Hex#toHexString}, but allows for {@code null}. 256  * 257  * @param data - byte-array to convert to a hex-string 258  * @return hex representation of the data.<br> 259  * Returns an empty String if the input is <code>null</code> 260  * 261  * @see Hex#toHexString 262  */ 263  @Nonnull 264  public static String toHexStringOrEmpty(@Nullable byte[] data) { 265  return data == null ? "" : toHexString(data); 266  } 267  268  /** 269  * Converts a byte-array into a hex String.<br> 270  * Works similar to {@link Hex#toHexString}. {@code data} cannot be {@code null}. 271  * 272  * @param data - byte-array to convert to a hex-string 273  * @return hex representation of the data.<br> 274  * @throws NullPointerException if {@code data} is {@code null} 275  * 276  * @see Hex#toHexString 277  */ 278  @Nonnull 279  public static String toHexString(@Nonnull byte[] data) { 280  return Hex.toHexString(Objects.requireNonNull(data)); 281  } 282  283  /** 284  * Converts a byte-array into a hex String.<br> 285  * Works similar to {@link Hex#toHexString}. {@code data} cannot be {@code null}. 286  * 287  * @param data - byte-array to convert to a hex-string 288  * @param off - initial offset of the subarray 289  * @param length - length of the subarray 290  * @return hex representation of the data.<br> 291  * @throws NullPointerException if {@code data} is {@code null} 292  * 293  * @see Hex#toHexString 294  */ 295  @Nonnull 296  public static String toHexString(@Nonnull byte[] data, int off, int length) { 297  return Hex.toHexString(Objects.requireNonNull(data), off, length); 298  } 299  300  /** 301  * Calculate packet length 302  * 303  * @param msg byte[] 304  * @return byte-array with 4 elements 305  */ 306  public static byte[] calcPacketLength(byte[] msg) { 307  int msgLen = msg.length; 308  return new byte[]{ 309  (byte) ((msgLen >> 24) & 0xFF), 310  (byte) ((msgLen >> 16) & 0xFF), 311  (byte) ((msgLen >> 8) & 0xFF), 312  (byte) ((msgLen) & 0xFF)}; 313  } 314  315  /** 316  * Cast hex encoded value from byte[] to int 317  * 318  * Limited to Integer.MAX_VALUE: 2^32-1 (4 bytes) 319  * 320  * @param b array contains the values 321  * @return unsigned positive int value. 322  */ 323  public static int byteArrayToInt(byte[] b) { 324  if (b == null || b.length == 0) { 325  return 0; 326  } 327  return new BigInteger(1, b).intValue(); 328  } 329  330  /** 331  * Cast from byte[] to long 332  * Limited to Long.MAX_VALUE: 2^63-1 (8 bytes) 333  * Will throw IlegalArgumentException if you pass 334  * a byte array with more than 8 bytes. 335  * 336  * @param b array contains the values 337  * @return unsigned positive long value. 338  */ 339  public static long byteArrayToLong(byte[] b) { 340  if (b == null || b.length == 0) { 341  return 0; 342  } 343  // avoids overflows in the result 344  if (b.length > 8) { 345  throw new IllegalArgumentException("byte array can't have more than 8 bytes if it is to be cast to long"); 346  } 347  long result = 0; 348  for (int i = 0; i < b.length; i++) { 349  result <<= 8; 350  result |= (b[i] & 0xFF); 351  } 352  return result; 353  } 354  355  356  /** 357  * Turn nibbles to a pretty looking output string 358  * 359  * Example. [ 1, 2, 3, 4, 5 ] becomes '\x11\x23\x45' 360  * 361  * @param nibbles - getting byte of data [ 04 ] and turning 362  * it to a '\x04' representation 363  * @return pretty string of nibbles 364  */ 365  public static String nibblesToPrettyString(byte[] nibbles) { 366  StringBuilder builder = new StringBuilder(); 367  for (byte nibble : nibbles) { 368  final String nibbleString = oneByteToHexString(nibble); 369  builder.append("\\x").append(nibbleString); 370  } 371  return builder.toString(); 372  } 373  374  public static String oneByteToHexString(byte value) { 375  String retVal = Integer.toString(value & 0xFF, 16); 376  if (retVal.length() == 1) { 377  retVal = "0" + retVal; 378  } 379  return retVal; 380  } 381  382  /** 383  * Calculate the number of bytes need 384  * to encode the number 385  * 386  * @param val - number 387  * @return number of min bytes used to encode the number 388  */ 389  public static int numBytes(String val) { 390  return new BigInteger(val).bitLength() / 8 + 1; 391  } 392  393  public static int firstNonZeroByte(byte[] data) { 394  for (int i = 0; i < data.length; ++i) { 395  if (data[i] != 0) { 396  return i; 397  } 398  } 399  return -1; 400  } 401  402  public static byte[] stripLeadingZeroes(byte[] data) { 403  return stripLeadingZeroes(data, ZERO_BYTE_ARRAY); 404  } 405  406  public static byte[] stripLeadingZeroes(byte[] data, byte[] valueForZero) { 407  if (data == null) { 408  return null; 409  } 410  411  final int firstNonZero = firstNonZeroByte(data); 412  switch (firstNonZero) { 413  case -1: 414  return valueForZero; 415  416  case 0: 417  return data; 418  419  default: 420  byte[] result = new byte[data.length - firstNonZero]; 421  System.arraycopy(data, firstNonZero, result, 0, data.length - firstNonZero); 422  423  return result; 424  } 425  } 426  427  /** 428  * increment byte array as a number until max is reached 429  * 430  * @param bytes byte[] 431  * @return boolean 432  */ 433  public static boolean increment(byte[] bytes) { 434  final int startIndex = 0; 435  int i; 436  for (i = bytes.length - 1; i >= startIndex; i--) { 437  bytes[i]++; 438  if (bytes[i] != 0) { 439  break; 440  } 441  } 442  // we return false when all bytes are 0 again 443  return (i >= startIndex || bytes[startIndex] != 0); 444  } 445  446  /** 447  * Utility function to copy a byte array into a new byte array with given size. 448  * If the src length is smaller than the given size, the result will be left-padded 449  * with zeros. 450  * 451  * @param value - a BigInteger with a maximum value of 2^256-1 452  * @return Byte array of given size with a copy of the <code>src</code> 453  */ 454  public static byte[] copyToArray(BigInteger value) { 455  byte[] src = ByteUtil.bigIntegerToBytes(value); 456  457  if (Arrays.equals(src, EMPTY_BYTE_ARRAY)) { 458  throw new NullPointerException(); 459  } 460  461  byte[] dest = ByteBuffer.allocate(32).array(); 462  System.arraycopy(src, 0, dest, dest.length - src.length, src.length); 463  return dest; 464  } 465  466  public static ByteArrayWrapper wrap(byte[] data) { 467  return new ByteArrayWrapper(data); 468  } 469  470  public static byte[] setBit(byte[] data, int pos, int val) { 471  472  if ((data.length * 8) - 1 < pos) { 473  throw new Error("outside byte array limit, pos: " + pos); 474  } 475  476  int posByte = data.length - 1 - (pos) / 8; 477  int posBit = (pos) % 8; 478  byte setter = (byte) (1 << (posBit)); 479  byte toBeSet = data[posByte]; 480  byte result; 481  if (val == 1) { 482  result = (byte) (toBeSet | setter); 483  } else { 484  result = (byte) (toBeSet & ~setter); 485  } 486  487  data[posByte] = result; 488  return data; 489  } 490  491  public static int getBit(byte[] data, int pos) { 492  493  if ((data.length * 8) - 1 < pos) { 494  throw new Error("outside byte array limit, pos: " + pos); 495  } 496  497  int posByte = data.length - 1 - pos / 8; 498  int posBit = pos % 8; 499  byte dataByte = data[posByte]; 500  return Math.min(1, (dataByte & 0xff & (1 << (posBit)))); 501  } 502  503  public static byte[] and(byte[] b1, byte[] b2) { 504  if (b1.length != b2.length) { 505  throw new RuntimeException("Array sizes differ"); 506  } 507  byte[] ret = new byte[b1.length]; 508  for (int i = 0; i < ret.length; i++) { 509  ret[i] = (byte) (b1[i] & b2[i]); 510  } 511  return ret; 512  } 513  514  public static byte[] or(byte[] b1, byte[] b2) { 515  if (b1.length != b2.length) { 516  throw new RuntimeException("Array sizes differ"); 517  } 518  byte[] ret = new byte[b1.length]; 519  for (int i = 0; i < ret.length; i++) { 520  ret[i] = (byte) (b1[i] | b2[i]); 521  } 522  return ret; 523  } 524  525  @java.lang.SuppressWarnings("squid:S3034") 526  public static byte[] shiftLeft(byte[] byteArray, int shiftBitCount) { 527  // Code taken from the Apache 2 licensed library 528  // https://github.com/patrickfav/bytes-java/blob/master/src/main/java/at/favre/lib/bytes/Util.java 529  final int shiftMod = shiftBitCount % 8; 530  final byte carryMask = (byte) ((1 << shiftMod) - 1); 531  final int offsetBytes = (shiftBitCount / 8); 532  533  int sourceIndex; 534  for (int i = 0; i < byteArray.length; i++) { 535  sourceIndex = i + offsetBytes; 536  if (sourceIndex >= byteArray.length) { 537  byteArray[i] = 0; 538  } else { 539  byte src = byteArray[sourceIndex]; 540  byte dst = (byte) (src << shiftMod); 541  if (sourceIndex + 1 < byteArray.length) { 542  dst |= byteArray[sourceIndex + 1] >>> (8 - shiftMod) & carryMask; 543  } 544  byteArray[i] = dst; 545  } 546  } 547  return byteArray; 548  } 549  550  @java.lang.SuppressWarnings("squid:S3034") 551  public static byte[] shiftRight(byte[] byteArray, int shiftBitCount) { 552  // Code taken from the Apache 2 licensed library 553  // https://github.com/patrickfav/bytes-java/blob/master/src/main/java/at/favre/lib/bytes/Util.java 554  final int shiftMod = shiftBitCount % 8; 555  final byte carryMask = (byte) (0xFF << (8 - shiftMod)); 556  final int offsetBytes = (shiftBitCount / 8); 557  558  int sourceIndex; 559  for (int i = byteArray.length - 1; i >= 0; i--) { 560  sourceIndex = i - offsetBytes; 561  if (sourceIndex < 0) { 562  byteArray[i] = 0; 563  } else { 564  byte src = byteArray[sourceIndex]; 565  byte dst = (byte) ((0xff & src) >>> shiftMod); 566  if (sourceIndex - 1 >= 0) { 567  dst |= byteArray[sourceIndex - 1] << (8 - shiftMod) & carryMask; 568  } 569  byteArray[i] = dst; 570  } 571  } 572  return byteArray; 573  } 574  575  /** 576  * @param arrays - arrays to merge 577  * @return - merged array 578  */ 579  public static byte[] merge(byte[]... arrays) { 580  int count = 0; 581  for (byte[] array: arrays) { 582  count += array.length; 583  } 584  585  // Create new array and copy all array contents 586  byte[] mergedArray = new byte[count]; 587  int start = 0; 588  for (byte[] array: arrays) { 589  System.arraycopy(array, 0, mergedArray, start, array.length); 590  start += array.length; 591  } 592  return mergedArray; 593  } 594  595  public static boolean isSingleZero(byte[] array){ 596  return (array.length == 1 && array[0] == 0); 597  } 598  599  public static boolean isAllZeroes(byte[] array) { 600  for (byte b : array) { 601  if (b != 0) { 602  return false; 603  } 604  } 605  606  return true; 607  } 608  609  public static <T> Set<T> difference(Set<T> setA, Set<T> setB){ 610  611  Set<T> temp = new HashSet<>(setA); 612  temp.removeAll(setB); 613  return temp; 614  } 615  616  public static int length(byte[]... bytes) { 617  int result = 0; 618  for (byte[] array : bytes) { 619  result += (array == null) ? 0 : array.length; 620  } 621  return result; 622  } 623  624  public static short bigEndianToShort(byte[] bs) { 625  return bigEndianToShort(bs, 0); 626  } 627  628  public static short bigEndianToShort(byte[] bs, int off) { 629  int n = bs[off] << 8; 630  ++off; 631  n |= bs[off] & 0xFF; 632  return (short) n; 633  } 634  635  public static byte[] shortToBytes(short n) { 636  return ByteBuffer.allocate(2).putShort(n).array(); 637  } 638  639  /** 640  * Returns a number of zero bits preceding the highest-order ("leftmost") one-bit 641  * interpreting input array as a big-endian integer value 642  */ 643  public static int numberOfLeadingZeros(byte[] bytes) { 644  645  int i = firstNonZeroByte(bytes); 646  647  if (i == -1) { 648  return bytes.length * 8; 649  } else { 650  int byteLeadingZeros = Integer.numberOfLeadingZeros((int)bytes[i] & 0xff) - 24; 651  return i * 8 + byteLeadingZeros; 652  } 653  } 654  655  /** 656  * Returns a copy of original padded to the left with zeroes, 657  * or original if {@code original.length >= newLength} 658  */ 659  public static byte[] leftPadBytes(@Nonnull byte[] original, int newLength) { 660  // the result array is larger than the modulus length, 661  // but this should never happen. 662  if (original.length >= newLength) { 663  return original; 664  } 665  666  // otherwise adjust result to the same length as the modulus has 667  byte[] copy = new byte[newLength]; 668  System.arraycopy(original, 0, copy, newLength - original.length, original.length); 669  return copy; 670  } 671  672  public static boolean fastEquals(byte[] left, byte[] right) { 673  return FastByteComparisons.compareTo( 674  left, 0, left.length, 675  right, 0, right.length) == 0; 676  } 677 }