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 }