1 /*
2 * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
142 i = i / radix;
143 }
144 buf[charPos] = (byte)Integer.digits[(int)(-i)];
145
146 if (negative) {
147 buf[--charPos] = '-';
148 }
149 return StringLatin1.newString(buf, charPos, (65 - charPos));
150 }
151 return toStringUTF16(i, radix);
152 }
153
154 private static String toStringUTF16(long i, int radix) {
155 byte[] buf = new byte[65 * 2];
156 int charPos = 64;
157 boolean negative = (i < 0);
158 if (!negative) {
159 i = -i;
160 }
161 while (i <= -radix) {
162 StringUTF16.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]);
163 i = i / radix;
164 }
165 StringUTF16.putChar(buf, charPos, Integer.digits[(int)(-i)]);
166 if (negative) {
167 StringUTF16.putChar(buf, --charPos, '-');
168 }
169 return StringUTF16.newString(buf, charPos, (65 - charPos));
170 }
171
172 /**
173 * Returns a string representation of the first argument as an
174 * unsigned integer value in the radix specified by the second
175 * argument.
176 *
177 * <p>If the radix is smaller than {@code Character.MIN_RADIX}
178 * or larger than {@code Character.MAX_RADIX}, then the radix
179 * {@code 10} is used instead.
180 *
181 * <p>Note that since the first argument is treated as an unsigned
182 * value, no leading sign character is printed.
183 *
184 * <p>If the magnitude is zero, it is represented by a single zero
185 * character {@code '0'} ({@code '\u005Cu0030'}); otherwise,
186 * the first character of the representation of the magnitude will
187 * not be the zero character.
397 *
398 * @param val the unsigned long to format
399 * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary)
400 * @param buf the character buffer to write to
401 * @param offset the offset in the destination buffer to start at
402 * @param len the number of characters to write
403 */
404
405 /** byte[]/LATIN1 version */
406 static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) {
407 int charPos = offset + len;
408 int radix = 1 << shift;
409 int mask = radix - 1;
410 do {
411 buf[--charPos] = (byte)Integer.digits[((int) val) & mask];
412 val >>>= shift;
413 } while (charPos > offset);
414 }
415
416 /** byte[]/UTF16 version */
417 static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
418 int charPos = offset + len;
419 int radix = 1 << shift;
420 int mask = radix - 1;
421 do {
422 StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]);
423 val >>>= shift;
424 } while (charPos > offset);
425 }
426
427 static String fastUUID(long lsb, long msb) {
428 if (COMPACT_STRINGS) {
429 byte[] buf = new byte[36];
430 formatUnsignedLong0(lsb, 4, buf, 24, 12);
431 formatUnsignedLong0(lsb >>> 48, 4, buf, 19, 4);
432 formatUnsignedLong0(msb, 4, buf, 14, 4);
433 formatUnsignedLong0(msb >>> 16, 4, buf, 9, 4);
434 formatUnsignedLong0(msb >>> 32, 4, buf, 0, 8);
435
436 buf[23] = '-';
437 buf[18] = '-';
438 buf[13] = '-';
439 buf[8] = '-';
440
441 return new String(buf, LATIN1);
442 } else {
443 byte[] buf = new byte[72];
444
445 formatUnsignedLong0UTF16(lsb, 4, buf, 24, 12);
446 formatUnsignedLong0UTF16(lsb >>> 48, 4, buf, 19, 4);
447 formatUnsignedLong0UTF16(msb, 4, buf, 14, 4);
448 formatUnsignedLong0UTF16(msb >>> 16, 4, buf, 9, 4);
449 formatUnsignedLong0UTF16(msb >>> 32, 4, buf, 0, 8);
450
451 StringUTF16.putChar(buf, 23, '-');
452 StringUTF16.putChar(buf, 18, '-');
453 StringUTF16.putChar(buf, 13, '-');
454 StringUTF16.putChar(buf, 8, '-');
455
456 return new String(buf, UTF16);
457 }
458 }
459
460 /**
461 * Returns a {@code String} object representing the specified
462 * {@code long}. The argument is converted to signed decimal
463 * representation and returned as a string, exactly as if the
464 * argument and the radix 10 were given as arguments to the {@link
465 * #toString(long, int)} method.
466 *
467 * @param i a {@code long} to be converted.
468 * @return a string representation of the argument in base 10.
469 */
470 public static String toString(long i) {
471 int size = stringSize(i);
472 if (COMPACT_STRINGS) {
473 byte[] buf = new byte[size];
474 getChars(i, size, buf);
475 return new String(buf, LATIN1);
476 } else {
477 byte[] buf = new byte[size * 2];
478 getCharsUTF16(i, size, buf);
479 return new String(buf, UTF16);
480 }
481 }
482
483 /**
484 * Returns a string representation of the argument as an unsigned
485 * decimal value.
486 *
487 * The argument is converted to unsigned decimal representation
488 * and returned as a string exactly as if the argument and radix
489 * 10 were given as arguments to the {@link #toUnsignedString(long,
490 * int)} method.
491 *
492 * @param i an integer to be converted to an unsigned string.
493 * @return an unsigned string representation of the argument.
494 * @see #toUnsignedString(long, int)
495 * @since 1.8
496 */
497 public static String toUnsignedString(long i) {
498 return toUnsignedString(i, 10);
540 while (i2 <= -100) {
541 q2 = i2 / 100;
542 r = (q2 * 100) - i2;
543 i2 = q2;
544 buf[--charPos] = Integer.DigitOnes[r];
545 buf[--charPos] = Integer.DigitTens[r];
546 }
547
548 // We know there are at most two digits left at this point.
549 q2 = i2 / 10;
550 r = (q2 * 10) - i2;
551 buf[--charPos] = (byte)('0' + r);
552
553 // Whatever left is the remaining digit.
554 if (q2 < 0) {
555 buf[--charPos] = (byte)('0' - q2);
556 }
557
558 if (negative) {
559 buf[--charPos] = (byte)'-';
560 }
561 return charPos;
562 }
563
564 /**
565 * This is a variant of {@link #getChars(long, int, byte[])}, but for
566 * UTF-16 coder.
567 *
568 * @param i value to convert
569 * @param index next index, after the least significant digit
570 * @param buf target buffer, UTF16-coded.
571 * @return index of the most significant digit or minus sign, if present
572 */
573 static int getCharsUTF16(long i, int index, byte[] buf) {
574 long q;
575 int r;
576 int charPos = index;
577
578 boolean negative = (i < 0);
579 if (!negative) {
580 i = -i;
581 }
582
583 // Get 2 digits/iteration using longs until quotient fits into an int
584 while (i <= Integer.MIN_VALUE) {
585 q = i / 100;
586 r = (int)((q * 100) - i);
587 i = q;
588 StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
589 StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
590 }
591
592 // Get 2 digits/iteration using ints
593 int q2;
594 int i2 = (int)i;
595 while (i2 <= -100) {
596 q2 = i2 / 100;
597 r = (q2 * 100) - i2;
598 i2 = q2;
599 StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
600 StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
601 }
602
603 // We know there are at most two digits left at this point.
604 q2 = i2 / 10;
605 r = (q2 * 10) - i2;
606 StringUTF16.putChar(buf, --charPos, '0' + r);
607
608 // Whatever left is the remaining digit.
609 if (q2 < 0) {
610 StringUTF16.putChar(buf, --charPos, '0' - q2);
611 }
612
613 if (negative) {
614 StringUTF16.putChar(buf, --charPos, '-');
615 }
616 return charPos;
617 }
618
619 /**
620 * Returns the string representation size for a given long value.
621 *
622 * @param x long value
623 * @return string size
624 *
625 * @implNote There are other ways to compute this: e.g. binary search,
626 * but values are biased heavily towards zero, and therefore linear search
627 * wins. The iteration results are also routinely inlined in the generated
628 * code after loop unrolling.
629 */
630 static int stringSize(long x) {
631 int d = 1;
632 if (x >= 0) {
633 d = 0;
634 x = -x;
|
1 /*
2 * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
142 i = i / radix;
143 }
144 buf[charPos] = (byte)Integer.digits[(int)(-i)];
145
146 if (negative) {
147 buf[--charPos] = '-';
148 }
149 return StringLatin1.newString(buf, charPos, (65 - charPos));
150 }
151 return toStringUTF16(i, radix);
152 }
153
154 private static String toStringUTF16(long i, int radix) {
155 byte[] buf = new byte[65 * 2];
156 int charPos = 64;
157 boolean negative = (i < 0);
158 if (!negative) {
159 i = -i;
160 }
161 while (i <= -radix) {
162 StringUTF16.Trusted.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]);
163 i = i / radix;
164 }
165 StringUTF16.Trusted.putChar(buf, charPos, Integer.digits[(int)(-i)]);
166 if (negative) {
167 StringUTF16.Trusted.putChar(buf, --charPos, '-');
168 }
169 return StringUTF16.newString(buf, charPos, (65 - charPos));
170 }
171
172 /**
173 * Returns a string representation of the first argument as an
174 * unsigned integer value in the radix specified by the second
175 * argument.
176 *
177 * <p>If the radix is smaller than {@code Character.MIN_RADIX}
178 * or larger than {@code Character.MAX_RADIX}, then the radix
179 * {@code 10} is used instead.
180 *
181 * <p>Note that since the first argument is treated as an unsigned
182 * value, no leading sign character is printed.
183 *
184 * <p>If the magnitude is zero, it is represented by a single zero
185 * character {@code '0'} ({@code '\u005Cu0030'}); otherwise,
186 * the first character of the representation of the magnitude will
187 * not be the zero character.
397 *
398 * @param val the unsigned long to format
399 * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary)
400 * @param buf the character buffer to write to
401 * @param offset the offset in the destination buffer to start at
402 * @param len the number of characters to write
403 */
404
405 /** byte[]/LATIN1 version */
406 static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) {
407 int charPos = offset + len;
408 int radix = 1 << shift;
409 int mask = radix - 1;
410 do {
411 buf[--charPos] = (byte)Integer.digits[((int) val) & mask];
412 val >>>= shift;
413 } while (charPos > offset);
414 }
415
416 /** byte[]/UTF16 version */
417 private static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
418 int charPos = offset + len;
419 int radix = 1 << shift;
420 int mask = radix - 1;
421 do {
422 StringUTF16.Trusted.putChar(buf, --charPos, Integer.digits[((int) val) & mask]);
423 val >>>= shift;
424 } while (charPos > offset);
425 }
426
427 static String fastUUID(long lsb, long msb) {
428 if (COMPACT_STRINGS) {
429 byte[] buf = new byte[36];
430 formatUnsignedLong0(lsb, 4, buf, 24, 12);
431 formatUnsignedLong0(lsb >>> 48, 4, buf, 19, 4);
432 formatUnsignedLong0(msb, 4, buf, 14, 4);
433 formatUnsignedLong0(msb >>> 16, 4, buf, 9, 4);
434 formatUnsignedLong0(msb >>> 32, 4, buf, 0, 8);
435
436 buf[23] = '-';
437 buf[18] = '-';
438 buf[13] = '-';
439 buf[8] = '-';
440
441 return new String(buf, LATIN1);
442 } else {
443 byte[] buf = new byte[72];
444
445 formatUnsignedLong0UTF16(lsb, 4, buf, 24, 12);
446 formatUnsignedLong0UTF16(lsb >>> 48, 4, buf, 19, 4);
447 formatUnsignedLong0UTF16(msb, 4, buf, 14, 4);
448 formatUnsignedLong0UTF16(msb >>> 16, 4, buf, 9, 4);
449 formatUnsignedLong0UTF16(msb >>> 32, 4, buf, 0, 8);
450
451 StringUTF16.Trusted.putChar(buf, 23, '-');
452 StringUTF16.Trusted.putChar(buf, 18, '-');
453 StringUTF16.Trusted.putChar(buf, 13, '-');
454 StringUTF16.Trusted.putChar(buf, 8, '-');
455
456 return new String(buf, UTF16);
457 }
458 }
459
460 /**
461 * Returns a {@code String} object representing the specified
462 * {@code long}. The argument is converted to signed decimal
463 * representation and returned as a string, exactly as if the
464 * argument and the radix 10 were given as arguments to the {@link
465 * #toString(long, int)} method.
466 *
467 * @param i a {@code long} to be converted.
468 * @return a string representation of the argument in base 10.
469 */
470 public static String toString(long i) {
471 int size = stringSize(i);
472 if (COMPACT_STRINGS) {
473 byte[] buf = new byte[size];
474 getChars(i, size, buf);
475 return new String(buf, LATIN1);
476 } else {
477 byte[] buf = new byte[size * 2];
478 StringUTF16.Trusted.getChars(i, size, buf);
479 return new String(buf, UTF16);
480 }
481 }
482
483 /**
484 * Returns a string representation of the argument as an unsigned
485 * decimal value.
486 *
487 * The argument is converted to unsigned decimal representation
488 * and returned as a string exactly as if the argument and radix
489 * 10 were given as arguments to the {@link #toUnsignedString(long,
490 * int)} method.
491 *
492 * @param i an integer to be converted to an unsigned string.
493 * @return an unsigned string representation of the argument.
494 * @see #toUnsignedString(long, int)
495 * @since 1.8
496 */
497 public static String toUnsignedString(long i) {
498 return toUnsignedString(i, 10);
540 while (i2 <= -100) {
541 q2 = i2 / 100;
542 r = (q2 * 100) - i2;
543 i2 = q2;
544 buf[--charPos] = Integer.DigitOnes[r];
545 buf[--charPos] = Integer.DigitTens[r];
546 }
547
548 // We know there are at most two digits left at this point.
549 q2 = i2 / 10;
550 r = (q2 * 10) - i2;
551 buf[--charPos] = (byte)('0' + r);
552
553 // Whatever left is the remaining digit.
554 if (q2 < 0) {
555 buf[--charPos] = (byte)('0' - q2);
556 }
557
558 if (negative) {
559 buf[--charPos] = (byte)'-';
560 }
561 return charPos;
562 }
563
564 /**
565 * Returns the string representation size for a given long value.
566 *
567 * @param x long value
568 * @return string size
569 *
570 * @implNote There are other ways to compute this: e.g. binary search,
571 * but values are biased heavily towards zero, and therefore linear search
572 * wins. The iteration results are also routinely inlined in the generated
573 * code after loop unrolling.
574 */
575 static int stringSize(long x) {
576 int d = 1;
577 if (x >= 0) {
578 d = 0;
579 x = -x;
|