History

Refactored java.lang.String class to work with Inferno's jvm

Dmitry Kabak (userdima committed 13 years ago

Commit b7c872b1 parent d8adc111 file · +255 −515Browse files

Showing the changes to java/pkg/java/lang/String.java (1 of 1 file). Show all

Unified · Split

java/pkg/java/lang/String.java+255−515
@@ -110,14 +110,22 @@ import java.util.regex.PatternSyntaxException; · 109 unmodified lines
110public final class String110public final class String
111 implements java.io.Serializable, Comparable<String>, CharSequence111 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 0131 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 is153 * 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 represents162 * 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 new176 // // The array representing the String is bigger than the new
170 // String itself. Perhaps this constructor is being called177 // // 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 same182 // // 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 string204 * 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 length460 * @param length
431 * The number of bytes to decode461 * The number of bytes to decode
432 462 *
433 * @param charsetName463 * @param charsetName
434 * The name of a supported {@linkplain java.nio.charset.Charset464 * 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.5675 * @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 this698 * @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.6711 * @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 this734 * 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 specified742 * Returns the character (Unicode code point) at the specified
@@ -720,10 +761,11 @@ public final class String · 18 unmodified lines
720 * @since 1.5761 * @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.5791 * @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.5821 * @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.5849 * @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 than897 * <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. Each903 * 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 UnsupportedEncodingException987 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.11027 * @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.51088 * @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, StringBuilder1095 // 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 CharSequence1111 // 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 the1392 * 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. 01425 * @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 of1468 * 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 a1607 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 than1846 * <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.12350 * @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.12427 * @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}