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

Class Method, % Line, %
FastByteComparisons 75% (3/4) 75% (3/4)
FastByteComparisons$Comparer
FastByteComparisons$LexicographicalComparerHolder 66.7% (2/3) 60% (6/10)
FastByteComparisons$LexicographicalComparerHolder$PureJavaComparer 100% (3/3) 100% (12/12)
Total 80% (8/10) 80.8% (21/26)


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  * Licensed to the Apache Software Foundation (ASF) under one 21  * or more contributor license agreements. See the NOTICE file 22  * distributed with this work for additional information 23  * regarding copyright ownership. The ASF licenses this file 24  * to you under the Apache License, Version 2.0 (the 25  * "License"); you may not use this file except in compliance 26  * with the License. You may obtain a copy of the License at 27  * 28  * http://www.apache.org/licenses/LICENSE-2.0 29  * 30  * Unless required by applicable law or agreed to in writing, software 31  * distributed under the License is distributed on an "AS IS" BASIS, 32  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 33  * See the License for the specific language governing permissions and 34  * limitations under the License. 35  */ 36 package org.ethereum.util; 37  38 import com.google.common.primitives.UnsignedBytes; 39  40  41 /** 42  * Utility code to do optimized byte-array comparison. 43  * This is borrowed and slightly modified from Guava's {@link UnsignedBytes} 44  * class to be able to compare arrays that start at non-zero offsets. 45  */ 46 @SuppressWarnings("restriction") 47 public class FastByteComparisons { 48  49  public static boolean equalBytes(byte[] b1, byte[] b2) { 50  return b1.length == b2.length && compareTo(b1, 0, b1.length, b2, 0, b2.length) == 0; 51  } 52  /** 53  * Lexicographically compare two byte arrays. 54  * 55  * @param b1 buffer1 56  * @param s1 offset1 57  * @param l1 length1 58  * @param b2 buffer2 59  * @param s2 offset2 60  * @param l2 length2 61  * @return int 62  */ 63  public static int compareTo(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { 64  return LexicographicalComparerHolder.BEST_COMPARER.compareTo( 65  b1, s1, l1, b2, s2, l2); 66  } 67  68  private interface Comparer<T> { 69  int compareTo(T buffer1, int offset1, int length1, 70  T buffer2, int offset2, int length2); 71  } 72  73  private static Comparer<byte[]> lexicographicalComparerJavaImpl() { 74  return LexicographicalComparerHolder.PureJavaComparer.INSTANCE; 75  } 76  77  78  /** 79  * 80  * <p>Uses reflection to gracefully fall back to the Java implementation if 81  * {@code Unsafe} isn't available. 82  */ 83  private static class LexicographicalComparerHolder { 84  static final String UNSAFE_COMPARER_NAME = 85  LexicographicalComparerHolder.class.getName() + "$UnsafeComparer"; 86  87  static final Comparer<byte[]> BEST_COMPARER = getBestComparer(); 88  89  /** 90  * Returns the Unsafe-using Comparer, or falls back to the pure-Java 91  * implementation if unable to do so. 92  */ 93  static Comparer<byte[]> getBestComparer() { 94  try { 95  Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME); 96  97  // yes, UnsafeComparer does implement Comparer<byte[]> 98  @SuppressWarnings("unchecked") 99  Comparer<byte[]> comparer = 100  (Comparer<byte[]>) theClass.getEnumConstants()[0]; 101  return comparer; 102  } catch (Throwable t) { // ensure we really catch *everything* 103  return lexicographicalComparerJavaImpl(); 104  } 105  } 106  107  private enum PureJavaComparer implements Comparer<byte[]> { 108  INSTANCE; 109  110  @Override 111  public int compareTo(byte[] buffer1, int offset1, int length1, 112  byte[] buffer2, int offset2, int length2) { 113  // Short circuit equalBytes case 114  if (buffer1 == buffer2 && 115  offset1 == offset2 && 116  length1 == length2) { 117  return 0; 118  } 119  int end1 = offset1 + length1; 120  int end2 = offset2 + length2; 121  for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) { 122  int a = (buffer1[i] & 0xff); 123  int b = (buffer2[j] & 0xff); 124  if (a != b) { 125  return a - b; 126  } 127  } 128  return length1 - length2; 129  } 130  } 131  132  133  } 134 }