Showing the changes to java/pkg/java/lang/String.java (1 of 1 file). Show all
Unified · Split
| @@ -110,14 +110,22 @@ import java.util.regex.PatternSyntaxException; · 109 unmodified lines | |||
| 110 | public final class String | 110 | public final class String |
| 111 | implements java.io.Serializable, Comparable<String>, CharSequence | 111 | implements java.io.Serializable, Comparable<String>, CharSequence |
| 112 | { | 112 | { |
| 113 | // [Inferno] < | ||
| 114 | |||
| 113 | /** The value is used for character storage. */ | 115 | /** The value is used for character storage. */ |
| 114 | private final char value[]; | 116 | //private final char value[]; |
| 115 | 117 | ||
| 116 | /** The offset is the first index of the storage that is used. */ | 118 | /** The offset is the first index of the storage that is used. */ |
| 117 | private final int offset; | 119 | //private final int offset; |
| 118 | 120 | ||
| 119 | /** The count is the number of characters in the String. */ | 121 | /** The count is the number of characters in the String. */ |
| 120 | private final int count; | 122 | //private final int count; |
| 123 | |||
| 124 | /** The first field represents internal dis string. It is used by | ||
| 125 | Inferno's jvm to store and manipulate the actual string data. */ | ||
| 126 | private transient String disString; | ||
| 127 | |||
| 128 | // [Inferno] > | ||
| 121 | 129 | ||
| 122 | /** Cache the hash code for the string */ | 130 | /** Cache the hash code for the string */ |
| 123 | private int hash; // Default to 0 | 131 | private int hash; // Default to 0 |
| @@ -145,11 +153,10 @@ public final class String · 21 unmodified lines | |||
| 145 | * an empty character sequence. Note that use of this constructor is | 153 | * an empty character sequence. Note that use of this constructor is |
| 146 | * unnecessary since Strings are immutable. | 154 | * unnecessary since Strings are immutable. |
| 147 | */ | 155 | */ |
| 156 | // [Inferno] < | ||
| 148 | public String() { | 157 | public String() { |
| 149 | this.offset = 0; | ||
| 150 | this.count = 0; | ||
| 151 | this.value = new char[0]; | ||
| 152 | } | 158 | } |
| 159 | // [Inferno] > | ||
| 153 | 160 | ||
| 154 | /** | 161 | /** |
| 155 | * Initializes a newly created {@code String} object so that it represents | 162 | * Initializes a newly created {@code String} object so that it represents |
| @@ -162,23 +169,29 @@ public final class String · 6 unmodified lines | |||
| 162 | * A {@code String} | 169 | * A {@code String} |
| 163 | */ | 170 | */ |
| 164 | public String(String original) { | 171 | public String(String original) { |
| 165 | int size = original.count; | 172 | //int size = original.count; |
| 166 | char[] originalValue = original.value; | 173 | //char[] originalValue = original.value; |
| 167 | char[] v; | 174 | //char[] v; |
| 168 | if (originalValue.length > size) { | 175 | //if (originalValue.length > size) { |
| 169 | // The array representing the String is bigger than the new | 176 | // // The array representing the String is bigger than the new |
| 170 | // String itself. Perhaps this constructor is being called | 177 | // // String itself. Perhaps this constructor is being called |
| 171 | // in order to trim the baggage, so make a copy of the array. | 178 | // // in order to trim the baggage, so make a copy of the array. |
| 172 | int off = original.offset; | 179 | // int off = original.offset; |
| 173 | v = Arrays.copyOfRange(originalValue, off, off+size); | 180 | // v = Arrays.copyOfRange(originalValue, off, off+size); |
| 174 | } else { | 181 | //} else { |
| 175 | // The array representing the String is the same | 182 | // // The array representing the String is the same |
| 176 | // size as the String, so no point in making a copy. | 183 | // // size as the String, so no point in making a copy. |
| 177 | v = originalValue; | 184 | // v = originalValue; |
| 178 | } | 185 | //} |
| 179 | this.offset = 0; | 186 | //this.offset = 0; |
| 180 | this.count = size; | 187 | //this.count = size; |
| 181 | this.value = v; | 188 | //this.value = v; |
| 189 | if (original == null) | ||
| 190 | throw new NullPointerException(); | ||
| 191 | |||
| 192 | // [Inferno] < | ||
| 193 | disString = original.disString; | ||
| 194 | // [Inferno] > | ||
| 182 | } | 195 | } |
| 183 | 196 | ||
| 184 | /** | 197 | /** |
| @@ -191,10 +204,16 @@ public final class String · 6 unmodified lines | |||
| 191 | * The initial value of the string | 204 | * The initial value of the string |
| 192 | */ | 205 | */ |
| 193 | public String(char value[]) { | 206 | public String(char value[]) { |
| 194 | int size = value.length; | 207 | //int size = value.length; |
| 195 | this.offset = 0; | 208 | //this.offset = 0; |
| 196 | this.count = size; | 209 | //this.count = size; |
| 197 | this.value = Arrays.copyOf(value, size); | 210 | //this.value = Arrays.copyOf(value, size); |
| 211 | if (value == null) | ||
| 212 | throw new NullPointerException(); | ||
| 213 | |||
| 214 | // [Inferno] < | ||
| 215 | fill(value, 0, value.length); | ||
| 216 | // [Inferno] > | ||
| 198 | } | 217 | } |
| 199 | 218 | ||
| 200 | /** | 219 | /** |
| @@ -229,9 +248,12 @@ public final class String · 28 unmodified lines | |||
| 229 | if (offset > value.length - count) { | 248 | if (offset > value.length - count) { |
| 230 | throw new StringIndexOutOfBoundsException(offset + count); | 249 | throw new StringIndexOutOfBoundsException(offset + count); |
| 231 | } | 250 | } |
| 232 | this.offset = 0; | 251 | //this.offset = 0; |
| 233 | this.count = count; | 252 | //this.count = count; |
| 234 | this.value = Arrays.copyOfRange(value, offset, offset+count); | 253 | |
| 254 | // [Inferno] < | ||
| 255 | fill(value, offset, count); | ||
| 256 | // [Inferno] > | ||
| 235 | } | 257 | } |
| 236 | 258 | ||
| 237 | /** | 259 | /** |
| @@ -298,9 +320,13 @@ public final class String · 60 unmodified lines | |||
| 298 | Character.toSurrogates(c, v, j++); | 320 | Character.toSurrogates(c, v, j++); |
| 299 | } | 321 | } |
| 300 | 322 | ||
| 301 | this.value = v; | 323 | //this.value = v; |
| 302 | this.count = n; | 324 | //this.count = n; |
| 303 | this.offset = 0; | 325 | //this.offset = 0; |
| 326 | |||
| 327 | // [Inferno] < | ||
| 328 | fill(v, 0, v.length); | ||
| 329 | // [Inferno] > | ||
| 304 | } | 330 | } |
| 305 | 331 | ||
| 306 | /** | 332 | /** |
| @@ -357,9 +383,13 @@ public final class String · 50 unmodified lines | |||
| 357 | value[i] = (char) (hibyte | (ascii[i + offset] & 0xff)); | 383 | value[i] = (char) (hibyte | (ascii[i + offset] & 0xff)); |
| 358 | } | 384 | } |
| 359 | } | 385 | } |
| 360 | this.offset = 0; | 386 | //this.offset = 0; |
| 361 | this.count = count; | 387 | //this.count = count; |
| 362 | this.value = value; | 388 | //this.value = value; |
| 389 | |||
| 390 | // [Inferno] < | ||
| 391 | fill(value, 0, value.length); | ||
| 392 | // [Inferno] > | ||
| 363 | } | 393 | } |
| 364 | 394 | ||
| 365 | /** | 395 | /** |
| @@ -429,7 +459,7 @@ public final class String · 63 unmodified lines | |||
| 429 | * | 459 | * |
| 430 | * @param length | 460 | * @param length |
| 431 | * The number of bytes to decode | 461 | * The number of bytes to decode |
| 432 | 462 | * | |
| 433 | * @param charsetName | 463 | * @param charsetName |
| 434 | * The name of a supported {@linkplain java.nio.charset.Charset | 464 | * The name of a supported {@linkplain java.nio.charset.Charset |
| 435 | * charset} | 465 | * charset} |
| @@ -450,9 +480,13 @@ public final class String · 14 unmodified lines | |||
| 450 | throw new NullPointerException("charsetName"); | 480 | throw new NullPointerException("charsetName"); |
| 451 | checkBounds(bytes, offset, length); | 481 | checkBounds(bytes, offset, length); |
| 452 | char[] v = StringCoding.decode(charsetName, bytes, offset, length); | 482 | char[] v = StringCoding.decode(charsetName, bytes, offset, length); |
| 453 | this.offset = 0; | 483 | //this.offset = 0; |
| 454 | this.count = v.length; | 484 | //this.count = v.length; |
| 455 | this.value = v; | 485 | //this.value = v; |
| 486 | |||
| 487 | // [Inferno] < | ||
| 488 | fill(v, 0, v.length); | ||
| 489 | // [Inferno] > | ||
| 456 | } | 490 | } |
| 457 | 491 | ||
| 458 | /** | 492 | /** |
| @@ -490,9 +524,13 @@ public final class String · 31 unmodified lines | |||
| 490 | throw new NullPointerException("charset"); | 524 | throw new NullPointerException("charset"); |
| 491 | checkBounds(bytes, offset, length); | 525 | checkBounds(bytes, offset, length); |
| 492 | char[] v = StringCoding.decode(charset, bytes, offset, length); | 526 | char[] v = StringCoding.decode(charset, bytes, offset, length); |
| 493 | this.offset = 0; | 527 | //this.offset = 0; |
| 494 | this.count = v.length; | 528 | //this.count = v.length; |
| 495 | this.value = v; | 529 | //this.value = v; |
| 530 | |||
| 531 | // [Inferno] < | ||
| 532 | fill(v, 0, v.length); | ||
| 533 | // [Inferno] > | ||
| 496 | } | 534 | } |
| 497 | 535 | ||
| 498 | /** | 536 | /** |
| @@ -577,9 +615,13 @@ public final class String · 78 unmodified lines | |||
| 577 | public String(byte bytes[], int offset, int length) { | 615 | public String(byte bytes[], int offset, int length) { |
| 578 | checkBounds(bytes, offset, length); | 616 | checkBounds(bytes, offset, length); |
| 579 | char[] v = StringCoding.decode(bytes, offset, length); | 617 | char[] v = StringCoding.decode(bytes, offset, length); |
| 580 | this.offset = 0; | 618 | //this.offset = 0; |
| 581 | this.count = v.length; | 619 | //this.count = v.length; |
| 582 | this.value = v; | 620 | //this.value = v; |
| 621 | |||
| 622 | // [Inferno] < | ||
| 623 | fill(v, 0, v.length); | ||
| 624 | // [Inferno] > | ||
| 583 | } | 625 | } |
| 584 | 626 | ||
| 585 | /** | 627 | /** |
| @@ -612,10 +654,9 @@ public final class String · 26 unmodified lines | |||
| 612 | * A {@code StringBuffer} | 654 | * A {@code StringBuffer} |
| 613 | */ | 655 | */ |
| 614 | public String(StringBuffer buffer) { | 656 | public String(StringBuffer buffer) { |
| 615 | String result = buffer.toString(); | 657 | // [Inferno] < |
| 616 | this.value = result.value; | 658 | this(buffer.toString()); |
| 617 | this.count = result.count; | 659 | // [Inferno] > |
| 618 | this.offset = result.offset; | ||
| 619 | } | 660 | } |
| 620 | 661 | ||
| 621 | /** | 662 | /** |
| @@ -634,18 +675,19 @@ public final class String · 12 unmodified lines | |||
| 634 | * @since 1.5 | 675 | * @since 1.5 |
| 635 | */ | 676 | */ |
| 636 | public String(StringBuilder builder) { | 677 | public String(StringBuilder builder) { |
| 637 | String result = builder.toString(); | 678 | // [Inferno] < |
| 638 | this.value = result.value; | 679 | this(builder.toString()); |
| 639 | this.count = result.count; | 680 | // [Inferno] > |
| 640 | this.offset = result.offset; | ||
| 641 | } | 681 | } |
| 642 | 682 | ||
| 643 | 683 | ||
| 644 | // Package private constructor which shares value array for speed. | 684 | // Package private constructor which shares value array for speed. |
| 645 | String(int offset, int count, char value[]) { | 685 | String(int offset, int count, char value[]) { |
| 646 | this.value = value; | 686 | // TODO: implement real sharing |
| 647 | this.offset = offset; | 687 | |
| 648 | this.count = count; | 688 | // [Inferno] < |
| 689 | fill(value, offset, count); | ||
| 690 | // [Inferno] > | ||
| 649 | } | 691 | } |
| 650 | 692 | ||
| 651 | /** | 693 | /** |
| @@ -656,9 +698,9 @@ public final class String · 4 unmodified lines | |||
| 656 | * @return the length of the sequence of characters represented by this | 698 | * @return the length of the sequence of characters represented by this |
| 657 | * object. | 699 | * object. |
| 658 | */ | 700 | */ |
| 659 | public int length() { | 701 | // [Inferno] < |
| 660 | return count; | 702 | public native int length(); |
| 661 | } | 703 | // [Inferno] > |
| 662 | 704 | ||
| 663 | /** | 705 | /** |
| 664 | * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>. | 706 | * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>. |
| @@ -669,7 +711,9 @@ public final class String · 4 unmodified lines | |||
| 669 | * @since 1.6 | 711 | * @since 1.6 |
| 670 | */ | 712 | */ |
| 671 | public boolean isEmpty() { | 713 | public boolean isEmpty() { |
| 672 | return count == 0; | 714 | // [Inferno] < |
| 715 | return length() == 0; | ||
| 716 | // [Inferno] > | ||
| 673 | } | 717 | } |
| 674 | 718 | ||
| 675 | /** | 719 | /** |
| @@ -690,12 +734,9 @@ public final class String · 14 unmodified lines | |||
| 690 | * argument is negative or not less than the length of this | 734 | * argument is negative or not less than the length of this |
| 691 | * string. | 735 | * string. |
| 692 | */ | 736 | */ |
| 693 | public char charAt(int index) { | 737 | // [Inferno] < |
| 694 | if ((index < 0) || (index >= count)) { | 738 | public native char charAt(int index); |
| 695 | throw new StringIndexOutOfBoundsException(index); | 739 | // [Inferno] > |
| 696 | } | ||
| 697 | return value[index + offset]; | ||
| 698 | } | ||
| 699 | 740 | ||
| 700 | /** | 741 | /** |
| 701 | * Returns the character (Unicode code point) at the specified | 742 | * Returns the character (Unicode code point) at the specified |
| @@ -720,10 +761,11 @@ public final class String · 18 unmodified lines | |||
| 720 | * @since 1.5 | 761 | * @since 1.5 |
| 721 | */ | 762 | */ |
| 722 | public int codePointAt(int index) { | 763 | public int codePointAt(int index) { |
| 723 | if ((index < 0) || (index >= count)) { | 764 | //if ((index < 0) || (index >= count)) { |
| 724 | throw new StringIndexOutOfBoundsException(index); | 765 | // throw new StringIndexOutOfBoundsException(index); |
| 725 | } | 766 | //} |
| 726 | return Character.codePointAtImpl(value, offset + index, offset + count); | 767 | //return Character.codePointAtImpl(value, offset + index, offset + count); |
| 768 | return 0; | ||
| 727 | } | 769 | } |
| 728 | 770 | ||
| 729 | /** | 771 | /** |
| @@ -749,11 +791,12 @@ public final class String · 19 unmodified lines | |||
| 749 | * @since 1.5 | 791 | * @since 1.5 |
| 750 | */ | 792 | */ |
| 751 | public int codePointBefore(int index) { | 793 | public int codePointBefore(int index) { |
| 752 | int i = index - 1; | 794 | //int i = index - 1; |
| 753 | if ((i < 0) || (i >= count)) { | 795 | //if ((i < 0) || (i >= count)) { |
| 754 | throw new StringIndexOutOfBoundsException(index); | 796 | // throw new StringIndexOutOfBoundsException(index); |
| 755 | } | 797 | //} |
| 756 | return Character.codePointBeforeImpl(value, offset + index, offset); | 798 | //return Character.codePointBeforeImpl(value, offset + index, offset); |
| 799 | return 0; | ||
| 757 | } | 800 | } |
| 758 | 801 | ||
| 759 | /** | 802 | /** |
| @@ -778,10 +821,11 @@ public final class String · 18 unmodified lines | |||
| 778 | * @since 1.5 | 821 | * @since 1.5 |
| 779 | */ | 822 | */ |
| 780 | public int codePointCount(int beginIndex, int endIndex) { | 823 | public int codePointCount(int beginIndex, int endIndex) { |
| 781 | if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { | 824 | //if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { |
| 782 | throw new IndexOutOfBoundsException(); | 825 | // throw new IndexOutOfBoundsException(); |
| 783 | } | 826 | //} |
| 784 | return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex); | 827 | //return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex); |
| 828 | return 0; | ||
| 785 | } | 829 | } |
| 786 | 830 | ||
| 787 | /** | 831 | /** |
| @@ -805,11 +849,12 @@ public final class String · 17 unmodified lines | |||
| 805 | * @since 1.5 | 849 | * @since 1.5 |
| 806 | */ | 850 | */ |
| 807 | public int offsetByCodePoints(int index, int codePointOffset) { | 851 | public int offsetByCodePoints(int index, int codePointOffset) { |
| 808 | if (index < 0 || index > count) { | 852 | //if (index < 0 || index > count) { |
| 809 | throw new IndexOutOfBoundsException(); | 853 | // throw new IndexOutOfBoundsException(); |
| 810 | } | 854 | //} |
| 811 | return Character.offsetByCodePointsImpl(value, offset, count, | 855 | //return Character.offsetByCodePointsImpl(value, offset, count, |
| 812 | offset+index, codePointOffset) - offset; | 856 | // offset+index, codePointOffset) - offset; |
| 857 | return 0; | ||
| 813 | } | 858 | } |
| 814 | 859 | ||
| 815 | /** | 860 | /** |
| @@ -817,7 +862,9 @@ public final class String · 1 unmodified line | |||
| 817 | * This method doesn't perform any range checking. | 862 | * This method doesn't perform any range checking. |
| 818 | */ | 863 | */ |
| 819 | void getChars(char dst[], int dstBegin) { | 864 | void getChars(char dst[], int dstBegin) { |
| 820 | System.arraycopy(value, offset, dst, dstBegin, count); | 865 | // [Inferno] < |
| 866 | getChars(0, length(), dst, dstBegin); | ||
| 867 | // [Inferno] > | ||
| 821 | } | 868 | } |
| 822 | 869 | ||
| 823 | /** | 870 | /** |
| @@ -850,19 +897,7 @@ public final class String · 26 unmodified lines | |||
| 850 | * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than | 897 | * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than |
| 851 | * <code>dst.length</code></ul> | 898 | * <code>dst.length</code></ul> |
| 852 | */ | 899 | */ |
| 853 | public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { | 900 | public native void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin); |
| 854 | if (srcBegin < 0) { | ||
| 855 | throw new StringIndexOutOfBoundsException(srcBegin); | ||
| 856 | } | ||
| 857 | if (srcEnd > count) { | ||
| 858 | throw new StringIndexOutOfBoundsException(srcEnd); | ||
| 859 | } | ||
| 860 | if (srcBegin > srcEnd) { | ||
| 861 | throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); | ||
| 862 | } | ||
| 863 | System.arraycopy(value, offset + srcBegin, dst, dstBegin, | ||
| 864 | srcEnd - srcBegin); | ||
| 865 | } | ||
| 866 | 901 | ||
| 867 | /** | 902 | /** |
| 868 | * Copies characters from this string into the destination byte array. Each | 903 | * Copies characters from this string into the destination byte array. Each |
| @@ -912,16 +947,16 @@ public final class String · 43 unmodified lines | |||
| 912 | if (srcBegin < 0) { | 947 | if (srcBegin < 0) { |
| 913 | throw new StringIndexOutOfBoundsException(srcBegin); | 948 | throw new StringIndexOutOfBoundsException(srcBegin); |
| 914 | } | 949 | } |
| 915 | if (srcEnd > count) { | 950 | if (srcEnd > length()) { |
| 916 | throw new StringIndexOutOfBoundsException(srcEnd); | 951 | throw new StringIndexOutOfBoundsException(srcEnd); |
| 917 | } | 952 | } |
| 918 | if (srcBegin > srcEnd) { | 953 | if (srcBegin > srcEnd) { |
| 919 | throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); | 954 | throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); |
| 920 | } | 955 | } |
| 921 | int j = dstBegin; | 956 | int j = dstBegin; |
| 922 | int n = offset + srcEnd; | 957 | int n = srcEnd; |
| 923 | int i = offset + srcBegin; | 958 | int i = srcBegin; |
| 924 | char[] val = value; /* avoid getfield opcode */ | 959 | char[] val = toCharArray(); |
| 925 | 960 | ||
| 926 | while (i < n) { | 961 | while (i < n) { |
| 927 | dst[j++] = (byte)val[i++]; | 962 | dst[j++] = (byte)val[i++]; |
| @@ -952,7 +987,7 @@ public final class String · 24 unmodified lines | |||
| 952 | throws UnsupportedEncodingException | 987 | throws UnsupportedEncodingException |
| 953 | { | 988 | { |
| 954 | if (charsetName == null) throw new NullPointerException(); | 989 | if (charsetName == null) throw new NullPointerException(); |
| 955 | return StringCoding.encode(charsetName, value, offset, count); | 990 | return StringCoding.encode(charsetName, toCharArray(), 0, length()); |
| 956 | } | 991 | } |
| 957 | 992 | ||
| 958 | /** | 993 | /** |
| @@ -975,7 +1010,7 @@ public final class String · 16 unmodified lines | |||
| 975 | */ | 1010 | */ |
| 976 | public byte[] getBytes(Charset charset) { | 1011 | public byte[] getBytes(Charset charset) { |
| 977 | if (charset == null) throw new NullPointerException(); | 1012 | if (charset == null) throw new NullPointerException(); |
| 978 | return StringCoding.encode(charset, value, offset, count); | 1013 | return StringCoding.encode(charset, toCharArray(), 0, length()); |
| 979 | } | 1014 | } |
| 980 | 1015 | ||
| 981 | /** | 1016 | /** |
| @@ -992,7 +1027,7 @@ public final class String · 10 unmodified lines | |||
| 992 | * @since JDK1.1 | 1027 | * @since JDK1.1 |
| 993 | */ | 1028 | */ |
| 994 | public byte[] getBytes() { | 1029 | public byte[] getBytes() { |
| 995 | return StringCoding.encode(value, offset, count); | 1030 | return StringCoding.encode(toCharArray(), 0, length()); |
| 996 | } | 1031 | } |
| 997 | 1032 | ||
| 998 | /** | 1033 | /** |
| @@ -1011,25 +1046,11 @@ public final class String · 12 unmodified lines | |||
| 1011 | * @see #equalsIgnoreCase(String) | 1046 | * @see #equalsIgnoreCase(String) |
| 1012 | */ | 1047 | */ |
| 1013 | public boolean equals(Object anObject) { | 1048 | public boolean equals(Object anObject) { |
| 1014 | if (this == anObject) { | 1049 | // [Inferno] < |
| 1015 | return true; | 1050 | if (anObject instanceof String) |
| 1016 | } | 1051 | return equality((String)anObject, false); |
| 1017 | if (anObject instanceof String) { | ||
| 1018 | String anotherString = (String)anObject; | ||
| 1019 | int n = count; | ||
| 1020 | if (n == anotherString.count) { | ||
| 1021 | char v1[] = value; | ||
| 1022 | char v2[] = anotherString.value; | ||
| 1023 | int i = offset; | ||
| 1024 | int j = anotherString.offset; | ||
| 1025 | while (n-- != 0) { | ||
| 1026 | if (v1[i++] != v2[j++]) | ||
| 1027 | return false; | ||
| 1028 | } | ||
| 1029 | return true; | ||
| 1030 | } | ||
| 1031 | } | ||
| 1032 | return false; | 1052 | return false; |
| 1053 | // [Inferno] > | ||
| 1033 | } | 1054 | } |
| 1034 | 1055 | ||
| 1035 | /** | 1056 | /** |
| @@ -1067,13 +1088,15 @@ public final class String · 31 unmodified lines | |||
| 1067 | * @since 1.5 | 1088 | * @since 1.5 |
| 1068 | */ | 1089 | */ |
| 1069 | public boolean contentEquals(CharSequence cs) { | 1090 | public boolean contentEquals(CharSequence cs) { |
| 1091 | // [Inferno] < | ||
| 1092 | int count = length(); | ||
| 1070 | if (count != cs.length()) | 1093 | if (count != cs.length()) |
| 1071 | return false; | 1094 | return false; |
| 1072 | // Argument is a StringBuffer, StringBuilder | 1095 | // Argument is a StringBuffer, StringBuilder |
| 1073 | if (cs instanceof AbstractStringBuilder) { | 1096 | if (cs instanceof AbstractStringBuilder) { |
| 1074 | char v1[] = value; | 1097 | char v1[] = toCharArray(); |
| 1075 | char v2[] = ((AbstractStringBuilder)cs).getValue(); | 1098 | char v2[] = ((AbstractStringBuilder)cs).getValue(); |
| 1076 | int i = offset; | 1099 | int i = 0; |
| 1077 | int j = 0; | 1100 | int j = 0; |
| 1078 | int n = count; | 1101 | int n = count; |
| 1079 | while (n-- != 0) { | 1102 | while (n-- != 0) { |
| @@ -1086,8 +1109,8 @@ public final class String · 6 unmodified lines | |||
| 1086 | if (cs.equals(this)) | 1109 | if (cs.equals(this)) |
| 1087 | return true; | 1110 | return true; |
| 1088 | // Argument is a generic CharSequence | 1111 | // Argument is a generic CharSequence |
| 1089 | char v1[] = value; | 1112 | char v1[] = toCharArray(); |
| 1090 | int i = offset; | 1113 | int i = 0; |
| 1091 | int j = 0; | 1114 | int j = 0; |
| 1092 | int n = count; | 1115 | int n = count; |
| 1093 | while (n-- != 0) { | 1116 | while (n-- != 0) { |
| @@ -1095,6 +1118,7 @@ public final class String · 1 unmodified line | |||
| 1095 | return false; | 1118 | return false; |
| 1096 | } | 1119 | } |
| 1097 | return true; | 1120 | return true; |
| 1121 | // [Inferno] > | ||
| 1098 | } | 1122 | } |
| 1099 | 1123 | ||
| 1100 | /** | 1124 | /** |
| @@ -1126,9 +1150,9 @@ public final class String · 25 unmodified lines | |||
| 1126 | * @see #equals(Object) | 1150 | * @see #equals(Object) |
| 1127 | */ | 1151 | */ |
| 1128 | public boolean equalsIgnoreCase(String anotherString) { | 1152 | public boolean equalsIgnoreCase(String anotherString) { |
| 1129 | return (this == anotherString) ? true : | 1153 | // [Inferno] < |
| 1130 | (anotherString != null) && (anotherString.count == count) && | 1154 | return equality(anotherString, true); |
| 1131 | regionMatches(true, 0, anotherString, 0, count); | 1155 | // [Inferno] > |
| 1132 | } | 1156 | } |
| 1133 | 1157 | ||
| 1134 | /** | 1158 | /** |
| @@ -1173,13 +1197,13 @@ public final class String · 38 unmodified lines | |||
| 1173 | * lexicographically greater than the string argument. | 1197 | * lexicographically greater than the string argument. |
| 1174 | */ | 1198 | */ |
| 1175 | public int compareTo(String anotherString) { | 1199 | public int compareTo(String anotherString) { |
| 1176 | int len1 = count; | 1200 | int len1 = length(); |
| 1177 | int len2 = anotherString.count; | 1201 | int len2 = anotherString.length(); |
| 1178 | int n = Math.min(len1, len2); | 1202 | int n = Math.min(len1, len2); |
| 1179 | char v1[] = value; | 1203 | char v1[] = toCharArray(); |
| 1180 | char v2[] = anotherString.value; | 1204 | char v2[] = anotherString.toCharArray(); |
| 1181 | int i = offset; | 1205 | int i = 0; |
| 1182 | int j = anotherString.offset; | 1206 | int j = 0; |
| 1183 | 1207 | ||
| 1184 | if (i == j) { | 1208 | if (i == j) { |
| 1185 | int k = i; | 1209 | int k = i; |
| @@ -1304,21 +1328,9 @@ public final class String · 118 unmodified lines | |||
| 1304 | */ | 1328 | */ |
| 1305 | public boolean regionMatches(int toffset, String other, int ooffset, | 1329 | public boolean regionMatches(int toffset, String other, int ooffset, |
| 1306 | int len) { | 1330 | int len) { |
| 1307 | char ta[] = value; | 1331 | // [Inferno] < |
| 1308 | int to = offset + toffset; | 1332 | return regionMatches(false, toffset, other, ooffset, len); |
| 1309 | char pa[] = other.value; | 1333 | // [Inferno] > |
| 1310 | int po = other.offset + ooffset; | ||
| 1311 | // Note: toffset, ooffset, or len might be near -1>>>1. | ||
| 1312 | if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) | ||
| 1313 | || (ooffset > (long)other.count - len)) { | ||
| 1314 | return false; | ||
| 1315 | } | ||
| 1316 | while (len-- > 0) { | ||
| 1317 | if (ta[to++] != pa[po++]) { | ||
| 1318 | return false; | ||
| 1319 | } | ||
| 1320 | } | ||
| 1321 | return true; | ||
| 1322 | } | 1334 | } |
| 1323 | 1335 | ||
| 1324 | /** | 1336 | /** |
| @@ -1348,7 +1360,7 @@ public final class String · 23 unmodified lines | |||
| 1348 | * integer <i>k</i> less than <tt>len</tt> such that: | 1360 | * integer <i>k</i> less than <tt>len</tt> such that: |
| 1349 | * <blockquote><pre> | 1361 | * <blockquote><pre> |
| 1350 | * Character.toLowerCase(this.charAt(toffset+k)) != | 1362 | * Character.toLowerCase(this.charAt(toffset+k)) != |
| 1351 | Character.toLowerCase(other.charAt(ooffset+k)) | 1363 | * Character.toLowerCase(other.charAt(ooffset+k)) |
| 1352 | * </pre></blockquote> | 1364 | * </pre></blockquote> |
| 1353 | * and: | 1365 | * and: |
| 1354 | * <blockquote><pre> | 1366 | * <blockquote><pre> |
| @@ -1371,45 +1383,10 @@ public final class String · 16 unmodified lines | |||
| 1371 | * or case insensitive depends on the <code>ignoreCase</code> | 1383 | * or case insensitive depends on the <code>ignoreCase</code> |
| 1372 | * argument. | 1384 | * argument. |
| 1373 | */ | 1385 | */ |
| 1374 | public boolean regionMatches(boolean ignoreCase, int toffset, | 1386 | // [Inferno] < |
| 1375 | String other, int ooffset, int len) { | 1387 | public native boolean regionMatches(boolean ignoreCase, int toffset, |
| 1376 | char ta[] = value; | 1388 | String other, int ooffset, int len); |
| 1377 | int to = offset + toffset; | 1389 | // [Inferno] > |
| 1378 | char pa[] = other.value; | ||
| 1379 | int po = other.offset + ooffset; | ||
| 1380 | // Note: toffset, ooffset, or len might be near -1>>>1. | ||
| 1381 | if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) || | ||
| 1382 | (ooffset > (long)other.count - len)) { | ||
| 1383 | return false; | ||
| 1384 | } | ||
| 1385 | while (len-- > 0) { | ||
| 1386 | char c1 = ta[to++]; | ||
| 1387 | char c2 = pa[po++]; | ||
| 1388 | if (c1 == c2) { | ||
| 1389 | continue; | ||
| 1390 | } | ||
| 1391 | if (ignoreCase) { | ||
| 1392 | // If characters don't match but case may be ignored, | ||
| 1393 | // try converting both characters to uppercase. | ||
| 1394 | // If the results match, then the comparison scan should | ||
| 1395 | // continue. | ||
| 1396 | char u1 = Character.toUpperCase(c1); | ||
| 1397 | char u2 = Character.toUpperCase(c2); | ||
| 1398 | if (u1 == u2) { | ||
| 1399 | continue; | ||
| 1400 | } | ||
| 1401 | // Unfortunately, conversion to uppercase does not work properly | ||
| 1402 | // for the Georgian alphabet, which has strange rules about case | ||
| 1403 | // conversion. So we need to make one last check before | ||
| 1404 | // exiting. | ||
| 1405 | if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { | ||
| 1406 | continue; | ||
| 1407 | } | ||
| 1408 | } | ||
| 1409 | return false; | ||
| 1410 | } | ||
| 1411 | return true; | ||
| 1412 | } | ||
| 1413 | 1390 | ||
| 1414 | /** | 1391 | /** |
| 1415 | * Tests if the substring of this string beginning at the | 1392 | * Tests if the substring of this string beginning at the |
| @@ -1429,21 +1406,9 @@ public final class String · 13 unmodified lines | |||
| 1429 | * </pre> | 1406 | * </pre> |
| 1430 | */ | 1407 | */ |
| 1431 | public boolean startsWith(String prefix, int toffset) { | 1408 | public boolean startsWith(String prefix, int toffset) { |
| 1432 | char ta[] = value; | 1409 | // [Inferno] < |
| 1433 | int to = offset + toffset; | 1410 | return isPrefix(prefix, toffset); |
| 1434 | char pa[] = prefix.value; | 1411 | // [Inferno] > |
| 1435 | int po = prefix.offset; | ||
| 1436 | int pc = prefix.count; | ||
| 1437 | // Note: toffset might be near -1>>>1. | ||
| 1438 | if ((toffset < 0) || (toffset > count - pc)) { | ||
| 1439 | return false; | ||
| 1440 | } | ||
| 1441 | while (--pc >= 0) { | ||
| 1442 | if (ta[to++] != pa[po++]) { | ||
| 1443 | return false; | ||
| 1444 | } | ||
| 1445 | } | ||
| 1446 | return true; | ||
| 1447 | } | 1412 | } |
| 1448 | 1413 | ||
| 1449 | /** | 1414 | /** |
| @@ -1460,7 +1425,9 @@ public final class String · 10 unmodified lines | |||
| 1460 | * @since 1. 0 | 1425 | * @since 1. 0 |
| 1461 | */ | 1426 | */ |
| 1462 | public boolean startsWith(String prefix) { | 1427 | public boolean startsWith(String prefix) { |
| 1463 | return startsWith(prefix, 0); | 1428 | // [Inferno] < |
| 1429 | return isPrefix(prefix, 0); | ||
| 1430 | // [Inferno] > | ||
| 1464 | } | 1431 | } |
| 1465 | 1432 | ||
| 1466 | /** | 1433 | /** |
| @@ -1475,7 +1442,9 @@ public final class String · 8 unmodified lines | |||
| 1475 | * as determined by the {@link #equals(Object)} method. | 1442 | * as determined by the {@link #equals(Object)} method. |
| 1476 | */ | 1443 | */ |
| 1477 | public boolean endsWith(String suffix) { | 1444 | public boolean endsWith(String suffix) { |
| 1478 | return startsWith(suffix, count - suffix.count); | 1445 | // [Inferno] < |
| 1446 | return isSuffix(suffix); | ||
| 1447 | // [Inferno] > | ||
| 1479 | } | 1448 | } |
| 1480 | 1449 | ||
| 1481 | /** | 1450 | /** |
| @@ -1491,20 +1460,9 @@ public final class String · 9 unmodified lines | |||
| 1491 | * | 1460 | * |
| 1492 | * @return a hash code value for this object. | 1461 | * @return a hash code value for this object. |
| 1493 | */ | 1462 | */ |
| 1494 | public int hashCode() { | 1463 | // [Inferno] < |
| 1495 | int h = hash; | 1464 | public native int hashCode(); |
| 1496 | if (h == 0 && count > 0) { | 1465 | // [Inferno] > |
| 1497 | int off = offset; | ||
| 1498 | char val[] = value; | ||
| 1499 | int len = count; | ||
| 1500 | |||
| 1501 | for (int i = 0; i < len; i++) { | ||
| 1502 | h = 31*h + val[off++]; | ||
| 1503 | } | ||
| 1504 | hash = h; | ||
| 1505 | } | ||
| 1506 | return h; | ||
| 1507 | } | ||
| 1508 | 1466 | ||
| 1509 | /** | 1467 | /** |
| 1510 | * Returns the index within this string of the first occurrence of | 1468 | * Returns the index within this string of the first occurrence of |
| @@ -1531,7 +1489,9 @@ public final class String · 20 unmodified lines | |||
| 1531 | * <code>-1</code> if the character does not occur. | 1489 | * <code>-1</code> if the character does not occur. |
| 1532 | */ | 1490 | */ |
| 1533 | public int indexOf(int ch) { | 1491 | public int indexOf(int ch) { |
| 1534 | return indexOf(ch, 0); | 1492 | // [Inferno] < |
| 1493 | return index(ch, 0); | ||
| 1494 | // [Inferno] > | ||
| 1535 | } | 1495 | } |
| 1536 | 1496 | ||
| 1537 | /** | 1497 | /** |
| @@ -1574,47 +1534,9 @@ public final class String · 36 unmodified lines | |||
| 1574 | * if the character does not occur. | 1534 | * if the character does not occur. |
| 1575 | */ | 1535 | */ |
| 1576 | public int indexOf(int ch, int fromIndex) { | 1536 | public int indexOf(int ch, int fromIndex) { |
| 1577 | if (fromIndex < 0) { | 1537 | // [Inferno] < |
| 1578 | fromIndex = 0; | 1538 | return index(ch, fromIndex); |
| 1579 | } else if (fromIndex >= count) { | 1539 | // [Inferno] > |
| 1580 | // Note: fromIndex might be near -1>>>1. | ||
| 1581 | return -1; | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { | ||
| 1585 | // handle most cases here (ch is a BMP code point or a | ||
| 1586 | // negative value (invalid code point)) | ||
| 1587 | final char[] value = this.value; | ||
| 1588 | final int offset = this.offset; | ||
| 1589 | final int max = offset + count; | ||
| 1590 | for (int i = offset + fromIndex; i < max ; i++) { | ||
| 1591 | if (value[i] == ch) { | ||
| 1592 | return i - offset; | ||
| 1593 | } | ||
| 1594 | } | ||
| 1595 | return -1; | ||
| 1596 | } else { | ||
| 1597 | return indexOfSupplementary(ch, fromIndex); | ||
| 1598 | } | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | /** | ||
| 1602 | * Handles (rare) calls of indexOf with a supplementary character. | ||
| 1603 | */ | ||
| 1604 | private int indexOfSupplementary(int ch, int fromIndex) { | ||
| 1605 | if (Character.isValidCodePoint(ch)) { | ||
| 1606 | final char[] value = this.value; | ||
| 1607 | final int offset = this.offset; | ||
| 1608 | final char hi = Character.highSurrogate(ch); | ||
| 1609 | final char lo = Character.lowSurrogate(ch); | ||
| 1610 | final int max = offset + count - 1; | ||
| 1611 | for (int i = offset + fromIndex; i < max; i++) { | ||
| 1612 | if (value[i] == hi && value[i+1] == lo) { | ||
| 1613 | return i - offset; | ||
| 1614 | } | ||
| 1615 | } | ||
| 1616 | } | ||
| 1617 | return -1; | ||
| 1618 | } | 1540 | } |
| 1619 | 1541 | ||
| 1620 | /** | 1542 | /** |
| @@ -1641,7 +1563,9 @@ public final class String · 20 unmodified lines | |||
| 1641 | * <code>-1</code> if the character does not occur. | 1563 | * <code>-1</code> if the character does not occur. |
| 1642 | */ | 1564 | */ |
| 1643 | public int lastIndexOf(int ch) { | 1565 | public int lastIndexOf(int ch) { |
| 1644 | return lastIndexOf(ch, count - 1); | 1566 | // [Inferno] < |
| 1567 | return rindex(ch, 0, true); | ||
| 1568 | // [Inferno] > | ||
| 1645 | } | 1569 | } |
| 1646 | 1570 | ||
| 1647 | /** | 1571 | /** |
| @@ -1679,40 +1603,9 @@ public final class String · 31 unmodified lines | |||
| 1679 | * if the character does not occur before that point. | 1603 | * if the character does not occur before that point. |
| 1680 | */ | 1604 | */ |
| 1681 | public int lastIndexOf(int ch, int fromIndex) { | 1605 | public int lastIndexOf(int ch, int fromIndex) { |
| 1682 | if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { | 1606 | // [Inferno] < |
| 1683 | // handle most cases here (ch is a BMP code point or a | 1607 | return rindex(ch, fromIndex, false); |
| 1684 | // negative value (invalid code point)) | 1608 | // [Inferno] > |
| 1685 | final char[] value = this.value; | ||
| 1686 | final int offset = this.offset; | ||
| 1687 | int i = offset + Math.min(fromIndex, count - 1); | ||
| 1688 | for (; i >= offset ; i--) { | ||
| 1689 | if (value[i] == ch) { | ||
| 1690 | return i - offset; | ||
| 1691 | } | ||
| 1692 | } | ||
| 1693 | return -1; | ||
| 1694 | } else { | ||
| 1695 | return lastIndexOfSupplementary(ch, fromIndex); | ||
| 1696 | } | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | /** | ||
| 1700 | * Handles (rare) calls of lastIndexOf with a supplementary character. | ||
| 1701 | */ | ||
| 1702 | private int lastIndexOfSupplementary(int ch, int fromIndex) { | ||
| 1703 | if (Character.isValidCodePoint(ch)) { | ||
| 1704 | final char[] value = this.value; | ||
| 1705 | final int offset = this.offset; | ||
| 1706 | char hi = Character.highSurrogate(ch); | ||
| 1707 | char lo = Character.lowSurrogate(ch); | ||
| 1708 | int i = offset + Math.min(fromIndex, count - 2); | ||
| 1709 | for (; i >= offset; i--) { | ||
| 1710 | if (value[i] == hi && value[i+1] == lo) { | ||
| 1711 | return i - offset; | ||
| 1712 | } | ||
| 1713 | } | ||
| 1714 | } | ||
| 1715 | return -1; | ||
| 1716 | } | 1609 | } |
| 1717 | 1610 | ||
| 1718 | /** | 1611 | /** |
| @@ -1730,7 +1623,9 @@ public final class String · 11 unmodified lines | |||
| 1730 | * or {@code -1} if there is no such occurrence. | 1623 | * or {@code -1} if there is no such occurrence. |
| 1731 | */ | 1624 | */ |
| 1732 | public int indexOf(String str) { | 1625 | public int indexOf(String str) { |
| 1733 | return indexOf(str, 0); | 1626 | // [Inferno] < |
| 1627 | return index(str, 0); | ||
| 1628 | // [Inferno] > | ||
| 1734 | } | 1629 | } |
| 1735 | 1630 | ||
| 1736 | /** | 1631 | /** |
| @@ -1750,8 +1645,9 @@ public final class String · 13 unmodified lines | |||
| 1750 | * or {@code -1} if there is no such occurrence. | 1645 | * or {@code -1} if there is no such occurrence. |
| 1751 | */ | 1646 | */ |
| 1752 | public int indexOf(String str, int fromIndex) { | 1647 | public int indexOf(String str, int fromIndex) { |
| 1753 | return indexOf(value, offset, count, | 1648 | // [Inferno] < |
| 1754 | str.value, str.offset, str.count, fromIndex); | 1649 | return index(str, fromIndex); |
| 1650 | // [Inferno] > | ||
| 1755 | } | 1651 | } |
| 1756 | 1652 | ||
| 1757 | /** | 1653 | /** |
| @@ -1821,7 +1717,9 @@ public final class String · 63 unmodified lines | |||
| 1821 | * or {@code -1} if there is no such occurrence. | 1717 | * or {@code -1} if there is no such occurrence. |
| 1822 | */ | 1718 | */ |
| 1823 | public int lastIndexOf(String str) { | 1719 | public int lastIndexOf(String str) { |
| 1824 | return lastIndexOf(str, count); | 1720 | // [Inferno] < |
| 1721 | return rindex(str, 0, true); | ||
| 1722 | // [Inferno] > | ||
| 1825 | } | 1723 | } |
| 1826 | 1724 | ||
| 1827 | /** | 1725 | /** |
| @@ -1841,8 +1739,9 @@ public final class String · 13 unmodified lines | |||
| 1841 | * or {@code -1} if there is no such occurrence. | 1739 | * or {@code -1} if there is no such occurrence. |
| 1842 | */ | 1740 | */ |
| 1843 | public int lastIndexOf(String str, int fromIndex) { | 1741 | public int lastIndexOf(String str, int fromIndex) { |
| 1844 | return lastIndexOf(value, offset, count, | 1742 | // [Inferno] < |
| 1845 | str.value, str.offset, str.count, fromIndex); | 1743 | return rindex(str, fromIndex, false); |
| 1744 | // [Inferno] > | ||
| 1846 | } | 1745 | } |
| 1847 | 1746 | ||
| 1848 | /** | 1747 | /** |
| @@ -1922,7 +1821,7 @@ public final class String · 73 unmodified lines | |||
| 1922 | * length of this <code>String</code> object. | 1821 | * length of this <code>String</code> object. |
| 1923 | */ | 1822 | */ |
| 1924 | public String substring(int beginIndex) { | 1823 | public String substring(int beginIndex) { |
| 1925 | return substring(beginIndex, count); | 1824 | return substring(beginIndex, length()); |
| 1926 | } | 1825 | } |
| 1927 | 1826 | ||
| 1928 | /** | 1827 | /** |
| @@ -1947,19 +1846,9 @@ public final class String · 18 unmodified lines | |||
| 1947 | * <code>beginIndex</code> is larger than | 1846 | * <code>beginIndex</code> is larger than |
| 1948 | * <code>endIndex</code>. | 1847 | * <code>endIndex</code>. |
| 1949 | */ | 1848 | */ |
| 1950 | public String substring(int beginIndex, int endIndex) { | 1849 | // [Inferno] < |
| 1951 | if (beginIndex < 0) { | 1850 | public native String substring(int beginIndex, int endIndex); |
| 1952 | throw new StringIndexOutOfBoundsException(beginIndex); | 1851 | // [Inferno] > |
| 1953 | } | ||
| 1954 | if (endIndex > count) { | ||
| 1955 | throw new StringIndexOutOfBoundsException(endIndex); | ||
| 1956 | } | ||
| 1957 | if (beginIndex > endIndex) { | ||
| 1958 | throw new StringIndexOutOfBoundsException(endIndex - beginIndex); | ||
| 1959 | } | ||
| 1960 | return ((beginIndex == 0) && (endIndex == count)) ? this : | ||
| 1961 | new String(offset + beginIndex, endIndex - beginIndex, value); | ||
| 1962 | } | ||
| 1963 | 1852 | ||
| 1964 | /** | 1853 | /** |
| 1965 | * Returns a new character sequence that is a subsequence of this sequence. | 1854 | * Returns a new character sequence that is a subsequence of this sequence. |
| @@ -2018,6 +1907,7 @@ public final class String · 52 unmodified lines | |||
| 2018 | if (otherLen == 0) { | 1907 | if (otherLen == 0) { |
| 2019 | return this; | 1908 | return this; |
| 2020 | } | 1909 | } |
| 1910 | int count = length(); | ||
| 2021 | char buf[] = new char[count + otherLen]; | 1911 | char buf[] = new char[count + otherLen]; |
| 2022 | getChars(0, count, buf, 0); | 1912 | getChars(0, count, buf, 0); |
| 2023 | str.getChars(0, otherLen, buf, count); | 1913 | str.getChars(0, otherLen, buf, count); |
| @@ -2055,28 +1945,29 @@ public final class String · 31 unmodified lines | |||
| 2055 | */ | 1945 | */ |
| 2056 | public String replace(char oldChar, char newChar) { | 1946 | public String replace(char oldChar, char newChar) { |
| 2057 | if (oldChar != newChar) { | 1947 | if (oldChar != newChar) { |
| 2058 | int len = count; | 1948 | // [Inferno] < |
| 2059 | int i = -1; | 1949 | int i = -1; |
| 2060 | char[] val = value; /* avoid getfield opcode */ | 1950 | int len = length(); |
| 2061 | int off = offset; /* avoid getfield opcode */ | 1951 | char[] val = toCharArray(); |
| 2062 | 1952 | ||
| 2063 | while (++i < len) { | 1953 | while (++i < len) { |
| 2064 | if (val[off + i] == oldChar) { | 1954 | if (val[i] == oldChar) { |
| 2065 | break; | 1955 | break; |
| 2066 | } | 1956 | } |
| 2067 | } | 1957 | } |
| 2068 | if (i < len) { | 1958 | if (i < len) { |
| 2069 | char buf[] = new char[len]; | 1959 | char buf[] = new char[len]; |
| 2070 | for (int j = 0 ; j < i ; j++) { | 1960 | for (int j = 0 ; j < i ; j++) { |
| 2071 | buf[j] = val[off+j]; | 1961 | buf[j] = val[j]; |
| 2072 | } | 1962 | } |
| 2073 | while (i < len) { | 1963 | while (i < len) { |
| 2074 | char c = val[off + i]; | 1964 | char c = val[i]; |
| 2075 | buf[i] = (c == oldChar) ? newChar : c; | 1965 | buf[i] = (c == oldChar) ? newChar : c; |
| 2076 | i++; | 1966 | i++; |
| 2077 | } | 1967 | } |
| 2078 | return new String(0, len, buf); | 1968 | return new String(0, len, buf); |
| 2079 | } | 1969 | } |
| 1970 | // [Inferno] > | ||
| 2080 | } | 1971 | } |
| 2081 | return this; | 1972 | return this; |
| 2082 | } | 1973 | } |
| @@ -2317,7 +2208,9 @@ public final class String · 234 unmodified lines | |||
| 2317 | the second is not the ascii digit or ascii letter. | 2208 | the second is not the ascii digit or ascii letter. |
| 2318 | */ | 2209 | */ |
| 2319 | char ch = 0; | 2210 | char ch = 0; |
| 2320 | if (((regex.count == 1 && | 2211 | // [Inferno] < |
| 2212 | int count = length(); | ||
| 2213 | if (((regex.length() == 1 && | ||
| 2321 | ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || | 2214 | ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || |
| 2322 | (regex.length() == 2 && | 2215 | (regex.length() == 2 && |
| 2323 | regex.charAt(0) == '\\' && | 2216 | regex.charAt(0) == '\\' && |
| @@ -2359,6 +2252,7 @@ public final class String · 35 unmodified lines | |||
| 2359 | return list.subList(0, resultSize).toArray(result); | 2252 | return list.subList(0, resultSize).toArray(result); |
| 2360 | } | 2253 | } |
| 2361 | return Pattern.compile(regex).split(this, limit); | 2254 | return Pattern.compile(regex).split(this, limit); |
| 2255 | // [Inferno] > | ||
| 2362 | } | 2256 | } |
| 2363 | 2257 | ||
| 2364 | /** | 2258 | /** |
| @@ -2456,97 +2350,9 @@ public final class String · 91 unmodified lines | |||
| 2456 | * @since 1.1 | 2350 | * @since 1.1 |
| 2457 | */ | 2351 | */ |
| 2458 | public String toLowerCase(Locale locale) { | 2352 | public String toLowerCase(Locale locale) { |
| 2459 | if (locale == null) { | 2353 | // [Inferno] < |
| 2460 | throw new NullPointerException(); | 2354 | return lowercase(); |
| 2461 | } | 2355 | // [Inferno] > |
| 2462 | |||
| 2463 | int firstUpper; | ||
| 2464 | |||
| 2465 | /* Now check if there are any characters that need to be changed. */ | ||
| 2466 | scan: { | ||
| 2467 | for (firstUpper = 0 ; firstUpper < count; ) { | ||
| 2468 | char c = value[offset+firstUpper]; | ||
| 2469 | if ((c >= Character.MIN_HIGH_SURROGATE) && | ||
| 2470 | (c <= Character.MAX_HIGH_SURROGATE)) { | ||
| 2471 | int supplChar = codePointAt(firstUpper); | ||
| 2472 | if (supplChar != Character.toLowerCase(supplChar)) { | ||
| 2473 | break scan; | ||
| 2474 | } | ||
| 2475 | firstUpper += Character.charCount(supplChar); | ||
| 2476 | } else { | ||
| 2477 | if (c != Character.toLowerCase(c)) { | ||
| 2478 | break scan; | ||
| 2479 | } | ||
| 2480 | firstUpper++; | ||
| 2481 | } | ||
| 2482 | } | ||
| 2483 | return this; | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | char[] result = new char[count]; | ||
| 2487 | int resultOffset = 0; /* result may grow, so i+resultOffset | ||
| 2488 | * is the write location in result */ | ||
| 2489 | |||
| 2490 | /* Just copy the first few lowerCase characters. */ | ||
| 2491 | System.arraycopy(value, offset, result, 0, firstUpper); | ||
| 2492 | |||
| 2493 | String lang = locale.getLanguage(); | ||
| 2494 | boolean localeDependent = | ||
| 2495 | (lang == "tr" || lang == "az" || lang == "lt"); | ||
| 2496 | char[] lowerCharArray; | ||
| 2497 | int lowerChar; | ||
| 2498 | int srcChar; | ||
| 2499 | int srcCount; | ||
| 2500 | for (int i = firstUpper; i < count; i += srcCount) { | ||
| 2501 | srcChar = (int)value[offset+i]; | ||
| 2502 | if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && | ||
| 2503 | (char)srcChar <= Character.MAX_HIGH_SURROGATE) { | ||
| 2504 | srcChar = codePointAt(i); | ||
| 2505 | srcCount = Character.charCount(srcChar); | ||
| 2506 | } else { | ||
| 2507 | srcCount = 1; | ||
| 2508 | } | ||
| 2509 | if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA | ||
| 2510 | lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale); | ||
| 2511 | } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT | ||
| 2512 | lowerChar = Character.ERROR; | ||
| 2513 | } else { | ||
| 2514 | lowerChar = Character.toLowerCase(srcChar); | ||
| 2515 | } | ||
| 2516 | if ((lowerChar == Character.ERROR) || | ||
| 2517 | (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { | ||
| 2518 | if (lowerChar == Character.ERROR) { | ||
| 2519 | if (!localeDependent && srcChar == '\u0130') { | ||
| 2520 | lowerCharArray = | ||
| 2521 | ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH); | ||
| 2522 | } else { | ||
| 2523 | lowerCharArray = | ||
| 2524 | ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale); | ||
| 2525 | } | ||
| 2526 | } else if (srcCount == 2) { | ||
| 2527 | resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount; | ||
| 2528 | continue; | ||
| 2529 | } else { | ||
| 2530 | lowerCharArray = Character.toChars(lowerChar); | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | /* Grow result if needed */ | ||
| 2534 | int mapLen = lowerCharArray.length; | ||
| 2535 | if (mapLen > srcCount) { | ||
| 2536 | char[] result2 = new char[result.length + mapLen - srcCount]; | ||
| 2537 | System.arraycopy(result, 0, result2, 0, | ||
| 2538 | i + resultOffset); | ||
| 2539 | result = result2; | ||
| 2540 | } | ||
| 2541 | for (int x=0; x<mapLen; ++x) { | ||
| 2542 | result[i+resultOffset+x] = lowerCharArray[x]; | ||
| 2543 | } | ||
| 2544 | resultOffset += (mapLen - srcCount); | ||
| 2545 | } else { | ||
| 2546 | result[i+resultOffset] = (char)lowerChar; | ||
| 2547 | } | ||
| 2548 | } | ||
| 2549 | return new String(0, count+resultOffset, result); | ||
| 2550 | } | 2356 | } |
| 2551 | 2357 | ||
| 2552 | /** | 2358 | /** |
| @@ -2569,7 +2375,7 @@ public final class String · 16 unmodified lines | |||
| 2569 | * @see java.lang.String#toLowerCase(Locale) | 2375 | * @see java.lang.String#toLowerCase(Locale) |
| 2570 | */ | 2376 | */ |
| 2571 | public String toLowerCase() { | 2377 | public String toLowerCase() { |
| 2572 | return toLowerCase(Locale.getDefault()); | 2378 | return lowercase(); |
| 2573 | } | 2379 | } |
| 2574 | 2380 | ||
| 2575 | /** | 2381 | /** |
| @@ -2621,95 +2427,9 @@ public final class String · 45 unmodified lines | |||
| 2621 | * @since 1.1 | 2427 | * @since 1.1 |
| 2622 | */ | 2428 | */ |
| 2623 | public String toUpperCase(Locale locale) { | 2429 | public String toUpperCase(Locale locale) { |
| 2624 | if (locale == null) { | 2430 | // [Inferno] < |
| 2625 | throw new NullPointerException(); | 2431 | return uppercase(); |
| 2626 | } | 2432 | // [Inferno] > |
| 2627 | |||
| 2628 | int firstLower; | ||
| 2629 | |||
| 2630 | /* Now check if there are any characters that need to be changed. */ | ||
| 2631 | scan: { | ||
| 2632 | for (firstLower = 0 ; firstLower < count; ) { | ||
| 2633 | int c = (int)value[offset+firstLower]; | ||
| 2634 | int srcCount; | ||
| 2635 | if ((c >= Character.MIN_HIGH_SURROGATE) && | ||
| 2636 | (c <= Character.MAX_HIGH_SURROGATE)) { | ||
| 2637 | c = codePointAt(firstLower); | ||
| 2638 | srcCount = Character.charCount(c); | ||
| 2639 | } else { | ||
| 2640 | srcCount = 1; | ||
| 2641 | } | ||
| 2642 | int upperCaseChar = Character.toUpperCaseEx(c); | ||
| 2643 | if ((upperCaseChar == Character.ERROR) || | ||
| 2644 | (c != upperCaseChar)) { | ||
| 2645 | break scan; | ||
| 2646 | } | ||
| 2647 | firstLower += srcCount; | ||
| 2648 | } | ||
| 2649 | return this; | ||
| 2650 | } | ||
| 2651 | |||
| 2652 | char[] result = new char[count]; /* may grow */ | ||
| 2653 | int resultOffset = 0; /* result may grow, so i+resultOffset | ||
| 2654 | * is the write location in result */ | ||
| 2655 | |||
| 2656 | /* Just copy the first few upperCase characters. */ | ||
| 2657 | System.arraycopy(value, offset, result, 0, firstLower); | ||
| 2658 | |||
| 2659 | String lang = locale.getLanguage(); | ||
| 2660 | boolean localeDependent = | ||
| 2661 | (lang == "tr" || lang == "az" || lang == "lt"); | ||
| 2662 | char[] upperCharArray; | ||
| 2663 | int upperChar; | ||
| 2664 | int srcChar; | ||
| 2665 | int srcCount; | ||
| 2666 | for (int i = firstLower; i < count; i += srcCount) { | ||
| 2667 | srcChar = (int)value[offset+i]; | ||
| 2668 | if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && | ||
| 2669 | (char)srcChar <= Character.MAX_HIGH_SURROGATE) { | ||
| 2670 | srcChar = codePointAt(i); | ||
| 2671 | srcCount = Character.charCount(srcChar); | ||
| 2672 | } else { | ||
| 2673 | srcCount = 1; | ||
| 2674 | } | ||
| 2675 | if (localeDependent) { | ||
| 2676 | upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale); | ||
| 2677 | } else { | ||
| 2678 | upperChar = Character.toUpperCaseEx(srcChar); | ||
| 2679 | } | ||
| 2680 | if ((upperChar == Character.ERROR) || | ||
| 2681 | (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { | ||
| 2682 | if (upperChar == Character.ERROR) { | ||
| 2683 | if (localeDependent) { | ||
| 2684 | upperCharArray = | ||
| 2685 | ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale); | ||
| 2686 | } else { | ||
| 2687 | upperCharArray = Character.toUpperCaseCharArray(srcChar); | ||
| 2688 | } | ||
| 2689 | } else if (srcCount == 2) { | ||
| 2690 | resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount; | ||
| 2691 | continue; | ||
| 2692 | } else { | ||
| 2693 | upperCharArray = Character.toChars(upperChar); | ||
| 2694 | } | ||
| 2695 | |||
| 2696 | /* Grow result if needed */ | ||
| 2697 | int mapLen = upperCharArray.length; | ||
| 2698 | if (mapLen > srcCount) { | ||
| 2699 | char[] result2 = new char[result.length + mapLen - srcCount]; | ||
| 2700 | System.arraycopy(result, 0, result2, 0, | ||
| 2701 | i + resultOffset); | ||
| 2702 | result = result2; | ||
| 2703 | } | ||
| 2704 | for (int x=0; x<mapLen; ++x) { | ||
| 2705 | result[i+resultOffset+x] = upperCharArray[x]; | ||
| 2706 | } | ||
| 2707 | resultOffset += (mapLen - srcCount); | ||
| 2708 | } else { | ||
| 2709 | result[i+resultOffset] = (char)upperChar; | ||
| 2710 | } | ||
| 2711 | } | ||
| 2712 | return new String(0, count+resultOffset, result); | ||
| 2713 | } | 2433 | } |
| 2714 | 2434 | ||
| 2715 | /** | 2435 | /** |
| @@ -2732,7 +2452,7 @@ public final class String · 16 unmodified lines | |||
| 2732 | * @see java.lang.String#toUpperCase(Locale) | 2452 | * @see java.lang.String#toUpperCase(Locale) |
| 2733 | */ | 2453 | */ |
| 2734 | public String toUpperCase() { | 2454 | public String toUpperCase() { |
| 2735 | return toUpperCase(Locale.getDefault()); | 2455 | return uppercase(); |
| 2736 | } | 2456 | } |
| 2737 | 2457 | ||
| 2738 | /** | 2458 | /** |
| @@ -2767,18 +2487,19 @@ public final class String · 28 unmodified lines | |||
| 2767 | * trailing white space. | 2487 | * trailing white space. |
| 2768 | */ | 2488 | */ |
| 2769 | public String trim() { | 2489 | public String trim() { |
| 2770 | int len = count; | 2490 | // [Inferno] < |
| 2771 | int st = 0; | 2491 | int st = 0; |
| 2772 | int off = offset; /* avoid getfield opcode */ | 2492 | int len = length(); |
| 2773 | char[] val = value; /* avoid getfield opcode */ | 2493 | char[] val = toCharArray(); |
| 2774 | 2494 | ||
| 2775 | while ((st < len) && (val[off + st] <= ' ')) { | 2495 | while ((st < len) && (val[st] <= ' ')) { |
| 2776 | st++; | 2496 | st++; |
| 2777 | } | 2497 | } |
| 2778 | while ((st < len) && (val[off + len - 1] <= ' ')) { | 2498 | while ((st < len) && (val[len - 1] <= ' ')) { |
| 2779 | len--; | 2499 | len--; |
| 2780 | } | 2500 | } |
| 2781 | return ((st > 0) || (len < count)) ? substring(st, len) : this; | 2501 | return ((st > 0) || (len < length())) ? substring(st, len) : this; |
| 2502 | // [Inferno] > | ||
| 2782 | } | 2503 | } |
| 2783 | 2504 | ||
| 2784 | /** | 2505 | /** |
| @@ -2798,6 +2519,9 @@ public final class String · 13 unmodified lines | |||
| 2798 | * the character sequence represented by this string. | 2519 | * the character sequence represented by this string. |
| 2799 | */ | 2520 | */ |
| 2800 | public char[] toCharArray() { | 2521 | public char[] toCharArray() { |
| 2522 | // [Inferno] < | ||
| 2523 | int count = length(); | ||
| 2524 | // [Inferno] > | ||
| 2801 | char result[] = new char[count]; | 2525 | char result[] = new char[count]; |
| 2802 | getChars(0, count, result, 0); | 2526 | getChars(0, count, result, 0); |
| 2803 | return result; | 2527 | return result; |
| @@ -3074,4 +2798,20 @@ public final class String · 270 unmodified lines | |||
| 3074 | */ | 2798 | */ |
| 3075 | public native String intern(); | 2799 | public native String intern(); |
| 3076 | 2800 | ||
| 2801 | // [Inferno] Some native platform-specific methods | ||
| 2802 | |||
| 2803 | private native boolean equality(String other, boolean ignoreCase); | ||
| 2804 | |||
| 2805 | private native void fill(char[] chars, int idx, int count); | ||
| 2806 | private native boolean isPrefix(String str, int index); | ||
| 2807 | private native boolean isSuffix(String str); | ||
| 2808 | private native String uppercase(); | ||
| 2809 | private native String lowercase(); | ||
| 2810 | |||
| 2811 | private native int index(String str, int begin); | ||
| 2812 | private native int index(int ch, int begin); | ||
| 2813 | |||
| 2814 | private native int rindex(String str, int begin, boolean fromend); | ||
| 2815 | private native int rindex(int ch, int begin, boolean fromend); | ||
| 2816 | |||
| 3077 | } | 2817 | } |