8342650: Move getChars to DecimalDigits
Reviewed-by: liach
This commit is contained in:
parent
ca69a53b76
commit
e1d684c645
@ -830,9 +830,9 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
|
|||||||
int spaceNeeded = count + DecimalDigits.stringSize(i);
|
int spaceNeeded = count + DecimalDigits.stringSize(i);
|
||||||
ensureCapacityInternal(spaceNeeded);
|
ensureCapacityInternal(spaceNeeded);
|
||||||
if (isLatin1()) {
|
if (isLatin1()) {
|
||||||
StringLatin1.getChars(i, spaceNeeded, value);
|
DecimalDigits.getCharsLatin1(i, spaceNeeded, value);
|
||||||
} else {
|
} else {
|
||||||
StringUTF16.getChars(i, count, spaceNeeded, value);
|
DecimalDigits.getCharsUTF16(i, spaceNeeded, value);
|
||||||
}
|
}
|
||||||
this.count = spaceNeeded;
|
this.count = spaceNeeded;
|
||||||
return this;
|
return this;
|
||||||
@ -855,9 +855,9 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
|
|||||||
int spaceNeeded = count + DecimalDigits.stringSize(l);
|
int spaceNeeded = count + DecimalDigits.stringSize(l);
|
||||||
ensureCapacityInternal(spaceNeeded);
|
ensureCapacityInternal(spaceNeeded);
|
||||||
if (isLatin1()) {
|
if (isLatin1()) {
|
||||||
StringLatin1.getChars(l, spaceNeeded, value);
|
DecimalDigits.getCharsLatin1(l, spaceNeeded, value);
|
||||||
} else {
|
} else {
|
||||||
StringUTF16.getChars(l, count, spaceNeeded, value);
|
DecimalDigits.getCharsUTF16(l, spaceNeeded, value);
|
||||||
}
|
}
|
||||||
this.count = spaceNeeded;
|
this.count = spaceNeeded;
|
||||||
return this;
|
return this;
|
||||||
|
@ -432,11 +432,11 @@ public final class Integer extends Number
|
|||||||
int size = DecimalDigits.stringSize(i);
|
int size = DecimalDigits.stringSize(i);
|
||||||
if (COMPACT_STRINGS) {
|
if (COMPACT_STRINGS) {
|
||||||
byte[] buf = new byte[size];
|
byte[] buf = new byte[size];
|
||||||
StringLatin1.getChars(i, size, buf);
|
DecimalDigits.getCharsLatin1(i, size, buf);
|
||||||
return new String(buf, LATIN1);
|
return new String(buf, LATIN1);
|
||||||
} else {
|
} else {
|
||||||
byte[] buf = new byte[size * 2];
|
byte[] buf = new byte[size * 2];
|
||||||
StringUTF16.getChars(i, size, buf);
|
DecimalDigits.getCharsUTF16(i, size, buf);
|
||||||
return new String(buf, UTF16);
|
return new String(buf, UTF16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,11 +462,11 @@ public final class Long extends Number
|
|||||||
int size = DecimalDigits.stringSize(i);
|
int size = DecimalDigits.stringSize(i);
|
||||||
if (COMPACT_STRINGS) {
|
if (COMPACT_STRINGS) {
|
||||||
byte[] buf = new byte[size];
|
byte[] buf = new byte[size];
|
||||||
StringLatin1.getChars(i, size, buf);
|
DecimalDigits.getCharsLatin1(i, size, buf);
|
||||||
return new String(buf, LATIN1);
|
return new String(buf, LATIN1);
|
||||||
} else {
|
} else {
|
||||||
byte[] buf = new byte[size * 2];
|
byte[] buf = new byte[size * 2];
|
||||||
StringUTF16.getChars(i, size, buf);
|
DecimalDigits.getCharsUTF16(i, size, buf);
|
||||||
return new String(buf, UTF16);
|
return new String(buf, UTF16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,12 +298,12 @@ final class StringConcatHelper {
|
|||||||
static long prepend(long indexCoder, byte[] buf, int value, String prefix) {
|
static long prepend(long indexCoder, byte[] buf, int value, String prefix) {
|
||||||
int index = (int)indexCoder;
|
int index = (int)indexCoder;
|
||||||
if (indexCoder < UTF16) {
|
if (indexCoder < UTF16) {
|
||||||
index = StringLatin1.getChars(value, index, buf);
|
index = DecimalDigits.getCharsLatin1(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.LATIN1);
|
prefix.getBytes(buf, index, String.LATIN1);
|
||||||
return index;
|
return index;
|
||||||
} else {
|
} else {
|
||||||
index = StringUTF16.getChars(value, index, buf);
|
index = DecimalDigits.getCharsUTF16(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.UTF16);
|
prefix.getBytes(buf, index, String.UTF16);
|
||||||
return index | UTF16;
|
return index | UTF16;
|
||||||
@ -324,12 +324,12 @@ final class StringConcatHelper {
|
|||||||
static long prepend(long indexCoder, byte[] buf, long value, String prefix) {
|
static long prepend(long indexCoder, byte[] buf, long value, String prefix) {
|
||||||
int index = (int)indexCoder;
|
int index = (int)indexCoder;
|
||||||
if (indexCoder < UTF16) {
|
if (indexCoder < UTF16) {
|
||||||
index = StringLatin1.getChars(value, index, buf);
|
index = DecimalDigits.getCharsLatin1(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.LATIN1);
|
prefix.getBytes(buf, index, String.LATIN1);
|
||||||
return index;
|
return index;
|
||||||
} else {
|
} else {
|
||||||
index = StringUTF16.getChars(value, index, buf);
|
index = DecimalDigits.getCharsUTF16(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.UTF16);
|
prefix.getBytes(buf, index, String.UTF16);
|
||||||
return index | UTF16;
|
return index | UTF16;
|
||||||
@ -682,11 +682,11 @@ final class StringConcatHelper {
|
|||||||
*/
|
*/
|
||||||
static int prepend(int index, byte coder, byte[] buf, int value, String prefix) {
|
static int prepend(int index, byte coder, byte[] buf, int value, String prefix) {
|
||||||
if (coder == String.LATIN1) {
|
if (coder == String.LATIN1) {
|
||||||
index = StringLatin1.getChars(value, index, buf);
|
index = DecimalDigits.getCharsLatin1(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.LATIN1);
|
prefix.getBytes(buf, index, String.LATIN1);
|
||||||
} else {
|
} else {
|
||||||
index = StringUTF16.getChars(value, index, buf);
|
index = DecimalDigits.getCharsUTF16(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.UTF16);
|
prefix.getBytes(buf, index, String.UTF16);
|
||||||
}
|
}
|
||||||
@ -706,11 +706,11 @@ final class StringConcatHelper {
|
|||||||
*/
|
*/
|
||||||
static int prepend(int index, byte coder, byte[] buf, long value, String prefix) {
|
static int prepend(int index, byte coder, byte[] buf, long value, String prefix) {
|
||||||
if (coder == String.LATIN1) {
|
if (coder == String.LATIN1) {
|
||||||
index = StringLatin1.getChars(value, index, buf);
|
index = DecimalDigits.getCharsLatin1(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.LATIN1);
|
prefix.getBytes(buf, index, String.LATIN1);
|
||||||
} else {
|
} else {
|
||||||
index = StringUTF16.getChars(value, index, buf);
|
index = DecimalDigits.getCharsUTF16(value, index, buf);
|
||||||
index -= prefix.length();
|
index -= prefix.length();
|
||||||
prefix.getBytes(buf, index, String.UTF16);
|
prefix.getBytes(buf, index, String.UTF16);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ import java.util.stream.Stream;
|
|||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.util.ArraysSupport;
|
import jdk.internal.util.ArraysSupport;
|
||||||
import jdk.internal.util.DecimalDigits;
|
|
||||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||||
|
|
||||||
import static java.lang.String.LATIN1;
|
import static java.lang.String.LATIN1;
|
||||||
@ -86,120 +85,6 @@ final class StringLatin1 {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Places characters representing the integer i into the
|
|
||||||
* character array buf. The characters are placed into
|
|
||||||
* the buffer backwards starting with the least significant
|
|
||||||
* digit at the specified index (exclusive), and working
|
|
||||||
* backwards from there.
|
|
||||||
*
|
|
||||||
* @implNote This method converts positive inputs into negative
|
|
||||||
* values, to cover the Integer.MIN_VALUE case. Converting otherwise
|
|
||||||
* (negative to positive) will expose -Integer.MIN_VALUE that overflows
|
|
||||||
* integer.
|
|
||||||
*
|
|
||||||
* @param i value to convert
|
|
||||||
* @param index next index, after the least significant digit
|
|
||||||
* @param buf target buffer, Latin1-encoded
|
|
||||||
* @return index of the most significant digit or minus sign, if present
|
|
||||||
*/
|
|
||||||
static int getChars(int i, int index, byte[] buf) {
|
|
||||||
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
|
||||||
int q;
|
|
||||||
int charPos = index;
|
|
||||||
|
|
||||||
boolean negative = i < 0;
|
|
||||||
if (!negative) {
|
|
||||||
i = -i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate two digits per iteration
|
|
||||||
while (i <= -100) {
|
|
||||||
q = i / 100;
|
|
||||||
charPos -= 2;
|
|
||||||
writeDigitPair(buf, charPos, (q * 100) - i);
|
|
||||||
i = q;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know there are at most two digits left at this point.
|
|
||||||
if (i < -9) {
|
|
||||||
charPos -= 2;
|
|
||||||
writeDigitPair(buf, charPos, -i);
|
|
||||||
} else {
|
|
||||||
buf[--charPos] = (byte)('0' - i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative) {
|
|
||||||
buf[--charPos] = (byte)'-';
|
|
||||||
}
|
|
||||||
return charPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Places characters representing the long i into the
|
|
||||||
* character array buf. The characters are placed into
|
|
||||||
* the buffer backwards starting with the least significant
|
|
||||||
* digit at the specified index (exclusive), and working
|
|
||||||
* backwards from there.
|
|
||||||
*
|
|
||||||
* @implNote This method converts positive inputs into negative
|
|
||||||
* values, to cover the Long.MIN_VALUE case. Converting otherwise
|
|
||||||
* (negative to positive) will expose -Long.MIN_VALUE that overflows
|
|
||||||
* long.
|
|
||||||
*
|
|
||||||
* @param i value to convert
|
|
||||||
* @param index next index, after the least significant digit
|
|
||||||
* @param buf target buffer, Latin1-encoded
|
|
||||||
* @return index of the most significant digit or minus sign, if present
|
|
||||||
*/
|
|
||||||
static int getChars(long i, int index, byte[] buf) {
|
|
||||||
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
|
||||||
long q;
|
|
||||||
int charPos = index;
|
|
||||||
|
|
||||||
boolean negative = (i < 0);
|
|
||||||
if (!negative) {
|
|
||||||
i = -i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 2 digits/iteration using longs until quotient fits into an int
|
|
||||||
while (i <= Integer.MIN_VALUE) {
|
|
||||||
q = i / 100;
|
|
||||||
charPos -= 2;
|
|
||||||
writeDigitPair(buf, charPos, (int)((q * 100) - i));
|
|
||||||
i = q;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 2 digits/iteration using ints
|
|
||||||
int q2;
|
|
||||||
int i2 = (int)i;
|
|
||||||
while (i2 <= -100) {
|
|
||||||
q2 = i2 / 100;
|
|
||||||
charPos -= 2;
|
|
||||||
writeDigitPair(buf, charPos, (q2 * 100) - i2);
|
|
||||||
i2 = q2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know there are at most two digits left at this point.
|
|
||||||
if (i2 < -9) {
|
|
||||||
charPos -= 2;
|
|
||||||
writeDigitPair(buf, charPos, -i2);
|
|
||||||
} else {
|
|
||||||
buf[--charPos] = (byte)('0' - i2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative) {
|
|
||||||
buf[--charPos] = (byte)'-';
|
|
||||||
}
|
|
||||||
return charPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void writeDigitPair(byte[] buf, int charPos, int value) {
|
|
||||||
short pair = DecimalDigits.digitPair(value);
|
|
||||||
buf[charPos] = (byte)(pair);
|
|
||||||
buf[charPos + 1] = (byte)(pair >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) {
|
public static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) {
|
||||||
inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
|
inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ import java.util.stream.StreamSupport;
|
|||||||
|
|
||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.util.ArraysSupport;
|
import jdk.internal.util.ArraysSupport;
|
||||||
import jdk.internal.util.DecimalDigits;
|
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||||
|
|
||||||
@ -1513,20 +1512,6 @@ final class StringUTF16 {
|
|||||||
return codePointCount(val, beginIndex, endIndex, true /* checked */);
|
return codePointCount(val, beginIndex, endIndex, true /* checked */);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getChars(int i, int begin, int end, byte[] value) {
|
|
||||||
checkBoundsBeginEnd(begin, end, value);
|
|
||||||
int pos = getChars(i, end, value);
|
|
||||||
assert begin == pos;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getChars(long l, int begin, int end, byte[] value) {
|
|
||||||
checkBoundsBeginEnd(begin, end, value);
|
|
||||||
int pos = getChars(l, end, value);
|
|
||||||
assert begin == pos;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean contentEquals(byte[] v1, byte[] v2, int len) {
|
public static boolean contentEquals(byte[] v1, byte[] v2, int len) {
|
||||||
checkBoundsOffCount(0, len, v2);
|
checkBoundsOffCount(0, len, v2);
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
@ -1662,109 +1647,6 @@ final class StringUTF16 {
|
|||||||
|
|
||||||
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
|
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
|
||||||
|
|
||||||
// Used by trusted callers. Assumes all necessary bounds checks have
|
|
||||||
// been done by the caller.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a variant of {@link StringLatin1#getChars(int, int, byte[])}, but for
|
|
||||||
* UTF-16 coder.
|
|
||||||
*
|
|
||||||
* @param i value to convert
|
|
||||||
* @param index next index, after the least significant digit
|
|
||||||
* @param buf target buffer, UTF16-coded.
|
|
||||||
* @return index of the most significant digit or minus sign, if present
|
|
||||||
*/
|
|
||||||
static int getChars(int i, int index, byte[] buf) {
|
|
||||||
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
|
||||||
int q, r;
|
|
||||||
int charPos = index;
|
|
||||||
|
|
||||||
boolean negative = (i < 0);
|
|
||||||
if (!negative) {
|
|
||||||
i = -i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 2 digits/iteration using ints
|
|
||||||
while (i <= -100) {
|
|
||||||
q = i / 100;
|
|
||||||
r = (q * 100) - i;
|
|
||||||
i = q;
|
|
||||||
charPos -= 2;
|
|
||||||
putPair(buf, charPos, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know there are at most two digits left at this point.
|
|
||||||
if (i < -9) {
|
|
||||||
charPos -= 2;
|
|
||||||
putPair(buf, charPos, -i);
|
|
||||||
} else {
|
|
||||||
putChar(buf, --charPos, '0' - i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative) {
|
|
||||||
putChar(buf, --charPos, '-');
|
|
||||||
}
|
|
||||||
return charPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a variant of {@link StringLatin1#getChars(long, int, byte[])}, but for
|
|
||||||
* UTF-16 coder.
|
|
||||||
*
|
|
||||||
* @param i value to convert
|
|
||||||
* @param index next index, after the least significant digit
|
|
||||||
* @param buf target buffer, UTF16-coded.
|
|
||||||
* @return index of the most significant digit or minus sign, if present
|
|
||||||
*/
|
|
||||||
static int getChars(long i, int index, byte[] buf) {
|
|
||||||
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
|
||||||
long q;
|
|
||||||
int charPos = index;
|
|
||||||
|
|
||||||
boolean negative = (i < 0);
|
|
||||||
if (!negative) {
|
|
||||||
i = -i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 2 digits/iteration using longs until quotient fits into an int
|
|
||||||
while (i <= Integer.MIN_VALUE) {
|
|
||||||
q = i / 100;
|
|
||||||
charPos -= 2;
|
|
||||||
putPair(buf, charPos, (int)((q * 100) - i));
|
|
||||||
i = q;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 2 digits/iteration using ints
|
|
||||||
int q2;
|
|
||||||
int i2 = (int)i;
|
|
||||||
while (i2 <= -100) {
|
|
||||||
q2 = i2 / 100;
|
|
||||||
charPos -= 2;
|
|
||||||
putPair(buf, charPos, (q2 * 100) - i2);
|
|
||||||
i2 = q2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know there are at most two digits left at this point.
|
|
||||||
if (i2 < -9) {
|
|
||||||
charPos -= 2;
|
|
||||||
putPair(buf, charPos, -i2);
|
|
||||||
} else {
|
|
||||||
putChar(buf, --charPos, '0' - i2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative) {
|
|
||||||
putChar(buf, --charPos, '-');
|
|
||||||
}
|
|
||||||
return charPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void putPair(byte[] buf, int charPos, int v) {
|
|
||||||
int packed = (int) DecimalDigits.digitPair(v);
|
|
||||||
putChar(buf, charPos, packed & 0xFF);
|
|
||||||
putChar(buf, charPos + 1, packed >> 8);
|
|
||||||
}
|
|
||||||
// End of trusted methods.
|
|
||||||
|
|
||||||
public static void checkIndex(int off, byte[] val) {
|
public static void checkIndex(int off, byte[] val) {
|
||||||
String.checkIndex(off, length(val));
|
String.checkIndex(off, length(val));
|
||||||
}
|
}
|
||||||
|
@ -2648,14 +2648,6 @@ public final class System {
|
|||||||
return str.coder();
|
return str.coder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCharsLatin1(long i, int index, byte[] buf) {
|
|
||||||
return StringLatin1.getChars(i, index, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCharsUTF16(long i, int index, byte[] buf) {
|
|
||||||
return StringUTF16.getChars(i, index, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String join(String prefix, String suffix, String delimiter, String[] elements, int size) {
|
public String join(String prefix, String suffix, String delimiter, String[] elements, int size) {
|
||||||
return String.join(prefix, suffix, delimiter, elements, size);
|
return String.join(prefix, suffix, delimiter, elements, size);
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,15 @@ import java.io.InvalidObjectException;
|
|||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectStreamException;
|
import java.io.ObjectStreamException;
|
||||||
import java.io.StreamCorruptedException;
|
import java.io.StreamCorruptedException;
|
||||||
|
import java.nio.charset.CharacterCodingException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import jdk.internal.access.JavaLangAccess;
|
||||||
|
import jdk.internal.access.SharedSecrets;
|
||||||
|
import jdk.internal.util.DecimalDigits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable, arbitrary-precision signed decimal numbers. A {@code
|
* Immutable, arbitrary-precision signed decimal numbers. A {@code
|
||||||
* BigDecimal} consists of an arbitrary precision integer
|
* BigDecimal} consists of an arbitrary precision integer
|
||||||
@ -328,6 +334,8 @@ import java.util.Objects;
|
|||||||
* @since 1.1
|
* @since 1.1
|
||||||
*/
|
*/
|
||||||
public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||||
|
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let l = log_2(10).
|
* Let l = log_2(10).
|
||||||
* Then, L < l < L + ulp(L) / 2, that is, L = roundTiesToEven(l).
|
* Then, L < l < L + ulp(L) / 2, that is, L = roundTiesToEven(l).
|
||||||
@ -4164,103 +4172,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
|||||||
return BigDecimal.valueOf(1, this.scale(), 1);
|
return BigDecimal.valueOf(1, this.scale(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private class to build a string representation for BigDecimal object. The
|
|
||||||
// StringBuilder field acts as a buffer to hold the temporary representation
|
|
||||||
// of BigDecimal. The cmpCharArray holds all the characters for the compact
|
|
||||||
// representation of BigDecimal (except for '-' sign' if it is negative) if
|
|
||||||
// its intCompact field is not INFLATED.
|
|
||||||
static class StringBuilderHelper {
|
|
||||||
final StringBuilder sb; // Placeholder for BigDecimal string
|
|
||||||
final char[] cmpCharArray; // character array to place the intCompact
|
|
||||||
|
|
||||||
StringBuilderHelper() {
|
|
||||||
sb = new StringBuilder(32);
|
|
||||||
// All non negative longs can be made to fit into 19 character array.
|
|
||||||
cmpCharArray = new char[19];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accessors.
|
|
||||||
StringBuilder getStringBuilder() {
|
|
||||||
sb.setLength(0);
|
|
||||||
return sb;
|
|
||||||
}
|
|
||||||
|
|
||||||
char[] getCompactCharArray() {
|
|
||||||
return cmpCharArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Places characters representing the intCompact in {@code long} into
|
|
||||||
* cmpCharArray and returns the offset to the array where the
|
|
||||||
* representation starts.
|
|
||||||
*
|
|
||||||
* @param intCompact the number to put into the cmpCharArray.
|
|
||||||
* @return offset to the array where the representation starts.
|
|
||||||
* Note: intCompact must be greater or equal to zero.
|
|
||||||
*/
|
|
||||||
int putIntCompact(long intCompact) {
|
|
||||||
assert intCompact >= 0;
|
|
||||||
|
|
||||||
long q;
|
|
||||||
int r;
|
|
||||||
// since we start from the least significant digit, charPos points to
|
|
||||||
// the last character in cmpCharArray.
|
|
||||||
int charPos = cmpCharArray.length;
|
|
||||||
|
|
||||||
// Get 2 digits/iteration using longs until quotient fits into an int
|
|
||||||
while (intCompact > Integer.MAX_VALUE) {
|
|
||||||
q = intCompact / 100;
|
|
||||||
r = (int)(intCompact - q * 100);
|
|
||||||
intCompact = q;
|
|
||||||
cmpCharArray[--charPos] = DIGIT_ONES[r];
|
|
||||||
cmpCharArray[--charPos] = DIGIT_TENS[r];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 2 digits/iteration using ints when i2 >= 100
|
|
||||||
int q2;
|
|
||||||
int i2 = (int)intCompact;
|
|
||||||
while (i2 >= 100) {
|
|
||||||
q2 = i2 / 100;
|
|
||||||
r = i2 - q2 * 100;
|
|
||||||
i2 = q2;
|
|
||||||
cmpCharArray[--charPos] = DIGIT_ONES[r];
|
|
||||||
cmpCharArray[--charPos] = DIGIT_TENS[r];
|
|
||||||
}
|
|
||||||
|
|
||||||
cmpCharArray[--charPos] = DIGIT_ONES[i2];
|
|
||||||
if (i2 >= 10)
|
|
||||||
cmpCharArray[--charPos] = DIGIT_TENS[i2];
|
|
||||||
|
|
||||||
return charPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static final char[] DIGIT_TENS = {
|
|
||||||
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
|
||||||
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
|
|
||||||
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
|
|
||||||
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
|
|
||||||
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
|
|
||||||
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
|
|
||||||
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
|
|
||||||
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
|
|
||||||
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
|
|
||||||
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
|
|
||||||
};
|
|
||||||
|
|
||||||
static final char[] DIGIT_ONES = {
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lay out this {@code BigDecimal} into a {@code char[]} array.
|
* Lay out this {@code BigDecimal} into a {@code char[]} array.
|
||||||
* The Java 1.2 equivalent to this was called {@code getValueString}.
|
* The Java 1.2 equivalent to this was called {@code getValueString}.
|
||||||
@ -4271,6 +4182,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
|||||||
* {@code BigDecimal}
|
* {@code BigDecimal}
|
||||||
*/
|
*/
|
||||||
private String layoutChars(boolean sci) {
|
private String layoutChars(boolean sci) {
|
||||||
|
long intCompact = this.intCompact;
|
||||||
|
int scale = this.scale;
|
||||||
if (scale == 0) // zero scale is trivial
|
if (scale == 0) // zero scale is trivial
|
||||||
return (intCompact != INFLATED) ?
|
return (intCompact != INFLATED) ?
|
||||||
Long.toString(intCompact):
|
Long.toString(intCompact):
|
||||||
@ -4280,18 +4193,24 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
|||||||
// currency fast path
|
// currency fast path
|
||||||
int lowInt = (int)intCompact % 100;
|
int lowInt = (int)intCompact % 100;
|
||||||
int highInt = (int)intCompact / 100;
|
int highInt = (int)intCompact / 100;
|
||||||
return (Integer.toString(highInt) + '.' +
|
int highIntSize = DecimalDigits.stringSize(highInt);
|
||||||
StringBuilderHelper.DIGIT_TENS[lowInt] +
|
byte[] buf = new byte[highIntSize + 3];
|
||||||
StringBuilderHelper.DIGIT_ONES[lowInt]) ;
|
DecimalDigits.putPairLatin1(buf, highIntSize + 1, lowInt);
|
||||||
|
buf[highIntSize] = '.';
|
||||||
|
DecimalDigits.getCharsLatin1(highInt, highIntSize, buf);
|
||||||
|
try {
|
||||||
|
return JLA.newStringNoRepl(buf, StandardCharsets.ISO_8859_1);
|
||||||
|
} catch (CharacterCodingException cce) {
|
||||||
|
throw new AssertionError(cce);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilderHelper sbHelper = new StringBuilderHelper();
|
|
||||||
char[] coeff;
|
char[] coeff;
|
||||||
int offset; // offset is the starting index for coeff array
|
int offset; // offset is the starting index for coeff array
|
||||||
// Get the significand as an absolute value
|
// Get the significand as an absolute value
|
||||||
if (intCompact != INFLATED) {
|
if (intCompact != INFLATED) {
|
||||||
offset = sbHelper.putIntCompact(Math.abs(intCompact));
|
coeff = new char[19];
|
||||||
coeff = sbHelper.getCompactCharArray();
|
offset = DecimalDigits.getChars(Math.abs(intCompact), coeff.length, coeff);
|
||||||
} else {
|
} else {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
coeff = intVal.abs().toString().toCharArray();
|
coeff = intVal.abs().toString().toCharArray();
|
||||||
@ -4301,7 +4220,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
|||||||
// If E-notation is needed, length will be: +1 if negative, +1
|
// If E-notation is needed, length will be: +1 if negative, +1
|
||||||
// if '.' needed, +2 for "E+", + up to 10 for adjusted exponent.
|
// if '.' needed, +2 for "E+", + up to 10 for adjusted exponent.
|
||||||
// Otherwise it could have +1 if negative, plus leading "0.00000"
|
// Otherwise it could have +1 if negative, plus leading "0.00000"
|
||||||
StringBuilder buf = sbHelper.getStringBuilder();
|
StringBuilder buf = new StringBuilder(32);;
|
||||||
if (signum() < 0) // prefix '-' if negative
|
if (signum() < 0) // prefix '-' if negative
|
||||||
buf.append('-');
|
buf.append('-');
|
||||||
int coeffLen = coeff.length - offset;
|
int coeffLen = coeff.length - offset;
|
||||||
|
@ -487,10 +487,6 @@ public interface JavaLangAccess {
|
|||||||
*/
|
*/
|
||||||
Object classData(Class<?> c);
|
Object classData(Class<?> c);
|
||||||
|
|
||||||
int getCharsLatin1(long i, int index, byte[] buf);
|
|
||||||
|
|
||||||
int getCharsUTF16(long i, int index, byte[] buf);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link NativeLibraries} object associated with the provided class loader.
|
* Returns the {@link NativeLibraries} object associated with the provided class loader.
|
||||||
* This is used by {@link SymbolLookup#loaderLookup()}.
|
* This is used by {@link SymbolLookup#loaderLookup()}.
|
||||||
|
@ -25,14 +25,18 @@
|
|||||||
|
|
||||||
package jdk.internal.util;
|
package jdk.internal.util;
|
||||||
|
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.vm.annotation.Stable;
|
import jdk.internal.vm.annotation.Stable;
|
||||||
|
|
||||||
|
import static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Digits class for decimal digits.
|
* Digits class for decimal digits.
|
||||||
*
|
*
|
||||||
* @since 21
|
* @since 21
|
||||||
*/
|
*/
|
||||||
public final class DecimalDigits {
|
public final class DecimalDigits {
|
||||||
|
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each element of the array represents the packaging of two ascii characters based on little endian:<p>
|
* Each element of the array represents the packaging of two ascii characters based on little endian:<p>
|
||||||
@ -76,15 +80,6 @@ public final class DecimalDigits {
|
|||||||
private DecimalDigits() {
|
private DecimalDigits() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For values from 0 to 99 return a short encoding a pair of ASCII-encoded digit characters in little-endian
|
|
||||||
* @param i value to convert
|
|
||||||
* @return a short encoding a pair of ASCII-encoded digit characters
|
|
||||||
*/
|
|
||||||
public static short digitPair(int i) {
|
|
||||||
return DIGITS[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the string representation size for a given int value.
|
* Returns the string representation size for a given int value.
|
||||||
*
|
*
|
||||||
@ -136,4 +131,306 @@ public final class DecimalDigits {
|
|||||||
}
|
}
|
||||||
return 19 + d;
|
return 19 + d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Places characters representing the integer i into the
|
||||||
|
* character array buf. The characters are placed into
|
||||||
|
* the buffer backwards starting with the least significant
|
||||||
|
* digit at the specified index (exclusive), and working
|
||||||
|
* backwards from there.
|
||||||
|
*
|
||||||
|
* @implNote This method converts positive inputs into negative
|
||||||
|
* values, to cover the Integer.MIN_VALUE case. Converting otherwise
|
||||||
|
* (negative to positive) will expose -Integer.MIN_VALUE that overflows
|
||||||
|
* integer.
|
||||||
|
*
|
||||||
|
* @param i value to convert
|
||||||
|
* @param index next index, after the least significant digit
|
||||||
|
* @param buf target buffer, Latin1-encoded
|
||||||
|
* @return index of the most significant digit or minus sign, if present
|
||||||
|
*/
|
||||||
|
public static int getCharsLatin1(int i, int index, byte[] buf) {
|
||||||
|
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
||||||
|
int q;
|
||||||
|
int charPos = index;
|
||||||
|
|
||||||
|
boolean negative = i < 0;
|
||||||
|
if (!negative) {
|
||||||
|
i = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate two digits per iteration
|
||||||
|
while (i <= -100) {
|
||||||
|
q = i / 100;
|
||||||
|
charPos -= 2;
|
||||||
|
putPairLatin1(buf, charPos, (q * 100) - i);
|
||||||
|
i = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know there are at most two digits left at this point.
|
||||||
|
if (i < -9) {
|
||||||
|
charPos -= 2;
|
||||||
|
putPairLatin1(buf, charPos, -i);
|
||||||
|
} else {
|
||||||
|
putCharLatin1(buf, --charPos, '0' - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
putCharLatin1(buf, --charPos, '-');
|
||||||
|
}
|
||||||
|
return charPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Places characters representing the long i into the
|
||||||
|
* character array buf. The characters are placed into
|
||||||
|
* the buffer backwards starting with the least significant
|
||||||
|
* digit at the specified index (exclusive), and working
|
||||||
|
* backwards from there.
|
||||||
|
*
|
||||||
|
* @implNote This method converts positive inputs into negative
|
||||||
|
* values, to cover the Long.MIN_VALUE case. Converting otherwise
|
||||||
|
* (negative to positive) will expose -Long.MIN_VALUE that overflows
|
||||||
|
* long.
|
||||||
|
*
|
||||||
|
* @param i value to convert
|
||||||
|
* @param index next index, after the least significant digit
|
||||||
|
* @param buf target buffer, Latin1-encoded
|
||||||
|
* @return index of the most significant digit or minus sign, if present
|
||||||
|
*/
|
||||||
|
public static int getCharsLatin1(long i, int index, byte[] buf) {
|
||||||
|
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
||||||
|
long q;
|
||||||
|
int charPos = index;
|
||||||
|
|
||||||
|
boolean negative = (i < 0);
|
||||||
|
if (!negative) {
|
||||||
|
i = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 2 digits/iteration using longs until quotient fits into an int
|
||||||
|
while (i <= Integer.MIN_VALUE) {
|
||||||
|
q = i / 100;
|
||||||
|
charPos -= 2;
|
||||||
|
putPairLatin1(buf, charPos, (int)((q * 100) - i));
|
||||||
|
i = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 2 digits/iteration using ints
|
||||||
|
int q2;
|
||||||
|
int i2 = (int)i;
|
||||||
|
while (i2 <= -100) {
|
||||||
|
q2 = i2 / 100;
|
||||||
|
charPos -= 2;
|
||||||
|
putPairLatin1(buf, charPos, (q2 * 100) - i2);
|
||||||
|
i2 = q2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know there are at most two digits left at this point.
|
||||||
|
if (i2 < -9) {
|
||||||
|
charPos -= 2;
|
||||||
|
putPairLatin1(buf, charPos, -i2);
|
||||||
|
} else {
|
||||||
|
putCharLatin1(buf, --charPos, '0' - i2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
putCharLatin1(buf, --charPos, '-');
|
||||||
|
}
|
||||||
|
return charPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a variant of {@link DecimalDigits#getCharsLatin1(int, int, byte[])}, but for
|
||||||
|
* UTF-16 coder.
|
||||||
|
*
|
||||||
|
* @param i value to convert
|
||||||
|
* @param index next index, after the least significant digit
|
||||||
|
* @param buf target buffer, UTF16-coded.
|
||||||
|
* @return index of the most significant digit or minus sign, if present
|
||||||
|
*/
|
||||||
|
public static int getCharsUTF16(int i, int index, byte[] buf) {
|
||||||
|
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
||||||
|
int q, r;
|
||||||
|
int charPos = index;
|
||||||
|
|
||||||
|
boolean negative = (i < 0);
|
||||||
|
if (!negative) {
|
||||||
|
i = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 2 digits/iteration using ints
|
||||||
|
while (i <= -100) {
|
||||||
|
q = i / 100;
|
||||||
|
r = (q * 100) - i;
|
||||||
|
i = q;
|
||||||
|
charPos -= 2;
|
||||||
|
putPairUTF16(buf, charPos, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know there are at most two digits left at this point.
|
||||||
|
if (i < -9) {
|
||||||
|
charPos -= 2;
|
||||||
|
putPairUTF16(buf, charPos, -i);
|
||||||
|
} else {
|
||||||
|
putCharUTF16(buf, --charPos, '0' - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
putCharUTF16(buf, --charPos, '-');
|
||||||
|
}
|
||||||
|
return charPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a variant of {@link DecimalDigits#getCharsLatin1(long, int, byte[])}, but for
|
||||||
|
* UTF-16 coder.
|
||||||
|
*
|
||||||
|
* @param i value to convert
|
||||||
|
* @param index next index, after the least significant digit
|
||||||
|
* @param buf target buffer, UTF16-coded.
|
||||||
|
* @return index of the most significant digit or minus sign, if present
|
||||||
|
*/
|
||||||
|
public static int getCharsUTF16(long i, int index, byte[] buf) {
|
||||||
|
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
||||||
|
long q;
|
||||||
|
int charPos = index;
|
||||||
|
|
||||||
|
boolean negative = (i < 0);
|
||||||
|
if (!negative) {
|
||||||
|
i = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 2 digits/iteration using longs until quotient fits into an int
|
||||||
|
while (i <= Integer.MIN_VALUE) {
|
||||||
|
q = i / 100;
|
||||||
|
charPos -= 2;
|
||||||
|
putPairUTF16(buf, charPos, (int)((q * 100) - i));
|
||||||
|
i = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 2 digits/iteration using ints
|
||||||
|
int q2;
|
||||||
|
int i2 = (int)i;
|
||||||
|
while (i2 <= -100) {
|
||||||
|
q2 = i2 / 100;
|
||||||
|
charPos -= 2;
|
||||||
|
putPairUTF16(buf, charPos, (q2 * 100) - i2);
|
||||||
|
i2 = q2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know there are at most two digits left at this point.
|
||||||
|
if (i2 < -9) {
|
||||||
|
charPos -= 2;
|
||||||
|
putPairUTF16(buf, charPos, -i2);
|
||||||
|
} else {
|
||||||
|
putCharUTF16(buf, --charPos, '0' - i2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
putCharUTF16(buf, --charPos, '-');
|
||||||
|
}
|
||||||
|
return charPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a variant of {@link DecimalDigits#getCharsUTF16(long, int, byte[])}, but for
|
||||||
|
* UTF-16 coder.
|
||||||
|
*
|
||||||
|
* @param i value to convert
|
||||||
|
* @param index next index, after the least significant digit
|
||||||
|
* @param buf target buffer, UTF16-coded.
|
||||||
|
* @return index of the most significant digit or minus sign, if present
|
||||||
|
*/
|
||||||
|
public static int getChars(long i, int index, char[] buf) {
|
||||||
|
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
|
||||||
|
long q;
|
||||||
|
int charPos = index;
|
||||||
|
|
||||||
|
boolean negative = (i < 0);
|
||||||
|
if (!negative) {
|
||||||
|
i = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 2 digits/iteration using longs until quotient fits into an int
|
||||||
|
while (i <= Integer.MIN_VALUE) {
|
||||||
|
q = i / 100;
|
||||||
|
charPos -= 2;
|
||||||
|
putPair(buf, charPos, (int)((q * 100) - i));
|
||||||
|
i = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 2 digits/iteration using ints
|
||||||
|
int q2;
|
||||||
|
int i2 = (int)i;
|
||||||
|
while (i2 <= -100) {
|
||||||
|
q2 = i2 / 100;
|
||||||
|
charPos -= 2;
|
||||||
|
putPair(buf, charPos, (q2 * 100) - i2);
|
||||||
|
i2 = q2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know there are at most two digits left at this point.
|
||||||
|
if (i2 < -9) {
|
||||||
|
charPos -= 2;
|
||||||
|
putPair(buf, charPos, -i2);
|
||||||
|
} else {
|
||||||
|
buf[--charPos] = (char) ('0' - i2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
buf[--charPos] = '-';
|
||||||
|
}
|
||||||
|
return charPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the 2-chars integer into the buf as 2 decimal digit ASCII chars,
|
||||||
|
* only least significant 16 bits of {@code v} are used.
|
||||||
|
* @param buf byte buffer to copy into
|
||||||
|
* @param charPos insert point
|
||||||
|
* @param v to convert
|
||||||
|
*/
|
||||||
|
public static void putPair(char[] buf, int charPos, int v) {
|
||||||
|
int packed = DIGITS[v];
|
||||||
|
buf[charPos ] = (char) (packed & 0xFF);
|
||||||
|
buf[charPos + 1] = (char) (packed >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the 2-bytes integer into the buf as 2 decimal digit ASCII bytes,
|
||||||
|
* only least significant 16 bits of {@code v} are used.
|
||||||
|
* @param buf byte buffer to copy into
|
||||||
|
* @param charPos insert point
|
||||||
|
* @param v to convert
|
||||||
|
*/
|
||||||
|
public static void putPairLatin1(byte[] buf, int charPos, int v) {
|
||||||
|
int packed = DIGITS[v];
|
||||||
|
putCharLatin1(buf, charPos, packed & 0xFF);
|
||||||
|
putCharLatin1(buf, charPos + 1, packed >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the 2-chars integer into the buf as 2 decimal digit UTF16 bytes,
|
||||||
|
* only least significant 16 bits of {@code v} are used.
|
||||||
|
* @param buf byte buffer to copy into
|
||||||
|
* @param charPos insert point
|
||||||
|
* @param v to convert
|
||||||
|
*/
|
||||||
|
public static void putPairUTF16(byte[] buf, int charPos, int v) {
|
||||||
|
int packed = DIGITS[v];
|
||||||
|
putCharUTF16(buf, charPos, packed & 0xFF);
|
||||||
|
putCharUTF16(buf, charPos + 1, packed >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void putCharLatin1(byte[] buf, int charPos, int c) {
|
||||||
|
UNSAFE.putByte(buf, ARRAY_BYTE_BASE_OFFSET + charPos, (byte) c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void putCharUTF16(byte[] buf, int charPos, int c) {
|
||||||
|
UNSAFE.putChar(buf, ARRAY_BYTE_BASE_OFFSET + (charPos << 1), (char) c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
|
import jdk.internal.util.DecimalDigits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class to get access to package-private members
|
* A helper class to get access to package-private members
|
||||||
*/
|
*/
|
||||||
@ -117,11 +119,17 @@ public class Helper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int getChars(int i, int begin, int end, byte[] value) {
|
public static int getChars(int i, int begin, int end, byte[] value) {
|
||||||
return StringUTF16.getChars(i, begin, end, value);
|
StringUTF16.checkBoundsBeginEnd(begin, end, value);
|
||||||
|
int pos = DecimalDigits.getCharsUTF16(i, end, value);
|
||||||
|
assert begin == pos;
|
||||||
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getChars(long l, int begin, int end, byte[] value) {
|
public static int getChars(long l, int begin, int end, byte[] value) {
|
||||||
return StringUTF16.getChars(l, begin, end, value);
|
StringUTF16.checkBoundsBeginEnd(begin, end, value);
|
||||||
|
int pos = DecimalDigits.getCharsUTF16(l, end, value);
|
||||||
|
assert begin == pos;
|
||||||
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean contentEquals(byte[] v1, byte[] v2, int len) {
|
public static boolean contentEquals(byte[] v1, byte[] v2, int len) {
|
||||||
|
@ -54,6 +54,8 @@ public class StringBuilders {
|
|||||||
private StringBuilder sbLatin2;
|
private StringBuilder sbLatin2;
|
||||||
private StringBuilder sbUtf16;
|
private StringBuilder sbUtf16;
|
||||||
private StringBuilder sbUtf17;
|
private StringBuilder sbUtf17;
|
||||||
|
private int[] intsArray;
|
||||||
|
private long[] longArray;
|
||||||
|
|
||||||
@Setup
|
@Setup
|
||||||
public void setup() {
|
public void setup() {
|
||||||
@ -69,6 +71,13 @@ public class StringBuilders {
|
|||||||
sbLatin2 = new StringBuilder("Latin1 string");
|
sbLatin2 = new StringBuilder("Latin1 string");
|
||||||
sbUtf16 = new StringBuilder("UTF-\uFF11\uFF16 string");
|
sbUtf16 = new StringBuilder("UTF-\uFF11\uFF16 string");
|
||||||
sbUtf17 = new StringBuilder("UTF-\uFF11\uFF16 string");
|
sbUtf17 = new StringBuilder("UTF-\uFF11\uFF16 string");
|
||||||
|
int size = 16;
|
||||||
|
intsArray = new int[size];
|
||||||
|
longArray = new long[size];
|
||||||
|
for (int i = 0; i < longArray.length; i++) {
|
||||||
|
intsArray[i] = ((100 * i + i) << 24) + 4543 + i * 4;
|
||||||
|
longArray[i] = ((100L * i + i) << 32) + 4543 + i * 4L;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -224,6 +233,47 @@ public class StringBuilders {
|
|||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public int appendWithIntLatin1() {
|
||||||
|
StringBuilder buf = sbLatin1;
|
||||||
|
buf.setLength(0);
|
||||||
|
for (long l : longArray) {
|
||||||
|
buf.append(l);
|
||||||
|
}
|
||||||
|
return buf.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public int appendWithIntUtf16() {
|
||||||
|
StringBuilder buf = sbUtf16;
|
||||||
|
buf.setLength(0);
|
||||||
|
buf.setLength(0);
|
||||||
|
for (long l : longArray) {
|
||||||
|
buf.append(l);
|
||||||
|
}
|
||||||
|
return buf.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public int appendWithLongLatin1() {
|
||||||
|
StringBuilder buf = sbLatin1;
|
||||||
|
buf.setLength(0);
|
||||||
|
for (long l : longArray) {
|
||||||
|
buf.append(l);
|
||||||
|
}
|
||||||
|
return buf.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public int appendWithLongUtf16() {
|
||||||
|
StringBuilder buf = sbUtf16;
|
||||||
|
buf.setLength(0);
|
||||||
|
buf.setLength(0);
|
||||||
|
for (long l : longArray) {
|
||||||
|
buf.append(l);
|
||||||
|
}
|
||||||
|
return buf.length();
|
||||||
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
public int appendWithBool8Latin1() {
|
public int appendWithBool8Latin1() {
|
||||||
|
Loading…
Reference in New Issue
Block a user