8251989: Hex formatting and parsing utility
Reviewed-by: tvaleev, chegar, naoto, darcy
This commit is contained in:
parent
efd61c6f53
commit
aa9c136d67
@ -264,10 +264,18 @@ public final class Integer extends Number
|
|||||||
* <blockquote>
|
* <blockquote>
|
||||||
* {@code Integer.toHexString(n).toUpperCase()}
|
* {@code Integer.toHexString(n).toUpperCase()}
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
|
* <p>
|
||||||
|
* @apiNote
|
||||||
|
* The {@link java.util.HexFormat} class provides formatting and parsing
|
||||||
|
* of byte arrays and primitives to return a string or adding to an {@link Appendable}.
|
||||||
|
* {@code HexFormat} formats and parses uppercase or lowercase hexadecimal characters,
|
||||||
|
* with leading zeros and for byte arrays includes for each byte
|
||||||
|
* a delimiter, prefix, and suffix.
|
||||||
*
|
*
|
||||||
* @param i an integer to be converted to a string.
|
* @param i an integer to be converted to a string.
|
||||||
* @return the string representation of the unsigned integer value
|
* @return the string representation of the unsigned integer value
|
||||||
* represented by the argument in hexadecimal (base 16).
|
* represented by the argument in hexadecimal (base 16).
|
||||||
|
* @see java.util.HexFormat
|
||||||
* @see #parseUnsignedInt(String, int)
|
* @see #parseUnsignedInt(String, int)
|
||||||
* @see #toUnsignedString(int, int)
|
* @see #toUnsignedString(int, int)
|
||||||
* @since 1.0.2
|
* @since 1.0.2
|
||||||
|
@ -299,11 +299,19 @@ public final class Long extends Number
|
|||||||
* <blockquote>
|
* <blockquote>
|
||||||
* {@code Long.toHexString(n).toUpperCase()}
|
* {@code Long.toHexString(n).toUpperCase()}
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
|
* <p>
|
||||||
|
* @apiNote
|
||||||
|
* The {@link java.util.HexFormat} class provides formatting and parsing
|
||||||
|
* of byte arrays and primitives to return a string or adding to an {@link Appendable}.
|
||||||
|
* {@code HexFormat} formats and parses uppercase or lowercase hexadecimal characters,
|
||||||
|
* with leading zeros and for byte arrays includes for each byte
|
||||||
|
* a delimiter, prefix, and suffix.
|
||||||
*
|
*
|
||||||
* @param i a {@code long} to be converted to a string.
|
* @param i a {@code long} to be converted to a string.
|
||||||
* @return the string representation of the unsigned {@code long}
|
* @return the string representation of the unsigned {@code long}
|
||||||
* value represented by the argument in hexadecimal
|
* value represented by the argument in hexadecimal
|
||||||
* (base 16).
|
* (base 16).
|
||||||
|
* @see java.util.HexFormat
|
||||||
* @see #parseUnsignedLong(String, int)
|
* @see #parseUnsignedLong(String, int)
|
||||||
* @see #toUnsignedString(long, int)
|
* @see #toUnsignedString(long, int)
|
||||||
* @since 1.0.2
|
* @since 1.0.2
|
||||||
|
@ -35,6 +35,7 @@ import java.util.Collection;
|
|||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.HexFormat;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -475,9 +476,10 @@ final class Resolver {
|
|||||||
if (actualHash == null)
|
if (actualHash == null)
|
||||||
findFail("Unable to compute the hash of module %s", dn);
|
findFail("Unable to compute the hash of module %s", dn);
|
||||||
if (!Arrays.equals(recordedHash, actualHash)) {
|
if (!Arrays.equals(recordedHash, actualHash)) {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
findFail("Hash of %s (%s) differs to expected hash (%s)" +
|
findFail("Hash of %s (%s) differs to expected hash (%s)" +
|
||||||
" recorded in %s", dn, toHexString(actualHash),
|
" recorded in %s", dn, hex.formatHex(actualHash),
|
||||||
toHexString(recordedHash), descriptor.name());
|
hex.formatHex(recordedHash), descriptor.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,15 +487,6 @@ final class Resolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toHexString(byte[] ba) {
|
|
||||||
StringBuilder sb = new StringBuilder(ba.length * 2);
|
|
||||||
for (byte b: ba) {
|
|
||||||
sb.append(String.format("%02x", b & 0xff));
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the readability graph for the modules in the given Configuration.
|
* Computes the readability graph for the modules in the given Configuration.
|
||||||
*
|
*
|
||||||
|
1108
src/java.base/share/classes/java/util/HexFormat.java
Normal file
1108
src/java.base/share/classes/java/util/HexFormat.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -701,7 +701,7 @@ public class Properties extends Hashtable<Object,Object> {
|
|||||||
bufLen = Integer.MAX_VALUE;
|
bufLen = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
StringBuilder outBuffer = new StringBuilder(bufLen);
|
StringBuilder outBuffer = new StringBuilder(bufLen);
|
||||||
|
HexFormat hex = HexFormat.of().withUpperCase();
|
||||||
for(int x=0; x<len; x++) {
|
for(int x=0; x<len; x++) {
|
||||||
char aChar = theString.charAt(x);
|
char aChar = theString.charAt(x);
|
||||||
// Handle common case first, selecting largest block that
|
// Handle common case first, selecting largest block that
|
||||||
@ -736,12 +736,8 @@ public class Properties extends Hashtable<Object,Object> {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode ) {
|
if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode ) {
|
||||||
outBuffer.append('\\');
|
outBuffer.append("\\u");
|
||||||
outBuffer.append('u');
|
outBuffer.append(hex.toHexDigits(aChar));
|
||||||
outBuffer.append(toHex((aChar >> 12) & 0xF));
|
|
||||||
outBuffer.append(toHex((aChar >> 8) & 0xF));
|
|
||||||
outBuffer.append(toHex((aChar >> 4) & 0xF));
|
|
||||||
outBuffer.append(toHex( aChar & 0xF));
|
|
||||||
} else {
|
} else {
|
||||||
outBuffer.append(aChar);
|
outBuffer.append(aChar);
|
||||||
}
|
}
|
||||||
@ -752,24 +748,19 @@ public class Properties extends Hashtable<Object,Object> {
|
|||||||
|
|
||||||
private static void writeComments(BufferedWriter bw, String comments)
|
private static void writeComments(BufferedWriter bw, String comments)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
HexFormat hex = HexFormat.of().withUpperCase();
|
||||||
bw.write("#");
|
bw.write("#");
|
||||||
int len = comments.length();
|
int len = comments.length();
|
||||||
int current = 0;
|
int current = 0;
|
||||||
int last = 0;
|
int last = 0;
|
||||||
char[] uu = new char[6];
|
|
||||||
uu[0] = '\\';
|
|
||||||
uu[1] = 'u';
|
|
||||||
while (current < len) {
|
while (current < len) {
|
||||||
char c = comments.charAt(current);
|
char c = comments.charAt(current);
|
||||||
if (c > '\u00ff' || c == '\n' || c == '\r') {
|
if (c > '\u00ff' || c == '\n' || c == '\r') {
|
||||||
if (last != current)
|
if (last != current)
|
||||||
bw.write(comments.substring(last, current));
|
bw.write(comments.substring(last, current));
|
||||||
if (c > '\u00ff') {
|
if (c > '\u00ff') {
|
||||||
uu[2] = toHex((c >> 12) & 0xf);
|
bw.write("\\u");
|
||||||
uu[3] = toHex((c >> 8) & 0xf);
|
bw.write(hex.toHexDigits(c));
|
||||||
uu[4] = toHex((c >> 4) & 0xf);
|
|
||||||
uu[5] = toHex( c & 0xf);
|
|
||||||
bw.write(new String(uu));
|
|
||||||
} else {
|
} else {
|
||||||
bw.newLine();
|
bw.newLine();
|
||||||
if (c == '\r' &&
|
if (c == '\r' &&
|
||||||
@ -1271,19 +1262,6 @@ public class Properties extends Hashtable<Object,Object> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a nibble to a hex character
|
|
||||||
* @param nibble the nibble to convert.
|
|
||||||
*/
|
|
||||||
private static char toHex(int nibble) {
|
|
||||||
return hexDigit[(nibble & 0xF)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A table of hex digits */
|
|
||||||
private static final char[] hexDigit = {
|
|
||||||
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hashtable methods overridden and delegated to a ConcurrentHashMap instance
|
// Hashtable methods overridden and delegated to a ConcurrentHashMap instance
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,6 +26,7 @@
|
|||||||
package javax.net.ssl;
|
package javax.net.ssl;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HexFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instances of this class represent a server name in a Server Name
|
* Instances of this class represent a server name in a Server Name
|
||||||
@ -52,9 +53,6 @@ public abstract class SNIServerName {
|
|||||||
// the encoded value of the server name
|
// the encoded value of the server name
|
||||||
private final byte[] encoded;
|
private final byte[] encoded;
|
||||||
|
|
||||||
// the hex digitals
|
|
||||||
private static final char[] HEXES = "0123456789ABCDEF".toCharArray();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an {@code SNIServerName} using the specified name type and
|
* Creates an {@code SNIServerName} using the specified name type and
|
||||||
* encoded value.
|
* encoded value.
|
||||||
@ -192,22 +190,7 @@ public abstract class SNIServerName {
|
|||||||
if (bytes.length == 0) {
|
if (bytes.length == 0) {
|
||||||
return "(empty)";
|
return "(empty)";
|
||||||
}
|
}
|
||||||
|
return HexFormat.ofDelimiter(":").withUpperCase().formatHex(bytes);
|
||||||
StringBuilder sb = new StringBuilder(bytes.length * 3 - 1);
|
|
||||||
boolean isInitial = true;
|
|
||||||
for (byte b : bytes) {
|
|
||||||
if (isInitial) {
|
|
||||||
isInitial = false;
|
|
||||||
} else {
|
|
||||||
sb.append(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
int k = b & 0xFF;
|
|
||||||
sb.append(HEXES[k >>> 4]);
|
|
||||||
sb.append(HEXES[k & 0xF]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ import java.nio.charset.CharsetDecoder;
|
|||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
import java.nio.charset.CoderResult;
|
import java.nio.charset.CoderResult;
|
||||||
import java.nio.charset.CodingErrorAction;
|
import java.nio.charset.CodingErrorAction;
|
||||||
|
import java.util.HexFormat;
|
||||||
|
|
||||||
import sun.nio.cs.UTF_8;
|
import sun.nio.cs.UTF_8;
|
||||||
|
|
||||||
@ -47,6 +48,8 @@ import sun.nio.cs.UTF_8;
|
|||||||
|
|
||||||
public final class ParseUtil {
|
public final class ParseUtil {
|
||||||
|
|
||||||
|
private static final HexFormat HEX_UPPERCASE = HexFormat.of().withUpperCase();
|
||||||
|
|
||||||
private ParseUtil() {}
|
private ParseUtil() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -515,15 +518,9 @@ public final class ParseUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final char[] hexDigits = {
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
|
||||||
};
|
|
||||||
|
|
||||||
private static void appendEscape(StringBuilder sb, byte b) {
|
private static void appendEscape(StringBuilder sb, byte b) {
|
||||||
sb.append('%');
|
sb.append('%');
|
||||||
sb.append(hexDigits[(b >> 4) & 0x0f]);
|
HEX_UPPERCASE.toHexDigits(sb, b);
|
||||||
sb.append(hexDigits[(b >> 0) & 0x0f]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell whether the given character is permitted by the given mask pair
|
// Tell whether the given character is permitted by the given mask pair
|
||||||
|
@ -30,6 +30,7 @@ import java.io.File;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HexFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unix specific Path <--> URI conversion
|
* Unix specific Path <--> URI conversion
|
||||||
@ -102,14 +103,14 @@ class UnixUriUtils {
|
|||||||
byte[] path = up.toAbsolutePath().asByteArray();
|
byte[] path = up.toAbsolutePath().asByteArray();
|
||||||
StringBuilder sb = new StringBuilder("file:///");
|
StringBuilder sb = new StringBuilder("file:///");
|
||||||
assert path[0] == '/';
|
assert path[0] == '/';
|
||||||
|
HexFormat hex = HexFormat.of().withUpperCase();
|
||||||
for (int i=1; i<path.length; i++) {
|
for (int i=1; i<path.length; i++) {
|
||||||
char c = (char)(path[i] & 0xff);
|
char c = (char)(path[i] & 0xff);
|
||||||
if (match(c, L_PATH, H_PATH)) {
|
if (match(c, L_PATH, H_PATH)) {
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
} else {
|
} else {
|
||||||
sb.append('%');
|
sb.append('%');
|
||||||
sb.append(hexDigits[(c >> 4) & 0x0f]);
|
hex.toHexDigits(sb, (byte)c);
|
||||||
sb.append(hexDigits[(c) & 0x0f]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,9 +243,4 @@ class UnixUriUtils {
|
|||||||
// All valid path characters
|
// All valid path characters
|
||||||
private static final long L_PATH = L_PCHAR | lowMask(";/");
|
private static final long L_PATH = L_PCHAR | lowMask(";/");
|
||||||
private static final long H_PATH = H_PCHAR | highMask(";/");
|
private static final long H_PATH = H_PCHAR | highMask(";/");
|
||||||
|
|
||||||
private static final char[] hexDigits = {
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -189,24 +189,6 @@ final class Filter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* convert character 'c' that represents a hexadecimal digit to an integer.
|
|
||||||
* if 'c' is not a hexadecimal digit [0-9A-Fa-f], -1 is returned.
|
|
||||||
* otherwise the converted value is returned.
|
|
||||||
*/
|
|
||||||
private static int hexchar2int( byte c ) {
|
|
||||||
if ( c >= '0' && c <= '9' ) {
|
|
||||||
return( c - '0' );
|
|
||||||
}
|
|
||||||
if ( c >= 'A' && c <= 'F' ) {
|
|
||||||
return( c - 'A' + 10 );
|
|
||||||
}
|
|
||||||
if ( c >= 'a' && c <= 'f' ) {
|
|
||||||
return( c - 'a' + 10 );
|
|
||||||
}
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// called by the LdapClient.compare method
|
// called by the LdapClient.compare method
|
||||||
static byte[] unescapeFilterValue(byte[] orig, int start, int end)
|
static byte[] unescapeFilterValue(byte[] orig, int start, int end)
|
||||||
throws NamingException {
|
throws NamingException {
|
||||||
@ -225,7 +207,7 @@ final class Filter {
|
|||||||
ch = orig[i];
|
ch = orig[i];
|
||||||
if (escape) {
|
if (escape) {
|
||||||
// Try LDAP V3 escape (\xx)
|
// Try LDAP V3 escape (\xx)
|
||||||
if ((ival = hexchar2int(ch)) < 0) {
|
if ((ival = Character.digit(ch, 16)) < 0) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If there is no hex char following a '\' when
|
* If there is no hex char following a '\' when
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,6 +27,7 @@ package com.sun.jndi.toolkit.dir;
|
|||||||
import javax.naming.*;
|
import javax.naming.*;
|
||||||
import javax.naming.directory.*;
|
import javax.naming.directory.*;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.HexFormat;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -466,26 +467,6 @@ public class SearchFilter implements AttrFilter {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes the hex representation of a byte to a StringBuffer.
|
|
||||||
private static void hexDigit(StringBuffer buf, byte x) {
|
|
||||||
char c;
|
|
||||||
|
|
||||||
c = (char) ((x >> 4) & 0xf);
|
|
||||||
if (c > 9)
|
|
||||||
c = (char) ((c-10) + 'A');
|
|
||||||
else
|
|
||||||
c = (char)(c + '0');
|
|
||||||
|
|
||||||
buf.append(c);
|
|
||||||
c = (char) (x & 0xf);
|
|
||||||
if (c > 9)
|
|
||||||
c = (char)((c-10) + 'A');
|
|
||||||
else
|
|
||||||
c = (char)(c + '0');
|
|
||||||
buf.append(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the string representation of an object (such as an attr value).
|
* Returns the string representation of an object (such as an attr value).
|
||||||
* If obj is a byte array, encode each item as \xx, where xx is hex encoding
|
* If obj is a byte array, encode each item as \xx, where xx is hex encoding
|
||||||
@ -506,13 +487,9 @@ public class SearchFilter implements AttrFilter {
|
|||||||
|
|
||||||
if (obj instanceof byte[]) {
|
if (obj instanceof byte[]) {
|
||||||
// binary data must be encoded as \hh where hh is a hex char
|
// binary data must be encoded as \hh where hh is a hex char
|
||||||
|
HexFormat hex = HexFormat.of().withUpperCase().withPrefix("\\");
|
||||||
byte[] bytes = (byte[])obj;
|
byte[] bytes = (byte[])obj;
|
||||||
StringBuffer b1 = new StringBuffer(bytes.length*3);
|
return hex.formatHex(bytes);
|
||||||
for (int i = 0; i < bytes.length; i++) {
|
|
||||||
b1.append('\\');
|
|
||||||
hexDigit(b1, bytes[i]);
|
|
||||||
}
|
|
||||||
return b1.toString();
|
|
||||||
}
|
}
|
||||||
if (!(obj instanceof String)) {
|
if (!(obj instanceof String)) {
|
||||||
str = obj.toString();
|
str = obj.toString();
|
||||||
|
@ -59,6 +59,7 @@ import java.text.Normalizer;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HexFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
@ -1085,17 +1086,6 @@ public final class Utils {
|
|||||||
|
|
||||||
// -- toAsciiString-like support to encode path and query URI segments
|
// -- toAsciiString-like support to encode path and query URI segments
|
||||||
|
|
||||||
private static final char[] hexDigits = {
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
|
||||||
};
|
|
||||||
|
|
||||||
private static void appendEscape(StringBuilder sb, byte b) {
|
|
||||||
sb.append('%');
|
|
||||||
sb.append(hexDigits[(b >> 4) & 0x0f]);
|
|
||||||
sb.append(hexDigits[(b >> 0) & 0x0f]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encodes all characters >= \u0080 into escaped, normalized UTF-8 octets,
|
// Encodes all characters >= \u0080 into escaped, normalized UTF-8 octets,
|
||||||
// assuming that s is otherwise legal
|
// assuming that s is otherwise legal
|
||||||
//
|
//
|
||||||
@ -1123,13 +1113,16 @@ public final class Utils {
|
|||||||
assert false : x;
|
assert false : x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HexFormat format = HexFormat.of().withUpperCase();
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
while (bb.hasRemaining()) {
|
while (bb.hasRemaining()) {
|
||||||
int b = bb.get() & 0xff;
|
int b = bb.get() & 0xff;
|
||||||
if (b >= 0x80)
|
if (b >= 0x80) {
|
||||||
appendEscape(sb, (byte)b);
|
sb.append('%');
|
||||||
else
|
format.toHexDigits(sb, (byte)b);
|
||||||
sb.append((char)b);
|
} else {
|
||||||
|
sb.append((char) b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -28,6 +28,8 @@
|
|||||||
* @summary Unit tests for supplementary character support (JSR-204)
|
* @summary Unit tests for supplementary character support (JSR-204)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.util.HexFormat;
|
||||||
|
|
||||||
public class Supplementary {
|
public class Supplementary {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@ -401,15 +403,13 @@ public class Supplementary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String toHexString(String s) {
|
private static String toHexString(String s) {
|
||||||
StringBuffer sb = new StringBuffer();
|
HexFormat format = HexFormat.of();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < s.length(); i++) {
|
for (int i = 0; i < s.length(); i++) {
|
||||||
char c = s.charAt(i);
|
char c = s.charAt(i);
|
||||||
|
|
||||||
sb.append(" 0x");
|
sb.append(" 0x");
|
||||||
if (c < 0x10) sb.append('0');
|
sb.append(format.toHexDigits(c));
|
||||||
if (c < 0x100) sb.append('0');
|
|
||||||
if (c < 0x1000) sb.append('0');
|
|
||||||
sb.append(Integer.toHexString(c));
|
|
||||||
}
|
}
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
756
test/jdk/java/util/HexFormat/HexFormatTest.java
Normal file
756
test/jdk/java/util/HexFormat/HexFormatTest.java
Normal file
@ -0,0 +1,756 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.io.CharArrayWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HexFormat;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertSame;
|
||||||
|
import static org.testng.Assert.assertThrows;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
import static org.testng.Assert.expectThrows;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Check HexFormat formatting and parsing
|
||||||
|
* @run testng/othervm -Xmx4G HexFormatTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public class HexFormatTest {
|
||||||
|
static final Class<NullPointerException> NPE = NullPointerException.class;
|
||||||
|
|
||||||
|
@DataProvider(name = "HexFormattersParsers")
|
||||||
|
Object[][] hexFormattersParsers() {
|
||||||
|
return new Object[][]{
|
||||||
|
{"", "", "", true,
|
||||||
|
HexFormat.of().withUpperCase()},
|
||||||
|
{", ", "#", "L", false,
|
||||||
|
HexFormat.ofDelimiter(", ").withPrefix("#").withSuffix("L")},
|
||||||
|
{"", "", "", false,
|
||||||
|
HexFormat.of().withPrefix("").withSuffix("")},
|
||||||
|
{".", "", "", false,
|
||||||
|
HexFormat.ofDelimiter(".").withPrefix("").withSuffix("")},
|
||||||
|
{", ", "0x", "", true,
|
||||||
|
HexFormat.ofDelimiter(", ").withUpperCase().withPrefix("0x")},
|
||||||
|
{"\u0202", "\u0203", "\u0204", false,
|
||||||
|
HexFormat.ofDelimiter("\u0202").withPrefix("\u0203").withSuffix("\u0204")},
|
||||||
|
{"\u0202", "", "", false,
|
||||||
|
HexFormat.ofDelimiter("\u0202")},
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "HexStringsThrowing")
|
||||||
|
Object[][] HexStringsThrowing() {
|
||||||
|
return new Object[][]{
|
||||||
|
{"0", ":", "", ""}, // wrong string length
|
||||||
|
{"01:", ":", "", ""}, // wrong string length
|
||||||
|
{"01:0", ":", "", ""}, // wrong string length
|
||||||
|
{"0", ",", "", ""}, // wrong length and separator
|
||||||
|
{"01:", ",", "", ""}, // wrong length and separator
|
||||||
|
{"01:0", ",", "", ""}, // wrong length and separator
|
||||||
|
{"01:00", ",", "", ""}, // wrong separator
|
||||||
|
{"00]", ",", "[", "]"}, // missing prefix
|
||||||
|
{"[00", ",", "[", "]"}, // missing suffix
|
||||||
|
{"]", ",", "[", "]"}, // missing prefix
|
||||||
|
{"[", ",", "[", "]"}, // missing suffix
|
||||||
|
{"00", ",", "abc", ""}, // Prefix longer than string
|
||||||
|
{"01", ",", "", "def"}, // Suffix longer than string
|
||||||
|
{"abc00,", ",", "abc", ""}, // Prefix and delim but not another value
|
||||||
|
{"01def,", ",", "", "def"}, // Suffix and delim but not another value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "BadBytesThrowing")
|
||||||
|
Object[][] badBytesThrowing() {
|
||||||
|
return new Object[][]{
|
||||||
|
{new byte[1], 0, 2}, // bad toIndex
|
||||||
|
{new byte[1], 1, 2}, // bad fromIndex + toIndex
|
||||||
|
{new byte[1], -1, 2}, // bad fromIndex
|
||||||
|
{new byte[1], -1, 1}, // bad fromIndex
|
||||||
|
{new byte[1], 0, -1}, // bad toIndex
|
||||||
|
{new byte[1], 1, -1}, // bad toIndex
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "BadParseHexThrowing")
|
||||||
|
Object[][] badParseHexThrowing() {
|
||||||
|
return new Object[][]{
|
||||||
|
{"a", 0, 2, IndexOutOfBoundsException.class}, // bad toIndex
|
||||||
|
{"b", 1, 2, IndexOutOfBoundsException.class}, // bad toIndex
|
||||||
|
{"a", -1, 2, IndexOutOfBoundsException.class}, // bad fromIndex
|
||||||
|
{"b", -1, 1, IndexOutOfBoundsException.class}, // bad fromIndex
|
||||||
|
{"a", 0, -1, IndexOutOfBoundsException.class}, // bad toIndex
|
||||||
|
{"b", 1, -1, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex
|
||||||
|
{"76543210", 0, 7, IllegalArgumentException.class}, // odd number of digits
|
||||||
|
{"zz00", 0, 4, IllegalArgumentException.class}, // non-hex digits
|
||||||
|
{"00zz", 0, 4, IllegalArgumentException.class}, // non-hex digits
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "BadFromHexDigitsThrowing")
|
||||||
|
Object[][] badHexDigitsThrowing() {
|
||||||
|
return new Object[][]{
|
||||||
|
{"a", 0, 2, IndexOutOfBoundsException.class}, // bad toIndex
|
||||||
|
{"b", 1, 2, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex
|
||||||
|
{"a", -1, 2, IndexOutOfBoundsException.class}, // bad toIndex
|
||||||
|
{"b", -1, 1, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex
|
||||||
|
{"a", 0, -1, IndexOutOfBoundsException.class}, // bad toIndex
|
||||||
|
{"b", 1, -1, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] genBytes(int origin, int len) {
|
||||||
|
byte[] bytes = new byte[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
bytes[i] = (byte) (origin + i);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testToHex() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
char c = hex.toLowHexDigit((byte)i);
|
||||||
|
String expected = Integer.toHexString(i & 0xf);
|
||||||
|
assertEquals(c, expected.charAt(0), "toHex formatting");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
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);
|
||||||
|
assertEquals(expected, i, "fromHexDigits");
|
||||||
|
assertEquals(actual.charAt(0), hex.toHighHexDigit((byte)i),
|
||||||
|
"first char mismatch");
|
||||||
|
assertEquals(actual.charAt(1), hex.toLowHexDigit((byte)i),
|
||||||
|
"second char mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testIsHexDigit() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
for (int i = 0; i < 0x3ff; i++) {
|
||||||
|
boolean actual = hex.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));
|
||||||
|
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);
|
||||||
|
expectThrows(NumberFormatException.class,
|
||||||
|
() -> hex.fromHexDigit(ch));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testAppendHexByteWithStringBuilder() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
sb.setLength(0);
|
||||||
|
StringBuilder sb1 = hex.toHexDigits(sb, (byte)i);
|
||||||
|
assertSame(sb1, sb, "toHexDigits returned different StringBuilder");
|
||||||
|
assertEquals(sb.length(), 2, "wrong length after append: " + i);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testAppendHexByteWithCharBuffer() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
CharBuffer cb = CharBuffer.allocate(256);
|
||||||
|
for (int i = 1; i <= 128; i++) {
|
||||||
|
CharBuffer cb1 = hex.toHexDigits(cb, (byte)i);
|
||||||
|
assertTrue(cb1 == cb);
|
||||||
|
assertEquals(cb.position(), i * 2);
|
||||||
|
}
|
||||||
|
assertEquals(cb.remaining(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testAppendHexByteWithCharArrayWriter() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
CharArrayWriter caw = new CharArrayWriter();
|
||||||
|
for (int i = 1; i <= 128; i++) {
|
||||||
|
CharArrayWriter caw1 = hex.toHexDigits(caw, (byte)i);
|
||||||
|
assertTrue(caw1 == caw);
|
||||||
|
assertEquals(caw.size(), i * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testFromHexPairInvalid() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
|
||||||
|
// An assortment of invalid characters
|
||||||
|
String chars = "-0--0-";
|
||||||
|
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)));
|
||||||
|
System.out.println(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "HexStringsThrowing")
|
||||||
|
static void testToBytesThrowing(String value, String sep, String prefix, String suffix) {
|
||||||
|
HexFormat hex = HexFormat.ofDelimiter(sep).withPrefix(prefix).withSuffix(suffix);
|
||||||
|
Throwable ex = expectThrows(IllegalArgumentException.class,
|
||||||
|
() -> {
|
||||||
|
byte[] v = hex.parseHex(value);
|
||||||
|
System.out.println("str: " + value + ", actual: " + v + ", bytes: " +
|
||||||
|
Arrays.toString(v));
|
||||||
|
});
|
||||||
|
System.out.println("ex: " + ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testFactoryNPE() {
|
||||||
|
assertThrows(NPE, () -> HexFormat.ofDelimiter(null));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().withDelimiter(null));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().withPrefix(null));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().withSuffix(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testFormatHexNPE() {
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().formatHex(null));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().formatHex(null, 0, 1));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().formatHex(null, null));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().formatHex(null, null, 0, 0));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().formatHex(sb, null));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().formatHex(sb, null, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testParseHexNPE() {
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().parseHex(null));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().parseHex((String)null, 0, 0));
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().parseHex((char[])null, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testToHexDigitsNPE() {
|
||||||
|
assertThrows(NPE, () -> HexFormat.of().toHexDigits(null, (byte)0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "BadParseHexThrowing")
|
||||||
|
static void badParseHex(String string, int offset, int length,
|
||||||
|
Class<? extends Throwable> exClass) {
|
||||||
|
assertThrows(exClass,
|
||||||
|
() -> HexFormat.of().parseHex(string, offset, length));
|
||||||
|
char[] chars = string.toCharArray();
|
||||||
|
assertThrows(exClass,
|
||||||
|
() -> HexFormat.of().parseHex(chars, offset, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "BadFromHexDigitsThrowing")
|
||||||
|
static void badFromHexDigits(String string, int fromIndex, int toIndex,
|
||||||
|
Class<? extends Throwable> exClass) {
|
||||||
|
assertThrows(exClass,
|
||||||
|
() -> HexFormat.of().fromHexDigits(string, fromIndex, toIndex));
|
||||||
|
assertThrows(exClass,
|
||||||
|
() -> HexFormat.of().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"));
|
||||||
|
assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> HexFormat.of().fromHexDigits("9876543210", 0, 9));
|
||||||
|
assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> HexFormat.of().fromHexDigitsToLong("98765432109876543210"));
|
||||||
|
assertThrows(IllegalArgumentException.class,
|
||||||
|
() -> HexFormat.of().fromHexDigitsToLong("98765432109876543210", 0, 17));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatter(String delimiter, String prefix, String suffix,
|
||||||
|
boolean uppercase,
|
||||||
|
HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
String res = hex.formatHex(expected);
|
||||||
|
assertTrue(res.startsWith(prefix), "Prefix not found");
|
||||||
|
assertTrue(res.endsWith(suffix), "Suffix not found");
|
||||||
|
int expectedLen = expected.length * (2 + prefix.length() +
|
||||||
|
delimiter.length() + suffix.length()) - delimiter.length();
|
||||||
|
assertEquals(res.length(), expectedLen, "String length");
|
||||||
|
|
||||||
|
if (expected.length > 1) {
|
||||||
|
// check prefix and suffix is present for each hex pair
|
||||||
|
for (int i = 0; i < expected.length; i++) {
|
||||||
|
int valueChars = prefix.length() + 2 + suffix.length();
|
||||||
|
int offset = i * (valueChars + delimiter.length());
|
||||||
|
String value = res.substring(offset, offset + valueChars);
|
||||||
|
assertTrue(value.startsWith(prefix), "wrong prefix");
|
||||||
|
assertTrue(value.endsWith(suffix), "wrong suffix");
|
||||||
|
|
||||||
|
// Check case of digits
|
||||||
|
String cc = value.substring(prefix.length(), prefix.length() + 2);
|
||||||
|
assertEquals(cc,
|
||||||
|
(uppercase) ? cc.toUpperCase(Locale.ROOT) : cc.toLowerCase(Locale.ROOT),
|
||||||
|
"Case mismatch");
|
||||||
|
if (i < expected.length - 1 && !delimiter.isEmpty()) {
|
||||||
|
// Check the delimiter is present for each pair except the last
|
||||||
|
assertEquals(res.substring(offset + valueChars,
|
||||||
|
offset + valueChars + delimiter.length()), delimiter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatHexString(String unused1, String unused2, String unused3,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
String s = hex.formatHex(expected);
|
||||||
|
System.out.println(" formatted: " + s);
|
||||||
|
|
||||||
|
byte[] actual = hex.parseHex(s);
|
||||||
|
System.out.println(" parsed as: " + Arrays.toString(actual));
|
||||||
|
int mismatch = Arrays.mismatch(expected, actual);
|
||||||
|
assertEquals(actual, expected, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testParseHexStringRange(String delimiter, String prefix, String suffix,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
String s = hex.formatHex(expected);
|
||||||
|
|
||||||
|
// Parse values 2, 3, 4 from the generated string
|
||||||
|
int low = 2;
|
||||||
|
int high = 5;
|
||||||
|
int stride = prefix.length() + 2 + suffix.length() + delimiter.length();
|
||||||
|
System.out.println(" formatted subrange: " +
|
||||||
|
s.substring(low * stride, high * stride - delimiter.length()));
|
||||||
|
byte[] actual = hex.parseHex(s, low * stride,
|
||||||
|
high * stride - delimiter.length());
|
||||||
|
System.out.println(" parsed as: " + Arrays.toString(actual));
|
||||||
|
|
||||||
|
assertEquals(actual.length, (high - low), "array length");
|
||||||
|
int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);
|
||||||
|
assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testParseHexEmptyString(String delimiter, String prefix, String suffix,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] actual = hex.parseHex("");
|
||||||
|
assertEquals(actual.length, 0, "empty string parse");
|
||||||
|
actual = hex.parseHex("abc", 0, 0);
|
||||||
|
assertEquals(actual.length, 0, "empty string range parse");
|
||||||
|
actual = hex.parseHex(new char[1], 0, 0);
|
||||||
|
assertEquals(actual.length, 0, "empty char array subrange empty parse");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatHexRangeString(String unused1, String unused2, String unused3,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
int low = 1;
|
||||||
|
int high = expected.length - 2;
|
||||||
|
String s = hex.formatHex(expected, low, high);
|
||||||
|
System.out.println(" formatted: " + s);
|
||||||
|
|
||||||
|
byte[] actual = hex.parseHex(s);
|
||||||
|
System.out.println(" parsed as: " + Arrays.toString(actual));
|
||||||
|
int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);
|
||||||
|
assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatHexAppendable(String unused1, String unused2, String unused3,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StringBuilder s = hex.formatHex(sb, expected);
|
||||||
|
assertEquals(s, sb, "formatHex returned unknown StringBuilder");
|
||||||
|
System.out.println(" formatted: " + s);
|
||||||
|
|
||||||
|
byte[] actual = hex.parseHex(s.toString());
|
||||||
|
System.out.println(" parsed as: " + Arrays.toString(actual));
|
||||||
|
int mismatch = Arrays.mismatch(expected, actual);
|
||||||
|
assertEquals(actual, expected, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatHexRangeAppendable(String unused1, String unused2, String unused3,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
int low = 1;
|
||||||
|
int high = expected.length - 2;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StringBuilder s = hex.formatHex(sb, expected, low, high);
|
||||||
|
assertEquals(s, sb, "formatHex returned unknown StringBuilder");
|
||||||
|
System.out.println(" formatted: " + s);
|
||||||
|
|
||||||
|
byte[] actual = hex.parseHex(s.toString());
|
||||||
|
System.out.println(" parsed as: " + Arrays.toString(actual));
|
||||||
|
byte[] sub = Arrays.copyOfRange(expected, low, high);
|
||||||
|
System.out.println("actual: " + Arrays.toString(actual));
|
||||||
|
System.out.println("sub : " + Arrays.toString(sub));
|
||||||
|
int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);
|
||||||
|
|
||||||
|
assertEquals(actual, sub, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatHexCharArray(String unused1, String unused2, String unused3,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
String s = hex.formatHex(expected);
|
||||||
|
System.out.println(" formatted: " + s);
|
||||||
|
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
byte[] actual = hex.parseHex(chars, 0, chars.length);
|
||||||
|
System.out.println(" parsed as: " + Arrays.toString(actual));
|
||||||
|
int mismatch = Arrays.mismatch(expected, actual);
|
||||||
|
assertEquals(actual, expected, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatHexCharArrayIndexed(String delimiter, String prefix, String suffix,
|
||||||
|
boolean unused4, HexFormat hex) {
|
||||||
|
byte[] expected = genBytes('A', 15);
|
||||||
|
String s = hex.formatHex(expected);
|
||||||
|
System.out.println(" formatted: " + s);
|
||||||
|
|
||||||
|
|
||||||
|
// Parse values 2, 3, 4 from the generated string
|
||||||
|
int low = 2;
|
||||||
|
int high = 5;
|
||||||
|
int stride = prefix.length() + 2 + suffix.length() + delimiter.length();
|
||||||
|
System.out.println(" formatted subrange: " +
|
||||||
|
s.substring(low * stride, high * stride - delimiter.length()));
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
byte[] actual = hex.parseHex(chars, low * stride,
|
||||||
|
high * stride - delimiter.length());
|
||||||
|
System.out.println(" parsed as: " + Arrays.toString(actual));
|
||||||
|
|
||||||
|
assertEquals(actual.length, (high - low), "array length");
|
||||||
|
int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);
|
||||||
|
assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatterToString(String delimiter, String prefix, String suffix,
|
||||||
|
boolean uppercase,
|
||||||
|
HexFormat hex) {
|
||||||
|
String actual = String.format(
|
||||||
|
"uppercase: %s, delimiter: \"%s\", prefix: \"%s\", suffix: \"%s\"",
|
||||||
|
uppercase, escapeNL(delimiter), escapeNL(prefix), escapeNL(suffix));
|
||||||
|
System.out.println(" hex: " + actual);
|
||||||
|
assertEquals(actual, hex.toString(), "Formatter toString mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatterParameterMethods(String delimiter, String prefix, String suffix,
|
||||||
|
boolean uppercase,
|
||||||
|
HexFormat hex) {
|
||||||
|
assertEquals(hex.delimiter(), delimiter);
|
||||||
|
assertEquals(hex.prefix(), prefix);
|
||||||
|
assertEquals(hex.suffix(), suffix);
|
||||||
|
assertEquals(hex.isUpperCase(), uppercase);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testFormatterTestEquals(String delimiter, String prefix, String suffix,
|
||||||
|
boolean uppercase,
|
||||||
|
HexFormat expected) {
|
||||||
|
HexFormat actual = HexFormat.of()
|
||||||
|
.withDelimiter(delimiter)
|
||||||
|
.withPrefix(prefix)
|
||||||
|
.withSuffix(suffix);
|
||||||
|
actual = uppercase ? actual.withUpperCase() : actual.withLowerCase();
|
||||||
|
|
||||||
|
assertEquals(actual.delimiter(), delimiter, "delimiter");
|
||||||
|
assertEquals(actual.prefix(), prefix, "prefix");
|
||||||
|
assertEquals(actual.suffix(), suffix, "suffix");
|
||||||
|
assertEquals(actual.isUpperCase(), uppercase, "uppercase");
|
||||||
|
assertTrue(actual.equals(expected), "equals method");
|
||||||
|
assertEquals(actual.hashCode(), expected.hashCode(), "hashCode");
|
||||||
|
|
||||||
|
assertTrue(actual.equals(actual)); // equals self
|
||||||
|
assertFalse(actual.equals(null)); // never equals null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testZeroLength(String delimiter, String prefix, String suffix, boolean uppercase,
|
||||||
|
HexFormat hex) {
|
||||||
|
// Test formatting of zero length byte arrays, should produce no output
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
assertEquals(hex.formatHex(new byte[0]), "", "Zero length");
|
||||||
|
assertEquals(hex.formatHex(new byte[0], 0, 0), "", "Zero length");
|
||||||
|
|
||||||
|
hex.formatHex(sb, new byte[0]);
|
||||||
|
assertEquals(sb.length(), 0, "length should not change");
|
||||||
|
hex.formatHex(sb, new byte[0], 0, 0);
|
||||||
|
assertEquals(sb.length(), 0, "length should not change");
|
||||||
|
|
||||||
|
}
|
||||||
|
private static String escapeNL(String string) {
|
||||||
|
return string.replace("\n", "\\n")
|
||||||
|
.replace("\r", "\\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testfromHexDigitsToInt() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
|
||||||
|
String allHex = "76543210";
|
||||||
|
final int orig = 0x76543210;
|
||||||
|
for (int digits = 0; digits <= 8; digits++) {
|
||||||
|
String s = hex.toHexDigits(orig, digits);
|
||||||
|
long actual = hex.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));
|
||||||
|
long expected = (digits < 8) ? orig & ~(0xffffffff << (4 * digits)) : orig;
|
||||||
|
assertEquals(actual, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testfromHexDigitsToLong() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
|
||||||
|
String allHex = "fedcba9876543210";
|
||||||
|
final long orig = 0xfedcba9876543210L;
|
||||||
|
for (int digits = 0; digits <= 16; digits++) {
|
||||||
|
String s = hex.toHexDigits(orig, digits);
|
||||||
|
long actual = hex.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));
|
||||||
|
long expected = (digits < 16) ? orig & ~(0xffffffffffffffffL << (4 * digits)) : orig;
|
||||||
|
assertEquals(actual, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
static void testToHexDigitsLong() {
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
|
||||||
|
String allHex = "fedcba9876543210";
|
||||||
|
final long expected = 0xfedcba9876543210L;
|
||||||
|
String s = hex.toHexDigits(expected);
|
||||||
|
long actual = hex.fromHexDigitsToLong(s);
|
||||||
|
System.out.printf(" formatted: \"%s\", parsed as: 0x%016xL%n", s, actual);
|
||||||
|
assertEquals(s, allHex);
|
||||||
|
assertEquals(actual, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testIOException(String delimiter, String prefix, String suffix, boolean uppercase,
|
||||||
|
HexFormat hex) {
|
||||||
|
Appendable throwingAppendable = new ThrowingAppendable();
|
||||||
|
assertThrows(UncheckedIOException.class,
|
||||||
|
() -> hex.formatHex(throwingAppendable, new byte[1]));
|
||||||
|
assertThrows(UncheckedIOException.class,
|
||||||
|
() -> hex.formatHex(throwingAppendable, new byte[1], 0, 1));
|
||||||
|
assertThrows(UncheckedIOException.class,
|
||||||
|
() -> hex.toHexDigits(throwingAppendable, (byte)1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider="HexFormattersParsers")
|
||||||
|
static void testOOME(String delimiter, String prefix, String suffix, boolean uppercase,
|
||||||
|
HexFormat hex) {
|
||||||
|
// compute the size of byte array that will exceed the buffer
|
||||||
|
long valueChars = prefix.length() + 2 + suffix.length();
|
||||||
|
long stride = valueChars + delimiter.length();
|
||||||
|
long max = Integer.MAX_VALUE & 0xFFFFFFFFL;
|
||||||
|
long len = max / stride;
|
||||||
|
long remainder = max - ((len - 1) * stride);
|
||||||
|
if (remainder > valueChars) {
|
||||||
|
len++;
|
||||||
|
remainder -= valueChars;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] bytes = new byte[(int) len];
|
||||||
|
Throwable ex = expectThrows(OutOfMemoryError.class,
|
||||||
|
() -> hex.formatHex(bytes));
|
||||||
|
System.out.println("ex: " + ex);
|
||||||
|
} catch (OutOfMemoryError oome) {
|
||||||
|
System.out.printf("OOME: total mem: %08x, free mem: %08x, max mem: %08x%n",
|
||||||
|
Runtime.getRuntime().totalMemory(),
|
||||||
|
Runtime.getRuntime().freeMemory(),
|
||||||
|
Runtime.getRuntime().maxMemory());
|
||||||
|
throw oome;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example code from the HexFormat javadoc.
|
||||||
|
* Showing simple usage of the API using "assert" to express the correct results
|
||||||
|
* when shown in the javadoc.
|
||||||
|
* The additional TestNG asserts verify the correctness of the same code.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
private static void samples() {
|
||||||
|
{
|
||||||
|
// Primitive formatting and parsing.
|
||||||
|
HexFormat hex = HexFormat.of();
|
||||||
|
|
||||||
|
byte b = 127;
|
||||||
|
String byteStr = hex.toHexDigits(b);
|
||||||
|
System.out.println(" " + byteStr);
|
||||||
|
|
||||||
|
byte byteVal = (byte)hex.fromHexDigits(byteStr);
|
||||||
|
assert(byteStr.equals("7f"));
|
||||||
|
assert(b == byteVal);
|
||||||
|
assertTrue(byteStr.equals("7f"));
|
||||||
|
assertTrue(b == byteVal);
|
||||||
|
|
||||||
|
|
||||||
|
char c = 'A';
|
||||||
|
String charStr = hex.toHexDigits(c);
|
||||||
|
System.out.println(" " + charStr);
|
||||||
|
int charVal = hex.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);
|
||||||
|
assert(i == intVal);
|
||||||
|
assertTrue(i == intVal);
|
||||||
|
|
||||||
|
long l = Long.MAX_VALUE;
|
||||||
|
String longStr = hex.toHexDigits(l, 16);
|
||||||
|
long longVal = hex.fromHexDigitsToLong(longStr, 0, 16);
|
||||||
|
System.out.println(" " + longStr + ", " + longVal);
|
||||||
|
assert(l == longVal);
|
||||||
|
assertTrue(l == longVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// RFC 4752 Fingerprint
|
||||||
|
HexFormat formatFingerprint = HexFormat.ofDelimiter(":").withUpperCase();
|
||||||
|
byte[] bytes = {0, 1, 2, 3, 124, 125, 126, 127};
|
||||||
|
String str = formatFingerprint.formatHex(bytes);
|
||||||
|
System.out.println(" Formatted: " + str);
|
||||||
|
|
||||||
|
byte[] parsed = formatFingerprint.parseHex(str);
|
||||||
|
System.out.println(" Parsed: " + Arrays.toString(parsed));
|
||||||
|
assert(Arrays.equals(bytes, parsed));
|
||||||
|
assertTrue(Arrays.equals(bytes, parsed));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Comma separated formatting
|
||||||
|
HexFormat commaFormat = HexFormat.ofDelimiter(",");
|
||||||
|
byte[] bytes = {0, 1, 2, 3, 124, 125, 126, 127};
|
||||||
|
String str = commaFormat.formatHex(bytes);
|
||||||
|
System.out.println(" Formatted: " + str);
|
||||||
|
|
||||||
|
byte[] parsed = commaFormat.parseHex(str);
|
||||||
|
System.out.println(" Parsed: " + Arrays.toString(parsed));
|
||||||
|
assert(Arrays.equals(bytes, parsed));
|
||||||
|
assertTrue(Arrays.equals(bytes, parsed));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Text formatting
|
||||||
|
HexFormat commaFormat = HexFormat.ofDelimiter(", ").withPrefix("#");
|
||||||
|
byte[] bytes = {0, 1, 2, 3, 124, 125, 126, 127};
|
||||||
|
String str = commaFormat.formatHex(bytes);
|
||||||
|
System.out.println(" Formatted: " + str);
|
||||||
|
|
||||||
|
byte[] parsed = commaFormat.parseHex(str);
|
||||||
|
System.out.println(" Parsed: " + Arrays.toString(parsed));
|
||||||
|
assert(Arrays.equals(bytes, parsed));
|
||||||
|
assertTrue(Arrays.equals(bytes, parsed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test implementation of Appendable that throws IOException on all methods.
|
||||||
|
*/
|
||||||
|
static class ThrowingAppendable implements Appendable {
|
||||||
|
@Override
|
||||||
|
public Appendable append(CharSequence csq) throws IOException {
|
||||||
|
throw new IOException(".append(CharSequence) always throws");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appendable append(CharSequence csq, int start, int end) throws IOException {
|
||||||
|
throw new IOException(".append(CharSequence, start, end) always throws");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appendable append(char c) throws IOException {
|
||||||
|
throw new IOException(".append(char) always throws");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -33,36 +33,11 @@ import java.text.*;
|
|||||||
|
|
||||||
public class ThaiGov {
|
public class ThaiGov {
|
||||||
|
|
||||||
char[] hex = {'0', '1', '2', '3',
|
|
||||||
'4', '5', '6', '7',
|
|
||||||
'8', '9', 'A', 'B',
|
|
||||||
'C', 'D', 'E', 'F'};
|
|
||||||
|
|
||||||
ThaiGov() {
|
ThaiGov() {
|
||||||
System.out.println("ThaiGov locale test...");
|
System.out.println("ThaiGov locale test...");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String toHex(String str) {
|
|
||||||
StringBuffer buff = new StringBuffer();
|
|
||||||
int y=0;
|
|
||||||
for(int x=0; x < str.length(); ++x) {
|
|
||||||
buff.append("\\u");
|
|
||||||
buff.append(toHex(str.charAt(x)));
|
|
||||||
}
|
|
||||||
return buff.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String toHex(char ch) {
|
|
||||||
StringBuffer buff = new StringBuffer();
|
|
||||||
buff.append(hex[ch>>12]);
|
|
||||||
buff.append(hex[(ch>>8) & 0x0F]);
|
|
||||||
buff.append(hex[(ch>>4) & 0x0F]);
|
|
||||||
buff.append(hex[ch & 0x0F]);
|
|
||||||
return buff.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void numberTest() throws RuntimeException {
|
void numberTest() throws RuntimeException {
|
||||||
final String strExpected = "\u0E51\u0E52\u002C\u0E53\u0E54\u0E55\u002C\u0E56\u0E57\u0E58\u002E\u0E52\u0E53\u0E54";
|
final String strExpected = "\u0E51\u0E52\u002C\u0E53\u0E54\u0E55\u002C\u0E56\u0E57\u0E58\u002E\u0E52\u0E53\u0E54";
|
||||||
final double value = 12345678.234;
|
final double value = 12345678.234;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user