You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/08/11 12:57:06 UTC

svn commit: r430756 [2/2] - /incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/lang/String.java

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<String>, 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<String>,
-			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<String> 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 <code>length < 0, start < 0</code> or
-	 *             <code>start + length > data.length</code>
-	 * @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 <code>length < 0, start < 0</code> or
-	 *             <code>start + length > data.length</code>
-	 * @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 <code>length < 0, start < 0</code> or
-	 *             <code>start + length > data.length</code>
-	 * @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 <code>length < 0, start < 0</code> or
-	 *             <code>start + length > data.length</code>
-	 * @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<String>,
+        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<String>(
+                    "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<String>, 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<String> 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 <code>length < 0, start < 0</code> or
+     *             <code>start + length > data.length</code>
+     * @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 <code>length < 0, start < 0</code> or
+     *             <code>start + length > data.length</code>
+     * @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 <code>length < 0, start < 0</code> or
+     *             <code>start + length > data.length</code>
+     * @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 <code>length < 0, start < 0</code> or
+     *             <code>start + length > data.length</code>
+     * @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();
+        }
+    }
+
+    /**
+     * <p>
+     * Constructs a <code>String</code> from the sub-array of Unicode code
+     * points.
+     * </p>
+     * 
+     * @param codePoints
+     *            The array of Unicode code points to convert.
+     * @param offset
+     *            The inclusive index into <code>codePoints</code> to begin
+     *            converting from.
+     * @param count
+     *            The number of element in <code>codePoints</code> to copy.
+     * @throws NullPointerException
+     *             if <code>codePoints</code> is null.
+     * @throws IllegalArgumentException
+     *             if any of the elements of <code>codePoints</code> are not
+     *             valid Unicode code points.
+     * @throws IndexOutOfBoundsException
+     *             if <code>offset</code> or <code>count</code> are not
+     *             within the bounds of <code>codePoints</code>.
+     * @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;
+    }
+
+    /**
+     * <p>
+     * Constructs a <code>String</code> from a <code>StringBuilder</code>.
+     * </p>
+     * 
+     * @param sb
+     *            The StringBuilder to copy from.
+     * @throws NullPointerException
+     *             if <code>sb</code> is <code>null</code>.
+     * @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 <code>index < 0</code> or
+     *             <code>index >= length()</code>
+     */
+    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 <code>length < 0, start < 0</code> or
+     *             <code>start + length > data.length</code>
+     * @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<String>(
+                            "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
+     *             <code>start < 0, end > length(), index < 0, end - start > data.length - index</code>
+     * 
+     * @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 <code>start < 0, end > length(),
+     *				start > end, index < 0, end - start > buffer.length - index</code>
+     * @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;
+    }
+
     /**
-     * <p>
-     * Constructs a <code>String</code> from the sub-array of Unicode code
-     * points.
-     * </p>
+     * 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 <code>codePoints</code> to begin
-     *        converting from.
-     * @param count The number of element in <code>codePoints</code> to copy.
-     * @throws NullPointerException if <code>codePoints</code> is null.
-     * @throws IllegalArgumentException if any of the elements of
-     *         <code>codePoints</code> are not valid Unicode code points.
-     * @throws IndexOutOfBoundsException if <code>offset</code> or
-     *         <code>count</code> are not within the bounds of
-     *         <code>codePoints</code>.
-     * @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();
     }
-    
+
     /**
-     * <p>
-     * Constructs a <code>String</code> from a <code>StringBuilder</code>.
-     * </p>
+     * Copies this String replacing occurrences of the specified character with
+     * another character.
      * 
-     * @param sb The StringBuilder to copy from.
-     * @throws NullPointerException if <code>sb</code> is <code>null</code>.
-     * @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 <code>index < 0</code> or
-	 *             <code>index >= length()</code>
-	 */
-	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 <code>length < 0, start < 0</code> or
-	 *             <code>start + length > data.length</code>
-	 * @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
-	 *             <code>start < 0, end > length(), index < 0, end - start > data.length - index</code>
-	 * 
-	 * @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 <code>start < 0</code> or
+     *             <code>start > length()</code>
+     */
+    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 <code>start < 0, start > end</code> or
+     *             <code>end > length()</code>
+     */
+    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 <code>start < 0, end > length(),
-	 *				start > end, index < 0, end - start > buffer.length - index</code>
-	 * @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 ...]