diff options
Diffstat (limited to 'libjava/classpath/java/lang/String.java')
| -rw-r--r-- | libjava/classpath/java/lang/String.java | 2204 |
1 files changed, 0 insertions, 2204 deletions
diff --git a/libjava/classpath/java/lang/String.java b/libjava/classpath/java/lang/String.java deleted file mode 100644 index 27294cd..0000000 --- a/libjava/classpath/java/lang/String.java +++ /dev/null @@ -1,2204 +0,0 @@ -/* String.java -- immutable character sequences; the object of string literals - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.lang; - -import gnu.java.lang.CharData; -import gnu.java.lang.CPStringBuilder; - -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.UnsupportedCharsetException; -import java.text.Collator; -import java.util.Comparator; -import java.util.Formatter; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -/** - * Strings represent an immutable set of characters. All String literals - * are instances of this class, and two string literals with the same contents - * refer to the same String object. - * - * <p>This class also includes a number of methods for manipulating the - * contents of strings (of course, creating a new object if there are any - * changes, as String is immutable). Case mapping relies on Unicode 3.0.0 - * standards, where some character sequences have a different number of - * characters in the uppercase version than the lower case. - * - * <p>Strings are special, in that they are the only object with an overloaded - * operator. When you use '+' with at least one String argument, both - * arguments have String conversion performed on them, and another String (not - * guaranteed to be unique) results. - * - * <p>String is special-cased when doing data serialization - rather than - * listing the fields of this class, a String object is converted to a string - * literal in the object stream. - * - * @author Paul N. Fisher - * @author Eric Blake (ebb9@email.byu.edu) - * @author Per Bothner (bothner@cygnus.com) - * @author Tom Tromey (tromey@redhat.com) - * @author Andrew John Hughes (gnu_andrew@member.fsf.org) - * @since 1.0 - * @status updated to 1.4; but could use better data sharing via offset field - */ -public final class String - implements Serializable, Comparable<String>, CharSequence -{ - // WARNING: String is a CORE class in the bootstrap cycle. See the comments - // in vm/reference/java/lang/Runtime for implications of this fact. - - /** - * This is probably not necessary because this class is special cased already - * but it will avoid showing up as a discrepancy when comparing SUIDs. - */ - private static final long serialVersionUID = -6849794470754667710L; - - /** - * Stores unicode multi-character uppercase expansion table. - * @see #toUpperCase(Locale) - * @see CharData#UPPER_EXPAND - */ - private static final char[] upperExpand - = zeroBasedStringValue(CharData.UPPER_EXPAND); - - /** - * 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. - */ - final char[] value; - - /** - * 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. - */ - final int count; - - /** - * Caches the result of hashCode(). If this value is zero, the hashcode - * is considered uncached (even if 0 is the correct hash value). - */ - 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. - */ - private static final class CaseInsensitiveComparator - implements Comparator<String>, Serializable - { - /** - * Compatible with JDK 1.2. - */ - private static final long serialVersionUID = 8575799808933029326L; - - /** - * The default private constructor generates unnecessary overhead. - */ - CaseInsensitiveComparator() {} - - /** - * Compares to Strings, using - * <code>String.compareToIgnoreCase(String)</code>. - * - * @param o1 the first string - * @param o2 the second string - * @return < 0, 0, or > 0 depending on the case-insensitive - * comparison of the two strings. - * @throws NullPointerException if either argument is null - * @throws ClassCastException if either argument is not a String - * @see #compareToIgnoreCase(String) - */ - public int compare(String o1, String o2) - { - return o1.compareToIgnoreCase(o2); - } - } // class CaseInsensitiveComparator - - /** - * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>. - * This comparator is {@link Serializable}. Note that it ignores Locale, - * for that, you want a Collator. - * - * @see Collator#compare(String, String) - * @since 1.2 - */ - public static final Comparator<String> CASE_INSENSITIVE_ORDER - = new CaseInsensitiveComparator(); - - /** - * Creates an empty String (length 0). Unless you really need a new object, - * consider using <code>""</code> instead. - */ - public String() - { - value = "".value; - offset = 0; - count = 0; - } - - /** - * Copies the contents of a String to a new String. Since Strings are - * immutable, only a shallow copy is performed. - * - * @param str String to copy - * @throws NullPointerException if value is null - */ - public String(String str) - { - value = str.value; - offset = str.offset; - count = str.count; - cachedHashCode = str.cachedHashCode; - } - - /** - * Creates a new String using the character sequence of the char array. - * Subsequent changes to data do not affect the String. - * - * @param data char array to copy - * @throws NullPointerException if data is null - */ - public String(char[] data) - { - this(data, 0, data.length, false); - } - - /** - * Creates a new String using the character sequence of a subarray of - * characters. The string starts at offset, and copies count chars. - * Subsequent changes to data do not affect the String. - * - * @param data char array to copy - * @param offset position (base 0) to start copying out of data - * @param count the number of characters from data to copy - * @throws NullPointerException if data is null - * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 - * || offset + count < 0 (overflow) - * || offset + count > data.length) - * (while unspecified, this is a StringIndexOutOfBoundsException) - */ - public String(char[] data, int offset, int count) - { - this(data, offset, count, false); - } - - /** - * Creates a new String using an 8-bit array of integer values, starting at - * an offset, and copying up to the count. Each character c, using - * corresponding byte b, is created in the new String as if by performing: - * - * <pre> - * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) - * </pre> - * - * @param ascii array of integer values - * @param hibyte top byte of each Unicode character - * @param offset position (base 0) to start copying out of ascii - * @param count the number of characters from ascii to copy - * @throws NullPointerException if ascii is null - * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 - * || offset + count < 0 (overflow) - * || offset + count > ascii.length) - * (while unspecified, this is a StringIndexOutOfBoundsException) - * @see #String(byte[]) - * @see #String(byte[], String) - * @see #String(byte[], int, int) - * @see #String(byte[], int, int, String) - * @deprecated use {@link #String(byte[], int, int, String)} to perform - * correct encoding - */ - public String(byte[] ascii, int hibyte, int offset, int count) - { - if (offset < 0) - throw new StringIndexOutOfBoundsException("offset: " + offset); - if (count < 0) - throw new StringIndexOutOfBoundsException("count: " + count); - // equivalent to: offset + count < 0 || offset + count > ascii.length - if (ascii.length - offset < count) - throw new StringIndexOutOfBoundsException("offset + count: " - + (offset + count)); - value = new char[count]; - this.offset = 0; - this.count = count; - hibyte <<= 8; - offset += count; - while (--count >= 0) - value[count] = (char) (hibyte | (ascii[--offset] & 0xff)); - } - - /** - * Creates a new String using an 8-bit array of integer values. Each - * character c, using corresponding byte b, is created in the new String - * as if by performing: - * - * <pre> - * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) - * </pre> - * - * @param ascii array of integer values - * @param hibyte top byte of each Unicode character - * @throws NullPointerException if ascii is null - * @see #String(byte[]) - * @see #String(byte[], String) - * @see #String(byte[], int, int) - * @see #String(byte[], int, int, String) - * @see #String(byte[], int, int, int) - * @deprecated use {@link #String(byte[], String)} to perform - * correct encoding - */ - public String(byte[] ascii, int hibyte) - { - this(ascii, hibyte, 0, ascii.length); - } - - /** - * Creates a new String using the portion of the byte array starting at the - * offset and ending at offset + count. Uses the specified encoding type - * to decode the byte array, so the resulting string may be longer or - * shorter than the byte array. For more decoding control, use - * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, - * see {@link java.nio.charset.Charset}. The behavior is not specified if - * the decoder encounters invalid characters; this implementation throws - * an Error. - * - * @param data byte array to copy - * @param offset the offset to start at - * @param count the number of bytes in the array to use - * @param encoding the name of the encoding to use - * @throws NullPointerException if data or encoding is null - * @throws IndexOutOfBoundsException if offset or count is incorrect - * (while unspecified, this is a StringIndexOutOfBoundsException) - * @throws UnsupportedEncodingException if encoding is not found - * @throws Error if the decoding fails - * @since 1.1 - */ - public String(byte[] data, int offset, int count, final String encoding) - throws UnsupportedEncodingException - { - this(data, offset, count, stringToCharset(encoding)); - } - - /** - * Wrapper method to convert exceptions resulting from - * the selection of a {@link java.nio.charset.Charset} based on - * a String. - * - * @throws UnsupportedEncodingException if encoding is not found - */ - private static final Charset stringToCharset(final String encoding) - throws UnsupportedEncodingException - { - try - { - return Charset.forName(encoding); - } - catch(IllegalCharsetNameException e) - { - throw new UnsupportedEncodingException("Encoding: "+encoding+ - " not found."); - } - catch(UnsupportedCharsetException e) - { - throw new UnsupportedEncodingException("Encoding: "+encoding+ - " not found."); - } - } - - /** - * Creates a new String using the portion of the byte array starting at the - * offset and ending at offset + count. Uses the specified encoding type - * to decode the byte array, so the resulting string may be longer or - * shorter than the byte array. For more decoding control, use - * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, - * see {@link java.nio.charset.Charset}. Malformed input and unmappable - * character sequences are replaced with the default replacement string - * provided by the {@link java.nio.charset.Charset}. - * - * @param data byte array to copy - * @param offset the offset to start at - * @param count the number of bytes in the array to use - * @param encoding the encoding to use - * @throws NullPointerException if data or encoding is null - * @throws IndexOutOfBoundsException if offset or count is incorrect - * (while unspecified, this is a StringIndexOutOfBoundsException) - * @since 1.6 - */ - public String(byte[] data, int offset, int count, Charset encoding) - { - if (offset < 0) - throw new StringIndexOutOfBoundsException("offset: " + offset); - if (count < 0) - throw new StringIndexOutOfBoundsException("count: " + count); - // equivalent to: offset + count < 0 || offset + count > data.length - if (data.length - offset < count) - throw new StringIndexOutOfBoundsException("offset + count: " - + (offset + count)); - try - { - CharsetDecoder csd = encoding.newDecoder(); - csd.onMalformedInput(CodingErrorAction.REPLACE); - csd.onUnmappableCharacter(CodingErrorAction.REPLACE); - CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); - if(cbuf.hasArray()) - { - value = cbuf.array(); - this.offset = cbuf.position(); - this.count = cbuf.remaining(); - } else { - // Doubt this will happen. But just in case. - value = new char[cbuf.remaining()]; - cbuf.get(value); - this.offset = 0; - this.count = value.length; - } - } - catch(CharacterCodingException e) - { - // This shouldn't ever happen. - throw (InternalError) new InternalError().initCause(e); - } - } - - /** - * Creates a new String using the byte array. Uses the specified encoding - * type to decode the byte array, so the resulting string may be longer or - * shorter than the byte array. For more decoding control, use - * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, - * see {@link java.nio.charset.Charset}. The behavior is not specified if - * the decoder encounters invalid characters; this implementation throws - * an Error. - * - * @param data byte array to copy - * @param encoding the name of the encoding to use - * @throws NullPointerException if data or encoding is null - * @throws UnsupportedEncodingException if encoding is not found - * @throws Error if the decoding fails - * @see #String(byte[], int, int, String) - * @since 1.1 - */ - public String(byte[] data, String encoding) - throws UnsupportedEncodingException - { - this(data, 0, data.length, encoding); - } - - /** - * Creates a new String using the byte array. Uses the specified encoding - * type to decode the byte array, so the resulting string may be longer or - * shorter than the byte array. For more decoding control, use - * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, - * see {@link java.nio.charset.Charset}. Malformed input and unmappable - * character sequences are replaced with the default replacement string - * provided by the {@link java.nio.charset.Charset}. - * - * @param data byte array to copy - * @param encoding the name of the encoding to use - * @throws NullPointerException if data or encoding is null - * @see #String(byte[], int, int, java.nio.Charset) - * @since 1.6 - */ - public String(byte[] data, Charset encoding) - { - this(data, 0, data.length, encoding); - } - - /** - * Creates a new String using the portion of the byte array starting at the - * offset and ending at offset + count. Uses the encoding of the platform's - * default charset, so the resulting string may be longer or shorter than - * the byte array. For more decoding control, use - * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified - * if the decoder encounters invalid characters; this implementation throws - * an Error. - * - * @param data byte array to copy - * @param offset the offset to start at - * @param count the number of bytes in the array to use - * @throws NullPointerException if data is null - * @throws IndexOutOfBoundsException if offset or count is incorrect - * @throws Error if the decoding fails - * @see #String(byte[], int, int, String) - * @since 1.1 - */ - public String(byte[] data, int offset, int count) - { - if (offset < 0) - throw new StringIndexOutOfBoundsException("offset: " + offset); - if (count < 0) - throw new StringIndexOutOfBoundsException("count: " + count); - // equivalent to: offset + count < 0 || offset + count > data.length - if (data.length - offset < count) - throw new StringIndexOutOfBoundsException("offset + count: " - + (offset + count)); - int o, c; - char[] v; - String encoding; - try - { - encoding = System.getProperty("file.encoding"); - CharsetDecoder csd = Charset.forName(encoding).newDecoder(); - csd.onMalformedInput(CodingErrorAction.REPLACE); - csd.onUnmappableCharacter(CodingErrorAction.REPLACE); - CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); - if(cbuf.hasArray()) - { - v = cbuf.array(); - o = cbuf.position(); - c = cbuf.remaining(); - } else { - // Doubt this will happen. But just in case. - v = new char[cbuf.remaining()]; - cbuf.get(v); - o = 0; - c = v.length; - } - } catch(Exception ex){ - // If anything goes wrong (System property not set, - // NIO provider not available, etc) - // Default to the 'safe' encoding ISO8859_1 - v = new char[count]; - o = 0; - c = count; - for (int i=0;i<count;i++) - v[i] = (char)data[offset+i]; - } - this.value = v; - this.offset = o; - this.count = c; - } - - /** - * Creates a new String using the byte array. Uses the encoding of the - * platform's default charset, so the resulting string may be longer or - * shorter than the byte array. For more decoding control, use - * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified - * if the decoder encounters invalid characters; this implementation throws - * an Error. - * - * @param data byte array to copy - * @throws NullPointerException if data is null - * @throws Error if the decoding fails - * @see #String(byte[], int, int) - * @see #String(byte[], int, int, String) - * @since 1.1 - */ - public String(byte[] data) - { - this(data, 0, data.length); - } - - /** - * Creates a new String using the character sequence represented by - * the StringBuffer. Subsequent changes to buf do not affect the String. - * - * @param buffer StringBuffer to copy - * @throws NullPointerException if buffer is null - */ - public String(StringBuffer buffer) - { - synchronized (buffer) - { - offset = 0; - count = buffer.count; - // Share unless buffer is 3/4 empty. - if ((count << 2) < buffer.value.length) - { - value = new char[count]; - VMSystem.arraycopy(buffer.value, 0, value, 0, count); - } - else - { - buffer.shared = true; - value = buffer.value; - } - } - } - - /** - * Creates a new String using the character sequence represented by - * the StringBuilder. Subsequent changes to buf do not affect the String. - * - * @param buffer StringBuilder to copy - * @throws NullPointerException if buffer is null - */ - public String(StringBuilder buffer) - { - this(buffer.value, 0, buffer.count); - } - - /** - * Special constructor which can share an array when safe to do so. - * - * @param data the characters to copy - * @param offset the location to start from - * @param count the number of characters to use - * @param dont_copy true if the array is trusted, and need not be copied - * @throws NullPointerException if chars is null - * @throws StringIndexOutOfBoundsException if bounds check fails - */ - String(char[] data, int offset, int count, boolean dont_copy) - { - if (offset < 0) - throw new StringIndexOutOfBoundsException("offset: " + offset); - if (count < 0) - throw new StringIndexOutOfBoundsException("count: " + count); - // equivalent to: offset + count < 0 || offset + count > data.length - if (data.length - offset < count) - throw new StringIndexOutOfBoundsException("offset + count: " - + (offset + count)); - if (dont_copy) - { - value = data; - this.offset = offset; - } - else - { - value = new char[count]; - VMSystem.arraycopy(data, offset, value, 0, count); - this.offset = 0; - } - this.count = count; - } - - /** - * Creates a new String containing the characters represented in the - * given subarray of Unicode code points. - * @param codePoints the entire array of code points - * @param offset the start of the subarray - * @param count the length of the subarray - * - * @throws IllegalArgumentException if an invalid code point is found - * in the codePoints array - * @throws IndexOutOfBoundsException if offset is negative or offset + count - * is greater than the length of the array. - */ - public String(int[] codePoints, int offset, int count) - { - // FIXME: This implementation appears to give correct internal - // representation of the String because: - // - length() is correct - // - getting a char[] from toCharArray() and testing - // Character.codePointAt() on all the characters in that array gives - // the appropriate results - // however printing the String gives incorrect results. This may be - // due to printing method errors (such as incorrectly looping through - // the String one char at a time rather than one "character" at a time. - - if (offset < 0) - throw new IndexOutOfBoundsException(); - int end = offset + count; - int pos = 0; - // This creates a char array that is long enough for all of the code - // points to represent supplementary characters. This is more than likely - // a waste of storage, so we use it only temporarily and then copy the - // used portion into the value array. - char[] temp = new char[2 * codePoints.length]; - for (int i = offset; i < end; i++) - { - pos += Character.toChars(codePoints[i], temp, pos); - } - this.count = pos; - this.value = new char[pos]; - System.arraycopy(temp, 0, value, 0, pos); - this.offset = 0; - } - - /** - * Returns the number of characters contained in this String. - * - * @return the length of this String - */ - public int length() - { - return count; - } - - /** - * Returns the character located at the specified index within this String. - * - * @param index position of character to return (base 0) - * @return character located at position index - * @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]; - } - - /** - * Get the code point at the specified index. This is like #charAt(int), - * but if the character is the start of a surrogate pair, and the - * following character completes the pair, then the corresponding - * supplementary code point is returned. - * @param index the index of the codepoint to get, starting at 0 - * @return the codepoint at the specified index - * @throws IndexOutOfBoundsException if index is negative or >= length() - * @since 1.5 - */ - public synchronized int codePointAt(int index) - { - if (index < 0 || index >= count) - throw new StringIndexOutOfBoundsException(index); - // Use the CharSequence overload as we get better range checking - // this way. - return Character.codePointAt(this, index); - } - - /** - * Get the code point before the specified index. This is like - * #codePointAt(int), but checks the characters at <code>index-1</code> and - * <code>index-2</code> to see if they form a supplementary code point. - * @param index the index just past the codepoint to get, starting at 0 - * @return the codepoint at the specified index - * @throws IndexOutOfBoundsException if index is less than 1 or > length() - * (while unspecified, this is a StringIndexOutOfBoundsException) - * @since 1.5 - */ - public synchronized int codePointBefore(int index) - { - if (index < 1 || index > count) - throw new StringIndexOutOfBoundsException(index); - // Use the CharSequence overload as we get better range checking - // this way. - return Character.codePointBefore(this, index); - } - - /** - * Copies characters from this String starting at a specified start index, - * ending at a specified stop index, to a character array starting at - * a specified destination begin index. - * - * @param srcBegin index to begin copying characters from this String - * @param srcEnd index after the last character to be copied from this String - * @param dst character array which this String is copied into - * @param dstBegin index to start writing characters into dst - * @throws NullPointerException if dst is null - * @throws IndexOutOfBoundsException if any indices are out of bounds - * (while unspecified, source problems cause a - * 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(); - VMSystem.arraycopy(value, srcBegin + offset, - dst, dstBegin, srcEnd - srcBegin); - } - - /** - * Copies the low byte of each character from this String starting at a - * specified start index, ending at a specified stop index, to a byte array - * starting at a specified destination begin index. - * - * @param srcBegin index to being copying characters from this String - * @param srcEnd index after the last character to be copied from this String - * @param dst byte array which each low byte of this String is copied into - * @param dstBegin index to start writing characters into dst - * @throws NullPointerException if dst is null and copy length is non-zero - * @throws IndexOutOfBoundsException if any indices are out of bounds - * (while unspecified, source problems cause a - * StringIndexOutOfBoundsException, and dst problems cause an - * ArrayIndexOutOfBoundsException) - * @see #getBytes() - * @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++]; - } - - /** - * 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. - * - * @param enc encoding name - * @return the resulting byte array - * @throws NullPointerException if enc is null - * @throws UnsupportedEncodingException if encoding is not supported - * @since 1.1 - */ - public byte[] getBytes(final String enc) - throws UnsupportedEncodingException - { - return getBytes(stringToCharset(enc)); - } - - /** - * 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 the {@link java.nio.charset.Charset}'s default replacement. - * - * @param enc encoding name - * @return the resulting byte array - * @throws NullPointerException if enc is null - * @since 1.6 - */ - public byte[] getBytes(Charset enc) - { - try - { - CharsetEncoder cse = enc.newEncoder(); - cse.onMalformedInput(CodingErrorAction.REPLACE); - cse.onUnmappableCharacter(CodingErrorAction.REPLACE); - ByteBuffer bbuf = cse.encode(CharBuffer.wrap(value, offset, count)); - if(bbuf.hasArray()) - return bbuf.array(); - - // Doubt this will happen. But just in case. - byte[] bytes = new byte[bbuf.remaining()]; - bbuf.get(bytes); - return bytes; - } - catch(CharacterCodingException e) - { - // This shouldn't ever happen. - throw (InternalError) new InternalError().initCause(e); - } - } - - /** - * 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. - * - * @return the resulting byte array, or null on a problem - * @since 1.1 - */ - public byte[] getBytes() - { - try - { - return getBytes(System.getProperty("file.encoding")); - } catch(Exception e) { - // XXX - Throw an error here? - // For now, default to the 'safe' encoding. - byte[] bytes = new byte[count]; - for(int i=0;i<count;i++) - bytes[i] = (byte)((value[offset+i] <= 0xFF)? - value[offset+i]:'?'); - return bytes; - } - } - - /** - * Predicate which compares anObject to this. This is true only for Strings - * with the same character sequence. - * - * @param anObject the object to compare - * @return true if anObject is semantically equal to this - * @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; - } - - /** - * Compares the given StringBuffer to this String. This is true if the - * StringBuffer has the same content as this String at this moment. - * - * @param buffer the StringBuffer to compare to - * @return true if StringBuffer has the same character sequence - * @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; - } - } - - /** - * Compares the given CharSequence to this String. This is true if - * the CharSequence has the same content as this String at this - * moment. - * - * @param seq the CharSequence to compare to - * @return true if CharSequence has the same character sequence - * @throws NullPointerException if the given CharSequence is null - * @since 1.5 - */ - public boolean contentEquals(CharSequence seq) - { - if (seq.length() != count) - return false; - for (int i = 0; i < count; ++i) - if (value[offset + i] != seq.charAt(i)) - return false; - return true; - } - - /** - * Compares a String to this String, ignoring case. This does not handle - * multi-character capitalization exceptions; instead the comparison is - * made on a character-by-character basis, and is true if:<br><ul> - * <li><code>c1 == c2</code></li> - * <li><code>Character.toUpperCase(c1) - * == Character.toUpperCase(c2)</code></li> - * <li><code>Character.toLowerCase(c1) - * == Character.toLowerCase(c2)</code></li> - * </ul> - * - * @param anotherString String to compare to this String - * @return true if anotherString is equal, ignoring case - * @see #equals(Object) - * @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; - } - - /** - * Compares this String and another String (case sensitive, - * lexicographically). The result is less than 0 if this string sorts - * before the other, 0 if they are equal, and greater than 0 otherwise. - * After any common starting sequence is skipped, the result is - * <code>this.charAt(k) - anotherString.charAt(k)</code> if both strings - * have characters remaining, or - * <code>this.length() - anotherString.length()</code> if one string is - * a subsequence of the other. - * - * @param anotherString the String to compare against - * @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; - } - - /** - * Compares this String and another String (case insensitive). This - * comparison is <em>similar</em> to equalsIgnoreCase, in that it ignores - * locale and multi-characater capitalization, and compares characters - * after performing - * <code>Character.toLowerCase(Character.toUpperCase(c))</code> on each - * character of the string. This is unsatisfactory for locale-based - * comparison, in which case you should use {@link java.text.Collator}. - * - * @param str the string to compare against - * @return the comparison - * @see Collator#compare(String, String) - * @since 1.2 - */ - 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; - } - - /** - * Predicate which determines if this String matches another String - * starting at a specified offset for each String and continuing - * for a specified length. Indices out of bounds are harmless, and give - * a false result. - * - * @param toffset index to start comparison at for this String - * @param other String to compare region to this String - * @param ooffset index to start comparison at for other - * @param len number of characters to compare - * @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); - } - - /** - * Predicate which determines if this String matches another String - * starting at a specified offset for each String and continuing - * for a specified length, optionally ignoring case. Indices out of bounds - * are harmless, and give a false result. Case comparisons are based on - * <code>Character.toLowerCase()</code> and - * <code>Character.toUpperCase()</code>, not on multi-character - * capitalization expansions. - * - * @param ignoreCase true if case should be ignored in comparision - * @param toffset index to start comparison at for this String - * @param other String to compare region to this String - * @param ooffset index to start comparison at for other - * @param len number of characters to compare - * @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; - } - - /** - * Predicate which determines if this String contains the given prefix, - * beginning comparison at toffset. The result is false if toffset is - * negative or greater than this.length(), otherwise it is the same as - * <code>this.substring(toffset).startsWith(prefix)</code>. - * - * @param prefix String to compare - * @param toffset offset for this String where comparison starts - * @return true if this String starts with prefix - * @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); - } - - /** - * Predicate which determines if this String starts with a given prefix. - * If the prefix is an empty String, true is returned. - * - * @param prefix String to compare - * @return true if this String starts with the prefix - * @throws NullPointerException if prefix is null - * @see #startsWith(String, int) - */ - public boolean startsWith(String prefix) - { - return regionMatches(false, 0, prefix, 0, prefix.count); - } - - /** - * Predicate which determines if this String ends with a given suffix. - * If the suffix is an empty String, true is returned. - * - * @param suffix String to compare - * @return true if this String ends with the suffix - * @throws NullPointerException if suffix is null - * @see #regionMatches(boolean, int, String, int, int) - */ - public boolean endsWith(String suffix) - { - return regionMatches(false, count - suffix.count, suffix, 0, suffix.count); - } - - /** - * Computes the hashcode for this String. This is done with int arithmetic, - * where ** represents exponentiation, by this formula:<br> - * <code>s[0]*31**(n-1) + s[1]*31**(n-2) + ... + s[n-1]</code>. - * - * @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; - } - - /** - * Finds the first instance of a character in this String. - * - * @param ch character to find - * @return location (base 0) of the character, or -1 if not found - */ - public int indexOf(int ch) - { - return indexOf(ch, 0); - } - - /** - * Finds the first instance of a character in this String, starting at - * a given index. If starting index is less than 0, the search - * starts at the beginning of this String. If the starting index - * is greater than the length of this String, -1 is returned. - * - * @param ch character to find - * @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; - } - - /** - * Finds the last instance of a character in this String. - * - * @param ch character to find - * @return location (base 0) of the character, or -1 if not found - */ - public int lastIndexOf(int ch) - { - return lastIndexOf(ch, count - 1); - } - - /** - * Finds the last instance of a character in this String, starting at - * a given index. If starting index is greater than the maximum valid - * index, then the search begins at the end of this String. If the - * starting index is less than zero, -1 is returned. - * - * @param ch character to find - * @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; - } - - /** - * Finds the first instance of a String in this String. - * - * @param str String to find - * @return location (base 0) of the String, or -1 if not found - * @throws NullPointerException if str is null - */ - public int indexOf(String str) - { - return indexOf(str, 0); - } - - /** - * Finds the first instance of a String in this String, starting at - * a given index. If starting index is less than 0, the search - * starts at the beginning of this String. If the starting index - * is greater than the length of this String, -1 is returned. - * - * @param str String to find - * @param fromIndex index to start the search - * @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; - } - - /** - * Finds the last instance of a String in this String. - * - * @param str String to find - * @return location (base 0) of the String, or -1 if not found - * @throws NullPointerException if str is null - */ - public int lastIndexOf(String str) - { - return lastIndexOf(str, count - str.count); - } - - /** - * Finds the last instance of a String in this String, starting at - * a given index. If starting index is greater than the maximum valid - * index, then the search begins at the end of this String. If the - * starting index is less than zero, -1 is returned. - * - * @param str String to find - * @param fromIndex index to start the search - * @return location (base 0) of the String, or -1 if not found - * @throws NullPointerException if str is null - */ - 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; - } - - /** - * Creates a substring of this String, starting at a specified index - * and ending at the end of this String. - * - * @param begin index to start substring (base 0) - * @return new String which is a substring of this String - * @throws IndexOutOfBoundsException if begin < 0 || begin > length() - * (while unspecified, this is a StringIndexOutOfBoundsException) - */ - public String substring(int begin) - { - return substring(begin, count); - } - - /** - * Creates a substring of this String, starting at a specified index - * and ending at one character before a specified index. - * - * @param beginIndex index to start substring (inclusive, base 0) - * @param endIndex index to end at (exclusive) - * @return new String which is a substring of this String - * @throws IndexOutOfBoundsException if begin < 0 || end > length() - * || 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); - } - - /** - * Creates a substring of this String, starting at a specified index - * and ending at one character before a specified index. This behaves like - * <code>substring(begin, end)</code>. - * - * @param begin index to start substring (inclusive, base 0) - * @param end index to end at (exclusive) - * @return new String which is a substring of this String - * @throws IndexOutOfBoundsException if begin < 0 || end > length() - * || begin > end - * @since 1.4 - */ - public CharSequence subSequence(int begin, int end) - { - return substring(begin, end); - } - - /** - * Concatenates a String to this String. This results in a new string unless - * one of the two originals is "". - * - * @param str String to append to this String - * @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]; - VMSystem.arraycopy(value, offset, newStr, 0, count); - VMSystem.arraycopy(str.value, str.offset, newStr, count, str.count); - // Package constructor avoids an array copy. - return new String(newStr, 0, newStr.length, true); - } - - /** - * Replaces every instance of a character in this String with a new - * character. If no replacements occur, this is returned. - * - * @param oldChar the old character to replace - * @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 = toCharArray(); - newStr[x - offset] = newChar; - while (--i >= 0) - if (value[++x] == oldChar) - newStr[x - offset] = newChar; - // Package constructor avoids an array copy. - return new String(newStr, 0, count, true); - } - - /** - * Test if this String matches a regular expression. This is shorthand for - * <code>{@link Pattern}.matches(regex, this)</code>. - * - * @param regex the pattern to match - * @return true if the pattern matches - * @throws NullPointerException if regex is null - * @throws PatternSyntaxException if regex is invalid - * @see Pattern#matches(String, CharSequence) - * @since 1.4 - */ - public boolean matches(String regex) - { - return Pattern.matches(regex, this); - } - - /** - * Replaces the first substring match of the regular expression with a - * given replacement. This is shorthand for <code>{@link Pattern} - * .compile(regex).matcher(this).replaceFirst(replacement)</code>. - * - * @param regex the pattern to match - * @param replacement the replacement string - * @return the modified string - * @throws NullPointerException if regex or replacement is null - * @throws PatternSyntaxException if regex is invalid - * @see #replaceAll(String, String) - * @see Pattern#compile(String) - * @see Pattern#matcher(CharSequence) - * @see Matcher#replaceFirst(String) - * @since 1.4 - */ - public String replaceFirst(String regex, String replacement) - { - return Pattern.compile(regex).matcher(this).replaceFirst(replacement); - } - - /** - * Replaces all matching substrings of the regular expression with a - * given replacement. This is shorthand for <code>{@link Pattern} - * .compile(regex).matcher(this).replaceAll(replacement)</code>. - * - * @param regex the pattern to match - * @param replacement the replacement string - * @return the modified string - * @throws NullPointerException if regex or replacement is null - * @throws PatternSyntaxException if regex is invalid - * @see #replaceFirst(String, String) - * @see Pattern#compile(String) - * @see Pattern#matcher(CharSequence) - * @see Matcher#replaceAll(String) - * @since 1.4 - */ - public String replaceAll(String regex, String replacement) - { - return Pattern.compile(regex).matcher(this).replaceAll(replacement); - } - - /** - * Split this string around the matches of a regular expression. Each - * element of the returned array is the largest block of characters not - * terminated by the regular expression, in the order the matches are found. - * - * <p>The limit affects the length of the array. If it is positive, the - * array will contain at most n elements (n - 1 pattern matches). If - * negative, the array length is unlimited, but there can be trailing empty - * entries. if 0, the array length is unlimited, and trailing empty entries - * are discarded. - * - * <p>For example, splitting "boo:and:foo" yields:<br> - * <table border=0> - * <th><td>Regex</td> <td>Limit</td> <td>Result</td></th> - * <tr><td>":"</td> <td>2</td> <td>{ "boo", "and:foo" }</td></tr> - * <tr><td>":"</td> <td>t</td> <td>{ "boo", "and", "foo" }</td></tr> - * <tr><td>":"</td> <td>-2</td> <td>{ "boo", "and", "foo" }</td></tr> - * <tr><td>"o"</td> <td>5</td> <td>{ "b", "", ":and:f", "", "" }</td></tr> - * <tr><td>"o"</td> <td>-2</td> <td>{ "b", "", ":and:f", "", "" }</td></tr> - * <tr><td>"o"</td> <td>0</td> <td>{ "b", "", ":and:f" }</td></tr> - * </table> - * - * <p>This is shorthand for - * <code>{@link Pattern}.compile(regex).split(this, limit)</code>. - * - * @param regex the pattern to match - * @param limit the limit threshold - * @return the array of split strings - * @throws NullPointerException if regex or replacement is null - * @throws PatternSyntaxException if regex is invalid - * @see Pattern#compile(String) - * @see Pattern#split(CharSequence, int) - * @since 1.4 - */ - public String[] split(String regex, int limit) - { - return Pattern.compile(regex).split(this, limit); - } - - /** - * Split this string around the matches of a regular expression. Each - * element of the returned array is the largest block of characters not - * terminated by the regular expression, in the order the matches are found. - * The array length is unlimited, and trailing empty entries are discarded, - * as though calling <code>split(regex, 0)</code>. - * - * @param regex the pattern to match - * @return the array of split strings - * @throws NullPointerException if regex or replacement is null - * @throws PatternSyntaxException if regex is invalid - * @see #split(String, int) - * @see Pattern#compile(String) - * @see Pattern#split(CharSequence, int) - * @since 1.4 - */ - public String[] split(String regex) - { - return Pattern.compile(regex).split(this, 0); - } - - /** - * Convert string to lower case for a Turkish locale that requires special - * handling of '\u0049' - */ - private String toLowerCaseTurkish() - { - // First, see if the current string is already lower case. - int i = count; - int x = offset - 1; - while (--i >= 0) - { - char ch = value[++x]; - if ((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 = new char[count]; - VMSystem.arraycopy(value, offset, newStr, 0, x - offset); - do - { - char ch = value[x]; - // Hardcoded special case. - if (ch != '\u0049') - { - newStr[x - offset] = Character.toLowerCase(ch); - } - else - { - newStr[x - offset] = '\u0131'; - } - x++; - } - while (--i >= 0); - // Package constructor avoids an array copy. - return new String(newStr, 0, count, true); - } - - /** - * Lowercases this String according to a particular locale. This uses - * Unicode's special case mappings, as applied to the given Locale, so the - * resulting string may be a different length. - * - * @param loc locale to use - * @return new lowercased String, or this if no characters were lowercased - * @throws NullPointerException if loc is null - * @see #toUpperCase(Locale) - * @since 1.1 - */ - public String toLowerCase(Locale loc) - { - // First, see if the current string is already lower case. - - // Is loc turkish? String equality test is ok as Locale.language is interned - if ("tr" == loc.getLanguage()) - { - return toLowerCaseTurkish(); - } - else - { - int i = count; - int x = offset - 1; - while (--i >= 0) - { - char ch = value[++x]; - if (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 = new char[count]; - VMSystem.arraycopy(value, offset, newStr, 0, x - offset); - do - { - char ch = value[x]; - // Hardcoded special case. - newStr[x - offset] = Character.toLowerCase(ch); - x++; - } - while (--i >= 0); - // Package constructor avoids an array copy. - return new String(newStr, 0, count, true); - } - } - - /** - * Lowercases this String. This uses Unicode's special case mappings, as - * applied to the platform's default Locale, so the resulting string may - * be a different length. - * - * @return new lowercased String, or this if no characters were lowercased - * @see #toLowerCase(Locale) - * @see #toUpperCase() - */ - public String toLowerCase() - { - return toLowerCase(Locale.getDefault()); - } - - /** - * Uppercase this string for a Turkish locale - */ - private String toUpperCaseTurkish() - { - // First, see how many characters we have to grow by, as well as if the - // current string is already upper case. - 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 - && ch != '\u0069' - && ch == Character.toUpperCase(ch)); - } - if (unchanged) - return this; - - // Now we perform the conversion. - i = count; - if (expand == 0) - { - char[] newStr = new char[count]; - VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); - while (--i >= 0) - { - char ch = value[x]; - // Hardcoded special case. - if (ch != '\u0069') - { - newStr[x - offset] = Character.toUpperCase(ch); - } - else - { - newStr[x - offset] = '\u0130'; - } - x++; - } - // Package constructor avoids an array copy. - return new String(newStr, 0, 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 (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); - } - - /** - * Uppercases this String according to a particular locale. This uses - * Unicode's special case mappings, as applied to the given Locale, so the - * resulting string may be a different length. - * - * @param loc locale to use - * @return new uppercased String, or this if no characters were uppercased - * @throws NullPointerException if loc is null - * @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. - - // Is loc turkish? String equality test is ok as Locale.language is interned - if ("tr" == loc.getLanguage()) - { - return toUpperCaseTurkish(); - } - else - { - 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 - && ch == Character.toUpperCase(ch)); - } - if (unchanged) - return this; - - // Now we perform the conversion. - i = count; - if (expand == 0) - { - char[] newStr = new char[count]; - VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); - while (--i >= 0) - { - char ch = value[x]; - newStr[x - offset] = Character.toUpperCase(ch); - x++; - } - // Package constructor avoids an array copy. - return new String(newStr, 0, count, true); - } - - // Expansion is necessary. - char[] newStr = new char[count + expand]; - int j = 0; - while (--i >= 0) - { - char ch = value[x++]; - 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); - } - } - /** - * Uppercases this String. This uses Unicode's special case mappings, as - * applied to the platform's default Locale, so the resulting string may - * be a different length. - * - * @return new uppercased String, or this if no characters were uppercased - * @see #toUpperCase(Locale) - * @see #toLowerCase() - */ - public String toUpperCase() - { - return toUpperCase(Locale.getDefault()); - } - - /** - * Trims all characters less than or equal to <code>'\u0020'</code> - * (<code>' '</code>) from the beginning and end of this String. This - * includes many, but not all, ASCII control characters, and all - * {@link Character#isWhitespace(char)}. - * - * @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); - } - - /** - * Returns this, as it is already a String! - * - * @return this - */ - public String toString() - { - return this; - } - - /** - * Copies the contents of this String into a character array. Subsequent - * changes to the array do not affect the String. - * - * @return character array copying the String - */ - public char[] toCharArray() - { - char[] copy = new char[count]; - VMSystem.arraycopy(value, offset, copy, 0, count); - return copy; - } - - /** - * Returns a String representation of an Object. This is "null" if the - * object is null, otherwise it is <code>obj.toString()</code> (which - * can be null). - * - * @param obj the Object - * @return the string conversion of obj - */ - public static String valueOf(Object obj) - { - return obj == null ? "null" : obj.toString(); - } - - /** - * Returns a String representation of a character array. Subsequent - * changes to the array do not affect the String. - * - * @param data the character array - * @return a String containing the same character sequence as data - * @throws NullPointerException if data is null - * @see #valueOf(char[], int, int) - * @see #String(char[]) - */ - public static String valueOf(char[] data) - { - return valueOf (data, 0, data.length); - } - - /** - * Returns a String representing the character sequence of the char array, - * starting at the specified offset, and copying chars up to the specified - * count. Subsequent changes to the array do not affect the String. - * - * @param data character array - * @param offset position (base 0) to start copying out of data - * @param count the number of characters from data to copy - * @return String containing the chars from data[offset..offset+count] - * @throws NullPointerException if data is null - * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 - * || offset + count > data.length) - * (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); - } - - /** - * Returns a String representing the character sequence of the char array, - * starting at the specified offset, and copying chars up to the specified - * count. Subsequent changes to the array do not affect the String. - * - * @param data character array - * @param offset position (base 0) to start copying out of data - * @param count the number of characters from data to copy - * @return String containing the chars from data[offset..offset+count] - * @throws NullPointerException if data is null - * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 - * || offset + count < 0 (overflow) - * || offset + count < 0 (overflow) - * || offset + count > data.length) - * (while unspecified, this is a StringIndexOutOfBoundsException) - * @see #String(char[], int, int) - */ - public static String copyValueOf(char[] data, int offset, int count) - { - return new String(data, offset, count, false); - } - - /** - * Returns a String representation of a character array. Subsequent - * changes to the array do not affect the String. - * - * @param data the character array - * @return a String containing the same character sequence as data - * @throws NullPointerException if data is null - * @see #copyValueOf(char[], int, int) - * @see #String(char[]) - */ - public static String copyValueOf(char[] data) - { - return copyValueOf (data, 0, data.length); - } - - /** - * Returns a String representing a boolean. - * - * @param b the boolean - * @return "true" if b is true, else "false" - */ - public static String valueOf(boolean b) - { - return b ? "true" : "false"; - } - - /** - * Returns a String representing a character. - * - * @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); - } - - /** - * Returns a String representing an integer. - * - * @param i the integer - * @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); - } - - /** - * Returns a String representing a long. - * - * @param l the long - * @return String containing the long in base 10 - * @see Long#toString(long) - */ - public static String valueOf(long l) - { - return Long.toString(l); - } - - /** - * Returns a String representing a float. - * - * @param f the float - * @return String containing the float - * @see Float#toString(float) - */ - public static String valueOf(float f) - { - return Float.toString(f); - } - - /** - * Returns a String representing a double. - * - * @param d the double - * @return String containing the double - * @see Double#toString(double) - */ - public static String valueOf(double d) - { - return Double.toString(d); - } - - - /** @since 1.5 */ - public static String format(Locale locale, String format, Object... args) - { - Formatter f = new Formatter(locale); - return f.format(format, args).toString(); - } - - /** @since 1.5 */ - public static String format(String format, Object... args) - { - return format(Locale.getDefault(), format, args); - } - - /** - * 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); - } - - /** - * Return the number of code points between two indices in the - * <code>String</code>. An unpaired surrogate counts as a - * code point for this purpose. Characters outside the indicated - * range are not examined, even if the range ends in the middle of a - * surrogate pair. - * - * @param start the starting index - * @param end one past the ending index - * @return the number of code points - * @since 1.5 - */ - public synchronized int codePointCount(int start, int end) - { - if (start < 0 || end > count || start > end) - throw new StringIndexOutOfBoundsException(); - - start += offset; - end += offset; - int count = 0; - while (start < end) - { - char base = value[start]; - if (base < Character.MIN_HIGH_SURROGATE - || base > Character.MAX_HIGH_SURROGATE - || start == end - || start == count - || value[start + 1] < Character.MIN_LOW_SURROGATE - || value[start + 1] > Character.MAX_LOW_SURROGATE) - { - // Nothing. - } - else - { - // Surrogate pair. - ++start; - } - ++start; - ++count; - } - return count; - } - - /** - * 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[0][Character.readCodePoint((int)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]; - VMSystem.arraycopy(s.value, s.offset, value, 0, count); - } - - return value; - } - - /** - * Returns true iff this String contains the sequence of Characters - * described in s. - * @param s the CharSequence - * @return true iff this String contains s - * - * @since 1.5 - */ - public boolean contains (CharSequence s) - { - return this.indexOf(s.toString()) != -1; - } - - /** - * Returns a string that is this string with all instances of the sequence - * represented by <code>target</code> replaced by the sequence in - * <code>replacement</code>. - * @param target the sequence to be replaced - * @param replacement the sequence used as the replacement - * @return the string constructed as above - */ - public String replace (CharSequence target, CharSequence replacement) - { - String targetString = target.toString(); - String replaceString = replacement.toString(); - int targetLength = target.length(); - int replaceLength = replacement.length(); - - int startPos = this.indexOf(targetString); - CPStringBuilder result = new CPStringBuilder(this); - while (startPos != -1) - { - // Replace the target with the replacement - result.replace(startPos, startPos + targetLength, replaceString); - - // Search for a new occurrence of the target - startPos = result.indexOf(targetString, startPos + replaceLength); - } - return result.toString(); - } - - /** - * Return the index into this String that is offset from the given index by - * <code>codePointOffset</code> code points. - * @param index the index at which to start - * @param codePointOffset the number of code points to offset - * @return the index into this String that is <code>codePointOffset</code> - * code points offset from <code>index</code>. - * - * @throws IndexOutOfBoundsException if index is negative or larger than the - * length of this string. - * @throws IndexOutOfBoundsException if codePointOffset is positive and the - * substring starting with index has fewer than codePointOffset code points. - * @throws IndexOutOfBoundsException if codePointOffset is negative and the - * substring ending with index has fewer than (-codePointOffset) code points. - * @since 1.5 - */ - public int offsetByCodePoints(int index, int codePointOffset) - { - if (index < 0 || index > count) - throw new IndexOutOfBoundsException(); - - return Character.offsetByCodePoints(value, offset, count, offset + index, - codePointOffset); - } - - /** - * Returns true if, and only if, {@link #length()} - * is <code>0</code>. - * - * @return true if the length of the string is zero. - * @since 1.6 - */ - public boolean isEmpty() - { - return count == 0; - } - -} |
