--- old/src/share/classes/java/lang/Integer.java 2014-06-14 22:28:12.422675612 +0400 +++ new/src/share/classes/java/lang/Integer.java 2014-06-14 22:28:11.878410451 +0400 @@ -227,6 +227,7 @@ * represented by the argument in hexadecimal (base 16). * @see #parseUnsignedInt(String, int) * @see #toUnsignedString(int, int) + * @see #toHexString(int, int) * @since 1.0.2 */ public static String toHexString(int i) { @@ -235,6 +236,56 @@ /** * Returns a string representation of the integer argument as an + * unsigned integer in base 16, padded with leading zeroes if + * necessary. + * + *

The unsigned integer value is the argument plus 232 + * if the argument is negative; otherwise, it is equal to the + * argument. This value is converted to a string of ASCII digits + * in hexadecimal (base 16) with possibly appended leading + * zeroes. A minimum amount of zeroes is appended to ensure + * the length of the resulting string is at least {@code minWidth}. + * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Integer#parseUnsignedInt(String, int) + * Integer.parseUnsignedInt(s, 16)}. + * + *

If the unsigned magnitude is zero, it is represented by a + * {@code minWidth} zero characters {@code '0'} ({@code '\u005Cu0030'}). + * The following characters are used as hexadecimal digits: + * + *

+ * {@code 0123456789abcdef} + *
+ * + * These are the characters {@code '\u005Cu0030'} through + * {@code '\u005Cu0039'} and {@code '\u005Cu0061'} through + * {@code '\u005Cu0066'}. If uppercase letters are + * desired, the {@link java.lang.String#toUpperCase()} method may + * be called on the result: + * + *
+ * {@code Integer.toHexString(n, 6).toUpperCase()} + *
+ * + * @param i an integer to be converted to a string. + * @param minWidth a minimum required length of the resulting string. + * @return the string representation of the unsigned integer value + * represented by the argument in hexadecimal (base 16), + * padded with leading zeroes if necessary. + * @see #parseUnsignedInt(String, int) + * @see #toUnsignedString(int, int) + * @see #toHexString(int) + * @since 1.9 + */ + public static String toHexString(int i, int minWidth) { + return toUnsignedString0(i, 4, minWidth); + } + + + /** + * Returns a string representation of the integer argument as an * unsigned integer in base 8. * *

The unsigned integer value is the argument plus 232 @@ -304,7 +355,9 @@ } /** - * Convert the integer to an unsigned number. + * Format an integer (treated as unsigned) into a String. + * @param val the value to format + * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) */ private static String toUnsignedString0(int val, int shift) { // assert shift > 0 && shift <=5 : "Illegal shift value"; @@ -319,7 +372,29 @@ } /** - * Format a long (treated as unsigned) into a character buffer. + * Format an integer (treated as unsigned) into a String. + * @param val the value to format + * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) + * @param minWidth the minimum width of the produced String + */ + private static String toUnsignedString0(int val, int shift, int minWidth) { + // assert shift > 0 && shift <=5 : "Illegal shift value"; + int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val); + int magLen = (mag + (shift - 1)) / shift; + int zeroes = Math.max(Math.max(minWidth, 1) - magLen, 0); + char[] buf = new char[magLen + zeroes]; + + for (int i = 0; i < zeroes; ++i) + buf[i] = '0'; + if (magLen > 0) + formatUnsignedInt(val, shift, buf, zeroes, magLen); + + // Use special constructor which takes over "buf". + return new String(buf, true); + } + + /** + * Format an integer (treated as unsigned) into a character buffer. * @param val the unsigned int to format * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) * @param buf the character buffer to write to --- old/src/share/classes/java/lang/Long.java 2014-06-14 22:28:14.263572481 +0400 +++ new/src/share/classes/java/lang/Long.java 2014-06-14 22:28:13.831361912 +0400 @@ -266,6 +266,7 @@ * (base 16). * @see #parseUnsignedLong(String, int) * @see #toUnsignedString(long, int) + * @see #toHexString(long, int) * @since 1.0.2 */ public static String toHexString(long i) { @@ -274,6 +275,56 @@ /** * Returns a string representation of the {@code long} + * argument as an unsigned integer in base 16, padded with + * leading zeroes if necessary. + * + *

The unsigned {@code long} value is the argument plus + * 264 if the argument is negative; otherwise, it is + * equal to the argument. This value is converted to a string of + * ASCII digits in hexadecimal (base 16) with possibly + * appended leading zeroes. A minimum amount of zeroes is appended + * to ensure the length of the resulting string is at least + * {@code minWidth}. + * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, + * 16)}. + * + *

If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} ({@code '\u005Cu0030'}). + * The following characters are used as hexadecimal digits: + * + *

+ * {@code 0123456789abcdef} + *
+ * + * These are the characters {@code '\u005Cu0030'} through + * {@code '\u005Cu0039'} and {@code '\u005Cu0061'} through + * {@code '\u005Cu0066'}. If uppercase letters are desired, + * the {@link java.lang.String#toUpperCase()} method may be called + * on the result: + * + *
+ * {@code Long.toHexString(n, 12).toUpperCase()} + *
+ * + * @param i a {@code long} to be converted to a string. + * @param minWidth a minimum required length of the resulting string. + * @return the string representation of the unsigned {@code long} + * value represented by the argument in hexadecimal + * (base 16), padded with leading zeroes if necessary. + * @see #parseUnsignedLong(String, int) + * @see #toUnsignedString(long, int) + * @see #toHexString(long) + * @since 1.9 + */ + public static String toHexString(long i, int minWidth) { + return toUnsignedString0(i, 4, minWidth); + } + + /** + * Returns a string representation of the {@code long} * argument as an unsigned integer in base 8. * *

The unsigned {@code long} value is the argument plus @@ -359,6 +410,25 @@ return new String(buf, true); } + /** + * Format a long (treated as unsigned) into a String. + * @param val the value to format + * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) + * @param minWidth the minimum width of the produced String + */ + static String toUnsignedString0(long val, int shift, int minWidth) { + int mag = Long.SIZE - Long.numberOfLeadingZeros(val); + int magLen = (mag + (shift - 1)) / shift; + int zeroes = Math.max(Math.max(minWidth, 1) - magLen, 0); + char[] buf = new char[magLen + zeroes]; + + for (int i = 0; i < zeroes; ++i) + buf[i] = '0'; + if (magLen > 0) + formatUnsignedLong(val, shift, buf, zeroes, magLen); + return new String(buf, true); + } + /** * Format a long (treated as unsigned) into a character buffer. * @param val the unsigned long to format --- old/src/share/classes/java/util/UUID.java 2014-06-14 22:28:16.080457652 +0400 +++ new/src/share/classes/java/util/UUID.java 2014-06-14 22:28:15.592219785 +0400 @@ -373,17 +373,11 @@ * @return A string representation of this {@code UUID} */ public String toString() { - return (digits(mostSigBits >> 32, 8) + "-" + - digits(mostSigBits >> 16, 4) + "-" + - digits(mostSigBits, 4) + "-" + - digits(leastSigBits >> 48, 4) + "-" + - digits(leastSigBits, 12)); - } - - /** Returns val represented by the specified number of hex digits. */ - private static String digits(long val, int digits) { - long hi = 1L << (digits * 4); - return Long.toHexString(hi | (val & (hi - 1))).substring(1); + return Long.toHexString((mostSigBits >>> 32) & 0xFFFFFFFFL, 8) + '-' + + Long.toHexString((mostSigBits >>> 16) & 0xFFFFL, 4) + '-' + + Long.toHexString( mostSigBits & 0xFFFFL, 4) + '-' + + Long.toHexString((leastSigBits >>> 48) & 0xFFFFL, 4) + '-' + + Long.toHexString( leastSigBits & 0xFFFFFFFFFFFFL, 12); } /** --- old/src/share/classes/sun/security/pkcs11/wrapper/Functions.java 2014-06-14 22:28:17.873331123 +0400 +++ new/src/share/classes/sun/security/pkcs11/wrapper/Functions.java 2014-06-14 22:28:17.405103006 +0400 @@ -54,7 +54,7 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; /** - * This class contains onyl static methods. It is the place for all functions + * This class contains only static methods. It is the place for all functions * that are used by several classes in this package. * * @author Karl Scheibelhofer @@ -96,11 +96,6 @@ /** - * For converting numbers to their hex presentation. - */ - private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); - - /** * Converts a long value to a hexadecimal String of length 16. Includes * leading zeros if necessary. * @@ -108,15 +103,8 @@ * @return The hexadecimal string representation of the long value. */ public static String toFullHexString(long value) { - long currentValue = value; - StringBuffer stringBuffer = new StringBuffer(16); - for(int j = 0; j < 16; j++) { - int currentDigit = (int) currentValue & 0xf; - stringBuffer.append(HEX_DIGITS[currentDigit]); - currentValue >>>= 4; - } - - return stringBuffer.reverse().toString(); + return Long.toHexString(value, 16) + .toUpperCase(); } /** @@ -127,15 +115,8 @@ * @return The hexadecimal string representation of the int value. */ public static String toFullHexString(int value) { - int currentValue = value; - StringBuffer stringBuffer = new StringBuffer(8); - for(int i = 0; i < 8; i++) { - int currentDigit = currentValue & 0xf; - stringBuffer.append(HEX_DIGITS[currentDigit]); - currentValue >>>= 4; - } - - return stringBuffer.reverse().toString(); + return Integer.toHexString(value, 8) + .toUpperCase(); } /** @@ -161,20 +142,11 @@ return null; } - StringBuffer buffer = new StringBuffer(2 * value.length); - int single; - - for (int i = 0; i < value.length; i++) { - single = value[i] & 0xFF; - - if (single < 0x10) { - buffer.append('0'); - } - - buffer.append(Integer.toString(single, 16)); + StringBuilder sb = new StringBuilder(2 * value.length); + for (byte b : value) { + sb.append(Integer.toHexString((int)b & 0xFF, 2)); } - - return buffer.toString(); + return sb.toString(); } /** --- old/test/java/lang/ToString.java 2014-06-14 22:28:19.586165598 +0400 +++ new/test/java/lang/ToString.java 2014-06-14 22:28:18.989875092 +0400 @@ -23,7 +23,7 @@ /* * @test - * @bug 4031762 + * @bug 4031762 8042990 * @summary Test the primitive wrappers static toString() */ @@ -100,5 +100,22 @@ throw new RuntimeException("Double wrapper toString() failure."); } + // unsigned hex int + for(int x=0; x<100; x++) { + int i = generator.nextInt(); + int w = 1 + generator.nextInt(9); + String s = String.format("%0" + w + "x", i); + if (!s.equals(Integer.toHexString(i, w))) + throw new RuntimeException("Integer wrapper toHexString() failed for " + i + "."); + } + + // unsigned hex long + for(int x=0; x<100; x++) { + long l = generator.nextLong(); + int w = 1 + generator.nextInt(19); + String s = String.format("%0" + w + "x", l); + if (!s.equals(Long.toHexString(l, w))) + throw new RuntimeException("Long wrapper toHexString() failed for " + l + "."); + } } } --- /dev/null 2014-06-14 21:43:26.723864616 +0400 +++ new/test/sun/security/pkcs11/wrapper/TestFun.java 2014-06-14 22:28:20.454588688 +0400 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * @test + * @bug 8042990 + * @summary Testing some auxilary functions from the + * sun.security.pkcs11.wrapper package + */ + +import java.util.Arrays; +import java.util.Random; +import sun.security.pkcs11.wrapper.Functions; + +public class TestFun { + private static final Random random = new Random(); + + public static void main(String[] args) throws Throwable { + for (int i = 0; i != 128; ++i) { + long longVal = random.nextLong(); + String s1 = Functions.toFullHexString(longVal); + String s2 = String.format("%016X", longVal); + if (! s1.equals(s2)) + throw new RuntimeException("Hex representations of " + + longVal + " aren't equal: '" + s1 + "' != '" + + s2 + "'"); + + int intVal = random.nextInt(); + String s3 = Functions.toFullHexString(intVal); + String s4 = String.format("%08X", intVal); + if (! s3.equals(s4)) + throw new RuntimeException("Hex representations of " + + intVal + " aren't equal: '" + s3 + "' != '" + + s4 + "'"); + + byte[] bytes = new byte[random.nextInt(32)]; + String s5 = Functions.toHexString(bytes); + String s6 = ""; + for (byte b : bytes) + s6 += String.format("%02x", (int)b & 0xff); + if (! s5.equals(s6)) + throw new RuntimeException("Hex representations of " + + Arrays.asList(bytes) + " aren't equal: '" + s5 + + "' != '" + s6 + "'"); + } + } +}