src/java.base/share/classes/java/lang/Integer.java

Print this page

        

@@ -27,10 +27,14 @@
 
 import java.lang.annotation.Native;
 import java.util.Objects;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+
 /**
  * The {@code Integer} class wraps a value of the primitive type
  * {@code int} in an object. An object of type {@code Integer}
  * contains a single field whose type is {@code int}.
  *

@@ -136,29 +140,51 @@
         /* Use the faster version */
         if (radix == 10) {
             return toString(i);
         }
 
-        char buf[] = new char[33];
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[33];
         boolean negative = (i < 0);
         int charPos = 32;
 
         if (!negative) {
             i = -i;
         }
 
         while (i <= -radix) {
-            buf[charPos--] = digits[-(i % radix)];
+                buf[charPos--] = (byte)digits[-(i % radix)];
             i = i / radix;
         }
-        buf[charPos] = digits[-i];
+            buf[charPos] = (byte)digits[-i];
 
         if (negative) {
             buf[--charPos] = '-';
         }
 
-        return new String(buf, charPos, (33 - charPos));
+            return StringLatin1.newString(buf, charPos, (33 - charPos));
+        }
+        return toStringUTF16(i, radix);
+    }
+
+    private static String toStringUTF16(int i, int radix) {
+        byte[] buf = new byte[33 * 2];
+        boolean negative = (i < 0);
+        int charPos = 32;
+        if (!negative) {
+            i = -i;
+        }
+        while (i <= -radix) {
+            StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
+            i = i / radix;
+        }
+        StringUTF16.putChar(buf, charPos, digits[-i]);
+
+        if (negative) {
+            StringUTF16.putChar(buf, --charPos, '-');
+        }
+        return StringUTF16.newString(buf, charPos, (33 - charPos));
     }
 
     /**
      * Returns a string representation of the first argument as an
      * unsigned integer value in the radix specified by the second

@@ -310,16 +336,20 @@
      */
     private static String toUnsignedString0(int val, int shift) {
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-        char[] buf = new char[chars];
 
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[chars];
         formatUnsignedInt(val, shift, buf, 0, chars);
-
-        // Use special constructor which takes over "buf".
-        return new String(buf, true);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[chars * 2];
+            formatUnsignedIntUTF16(val, shift, buf, 0, chars);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
      * Format an {@code int} (treated as unsigned) into a character buffer. If
      * {@code len} exceeds the formatted ASCII representation of {@code val},

@@ -342,10 +372,32 @@
             buf[--charPos] = Integer.digits[val & mask];
             val >>>= shift;
         } while (charPos > offset);
     }
 
+    /** byte[]/LATIN1 version    */
+    static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            buf[--charPos] = (byte)Integer.digits[val & mask];
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
+    /** byte[]/UTF16 version    */
+    static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
     static final char [] DigitTens = {
         '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
         '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
         '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
         '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',

@@ -399,13 +451,19 @@
     @HotSpotIntrinsicCandidate
     public static String toString(int i) {
         if (i == Integer.MIN_VALUE)
             return "-2147483648";
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-        char[] buf = new char[size];
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[size];
         getChars(i, size, buf);
-        return new String(buf, true);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[size * 2];
+            getCharsUTF16(i, size, buf);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
      * Returns a string representation of the argument as an unsigned
      * decimal value.

@@ -431,11 +489,45 @@
      * digit at the specified index (exclusive), and working
      * backwards from there.
      *
      * Will fail if i == Integer.MIN_VALUE
      */
-    static void getChars(int i, int index, char[] buf) {
+    static void getChars(int i, int index, byte[] buf) {
+        int q, r;
+        int charPos = index;
+        char sign = 0;
+
+        if (i < 0) {
+            sign = '-';
+            i = -i;
+        }
+
+        // Generate two digits per iteration
+        while (i >= 65536) {
+            q = i / 100;
+        // really: r = i - (q * 100);
+            r = i - ((q << 6) + (q << 5) + (q << 2));
+            i = q;
+            buf [--charPos] = (byte)DigitOnes[r];
+            buf [--charPos] = (byte)DigitTens[r];
+        }
+
+        // Fall thru to fast mode for smaller numbers
+        // assert(i <= 65536, i);
+        for (;;) {
+            q = (i * 52429) >>> (16+3);
+            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
+            buf [--charPos] = (byte)digits [r];
+            i = q;
+            if (i == 0) break;
+        }
+        if (sign != 0) {
+            buf [--charPos] = (byte)sign;
+        }
+    }
+
+    static void getCharsUTF16(int i, int index, byte[] buf) {
         int q, r;
         int charPos = index;
         char sign = 0;
 
         if (i < 0) {

@@ -447,25 +539,25 @@
         while (i >= 65536) {
             q = i / 100;
         // really: r = i - (q * 100);
             r = i - ((q << 6) + (q << 5) + (q << 2));
             i = q;
-            buf [--charPos] = DigitOnes[r];
-            buf [--charPos] = DigitTens[r];
+            StringUTF16.putChar(buf, --charPos, DigitOnes[r]);
+            StringUTF16.putChar(buf, --charPos, DigitTens[r]);
         }
 
         // Fall thru to fast mode for smaller numbers
         // assert(i <= 65536, i);
         for (;;) {
             q = (i * 52429) >>> (16+3);
             r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
-            buf [--charPos] = digits [r];
+            StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
             i = q;
             if (i == 0) break;
         }
         if (sign != 0) {
-            buf [--charPos] = sign;
+            StringUTF16.putChar(buf, --charPos, sign);
         }
     }
 
     static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                       99999999, 999999999, Integer.MAX_VALUE };