Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8263754: HexFormat 'fromHex' methods should be static #3205

Closed
Closed
Changes from all commits
Commits
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -877,7 +877,7 @@ private static int checkDigitCount(int fromIndex, int toIndex, int limit) {
* @return {@code true} if the character is valid a hexadecimal character,
* otherwise {@code false}
*/
public boolean isHexDigit(int ch) {
public static boolean isHexDigit(int ch) {
return ((ch >>> 8) == 0 && DIGITS[ch] >= 0);
}

@@ -889,13 +889,12 @@ public boolean isHexDigit(int ch) {
* <li>{@code (ch - 'A' + 10)} for {@code 'A'} through {@code 'F'} inclusive, and
* <li>{@code (ch - 'a' + 10)} for {@code 'a'} through {@code 'f'} inclusive.
* </ul>
* The delimiter, prefix, suffix, and uppercase parameters are not used.
*
* @param ch a character or codepoint
* @return the value {@code 0-15}
* @throws NumberFormatException if the codepoint is not a hexadecimal character
*/
public int fromHexDigit(int ch) {
public static int fromHexDigit(int ch) {
int value;
if ((ch >>> 8) == 0 && (value = DIGITS[ch]) >= 0) {
return value;
@@ -907,7 +906,6 @@ public int fromHexDigit(int ch) {
* Returns a value parsed from two hexadecimal characters in a string.
* The characters in the range from {@code index} to {@code index + 1},
* inclusive, must be valid hex digits according to {@link #fromHexDigit(int)}.
* The delimiter, prefix, suffix, and uppercase parameters are not used.
*
* @param string a CharSequence containing the characters
* @param index the index of the first character of the range
@@ -917,7 +915,7 @@ public int fromHexDigit(int ch) {
* @throws IndexOutOfBoundsException if the range is out of bounds
* for the {@code CharSequence}
*/
private 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 low = fromHexDigit(string.charAt(index + 1));
@@ -929,7 +927,6 @@ private int fromHexDigits(CharSequence string, int index) {
* The hexadecimal characters are parsed from most significant to least significant
* using {@link #fromHexDigit(int)} to form an unsigned value.
* The value is zero extended to 32 bits and is returned as an {@code int}.
* The delimiter, prefix, suffix, and uppercase parameters are not used.
*
* @apiNote
* {@link Integer#parseInt(String, int) Integer.parseInt(s, 16)} and
@@ -944,7 +941,7 @@ private int fromHexDigits(CharSequence string, int index) {
* @throws IllegalArgumentException if the string length is greater than eight (8) or
* if any of the characters is not a hexadecimal character
*/
public int fromHexDigits(CharSequence string) {
public static int fromHexDigits(CharSequence string) {
Objects.requireNonNull(string, "string");
int length = checkDigitCount(0, string.length(), 8);
int value = 0;
@@ -961,7 +958,6 @@ public int fromHexDigits(CharSequence string) {
* are parsed from most significant to least significant
* using {@link #fromHexDigit(int)} to form an unsigned value.
* The value is zero extended to 32 bits and is returned as an {@code int}.
* The delimiter, prefix, suffix, and uppercase parameters are not used.
*
* @apiNote
* {@link Integer#parseInt(String, int) Integer.parseInt(s, 16)} and
@@ -980,7 +976,7 @@ public int fromHexDigits(CharSequence string) {
* @throws IllegalArgumentException if length of the range is greater than eight (8) or
* if any of the characters is not a hexadecimal character
*/
public int fromHexDigits(CharSequence string, int fromIndex, int toIndex) {
public static int fromHexDigits(CharSequence string, int fromIndex, int toIndex) {
Objects.requireNonNull(string, "string");
Objects.checkFromToIndex(fromIndex, toIndex, string.length());
int length = checkDigitCount(fromIndex, toIndex, 8);
@@ -996,7 +992,6 @@ public int fromHexDigits(CharSequence string, int fromIndex, int toIndex) {
* The hexadecimal characters are parsed from most significant to least significant
* using {@link #fromHexDigit(int)} to form an unsigned value.
* The value is zero extended to 64 bits and is returned as a {@code long}.
* The delimiter, prefix, suffix, and uppercase parameters are not used.
*
* @apiNote
* {@link Long#parseLong(String, int) Long.parseLong(s, 16)} and
@@ -1011,7 +1006,7 @@ public int fromHexDigits(CharSequence string, int fromIndex, int toIndex) {
* @throws IllegalArgumentException if the string length is greater than sixteen (16) or
* if any of the characters is not a hexadecimal character
*/
public long fromHexDigitsToLong(CharSequence string) {
public static long fromHexDigitsToLong(CharSequence string) {
Objects.requireNonNull(string, "string");
int length = checkDigitCount(0, string.length(), 16);
long value = 0L;
@@ -1028,7 +1023,6 @@ public long fromHexDigitsToLong(CharSequence string) {
* are parsed from most significant to least significant
* using {@link #fromHexDigit(int)} to form an unsigned value.
* The value is zero extended to 64 bits and is returned as a {@code long}.
* The delimiter, prefix, suffix, and uppercase parameters are not used.
*
* @apiNote
* {@link Long#parseLong(String, int) Long.parseLong(s, 16)} and
@@ -1047,7 +1041,7 @@ public long fromHexDigitsToLong(CharSequence string) {
* @throws IllegalArgumentException if the length of the range is greater than sixteen (16) or
* if any of the characters is not a hexadecimal character
*/
public long fromHexDigitsToLong(CharSequence string, int fromIndex, int toIndex) {
public static long fromHexDigitsToLong(CharSequence string, int fromIndex, int toIndex) {
Objects.requireNonNull(string, "string");
Objects.checkFromToIndex(fromIndex, toIndex, string.length());
int length = checkDigitCount(fromIndex, toIndex, 16);
@@ -815,11 +815,10 @@ private void checkOCSP(X509Certificate cert,
* Removes any non-hexadecimal characters from a string.
*/
private static String stripOutSeparators(String value) {
HexFormat hex = HexFormat.of();
char[] chars = value.toCharArray();
StringBuilder hexNumber = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (hex.isHexDigit(chars[i])) {
if (HexFormat.isHexDigit(chars[i])) {

This comment has been minimized.

@cl4es

cl4es Mar 25, 2021
Member

hex left unused.

hexNumber.append(chars[i]);
}
}
@@ -40,7 +40,6 @@

import java.security.interfaces.ECKey;
import java.security.interfaces.EdECKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
import java.text.Collator;
import java.text.MessageFormat;
@@ -4574,16 +4573,15 @@ private CertificateExtensions createV3Extensions(
break;
case -1:
ObjectIdentifier oid = ObjectIdentifier.of(name);
HexFormat hexFmt = HexFormat.of();
byte[] data = null;
if (value != null) {
data = new byte[value.length() / 2 + 1];
int pos = 0;
for (char c: value.toCharArray()) {
if (!hexFmt.isHexDigit(c)) {
if (!HexFormat.isHexDigit(c)) {

This comment has been minimized.

@cl4es

cl4es Mar 25, 2021
Member

hexFmt created on line 4576 appears to be unused after this.

This comment has been minimized.

@RogerRiggs

RogerRiggs Mar 25, 2021
Author Contributor

The toHexDigit methods need access to the uppercase/lowercase distinction.
So there is no plan to change them.
I'll amend to include the above and re-check for uncaught uses.

This comment has been minimized.

@cl4es

cl4es Mar 25, 2021
Member

Hmm, I missed that unfortunate detail. It looks mis-matched to have fromHex* be static while toHex* variants aren't.

continue;
}
int hex = hexFmt.fromHexDigit(c);
int hex = HexFormat.fromHexDigit(c);
if (pos % 2 == 0) {
data[pos/2] = (byte)(hex << 4);
} else {
@@ -29,7 +29,6 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.security.AccessController;
import java.text.Normalizer;
import java.util.*;

@@ -251,7 +250,6 @@ public String getValueString() {

private static DerValue parseHexString
(Reader in, int format) throws IOException {
HexFormat hex = HexFormat.of();
int c;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte b = 0;
@@ -263,7 +261,7 @@ public String getValueString() {
break;
}
try {
int cVal = hex.fromHexDigit(c); // throws on invalid character
int cVal = HexFormat.fromHexDigit(c); // throws on invalid character
if ((cNdx % 2) == 1) {
b = (byte)((b * 16) + (byte)(cVal));
baos.write(b);
@@ -502,14 +500,13 @@ public String getValueString() {
private static Byte getEmbeddedHexPair(int c1, Reader in)
throws IOException {

HexFormat hex = HexFormat.of();
if (hex.isHexDigit(c1)) {
if (HexFormat.isHexDigit(c1)) {
int c2 = readChar(in, "unexpected EOF - " +
"escaped hex value must include two valid digits");

if (hex.isHexDigit(c2)) {
int hi = hex.fromHexDigit(c1);
int lo = hex.fromHexDigit(c2);
if (HexFormat.isHexDigit(c2)) {
int hi = HexFormat.fromHexDigit(c1);
int lo = HexFormat.fromHexDigit(c2);
return (byte)((hi<<4) + lo);
} else {
throw new IOException
@@ -153,7 +153,7 @@ static void testToHexDigits() {
HexFormat hex = HexFormat.of();
for (int i = 0; i < 256; i++) {
String actual = hex.toHexDigits((byte)i);
int expected = hex.fromHexDigits(actual);
int expected = HexFormat.fromHexDigits(actual);
assertEquals(expected, i, "fromHexDigits");
assertEquals(actual.charAt(0), hex.toHighHexDigit((byte)i),
"first char mismatch");
@@ -164,33 +164,30 @@ static void testToHexDigits() {

@Test
static void testIsHexDigit() {
HexFormat hex = HexFormat.of();
for (int i = 0; i < 0x3ff; i++) {
boolean actual = hex.isHexDigit(i);
boolean actual = HexFormat.isHexDigit(i);
boolean expected = Character.digit(i, 16) >= 0;
assertEquals(actual, expected, "isHexDigit: " + i);
}
}

@Test
static void testFromHexDigit() {
HexFormat hex = HexFormat.of();
String chars = "0123456789ABCDEF0123456789abcdef";
for (int i = 0; i < chars.length(); i++) {
int v = hex.fromHexDigit(chars.charAt(i));
int v = HexFormat.fromHexDigit(chars.charAt(i));
assertEquals(v, i & 0xf, "fromHex decode");
}
}

@Test
static void testFromHexInvalid() {
HexFormat hex = HexFormat.of();
for (int i = 0; i < 65536; i++) {
char ch = (char)i;
if (ch > 0xff || Character.digit(ch, 16) < 0) {
assertFalse(hex.isHexDigit(ch), "isHexDigit incorrect for '" + ch + "' = " + i);
assertFalse(HexFormat.isHexDigit(ch), "isHexDigit incorrect for '" + ch + "' = " + i);
expectThrows(NumberFormatException.class,
() -> hex.fromHexDigit(ch));
() -> HexFormat.fromHexDigit(ch));

}
}
@@ -208,7 +205,7 @@ static void testAppendHexByteWithStringBuilder() {
assertEquals(sb.charAt(0), hex.toHighHexDigit((byte)i), "MSB converted wrong");
assertEquals(sb.charAt(1), hex.toLowHexDigit((byte)i), "LSB converted wrong");

assertEquals(hex.fromHexDigits(sb), i, "hex.format(sb, byte) wrong");
assertEquals(HexFormat.fromHexDigits(sb), i, "hex.format(sb, byte) wrong");
}
}

@@ -244,7 +241,7 @@ static void testFromHexPairInvalid() {
for (int i = 0; i < chars.length(); i += 2) {
final int ndx = i;
Throwable ex = expectThrows(NumberFormatException.class,
() -> hex.fromHexDigits(chars.subSequence(ndx, ndx+2)));
() -> HexFormat.fromHexDigits(chars.subSequence(ndx, ndx+2)));
System.out.println(ex);
}
}
@@ -289,10 +286,10 @@ static void testParseHexNPE() {

@Test
static void testFromHexNPE() {
assertThrows(NPE, () -> HexFormat.of().fromHexDigits(null));
assertThrows(NPE, () -> HexFormat.of().fromHexDigits(null, 0, 0));
assertThrows(NPE, () -> HexFormat.of().fromHexDigitsToLong(null));
assertThrows(NPE, () -> HexFormat.of().fromHexDigitsToLong(null, 0, 0));
assertThrows(NPE, () -> HexFormat.fromHexDigits(null));
assertThrows(NPE, () -> HexFormat.fromHexDigits(null, 0, 0));
assertThrows(NPE, () -> HexFormat.fromHexDigitsToLong(null));
assertThrows(NPE, () -> HexFormat.fromHexDigitsToLong(null, 0, 0));
}

@Test
@@ -314,23 +311,23 @@ static void badParseHex(String string, int offset, int length,
static void badFromHexDigits(String string, int fromIndex, int toIndex,
Class<? extends Throwable> exClass) {
assertThrows(exClass,
() -> HexFormat.of().fromHexDigits(string, fromIndex, toIndex));
() -> HexFormat.fromHexDigits(string, fromIndex, toIndex));
assertThrows(exClass,
() -> HexFormat.of().fromHexDigitsToLong(string, fromIndex, toIndex));
() -> HexFormat.fromHexDigitsToLong(string, fromIndex, toIndex));
}

// Verify IAE for strings that are too long for the target primitive type
// or the number of requested digits is too large.
@Test
static void wrongNumberDigits() {
assertThrows(IllegalArgumentException.class,
() -> HexFormat.of().fromHexDigits("9876543210"));
() -> HexFormat.fromHexDigits("9876543210"));
assertThrows(IllegalArgumentException.class,
() -> HexFormat.of().fromHexDigits("9876543210", 0, 9));
() -> HexFormat.fromHexDigits("9876543210", 0, 9));
assertThrows(IllegalArgumentException.class,
() -> HexFormat.of().fromHexDigitsToLong("98765432109876543210"));
() -> HexFormat.fromHexDigitsToLong("98765432109876543210"));
assertThrows(IllegalArgumentException.class,
() -> HexFormat.of().fromHexDigitsToLong("98765432109876543210", 0, 17));
() -> HexFormat.fromHexDigitsToLong("98765432109876543210", 0, 17));
}

@Test(dataProvider="HexFormattersParsers")
@@ -572,7 +569,7 @@ static void testfromHexDigitsToInt() {
final int orig = 0x76543210;
for (int digits = 0; digits <= 8; digits++) {
String s = hex.toHexDigits(orig, digits);
long actual = hex.fromHexDigits(s, 0, digits);
long actual = HexFormat.fromHexDigits(s, 0, digits);
System.out.printf(" digits: %2d, formatted: \"%s\", parsed as: 0x%08x%n",
digits, s, actual);
assertEquals(s, allHex.substring(8 - digits, 8));
@@ -589,7 +586,7 @@ static void testfromHexDigitsToLong() {
final long orig = 0xfedcba9876543210L;
for (int digits = 0; digits <= 16; digits++) {
String s = hex.toHexDigits(orig, digits);
long actual = hex.fromHexDigitsToLong(s, 0, digits);
long actual = HexFormat.fromHexDigitsToLong(s, 0, digits);
System.out.printf(" digits: %2d, formatted: \"%s\", parsed as: 0x%016xL%n",
digits, s, actual);
assertEquals(s, allHex.substring(16 - digits, 16));
@@ -605,7 +602,7 @@ static void testToHexDigitsLong() {
String allHex = "fedcba9876543210";
final long expected = 0xfedcba9876543210L;
String s = hex.toHexDigits(expected);
long actual = hex.fromHexDigitsToLong(s);
long actual = HexFormat.fromHexDigitsToLong(s);
System.out.printf(" formatted: \"%s\", parsed as: 0x%016xL%n", s, actual);
assertEquals(s, allHex);
assertEquals(actual, expected);
@@ -667,7 +664,7 @@ private static void samples() {
String byteStr = hex.toHexDigits(b);
System.out.println(" " + byteStr);

byte byteVal = (byte)hex.fromHexDigits(byteStr);
byte byteVal = (byte) HexFormat.fromHexDigits(byteStr);
assert(byteStr.equals("7f"));
assert(b == byteVal);
assertTrue(byteStr.equals("7f"));
@@ -677,20 +674,20 @@ private static void samples() {
char c = 'A';
String charStr = hex.toHexDigits(c);
System.out.println(" " + charStr);
int charVal = hex.fromHexDigits(charStr);
int charVal = HexFormat.fromHexDigits(charStr);
assert(c == charVal);
assertTrue(c == charVal);

int i = 12345;
String intStr = hex.toHexDigits(i);
System.out.println(" " + intStr);
int intVal = hex.fromHexDigits(intStr);
int intVal = HexFormat.fromHexDigits(intStr);
assert(i == intVal);
assertTrue(i == intVal);

long l = Long.MAX_VALUE;
String longStr = hex.toHexDigits(l, 16);
long longVal = hex.fromHexDigitsToLong(longStr, 0, 16);
long longVal = HexFormat.fromHexDigitsToLong(longStr, 0, 16);
System.out.println(" " + longStr + ", " + longVal);
assert(l == longVal);
assertTrue(l == longVal);
ProTip! Use n and p to navigate between commits in a pull request.