Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 3248 invoked from network); 11 Aug 2006 10:58:14 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 11 Aug 2006 10:58:14 -0000 Received: (qmail 14006 invoked by uid 500); 11 Aug 2006 10:58:14 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 13980 invoked by uid 500); 11 Aug 2006 10:58:14 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 13968 invoked by uid 99); 11 Aug 2006 10:58:14 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Aug 2006 03:58:14 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Aug 2006 03:58:10 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 614101A981D; Fri, 11 Aug 2006 03:57:07 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r430756 [2/2] - /incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/String.java Date: Fri, 11 Aug 2006 10:57:06 -0000 To: harmony-commits@incubator.apache.org From: tellison@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060811105707.614101A981D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/String.java URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/String.java?rev=430756&r1=430755&r2=430756&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/String.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/String.java Fri Aug 11 03:57:06 2006 @@ -1,4 +1,4 @@ -/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable +/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import java.security.AccessController; import java.util.regex.PatternSyntaxException; +import org.apache.harmony.kernel.vm.VM; import org.apache.harmony.luni.util.PriviAction; /** @@ -46,1681 +47,1760 @@ * @see Charset * @since 1.0 */ -public final class String implements Serializable, Comparable, CharSequence { - - private static final long serialVersionUID = -6849794470754667710L; - - /** - * An PrintStream used for System.out which performs the correct character - * conversion for the console, since the console may use a different - * conversion than the default file.encoding. - */ - static class ConsolePrintStream extends java.io.PrintStream { - private static String charset; - - static { - charset = (String) AccessController.doPrivileged(new PriviAction( - "console.encoding", "ISO8859_1")); //$NON-NLS-1$ //$NON-NLS-2$ - if (!Charset.isSupported(charset)) { - charset = "ISO-8859-1"; //$NON-NLS-1$ - } - } - - /** - * Create a ConsolePrintStream on the specified OutputStream, usually - * System.out. - * - * @param out - * the console OutputStream - */ - public ConsolePrintStream(java.io.OutputStream out) { - super(out, true); - - } - - /** - * Override the print(String) method from PrintStream to perform the - * character conversion using the console character converter. - * - * @param str - * the String to convert - */ - public void print(String str) { - if (str == null) - str = "null"; - - try { - write(str.getBytes(charset)); - } catch (java.io.IOException e) { - setError(); - } - } - } - - /** - * CaseInsensitiveComparator compares Strings ignoring the case of the - * characters. - */ - private static final class CaseInsensitiveComparator implements Comparator, - Serializable { - private static final long serialVersionUID = 8575799808933029326L; - - /** - * Compare the two objects to determine the relative ordering. - * - * @param o1 - * an Object to compare - * @param o2 - * an Object to compare - * @return an int < 0 if object1 is less than object2, 0 if they are - * equal, and > 0 if object1 is greater - * - * @exception ClassCastException - * when objects are not the correct type - */ - public int compare(String o1, String o2) { - return o1.compareToIgnoreCase(o2); - } - } - - /* - * A Comparator which compares Strings ignoring the case of the characters. - */ - public static final Comparator CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); - - private static final char[] ascii; - - private final char[] value; - - private final int offset; - - private final int count; - - private int hashCode; - - private static Charset DefaultCharset; - - private static Charset lastCharset; - - static { - ascii = new char[128]; - for (int i = 0; i < ascii.length; i++) - ascii[i] = (char) i; - } - - /** - * Answers an empty string. - */ - public String() { - value = new char[0]; - offset = 0; - count = 0; - } - - private String(String s, char c) { - offset = 0; - value = new char[s.count + 1]; - count = s.count + 1; - System.arraycopy(s.value, s.offset, value, 0, s.count); - value[s.count] = c; - } - - /** - * Converts the byte array to a String using the default encoding as - * specified by the file.encoding system property. If the system property is - * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 - * is not available, an ASCII encoding is used. - * - * @param data - * the byte array to convert to a String - * - * @throws NullPointerException - * when data is null - * - * @see #getBytes() - * @see #getBytes(int, int, byte[], int) - * @see #getBytes(String) - * @see #valueOf(boolean) - * @see #valueOf(char) - * @see #valueOf(char[]) - * @see #valueOf(char[], int, int) - * @see #valueOf(double) - * @see #valueOf(float) - * @see #valueOf(int) - * @see #valueOf(long) - * @see #valueOf(Object) - * - */ - public String(byte[] data) { - this(data, 0, data.length); - } - - /** - * Converts the byte array to a String, setting the high byte of every - * character to the specified value. - * - * @param data - * the byte array to convert to a String - * @param high - * the high byte to use - * - * @throws NullPointerException - * when data is null - * - * @deprecated Use String(byte[]) or String(byte[], String) instead - */ - public String(byte[] data, int high) { - this(data, high, 0, data.length); - } - - /** - * Converts the byte array to a String using the default encoding as - * specified by the file.encoding system property. If the system property is - * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 - * is not available, an ASCII encoding is used. - * - * @param data - * the byte array to convert to a String - * @param start - * the starting offset in the byte array - * @param length - * the number of bytes to convert - * - * @throws IndexOutOfBoundsException - * when length < 0, start < 0 or - * start + length > data.length - * @throws NullPointerException - * when data is null - * - * @see #getBytes() - * @see #getBytes(int, int, byte[], int) - * @see #getBytes(String) - * @see #valueOf(boolean) - * @see #valueOf(char) - * @see #valueOf(char[]) - * @see #valueOf(char[], int, int) - * @see #valueOf(double) - * @see #valueOf(float) - * @see #valueOf(int) - * @see #valueOf(long) - * @see #valueOf(Object) - * - */ - public String(byte[] data, int start, int length) { - // start + length could overflow, start/length maybe MaxInt - if (start >= 0 && 0 <= length && length <= data.length - start) { - offset = 0; - Charset charset = defaultCharset(); - int result; - CharBuffer cb = charset - .decode(ByteBuffer.wrap(data, start, length)); - if ((result = cb.length()) > 0) { - value = cb.array(); - count = result; - } else { - count = 0; - value = new char[0]; - } - } else - throw new StringIndexOutOfBoundsException(); - } - - /** - * Converts the byte array to a String, setting the high byte of every - * character to the specified value. - * - * @param data - * the byte array to convert to a String - * @param high - * the high byte to use - * @param start - * the starting offset in the byte array - * @param length - * the number of bytes to convert - * - * @throws IndexOutOfBoundsException - * when length < 0, start < 0 or - * start + length > data.length - * @throws NullPointerException - * when data is null - * - * @deprecated Use String(byte[], int, int) instead - */ - public String(byte[] data, int high, int start, int length) { - if (data != null) { - // start + length could overflow, start/length maybe MaxInt - if (start >= 0 && 0 <= length && length <= data.length - start) { - offset = 0; - value = new char[length]; - count = length; - high <<= 8; - for (int i = 0; i < count; i++) - value[i] = (char) (high + (data[start++] & 0xff)); - } else - throw new StringIndexOutOfBoundsException(); - } else - throw new NullPointerException(); - } - - /** - * Converts the byte array to a String using the specified encoding. - * - * @param data - * the byte array to convert to a String - * @param start - * the starting offset in the byte array - * @param length - * the number of bytes to convert - * @param encoding - * the encoding - * - * @throws IndexOutOfBoundsException - * when length < 0, start < 0 or - * start + length > data.length - * @throws UnsupportedEncodingException - * when encoding is not supported - * @throws NullPointerException - * when data is null - * - * @see #getBytes() - * @see #getBytes(int, int, byte[], int) - * @see #getBytes(String) - * @see #valueOf(boolean) - * @see #valueOf(char) - * @see #valueOf(char[]) - * @see #valueOf(char[], int, int) - * @see #valueOf(double) - * @see #valueOf(float) - * @see #valueOf(int) - * @see #valueOf(long) - * @see #valueOf(Object) - * @see UnsupportedEncodingException - */ - public String(byte[] data, int start, int length, final String encoding) - throws UnsupportedEncodingException { - if (encoding == null) - throw new NullPointerException(); - // start + length could overflow, start/length maybe MaxInt - if (start >= 0 && 0 <= length && length <= data.length - start) { - offset = 0; - Charset charset = getCharset(encoding); - - int result; - CharBuffer cb = charset - .decode(ByteBuffer.wrap(data, start, length)); - if ((result = cb.length()) > 0) { - value = cb.array(); - count = result; - } else { - count = 0; - value = new char[0]; - } - } else - throw new StringIndexOutOfBoundsException(); - } - - /** - * Converts the byte array to a String using the specified encoding. - * - * @param data - * the byte array to convert to a String - * @param encoding - * the encoding - * - * @throws UnsupportedEncodingException - * when encoding is not supported - * @throws NullPointerException - * when data is null - * - * @see #getBytes() - * @see #getBytes(int, int, byte[], int) - * @see #getBytes(String) - * @see #valueOf(boolean) - * @see #valueOf(char) - * @see #valueOf(char[]) - * @see #valueOf(char[], int, int) - * @see #valueOf(double) - * @see #valueOf(float) - * @see #valueOf(int) - * @see #valueOf(long) - * @see #valueOf(Object) - * @see UnsupportedEncodingException - */ - public String(byte[] data, String encoding) - throws UnsupportedEncodingException { - this(data, 0, data.length, encoding); - } - - /** - * Initializes this String to contain the characters in the specified - * character array. Modifying the character array after creating the String - * has no effect on the String. - * - * @param data - * the array of characters - * - * @throws NullPointerException - * when data is null - */ - public String(char[] data) { - this(data, 0, data.length); - } - - /** - * Initializes this String to contain the specified characters in the - * character array. Modifying the character array after creating the String - * has no effect on the String. - * - * @param data - * the array of characters - * @param start - * the starting offset in the character array - * @param length - * the number of characters to use - * - * @throws IndexOutOfBoundsException - * when length < 0, start < 0 or - * start + length > data.length - * @throws NullPointerException - * when data is null - */ - public String(char[] data, int start, int length) { - // range check everything so a new char[] is not created - // start + length could overflow, start/length maybe MaxInt - if (start >= 0 && 0 <= length && length <= data.length - start) { - offset = 0; - value = new char[length]; - count = length; - - System.arraycopy(data, start, value, 0, count); - } else - throw new StringIndexOutOfBoundsException(); - } - - /* - * Internal version of string constructor. Does not range check, null check, - * or copy the character array. - */ - String(int start, int length, char[] data) { - value = data; - offset = start; - count = length; - } - - /** - * Creates a string that is a copy of another string - * - * @param string - * the String to copy - */ - public String(String string) { - value = string.value; - offset = string.offset; - count = string.count; - } - - /** - * Creates a string from the contents of a StringBuffer. - * - * @param stringbuffer - * the StringBuffer - */ - public String(StringBuffer stringbuffer) { - offset = 0; - synchronized (stringbuffer) { - value = stringbuffer.shareValue(); - count = stringbuffer.length(); - } - } - +public final class String implements Serializable, Comparable, + CharSequence { + + private static final long serialVersionUID = -6849794470754667710L; + + /** + * An PrintStream used for System.out which performs the correct character + * conversion for the console, since the console may use a different + * conversion than the default file.encoding. + */ + static class ConsolePrintStream extends java.io.PrintStream { + private static String charset; + + static { + charset = AccessController.doPrivileged(new PriviAction( + "console.encoding", "ISO8859_1")); //$NON-NLS-1$ //$NON-NLS-2$ + if (!Charset.isSupported(charset)) { + charset = "ISO-8859-1"; //$NON-NLS-1$ + } + } + + /** + * Create a ConsolePrintStream on the specified OutputStream, usually + * System.out. + * + * @param out + * the console OutputStream + */ + public ConsolePrintStream(java.io.OutputStream out) { + super(out, true); + + } + + /** + * Override the print(String) method from PrintStream to perform the + * character conversion using the console character converter. + * + * @param str + * the String to convert + */ + @Override + public void print(String str) { + if (str == null) { + str = "null"; //$NON-NLS-1$ + } + + try { + write(str.getBytes(charset)); + } catch (java.io.IOException e) { + setError(); + } + } + } + + /** + * CaseInsensitiveComparator compares Strings ignoring the case of the + * characters. + */ + private static final class CaseInsensitiveComparator implements + Comparator, Serializable { + private static final long serialVersionUID = 8575799808933029326L; + + /** + * Compare the two objects to determine the relative ordering. + * + * @param o1 + * an Object to compare + * @param o2 + * an Object to compare + * @return an int < 0 if object1 is less than object2, 0 if they are + * equal, and > 0 if object1 is greater + * + * @exception ClassCastException + * when objects are not the correct type + */ + public int compare(String o1, String o2) { + return o1.compareToIgnoreCase(o2); + } + } + + /* + * A Comparator which compares Strings ignoring the case of the characters. + */ + public static final Comparator CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); + + private static final char[] ascii; + + private final char[] value; + + private final int offset; + + private final int count; + + private int hashCode; + + private static Charset DefaultCharset; + + private static Charset lastCharset; + + static { + ascii = new char[128]; + for (int i = 0; i < ascii.length; i++) { + ascii[i] = (char) i; + } + } + + /** + * Answers an empty string. + */ + public String() { + value = new char[0]; + offset = 0; + count = 0; + } + + @SuppressWarnings("unused") + private String(String s, char c) { + offset = 0; + value = new char[s.count + 1]; + count = s.count + 1; + System.arraycopy(s.value, s.offset, value, 0, s.count); + value[s.count] = c; + } + + /** + * Converts the byte array to a String using the default encoding as + * specified by the file.encoding system property. If the system property is + * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 + * is not available, an ASCII encoding is used. + * + * @param data + * the byte array to convert to a String + * + * @throws NullPointerException + * when data is null + * + * @see #getBytes() + * @see #getBytes(int, int, byte[], int) + * @see #getBytes(String) + * @see #valueOf(boolean) + * @see #valueOf(char) + * @see #valueOf(char[]) + * @see #valueOf(char[], int, int) + * @see #valueOf(double) + * @see #valueOf(float) + * @see #valueOf(int) + * @see #valueOf(long) + * @see #valueOf(Object) + * + */ + public String(byte[] data) { + this(data, 0, data.length); + } + + /** + * Converts the byte array to a String, setting the high byte of every + * character to the specified value. + * + * @param data + * the byte array to convert to a String + * @param high + * the high byte to use + * + * @throws NullPointerException + * when data is null + * + * @deprecated Use String(byte[]) or String(byte[], String) instead + */ + @Deprecated + public String(byte[] data, int high) { + this(data, high, 0, data.length); + } + + /** + * Converts the byte array to a String using the default encoding as + * specified by the file.encoding system property. If the system property is + * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 + * is not available, an ASCII encoding is used. + * + * @param data + * the byte array to convert to a String + * @param start + * the starting offset in the byte array + * @param length + * the number of bytes to convert + * + * @throws IndexOutOfBoundsException + * when length < 0, start < 0 or + * start + length > data.length + * @throws NullPointerException + * when data is null + * + * @see #getBytes() + * @see #getBytes(int, int, byte[], int) + * @see #getBytes(String) + * @see #valueOf(boolean) + * @see #valueOf(char) + * @see #valueOf(char[]) + * @see #valueOf(char[], int, int) + * @see #valueOf(double) + * @see #valueOf(float) + * @see #valueOf(int) + * @see #valueOf(long) + * @see #valueOf(Object) + */ + public String(byte[] data, int start, int length) { + // start + length could overflow, start/length maybe MaxInt + if (start >= 0 && 0 <= length && length <= data.length - start) { + offset = 0; + Charset charset = defaultCharset(); + int result; + CharBuffer cb = charset + .decode(ByteBuffer.wrap(data, start, length)); + if ((result = cb.length()) > 0) { + value = cb.array(); + count = result; + } else { + count = 0; + value = new char[0]; + } + } else { + throw new StringIndexOutOfBoundsException(); + } + } + + /** + * Converts the byte array to a String, setting the high byte of every + * character to the specified value. + * + * @param data + * the byte array to convert to a String + * @param high + * the high byte to use + * @param start + * the starting offset in the byte array + * @param length + * the number of bytes to convert + * + * @throws IndexOutOfBoundsException + * when length < 0, start < 0 or + * start + length > data.length + * @throws NullPointerException + * when data is null + * + * @deprecated Use String(byte[], int, int) instead + */ + @Deprecated + public String(byte[] data, int high, int start, int length) { + if (data != null) { + // start + length could overflow, start/length maybe MaxInt + if (start >= 0 && 0 <= length && length <= data.length - start) { + offset = 0; + value = new char[length]; + count = length; + high <<= 8; + for (int i = 0; i < count; i++) { + value[i] = (char) (high + (data[start++] & 0xff)); + } + } else { + throw new StringIndexOutOfBoundsException(); + } + } else { + throw new NullPointerException(); + } + } + + /** + * Converts the byte array to a String using the specified encoding. + * + * @param data + * the byte array to convert to a String + * @param start + * the starting offset in the byte array + * @param length + * the number of bytes to convert + * @param encoding + * the encoding + * + * @throws IndexOutOfBoundsException + * when length < 0, start < 0 or + * start + length > data.length + * @throws UnsupportedEncodingException + * when encoding is not supported + * @throws NullPointerException + * when data is null + * + * @see #getBytes() + * @see #getBytes(int, int, byte[], int) + * @see #getBytes(String) + * @see #valueOf(boolean) + * @see #valueOf(char) + * @see #valueOf(char[]) + * @see #valueOf(char[], int, int) + * @see #valueOf(double) + * @see #valueOf(float) + * @see #valueOf(int) + * @see #valueOf(long) + * @see #valueOf(Object) + * @see UnsupportedEncodingException + */ + public String(byte[] data, int start, int length, final String encoding) + throws UnsupportedEncodingException { + if (encoding == null) { + throw new NullPointerException(); + } + // start + length could overflow, start/length maybe MaxInt + if (start >= 0 && 0 <= length && length <= data.length - start) { + offset = 0; + Charset charset = getCharset(encoding); + + int result; + CharBuffer cb = charset + .decode(ByteBuffer.wrap(data, start, length)); + if ((result = cb.length()) > 0) { + value = cb.array(); + count = result; + } else { + count = 0; + value = new char[0]; + } + } else { + throw new StringIndexOutOfBoundsException(); + } + } + + /** + * Converts the byte array to a String using the specified encoding. + * + * @param data + * the byte array to convert to a String + * @param encoding + * the encoding + * + * @throws UnsupportedEncodingException + * when encoding is not supported + * @throws NullPointerException + * when data is null + * + * @see #getBytes() + * @see #getBytes(int, int, byte[], int) + * @see #getBytes(String) + * @see #valueOf(boolean) + * @see #valueOf(char) + * @see #valueOf(char[]) + * @see #valueOf(char[], int, int) + * @see #valueOf(double) + * @see #valueOf(float) + * @see #valueOf(int) + * @see #valueOf(long) + * @see #valueOf(Object) + * @see UnsupportedEncodingException + */ + public String(byte[] data, String encoding) throws UnsupportedEncodingException { + this(data, 0, data.length, encoding); + } + + /** + * Initializes this String to contain the characters in the specified + * character array. Modifying the character array after creating the String + * has no effect on the String. + * + * @param data + * the array of characters + * + * @throws NullPointerException + * when data is null + */ + public String(char[] data) { + this(data, 0, data.length); + } + + /** + * Initializes this String to contain the specified characters in the + * character array. Modifying the character array after creating the String + * has no effect on the String. + * + * @param data + * the array of characters + * @param start + * the starting offset in the character array + * @param length + * the number of characters to use + * + * @throws IndexOutOfBoundsException + * when length < 0, start < 0 or + * start + length > data.length + * @throws NullPointerException + * when data is null + */ + public String(char[] data, int start, int length) { + // range check everything so a new char[] is not created + // start + length could overflow, start/length maybe MaxInt + if (start >= 0 && 0 <= length && length <= data.length - start) { + offset = 0; + value = new char[length]; + count = length; + System.arraycopy(data, start, value, 0, count); + } else { + throw new StringIndexOutOfBoundsException(); + } + } + + /* + * Internal version of string constructor. Does not range check, null check, + * or copy the character array. + */ + String(int start, int length, char[] data) { + value = data; + offset = start; + count = length; + } + + /** + * Creates a string that is a copy of another string + * + * @param string + * the String to copy + */ + public String(String string) { + value = string.value; + offset = string.offset; + count = string.count; + } + + /** + * Creates a string from the contents of a StringBuffer. + * + * @param stringbuffer + * the StringBuffer + */ + public String(StringBuffer stringbuffer) { + offset = 0; + synchronized (stringbuffer) { + value = stringbuffer.shareValue(); + count = stringbuffer.length(); + } + } + + /** + *

+ * Constructs a String from the sub-array of Unicode code + * points. + *

+ * + * @param codePoints + * The array of Unicode code points to convert. + * @param offset + * The inclusive index into codePoints to begin + * converting from. + * @param count + * The number of element in codePoints to copy. + * @throws NullPointerException + * if codePoints is null. + * @throws IllegalArgumentException + * if any of the elements of codePoints are not + * valid Unicode code points. + * @throws IndexOutOfBoundsException + * if offset or count are not + * within the bounds of codePoints. + * @since 1.5 + */ + public String(int[] codePoints, int offset, int count) { + super(); + if (codePoints == null) { + throw new NullPointerException(); + } + if (offset < 0 || count < 0 + || (long) offset + (long) count > codePoints.length) { + throw new IndexOutOfBoundsException(); + } + this.offset = 0; + this.value = new char[count * 2]; + int end = offset + count; + int c = 0; + for (int i = offset; i < end; i++) { + c += Character.toChars(codePoints[i], this.value, c); + } + this.count = c; + } + + /** + *

+ * Constructs a String from a StringBuilder. + *

+ * + * @param sb + * The StringBuilder to copy from. + * @throws NullPointerException + * if sb is null. + * @since 1.5 + */ + public String(StringBuilder sb) { + if (sb == null) { + throw new NullPointerException(); + } + this.offset = 0; + this.count = sb.length(); + this.value = new char[this.count]; + sb.getChars(0, this.count, this.value, 0); + } + + /* + * Creates a string that is s1 + v1. May be used by JIT code. + */ + @SuppressWarnings("unused") + private String(String s1, int v1) { + if (s1 == null) { + s1 = "null"; //$NON-NLS-1$ + } + String s2 = String.valueOf(v1); + int len = s1.count + s2.count; + value = new char[len]; + offset = 0; + System.arraycopy(s1.value, s1.offset, value, 0, s1.count); + System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); + count = len; + } + + /** + * Answers the character at the specified offset in this String. + * + * @param index + * the zero-based index in this string + * @return the character at the index + * + * @throws IndexOutOfBoundsException + * when index < 0 or + * index >= length() + */ + public char charAt(int index) { + if (0 <= index && index < count) { + return value[offset + index]; + } + throw new StringIndexOutOfBoundsException(); + } + + /** + * Compares the specified String to this String using the Unicode values of + * the characters. Answer 0 if the strings contain the same characters in + * the same order. Answer a negative integer if the first non-equal + * character in this String has a Unicode value which is less than the + * Unicode value of the character at the same position in the specified + * string, or if this String is a prefix of the specified string. Answer a + * positive integer if the first non-equal character in this String has a + * Unicode value which is greater than the Unicode value of the character at + * the same position in the specified string, or if the specified String is + * a prefix of the this String. + * + * @param string + * the string to compare + * @return 0 if the strings are equal, a negative integer if this String is + * before the specified String, or a positive integer if this String + * is after the specified String + * + * @throws NullPointerException + * when string is null + */ + public int compareTo(String string) { + // Code adapted from K&R, pg 101 + int o1 = offset, o2 = string.offset, result; + int end = offset + (count < string.count ? count : string.count); + char[] target = string.value; + while (o1 < end) { + if ((result = value[o1++] - target[o2++]) != 0) { + return result; + } + } + return count - string.count; + } + + /** + * Compare the receiver to the specified String to determine the relative + * ordering when the case of the characters is ignored. + * + * @param string + * a String + * @return an int < 0 if this String is less than the specified String, 0 if + * they are equal, and > 0 if this String is greater + */ + public int compareToIgnoreCase(String string) { + int o1 = offset, o2 = string.offset, result; + int end = offset + (count < string.count ? count : string.count); + char c1, c2; + char[] target = string.value; + while (o1 < end) { + if ((c1 = value[o1++]) == (c2 = target[o2++])) { + continue; + } + c1 = Character.toLowerCase(Character.toUpperCase(c1)); + c2 = Character.toLowerCase(Character.toUpperCase(c2)); + if ((result = c1 - c2) != 0) { + return result; + } + } + return count - string.count; + } + + /** + * Concatenates this String and the specified string. + * + * @param string + * the string to concatenate + * @return a new String which is the concatenation of this String and the + * specified String + * + * @throws NullPointerException + * if string is null + */ + public String concat(String string) { + if (string.count > 0 && count > 0) { + char[] buffer = new char[count + string.count]; + System.arraycopy(value, offset, buffer, 0, count); + System.arraycopy(string.value, string.offset, buffer, count, + string.count); + return new String(0, buffer.length, buffer); + } + return count == 0 ? string : this; + } + + /** + * Creates a new String containing the characters in the specified character + * array. Modifying the character array after creating the String has no + * effect on the String. + * + * @param data + * the array of characters + * @return the new String + * + * @throws NullPointerException + * if data is null + */ + public static String copyValueOf(char[] data) { + return new String(data, 0, data.length); + } + + /** + * Creates a new String containing the specified characters in the character + * array. Modifying the character array after creating the String has no + * effect on the String. + * + * @param data + * the array of characters + * @param start + * the starting offset in the character array + * @param length + * the number of characters to use + * @return the new String + * + * @throws IndexOutOfBoundsException + * if length < 0, start < 0 or + * start + length > data.length + * @throws NullPointerException + * if data is null + */ + public static String copyValueOf(char[] data, int start, int length) { + return new String(data, start, length); + } + + private Charset defaultCharset() { + if (DefaultCharset == null) { + String encoding = AccessController + .doPrivileged(new PriviAction( + "file.encoding", "ISO8859_1")); //$NON-NLS-1$ //$NON-NLS-2$ + // calling System.getProperty() may cause DefaultCharset to be + // initialized + try { + DefaultCharset = Charset.forName(encoding); + } catch (IllegalCharsetNameException e) { + // Ignored + } catch (UnsupportedCharsetException e) { + // Ignored + } + + if (DefaultCharset == null) { + DefaultCharset = Charset.forName("ISO-8859-1"); //$NON-NLS-1$ + } + } + return DefaultCharset; + } + + /** + * Compares the specified string to this String to determine if the + * specified string is a suffix. + * + * @param suffix + * the string to look for + * @return true when the specified string is a suffix of this String, false + * otherwise + * + * @throws NullPointerException + * if suffix is null + */ + public boolean endsWith(String suffix) { + return regionMatches(count - suffix.count, suffix, 0, suffix.count); + } + + /** + * Compares the specified object to this String and answer if they are + * equal. The object must be an instance of String with the same characters + * in the same order. + * + * @param object + * the object to compare + * @return true if the specified object is equal to this String, false + * otherwise + * + * @see #hashCode + */ + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof String) { + String s = (String) object; + if (count != s.count + || (hashCode != s.hashCode && hashCode != 0 && s.hashCode != 0)) { + return false; + } + return regionMatches(0, s, 0, count); + } + return false; + } + + /** + * Compares the specified String to this String ignoring the case of the + * characters and answer if they are equal. + * + * @param string + * the string to compare + * @return true if the specified string is equal to this String, false + * otherwise + */ + public boolean equalsIgnoreCase(String string) { + if (string == this) { + return true; + } + if (string == null || count != string.count) { + return false; + } + + int o1 = offset, o2 = string.offset; + int end = offset + count; + char c1, c2; + char[] target = string.value; + while (o1 < end) { + if ((c1 = value[o1++]) != (c2 = target[o2++]) + && Character.toUpperCase(c1) != Character.toUpperCase(c2) + // Required for unicode that we test both cases + && Character.toLowerCase(c1) != Character.toLowerCase(c2)) { + return false; + } + } + return true; + } + + /** + * Converts this String to a byte encoding using the default encoding as + * specified by the file.encoding system property. If the system property is + * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 + * is not available, an ASCII encoding is used. + * + * @return the byte array encoding of this String + * + * @see String + */ + public byte[] getBytes() { + ByteBuffer buffer = defaultCharset().encode( + CharBuffer.wrap(this.value, this.offset, this.count)); + byte[] bytes = new byte[buffer.limit()]; + buffer.get(bytes); + return bytes; + } + + /** + * Converts this String to a byte array, ignoring the high order bits of + * each character. + * + * @param start + * the starting offset of characters to copy + * @param end + * the ending offset of characters to copy + * @param data + * the destination byte array + * @param index + * the starting offset in the byte array + * + * @throws NullPointerException + * when data is null + * @throws IndexOutOfBoundsException + * when + * start < 0, end > length(), index < 0, end - start > data.length - index + * + * @deprecated Use getBytes() or getBytes(String) + */ + @Deprecated + public void getBytes(int start, int end, byte[] data, int index) { + if (0 <= start && start <= end && end <= count) { + end += offset; + try { + for (int i = offset + start; i < end; i++) { + data[index++] = (byte) value[i]; + } + } catch (ArrayIndexOutOfBoundsException e) { + throw new StringIndexOutOfBoundsException(); + } + } else { + throw new StringIndexOutOfBoundsException(); + } + } + + /** + * Converts this String to a byte encoding using the specified encoding. + * + * @param encoding + * the encoding + * @return the byte array encoding of this String + * + * @throws UnsupportedEncodingException + * when the encoding is not supported + * + * @see String + * @see UnsupportedEncodingException + */ + public byte[] getBytes(String encoding) throws UnsupportedEncodingException { + ByteBuffer buffer = getCharset(encoding).encode( + CharBuffer.wrap(this.value, this.offset, this.count)); + byte[] bytes = new byte[buffer.limit()]; + buffer.get(bytes); + return bytes; + } + + private Charset getCharset(final String encoding) + throws UnsupportedEncodingException { + Charset charset = lastCharset; + if (charset == null || !encoding.equalsIgnoreCase(charset.name())) { + try { + charset = Charset.forName(encoding); + } catch (IllegalCharsetNameException e) { + throw (UnsupportedEncodingException) (new UnsupportedEncodingException( + encoding).initCause(e)); + } catch (UnsupportedCharsetException e) { + throw (UnsupportedEncodingException) (new UnsupportedEncodingException( + encoding).initCause(e)); + } + lastCharset = charset; + } + return charset; + } + + /** + * Copies the specified characters in this String to the character array + * starting at the specified offset in the character array. + * + * @param start + * the starting offset of characters to copy + * @param end + * the ending offset of characters to copy + * @param buffer + * the destination character array + * @param index + * the starting offset in the character array + * + * @throws IndexOutOfBoundsException + * when start < 0, end > length(), + * start > end, index < 0, end - start > buffer.length - index + * @throws NullPointerException + * when buffer is null + */ + public void getChars(int start, int end, char[] buffer, int index) { + // NOTE last character not copied! + // Fast range check. + if (0 <= start && start <= end && end <= count) { + System.arraycopy(value, start + offset, buffer, index, end - start); + } else { + throw new StringIndexOutOfBoundsException(); + } + } + + /** + * Answers an integer hash code for the receiver. Objects which are equal + * answer the same value for this method. + * + * @return the receiver's hash + * + * @see #equals + */ + @Override + public int hashCode() { + if (hashCode == 0) { + int hash = 0, multiplier = 1; + for (int i = offset + count - 1; i >= offset; i--) { + hash += value[i] * multiplier; + int shifted = multiplier << 5; + multiplier = shifted - multiplier; + } + hashCode = hash; + } + return hashCode; + } + + /** + * Searches in this String for the first index of the specified character. + * The search for the character starts at the beginning and moves towards + * the end of this String. + * + * @param c + * the character to find + * @return the index in this String of the specified character, -1 if the + * character isn't found + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int indexOf(int c) { + return indexOf(c, 0); + } + + /** + * Searches in this String for the index of the specified character. The + * search for the character starts at the specified offset and moves towards + * the end of this String. + * + * @param c + * the character to find + * @param start + * the starting offset + * @return the index in this String of the specified character, -1 if the + * character isn't found + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int indexOf(int c, int start) { + if (start < count) { + if (start < 0) { + start = 0; + } + for (int i = offset + start; i < offset + count; i++) { + if (value[i] == c) { + return i - offset; + } + } + } + return -1; + } + + /** + * Searches in this String for the first index of the specified string. The + * search for the string starts at the beginning and moves towards the end + * of this String. + * + * @param string + * the string to find + * @return the index in this String of the specified string, -1 if the + * string isn't found + * + * @throws NullPointerException + * when string is null + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int indexOf(String string) { + return indexOf(string, 0); + } + + /** + * Searches in this String for the index of the specified string. The search + * for the string starts at the specified offset and moves towards the end + * of this String. + * + * @param subString + * the string to find + * @param start + * the starting offset + * @return the index in this String of the specified string, -1 if the + * string isn't found + * + * @throws NullPointerException + * when string is null + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int indexOf(String subString, int start) { + if (start < 0) { + start = 0; + } + int subCount = subString.count; + if (subCount > 0) { + if (subCount + start > count) { + return -1; + } + char[] target = subString.value; + int subOffset = subString.offset; + char firstChar = target[subOffset]; + int end = subOffset + subCount; + while (true) { + int i = indexOf(firstChar, start); + if (i == -1 || subCount + i > count) { + return -1; // handles subCount > count || start >= count + } + int o1 = offset + i, o2 = subOffset; + while (++o2 < end && value[++o1] == target[o2]) { + // Intentionally empty + } + if (o2 == end) { + return i; + } + start = i + 1; + } + } + return start < count ? start : count; + } + + /** + * Searches an internal table of strings for a string equal to this String. + * If the string is not in the table, it is added. Answers the string + * contained in the table which is equal to this String. The same string + * object is always answered for strings which are equal. + * + * @return the interned string equal to this String + */ + public String intern() { + return VM.intern(this); + } + + /** + * Searches in this String for the last index of the specified character. + * The search for the character starts at the end and moves towards the + * beginning of this String. + * + * @param c + * the character to find + * @return the index in this String of the specified character, -1 if the + * character isn't found + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int lastIndexOf(int c) { + return lastIndexOf(c, count - 1); + } + + /** + * Searches in this String for the index of the specified character. The + * search for the character starts at the specified offset and moves towards + * the beginning of this String. + * + * @param c + * the character to find + * @param start + * the starting offset + * @return the index in this String of the specified character, -1 if the + * character isn't found + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int lastIndexOf(int c, int start) { + if (start >= 0) { + if (start >= count) { + start = count - 1; + } + for (int i = offset + start; i >= offset; --i) { + if (value[i] == c) { + return i - offset; + } + } + } + return -1; + } + + /** + * Searches in this String for the last index of the specified string. The + * search for the string starts at the end and moves towards the beginning + * of this String. + * + * @param string + * the string to find + * @return the index in this String of the specified string, -1 if the + * string isn't found + * + * @throws NullPointerException + * when string is null + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int lastIndexOf(String string) { + // Use count instead of count - 1 so lastIndexOf("") answers count + return lastIndexOf(string, count); + } + + /** + * Searches in this String for the index of the specified string. The search + * for the string starts at the specified offset and moves towards the + * beginning of this String. + * + * @param subString + * the string to find + * @param start + * the starting offset + * @return the index in this String of the specified string, -1 if the + * string isn't found + * + * @throws NullPointerException + * when string is null + * + * @see #lastIndexOf(int) + * @see #lastIndexOf(int, int) + * @see #lastIndexOf(String) + * @see #lastIndexOf(String, int) + */ + public int lastIndexOf(String subString, int start) { + int subCount = subString.count; + if (subCount <= count && start >= 0) { + if (subCount > 0) { + if (start > count - subCount) { + start = count - subCount; + } + // count and subCount are both >= 1 + char[] target = subString.value; + int subOffset = subString.offset; + char firstChar = target[subOffset]; + int end = subOffset + subCount; + while (true) { + int i = lastIndexOf(firstChar, start); + if (i == -1) { + return -1; + } + int o1 = offset + i, o2 = subOffset; + while (++o2 < end && value[++o1] == target[o2]) { + // Intentionally empty + } + if (o2 == end) { + return i; + } + start = i - 1; + } + } + return start < count ? start : count; + } + return -1; + } + + /** + * Answers the size of this String. + * + * @return the number of characters in this String + */ + public int length() { + return count; + } + + /** + * Compares the specified string to this String and compares the specified + * range of characters to determine if they are the same. + * + * @param thisStart + * the starting offset in this String + * @param string + * the string to compare + * @param start + * the starting offset in string + * @param length + * the number of characters to compare + * @return true if the ranges of characters is equal, false otherwise + * + * @throws NullPointerException + * when string is null + */ + public boolean regionMatches(int thisStart, String string, int start, + int length) { + if (string == null) { + throw new NullPointerException(); + } + if (start < 0 || string.count - start < length) { + return false; + } + if (thisStart < 0 || count - thisStart < length) { + return false; + } + if (length <= 0) { + return true; + } + int o1 = offset + thisStart, o2 = string.offset + start; + for (int i = 0; i < length; ++i) { + if (value[o1 + i] != string.value[o2 + i]) { + return false; + } + } + return true; + } + /** - *

- * Constructs a String from the sub-array of Unicode code - * points. - *

+ * Compares the specified string to this String and compares the specified + * range of characters to determine if they are the same. When ignoreCase is + * true, the case of the characters is ignored during the comparison. * - * @param codePoints The array of Unicode code points to convert. - * @param offset The inclusive index into codePoints to begin - * converting from. - * @param count The number of element in codePoints to copy. - * @throws NullPointerException if codePoints is null. - * @throws IllegalArgumentException if any of the elements of - * codePoints are not valid Unicode code points. - * @throws IndexOutOfBoundsException if offset or - * count are not within the bounds of - * codePoints. - * @since 1.5 + * @param ignoreCase + * specifies if case should be ignored + * @param thisStart + * the starting offset in this String + * @param string + * the string to compare + * @param start + * the starting offset in string + * @param length + * the number of characters to compare + * @return true if the ranges of characters is equal, false otherwise + * + * @throws NullPointerException + * when string is null */ - public String(int[] codePoints, int offset, int count) { - super(); - if (codePoints == null) - throw new NullPointerException(); - if (offset < 0 || count < 0 || (long)offset + (long)count > codePoints.length) - throw new IndexOutOfBoundsException(); - this.offset = 0; - this.value = new char[count * 2]; - int end = offset + count; - int c = 0; - for (int i = offset; i < end; i++) { - c += Character.toChars(codePoints[i], this.value, c); + public boolean regionMatches(boolean ignoreCase, int thisStart, + String string, int start, int length) { + if (!ignoreCase) { + return regionMatches(thisStart, string, start, length); } - this.count = c; + + if (string != null) { + if (thisStart < 0 || length > count - thisStart) { + return false; + } + if (start < 0 || length > string.count - start) { + return false; + } + + thisStart += offset; + start += string.offset; + int end = thisStart + length; + char c1, c2; + char[] target = string.value; + while (thisStart < end) { + if ((c1 = value[thisStart++]) != (c2 = target[start++]) + && Character.toUpperCase(c1) != Character + .toUpperCase(c2) + // Required for unicode that we test both cases + && Character.toLowerCase(c1) != Character + .toLowerCase(c2)) { + return false; + } + } + return true; + } + throw new NullPointerException(); } - + /** - *

- * Constructs a String from a StringBuilder. - *

+ * Copies this String replacing occurrences of the specified character with + * another character. * - * @param sb The StringBuilder to copy from. - * @throws NullPointerException if sb is null. - * @since 1.5 + * @param oldChar + * the character to replace + * @param newChar + * the replacement character + * @return a new String with occurrences of oldChar replaced by newChar */ - public String(StringBuilder sb) { - if (sb == null) - throw new NullPointerException(); - this.offset = 0; - this.count = sb.length(); - this.value = new char[this.count]; - sb.getChars(0, this.count, this.value, 0); + public String replace(char oldChar, char newChar) { + int index = indexOf(oldChar, 0); + if (index == -1) { + return this; + } + + char[] buffer = new char[count]; + System.arraycopy(value, offset, buffer, 0, count); + do { + buffer[index++] = newChar; + } while ((index = indexOf(oldChar, index)) != -1); + return new String(0, count, buffer); } - /* - * Creates a string that is s1 + v1. + /** + * Compares the specified string to this String to determine if the + * specified string is a prefix. + * + * @param prefix + * the string to look for + * @return true when the specified string is a prefix of this String, false + * otherwise + * + * @throws NullPointerException + * when prefix is null */ - private String(String s1, int v1) { - if (s1 == null) - s1 = "null"; - String s2 = String.valueOf(v1); - int len = s1.count + s2.count; - value = new char[len]; - offset = 0; - System.arraycopy(s1.value, s1.offset, value, 0, s1.count); - System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); - count = len; - } - - /** - * Answers the character at the specified offset in this String. - * - * @param index - * the zero-based index in this string - * @return the character at the index - * - * @throws IndexOutOfBoundsException - * when index < 0 or - * index >= length() - */ - public char charAt(int index) { - if (0 <= index && index < count) - return value[offset + index]; - throw new StringIndexOutOfBoundsException(); - } - - /** - * Compares the specified String to this String using the Unicode values of - * the characters. Answer 0 if the strings contain the same characters in - * the same order. Answer a negative integer if the first non-equal - * character in this String has a Unicode value which is less than the - * Unicode value of the character at the same position in the specified - * string, or if this String is a prefix of the specified string. Answer a - * positive integer if the first non-equal character in this String has a - * Unicode value which is greater than the Unicode value of the character at - * the same position in the specified string, or if the specified String is - * a prefix of the this String. - * - * @param string - * the string to compare - * @return 0 if the strings are equal, a negative integer if this String is - * before the specified String, or a positive integer if this String - * is after the specified String - * - * @throws NullPointerException - * when string is null - */ - public int compareTo(String string) { - // Code adapted from K&R, pg 101 - int o1 = offset, o2 = string.offset, result; - int end = offset + (count < string.count ? count : string.count); - char[] target = string.value; - while (o1 < end) - if ((result = value[o1++] - target[o2++]) != 0) - return result; - return count - string.count; - } - - /** - * Compare the receiver to the specified String to determine the relative - * ordering when the case of the characters is ignored. - * - * @param string - * a String - * @return an int < 0 if this String is less than the specified String, 0 if - * they are equal, and > 0 if this String is greater - */ - public int compareToIgnoreCase(String string) { - int o1 = offset, o2 = string.offset, result; - int end = offset + (count < string.count ? count : string.count); - char c1, c2; - char[] target = string.value; - while (o1 < end) { - if ((c1 = value[o1++]) == (c2 = target[o2++])) - continue; - c1 = Character.toLowerCase(Character.toUpperCase(c1)); - c2 = Character.toLowerCase(Character.toUpperCase(c2)); - if ((result = c1 - c2) != 0) - return result; - } - return count - string.count; - } - - /** - * Concatenates this String and the specified string. - * - * @param string - * the string to concatenate - * @return a new String which is the concatenation of this String and the - * specified String - * - * @throws NullPointerException - * if string is null - */ - public String concat(String string) { - if (string.count > 0 && count > 0) { - char[] buffer = new char[count + string.count]; - System.arraycopy(value, offset, buffer, 0, count); - System.arraycopy(string.value, string.offset, buffer, count, - string.count); - return new String(0, buffer.length, buffer); - } - return count == 0 ? string : this; - } - - /** - * Creates a new String containing the characters in the specified character - * array. Modifying the character array after creating the String has no - * effect on the String. - * - * @param data - * the array of characters - * @return the new String - * - * @throws NullPointerException - * if data is null - */ - public static String copyValueOf(char[] data) { - return new String(data, 0, data.length); - } - - /** - * Creates a new String containing the specified characters in the character - * array. Modifying the character array after creating the String has no - * effect on the String. - * - * @param data - * the array of characters - * @param start - * the starting offset in the character array - * @param length - * the number of characters to use - * @return the new String - * - * @throws IndexOutOfBoundsException - * if length < 0, start < 0 or - * start + length > data.length - * @throws NullPointerException - * if data is null - */ - public static String copyValueOf(char[] data, int start, int length) { - return new String(data, start, length); - } - - private Charset defaultCharset() { - if (DefaultCharset == null) { - String encoding = (String) AccessController - .doPrivileged(new PriviAction("file.encoding", "ISO8859_1")); - // calling System.getProperty() may cause DefaultCharset to be - // initialized - try { - DefaultCharset = Charset.forName(encoding); - } catch (IllegalCharsetNameException e) { - // - } catch (UnsupportedCharsetException e) { - // - } - - if (DefaultCharset == null) { - DefaultCharset = Charset.forName("ISO-8859-1"); - } - } - return DefaultCharset; - } - - /** - * Compares the specified string to this String to determine if the - * specified string is a suffix. - * - * @param suffix - * the string to look for - * @return true when the specified string is a suffix of this String, false - * otherwise - * - * @throws NullPointerException - * if suffix is null - */ - public boolean endsWith(String suffix) { - return regionMatches(count - suffix.count, suffix, 0, suffix.count); - } - - /** - * Compares the specified object to this String and answer if they are - * equal. The object must be an instance of String with the same characters - * in the same order. - * - * @param object - * the object to compare - * @return true if the specified object is equal to this String, false - * otherwise - * - * @see #hashCode - */ - public boolean equals(Object object) { - if (object == this) - return true; - if (object instanceof String) { - String s = (String) object; - if (count != s.count - || (hashCode != s.hashCode && hashCode != 0 && s.hashCode != 0)) - return false; - return regionMatches(0, s, 0, count); - } - return false; - } - - /** - * Compares the specified String to this String ignoring the case of the - * characters and answer if they are equal. - * - * @param string - * the string to compare - * @return true if the specified string is equal to this String, false - * otherwise - */ - public boolean equalsIgnoreCase(String string) { - if (string == this) - return true; - if (string == null || count != string.count) - return false; - - int o1 = offset, o2 = string.offset; - int end = offset + count; - char c1, c2; - char[] target = string.value; - while (o1 < end) { - if ((c1 = value[o1++]) != (c2 = target[o2++]) - && Character.toUpperCase(c1) != Character.toUpperCase(c2) - // Required for unicode that we test both cases - && Character.toLowerCase(c1) != Character.toLowerCase(c2)) - return false; - } - return true; - } - - /** - * Converts this String to a byte encoding using the default encoding as - * specified by the file.encoding system property. If the system property is - * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 - * is not available, an ASCII encoding is used. - * - * @return the byte array encoding of this String - * - * @see String - */ - public byte[] getBytes() { - ByteBuffer buffer = defaultCharset().encode( - CharBuffer.wrap(this.value, this.offset, this.count)); - byte[] bytes = new byte[buffer.limit()]; - buffer.get(bytes); - return bytes; - } - - /** - * Converts this String to a byte array, ignoring the high order bits of - * each character. - * - * @param start - * the starting offset of characters to copy - * @param end - * the ending offset of characters to copy - * @param data - * the destination byte array - * @param index - * the starting offset in the byte array - * - * @throws NullPointerException - * when data is null - * @throws IndexOutOfBoundsException - * when - * start < 0, end > length(), index < 0, end - start > data.length - index - * - * @deprecated Use getBytes() or getBytes(String) - */ - public void getBytes(int start, int end, byte[] data, int index) { - if (0 <= start && start <= end && end <= count) { - end += offset; - try { - for (int i = offset + start; i < end; i++) - data[index++] = (byte) value[i]; - } catch (ArrayIndexOutOfBoundsException e) { - throw new StringIndexOutOfBoundsException(); - } - } else - throw new StringIndexOutOfBoundsException(); - } - - /** - * Converts this String to a byte encoding using the specified encoding. - * - * @param encoding - * the encoding - * @return the byte array encoding of this String - * - * @throws UnsupportedEncodingException - * when the encoding is not supported - * - * @see String - * @see UnsupportedEncodingException - */ - public byte[] getBytes(String encoding) throws UnsupportedEncodingException { - ByteBuffer buffer = getCharset(encoding).encode( - CharBuffer.wrap(this.value, this.offset, this.count)); - byte[] bytes = new byte[buffer.limit()]; - buffer.get(bytes); - return bytes; - } - - private Charset getCharset(final String encoding) - throws UnsupportedEncodingException { - Charset charset = lastCharset; - if (charset == null || !encoding.equalsIgnoreCase(charset.name())) { - try { - charset = Charset.forName(encoding); - } catch (IllegalCharsetNameException e) { - throw (UnsupportedEncodingException) (new UnsupportedEncodingException( - encoding).initCause(e)); - } catch (UnsupportedCharsetException e) { - throw (UnsupportedEncodingException) (new UnsupportedEncodingException( - encoding).initCause(e)); + public boolean startsWith(String prefix) { + return startsWith(prefix, 0); + } + + /** + * Compares the specified string to this String, starting at the specified + * offset, to determine if the specified string is a prefix. + * + * @param prefix + * the string to look for + * @param start + * the starting offset + * @return true when the specified string occurs in this String at the + * specified offset, false otherwise + * + * @throws NullPointerException + * when prefix is null + */ + public boolean startsWith(String prefix, int start) { + return regionMatches(start, prefix, 0, prefix.count); + } + + /** + * Copies a range of characters into a new String. + * + * @param start + * the offset of the first character + * @return a new String containing the characters from start to the end of + * the string + * + * @throws IndexOutOfBoundsException + * when start < 0 or + * start > length() + */ + public String substring(int start) { + if (start == 0) { + return this; + } + if (0 <= start && start <= count) { + return new String(offset + start, count - start, value); + } + throw new StringIndexOutOfBoundsException(start); + } + + /** + * Copies a range of characters into a new String. + * + * @param start + * the offset of the first character + * @param end + * the offset one past the last character + * @return a new String containing the characters from start to end - 1 + * + * @throws IndexOutOfBoundsException + * when start < 0, start > end or + * end > length() + */ + public String substring(int start, int end) { + if (start == 0 && end == count) { + return this; + } + // NOTE last character not copied! + // Fast range check. + if (0 <= start && start <= end && end <= count) { + return new String(offset + start, end - start, value); + } + throw new StringIndexOutOfBoundsException(); + } + + /** + * Copies the characters in this String to a character array. + * + * @return a character array containing the characters of this String + */ + public char[] toCharArray() { + char[] buffer = new char[count]; + System.arraycopy(value, offset, buffer, 0, count); + return buffer; + } + + /** + * Converts the characters in this String to lowercase, using the default + * Locale. + * + * @return a new String containing the lowercase characters equivalent to + * the characters in this String + */ + public String toLowerCase() { + return toLowerCase(Locale.getDefault()); + } + + /** + * Converts the characters in this String to lowercase, using the specified + * Locale. + * + * @param locale + * the Locale + * @return a new String containing the lowercase characters equivalent to + * the characters in this String + */ + public String toLowerCase(Locale locale) { + for (int o = offset, end = offset + count; o < end; o++) { + char ch = value[o]; + if (ch != Character.toLowerCase(ch)) { + char[] buffer = new char[count]; + int i = o - offset; + // Not worth checking for i == 0 case + System.arraycopy(value, offset, buffer, 0, i); + // Turkish + if (!"tr".equals(locale.getLanguage())) { //$NON-NLS-1$ + while (i < count) { + buffer[i++] = Character.toLowerCase(value[o++]); + } + } else { + while (i < count) { + buffer[i++] = (ch = value[o++]) != 0x49 ? Character + .toLowerCase(ch) : (char) 0x131; + } + } + return new String(0, count, buffer); } - lastCharset = charset; - } - return charset; - } - - /** - * Copies the specified characters in this String to the character array - * starting at the specified offset in the character array. - * - * @param start - * the starting offset of characters to copy - * @param end - * the ending offset of characters to copy - * @param buffer - * the destination character array - * @param index - * the starting offset in the character array - * - * @throws IndexOutOfBoundsException - * when start < 0, end > length(), - * start > end, index < 0, end - start > buffer.length - index - * @throws NullPointerException - * when buffer is null - */ - public void getChars(int start, int end, char[] buffer, int index) { - // NOTE last character not copied! - // Fast range check. - if (0 <= start && start <= end && end <= count) - System.arraycopy(value, start + offset, buffer, index, end - start); - else - throw new StringIndexOutOfBoundsException(); - } - - /** - * Answers an integer hash code for the receiver. Objects which are equal - * answer the same value for this method. - * - * @return the receiver's hash - * - * @see #equals - */ - public int hashCode() { - if (hashCode == 0) { - int hash = 0, multiplier = 1; - for (int i = offset + count - 1; i >= offset; i--) { - hash += value[i] * multiplier; - int shifted = multiplier << 5; - multiplier = shifted - multiplier; - } - hashCode = hash; - } - return hashCode; - } - - /** - * Searches in this String for the first index of the specified character. - * The search for the character starts at the beginning and moves towards - * the end of this String. - * - * @param c - * the character to find - * @return the index in this String of the specified character, -1 if the - * character isn't found - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - */ - public int indexOf(int c) { - return indexOf(c, 0); - } - - /** - * Searches in this String for the index of the specified character. The - * search for the character starts at the specified offset and moves towards - * the end of this String. - * - * @param c - * the character to find - * @param start - * the starting offset - * @return the index in this String of the specified character, -1 if the - * character isn't found - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - */ - public int indexOf(int c, int start) { - if (start < count) { - if (start < 0) - start = 0; - for (int i = offset + start; i < offset + count; i++) { - if (value[i] == c) - return i - offset; - } - } - return -1; - } - - /** - * Searches in this String for the first index of the specified string. The - * search for the string starts at the beginning and moves towards the end - * of this String. - * - * @param string - * the string to find - * @return the index in this String of the specified string, -1 if the - * string isn't found - * - * @throws NullPointerException - * when string is null - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - * - */ - public int indexOf(String string) { - return indexOf(string, 0); - } - - /** - * Searches in this String for the index of the specified string. The search - * for the string starts at the specified offset and moves towards the end - * of this String. - * - * @param subString - * the string to find - * @param start - * the starting offset - * @return the index in this String of the specified string, -1 if the - * string isn't found - * - * @throws NullPointerException - * when string is null - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - */ - public int indexOf(String subString, int start) { - if (start < 0) - start = 0; - int subCount = subString.count; - if (subCount > 0) { - if (subCount + start > count) - return -1; - char[] target = subString.value; - int subOffset = subString.offset; - char firstChar = target[subOffset]; - int end = subOffset + subCount; - while (true) { - int i = indexOf(firstChar, start); - if (i == -1 || subCount + i > count) - return -1; // handles subCount > count || start >= count - int o1 = offset + i, o2 = subOffset; - while (++o2 < end && value[++o1] == target[o2]) { - // Intentionally empty - } - if (o2 == end) { - return i; - } - start = i + 1; - } - } - return start < count ? start : count; - } - - /** - * Searches an internal table of strings for a string equal to this String. - * If the string is not in the table, it is added. Answers the string - * contained in the table which is equal to this String. The same string - * object is always answered for strings which are equal. - * - * @return the interned string equal to this String - */ - public String intern() { - return org.apache.harmony.kernel.vm.VM.intern(this); - } - - /** - * Searches in this String for the last index of the specified character. - * The search for the character starts at the end and moves towards the - * beginning of this String. - * - * @param c - * the character to find - * @return the index in this String of the specified character, -1 if the - * character isn't found - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - */ - public int lastIndexOf(int c) { - return lastIndexOf(c, count - 1); - } - - /** - * Searches in this String for the index of the specified character. The - * search for the character starts at the specified offset and moves towards - * the beginning of this String. - * - * @param c - * the character to find - * @param start - * the starting offset - * @return the index in this String of the specified character, -1 if the - * character isn't found - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - */ - public int lastIndexOf(int c, int start) { - if (start >= 0) { - if (start >= count) - start = count - 1; - for (int i = offset + start; i >= offset; --i) { - if (value[i] == c) - return i - offset; - } - } - return -1; - } - - /** - * Searches in this String for the last index of the specified string. The - * search for the string starts at the end and moves towards the beginning - * of this String. - * - * @param string - * the string to find - * @return the index in this String of the specified string, -1 if the - * string isn't found - * - * @throws NullPointerException - * when string is null - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - */ - public int lastIndexOf(String string) { - // Use count instead of count - 1 so lastIndexOf("") answers count - return lastIndexOf(string, count); - } - - /** - * Searches in this String for the index of the specified string. The search - * for the string starts at the specified offset and moves towards the - * beginning of this String. - * - * @param subString - * the string to find - * @param start - * the starting offset - * @return the index in this String of the specified string, -1 if the - * string isn't found - * - * @throws NullPointerException - * when string is null - * - * @see #lastIndexOf(int) - * @see #lastIndexOf(int, int) - * @see #lastIndexOf(String) - * @see #lastIndexOf(String, int) - */ - public int lastIndexOf(String subString, int start) { - int subCount = subString.count; - if (subCount <= count && start >= 0) { - if (subCount > 0) { - if (start > count - subCount) - start = count - subCount; // count and subCount are both - // >= 1 - char[] target = subString.value; - int subOffset = subString.offset; - char firstChar = target[subOffset]; - int end = subOffset + subCount; - while (true) { - int i = lastIndexOf(firstChar, start); - if (i == -1) - return -1; - int o1 = offset + i, o2 = subOffset; - while (++o2 < end && value[++o1] == target[o2]) { - // Intentionally empty - } - if (o2 == end) { - return i; - } - start = i - 1; - } - } - return start < count ? start : count; - } - return -1; - } - - /** - * Answers the size of this String. - * - * @return the number of characters in this String - */ - public int length() { - return count; - } - - /** - * Compares the specified string to this String and compares the specified - * range of characters to determine if they are the same. - * - * @param thisStart - * the starting offset in this String - * @param string - * the string to compare - * @param start - * the starting offset in string - * @param length - * the number of characters to compare - * @return true if the ranges of characters is equal, false otherwise - * - * @throws NullPointerException - * when string is null - */ - public boolean regionMatches(int thisStart, String string, int start, - int length) { - if (string == null) - throw new NullPointerException(); - if (start < 0 || string.count - start < length) - return false; - if (thisStart < 0 || count - thisStart < length) - return false; - if (length <= 0) - return true; - int o1 = offset + thisStart, o2 = string.offset + start; - for (int i = 0; i < length; ++i) { - if (value[o1 + i] != string.value[o2 + i]) - return false; - } - return true; - } - - /** - * Compares the specified string to this String and compares the specified - * range of characters to determine if they are the same. When ignoreCase is - * true, the case of the characters is ignored during the comparison. - * - * @param ignoreCase - * specifies if case should be ignored - * @param thisStart - * the starting offset in this String - * @param string - * the string to compare - * @param start - * the starting offset in string - * @param length - * the number of characters to compare - * @return true if the ranges of characters is equal, false otherwise - * - * @throws NullPointerException - * when string is null - */ - public boolean regionMatches(boolean ignoreCase, int thisStart, - String string, int start, int length) { - if (!ignoreCase) - return regionMatches(thisStart, string, start, length); - - if (string != null) { - if (thisStart < 0 || length > count - thisStart) - return false; - if (start < 0 || length > string.count - start) - return false; - - thisStart += offset; - start += string.offset; - int end = thisStart + length; - char c1, c2; - char[] target = string.value; - while (thisStart < end) { - if ((c1 = value[thisStart++]) != (c2 = target[start++]) - && Character.toUpperCase(c1) != Character - .toUpperCase(c2) - // Required for unicode that we test both cases - && Character.toLowerCase(c1) != Character - .toLowerCase(c2)) { - return false; - } - } - return true; - } - throw new NullPointerException(); - } - - /** - * Copies this String replacing occurrences of the specified character with - * another character. - * - * @param oldChar - * the character to replace - * @param newChar - * the replacement character - * @return a new String with occurrences of oldChar replaced by newChar - */ - public String replace(char oldChar, char newChar) { - int index = indexOf(oldChar, 0); - if (index == -1) - return this; - - char[] buffer = new char[count]; - System.arraycopy(value, offset, buffer, 0, count); - do { - buffer[index++] = newChar; - } while ((index = indexOf(oldChar, index)) != -1); - return new String(0, count, buffer); - } - - /** - * Compares the specified string to this String to determine if the - * specified string is a prefix. - * - * @param prefix - * the string to look for - * @return true when the specified string is a prefix of this String, false - * otherwise - * - * @throws NullPointerException - * when prefix is null - */ [... 1249 lines stripped ...]