/* StringBuffer.java -- Growable strings
   Copyright (C) 1998, 1999, 2000, 2001 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */

package java.lang;
import java.io.Serializable;

/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
 * Updated using online JDK 1.2 docs.
 * Believed complete and correct to JDK 1.2.
 * Merged with Classpath.
 */

/**
 * <code>StringBuffer</code> represents a changeable <code>String</code>.
 * It provides the operations required to modify the
 * <code>StringBuffer</code> including insert, replace, delete, append,
 * and reverse.
 * <P>
 *
 * <code>StringBuffer</code>s are variable-length in nature, so even if
 * you initialize them to a certain size, they can still grow larger than
 * that.  <EM>Capacity</EM> indicates the number of characters the
 * <code>StringBuffer</code> can have in it before it has to grow (growing
 * the char array is an expensive operation involving <code>new</code>).
 * <P>
 *
 * Incidentally, the String operator "+" actually is turned into a
 * <code>StringBuffer</code> operation:
 * <BR>
 * <code>a + b</code>
 * <BR>
 * is the same as
 * <BR>
 * <code>new StringBuffer(a).append(b).toString()</code>.
 *
 * @implnote Classpath's StringBuffer is capable of sharing memory with
 *           Strings for efficiency.  This will help in two instances:
 *           first, when a StringBuffer is created from a String but is
 *           never changed, and second, when a StringBuffer is converted
 *           to a String and the StringBuffer is not changed after that.
 *
 * @since JDK1.0
 * @author Paul Fisher
 * @author John Keiser
 * @author Tom Tromey
 * @see java.lang.String
 */
public final class StringBuffer implements Serializable, CharSequence
{
  /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param bool the <code>boolean</code> to convert and append.
   *  @return this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(boolean)
   */
  public StringBuffer append (boolean bool)
  {
    return append (String.valueOf(bool));
  }

  /** Append the <code>char</code> to this <code>StringBuffer</code>.
   *  @param c the <code>char</code> to append.
   *  @return this <code>StringBuffer</code>.
   */
  public synchronized StringBuffer append (char ch)
  {
    ensureCapacity_unsynchronized (count + 1);
    value[count++] = ch;
    return this;
  }

  /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param inum the <code>int</code> to convert and append.
   *  @return this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(int)
   */
  public native StringBuffer append (int inum);

  /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param lnum the <code>long</code> to convert and append.
   *  @return this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(long)
   */
  public StringBuffer append (long lnum)
  {
    return append (String.valueOf(lnum));
  }

  /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param fnum the <code>float</code> to convert and append.
   *  @return this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(float)
   */
  public StringBuffer append (float fnum)
  {
    return append (String.valueOf(fnum));
  }

  /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param dnum the <code>double</code> to convert and append.
   *  @return this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(double)
   */
  public StringBuffer append (double dnum)
  {
    return append (String.valueOf(dnum));
  }

  /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param obj the <code>Object</code> to convert and append.
   *  @return this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(java.lang.Object)
   */
  public StringBuffer append (Object obj)
  {
    return append (String.valueOf(obj));
  }

  /** Append the <code>String</code> to this <code>StringBuffer</code>.
   *  @param str the <code>String</code> to append.
   *  @return this <code>StringBuffer</code>.
   */
  public synchronized StringBuffer append (String str)
  {
    if (str == null)
      str = "null";
    int len = str.length();
    ensureCapacity_unsynchronized (count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
  }

  /** Append the <code>char</code> array to this <code>StringBuffer</code>.
   *  @param data the <code>char[]</code> to append.
   *  @return this <code>StringBuffer</code>.
   *  @exception NullPointerException if <code>str</code> is <code>null</code>.
   */
  public StringBuffer append (char[] data)
  {
    return append (data, 0, data.length);
  }

  /** Append the <code>char</code> array to this <code>StringBuffer</code>.
   *  @param data the <code>char[]</code> to append.
   *  @param offset the place to start grabbing characters from
   *         <code>str</code>.
   *  @param count the number of characters to get from <code>str</code>.
   *  @return this <code>StringBuffer</code>.
   *  @exception NullPointerException if <code>str</code> is <code>null</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> or
   *             <code>offset+len</code> is out of range.
   */
  public synchronized StringBuffer append (char[] data, int offset, int count)
  {
    ensureCapacity_unsynchronized (this.count + count);
    System.arraycopy(data, offset, value, this.count, count);
    this.count += count;
    return this;
  } 

  /** Get the total number of characters this <code>StringBuffer</code>
   *  can support before it must be grown.  Not to be confused with
   *  <em>length</em>.
   *  @return the capacity of this <code>StringBuffer</code>
   *  @see #length()
   *  @see #ensureCapacity(int)
   */
  public int capacity ()
  {
    return value.length;
  }

  /** Get the character at the specified index.
   *  @param index the index of the character to get, starting at 0.
   *  @return the character at the specified index.
   *  @exception IndexOutOfBoundsException if the desired character index
   *             is negative or greater then length() - 1.
   */
  public synchronized char charAt (int index)
  {
    if (index >= count)
      throw new StringIndexOutOfBoundsException (index);
    return value[index];
  }

  /** Delete characters from this <code>StringBuffer</code>.
   *  <code>delete(10, 12)</code> will delete 10 and 11, but not 12.
   *  @param start the first character to delete.
   *  @param end the index after the last character to delete.
   *  @return this <code>StringBuffer</code>.
   *  @exception StringIndexOutOfBoundsException if <code>start</code>
   *             or <code>end-1</code> are out of bounds, or if
   *             <code>start > end</code>.
   */
  public synchronized StringBuffer delete (int start, int end)
  {
    if (start < 0 || start > count || start > end)
      throw new StringIndexOutOfBoundsException (start);
    if (end > count)
      end = count;
    // This will unshare if required.
    ensureCapacity_unsynchronized (count);
    if (count - end != 0)
      System.arraycopy (value, end, value, start, count - end);
    count -= (end - start);
    return this;
  }

  /** Delete a character from this <code>StringBuffer</code>.
   *  @param index the index of the character to delete.
   *  @return this <code>StringBuffer</code>.
   *  @exception StringIndexOutOfBoundsException if <code>index</code>
   *             is out of bounds.
   */
  public StringBuffer deleteCharAt(int index)
  {
    return delete (index, index + 1);
  }

  /** Increase the capacity of this <code>StringBuffer</code>.
   *  This will ensure that an expensive growing operation will not occur
   *  until <code>minimumCapacity</code> is reached.
   *  If the capacity is actually already greater than <code>minimumCapacity</code>
   *  @param minimumCapacity the new capacity.
   *  @see #capacity()
   */
  public synchronized void ensureCapacity (int minimumCapacity)
  {
    if (shared || minimumCapacity > value.length)
      {
	// We don't want to make a larger vector when `shared' is
	// set.  If we do, then setLength becomes very inefficient
	// when repeatedly reusing a StringBuffer in a loop.
	int max = (minimumCapacity > value.length
		   ? value.length*2+2
		   : value.length);
	minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
	char[] nb = new char[minimumCapacity];
	System.arraycopy(value, 0, nb, 0, count);
	value = nb;
	shared = false;
      }
  }

  // ensureCapacity is used by several synchronized methods in StringBuffer.
  // There's no need to synchronize again.
  private void ensureCapacity_unsynchronized (int minimumCapacity)
  {
    if (shared || minimumCapacity > value.length)
      {
	// We don't want to make a larger vector when `shared' is
	// set.  If we do, then setLength becomes very inefficient
	// when repeatedly reusing a StringBuffer in a loop.
	int max = (minimumCapacity > value.length
		   ? value.length*2+2
		   : value.length);
	minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
	char[] nb = new char[minimumCapacity];
	System.arraycopy(value, 0, nb, 0, count);
	value = nb;
	shared = false;
      }
  }

  /** Get the specified array of characters.
   *  The characters will be copied into the array you pass in.
   *  @param srcOffset the index to start copying from in the
   *         <code>StringBuffer</code>.
   *  @param srcEnd the number of characters to copy.
   *  @param dst the array to copy into.
   *  @param dstOffset the index to start copying into <code>dst</code>.
   *  @exception NullPointerException if dst is null.
   *  @exception IndexOutOfBoundsException if any source or target
   *             indices are out of range.
   *  @see java.lang.System#arraycopy(java.lang.Object,int,java.lang.Object,int,int)
   */
  public synchronized void getChars (int srcOffset, int srcEnd,
				     char[] dst, int dstOffset)
  {
    if (srcOffset < 0 || srcOffset > srcEnd)
      throw new StringIndexOutOfBoundsException (srcOffset);
    int todo = srcEnd - srcOffset;
    if (srcEnd > count || dstOffset + todo > count)
      throw new StringIndexOutOfBoundsException (srcEnd);
    System.arraycopy(value, srcOffset, dst, dstOffset, todo);
  }

  /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param offset the place to insert.
   *  @param bool the <code>boolean</code> to convert and insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(boolean)
   */
  public StringBuffer insert (int offset, boolean bool)
  {
    return insert (offset, bool ? "true" : "false");
  }

  /** Insert the <code>char</code> argument into this <code>StringBuffer</code>.
   *  @param offset the place to insert.
   *  @param ch the <code>char</code> to insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   */
  public synchronized StringBuffer insert (int offset, char ch)
  {
    if (offset < 0 || offset > count)
      throw new StringIndexOutOfBoundsException (offset);
    ensureCapacity_unsynchronized (count+1);
    System.arraycopy(value, offset, value, offset+1, count-offset);
    value[offset] = ch;
    count++;
    return this;
  }

  /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param offset the place to insert.
   *  @param inum the <code>int</code> to convert and insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(int)
   */
  public StringBuffer insert (int offset, int inum)
  {
    return insert (offset, String.valueOf(inum));
  }

  /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param offset the place to insert.
   *  @param lnum the <code>long</code> to convert and insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(long)
   */
  public StringBuffer insert (int offset, long lnum)
  {
    return insert (offset, String.valueOf(lnum));
  }

  /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param offset the place to insert.
   *  @param fnum the <code>float</code> to convert and insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(float)
   */
  public StringBuffer insert (int offset, float fnum)
  {
    return insert (offset, String.valueOf(fnum));
  }

  /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param offset the place to insert.
   *  @param dnum the <code>double</code> to convert and insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(double)
   */
  public StringBuffer insert (int offset, double dnum)
  {
    return insert (offset, String.valueOf(dnum));
  }

  /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
   *  Uses <code>String.valueOf()</code> to convert to
   *  <code>String</code>.
   *  @param offset the place to insert.
   *  @param obj the <code>Object</code> to convert and insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   *  @see java.lang.String#valueOf(java.lang.Object)
   */
  public StringBuffer insert (int offset, Object obj)
  {
    return insert (offset, String.valueOf(obj));
  }

  /** Insert the <code>String</code> argument into this <code>StringBuffer</code>.
   *  @param offset the place to insert.
   *  @param str the <code>String</code> to insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   */
  public synchronized StringBuffer insert (int offset, String str)
  {
    if (offset < 0 || offset > count)
      throw new StringIndexOutOfBoundsException (offset);
    // Note that using `null' is from JDK 1.2.
    if (str == null)
      str = "null";
    int len = str.length();
    ensureCapacity_unsynchronized (count+len);
    System.arraycopy(value, offset, value, offset+len, count-offset);
    str.getChars(0, len, value, offset);
    count += len;
    return this;
  }

  /** Insert the <code>char[]</code> argument into this
   *  <code>StringBuffer</code>. 
   *  @param offset the place to insert.
   *  @param data the <code>char[]</code> to insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception NullPointerException if <code>data</code> is
   *             <code>null</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range for this <code>StringBuffer</code>.
   */
  public StringBuffer insert (int offset, char[] data)
  {
    // One could check if offset is invalid here instead of making sure that
    // data isn't null before dereferencing, but this works just as well.
    return insert (offset, data, 0, data == null ? 0 : data.length);
  }

  /** Insert the <code>char[]</code> argument into this
   *  <code>StringBuffer</code>.
   *  @param offset the place to insert.
   *  @param str the <code>char[]</code> to insert.
   *  @param str_offset the index in <code>str</code> to start inserting
   *         from.
   *  @param len the number of characters to insert.
   *  @return this <code>StringBuffer</code>.
   *  @exception NullPointerException if <code>str</code> is <code>null</code>.
   *  @exception IndexOutOfBoundsException if <code>offset</code> is out
   *             of range, for this <code>StringBuffer</code>, or if
   *             <code>str_offset</code> or <code>str_offset+len</code>
   *             are out of range for <code>str</code>.
   */
  public synchronized StringBuffer insert(int offset, char[] str,
					  int str_offset, int len)
  {
    if (offset < 0 || offset > count)
      throw new StringIndexOutOfBoundsException (offset);
    if (len < 0)
      throw new StringIndexOutOfBoundsException (len);
    if (str_offset < 0 || str_offset + len > str.length)
      throw new StringIndexOutOfBoundsException (str_offset);
    ensureCapacity_unsynchronized (count + len);
    System.arraycopy(value, offset, value, offset + len, count - offset);
    System.arraycopy(str, str_offset, value, offset, len);
    count += len;
    return this;
  }

  /** Get the length of the <code>String</code> this
   *  <code>StringBuffer</code> would create.  Not to be confused with the
   *  <em>capacity</em> of the <code>StringBuffer</code>.
   *  @return the length of this <code>StringBuffer</code>.
   *  @see #capacity()
   *  @see #setLength(int)
   */
  public int length ()
  {
    return count;
  }

  /** Replace characters between index <code>start</code> (inclusive) and 
   *  <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> 
   *  is larger than the size of this StringBuffer, all characters after
   *  <code>start</code> are replaced.
   *  @param start the beginning index of characters to delete (inclusive).
   *  @param end the ending index of characters to delete (exclusive).
   *  @param str the new <code>String</code> to insert.
   *  @return this <code>StringBuffer</code>.
   */
  public synchronized StringBuffer replace (int start, int end, String str)
  {
    if (start < 0 || start > count || start > end)
      throw new StringIndexOutOfBoundsException (start);
  
    int len = str.length();
    // Calculate the difference in 'count' after the replace.
    int delta = len - ((end > count ? count : end) - start);
    ensureCapacity_unsynchronized (count + delta);
        
    if (delta != 0 && end < count)
      System.arraycopy(value, end, value, end + delta, count - end);
    
    str.getChars (0, len, value, start);    
    count += delta;    
    return this;    
  }

  /** Reverse the characters in this StringBuffer.
   *  @return this <code>StringBuffer</code>.
   */
  public synchronized StringBuffer reverse ()
  {
    // Call ensureCapacity to enforce copy-on-write.
    ensureCapacity_unsynchronized (count);
    for (int i = 0; i < count / 2; ++i)
      {
	char c = value[i];
	value[i] = value[count - i - 1];
	value[count - i - 1] = c;
      }
    return this;
  }

  /** Set the character at the specified index.
   *  @param index the index of the character to set starting at 0.
   *  @param ch the value to set that character to.
   *  @exception IndexOutOfBoundsException if the specified character
   *             index is not between 0 and length() - 1 (inclusive).
   */
  public synchronized void setCharAt (int index, char ch)
  {
    if (index < 0 || index >= count)
      throw new StringIndexOutOfBoundsException (index);
    // Call ensureCapacity to enforce copy-on-write.
    ensureCapacity_unsynchronized (count);
    value[index] = ch;
  }

  /** Set the length of this StringBuffer.
   *  <P>
   *  If the new length is greater than the current length, all the new
   *  characters are set to '\0'.
   *  <P>
   *  If the new length is less than the current length, the first
   *  <code>newLength</code> characters of the old array will be
   * @param newLength the new length
   * @exception IndexOutOfBoundsException if the new length is
   *            negative.
   * @see #length()
   */
  public synchronized void setLength (int newLength)
  {
    if (newLength < 0)
      throw new StringIndexOutOfBoundsException (newLength);

    ensureCapacity_unsynchronized (newLength);
    for (int i = count; i < newLength; ++i)
      value[i] = '\0';
    count = newLength;
  }

  /** Create a new StringBuffer with default capacity 16.
   *  @see JLS 20.13.1
   */
  public StringBuffer ()
  {
    this (DEFAULT_CAPACITY);
  }

  /** Create an empty <code>StringBuffer</code> with the specified initial capacity.
   *  @param capacity the initial capacity.
   */
  public StringBuffer (int capacity)
  {
    count = 0;
    value = new char[capacity];
    shared = false;
  }

  /** Create a new <code>StringBuffer</code> with the characters in the specified <code>String</code>.
   *  Initial capacity will be the size of the String plus 16.
   *  @param str the <code>String</code> to make a <code>StringBuffer</code> out of.
   *  @XXX optimize for sharing.
   */
  public StringBuffer (String str)
  {
    // The documentation is not clear, but experimentation with
    // other implementations indicates that StringBuffer(null)
    // should throw a NullPointerException.
    count = str.length();
    // JLS: The initial capacity of the string buffer is 16 plus the
    // length of the argument string.
    value = new char[count + DEFAULT_CAPACITY];
    str.getChars(0, count, value, 0);
    shared = false;
  }

  /**
   * Creates a substring of this StringBuffer, starting at a specified index
   * and ending at the end of this StringBuffer.
   *
   * @param beginIndex index to start substring (base 0)
   * 
   * @return new String which is a substring of this StringBuffer
   *
   * @exception StringIndexOutOfBoundsException 
   *   if (beginIndex < 0 || beginIndex > this.length())
   */
  public String substring (int beginIndex)
  {
    return substring (beginIndex, count);
  }

  /**
   * Creates a substring of this StringBuffer, starting at a specified index
   * and ending at one character before a specified index.
   *
   * @param beginIndex index to start substring (base 0)
   * @param endIndex index after the last character to be 
   *   copied into the substring
   * 
   * @return new String which is a substring of this StringBuffer
   *
   * @exception StringIndexOutOfBoundsException 
   *   if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)
   */
  public synchronized String substring (int beginIndex, int endIndex) 
  {
    if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
      throw new StringIndexOutOfBoundsException ();
    // FIXME: for libgcj it would be possible, and more efficient, to
    // enable sharing here.
    return new String (value, beginIndex, endIndex - beginIndex);
  }

  /**
   * Creates a substring of this StringBuffer, starting at a specified index
   * and ending at one character before a specified index.
   * <p>
   * To implement <code>CharSequence</code>.
   * Calls <code>substring(beginIndex, endIndex)</code>.
   *
   * @param beginIndex index to start substring (base 0)
   * @param endIndex index after the last character to be 
   *   copied into the substring
   * 
   * @return new String which is a substring of this StringBuffer
   *
   * @exception StringIndexOutOfBoundsException 
   *   if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)
   */
  public CharSequence subSequence (int beginIndex, int endIndex) 
  {
    return substring(beginIndex, endIndex);
  }


  /** Convert this <code>StringBuffer</code> to a <code>String</code>.
   *  @return the characters in this StringBuffer
   */
  public String toString ()
  {
    // Note: in libgcj this causes the StringBuffer to be shared.  In
    // Classpath it does not.
    return new String (this);
  }

  // Index of next available character.  Note that this has
  // permissions set this way so that String can get the value.
  int count;

  // The buffer.  Note that this has permissions set this way so that
  // String can get the value.
  char[] value;

  // True if we need to copy the buffer before writing to it again.
  // FIXME: JDK 1.2 doesn't specify this.  The new buffer-growing
  // semantics make this less useful in that case, too.  Note that
  // this has permissions set this way so that String can get the
  // value.
  boolean shared;

  static final long serialVersionUID = 3388685877147921107L;
  private final static int DEFAULT_CAPACITY = 16; // JLS 20.13.1
}
