8264514: HexFormat implementation tweaks
Reviewed-by: rriggs
This commit is contained in:
parent
e16d568c1f
commit
fa82d47591
@ -150,20 +150,24 @@ public final class HexFormat {
|
|||||||
};
|
};
|
||||||
// Analysis has shown that generating the whole array allows the JIT to generate
|
// Analysis has shown that generating the whole array allows the JIT to generate
|
||||||
// better code compared to a slimmed down array, such as one cutting off after 'f'
|
// better code compared to a slimmed down array, such as one cutting off after 'f'
|
||||||
private static final byte[] DIGITS = new byte[] {
|
private static final byte[] DIGITS = {
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12,
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Format each byte of an array as a pair of hexadecimal digits.
|
* Format each byte of an array as a pair of hexadecimal digits.
|
||||||
* The hexadecimal characters are from lowercase alpha digits.
|
* The hexadecimal characters are from lowercase alpha digits.
|
||||||
@ -171,7 +175,7 @@ public final class HexFormat {
|
|||||||
private static final HexFormat HEX_FORMAT =
|
private static final HexFormat HEX_FORMAT =
|
||||||
new HexFormat("", "", "", LOWERCASE_DIGITS);
|
new HexFormat("", "", "", LOWERCASE_DIGITS);
|
||||||
|
|
||||||
private static final byte[] EMPTY_BYTES = new byte[0];
|
private static final byte[] EMPTY_BYTES = {};
|
||||||
|
|
||||||
private final String delimiter;
|
private final String delimiter;
|
||||||
private final String prefix;
|
private final String prefix;
|
||||||
@ -191,7 +195,7 @@ public final class HexFormat {
|
|||||||
this.delimiter = Objects.requireNonNull(delimiter, "delimiter");
|
this.delimiter = Objects.requireNonNull(delimiter, "delimiter");
|
||||||
this.prefix = Objects.requireNonNull(prefix, "prefix");
|
this.prefix = Objects.requireNonNull(prefix, "prefix");
|
||||||
this.suffix = Objects.requireNonNull(suffix, "suffix");
|
this.suffix = Objects.requireNonNull(suffix, "suffix");
|
||||||
this.digits = Objects.requireNonNull(digits, "digits");
|
this.digits = digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -468,7 +472,8 @@ public final class HexFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checked that the requested size for the result string is less than the max array size.
|
* Checked that the requested size for the result string is
|
||||||
|
* less than or equal to the max array size.
|
||||||
*
|
*
|
||||||
* @param length the requested size of a byte array.
|
* @param length the requested size of a byte array.
|
||||||
* @return the length
|
* @return the length
|
||||||
@ -526,7 +531,7 @@ public final class HexFormat {
|
|||||||
string = string.subSequence(fromIndex, toIndex);
|
string = string.subSequence(fromIndex, toIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.length() == 0)
|
if (string.isEmpty())
|
||||||
return EMPTY_BYTES;
|
return EMPTY_BYTES;
|
||||||
if (delimiter.isEmpty() && prefix.isEmpty() && suffix.isEmpty())
|
if (delimiter.isEmpty() && prefix.isEmpty() && suffix.isEmpty())
|
||||||
return parseNoDelimiter(string);
|
return parseNoDelimiter(string);
|
||||||
@ -534,7 +539,7 @@ public final class HexFormat {
|
|||||||
// avoid overflow for max length prefix or suffix
|
// avoid overflow for max length prefix or suffix
|
||||||
long valueChars = prefix.length() + 2L + suffix.length();
|
long valueChars = prefix.length() + 2L + suffix.length();
|
||||||
long stride = valueChars + delimiter.length();
|
long stride = valueChars + delimiter.length();
|
||||||
if (string.length() < valueChars || (string.length() - valueChars) % stride != 0)
|
if ((string.length() - valueChars) % stride != 0)
|
||||||
throw new IllegalArgumentException("extra or missing delimiters " +
|
throw new IllegalArgumentException("extra or missing delimiters " +
|
||||||
"or values consisting of prefix, two hexadecimal digits, and suffix");
|
"or values consisting of prefix, two hexadecimal digits, and suffix");
|
||||||
|
|
||||||
@ -545,16 +550,10 @@ public final class HexFormat {
|
|||||||
byte[] bytes = new byte[len];
|
byte[] bytes = new byte[len];
|
||||||
int i, offset;
|
int i, offset;
|
||||||
for (i = 0, offset = prefix.length(); i < len - 1; i++, offset += 2 + between.length()) {
|
for (i = 0, offset = prefix.length(); i < len - 1; i++, offset += 2 + between.length()) {
|
||||||
int v = fromHexDigits(string, offset);
|
bytes[i] = (byte) fromHexDigits(string, offset);
|
||||||
if (v < 0)
|
|
||||||
throw new IllegalArgumentException("input contains non-hexadecimal characters");
|
|
||||||
bytes[i] = (byte) v;
|
|
||||||
checkLiteral(string, offset + 2, between);
|
checkLiteral(string, offset + 2, between);
|
||||||
}
|
}
|
||||||
int v = fromHexDigits(string, offset);
|
bytes[i] = (byte) fromHexDigits(string, offset);
|
||||||
if (v < 0)
|
|
||||||
throw new IllegalArgumentException("input contains non-hexadecimal characters");
|
|
||||||
bytes[i] = (byte) v;
|
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
@ -830,21 +829,15 @@ public final class HexFormat {
|
|||||||
* @throws IllegalArgumentException if the string length is not valid or
|
* @throws IllegalArgumentException if the string length is not valid or
|
||||||
* the string contains non-hexadecimal characters
|
* the string contains non-hexadecimal characters
|
||||||
*/
|
*/
|
||||||
private byte[] parseNoDelimiter(CharSequence string) {
|
private static byte[] parseNoDelimiter(CharSequence string) {
|
||||||
if ((string.length() & 1) != 0)
|
if ((string.length() & 1) != 0)
|
||||||
throw new IllegalArgumentException("string length not even: " +
|
throw new IllegalArgumentException("string length not even: " +
|
||||||
string.length());
|
string.length());
|
||||||
|
|
||||||
byte[] bytes = new byte[string.length() / 2];
|
byte[] bytes = new byte[string.length() / 2];
|
||||||
int illegal = 0; // Accumulate logical-or of all bytes
|
|
||||||
for (int i = 0; i < bytes.length; i++) {
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
int v = fromHexDigits(string, i * 2);
|
bytes[i] = (byte) fromHexDigits(string, i * 2);
|
||||||
bytes[i] = (byte) v;
|
|
||||||
illegal |= v;
|
|
||||||
}
|
}
|
||||||
// check if any character was an illegal character
|
|
||||||
if (illegal < 0)
|
|
||||||
throw new IllegalArgumentException("input contains non-hexadecimal characters");
|
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
@ -916,7 +909,6 @@ public final class HexFormat {
|
|||||||
* for the {@code CharSequence}
|
* for the {@code CharSequence}
|
||||||
*/
|
*/
|
||||||
private static int fromHexDigits(CharSequence string, int index) {
|
private static int fromHexDigits(CharSequence string, int index) {
|
||||||
Objects.requireNonNull(string, "string");
|
|
||||||
int high = fromHexDigit(string.charAt(index));
|
int high = fromHexDigit(string.charAt(index));
|
||||||
int low = fromHexDigit(string.charAt(index + 1));
|
int low = fromHexDigit(string.charAt(index + 1));
|
||||||
return (high << 4) | low;
|
return (high << 4) | low;
|
||||||
@ -933,7 +925,8 @@ public final class HexFormat {
|
|||||||
* {@link Integer#parseUnsignedInt(String, int) Integer.parseUnsignedInt(s, 16)}
|
* {@link Integer#parseUnsignedInt(String, int) Integer.parseUnsignedInt(s, 16)}
|
||||||
* are similar but allow all Unicode hexadecimal digits defined by
|
* are similar but allow all Unicode hexadecimal digits defined by
|
||||||
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
||||||
* {@code HexFormat} uses only hexadecimal characters "0-9, "A-F", and "a-f".
|
* {@code HexFormat} uses only hexadecimal characters
|
||||||
|
* {@code "0-9"}, {@code "A-F"} and {@code "a-f"}.
|
||||||
* Signed hexadecimal strings can be parsed with {@link Integer#parseInt(String, int)}.
|
* Signed hexadecimal strings can be parsed with {@link Integer#parseInt(String, int)}.
|
||||||
*
|
*
|
||||||
* @param string a CharSequence containing up to eight hexadecimal characters
|
* @param string a CharSequence containing up to eight hexadecimal characters
|
||||||
@ -942,13 +935,7 @@ public final class HexFormat {
|
|||||||
* if any of the characters is not a hexadecimal character
|
* if any of the characters is not a hexadecimal character
|
||||||
*/
|
*/
|
||||||
public static int fromHexDigits(CharSequence string) {
|
public static int fromHexDigits(CharSequence string) {
|
||||||
Objects.requireNonNull(string, "string");
|
return fromHexDigits(string, 0, string.length());
|
||||||
int length = checkDigitCount(0, string.length(), 8);
|
|
||||||
int value = 0;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
value = (value << 4) + fromHexDigit(string.charAt(i));
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -964,7 +951,8 @@ public final class HexFormat {
|
|||||||
* {@link Integer#parseUnsignedInt(String, int) Integer.parseUnsignedInt(s, 16)}
|
* {@link Integer#parseUnsignedInt(String, int) Integer.parseUnsignedInt(s, 16)}
|
||||||
* are similar but allow all Unicode hexadecimal digits defined by
|
* are similar but allow all Unicode hexadecimal digits defined by
|
||||||
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
||||||
* {@code HexFormat} uses only hexadecimal characters "0-9, "A-F", and "a-f".
|
* {@code HexFormat} uses only hexadecimal characters
|
||||||
|
* {@code "0-9"}, {@code "A-F"} and {@code "a-f"}.
|
||||||
* Signed hexadecimal strings can be parsed with {@link Integer#parseInt(String, int)}.
|
* Signed hexadecimal strings can be parsed with {@link Integer#parseInt(String, int)}.
|
||||||
*
|
*
|
||||||
* @param string a CharSequence containing the characters
|
* @param string a CharSequence containing the characters
|
||||||
@ -998,7 +986,8 @@ public final class HexFormat {
|
|||||||
* {@link Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, 16)}
|
* {@link Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, 16)}
|
||||||
* are similar but allow all Unicode hexadecimal digits defined by
|
* are similar but allow all Unicode hexadecimal digits defined by
|
||||||
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
||||||
* {@code HexFormat} uses only hexadecimal characters "0-9, "A-F", and "a-f".
|
* {@code HexFormat} uses only hexadecimal characters
|
||||||
|
* {@code "0-9"}, {@code "A-F"} and {@code "a-f"}.
|
||||||
* Signed hexadecimal strings can be parsed with {@link Long#parseLong(String, int)}.
|
* Signed hexadecimal strings can be parsed with {@link Long#parseLong(String, int)}.
|
||||||
*
|
*
|
||||||
* @param string a CharSequence containing up to sixteen hexadecimal characters
|
* @param string a CharSequence containing up to sixteen hexadecimal characters
|
||||||
@ -1007,13 +996,7 @@ public final class HexFormat {
|
|||||||
* if any of the characters is not a hexadecimal character
|
* if any of the characters is not a hexadecimal character
|
||||||
*/
|
*/
|
||||||
public static long fromHexDigitsToLong(CharSequence string) {
|
public static long fromHexDigitsToLong(CharSequence string) {
|
||||||
Objects.requireNonNull(string, "string");
|
return fromHexDigitsToLong(string, 0, string.length());
|
||||||
int length = checkDigitCount(0, string.length(), 16);
|
|
||||||
long value = 0L;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
value = (value << 4) + fromHexDigit(string.charAt(i));
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1029,7 +1012,8 @@ public final class HexFormat {
|
|||||||
* {@link Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, 16)}
|
* {@link Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, 16)}
|
||||||
* are similar but allow all Unicode hexadecimal digits defined by
|
* are similar but allow all Unicode hexadecimal digits defined by
|
||||||
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
* {@link Character#digit(char, int) Character.digit(ch, 16)}.
|
||||||
* {@code HexFormat} uses only hexadecimal characters "0-9, "A-F", and "a-f".
|
* {@code HexFormat} uses only hexadecimal characters
|
||||||
|
* {@code "0-9"}, {@code "A-F"} and {@code "a-f"}.
|
||||||
* Signed hexadecimal strings can be parsed with {@link Long#parseLong(String, int)}.
|
* Signed hexadecimal strings can be parsed with {@link Long#parseLong(String, int)}.
|
||||||
*
|
*
|
||||||
* @param string a CharSequence containing the characters
|
* @param string a CharSequence containing the characters
|
||||||
@ -1068,10 +1052,10 @@ public final class HexFormat {
|
|||||||
if (o == null || getClass() != o.getClass())
|
if (o == null || getClass() != o.getClass())
|
||||||
return false;
|
return false;
|
||||||
HexFormat otherHex = (HexFormat) o;
|
HexFormat otherHex = (HexFormat) o;
|
||||||
return delimiter.equals(otherHex.delimiter) &&
|
return Arrays.equals(digits, otherHex.digits) &&
|
||||||
|
delimiter.equals(otherHex.delimiter) &&
|
||||||
prefix.equals(otherHex.prefix) &&
|
prefix.equals(otherHex.prefix) &&
|
||||||
suffix.equals(otherHex.suffix) &&
|
suffix.equals(otherHex.suffix);
|
||||||
Arrays.equals(digits, otherHex.digits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user