Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 40 additions & 29 deletions src/java.base/share/classes/java/text/DigitList.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;

import jdk.internal.access.SharedSecrets;
import jdk.internal.math.FloatingDecimal;
import jdk.internal.util.ArraysSupport;

Expand Down Expand Up @@ -103,9 +106,9 @@ final class DigitList implements Cloneable {
*/
public int decimalAt = 0;
public int count = 0;
public char[] digits = new char[MAX_COUNT];
public byte[] digits = new byte[MAX_COUNT];

private char[] data;
private byte[] data;
private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
private boolean isNegative = false;

Expand Down Expand Up @@ -154,11 +157,11 @@ public void clear () {
*/
public void append(char digit) {
if (count == digits.length) {
char[] data = new char[ArraysSupport.newLength(count, 1, count)];
byte[] data = new byte[ArraysSupport.newLength(count, 1, count)];
System.arraycopy(digits, 0, data, 0, count);
digits = data;
}
digits[count++] = digit;
digits[count++] = (byte) digit;
}

/**
Expand Down Expand Up @@ -188,7 +191,7 @@ public long getLong() {
// Parse as unsigned to handle Long.MIN_VALUE, which is the one NEGATIVE value
// we represent. If we tried to just pass the digits off to parseLong,
// we'd get a parse failure.
long v = Long.parseUnsignedLong(new String(digits, 0, count));
long v = Long.parseUnsignedLong(new String(digits, 0, count, StandardCharsets.ISO_8859_1));
if (v < 0) {
if (v == Long.MIN_VALUE) {
return Long.MIN_VALUE;
Expand All @@ -209,15 +212,20 @@ public long getLong() {
* unlike BigDecimal("").
*/
public BigDecimal getBigDecimal() {
int count = this.count;
if (count == 0) {
return BigDecimal.valueOf(0, -decimalAt);
}

if (decimalAt == count) {
return new BigDecimal(digits, 0, count);
} else {
return new BigDecimal(digits, 0, count).scaleByPowerOfTen(decimalAt - count);
}
char[] chars = new char[count];
SharedSecrets.getJavaLangAccess()
.inflateBytesToChars(digits, 0, chars, 0, count);
BigDecimal value = new BigDecimal(chars, 0, count);
if (decimalAt == count) {
return value;
} else {
return value.scaleByPowerOfTen(decimalAt - count);
}
}

/**
Expand Down Expand Up @@ -256,7 +264,7 @@ boolean fitsIntoLong(boolean isPositive, boolean ignoreNegativeZero) {
// The number will overflow if it is larger than 9223372036854775807
// or smaller than -9223372036854775808.
for (int i=0; i<count; ++i) {
char dig = digits[i], max = LONG_MIN_REP[i];
byte dig = digits[i], max = LONG_MIN_REP[i];
if (dig > max) return false;
if (dig < max) return true;
}
Expand Down Expand Up @@ -317,9 +325,10 @@ void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoin
boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp();
boolean valueExactAsDecimal = fdConverter.decimalDigitsExact();
assert !fdConverter.isExceptional();
String digitsString = fdConverter.toJavaFormatString();

set(isNegative, digitsString,
byte[] chars = getDataChars(26);
int len = fdConverter.getChars(chars);
set(isNegative, chars, len,
hasBeenRoundedUp, valueExactAsDecimal,
maximumDigits, fixedPoint);
}
Expand All @@ -331,14 +340,11 @@ void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoin
* @param valueExactAsDecimal whether or not collected digits provide
* an exact decimal representation of the value.
*/
private void set(boolean isNegative, String s,
private void set(boolean isNegative, byte[] source, int len,
boolean roundedUp, boolean valueExactAsDecimal,
int maximumDigits, boolean fixedPoint) {

this.isNegative = isNegative;
int len = s.length();
char[] source = getDataChars(len);
s.getChars(0, len, source, 0);

decimalAt = -1;
count = 0;
Expand All @@ -349,7 +355,7 @@ private void set(boolean isNegative, String s,
boolean nonZeroDigitSeen = false;

for (int i = 0; i < len; ) {
char c = source[i++];
byte c = source[i++];
if (c == '.') {
decimalAt = count;
} else if (c == 'e' || c == 'E') {
Expand Down Expand Up @@ -633,7 +639,7 @@ void set(boolean isNegative, long source, int maximumDigits) {
int left = MAX_COUNT;
int right;
while (source > 0) {
digits[--left] = (char)('0' + (source % 10));
digits[--left] = (byte)('0' + (source % 10));
source /= 10;
}
decimalAt = MAX_COUNT - left;
Expand Down Expand Up @@ -661,11 +667,15 @@ void set(boolean isNegative, long source, int maximumDigits) {
* @param fixedPoint If true, then maximumDigits is the maximum
* fractional digits to be converted. If false, total digits.
*/
@SuppressWarnings("deprecation")
void set(boolean isNegative, BigDecimal source, int maximumDigits, boolean fixedPoint) {
String s = source.toString();
extendDigits(s.length());

set(isNegative, s,
int len = s.length();
byte[] chars = getDataChars(len);
s.getBytes(0, len, chars, 0);
set(isNegative, chars, len,
false, true,
maximumDigits, fixedPoint);
}
Expand All @@ -678,12 +688,13 @@ void set(boolean isNegative, BigDecimal source, int maximumDigits, boolean fixed
* If maximumDigits is lower than the number of significant digits
* in source, the representation will be rounded. Ignored if <= 0.
*/
@SuppressWarnings("deprecation")
void set(boolean isNegative, BigInteger source, int maximumDigits) {
this.isNegative = isNegative;
String s = source.toString();
int len = s.length();
extendDigits(len);
s.getChars(0, len, digits, 0);
s.getBytes(0, len, digits, 0);

decimalAt = len;
int right = len - 1;
Expand Down Expand Up @@ -734,7 +745,7 @@ public int hashCode() {
public Object clone() {
try {
DigitList other = (DigitList) super.clone();
char[] newDigits = new char[digits.length];
byte[] newDigits = new byte[digits.length];
System.arraycopy(digits, 0, newDigits, 0, digits.length);
other.digits = newDigits;

Expand All @@ -749,8 +760,8 @@ public Object clone() {
}
}

private static int parseInt(char[] str, int offset, int strLen) {
char c;
private static int parseInt(byte[] str, int offset, int strLen) {
byte c;
boolean positive = true;
if ((c = str[offset]) == '-') {
positive = false;
Expand All @@ -772,25 +783,25 @@ private static int parseInt(char[] str, int offset, int strLen) {
}

// The digit part of -9223372036854775808L
private static final char[] LONG_MIN_REP = "9223372036854775808".toCharArray();
private static final byte[] LONG_MIN_REP = "9223372036854775808".getBytes(StandardCharsets.ISO_8859_1);

public String toString() {
if (isZero()) {
return "0";
}

return "0." + new String(digits, 0, count) + "x10^" + decimalAt;
return "0." + new String(digits, 0, count, StandardCharsets.ISO_8859_1) + "x10^" + decimalAt;
}

private void extendDigits(int len) {
if (len > digits.length) {
digits = new char[len];
digits = new byte[len];
}
}

private char[] getDataChars(int length) {
private byte[] getDataChars(int length) {
if (data == null || data.length < length) {
data = new char[length];
data = new byte[length];
}
return data;
}
Expand Down
Loading