148 lines
4.6 KiB
Java
148 lines
4.6 KiB
Java
/*
|
|
* Copyright 2015 Christian Basler
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package ch.dissem.bitmessage.utils;
|
|
|
|
/**
|
|
* A helper class for working with byte arrays interpreted as unsigned big endian integers.
|
|
* This is one part due to the fact that Java doesn't support unsigned numbers, and another
|
|
* part so we don't have to convert between byte arrays and numbers in time critical
|
|
* situations.
|
|
*/
|
|
public class Bytes {
|
|
public static void inc(byte[] nonce) {
|
|
for (int i = nonce.length - 1; i >= 0; i--) {
|
|
nonce[i]++;
|
|
if (nonce[i] != 0) break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Increases nonce by value, which is used as an unsigned byte value.
|
|
*
|
|
* @param nonce an unsigned number
|
|
* @param value to be added to nonce
|
|
*/
|
|
public static void inc(byte[] nonce, byte value) {
|
|
int i = nonce.length - 1;
|
|
nonce[i] += value;
|
|
if (value > 0 && (nonce[i] < 0 || nonce[i] >= value))
|
|
return;
|
|
if (value < 0 && (nonce[i] < 0 && nonce[i] >= value))
|
|
return;
|
|
|
|
for (i = i - 1; i >= 0; i--) {
|
|
nonce[i]++;
|
|
if (nonce[i] != 0) break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return true if a < b.
|
|
*/
|
|
public static boolean lt(byte[] a, byte[] b) {
|
|
byte[] max = (a.length > b.length ? a : b);
|
|
byte[] min = (max == a ? b : a);
|
|
int diff = max.length - min.length;
|
|
|
|
for (int i = 0; i < max.length - min.length; i++) {
|
|
if (max[i] != 0) return a != max;
|
|
}
|
|
for (int i = diff; i < max.length; i++) {
|
|
if (max[i] != min[i - diff]) {
|
|
return lt(max[i], min[i - diff]) == (a == max);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @return true if a < b, where the first [size] bytes are used as the numbers to check.
|
|
*/
|
|
public static boolean lt(byte[] a, byte[] b, int size) {
|
|
for (int i = 0; i < size; i++) {
|
|
if (a[i] != b[i]) {
|
|
return lt(a[i], b[i]);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static boolean lt(byte a, byte b) {
|
|
if (a < 0) return b < 0 && a < b;
|
|
if (b < 0) return a >= 0 || a < b;
|
|
return a < b;
|
|
// This would be easier to understand, but is (slightly) slower:
|
|
// return (a & 0xff) < (b & 0xff);
|
|
}
|
|
|
|
/**
|
|
* @return a new byte array of length, left-padded with '0'.
|
|
*/
|
|
public static byte[] expand(byte[] source, int size) {
|
|
byte[] result = new byte[size];
|
|
System.arraycopy(source, 0, result, size - source.length, source.length);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @return a new byte array containing the first <em>size</em> bytes of the given array.
|
|
*/
|
|
public static byte[] truncate(byte[] source, int size) {
|
|
byte[] result = new byte[size];
|
|
System.arraycopy(source, 0, result, 0, size);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @return the byte array that hex represents. This is meant for test use and should be rewritten if used in
|
|
* production code.
|
|
*/
|
|
public static byte[] fromHex(String hex) {
|
|
if (hex.length() % 2 != 0) throw new IllegalArgumentException("expected even number of characters");
|
|
byte[] result = new byte[hex.length() / 2];
|
|
for (int i = 0; i < result.length; i++) {
|
|
result[i] = (byte) (hexValue(hex.charAt(i * 2)) * 16);
|
|
result[i] += hexValue(hex.charAt(i * 2 + 1));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static int hexValue(char c) {
|
|
if (c >= '0' && c <= '9') {
|
|
return c - '0';
|
|
}
|
|
if (c >= 'a' && c <= 'f') {
|
|
return 10 + c - 'a';
|
|
}
|
|
if (c >= 'A' && c <= 'F') {
|
|
return 10 + c - 'A';
|
|
}
|
|
throw new IllegalArgumentException("'" + c + "' is not a valid hex value");
|
|
}
|
|
|
|
/**
|
|
* @return the number of leading '0' of a byte array.
|
|
*/
|
|
public static int numberOfLeadingZeros(byte[] bytes) {
|
|
int i;
|
|
for (i = 0; i < bytes.length; i++) {
|
|
if (bytes[i] != 0) return i;
|
|
}
|
|
return i;
|
|
}
|
|
}
|