/* String.java -- immutable character sequences; the object of string literals
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.lang;

import gnu.java.lang.CharData;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * Strings represent an immutable set of characters.  All String literals
 * are instances of this class, and two string literals with the same contents
 * refer to the same String object.
 *
 * <p>This class also includes a number of methods for manipulating the
 * contents of strings (of course, creating a new object if there are any
 * changes, as String is immutable). Case mapping relies on Unicode 3.0.0
 * standards, where some character sequences have a different number of
 * characters in the uppercase version than the lower case.
 *
 * <p>Strings are special, in that they are the only object with an overloaded
 * operator. When you use '+' with at least one String argument, both
 * arguments have String conversion performed on them, and another String (not
 * guaranteed to be unique) results.
 *
 * <p>String is special-cased when doing data serialization - rather than
 * listing the fields of this class, a String object is converted to a string
 * literal in the object stream.
 *
 * @author Paul N. Fisher
 * @author Eric Blake (ebb9@email.byu.edu)
 * @author Per Bothner (bothner@cygnus.com)
 * @since 1.0
 * @status updated to 1.4; but could use better data sharing via offset field
 */
public final class String implements Serializable, Comparable, CharSequence
{
  // WARNING: String is a CORE class in the bootstrap cycle. See the comments
  // in vm/reference/java/lang/Runtime for implications of this fact.

  /**
   * This is probably not necessary because this class is special cased already
   * but it will avoid showing up as a discrepancy when comparing SUIDs.
   */
  private static final long serialVersionUID = -6849794470754667710L;

  /**
   * Stores unicode multi-character uppercase expansion table.
   * @see #toUpperCase(Locale)
   * @see CharData#UPPER_EXPAND
   */
  private static final char[] upperExpand
	= zeroBasedStringValue(CharData.UPPER_EXPAND);

  /**
   * Stores unicode multi-character uppercase special casing table.
   * @see #upperCaseExpansion(char)
   * @see CharData#UPPER_SPECIAL
   */
  private static final char[] upperSpecial
	  = zeroBasedStringValue(CharData.UPPER_SPECIAL);
  
  /**
   * Characters which make up the String.
   * Package access is granted for use by StringBuffer.
   */
  final char[] value;

  /**
   * Holds the number of characters in value.  This number is generally
   * the same as value.length, but can be smaller because substrings and
   * StringBuffers can share arrays. Package visible for use by trusted code.
   */
  final int count;

  /**
   * Caches the result of hashCode().  If this value is zero, the hashcode
   * is considered uncached (even if 0 is the correct hash value).
   */
  private int cachedHashCode;

  /**
   * Holds the starting position for characters in value[].  Since
   * substring()'s are common, the use of offset allows the operation
   * to perform in O(1). Package access is granted for use by StringBuffer.
   */
  final int offset;

  /**
   * An implementation for {@link #CASE_INSENSITIVE_ORDER}.
   * This must be {@link Serializable}. The class name is dictated by
   * compatibility with Sun's JDK.
   */
  private static final class CaseInsensitiveComparator
    implements Comparator, Serializable
  {
    /**
     * Compatible with JDK 1.2.
     */
    private static final long serialVersionUID = 8575799808933029326L;

    /**
     * The default private constructor generates unnecessary overhead.
     */
    CaseInsensitiveComparator() {}

    /**
     * Compares to Strings, using
     * <code>String.compareToIgnoreCase(String)</code>.
     *
     * @param o1 the first string
     * @param o2 the second string
     * @return &lt; 0, 0, or &gt; 0 depending on the case-insensitive
     *         comparison of the two strings.
     * @throws NullPointerException if either argument is null
     * @throws ClassCastException if either argument is not a String
     * @see #compareToIgnoreCase(String)
     */
    public int compare(Object o1, Object o2)
    {
      return ((String) o1).compareToIgnoreCase((String) o2);
    }
  } // class CaseInsensitiveComparator

  /**
   * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>.
   * This comparator is {@link Serializable}. Note that it ignores Locale,
   * for that, you want a Collator.
   *
   * @see Collator#compare(String, String)
   * @since 1.2
   */
  public static final Comparator CASE_INSENSITIVE_ORDER
    = new CaseInsensitiveComparator();

  /**
   * Creates an empty String (length 0). Unless you really need a new object,
   * consider using <code>""</code> instead.
   */
  public String()
  {
    value = "".value;
    offset = 0;
    count = 0;
  }

  /**
   * Copies the contents of a String to a new String. Since Strings are
   * immutable, only a shallow copy is performed.
   *
   * @param str String to copy
   * @throws NullPointerException if value is null
   */
  public String(String str)
  {
    value = str.value;
    offset = str.offset;
    count = str.count;
    cachedHashCode = str.cachedHashCode;
  }

  /**
   * Creates a new String using the character sequence of the char array.
   * Subsequent changes to data do not affect the String.
   *
   * @param data char array to copy
   * @throws NullPointerException if data is null
   */
  public String(char[] data)
  {
    this(data, 0, data.length, false);
  }

  /**
   * Creates a new String using the character sequence of a subarray of
   * characters. The string starts at offset, and copies count chars.
   * Subsequent changes to data do not affect the String.
   *
   * @param data char array to copy
   * @param offset position (base 0) to start copying out of data
   * @param count the number of characters from data to copy
   * @throws NullPointerException if data is null
   * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
   *         || offset + count &lt; 0 (overflow)
   *         || offset + count &gt; data.length)
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   */
  public String(char[] data, int offset, int count)
  {
    this(data, offset, count, false);
  }

  /**
   * Creates a new String using an 8-bit array of integer values, starting at
   * an offset, and copying up to the count. Each character c, using
   * corresponding byte b, is created in the new String as if by performing:
   *
   * <pre>
   * c = (char) (((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))
   * </pre>
   *
   * @param ascii array of integer values
   * @param hibyte top byte of each Unicode character
   * @param offset position (base 0) to start copying out of ascii
   * @param count the number of characters from ascii to copy
   * @throws NullPointerException if ascii is null
   * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
   *         || offset + count &lt; 0 (overflow)
   *         || offset + count &gt; ascii.length)
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   * @see #String(byte[])
   * @see #String(byte[], String)
   * @see #String(byte[], int, int)
   * @see #String(byte[], int, int, String)
   * @deprecated use {@link #String(byte[], int, int, String)} to perform
   *             correct encoding
   */
  public String(byte[] ascii, int hibyte, int offset, int count)
  {
    if (offset < 0)
      throw new StringIndexOutOfBoundsException("offset: " + offset);
    if (count < 0)
      throw new StringIndexOutOfBoundsException("count: " + count);
    // equivalent to: offset + count < 0 || offset + count > ascii.length
    if (ascii.length - offset < count)
      throw new StringIndexOutOfBoundsException("offset + count: "
						+ (offset + count));
    value = new char[count];
    this.offset = 0;
    this.count = count;
    hibyte <<= 8;
    offset += count;
    while (--count >= 0)
      value[count] = (char) (hibyte | (ascii[--offset] & 0xff));
  }

  /**
   * Creates a new String using an 8-bit array of integer values. Each
   * character c, using corresponding byte b, is created in the new String
   * as if by performing:
   *
   * <pre>
   * c = (char) (((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))
   * </pre>
   *
   * @param ascii array of integer values
   * @param hibyte top byte of each Unicode character
   * @throws NullPointerException if ascii is null
   * @see #String(byte[])
   * @see #String(byte[], String)
   * @see #String(byte[], int, int)
   * @see #String(byte[], int, int, String)
   * @see #String(byte[], int, int, int)
   * @deprecated use {@link #String(byte[], String)} to perform
   *             correct encoding
   */
  public String(byte[] ascii, int hibyte)
  {
    this(ascii, hibyte, 0, ascii.length);
  }

  /**
   * Creates a new String using the portion of the byte array starting at the
   * offset and ending at offset + count. Uses the specified encoding type
   * to decode the byte array, so the resulting string may be longer or
   * shorter than the byte array. For more decoding control, use
   * {@link java.nio.charset.CharsetDecoder}, and for valid character sets,
   * see {@link java.nio.charset.Charset}. The behavior is not specified if
   * the decoder encounters invalid characters; this implementation throws
   * an Error.
   *
   * @param data byte array to copy
   * @param offset the offset to start at
   * @param count the number of bytes in the array to use
   * @param encoding the name of the encoding to use
   * @throws NullPointerException if data or encoding is null
   * @throws IndexOutOfBoundsException if offset or count is incorrect
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   * @throws UnsupportedEncodingException if encoding is not found
   * @throws Error if the decoding fails
   * @since 1.1
   */
  public String(byte[] data, int offset, int count, String encoding)
    throws UnsupportedEncodingException
  {
    if (offset < 0)
      throw new StringIndexOutOfBoundsException("offset: " + offset);
    if (count < 0)
      throw new StringIndexOutOfBoundsException("count: " + count);
    // equivalent to: offset + count < 0 || offset + count > data.length
    if (data.length - offset < count)
      throw new StringIndexOutOfBoundsException("offset + count: "
						+ (offset + count));
    try 
      {
        CharsetDecoder csd = Charset.forName(encoding).newDecoder();
	csd.onMalformedInput(CodingErrorAction.REPLACE);
	csd.onUnmappableCharacter(CodingErrorAction.REPLACE);
	CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count));
 	if(cbuf.hasArray())
 	  {
 	    value = cbuf.array();
	    this.offset = cbuf.position();
	    this.count = cbuf.remaining();
 	  } else {
	    // Doubt this will happen. But just in case.
	    value = new char[cbuf.remaining()];
	    cbuf.get(value);
	    this.offset = 0;
	    this.count = value.length;
	  }
      } catch(CharacterCodingException e){
	  throw new UnsupportedEncodingException("Encoding: "+encoding+
						 " not found.");	  
      } catch(IllegalCharsetNameException e){
	  throw new UnsupportedEncodingException("Encoding: "+encoding+
						 " not found.");
      } catch(UnsupportedCharsetException e){
	  throw new UnsupportedEncodingException("Encoding: "+encoding+
						 " not found.");
      }    
  }

  /**
   * Creates a new String using the byte array. Uses the specified encoding
   * type to decode the byte array, so the resulting string may be longer or
   * shorter than the byte array. For more decoding control, use
   * {@link java.nio.charset.CharsetDecoder}, and for valid character sets,
   * see {@link java.nio.charset.Charset}. The behavior is not specified if
   * the decoder encounters invalid characters; this implementation throws
   * an Error.
   *
   * @param data byte array to copy
   * @param encoding the name of the encoding to use
   * @throws NullPointerException if data or encoding is null
   * @throws UnsupportedEncodingException if encoding is not found
   * @throws Error if the decoding fails
   * @see #String(byte[], int, int, String)
   * @since 1.1
   */
  public String(byte[] data, String encoding)
    throws UnsupportedEncodingException
  {
    this(data, 0, data.length, encoding);
  }

  /**
   * Creates a new String using the portion of the byte array starting at the
   * offset and ending at offset + count. Uses the encoding of the platform's
   * default charset, so the resulting string may be longer or shorter than
   * the byte array. For more decoding control, use
   * {@link java.nio.charset.CharsetDecoder}.  The behavior is not specified
   * if the decoder encounters invalid characters; this implementation throws
   * an Error.
   *
   * @param data byte array to copy
   * @param offset the offset to start at
   * @param count the number of bytes in the array to use
   * @throws NullPointerException if data is null
   * @throws IndexOutOfBoundsException if offset or count is incorrect
   * @throws Error if the decoding fails
   * @see #String(byte[], int, int, String)
   * @since 1.1
   */
  public String(byte[] data, int offset, int count)
  {
    if (offset < 0)
      throw new StringIndexOutOfBoundsException("offset: " + offset);
    if (count < 0)
      throw new StringIndexOutOfBoundsException("count: " + count);
    // equivalent to: offset + count < 0 || offset + count > data.length
    if (data.length - offset < count)
      throw new StringIndexOutOfBoundsException("offset + count: "
						+ (offset + count));
    int o, c;
    char[] v;
    String encoding;
    try 
	{
	  encoding = System.getProperty("file.encoding");
	  CharsetDecoder csd = Charset.forName(encoding).newDecoder();
	  csd.onMalformedInput(CodingErrorAction.REPLACE);
	  csd.onUnmappableCharacter(CodingErrorAction.REPLACE);
	  CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count));
	  if(cbuf.hasArray())
	    {
              v = cbuf.array();
	      o = cbuf.position();
	      c = cbuf.remaining();
	    } else {
	      // Doubt this will happen. But just in case.
	      v = new char[cbuf.remaining()];
	      cbuf.get(v);
	      o = 0;
	      c = v.length;
	    }
	} catch(Exception ex){
	    // If anything goes wrong (System property not set,
	    // NIO provider not available, etc)
	    // Default to the 'safe' encoding ISO8859_1
	    v = new char[count];
	    o = 0;
	    c = count;
	    for (int i=0;i<count;i++)
	      v[i] = (char)data[offset+i];
	}
    this.value = v;
    this.offset = o;
    this.count = c;
  }

  /**
   * Creates a new String using the byte array. Uses the encoding of the
   * platform's default charset, so the resulting string may be longer or
   * shorter than the byte array. For more decoding control, use
   * {@link java.nio.charset.CharsetDecoder}.  The behavior is not specified
   * if the decoder encounters invalid characters; this implementation throws
   * an Error.
   *
   * @param data byte array to copy
   * @throws NullPointerException if data is null
   * @throws Error if the decoding fails
   * @see #String(byte[], int, int)
   * @see #String(byte[], int, int, String)
   * @since 1.1
   */
  public String(byte[] data)
  {
    this(data, 0, data.length);
  }

  /**
   * Creates a new String using the character sequence represented by
   * the StringBuffer. Subsequent changes to buf do not affect the String.
   *
   * @param buffer StringBuffer to copy
   * @throws NullPointerException if buffer is null
   */
  public String(StringBuffer buffer)
  {
    synchronized (buffer)
      {
        offset = 0;
        count = buffer.count;
        // Share unless buffer is 3/4 empty.
        if ((count << 2) < buffer.value.length)
          {
            value = new char[count];
            VMSystem.arraycopy(buffer.value, 0, value, 0, count);
          }
        else
          {
            buffer.shared = true;
            value = buffer.value;
          }
      }
  }

  /**
   * Creates a new String using the character sequence represented by
   * the StringBuilder. Subsequent changes to buf do not affect the String.
   *
   * @param buffer StringBuilder to copy
   * @throws NullPointerException if buffer is null
   */
  public String(StringBuilder buffer)
  {
    this(buffer.value, 0, buffer.count);
  }

  /**
   * Special constructor which can share an array when safe to do so.
   *
   * @param data the characters to copy
   * @param offset the location to start from
   * @param count the number of characters to use
   * @param dont_copy true if the array is trusted, and need not be copied
   * @throws NullPointerException if chars is null
   * @throws StringIndexOutOfBoundsException if bounds check fails
   */
  String(char[] data, int offset, int count, boolean dont_copy)
  {
    if (offset < 0)
      throw new StringIndexOutOfBoundsException("offset: " + offset);
    if (count < 0)
      throw new StringIndexOutOfBoundsException("count: " + count);
    // equivalent to: offset + count < 0 || offset + count > data.length
    if (data.length - offset < count)
      throw new StringIndexOutOfBoundsException("offset + count: "
						+ (offset + count));
    if (dont_copy)
      {
        value = data;
        this.offset = offset;
      }
    else
      {
        value = new char[count];
        VMSystem.arraycopy(data, offset, value, 0, count);
        this.offset = 0;
      }
    this.count = count;
  }

  /**
   * Creates a new String containing the characters represented in the
   * given subarray of Unicode code points.
   * @param codePoints the entire array of code points
   * @param offset the start of the subarray
   * @param count the length of the subarray
   * 
   * @throws IllegalArgumentException if an invalid code point is found
   * in the codePoints array
   * @throws IndexOutOfBoundsException if offset is negative or offset + count
   * is greater than the length of the array.
   */
  public String(int[] codePoints, int offset, int count)
  {
    // FIXME: This implementation appears to give correct internal
    // representation of the String because: 
    //   - length() is correct
    //   - getting a char[] from toCharArray() and testing 
    //     Character.codePointAt() on all the characters in that array gives
    //     the appropriate results
    // however printing the String gives incorrect results.  This may be 
    // due to printing method errors (such as incorrectly looping through
    // the String one char at a time rather than one "character" at a time.
    
    if (offset < 0)
      throw new IndexOutOfBoundsException();
    int end = offset + count;
    int pos = 0;
    // This creates a char array that is long enough for all of the code
    // points to represent supplementary characters.  This is more than likely
    // a waste of storage, so we use it only temporarily and then copy the 
    // used portion into the value array.
    char[] temp = new char[2 * codePoints.length];
    for (int i = offset; i < end; i++)
      {
        pos += Character.toChars(codePoints[i], temp, pos);        
      }
    this.count = pos;
    this.value = new char[pos];
    System.arraycopy(temp, 0, value, 0, pos);
    this.offset = 0;
  }
  
  /**
   * Returns the number of characters contained in this String.
   *
   * @return the length of this String
   */
  public int length()
  {
    return count;
  }

  /**
   * Returns the character located at the specified index within this String.
   *
   * @param index position of character to return (base 0)
   * @return character located at position index
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= length()
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   */
  public char charAt(int index)
  {
    if (index < 0 || index >= count)
      throw new StringIndexOutOfBoundsException(index);
    return value[offset + index];
  }

  /**
   * Get the code point at the specified index.  This is like #charAt(int),
   * but if the character is the start of a surrogate pair, and the
   * following character completes the pair, then the corresponding
   * supplementary code point is returned.
   * @param index the index of the codepoint to get, starting at 0
   * @return the codepoint at the specified index
   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
   * @since 1.5
   */
  public synchronized int codePointAt(int index)
  {
    // Use the CharSequence overload as we get better range checking
    // this way.
    return Character.codePointAt(this, index);
  }

  /**
   * Get the code point before the specified index.  This is like
   * #codePointAt(int), but checks the characters at <code>index-1</code> and
   * <code>index-2</code> to see if they form a supplementary code point.
   * @param index the index just past the codepoint to get, starting at 0
   * @return the codepoint at the specified index
   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   * @since 1.5
   */
  public synchronized int codePointBefore(int index)
  {
    // Use the CharSequence overload as we get better range checking
    // this way.
    return Character.codePointBefore(this, index);
  }

  /**
   * Copies characters from this String starting at a specified start index,
   * ending at a specified stop index, to a character array starting at
   * a specified destination begin index.
   *
   * @param srcBegin index to begin copying characters from this String
   * @param srcEnd index after the last character to be copied from this String
   * @param dst character array which this String is copied into
   * @param dstBegin index to start writing characters into dst
   * @throws NullPointerException if dst is null
   * @throws IndexOutOfBoundsException if any indices are out of bounds
   *         (while unspecified, source problems cause a
   *         StringIndexOutOfBoundsException, and dst problems cause an
   *         ArrayIndexOutOfBoundsException)
   */
  public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
  {
    if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
      throw new StringIndexOutOfBoundsException();
    VMSystem.arraycopy(value, srcBegin + offset,
                     dst, dstBegin, srcEnd - srcBegin);
  }

  /**
   * Copies the low byte of each character from this String starting at a
   * specified start index, ending at a specified stop index, to a byte array
   * starting at a specified destination begin index.
   *
   * @param srcBegin index to being copying characters from this String
   * @param srcEnd index after the last character to be copied from this String
   * @param dst byte array which each low byte of this String is copied into
   * @param dstBegin index to start writing characters into dst
   * @throws NullPointerException if dst is null and copy length is non-zero
   * @throws IndexOutOfBoundsException if any indices are out of bounds
   *         (while unspecified, source problems cause a
   *         StringIndexOutOfBoundsException, and dst problems cause an
   *         ArrayIndexOutOfBoundsException)
   * @see #getBytes()
   * @see #getBytes(String)
   * @deprecated use {@link #getBytes()}, which uses a char to byte encoder
   */
  public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin)
  {
    if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
      throw new StringIndexOutOfBoundsException();
    int i = srcEnd - srcBegin;
    srcBegin += offset;
    while (--i >= 0)
      dst[dstBegin++] = (byte) value[srcBegin++];
  }

  /**
   * Converts the Unicode characters in this String to a byte array. Uses the
   * specified encoding method, so the result may be longer or shorter than
   * the String. For more encoding control, use
   * {@link java.nio.charset.CharsetEncoder}, and for valid character sets,
   * see {@link java.nio.charset.Charset}. Unsupported characters get
   * replaced by an encoding specific byte.
   *
   * @param enc encoding name
   * @return the resulting byte array
   * @throws NullPointerException if enc is null
   * @throws UnsupportedEncodingException if encoding is not supported
   * @since 1.1
   */
  public byte[] getBytes(String enc) throws UnsupportedEncodingException
  {
    try 
      {
	CharsetEncoder cse = Charset.forName(enc).newEncoder();
	cse.onMalformedInput(CodingErrorAction.REPLACE);
	cse.onUnmappableCharacter(CodingErrorAction.REPLACE);
	ByteBuffer bbuf = cse.encode(CharBuffer.wrap(value, offset, count));
	if(bbuf.hasArray())
	  return bbuf.array();
	
	// Doubt this will happen. But just in case.
	byte[] bytes = new byte[bbuf.remaining()];
	bbuf.get(bytes);
	return bytes;
      } 
    catch(IllegalCharsetNameException e)
      {
	throw new UnsupportedEncodingException("Encoding: " + enc
					       + " not found.");
      } 
    catch(UnsupportedCharsetException e)
      {
	throw new UnsupportedEncodingException("Encoding: " + enc
					       + " not found.");
      } 
    catch(CharacterCodingException e)
      {
	// This shouldn't ever happen.
	throw (InternalError) new InternalError().initCause(e);
      }	  
  }

  /**
   * Converts the Unicode characters in this String to a byte array. Uses the
   * encoding of the platform's default charset, so the result may be longer
   * or shorter than the String. For more encoding control, use
   * {@link java.nio.charset.CharsetEncoder}. Unsupported characters get
   * replaced by an encoding specific byte.
   *
   * @return the resulting byte array, or null on a problem
   * @since 1.1
   */
  public byte[] getBytes()
  { 
      try 
	  {
	      return getBytes(System.getProperty("file.encoding"));
	  } catch(Exception e) {
	      // XXX - Throw an error here? 
	      // For now, default to the 'safe' encoding.
	      byte[] bytes = new byte[count];
	      for(int i=0;i<count;i++)
		  bytes[i] = (byte)((value[offset+i] <= 0xFF)?
				    value[offset+i]:'?');
	      return bytes;
      }
  }

  /**
   * Predicate which compares anObject to this. This is true only for Strings
   * with the same character sequence.
   *
   * @param anObject the object to compare
   * @return true if anObject is semantically equal to this
   * @see #compareTo(String)
   * @see #equalsIgnoreCase(String)
   */
  public boolean equals(Object anObject)
  {
    if (! (anObject instanceof String))
      return false;
    String str2 = (String) anObject;
    if (count != str2.count)
      return false;
    if (value == str2.value && offset == str2.offset)
      return true;
    int i = count;
    int x = offset;
    int y = str2.offset;
    while (--i >= 0)
      if (value[x++] != str2.value[y++])
        return false;
    return true;
  }

  /**
   * Compares the given StringBuffer to this String. This is true if the
   * StringBuffer has the same content as this String at this moment.
   *
   * @param buffer the StringBuffer to compare to
   * @return true if StringBuffer has the same character sequence
   * @throws NullPointerException if the given StringBuffer is null
   * @since 1.4
   */
  public boolean contentEquals(StringBuffer buffer)
  {
    synchronized (buffer)
      {
        if (count != buffer.count)
          return false;
        if (value == buffer.value)
          return true; // Possible if shared.
        int i = count;
        int x = offset + count;
        while (--i >= 0)
          if (value[--x] != buffer.value[i])
            return false;
        return true;
      }
  }

  /**
   * Compares the given CharSequence to this String. This is true if
   * the CharSequence has the same content as this String at this
   * moment.
   *
   * @param seq the CharSequence to compare to
   * @return true if CharSequence has the same character sequence
   * @throws NullPointerException if the given CharSequence is null
   * @since 1.5
   */
  public boolean contentEquals(CharSequence seq)
  {
    if (seq.length() != count)
      return false;
    for (int i = 0; i < count; ++i)
      if (value[offset + i] != seq.charAt(i))
	return false;
    return true;
  }

  /**
   * Compares a String to this String, ignoring case. This does not handle
   * multi-character capitalization exceptions; instead the comparison is
   * made on a character-by-character basis, and is true if:<br><ul>
   * <li><code>c1 == c2</code></li>
   * <li><code>Character.toUpperCase(c1)
   *     == Character.toUpperCase(c2)</code></li>
   * <li><code>Character.toLowerCase(c1)
   *     == Character.toLowerCase(c2)</code></li>
   * </ul>
   *
   * @param anotherString String to compare to this String
   * @return true if anotherString is equal, ignoring case
   * @see #equals(Object)
   * @see Character#toUpperCase(char)
   * @see Character#toLowerCase(char)
   */
  public boolean equalsIgnoreCase(String anotherString)
  {
    if (anotherString == null || count != anotherString.count)
      return false;
    int i = count;
    int x = offset;
    int y = anotherString.offset;
    while (--i >= 0)
      {
        char c1 = value[x++];
        char c2 = anotherString.value[y++];
        // Note that checking c1 != c2 is redundant, but avoids method calls.
        if (c1 != c2
            && Character.toUpperCase(c1) != Character.toUpperCase(c2)
            && Character.toLowerCase(c1) != Character.toLowerCase(c2))
          return false;
      }
    return true;
  }

  /**
   * Compares this String and another String (case sensitive,
   * lexicographically). The result is less than 0 if this string sorts
   * before the other, 0 if they are equal, and greater than 0 otherwise.
   * After any common starting sequence is skipped, the result is
   * <code>this.charAt(k) - anotherString.charAt(k)</code> if both strings
   * have characters remaining, or
   * <code>this.length() - anotherString.length()</code> if one string is
   * a subsequence of the other.
   *
   * @param anotherString the String to compare against
   * @return the comparison
   * @throws NullPointerException if anotherString is null
   */
  public int compareTo(String anotherString)
  {
    int i = Math.min(count, anotherString.count);
    int x = offset;
    int y = anotherString.offset;
    while (--i >= 0)
      {
        int result = value[x++] - anotherString.value[y++];
        if (result != 0)
          return result;
      }
    return count - anotherString.count;
  }

  /**
   * Behaves like <code>compareTo(java.lang.String)</code> unless the Object
   * is not a <code>String</code>.  Then it throws a
   * <code>ClassCastException</code>.
   *
   * @param o the object to compare against
   * @return the comparison
   * @throws NullPointerException if o is null
   * @throws ClassCastException if o is not a <code>String</code>
   * @since 1.2
   */
  public int compareTo(Object o)
  {
    return compareTo((String) o);
  }

  /**
   * Compares this String and another String (case insensitive). This
   * comparison is <em>similar</em> to equalsIgnoreCase, in that it ignores
   * locale and multi-characater capitalization, and compares characters
   * after performing
   * <code>Character.toLowerCase(Character.toUpperCase(c))</code> on each
   * character of the string. This is unsatisfactory for locale-based
   * comparison, in which case you should use {@link java.text.Collator}.
   *
   * @param str the string to compare against
   * @return the comparison
   * @see Collator#compare(String, String)
   * @since 1.2
   */
  public int compareToIgnoreCase(String str)
  {
    int i = Math.min(count, str.count);
    int x = offset;
    int y = str.offset;
    while (--i >= 0)
      {
        int result = Character.toLowerCase(Character.toUpperCase(value[x++]))
          - Character.toLowerCase(Character.toUpperCase(str.value[y++]));
        if (result != 0)
          return result;
      }
    return count - str.count;
  }  

  /**
   * Predicate which determines if this String matches another String
   * starting at a specified offset for each String and continuing
   * for a specified length. Indices out of bounds are harmless, and give
   * a false result.
   *
   * @param toffset index to start comparison at for this String
   * @param other String to compare region to this String
   * @param ooffset index to start comparison at for other
   * @param len number of characters to compare
   * @return true if regions match (case sensitive)
   * @throws NullPointerException if other is null
   */
  public boolean regionMatches(int toffset, String other, int ooffset, int len)
  {
    return regionMatches(false, toffset, other, ooffset, len);
  }

  /**
   * Predicate which determines if this String matches another String
   * starting at a specified offset for each String and continuing
   * for a specified length, optionally ignoring case. Indices out of bounds
   * are harmless, and give a false result. Case comparisons are based on
   * <code>Character.toLowerCase()</code> and
   * <code>Character.toUpperCase()</code>, not on multi-character
   * capitalization expansions.
   *
   * @param ignoreCase true if case should be ignored in comparision
   * @param toffset index to start comparison at for this String
   * @param other String to compare region to this String
   * @param ooffset index to start comparison at for other
   * @param len number of characters to compare
   * @return true if regions match, false otherwise
   * @throws NullPointerException if other is null
   */
  public boolean regionMatches(boolean ignoreCase, int toffset,
                               String other, int ooffset, int len)
  {
    if (toffset < 0 || ooffset < 0 || toffset + len > count
        || ooffset + len > other.count)
      return false;
    toffset += offset;
    ooffset += other.offset;
    while (--len >= 0)
      {
        char c1 = value[toffset++];
        char c2 = other.value[ooffset++];
        // Note that checking c1 != c2 is redundant when ignoreCase is true,
        // but it avoids method calls.
        if (c1 != c2
            && (! ignoreCase
                || (Character.toLowerCase(c1) != Character.toLowerCase(c2)
                    && (Character.toUpperCase(c1)
                        != Character.toUpperCase(c2)))))
          return false;
      }
    return true;
  }

  /**
   * Predicate which determines if this String contains the given prefix,
   * beginning comparison at toffset. The result is false if toffset is
   * negative or greater than this.length(), otherwise it is the same as
   * <code>this.substring(toffset).startsWith(prefix)</code>.
   *
   * @param prefix String to compare
   * @param toffset offset for this String where comparison starts
   * @return true if this String starts with prefix
   * @throws NullPointerException if prefix is null
   * @see #regionMatches(boolean, int, String, int, int)
   */
  public boolean startsWith(String prefix, int toffset)
  {
    return regionMatches(false, toffset, prefix, 0, prefix.count);
  }

  /**
   * Predicate which determines if this String starts with a given prefix.
   * If the prefix is an empty String, true is returned.
   *
   * @param prefix String to compare
   * @return true if this String starts with the prefix
   * @throws NullPointerException if prefix is null
   * @see #startsWith(String, int)
   */
  public boolean startsWith(String prefix)
  {
    return regionMatches(false, 0, prefix, 0, prefix.count);
  }

  /**
   * Predicate which determines if this String ends with a given suffix.
   * If the suffix is an empty String, true is returned.
   *
   * @param suffix String to compare
   * @return true if this String ends with the suffix
   * @throws NullPointerException if suffix is null
   * @see #regionMatches(boolean, int, String, int, int)
   */
  public boolean endsWith(String suffix)
  {
    return regionMatches(false, count - suffix.count, suffix, 0, suffix.count);
  }

  /**
   * Computes the hashcode for this String. This is done with int arithmetic,
   * where ** represents exponentiation, by this formula:<br>
   * <code>s[0]*31**(n-1) + s[1]*31**(n-2) + ... + s[n-1]</code>.
   *
   * @return hashcode value of this String
   */
  public int hashCode()
  {
    if (cachedHashCode != 0)
      return cachedHashCode;

    // Compute the hash code using a local variable to be reentrant.
    int hashCode = 0;
    int limit = count + offset;
    for (int i = offset; i < limit; i++)
      hashCode = hashCode * 31 + value[i];
    return cachedHashCode = hashCode;
  }

  /**
   * Finds the first instance of a character in this String.
   *
   * @param ch character to find
   * @return location (base 0) of the character, or -1 if not found
   */
  public int indexOf(int ch)
  {
    return indexOf(ch, 0);
  }

  /**
   * Finds the first instance of a character in this String, starting at
   * a given index.  If starting index is less than 0, the search
   * starts at the beginning of this String.  If the starting index
   * is greater than the length of this String, -1 is returned.
   *
   * @param ch character to find
   * @param fromIndex index to start the search
   * @return location (base 0) of the character, or -1 if not found
   */
  public int indexOf(int ch, int fromIndex)
  {
    if ((char) ch != ch)
      return -1;
    if (fromIndex < 0)
      fromIndex = 0;
    int i = fromIndex + offset;
    for ( ; fromIndex < count; fromIndex++)
      if (value[i++] == ch)
        return fromIndex;
    return -1;
  }

  /**
   * Finds the last instance of a character in this String.
   *
   * @param ch character to find
   * @return location (base 0) of the character, or -1 if not found
   */
  public int lastIndexOf(int ch)
  {
    return lastIndexOf(ch, count - 1);
  }

  /**
   * Finds the last instance of a character in this String, starting at
   * a given index.  If starting index is greater than the maximum valid
   * index, then the search begins at the end of this String.  If the
   * starting index is less than zero, -1 is returned.
   *
   * @param ch character to find
   * @param fromIndex index to start the search
   * @return location (base 0) of the character, or -1 if not found
   */
  public int lastIndexOf(int ch, int fromIndex)
  {
    if ((char) ch != ch)
      return -1;
    if (fromIndex >= count)
      fromIndex = count - 1;
    int i = fromIndex + offset;
    for ( ; fromIndex >= 0; fromIndex--)
      if (value[i--] == ch)
        return fromIndex;
    return -1;
  }

  /**
   * Finds the first instance of a String in this String.
   *
   * @param str String to find
   * @return location (base 0) of the String, or -1 if not found
   * @throws NullPointerException if str is null
   */
  public int indexOf(String str)
  {
    return indexOf(str, 0);
  }

  /**
   * Finds the first instance of a String in this String, starting at
   * a given index.  If starting index is less than 0, the search
   * starts at the beginning of this String.  If the starting index
   * is greater than the length of this String, -1 is returned.
   *
   * @param str String to find
   * @param fromIndex index to start the search
   * @return location (base 0) of the String, or -1 if not found
   * @throws NullPointerException if str is null
   */
  public int indexOf(String str, int fromIndex)
  {
    if (fromIndex < 0)
      fromIndex = 0;
    int limit = count - str.count;
    for ( ; fromIndex <= limit; fromIndex++)
      if (regionMatches(fromIndex, str, 0, str.count))
        return fromIndex;
    return -1;
  }

  /**
   * Finds the last instance of a String in this String.
   *
   * @param str String to find
   * @return location (base 0) of the String, or -1 if not found
   * @throws NullPointerException if str is null
   */
  public int lastIndexOf(String str)
  {
    return lastIndexOf(str, count - str.count);
  }

  /**
   * Finds the last instance of a String in this String, starting at
   * a given index.  If starting index is greater than the maximum valid
   * index, then the search begins at the end of this String.  If the
   * starting index is less than zero, -1 is returned.
   *
   * @param str String to find
   * @param fromIndex index to start the search
   * @return location (base 0) of the String, or -1 if not found
   * @throws NullPointerException if str is null
   */
  public int lastIndexOf(String str, int fromIndex)
  {
    fromIndex = Math.min(fromIndex, count - str.count);
    for ( ; fromIndex >= 0; fromIndex--)
      if (regionMatches(fromIndex, str, 0, str.count))
        return fromIndex;
    return -1;
  }

  /**
   * Creates a substring of this String, starting at a specified index
   * and ending at the end of this String.
   *
   * @param begin index to start substring (base 0)
   * @return new String which is a substring of this String
   * @throws IndexOutOfBoundsException if begin &lt; 0 || begin &gt; length()
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   */
  public String substring(int begin)
  {
    return substring(begin, count);
  }

  /**
   * Creates a substring of this String, starting at a specified index
   * and ending at one character before a specified index.
   *
   * @param beginIndex index to start substring (inclusive, base 0)
   * @param endIndex index to end at (exclusive)
   * @return new String which is a substring of this String
   * @throws IndexOutOfBoundsException if begin &lt; 0 || end &gt; length()
   *         || begin &gt; end (while unspecified, this is a
   *         StringIndexOutOfBoundsException)
   */
  public String substring(int beginIndex, int endIndex)
  {
    if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
      throw new StringIndexOutOfBoundsException();
    if (beginIndex == 0 && endIndex == count)
      return this;
    int len = endIndex - beginIndex;
    // Package constructor avoids an array copy.
    return new String(value, beginIndex + offset, len,
                      (len << 2) >= value.length);
  }

  /**
   * Creates a substring of this String, starting at a specified index
   * and ending at one character before a specified index. This behaves like
   * <code>substring(begin, end)</code>.
   *
   * @param begin index to start substring (inclusive, base 0)
   * @param end index to end at (exclusive)
   * @return new String which is a substring of this String
   * @throws IndexOutOfBoundsException if begin &lt; 0 || end &gt; length()
   *         || begin &gt; end
   * @since 1.4
   */
  public CharSequence subSequence(int begin, int end)
  {
    return substring(begin, end);
  }

  /**
   * Concatenates a String to this String. This results in a new string unless
   * one of the two originals is "".
   *
   * @param str String to append to this String
   * @return newly concatenated String
   * @throws NullPointerException if str is null
   */
  public String concat(String str)
  {
    if (str.count == 0)
      return this;
    if (count == 0)
      return str;
    char[] newStr = new char[count + str.count];
    VMSystem.arraycopy(value, offset, newStr, 0, count);
    VMSystem.arraycopy(str.value, str.offset, newStr, count, str.count);
    // Package constructor avoids an array copy.
    return new String(newStr, 0, newStr.length, true);
  }

  /**
   * Replaces every instance of a character in this String with a new
   * character. If no replacements occur, this is returned.
   *
   * @param oldChar the old character to replace
   * @param newChar the new character
   * @return new String with all instances of oldChar replaced with newChar
   */
  public String replace(char oldChar, char newChar)
  {
    if (oldChar == newChar)
      return this;
    int i = count;
    int x = offset - 1;
    while (--i >= 0)
      if (value[++x] == oldChar)
        break;
    if (i < 0)
      return this;
    char[] newStr = (char[]) value.clone();
    newStr[x] = newChar;
    while (--i >= 0)
      if (value[++x] == oldChar)
        newStr[x] = newChar;
    // Package constructor avoids an array copy.
    return new String(newStr, offset, count, true);
  }

  /**
   * Test if this String matches a regular expression. This is shorthand for
   * <code>{@link Pattern}.matches(regex, this)</code>.
   *
   * @param regex the pattern to match
   * @return true if the pattern matches
   * @throws NullPointerException if regex is null
   * @throws PatternSyntaxException if regex is invalid
   * @see Pattern#matches(String, CharSequence)
   * @since 1.4
   */
  public boolean matches(String regex)
  {
    return Pattern.matches(regex, this);
  }

  /**
   * Replaces the first substring match of the regular expression with a
   * given replacement. This is shorthand for <code>{@link Pattern}
   *   .compile(regex).matcher(this).replaceFirst(replacement)</code>.
   *
   * @param regex the pattern to match
   * @param replacement the replacement string
   * @return the modified string
   * @throws NullPointerException if regex or replacement is null
   * @throws PatternSyntaxException if regex is invalid
   * @see #replaceAll(String, String)
   * @see Pattern#compile(String)
   * @see Pattern#matcher(CharSequence)
   * @see Matcher#replaceFirst(String)
   * @since 1.4
   */
  public String replaceFirst(String regex, String replacement)
  {
    return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
  }

  /**
   * Replaces all matching substrings of the regular expression with a
   * given replacement. This is shorthand for <code>{@link Pattern}
   *   .compile(regex).matcher(this).replaceAll(replacement)</code>.
   *
   * @param regex the pattern to match
   * @param replacement the replacement string
   * @return the modified string
   * @throws NullPointerException if regex or replacement is null
   * @throws PatternSyntaxException if regex is invalid
   * @see #replaceFirst(String, String)
   * @see Pattern#compile(String)
   * @see Pattern#matcher(CharSequence)
   * @see Matcher#replaceAll(String)
   * @since 1.4
   */
  public String replaceAll(String regex, String replacement)
  {
    return Pattern.compile(regex).matcher(this).replaceAll(replacement);
  }

  /**
   * Split this string around the matches of a regular expression. Each
   * element of the returned array is the largest block of characters not
   * terminated by the regular expression, in the order the matches are found.
   *
   * <p>The limit affects the length of the array. If it is positive, the
   * array will contain at most n elements (n - 1 pattern matches). If
   * negative, the array length is unlimited, but there can be trailing empty
   * entries. if 0, the array length is unlimited, and trailing empty entries
   * are discarded.
   *
   * <p>For example, splitting "boo:and:foo" yields:<br>
   * <table border=0>
   * <th><td>Regex</td> <td>Limit</td> <td>Result</td></th>
   * <tr><td>":"</td>   <td>2</td>  <td>{ "boo", "and:foo" }</td></tr>
   * <tr><td>":"</td>   <td>t</td>  <td>{ "boo", "and", "foo" }</td></tr>
   * <tr><td>":"</td>   <td>-2</td> <td>{ "boo", "and", "foo" }</td></tr>
   * <tr><td>"o"</td>   <td>5</td>  <td>{ "b", "", ":and:f", "", "" }</td></tr>
   * <tr><td>"o"</td>   <td>-2</td> <td>{ "b", "", ":and:f", "", "" }</td></tr>
   * <tr><td>"o"</td>   <td>0</td>  <td>{ "b", "", ":and:f" }</td></tr>
   * </table>
   *
   * <p>This is shorthand for
   * <code>{@link Pattern}.compile(regex).split(this, limit)</code>.
   *
   * @param regex the pattern to match
   * @param limit the limit threshold
   * @return the array of split strings
   * @throws NullPointerException if regex or replacement is null
   * @throws PatternSyntaxException if regex is invalid
   * @see Pattern#compile(String)
   * @see Pattern#split(CharSequence, int)
   * @since 1.4
   */
  public String[] split(String regex, int limit)
  {
    return Pattern.compile(regex).split(this, limit);
  }

  /**
   * Split this string around the matches of a regular expression. Each
   * element of the returned array is the largest block of characters not
   * terminated by the regular expression, in the order the matches are found.
   * The array length is unlimited, and trailing empty entries are discarded,
   * as though calling <code>split(regex, 0)</code>.
   *
   * @param regex the pattern to match
   * @return the array of split strings
   * @throws NullPointerException if regex or replacement is null
   * @throws PatternSyntaxException if regex is invalid
   * @see #split(String, int)
   * @see Pattern#compile(String)
   * @see Pattern#split(CharSequence, int)
   * @since 1.4
   */
  public String[] split(String regex)
  {
    return Pattern.compile(regex).split(this, 0);
  }

  /**
   * Lowercases this String according to a particular locale. This uses
   * Unicode's special case mappings, as applied to the given Locale, so the
   * resulting string may be a different length.
   *
   * @param loc locale to use
   * @return new lowercased String, or this if no characters were lowercased
   * @throws NullPointerException if loc is null
   * @see #toUpperCase(Locale)
   * @since 1.1
   */
  public String toLowerCase(Locale loc)
  {
    // First, see if the current string is already lower case.
    boolean turkish = "tr".equals(loc.getLanguage());
    int i = count;
    int x = offset - 1;
    while (--i >= 0)
      {
        char ch = value[++x];
        if ((turkish && ch == '\u0049')
            || ch != Character.toLowerCase(ch))
          break;
      }
    if (i < 0)
      return this;

    // Now we perform the conversion. Fortunately, there are no multi-character
    // lowercase expansions in Unicode 3.0.0.
    char[] newStr = (char[]) value.clone();
    do
      {
        char ch = value[x];
        // Hardcoded special case.
        newStr[x++] = (turkish && ch == '\u0049') ? '\u0131'
          : Character.toLowerCase(ch);
      }
    while (--i >= 0);
    // Package constructor avoids an array copy.
    return new String(newStr, offset, count, true);
  }

  /**
   * Lowercases this String. This uses Unicode's special case mappings, as
   * applied to the platform's default Locale, so the resulting string may
   * be a different length.
   *
   * @return new lowercased String, or this if no characters were lowercased
   * @see #toLowerCase(Locale)
   * @see #toUpperCase()
   */
  public String toLowerCase()
  {
    return toLowerCase(Locale.getDefault());
  }

  /**
   * Uppercases this String according to a particular locale. This uses
   * Unicode's special case mappings, as applied to the given Locale, so the
   * resulting string may be a different length.
   *
   * @param loc locale to use
   * @return new uppercased String, or this if no characters were uppercased
   * @throws NullPointerException if loc is null
   * @see #toLowerCase(Locale)
   * @since 1.1
   */
  public String toUpperCase(Locale loc)
  {
    // First, see how many characters we have to grow by, as well as if the
    // current string is already upper case.
    boolean turkish = "tr".equals(loc.getLanguage());
    int expand = 0;
    boolean unchanged = true;
    int i = count;
    int x = i + offset;
    while (--i >= 0)
      {
        char ch = value[--x];
        expand += upperCaseExpansion(ch);
        unchanged = (unchanged && expand == 0
                     && ! (turkish && ch == '\u0069')
                     && ch == Character.toUpperCase(ch));
      }
    if (unchanged)
      return this;

    // Now we perform the conversion.
    i = count;
    if (expand == 0)
      {
        char[] newStr = (char[]) value.clone();
        while (--i >= 0)
          {
            char ch = value[x];
            // Hardcoded special case.
            newStr[x++] = (turkish && ch == '\u0069') ? '\u0130'
              : Character.toUpperCase(ch);
          }
        // Package constructor avoids an array copy.
        return new String(newStr, offset, count, true);
      }

    // Expansion is necessary.
    char[] newStr = new char[count + expand];
    int j = 0;
    while (--i >= 0)
      {
        char ch = value[x++];
        // Hardcoded special case.
        if (turkish && ch == '\u0069')
          {
            newStr[j++] = '\u0130';
            continue;
          }
        expand = upperCaseExpansion(ch);
        if (expand > 0)
          {
            int index = upperCaseIndex(ch);
            while (expand-- >= 0)
              newStr[j++] = upperExpand[index++];
          }
        else
          newStr[j++] = Character.toUpperCase(ch);
      }
    // Package constructor avoids an array copy.
    return new String(newStr, 0, newStr.length, true);
  }

  /**
   * Uppercases this String. This uses Unicode's special case mappings, as
   * applied to the platform's default Locale, so the resulting string may
   * be a different length.
   *
   * @return new uppercased String, or this if no characters were uppercased
   * @see #toUpperCase(Locale)
   * @see #toLowerCase()
   */
  public String toUpperCase()
  {
    return toUpperCase(Locale.getDefault());
  }

  /**
   * Trims all characters less than or equal to <code>'\u0020'</code>
   * (<code>' '</code>) from the beginning and end of this String. This
   * includes many, but not all, ASCII control characters, and all
   * {@link Character#isWhitespace(char)}.
   *
   * @return new trimmed String, or this if nothing trimmed
   */
  public String trim()
  {
    int limit = count + offset;
    if (count == 0 || (value[offset] > '\u0020'
                       && value[limit - 1] > '\u0020'))
      return this;
    int begin = offset;
    do
      if (begin == limit)
        return "";
    while (value[begin++] <= '\u0020');
    int end = limit;
    while (value[--end] <= '\u0020');
    return substring(begin - offset - 1, end - offset + 1);
  }

  /**
   * Returns this, as it is already a String!
   *
   * @return this
   */
  public String toString()
  {
    return this;
  }

  /**
   * Copies the contents of this String into a character array. Subsequent
   * changes to the array do not affect the String.
   *
   * @return character array copying the String
   */
  public char[] toCharArray()
  {
    if (count == value.length)
      return (char[]) value.clone();

    char[] copy = new char[count];
    VMSystem.arraycopy(value, offset, copy, 0, count);
    return copy;
  }

  /**
   * Returns a String representation of an Object. This is "null" if the
   * object is null, otherwise it is <code>obj.toString()</code> (which
   * can be null).
   *
   * @param obj the Object
   * @return the string conversion of obj
   */
  public static String valueOf(Object obj)
  {
    return obj == null ? "null" : obj.toString();
  }

  /**
   * Returns a String representation of a character array. Subsequent
   * changes to the array do not affect the String.
   *
   * @param data the character array
   * @return a String containing the same character sequence as data
   * @throws NullPointerException if data is null
   * @see #valueOf(char[], int, int)
   * @see #String(char[])
   */
  public static String valueOf(char[] data)
  {
    return valueOf (data, 0, data.length);
  }

  /**
   * Returns a String representing the character sequence of the char array,
   * starting at the specified offset, and copying chars up to the specified
   * count. Subsequent changes to the array do not affect the String.
   *
   * @param data character array
   * @param offset position (base 0) to start copying out of data
   * @param count the number of characters from data to copy
   * @return String containing the chars from data[offset..offset+count]
   * @throws NullPointerException if data is null
   * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
   *         || offset + count &lt; 0 (overflow)
   *         || offset + count &gt; data.length)
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   * @see #String(char[], int, int)
   */
  public static String valueOf(char[] data, int offset, int count)
  {
    return new String(data, offset, count, false);
  }

  /**
   * Returns a String representing the character sequence of the char array,
   * starting at the specified offset, and copying chars up to the specified
   * count. Subsequent changes to the array do not affect the String.
   *
   * @param data character array
   * @param offset position (base 0) to start copying out of data
   * @param count the number of characters from data to copy
   * @return String containing the chars from data[offset..offset+count]
   * @throws NullPointerException if data is null
   * @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
   *         || offset + count &lt; 0 (overflow)
   *         || offset + count &gt; data.length)
   *         (while unspecified, this is a StringIndexOutOfBoundsException)
   * @see #String(char[], int, int)
   */
  public static String copyValueOf(char[] data, int offset, int count)
  {
    return new String(data, offset, count, false);
  }

  /**
   * Returns a String representation of a character array. Subsequent
   * changes to the array do not affect the String.
   *
   * @param data the character array
   * @return a String containing the same character sequence as data
   * @throws NullPointerException if data is null
   * @see #copyValueOf(char[], int, int)
   * @see #String(char[])
   */
  public static String copyValueOf(char[] data)
  {
    return copyValueOf (data, 0, data.length);
  }

  /**
   * Returns a String representing a boolean.
   *
   * @param b the boolean
   * @return "true" if b is true, else "false"
   */
  public static String valueOf(boolean b)
  {
    return b ? "true" : "false";
  }

  /**
   * Returns a String representing a character.
   *
   * @param c the character
   * @return String containing the single character c
   */
  public static String valueOf(char c)
  {
    // Package constructor avoids an array copy.
    return new String(new char[] { c }, 0, 1, true);
  }

  /**
   * Returns a String representing an integer.
   *
   * @param i the integer
   * @return String containing the integer in base 10
   * @see Integer#toString(int)
   */
  public static String valueOf(int i)
  {
    // See Integer to understand why we call the two-arg variant.
    return Integer.toString(i, 10);
  }

  /**
   * Returns a String representing a long.
   *
   * @param l the long
   * @return String containing the long in base 10
   * @see Long#toString(long)
   */
  public static String valueOf(long l)
  {
    return Long.toString(l);
  }

  /**
   * Returns a String representing a float.
   *
   * @param f the float
   * @return String containing the float
   * @see Float#toString(float)
   */
  public static String valueOf(float f)
  {
    return Float.toString(f);
  }

  /**
   * Returns a String representing a double.
   *
   * @param d the double
   * @return String containing the double
   * @see Double#toString(double)
   */
  public static String valueOf(double d)
  {
    return Double.toString(d);
  }

  /**
   * If two Strings are considered equal, by the equals() method, 
   * then intern() will return the same String instance. ie. 
   * if (s1.equals(s2)) then (s1.intern() == s2.intern()). 
   * All string literals and string-valued constant expressions 
   * are already interned.
   *
   * @return the interned String
   */
  public String intern()
  {
    return VMString.intern(this);
  }

  /**
   * Return the number of code points between two indices in the
   * <code>String</code>.  An unpaired surrogate counts as a
   * code point for this purpose.  Characters outside the indicated
   * range are not examined, even if the range ends in the middle of a
   * surrogate pair.
   *
   * @param start the starting index
   * @param end one past the ending index
   * @return the number of code points
   * @since 1.5
   */
  public synchronized int codePointCount(int start, int end)
  {
    if (start < 0 || end > count || start > end)
      throw new StringIndexOutOfBoundsException();

    start += offset;
    end += offset;
    int count = 0;
    while (start < end)
      {
	char base = value[start];
	if (base < Character.MIN_HIGH_SURROGATE
	    || base > Character.MAX_HIGH_SURROGATE
	    || start == end
	    || start == count
	    || value[start + 1] < Character.MIN_LOW_SURROGATE
	    || value[start + 1] > Character.MAX_LOW_SURROGATE)
	  {
	    // Nothing.
	  }
	else
	  {
	    // Surrogate pair.
	    ++start;
	  }
	++start;
	++count;
      }
    return count;
  }

  /**
   * Helper function used to detect which characters have a multi-character
   * uppercase expansion. Note that this is only used in locations which
   * track one-to-many capitalization (java.lang.Character does not do this).
   * As of Unicode 3.0.0, the result is limited in the range 0 to 2, as the
   * longest uppercase expansion is three characters (a growth of 2 from the
   * lowercase character).
   *
   * @param ch the char to check
   * @return the number of characters to add when converting to uppercase
   * @see CharData#DIRECTION
   * @see CharData#UPPER_SPECIAL
   * @see #toUpperCase(Locale)
   */
  private static int upperCaseExpansion(char ch)
  {
    return Character.direction[0][Character.readCodePoint((int)ch) >> 7] & 3;
  }

  /**
   * Helper function used to locate the offset in upperExpand given a
   * character with a multi-character expansion. The binary search is
   * optimized under the assumption that this method will only be called on
   * characters which exist in upperSpecial.
   *
   * @param ch the char to check
   * @return the index where its expansion begins
   * @see CharData#UPPER_SPECIAL
   * @see CharData#UPPER_EXPAND
   * @see #toUpperCase(Locale)
   */
  private static int upperCaseIndex(char ch)
  {
    // Simple binary search for the correct character.
    int low = 0;
    int hi = upperSpecial.length - 2;
    int mid = ((low + hi) >> 2) << 1;
    char c = upperSpecial[mid];
    while (ch != c)
      {
        if (ch < c)
          hi = mid - 2;
        else
          low = mid + 2;
        mid = ((low + hi) >> 2) << 1;
        c = upperSpecial[mid];
      }
    return upperSpecial[mid + 1];
  }

  /**
   * Returns the value array of the given string if it is zero based or a
   * copy of it that is zero based (stripping offset and making length equal
   * to count). Used for accessing the char[]s of gnu.java.lang.CharData.
   * Package private for use in Character.
   */
  static char[] zeroBasedStringValue(String s)
  {
    char[] value;

    if (s.offset == 0 && s.count == s.value.length)
      value = s.value;
    else
      {
	int count = s.count;
	value = new char[count];
	VMSystem.arraycopy(s.value, s.offset, value, 0, count);
      }

    return value;
  }
  
  /**
   * Returns true iff this String contains the sequence of Characters
   * described in s.
   * @param s the CharSequence
   * @return true iff this String contains s
   * 
   * @since 1.5
   */
  public boolean contains (CharSequence s)
  {
    return this.indexOf(s.toString()) != -1;
  }
  
  /**
   * Returns a string that is this string with all instances of the sequence
   * represented by <code>target</code> replaced by the sequence in 
   * <code>replacement</code>.
   * @param target the sequence to be replaced
   * @param replacement the sequence used as the replacement
   * @return the string constructed as above
   */
  public String replace (CharSequence target, CharSequence replacement)
  {
    String targetString = target.toString();
    String replaceString = replacement.toString();
    int targetLength = target.length();
    int replaceLength = replacement.length();
    
    int startPos = this.indexOf(targetString);
    StringBuilder result = new StringBuilder(this);    
    while (startPos != -1)
      {
        // Replace the target with the replacement
        result.replace(startPos, startPos + targetLength, replaceString);

        // Search for a new occurrence of the target
        startPos = result.indexOf(targetString, startPos + replaceLength);
      }
    return result.toString();
  }
  
  /**
   * Return the index into this String that is offset from the given index by 
   * <code>codePointOffset</code> code points.
   * @param index the index at which to start
   * @param codePointOffset the number of code points to offset
   * @return the index into this String that is <code>codePointOffset</code>
   * code points offset from <code>index</code>.
   * 
   * @throws IndexOutOfBoundsException if index is negative or larger than the
   * length of this string.
   * @throws IndexOutOfBoundsException if codePointOffset is positive and the
   * substring starting with index has fewer than codePointOffset code points.
   * @throws IndexOutOfBoundsException if codePointOffset is negative and the
   * substring ending with index has fewer than (-codePointOffset) code points.
   * @since 1.5
   */
  public int offsetByCodePoints(int index, int codePointOffset)
  {
    if (index < 0 || index > count)
      throw new IndexOutOfBoundsException();
    
    return Character.offsetByCodePoints(value, offset, count, offset + index,
                                        codePointOffset);
  }
}
