--- /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);
}