--- /home/tromey/gnu/Nightly/classpath/classpath/java/lang/String.java 2004-11-23 02:24:10.000000000 -0700 +++ java/lang/String.java 2004-11-25 02:16:35.000000000 -0700 @@ -1,5 +1,5 @@ /* String.java -- immutable character sequences; the object of string literals - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,14 +39,13 @@ package java.lang; -import gnu.java.io.EncodingManager; -import gnu.java.lang.CharData; - import java.io.Serializable; import java.io.UnsupportedEncodingException; +import java.lang.Comparable; import java.util.Comparator; import java.util.Locale; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; /** * Strings represent an immutable set of characters. All String literals @@ -72,7 +71,7 @@ * @author Eric Blake (ebb9@email.byu.edu) * @author Per Bothner (bothner@cygnus.com) * @since 1.0 - * @status updated to 1.4; but could use better data sharing via offset field + * @status updated to 1.4 */ public final class String implements Serializable, Comparable, CharSequence { @@ -86,33 +85,26 @@ private static final long serialVersionUID = -6849794470754667710L; /** - * Stores unicode multi-character uppercase expansion table. - * @see #toUpperCase(char) - * @see CharData#UPPER_EXPAND + * This is the object that holds the characters that make up the + * String. It might be a char[], or it could be String. It could + * even be `this'. The actual characters can't be located using + * pure Java code. + * @see #boffset */ - private static final char[] upperExpand - = zeroBasedStringValue(CharData.UPPER_EXPAND); + private Object data; /** - * Stores unicode multi-character uppercase special casing table. - * @see #upperCaseExpansion(char) - * @see CharData#UPPER_SPECIAL - */ - private static final char[] upperSpecial - = zeroBasedStringValue(CharData.UPPER_SPECIAL); - - /** - * Characters which make up the String. - * Package access is granted for use by StringBuffer. + * This is a byte offset of the actual characters from + * the start of the character-holding object. Don't use this field + * in Java code. */ - final char[] value; + private int boffset; /** - * Holds the number of characters in value. This number is generally - * the same as value.length, but can be smaller because substrings and - * StringBuffers can share arrays. Package visible for use by trusted code. + * Holds the number of characters in value. Package visible for use + * by trusted code. */ - final int count; + int count; /** * Caches the result of hashCode(). If this value is zero, the hashcode @@ -121,13 +113,6 @@ private int cachedHashCode; /** - * Holds the starting position for characters in value[]. Since - * substring()'s are common, the use of offset allows the operation - * to perform in O(1). Package access is granted for use by StringBuffer. - */ - final int offset; - - /** * An implementation for {@link CASE_INSENSITIVE_ORDER}. * This must be {@link Serializable}. The class name is dictated by * compatibility with Sun's JDK. @@ -180,8 +165,8 @@ */ public String() { - value = "".value; - offset = 0; + data = "".data; + boffset = 0; count = 0; } @@ -194,8 +179,8 @@ */ public String(String str) { - value = str.value; - offset = str.offset; + data = str.data; + boffset = str.boffset; count = str.count; cachedHashCode = str.cachedHashCode; } @@ -209,7 +194,7 @@ */ public String(char[] data) { - this(data, 0, data.length, false); + init(data, 0, data.length, false); } /** @@ -227,7 +212,7 @@ */ public String(char[] data, int offset, int count) { - this(data, offset, count, false); + init(data, offset, count, false); } /** @@ -256,15 +241,7 @@ */ public String(byte[] ascii, int hibyte, int offset, int count) { - if (offset < 0 || count < 0 || offset + count > ascii.length) - throw new StringIndexOutOfBoundsException(); - value = new char[count]; - this.offset = 0; - this.count = count; - hibyte <<= 8; - offset += count; - while (--count >= 0) - value[count] = (char) (hibyte | (ascii[--offset] & 0xff)); + init(ascii, hibyte, offset, count); } /** @@ -289,7 +266,7 @@ */ public String(byte[] ascii, int hibyte) { - this(ascii, hibyte, 0, ascii.length); + init(ascii, hibyte, 0, ascii.length); } /** @@ -316,13 +293,7 @@ public String(byte[] data, int offset, int count, String encoding) throws UnsupportedEncodingException { - if (offset < 0 || count < 0 || offset + count > data.length) - throw new StringIndexOutOfBoundsException(); - // XXX Consider using java.nio here. - value = EncodingManager.getDecoder(encoding) - .convertToChars(data, offset, count); - this.offset = 0; - this.count = value.length; + init (data, offset, count, encoding); } /** @@ -368,13 +339,23 @@ */ public String(byte[] data, int offset, int count) { - if (offset < 0 || count < 0 || offset + count > data.length) - throw new StringIndexOutOfBoundsException(); - // XXX Consider using java.nio here. - value = EncodingManager.getDecoder() - .convertToChars(data, offset, count); - this.offset = 0; - this.count = value.length; + try + { + init (data, offset, count, + System.getProperty("file.encoding", "8859_1")); + } + catch (UnsupportedEncodingException x1) + { + // Maybe the default encoding is bad. + try + { + init (data, offset, count, "8859_1"); + } + catch (UnsupportedEncodingException x2) + { + // We know this can't happen. + } + } } /** @@ -408,19 +389,11 @@ { synchronized (buffer) { - offset = 0; - count = buffer.count; - // Share unless buffer is 3/4 empty. - if ((count << 2) < buffer.value.length) - { - value = new char[count]; - System.arraycopy(buffer.value, 0, value, 0, count); - } - else - { - buffer.shared = true; - value = buffer.value; - } + // Share unless buffer is 3/4 empty. + boolean should_copy = ((buffer.count << 2) < buffer.value.length); + if (! should_copy) + buffer.shared = true; + init (buffer.value, 0, buffer.count, ! should_copy); } } @@ -436,20 +409,17 @@ */ String(char[] data, int offset, int count, boolean dont_copy) { - if (offset < 0 || count < 0 || offset + count > data.length) - throw new StringIndexOutOfBoundsException(); - if (dont_copy) - { - value = data; - this.offset = offset; - } - else - { - value = new char[count]; - System.arraycopy(data, offset, value, 0, count); - this.offset = 0; - } - this.count = count; + init(data, offset, count, dont_copy); + } + + // This is used by gnu.gcj.runtime.StringBuffer, so it must have + // package-private protection. It is accessed via CNI and so avoids + // ordinary protection mechanisms. + String(gnu.gcj.runtime.StringBuffer buffer) + { + // No need to synchronize or mark the buffer, since we know it is + // only used once. + init (buffer); } /** @@ -470,12 +440,7 @@ * @throws IndexOutOfBoundsException if index < 0 || index >= length() * (while unspecified, this is a StringIndexOutOfBoundsException) */ - public char charAt(int index) - { - if (index < 0 || index >= count) - throw new StringIndexOutOfBoundsException(index); - return value[offset + index]; - } + public native char charAt(int index); /** * Copies characters from this String starting at a specified start index, @@ -492,13 +457,8 @@ * StringIndexOutOfBoundsException, and dst problems cause an * ArrayIndexOutOfBoundsException) */ - public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) - { - if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) - throw new StringIndexOutOfBoundsException(); - System.arraycopy(value, srcBegin + offset, - dst, dstBegin, srcEnd - srcBegin); - } + public native void getChars(int srcBegin, int srcEnd, + char[] dst, int dstBegin); /** * Copies the low byte of each character from this String starting at a @@ -518,52 +478,57 @@ * @see #getBytes(String) * @deprecated use {@link #getBytes()}, which uses a char to byte encoder */ - public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) - { - if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) - throw new StringIndexOutOfBoundsException(); - int i = srcEnd - srcBegin; - srcBegin += offset; - while (--i >= 0) - dst[dstBegin++] = (byte) value[srcBegin++]; - } + public native void getBytes(int srcBegin, int srcEnd, + byte[] dst, int dstBegin); /** * Converts the Unicode characters in this String to a byte array. Uses the * specified encoding method, so the result may be longer or shorter than * the String. For more encoding control, use * {@link java.nio.charset.CharsetEncoder}, and for valid character sets, - * see {@link java.nio.charset.Charset}. Unsupported characters get - * replaced by an encoding specific byte. + * see {@link java.nio.charset.Charset}. The behavior is not specified if + * the encoder encounters a problem; this implementation returns null. * * @param enc encoding name - * @return the resulting byte array + * @return the resulting byte array, or null on a problem * @throws NullPointerException if enc is null * @throws UnsupportedEncodingException if encoding is not supported * @since 1.1 */ - public byte[] getBytes(String enc) throws UnsupportedEncodingException - { - // XXX Consider using java.nio here. - return EncodingManager.getEncoder(enc) - .convertToBytes(value, offset, count); - } + public native byte[] getBytes(String enc) + throws UnsupportedEncodingException; /** * Converts the Unicode characters in this String to a byte array. Uses the * encoding of the platform's default charset, so the result may be longer * or shorter than the String. For more encoding control, use - * {@link java.nio.charset.CharsetEncoder}. Unsupported characters get - * replaced by an encoding specific byte. + * {@link java.nio.charset.CharsetEncoder}. The behavior is not specified if + * the encoder encounters a problem; this implementation returns null. * * @return the resulting byte array, or null on a problem * @since 1.1 */ public byte[] getBytes() { - // XXX Consider using java.nio here. - return EncodingManager.getEncoder() - .convertToBytes(value, offset, count); + try + { + return getBytes (System.getProperty("file.encoding", "8859_1")); + } + catch (UnsupportedEncodingException x) + { + // This probably shouldn't happen, but could if file.encoding + // is somehow changed to a value we don't understand. + try + { + return getBytes ("8859_1"); + } + catch (UnsupportedEncodingException x2) + { + // This really shouldn't happen, because the 8859_1 + // encoding should always be available. + throw new InternalError ("couldn't find 8859_1 encoder"); + } + } } /** @@ -575,23 +540,7 @@ * @see #compareTo(String) * @see #equalsIgnoreCase(String) */ - public boolean equals(Object anObject) - { - if (! (anObject instanceof String)) - return false; - String str2 = (String) anObject; - if (count != str2.count) - return false; - if (value == str2.value && offset == str2.offset) - return true; - int i = count; - int x = offset; - int y = str2.offset; - while (--i >= 0) - if (value[x++] != str2.value[y++]) - return false; - return true; - } + public native boolean equals(Object anObject); /** * Compares the given StringBuffer to this String. This is true if the @@ -602,22 +551,7 @@ * @throws NullPointerException if the given StringBuffer is null * @since 1.4 */ - public boolean contentEquals(StringBuffer buffer) - { - synchronized (buffer) - { - if (count != buffer.count) - return false; - if (value == buffer.value) - return true; // Possible if shared. - int i = count; - int x = offset + count; - while (--i >= 0) - if (value[--x] != buffer.value[i]) - return false; - return true; - } - } + public native boolean contentEquals(StringBuffer buffer); /** * Compares a String to this String, ignoring case. This does not handle @@ -636,25 +570,7 @@ * @see Character#toUpperCase(char) * @see Character#toLowerCase(char) */ - public boolean equalsIgnoreCase(String anotherString) - { - if (anotherString == null || count != anotherString.count) - return false; - int i = count; - int x = offset; - int y = anotherString.offset; - while (--i >= 0) - { - char c1 = value[x++]; - char c2 = anotherString.value[y++]; - // Note that checking c1 != c2 is redundant, but avoids method calls. - if (c1 != c2 - && Character.toUpperCase(c1) != Character.toUpperCase(c2) - && Character.toLowerCase(c1) != Character.toLowerCase(c2)) - return false; - } - return true; - } + public native boolean equalsIgnoreCase(String anotherString); /** * Compares this String and another String (case sensitive, @@ -670,19 +586,7 @@ * @return the comparison * @throws NullPointerException if anotherString is null */ - public int compareTo(String anotherString) - { - int i = Math.min(count, anotherString.count); - int x = offset; - int y = anotherString.offset; - while (--i >= 0) - { - int result = value[x++] - anotherString.value[y++]; - if (result != 0) - return result; - } - return count - anotherString.count; - } + public native int compareTo(String anotherString); /** * Behaves like compareTo(java.lang.String) unless the Object @@ -716,17 +620,8 @@ */ public int compareToIgnoreCase(String str) { - int i = Math.min(count, str.count); - int x = offset; - int y = str.offset; - while (--i >= 0) - { - int result = Character.toLowerCase(Character.toUpperCase(value[x++])) - - Character.toLowerCase(Character.toUpperCase(str.value[y++])); - if (result != 0) - return result; - } - return count - str.count; + return this.toUpperCase().toLowerCase().compareTo( + str.toUpperCase().toLowerCase()); } /** @@ -742,10 +637,8 @@ * @return true if regions match (case sensitive) * @throws NullPointerException if other is null */ - public boolean regionMatches(int toffset, String other, int ooffset, int len) - { - return regionMatches(false, toffset, other, ooffset, len); - } + public native boolean regionMatches(int toffset, + String other, int ooffset, int len); /** * Predicate which determines if this String matches another String @@ -764,29 +657,8 @@ * @return true if regions match, false otherwise * @throws NullPointerException if other is null */ - public boolean regionMatches(boolean ignoreCase, int toffset, - String other, int ooffset, int len) - { - if (toffset < 0 || ooffset < 0 || toffset + len > count - || ooffset + len > other.count) - return false; - toffset += offset; - ooffset += other.offset; - while (--len >= 0) - { - char c1 = value[toffset++]; - char c2 = other.value[ooffset++]; - // Note that checking c1 != c2 is redundant when ignoreCase is true, - // but it avoids method calls. - if (c1 != c2 - && (! ignoreCase - || (Character.toLowerCase(c1) != Character.toLowerCase(c2) - && (Character.toUpperCase(c1) - != Character.toUpperCase(c2))))) - return false; - } - return true; - } + public native boolean regionMatches(boolean ignoreCase, int toffset, + String other, int ooffset, int len); /** * Predicate which determines if this String contains the given prefix, @@ -800,10 +672,7 @@ * @throws NullPointerException if prefix is null * @see #regionMatches(boolean, int, String, int, int) */ - public boolean startsWith(String prefix, int toffset) - { - return regionMatches(false, toffset, prefix, 0, prefix.count); - } + public native boolean startsWith(String prefix, int toffset); /** * Predicate which determines if this String starts with a given prefix. @@ -816,7 +685,7 @@ */ public boolean startsWith(String prefix) { - return regionMatches(false, 0, prefix, 0, prefix.count); + return startsWith (prefix, 0); } /** @@ -830,7 +699,7 @@ */ public boolean endsWith(String suffix) { - return regionMatches(false, count - suffix.count, suffix, 0, suffix.count); + return regionMatches (this.count - suffix.count, suffix, 0, suffix.count); } /** @@ -840,18 +709,7 @@ * * @return hashcode value of this String */ - public int hashCode() - { - if (cachedHashCode != 0) - return cachedHashCode; - - // Compute the hash code using a local variable to be reentrant. - int hashCode = 0; - int limit = count + offset; - for (int i = offset; i < limit; i++) - hashCode = hashCode * 31 + value[i]; - return cachedHashCode = hashCode; - } + public native int hashCode(); /** * Finds the first instance of a character in this String. @@ -874,18 +732,7 @@ * @param fromIndex index to start the search * @return location (base 0) of the character, or -1 if not found */ - public int indexOf(int ch, int fromIndex) - { - if ((char) ch != ch) - return -1; - if (fromIndex < 0) - fromIndex = 0; - int i = fromIndex + offset; - for ( ; fromIndex < count; fromIndex++) - if (value[i++] == ch) - return fromIndex; - return -1; - } + public native int indexOf(int ch, int fromIndex); /** * Finds the last instance of a character in this String. @@ -908,18 +755,7 @@ * @param fromIndex index to start the search * @return location (base 0) of the character, or -1 if not found */ - public int lastIndexOf(int ch, int fromIndex) - { - if ((char) ch != ch) - return -1; - if (fromIndex >= count) - fromIndex = count - 1; - int i = fromIndex + offset; - for ( ; fromIndex >= 0; fromIndex--) - if (value[i--] == ch) - return fromIndex; - return -1; - } + public native int lastIndexOf(int ch, int fromIndex); /** * Finds the first instance of a String in this String. @@ -944,16 +780,7 @@ * @return location (base 0) of the String, or -1 if not found * @throws NullPointerException if str is null */ - public int indexOf(String str, int fromIndex) - { - if (fromIndex < 0) - fromIndex = 0; - int limit = count - str.count; - for ( ; fromIndex <= limit; fromIndex++) - if (regionMatches(fromIndex, str, 0, str.count)) - return fromIndex; - return -1; - } + public native int indexOf(String str, int fromIndex); /** * Finds the last instance of a String in this String. @@ -980,11 +807,15 @@ */ public int lastIndexOf(String str, int fromIndex) { - fromIndex = Math.min(fromIndex, count - str.count); - for ( ; fromIndex >= 0; fromIndex--) - if (regionMatches(fromIndex, str, 0, str.count)) - return fromIndex; - return -1; + if (fromIndex >= count) + fromIndex = count - str.count; + for (;; --fromIndex) + { + if (fromIndex < 0) + return -1; + if (startsWith(str, fromIndex)) + return fromIndex; + } } /** @@ -1012,17 +843,7 @@ * || begin > end (while unspecified, this is a * StringIndexOutOfBoundsException) */ - public String substring(int beginIndex, int endIndex) - { - if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) - throw new StringIndexOutOfBoundsException(); - if (beginIndex == 0 && endIndex == count) - return this; - int len = endIndex - beginIndex; - // Package constructor avoids an array copy. - return new String(value, beginIndex + offset, len, - (len << 2) >= value.length); - } + public native String substring(int begin, int end); /** * Creates a substring of this String, starting at a specified index @@ -1049,18 +870,7 @@ * @return newly concatenated String * @throws NullPointerException if str is null */ - public String concat(String str) - { - if (str.count == 0) - return this; - if (count == 0) - return str; - char[] newStr = new char[count + str.count]; - System.arraycopy(value, offset, newStr, 0, count); - System.arraycopy(str.value, str.offset, newStr, count, str.count); - // Package constructor avoids an array copy. - return new String(newStr, 0, newStr.length, true); - } + public native String concat(String str); /** * Replaces every instance of a character in this String with a new @@ -1070,25 +880,7 @@ * @param newChar the new character * @return new String with all instances of oldChar replaced with newChar */ - public String replace(char oldChar, char newChar) - { - if (oldChar == newChar) - return this; - int i = count; - int x = offset - 1; - while (--i >= 0) - if (value[++x] == oldChar) - break; - if (i < 0) - return this; - char[] newStr = (char[]) value.clone(); - newStr[x] = newChar; - while (--i >= 0) - if (value[++x] == oldChar) - newStr[x] = newChar; - // Package constructor avoids an array copy. - return new String(newStr, offset, count, true); - } + public native String replace(char oldChar, char newChar); /** * Test if this String matches a regular expression. This is shorthand for @@ -1219,36 +1011,7 @@ * @see #toUpperCase(Locale) * @since 1.1 */ - public String toLowerCase(Locale loc) - { - // First, see if the current string is already lower case. - boolean turkish = "tr".equals(loc.getLanguage()); - int i = count; - int x = offset - 1; - while (--i >= 0) - { - char ch = value[++x]; - if ((turkish && ch == '\u0049') - || ch != Character.toLowerCase(ch)) - break; - } - if (i < 0) - return this; - - // Now we perform the conversion. Fortunately, there are no multi-character - // lowercase expansions in Unicode 3.0.0. - char[] newStr = (char[]) value.clone(); - do - { - char ch = value[x]; - // Hardcoded special case. - newStr[x++] = (turkish && ch == '\u0049') ? '\u0131' - : Character.toLowerCase(ch); - } - while (--i >= 0); - // Package constructor avoids an array copy. - return new String(newStr, offset, count, true); - } + public native String toLowerCase(Locale locale); /** * Lowercases this String. This uses Unicode's special case mappings, as @@ -1261,7 +1024,11 @@ */ public String toLowerCase() { - return toLowerCase(Locale.getDefault()); + // The JDK is a bit confused about what to do here. If we pass in + // the default Locale then special Locale handling might be + // invoked. However, the docs also say that Character.toLowerCase + // rules here. We go with the latter. + return toLowerCase (null); } /** @@ -1275,67 +1042,7 @@ * @see #toLowerCase(Locale) * @since 1.1 */ - public String toUpperCase(Locale loc) - { - // First, see how many characters we have to grow by, as well as if the - // current string is already upper case. - boolean turkish = "tr".equals(loc.getLanguage()); - int expand = 0; - boolean unchanged = true; - int i = count; - int x = i + offset; - while (--i >= 0) - { - char ch = value[--x]; - expand += upperCaseExpansion(ch); - unchanged = (unchanged && expand == 0 - && ! (turkish && ch == '\u0069') - && ch == Character.toUpperCase(ch)); - } - if (unchanged) - return this; - - // Now we perform the conversion. - i = count; - if (expand == 0) - { - char[] newStr = (char[]) value.clone(); - while (--i >= 0) - { - char ch = value[x]; - // Hardcoded special case. - newStr[x++] = (turkish && ch == '\u0069') ? '\u0130' - : Character.toUpperCase(ch); - } - // Package constructor avoids an array copy. - return new String(newStr, offset, count, true); - } - - // Expansion is necessary. - char[] newStr = new char[count + expand]; - int j = 0; - while (--i >= 0) - { - char ch = value[x++]; - // Hardcoded special case. - if (turkish && ch == '\u0069') - { - newStr[j++] = '\u0130'; - continue; - } - expand = upperCaseExpansion(ch); - if (expand > 0) - { - int index = upperCaseIndex(ch); - while (expand-- >= 0) - newStr[j++] = upperExpand[index++]; - } - else - newStr[j++] = Character.toUpperCase(ch); - } - // Package constructor avoids an array copy. - return new String(newStr, 0, newStr.length, true); - } + public native String toUpperCase(Locale locale); /** * Uppercases this String. This uses Unicode's special case mappings, as @@ -1348,7 +1055,11 @@ */ public String toUpperCase() { - return toUpperCase(Locale.getDefault()); + // The JDK is a bit confused about what to do here. If we pass in + // the default Locale then special Locale handling might be + // invoked. However, the docs also say that Character.toLowerCase + // rules here. We go with the latter. + return toUpperCase (null); } /** @@ -1359,21 +1070,7 @@ * * @return new trimmed String, or this if nothing trimmed */ - public String trim() - { - int limit = count + offset; - if (count == 0 || (value[offset] > '\u0020' - && value[limit - 1] > '\u0020')) - return this; - int begin = offset; - do - if (begin == limit) - return ""; - while (value[begin++] <= '\u0020'); - int end = limit; - while (value[--end] <= '\u0020'); - return substring(begin - offset - 1, end - offset + 1); - } + public native String trim(); /** * Returns this, as it is already a String! @@ -1391,16 +1088,7 @@ * * @return character array copying the String */ - public char[] toCharArray() - { - // XXX ORP 1.0.9 crashes on (char[]) clone() during bootstrap, so we - // omit this optimization for now. - // if (count == value.length) - // return (char[]) value.clone(); - char[] copy = new char[count]; - System.arraycopy(value, offset, copy, 0, count); - return copy; - } + public native char[] toCharArray(); /** * Returns a String representation of an Object. This is "null" if the @@ -1445,10 +1133,7 @@ * (while unspecified, this is a StringIndexOutOfBoundsException) * @see #String(char[], int, int) */ - public static String valueOf(char[] data, int offset, int count) - { - return new String(data, offset, count, false); - } + public static native String valueOf(char[] data, int offset, int count); /** * Returns a String representing the character sequence of the char array, @@ -1467,7 +1152,9 @@ */ public static String copyValueOf(char[] data, int offset, int count) { - return new String(data, offset, count, false); + String r = new String (); + r.init(data, offset, count, false); + return r; } /** @@ -1502,11 +1189,7 @@ * @param c the character * @return String containing the single character c */ - public static String valueOf(char c) - { - // Package constructor avoids an array copy. - return new String(new char[] { c }, 0, 1, true); - } + public static native String valueOf(char c); /** * Returns a String representing an integer. @@ -1515,11 +1198,7 @@ * @return String containing the integer in base 10 * @see Integer#toString(int) */ - public static String valueOf(int i) - { - // See Integer to understand why we call the two-arg variant. - return Integer.toString(i, 10); - } + public static native String valueOf(int i); /** * Returns a String representing a long. @@ -1558,88 +1237,21 @@ } /** - * If two Strings are considered equal, by the equals() method, - * then intern() will return the same String instance. ie. - * if (s1.equals(s2)) then (s1.intern() == s2.intern()). - * All string literals and string-valued constant expressions - * are already interned. + * Fetches this String from the intern hashtable. If two Strings are + * considered equal, by the equals() method, then intern() will return the + * same String instance. ie. if (s1.equals(s2)) then + * (s1.intern() == s2.intern()). All string literals and string-valued + * constant expressions are already interned. * * @return the interned String */ - public String intern() - { - return VMString.intern(this); - } + public native String intern(); - /** - * Helper function used to detect which characters have a multi-character - * uppercase expansion. Note that this is only used in locations which - * track one-to-many capitalization (java.lang.Character does not do this). - * As of Unicode 3.0.0, the result is limited in the range 0 to 2, as the - * longest uppercase expansion is three characters (a growth of 2 from the - * lowercase character). - * - * @param ch the char to check - * @return the number of characters to add when converting to uppercase - * @see CharData#DIRECTION - * @see CharData#UPPER_SPECIAL - * @see #toUpperCase(Locale) - */ - private static int upperCaseExpansion(char ch) - { - return Character.direction[Character.readChar(ch) >> 7] & 3; - } - /** - * Helper function used to locate the offset in upperExpand given a - * character with a multi-character expansion. The binary search is - * optimized under the assumption that this method will only be called on - * characters which exist in upperSpecial. - * - * @param ch the char to check - * @return the index where its expansion begins - * @see CharData#UPPER_SPECIAL - * @see CharData#UPPER_EXPAND - * @see #toUpperCase(Locale) - */ - private static int upperCaseIndex(char ch) - { - // Simple binary search for the correct character. - int low = 0; - int hi = upperSpecial.length - 2; - int mid = ((low + hi) >> 2) << 1; - char c = upperSpecial[mid]; - while (ch != c) - { - if (ch < c) - hi = mid - 2; - else - low = mid + 2; - mid = ((low + hi) >> 2) << 1; - c = upperSpecial[mid]; - } - return upperSpecial[mid + 1]; - } - - /** - * Returns the value array of the given string if it is zero based or a - * copy of it that is zero based (stripping offset and making length equal - * to count). Used for accessing the char[]s of gnu.java.lang.CharData. - * Package private for use in Character. - */ - static char[] zeroBasedStringValue(String s) - { - char[] value; - - if (s.offset == 0 && s.count == s.value.length) - value = s.value; - else - { - int count = s.count; - value = new char[count]; - System.arraycopy(s.value, s.offset, value, 0, count); - } - - return value; - } + private native void init(char[] chars, int offset, int count, + boolean dont_copy); + private native void init(byte[] chars, int hibyte, int offset, int count); + private native void init(byte[] chars, int offset, int count, String enc) + throws UnsupportedEncodingException; + private native void init(gnu.gcj.runtime.StringBuffer buffer); }