diff options
author | Elliott Hughes <enh@google.com> | 2010-04-19 14:29:52 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2010-04-19 14:29:52 -0700 |
commit | 0fa251a6abd62d73a1a3d1ca74ee0bfc55050d90 (patch) | |
tree | 36e2045690a22472db680f3663d2290f12501b3a | |
parent | 95b613e08fe901506977b0e5860184f0baf09a6f (diff) | |
download | libcore-0fa251a6abd62d73a1a3d1ca74ee0bfc55050d90.zip libcore-0fa251a6abd62d73a1a3d1ca74ee0bfc55050d90.tar.gz libcore-0fa251a6abd62d73a1a3d1ca74ee0bfc55050d90.tar.bz2 |
Fix several BigInteger failures.
From Java 7 on, BigInteger also accepts a leading "+" in its string
constructors.
BigInteger has always claimed to accept non-ASCII digits, but our
implementation never has.
BigInteger.isProbablePrime is defined to return true for certainty <= 0,
but OpenSSL (on which we're based) takes the opposite stance.
Change-Id: I00bfc591a4d583460f71b7eec3de91bf6b03cd87
-rw-r--r-- | luni/src/test/java/java/math/BigIntegerTest.java | 7 | ||||
-rw-r--r-- | math/src/main/java/java/math/BigInt.java | 61 | ||||
-rw-r--r-- | math/src/main/java/java/math/BigInteger.java | 11 |
3 files changed, 55 insertions, 24 deletions
diff --git a/luni/src/test/java/java/math/BigIntegerTest.java b/luni/src/test/java/java/math/BigIntegerTest.java index 831ed62..ec63e20 100644 --- a/luni/src/test/java/java/math/BigIntegerTest.java +++ b/luni/src/test/java/java/math/BigIntegerTest.java @@ -30,13 +30,10 @@ public class BigIntegerTest extends junit.framework.TestCase { new BigInteger("1a", 16); new BigInteger("-1", 10); new BigInteger("-1a", 16); + // This is allowed from Java 7 on. + new BigInteger("+1"); // Now check the invalid cases... try { - new BigInteger("+1"); // no positive sign allowed. - fail(); - } catch (NumberFormatException expected) { - } - try { new BigInteger("-a"); // no digits from other bases. fail(); } catch (NumberFormatException expected) { diff --git a/math/src/main/java/java/math/BigInt.java b/math/src/main/java/java/math/BigInt.java index d1bd29b..76ed1ff 100644 --- a/math/src/main/java/java/math/BigInt.java +++ b/math/src/main/java/java/math/BigInt.java @@ -151,49 +151,80 @@ class BigInt Check(NativeBN.putULongInt(this.bignum, val, neg)); } - public void putDecString(String str) { - checkString(str, 10); + public void putDecString(String original) { + String s = checkString(original, 10); this.makeValid(); - int usedLen = NativeBN.BN_dec2bn(this.bignum, str); + int usedLen = NativeBN.BN_dec2bn(this.bignum, s); Check((usedLen > 0)); - if (usedLen < str.length()) { - throw new NumberFormatException(str); + if (usedLen < s.length()) { + throw new NumberFormatException(original); } } - public void putHexString(String str) { - checkString(str, 16); + public void putHexString(String original) { + String s = checkString(original, 16); this.makeValid(); - int usedLen = NativeBN.BN_hex2bn(this.bignum, str); + int usedLen = NativeBN.BN_hex2bn(this.bignum, s); Check((usedLen > 0)); - if (usedLen < str.length()) { - throw new NumberFormatException(str); + if (usedLen < s.length()) { + throw new NumberFormatException(original); } } /** + * Returns a string suitable for passing to OpenSSL. * Throws if 's' doesn't match Java's rules for valid BigInteger strings. * BN_dec2bn and BN_hex2bn do very little checking, so we need to manually * ensure we comply with Java's rules. * http://code.google.com/p/android/issues/detail?id=7036 */ - public void checkString(String s, int radix) { + public String checkString(String s, int radix) { if (s == null) { throw new NullPointerException(); } - // A valid big integer consists of an optional '-' followed by + // A valid big integer consists of an optional '-' or '+' followed by // one or more digit characters appropriate to the given radix, // and no other characters. - final int charCount = s.length(); - int i = (charCount > 0 && s.charAt(0) == '-') ? 1 : 0; + int charCount = s.length(); + int i = 0; + if (charCount > 0) { + char ch = s.charAt(0); + if (ch == '+') { + // Java supports leading +, but OpenSSL doesn't, so we need to strip it. + s = s.substring(1); + --charCount; + } else if (ch == '-') { + ++i; + } + } if (charCount - i == 0) { throw new NumberFormatException(s); } + boolean nonAscii = false; for (; i < charCount; ++i) { - if (Character.digit(s.charAt(i), radix) == -1) { + char ch = s.charAt(i); + if (Character.digit(ch, radix) == -1) { throw new NumberFormatException(s); } + if (ch < '0' || ch > '9') { + nonAscii = true; + } + } + return nonAscii ? toAscii(s) : s; + } + + // Java supports non-ASCII digits, but OpenSSL doesn't. + private static String toAscii(String s) { + int length = s.length(); + StringBuilder result = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + char ch = s.charAt(i); + if (ch != '-') { + ch = (char) ('0' + Character.digit(ch, 10)); + } + result.append(ch); } + return result.toString(); } public void putBigEndian(byte[] a, boolean neg) { diff --git a/math/src/main/java/java/math/BigInteger.java b/math/src/main/java/java/math/BigInteger.java index 1fbeb48..adef534 100644 --- a/math/src/main/java/java/math/BigInteger.java +++ b/math/src/main/java/java/math/BigInteger.java @@ -271,8 +271,9 @@ public class BigInteger extends Number implements Comparable<BigInteger>, /** * Constructs a new {@code BigInteger} instance from the string - * representation. The string representation consists of an optional minus + * representation. The string representation consists of an optional plus or minus * sign followed by a non-empty sequence of decimal digits. + * Digits are interpreted as if by {@code Character.digit(char, 10)}. * * @param val * string representation of the new {@code BigInteger}. @@ -291,10 +292,9 @@ public class BigInteger extends Number implements Comparable<BigInteger>, /** * Constructs a new {@code BigInteger} instance from the string - * representation. The string representation consists of an optional minus + * representation. The string representation consists of an optional plus or minus * sign followed by a non-empty sequence of digits in the specified radix. - * For the conversion the method {@code Character.digit(char, radix)} is - * used. + * Digits are interpreted as if by {@code Character.digit(char, radix)}. * * @param val * string representation of the new {@code BigInteger}. @@ -1215,6 +1215,9 @@ public class BigInteger extends Number implements Comparable<BigInteger>, * otherwise. */ public boolean isProbablePrime(int certainty) { + if (certainty <= 0) { + return true; + } validate1("isProbablePrime", this); return bigInt.isPrime(certainty, null, null); } |