mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-19 18:00:39 +01:00
Preconditions: replace Guava checkArgument()
and checkState()
in base
with own implementation
This has the added benefit of exception messages only being evaluated on demand.
This commit is contained in:
parent
9ab5653fcf
commit
dca54e0621
@ -22,7 +22,7 @@ import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* <p>Implementation of the Bech32 encoding.</p>
|
||||
@ -127,16 +127,16 @@ public class Bech32 {
|
||||
}
|
||||
|
||||
/** Encode a Bech32 string. */
|
||||
public static String encode(Encoding encoding, String hrp, final byte[] values) {
|
||||
checkArgument(hrp.length() >= 1, "Human-readable part is too short");
|
||||
checkArgument(hrp.length() <= 83, "Human-readable part is too long");
|
||||
hrp = hrp.toLowerCase(Locale.ROOT);
|
||||
byte[] checksum = createChecksum(encoding, hrp, values);
|
||||
public static String encode(Encoding encoding, final String hrp, final byte[] values) {
|
||||
checkArgument(hrp.length() >= 1, () -> "human-readable part is too short: " + hrp.length());
|
||||
checkArgument(hrp.length() <= 83, () -> "human-readable part is too long: " + hrp.length());
|
||||
String lcHrp = hrp.toLowerCase(Locale.ROOT);
|
||||
byte[] checksum = createChecksum(encoding, lcHrp, values);
|
||||
byte[] combined = new byte[values.length + checksum.length];
|
||||
System.arraycopy(values, 0, combined, 0, values.length);
|
||||
System.arraycopy(checksum, 0, combined, values.length, checksum.length);
|
||||
StringBuilder sb = new StringBuilder(hrp.length() + 1 + combined.length);
|
||||
sb.append(hrp);
|
||||
StringBuilder sb = new StringBuilder(lcHrp.length() + 1 + combined.length);
|
||||
sb.append(lcHrp);
|
||||
sb.append('1');
|
||||
for (byte b : combined) {
|
||||
sb.append(CHARSET.charAt(b));
|
||||
|
@ -20,7 +20,7 @@ import org.bitcoinj.base.utils.MonetaryFormat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* Represents a monetary Bitcoin value. This class is immutable and should be treated as a Java <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/doc-files/ValueBased.html#Value-basedClasses">Value-based class</a>.
|
||||
@ -129,9 +129,9 @@ public final class Coin implements Monetary, Comparable<Coin> {
|
||||
* @return {@code Coin} object containing value in satoshis
|
||||
*/
|
||||
public static Coin valueOf(final int coins, final int cents) {
|
||||
checkArgument(cents < 100);
|
||||
checkArgument(cents >= 0);
|
||||
checkArgument(coins >= 0);
|
||||
checkArgument(cents < 100, () -> "cents nust be below 100: " + cents);
|
||||
checkArgument(cents >= 0, () -> "cents cannot be negative: " + cents);
|
||||
checkArgument(coins >= 0, () -> "coins cannot be negative: " + cents);
|
||||
final Coin coin = COIN.multiply(coins).add(CENT.multiply(cents));
|
||||
return coin;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* A {@code Sha256Hash} wraps a {@code byte[]} so that {@link #equals} and {@link #hashCode} work correctly, allowing it to be used as a key in a
|
||||
@ -42,7 +42,8 @@ public class Sha256Hash implements Comparable<Sha256Hash> {
|
||||
private final byte[] bytes;
|
||||
|
||||
private Sha256Hash(byte[] rawHashBytes) {
|
||||
checkArgument(rawHashBytes.length == LENGTH);
|
||||
checkArgument(rawHashBytes.length == LENGTH, () ->
|
||||
"length must be " + LENGTH + ": " + rawHashBytes.length);
|
||||
this.bytes = rawHashBytes;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Comparator;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* Utility methods for bit, byte, and integer manipulation and conversion. Most of these were moved here
|
||||
@ -71,13 +71,13 @@ public class ByteUtils {
|
||||
* @return numBytes byte long array.
|
||||
*/
|
||||
public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) {
|
||||
checkArgument(b.signum() >= 0, "b must be positive or zero");
|
||||
checkArgument(numBytes > 0, "numBytes must be positive");
|
||||
checkArgument(b.signum() >= 0, () -> "b must be positive or zero: " + b);
|
||||
checkArgument(numBytes > 0, () -> "numBytes must be positive: " + numBytes);
|
||||
byte[] src = b.toByteArray();
|
||||
byte[] dest = new byte[numBytes];
|
||||
boolean isFirstByteOnlyForSign = src[0] == 0;
|
||||
int length = isFirstByteOnlyForSign ? src.length - 1 : src.length;
|
||||
checkArgument(length <= numBytes, "The given number does not fit in " + numBytes);
|
||||
checkArgument(length <= numBytes, () -> "The given number does not fit in " + numBytes);
|
||||
int srcPos = isFirstByteOnlyForSign ? 1 : 0;
|
||||
int destPos = numBytes - length;
|
||||
System.arraycopy(src, srcPos, dest, destPos, length);
|
||||
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* 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 org.bitcoinj.base.internal;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Preconditions {
|
||||
/**
|
||||
* Ensures the truth of an expression involving one or more parameters to the calling method.
|
||||
* @param expression a boolean expression
|
||||
* @throws IllegalArgumentException if {@code expression} is false
|
||||
*/
|
||||
public static void checkArgument(boolean expression) {
|
||||
if (!expression)
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the truth of an expression involving one or more parameters to the calling method.
|
||||
* @param expression a boolean expression
|
||||
* @param messageSupplier supplier of the detail message to be used in the event that a IllegalArgumentException is thrown
|
||||
* @throws IllegalArgumentException if {@code expression} is false
|
||||
*/
|
||||
public static void checkArgument(boolean expression, Supplier<String> messageSupplier) {
|
||||
if (!expression)
|
||||
throw new IllegalArgumentException(messageSupplier.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the truth of an expression involving the state of the calling instance, but not
|
||||
* involving any parameters to the calling method.
|
||||
* @param expression a boolean expression
|
||||
* @throws IllegalStateException if {@code expression} is false
|
||||
*/
|
||||
public static void checkState(boolean expression) {
|
||||
if (!expression)
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the truth of an expression involving the state of the calling instance, but not
|
||||
* involving any parameters to the calling method.
|
||||
* @param expression a boolean expression
|
||||
* @param messageSupplier supplier of the detail message to be used in the event that a IllegalStateException is thrown
|
||||
* @throws IllegalStateException if {@code expression} is false
|
||||
*/
|
||||
public static void checkState(boolean expression, Supplier<String> messageSupplier) {
|
||||
if (!expression)
|
||||
throw new IllegalStateException(messageSupplier.get());
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import org.bitcoinj.base.Monetary;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* Represents a monetary fiat value. It was decided to not fold this into {@link Coin} because of type
|
||||
@ -105,12 +105,14 @@ public final class Fiat implements Monetary, Comparable<Fiat> {
|
||||
}
|
||||
|
||||
public Fiat add(final Fiat value) {
|
||||
checkArgument(value.currencyCode.equals(currencyCode));
|
||||
checkArgument(value.currencyCode.equals(currencyCode), () ->
|
||||
"values to add must be of same currency: " + value.currencyCode + " vs " + currencyCode);
|
||||
return new Fiat(currencyCode, Math.addExact(this.value, value.value));
|
||||
}
|
||||
|
||||
public Fiat subtract(final Fiat value) {
|
||||
checkArgument(value.currencyCode.equals(currencyCode));
|
||||
checkArgument(value.currencyCode.equals(currencyCode), () ->
|
||||
"values to substract must be of same currency: " + value.currencyCode + " vs " + currencyCode);
|
||||
return new Fiat(currencyCode, Math.subtractExact(this.value, value.value));
|
||||
}
|
||||
|
||||
@ -127,7 +129,8 @@ public final class Fiat implements Monetary, Comparable<Fiat> {
|
||||
}
|
||||
|
||||
public long divide(final Fiat divisor) {
|
||||
checkArgument(divisor.currencyCode.equals(currencyCode));
|
||||
checkArgument(divisor.currencyCode.equals(currencyCode), () ->
|
||||
"values to divide must be of same currency: " + divisor.currencyCode + " vs " + currencyCode);
|
||||
return this.value / divisor.value;
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,10 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.math.LongMath.checkedPow;
|
||||
import static com.google.common.math.LongMath.divide;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkState;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -92,8 +92,10 @@ public final class MonetaryFormat {
|
||||
* Set character to prefix negative values.
|
||||
*/
|
||||
public MonetaryFormat negativeSign(char negativeSign) {
|
||||
checkArgument(!Character.isDigit(negativeSign));
|
||||
checkArgument(negativeSign > 0);
|
||||
checkArgument(!Character.isDigit(negativeSign), () ->
|
||||
"negativeSign can't be digit: " + negativeSign);
|
||||
checkArgument(negativeSign > 0, () ->
|
||||
"negativeSign must be positive: " + negativeSign);
|
||||
if (negativeSign == this.negativeSign)
|
||||
return this;
|
||||
else
|
||||
@ -106,7 +108,8 @@ public final class MonetaryFormat {
|
||||
* sign will always be interpreted as if the positive sign was used.
|
||||
*/
|
||||
public MonetaryFormat positiveSign(char positiveSign) {
|
||||
checkArgument(!Character.isDigit(positiveSign));
|
||||
checkArgument(!Character.isDigit(positiveSign), () ->
|
||||
"positiveSign can't be digit: " + positiveSign);
|
||||
if (positiveSign == this.positiveSign)
|
||||
return this;
|
||||
else
|
||||
@ -130,8 +133,10 @@ public final class MonetaryFormat {
|
||||
* used either.
|
||||
*/
|
||||
public MonetaryFormat decimalMark(char decimalMark) {
|
||||
checkArgument(!Character.isDigit(decimalMark));
|
||||
checkArgument(decimalMark > 0);
|
||||
checkArgument(!Character.isDigit(decimalMark), () ->
|
||||
"decimalMark can't be digit: " + decimalMark);
|
||||
checkArgument(decimalMark > 0, () ->
|
||||
"decimalMark must be positive: " + decimalMark);
|
||||
if (decimalMark == this.decimalMark)
|
||||
return this;
|
||||
else
|
||||
@ -194,7 +199,8 @@ public final class MonetaryFormat {
|
||||
* number of repetitions
|
||||
*/
|
||||
public MonetaryFormat repeatOptionalDecimals(int decimals, int repetitions) {
|
||||
checkArgument(repetitions >= 0);
|
||||
checkArgument(repetitions >= 0, () ->
|
||||
"repetitions cannot be negative: " + repetitions);
|
||||
List<Integer> decimalGroups = new ArrayList<>(repetitions);
|
||||
for (int i = 0; i < repetitions; i++)
|
||||
decimalGroups.add(decimals);
|
||||
@ -245,7 +251,8 @@ public final class MonetaryFormat {
|
||||
* currency code
|
||||
*/
|
||||
public MonetaryFormat code(int codeShift, String code) {
|
||||
checkArgument(codeShift >= 0);
|
||||
checkArgument(codeShift >= 0, () ->
|
||||
"codeShift cannot be negative: " + codeShift);
|
||||
final String[] codes = null == this.codes
|
||||
? new String[MAX_DECIMALS]
|
||||
: Arrays.copyOf(this.codes, this.codes.length);
|
||||
@ -259,8 +266,10 @@ public final class MonetaryFormat {
|
||||
* Separator between currency code and formatted value. This configuration is not relevant for parsing.
|
||||
*/
|
||||
public MonetaryFormat codeSeparator(char codeSeparator) {
|
||||
checkArgument(!Character.isDigit(codeSeparator));
|
||||
checkArgument(codeSeparator > 0);
|
||||
checkArgument(!Character.isDigit(codeSeparator), () ->
|
||||
"codeSeparator can't be digit: " + codeSeparator);
|
||||
checkArgument(codeSeparator > 0, () ->
|
||||
"codeSeparator must be positive: " + codeSeparator);
|
||||
if (codeSeparator == this.codeSeparator)
|
||||
return this;
|
||||
else
|
||||
@ -354,13 +363,14 @@ public final class MonetaryFormat {
|
||||
*/
|
||||
public CharSequence format(Monetary monetary) {
|
||||
// preparation
|
||||
int maxDecimals = minDecimals;
|
||||
int max = minDecimals;
|
||||
if (decimalGroups != null)
|
||||
for (int group : decimalGroups)
|
||||
maxDecimals += group;
|
||||
max += group;
|
||||
int smallestUnitExponent = monetary.smallestUnitExponent();
|
||||
checkState(maxDecimals <= smallestUnitExponent,
|
||||
"The maximum possible number of decimals (%s) cannot exceed %s.", maxDecimals, smallestUnitExponent);
|
||||
int maxDecimals = max;
|
||||
checkState(maxDecimals <= smallestUnitExponent, () ->
|
||||
"maxDecimals cannot exceed " + smallestUnitExponent + ": " + maxDecimals);
|
||||
|
||||
// rounding
|
||||
long satoshis = Math.abs(monetary.getValue());
|
||||
@ -440,7 +450,8 @@ public final class MonetaryFormat {
|
||||
}
|
||||
|
||||
private long parseValue(String str, int smallestUnitExponent) {
|
||||
checkState(DECIMALS_PADDING.length() >= smallestUnitExponent);
|
||||
checkState(DECIMALS_PADDING.length() >= smallestUnitExponent, () ->
|
||||
"smallestUnitExponent can't be higher than " + DECIMALS_PADDING.length() + ": " + smallestUnitExponent);
|
||||
if (str.isEmpty())
|
||||
throw new NumberFormatException("empty string");
|
||||
char first = str.charAt(0);
|
||||
|
Loading…
Reference in New Issue
Block a user