CPStringBuilder changes in the VM layer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In doing the work on CPStringBuilder, I noticed that many of our VMs
use code verbatim from the
java.lang.reflect.{Field,Constructor,Method} classes when they all
broke in the same way.  This suggests we should have a VM separation
here and I propose to add this in this evening.

For now, the patch to make a VM work is fairly trivial.  I've attached
ones for CACAO, JikesRVM, JamVM and CACAO.

Thanks,
-- 
Andrew :-)

Document Freedom Day - March 26th
http://documentfreedom.org

Support Free Java!
Contribute to GNU Classpath and the OpenJDK
http://www.gnu.org/software/classpath
http://openjdk.java.net
diff -r d73f6705d7ad src/lib/gnu/java/lang/reflect/Constructor.java
--- a/src/lib/gnu/java/lang/reflect/Constructor.java	Fri Feb 29 12:27:16 2008 +0100
+++ b/src/lib/gnu/java/lang/reflect/Constructor.java	Sat Mar 01 11:57:01 2008 +0000
@@ -39,6 +39,7 @@ package java.lang.reflect;
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 
 import gnu.java.lang.reflect.MethodSignatureParser;
 
@@ -247,7 +248,7 @@ public final class Constructor<T>
   public String toString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getDeclaringClass().getName()).append('(');
     Class[] c = getParameterTypes();
@@ -269,7 +270,7 @@ public final class Constructor<T>
   }
 
   static <X extends GenericDeclaration>
-  void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs)
+  void addTypeParameters(CPStringBuilder sb, TypeVariable<X>[] typeArgs)
   {
     if (typeArgs.length == 0)
       return;
@@ -285,7 +286,7 @@ public final class Constructor<T>
 
   public String toGenericString()
   {
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     addTypeParameters(sb, getTypeParameters());
     sb.append(getDeclaringClass().getName()).append('(');
diff -r d73f6705d7ad src/lib/gnu/java/lang/reflect/Field.java
--- a/src/lib/gnu/java/lang/reflect/Field.java	Fri Feb 29 12:27:16 2008 +0100
+++ b/src/lib/gnu/java/lang/reflect/Field.java	Sat Mar 01 11:57:01 2008 +0000
@@ -39,6 +39,7 @@ package java.lang.reflect;
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 
 import gnu.java.lang.reflect.FieldSignatureParser;
 
@@ -227,7 +228,7 @@ extends AccessibleObject implements Memb
   public String toString()
   {
     // 64 is a reasonable buffer initial size for field
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(ClassHelper.getUserName(getType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -237,7 +238,7 @@ extends AccessibleObject implements Memb
 
   public String toGenericString()
   {
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getGenericType()).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
diff -r d73f6705d7ad src/lib/gnu/java/lang/reflect/Method.java
--- a/src/lib/gnu/java/lang/reflect/Method.java	Fri Feb 29 12:27:16 2008 +0100
+++ b/src/lib/gnu/java/lang/reflect/Method.java	Sat Mar 01 11:57:01 2008 +0000
@@ -39,6 +39,7 @@ package java.lang.reflect;
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 
 import gnu.java.lang.reflect.MethodSignatureParser;
 
@@ -287,7 +288,7 @@ extends AccessibleObject implements Memb
   public String toString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(ClassHelper.getUserName(getReturnType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -313,7 +314,7 @@ extends AccessibleObject implements Memb
   public String toGenericString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     Constructor.addTypeParameters(sb, getTypeParameters());
     sb.append(getGenericReturnType()).append(' ');
Index: lib/java/lang/reflect/Constructor.java
===================================================================
RCS file: /cvsroot/jamvm/jamvm/lib/java/lang/reflect/Constructor.java,v
retrieving revision 1.6
diff -u -3 -p -u -r1.6 Constructor.java
--- lib/java/lang/reflect/Constructor.java	24 Feb 2007 22:57:34 -0000	1.6
+++ lib/java/lang/reflect/Constructor.java	1 Mar 2008 12:15:34 -0000
@@ -43,6 +43,7 @@ This Classpath reference implementation 
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 import gnu.java.lang.reflect.MethodSignatureParser;
 import java.util.Arrays;
 import java.lang.annotation.Annotation;
@@ -231,7 +232,7 @@ public final class Constructor
   public String toString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getDeclaringClass().getName()).append('(');
     Class[] c = getParameterTypes();
@@ -253,7 +254,7 @@ public final class Constructor
   }
 
   /* FIXME[GENERICS]: Add X extends GenericDeclaration and TypeVariable<X> */
-  static void addTypeParameters(StringBuilder sb, TypeVariable[] typeArgs)
+  static void addTypeParameters(CPStringBuilder sb, TypeVariable[] typeArgs)
   {
     if (typeArgs.length == 0)
       return;
@@ -269,7 +270,7 @@ public final class Constructor
 
   public String toGenericString()
   {
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     addTypeParameters(sb, getTypeParameters());
     sb.append(getDeclaringClass().getName()).append('(');
Index: lib/java/lang/reflect/Field.java
===================================================================
RCS file: /cvsroot/jamvm/jamvm/lib/java/lang/reflect/Field.java,v
retrieving revision 1.6
diff -u -3 -p -u -r1.6 Field.java
--- lib/java/lang/reflect/Field.java	24 Feb 2007 22:57:34 -0000	1.6
+++ lib/java/lang/reflect/Field.java	1 Mar 2008 12:15:34 -0000
@@ -44,6 +44,7 @@ This Classpath reference implementation 
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 import gnu.java.lang.reflect.FieldSignatureParser;
 import java.lang.annotation.Annotation;
 
@@ -204,7 +205,7 @@ extends AccessibleObject implements Memb
   public String toString()
   {
     // 64 is a reasonable buffer initial size for field
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(ClassHelper.getUserName(getType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -214,7 +215,7 @@ extends AccessibleObject implements Memb
  
   public String toGenericString()
   {
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getGenericType()).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
Index: lib/java/lang/reflect/Method.java
===================================================================
RCS file: /cvsroot/jamvm/jamvm/lib/java/lang/reflect/Method.java,v
retrieving revision 1.6
diff -u -3 -p -u -r1.6 Method.java
--- lib/java/lang/reflect/Method.java	24 Feb 2007 22:57:34 -0000	1.6
+++ lib/java/lang/reflect/Method.java	1 Mar 2008 12:15:34 -0000
@@ -43,6 +43,7 @@ This Classpath reference implementation 
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 import gnu.java.lang.reflect.MethodSignatureParser;
 import java.lang.annotation.Annotation;
 import java.util.Arrays;
@@ -270,7 +271,7 @@ public final class Method
   public String toString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(ClassHelper.getUserName(getReturnType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -296,7 +297,7 @@ public final class Method
   public String toGenericString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     Constructor.addTypeParameters(sb, getTypeParameters());
     sb.append(getGenericReturnType()).append(' ');
Index: libraryInterface/Common/src/java/lang/reflect/Method.java
===================================================================
--- libraryInterface/Common/src/java/lang/reflect/Method.java	(revision 13987)
+++ libraryInterface/Common/src/java/lang/reflect/Method.java	(working copy)
@@ -12,6 +12,8 @@
  */
 package java.lang.reflect;
 
+import gnu.java.lang.CPStringBuilder;
+
 import java.lang.annotation.Annotation;
 
 import org.jikesrvm.classloader.*;
@@ -155,7 +157,7 @@ public final class Method extends Access
   }
 
   public String toString() {
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(JikesRVMHelpers.getUserName(getReturnType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -230,7 +232,7 @@ public final class Method extends Access
   }
 
   public String toGenericString() {
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     Constructor.addTypeParameters(sb, getTypeParameters());
     sb.append(getGenericReturnType()).append(' ');
Index: libraryInterface/Common/src/java/lang/reflect/Field.java
===================================================================
--- libraryInterface/Common/src/java/lang/reflect/Field.java	(revision 13987)
+++ libraryInterface/Common/src/java/lang/reflect/Field.java	(working copy)
@@ -12,6 +12,8 @@
  */
 package java.lang.reflect;
 
+import gnu.java.lang.CPStringBuilder;
+
 import java.lang.annotation.Annotation;
 
 import org.jikesrvm.classloader.VM_Class;
@@ -239,7 +241,7 @@ public final class Field extends Accessi
   }
 
   public String toString() {
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(JikesRVMHelpers.getUserName(getType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -544,7 +546,7 @@ public final class Field extends Accessi
   }
 
   public String toGenericString() {
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getGenericType()).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
Index: libraryInterface/Common/src/java/lang/reflect/Constructor.java
===================================================================
--- libraryInterface/Common/src/java/lang/reflect/Constructor.java	(revision 13987)
+++ libraryInterface/Common/src/java/lang/reflect/Constructor.java	(working copy)
@@ -12,6 +12,8 @@
  */
 package java.lang.reflect;
 
+import gnu.java.lang.CPStringBuilder;
+
 import org.jikesrvm.classloader.*;
 import org.jikesrvm.runtime.VM_Reflection;
 import org.jikesrvm.runtime.VM_Runtime;
@@ -137,7 +139,7 @@ public final class Constructor<T> extend
   }
 
   public String toString() {
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getDeclaringClass().getName()).append('(');
     Class<?>[] c = getParameterTypes();
@@ -188,7 +190,7 @@ public final class Constructor<T> extend
   }
 
   public String toGenericString() {
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     addTypeParameters(sb, getTypeParameters());
     sb.append(getDeclaringClass().getName()).append('(');
@@ -210,7 +212,7 @@ public final class Constructor<T> extend
     return sb.toString();
   }
 
-  static void addTypeParameters(StringBuilder sb, TypeVariable<?>[] typeArgs) {
+  static void addTypeParameters(CPStringBuilder sb, TypeVariable<?>[] typeArgs) {
     if (typeArgs.length == 0)
       return;
     sb.append('<');
Index: build/components/classpath.xml
===================================================================
--- build/components/classpath.xml	(revision 13987)
+++ build/components/classpath.xml	(working copy)
@@ -117,6 +117,14 @@
   <target name="patch-classpath-web" depends="fetch" if="classpath.from-web">
     <patch patchfile="${components.patch.dir}/classpath-web.RVM-185.patch"
            dir="${classpath.package.dir}/classpath/" strip="0"/>
+    <patch patchfile="${components.patch.dir}/classpath-web.RVM-266-01.patch"
+           dir="${classpath.package.dir}/classpath/" strip="0"/>
+    <patch patchfile="${components.patch.dir}/classpath-web.RVM-266-02.patch"
+           dir="${classpath.package.dir}/classpath/" strip="0"/>
+    <patch patchfile="${components.patch.dir}/classpath-web.RVM-266-03.patch"
+           dir="${classpath.package.dir}/classpath/" strip="0"/>
+    <patch patchfile="${components.patch.dir}/classpath-web.RVM-266-04.patch"
+           dir="${classpath.package.dir}/classpath/" strip="0"/>
   </target>
   <target name="patch" depends="patch-classpath-web,patch-classpath-cvs"/>
 
Index: build/components/patches/classpath-web.RVM-266-01.patch
===================================================================
--- build/components/patches/classpath-web.RVM-266-01.patch	(revision 0)
+++ build/components/patches/classpath-web.RVM-266-01.patch	(revision 0)
@@ -0,0 +1,1168 @@
+Index: gnu/classpath/CPStringBuffer.java
+===================================================================
+RCS file: gnu/classpath/CPStringBuffer.java
+diff -N gnu/classpath/CPStringBuffer.java
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ gnu/classpath/CPStringBuffer.java	29 Feb 2008 21:45:23 -0000
+@@ -0,0 +1,1161 @@
++/* ClasspathStringBuffer.java -- Growable strings without locking or copying
++   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
++   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 gnu.classpath;
++
++import java.lang.reflect.Constructor;
++import java.lang.reflect.InvocationTargetException;
++
++import java.io.Serializable;
++
++/**
++ * This class is based on java.lang.AbstractStringBuffer but
++ * without the copying of the string by toString.
++ * If you modify this, please consider also modifying that code.
++ * This code is not thread-safe; limit its use to internal use within
++ * methods.
++ */
++public final class CPStringBuffer
++  implements Serializable, CharSequence, Appendable
++{
++
++  /**
++   * Index of next available character (and thus the size of the current
++   * string contents).  Note that this has permissions set this way so that
++   * String can get the value.
++   *
++   * @serial the number of characters in the buffer
++   */
++  private int count;
++
++  /**
++   * The buffer.  Note that this has permissions set this way so that String
++   * can get the value.
++   *
++   * @serial the buffer
++   */
++  private char[] value;
++
++  /**
++   * The package-private constructor for String objects without copying.
++   */
++  private static final Constructor<String> cons;
++
++  /**
++   * The default capacity of a buffer.
++   */
++  private static final int DEFAULT_CAPACITY = 16;
++
++  static
++  {
++    try
++      {
++	cons = String.class.getDeclaredConstructor(char[].class, Integer.TYPE,
++						   Integer.TYPE, Boolean.TYPE);
++      }
++    catch (NoSuchMethodException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not get no-copy String constructor").initCause(e);
++      }
++  }
++
++  /**
++   * Create a new CPStringBuffer with default capacity 16.
++   */
++  CPStringBuffer()
++  {
++    this(DEFAULT_CAPACITY);
++  }
++
++  /**
++   * Create an empty <code>StringBuffer</code> with the specified initial
++   * capacity.
++   *
++   * @param capacity the initial capacity
++   * @throws NegativeArraySizeException if capacity is negative
++   */
++  CPStringBuffer(int capacity)
++  {
++    value = new char[capacity];
++  }
++
++  /**
++   * 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 convert
++   * @throws NullPointerException if str is null
++   */
++  CPStringBuffer(String str)
++  {
++    count = str.count;
++    value = new char[count + DEFAULT_CAPACITY];
++    str.getChars(0, count, value, 0);
++  }
++
++  /**
++   * Create a new <code>StringBuffer</code> with the characters in the
++   * specified <code>CharSequence</code>. Initial capacity will be the
++   * length of the sequence plus 16; if the sequence reports a length
++   * less than or equal to 0, then the initial capacity will be 16.
++   *
++   * @param seq the initializing <code>CharSequence</code>
++   * @throws NullPointerException if str is null
++   * @since 1.5
++   */
++  CPStringBuffer(CharSequence seq)
++  {
++    int len = seq.length();
++    count = len <= 0 ? 0 : len;
++    value = new char[count + DEFAULT_CAPACITY];
++    for (int i = 0; i < len; ++i)
++      value[i] = seq.charAt(i);
++  }
++
++  /**
++   * 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. The buffer is grown to the
++   * larger of <code>minimumCapacity</code> and
++   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
++   *
++   * @param minimumCapacity the new capacity
++   * @see #capacity()
++   */
++  public void ensureCapacity(int minimumCapacity)
++  {
++    ensureCapacity_unsynchronized(minimumCapacity);
++  }
++
++  /**
++   * Set the length of this StringBuffer. If the new length is greater than
++   * the current length, all the new characters are set to '\0'. If the new
++   * length is less than the current length, the first <code>newLength</code>
++   * characters of the old array will be preserved, and the remaining
++   * characters are truncated.
++   *
++   * @param newLength the new length
++   * @throws IndexOutOfBoundsException if the new length is negative
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   * @see #length()
++   */
++  public void setLength(int newLength)
++  {
++    if (newLength < 0)
++      throw new StringIndexOutOfBoundsException(newLength);
++
++    int valueLength = value.length;
++
++    /* Always call ensureCapacity_unsynchronized in order to preserve
++       copy-on-write semantics.  */
++    ensureCapacity_unsynchronized(newLength);
++
++    if (newLength < valueLength)
++      {
++        /* If the StringBuffer's value just grew, then we know that
++           value is newly allocated and the region between count and
++           newLength is filled with '\0'.  */
++	count = newLength;
++      }
++    else
++      {
++	/* The StringBuffer's value doesn't need to grow.  However,
++	   we should clear out any cruft that may exist.  */
++	while (count < newLength)
++          value[count++] = '\0';
++      }
++  }
++
++  /**
++   * 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
++   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public char charAt(int index)
++  {
++    if (index < 0 || index >= count)
++      throw new StringIndexOutOfBoundsException(index);
++    return value[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 int codePointAt(int index)
++  {
++    return Character.codePointAt(value, index, count);
++  }
++
++  /**
++   * 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()
++   * @since 1.5
++   */
++  public int codePointBefore(int index)
++  {
++    // Character.codePointBefore() doesn't perform this check.  We
++    // could use the CharSequence overload, but this is just as easy.
++    if (index >= count)
++      throw new IndexOutOfBoundsException();
++    return Character.codePointBefore(value, index, 1);
++  }
++
++  /**
++   * Get the specified array of characters. <code>srcOffset - srcEnd</code>
++   * characters will be copied into the array you pass in.
++   *
++   * @param srcOffset the index to start copying from (inclusive)
++   * @param srcEnd the index to stop copying from (exclusive)
++   * @param dst the array to copy into
++   * @param dstOffset the index to start copying into
++   * @throws NullPointerException if dst is null
++   * @throws IndexOutOfBoundsException if any source or target indices are
++   *         out of range (while unspecified, source problems cause a
++   *         StringIndexOutOfBoundsException, and dest problems cause an
++   *         ArrayIndexOutOfBoundsException)
++   * @see System#arraycopy(Object, int, Object, int, int)
++   */
++  public void getChars(int srcOffset, int srcEnd,
++		       char[] dst, int dstOffset)
++  {
++    if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
++      throw new StringIndexOutOfBoundsException();
++    VMSystem.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
++  }
++
++  /**
++   * 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
++   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public 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;
++  }
++
++  /**
++   * 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 String#valueOf(Object)
++   * @see #append(String)
++   */
++  public CPStringBuffer append(Object obj)
++  {
++    return append(String.valueOf(obj));
++  }
++
++  /**
++   * Append the <code>String</code> to this <code>StringBuffer</code>. If
++   * str is null, the String "null" is appended.
++   *
++   * @param str the <code>String</code> to append
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuffer append(String str)
++  {
++    if (str == null)
++      str = "null";
++    int len = str.count;
++    ensureCapacity_unsynchronized(count + len);
++    str.getChars(0, len, value, count);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Append the <code>StringBuilder</code> value of the argument to this
++   * <code>StringBuilder</code>. This behaves the same as
++   * <code>append((Object) stringBuffer)</code>, except it is more efficient.
++   *
++   * @param stringBuffer the <code>StringBuilder</code> to convert and append
++   * @return this <code>StringBuilder</code>
++   * @see #append(Object)
++   */
++  public CPStringBuffer append(StringBuffer stringBuffer)
++  {
++    if (stringBuffer == null)
++      return append("null");
++    synchronized (stringBuffer)
++      {
++	int len = stringBuffer.count;
++	ensureCapacity(count + len);
++	VMSystem.arraycopy(stringBuffer.value, 0, value, count, len);
++	count += len;
++      }
++    return this;
++  }
++
++  /**
++   * Append the <code>char</code> array to this <code>StringBuffer</code>.
++   * This is similar (but more efficient) than
++   * <code>append(new String(data))</code>, except in the case of null.
++   *
++   * @param data the <code>char[]</code> to append
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @see #append(char[], int, int)
++   */
++  public CPStringBuffer append(char[] data)
++  {
++    return append(data, 0, data.length);
++  }
++
++  /**
++   * Append part of the <code>char</code> array to this
++   * <code>StringBuffer</code>. This is similar (but more efficient) than
++   * <code>append(new String(data, offset, count))</code>, except in the case
++   * of null.
++   *
++   * @param data the <code>char[]</code> to append
++   * @param offset the start location in <code>str</code>
++   * @param count the number of characters to get from <code>str</code>
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @throws IndexOutOfBoundsException if offset or count is out of range
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public CPStringBuffer append(char[] data, int offset, int count)
++  {
++    if (offset < 0 || count < 0 || offset > data.length - count)
++      throw new StringIndexOutOfBoundsException();
++    ensureCapacity_unsynchronized(this.count + count);
++    VMSystem.arraycopy(data, offset, value, this.count, count);
++    this.count += count;
++    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 bool the <code>boolean</code> to convert and append
++   * @return this <code>StringBuffer</code>
++   * @see String#valueOf(boolean)
++   */
++  public CPStringBuffer append(boolean bool)
++  {
++    return append(bool ? "true" : "false");
++  }
++
++  /**
++   * Append the <code>char</code> to this <code>StringBuffer</code>.
++   *
++   * @param ch the <code>char</code> to append
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuffer append(char ch)
++  {
++    ensureCapacity_unsynchronized(count + 1);
++    value[count++] = ch;
++    return this;
++  }
++
++  /**
++   * Append the characters in the <code>CharSequence</code> to this
++   * buffer.
++   *
++   * @param seq the <code>CharSequence</code> providing the characters
++   * @return this <code>StringBuffer</code>
++   * @since 1.5
++   */
++  public CPStringBuffer append(CharSequence seq)
++  {
++    return append(seq, 0, seq.length());
++  }
++
++  /**
++   * Append some characters from the <code>CharSequence</code> to this
++   * buffer.  If the argument is null, the four characters "null" are
++   * appended.
++   *
++   * @param seq the <code>CharSequence</code> providing the characters
++   * @param start the starting index
++   * @param end one past the final index
++   * @return this <code>StringBuffer</code>
++   * @since 1.5
++   */
++  public CPStringBuffer append(CharSequence seq, int start, int end)
++  {
++    if (seq == null)
++      return append("null");
++    if (end - start > 0)
++      {
++	ensureCapacity_unsynchronized(count + end - start);
++	for (; start < end; ++start)
++	  value[count++] = seq.charAt(start);
++      }
++    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 String#valueOf(int)
++   */
++  // This is native in libgcj, for efficiency.
++  public CPStringBuffer append(int inum)
++  {
++    return append(String.valueOf(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 String#valueOf(long)
++   */
++  public CPStringBuffer append(long lnum)
++  {
++    return append(Long.toString(lnum, 10));
++  }
++
++  /**
++   * 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 String#valueOf(float)
++   */
++  public CPStringBuffer append(float fnum)
++  {
++    return append(Float.toString(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 String#valueOf(double)
++   */
++  public CPStringBuffer append(double dnum)
++  {
++    return append(Double.toString(dnum));
++  }
++
++  /**
++   * Append the code point to this <code>StringBuffer</code>.
++   * This is like #append(char), but will append two characters
++   * if a supplementary code point is given.
++   *
++   * @param code the code point to append
++   * @return this <code>StringBuffer</code>
++   * @see Character#toChars(int, char[], int)
++   * @since 1.5
++   */
++  public CPStringBuffer appendCodePoint(int code)
++  {
++    int len = Character.charCount(code);
++    ensureCapacity_unsynchronized(count + len);
++    Character.toChars(code, value, count);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Delete characters from this <code>StringBuffer</code>.
++   * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
++   * harmless for end to be larger than length().
++   *
++   * @param start the first character to delete
++   * @param end the index after the last character to delete
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
++   * @since 1.2
++   */
++  public CPStringBuffer delete(int start, int end)
++  {
++    if (start < 0 || start > count || start > end)
++      throw new StringIndexOutOfBoundsException(start);
++    if (end > count)
++      end = count;
++    ensureCapacity_unsynchronized(count);
++    if (count - end != 0)
++      VMSystem.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>
++   * @throws StringIndexOutOfBoundsException if index is out of bounds
++   * @since 1.2
++   */
++  public CPStringBuffer deleteCharAt(int index)
++  {
++    return delete(index, index + 1);
++  }
++
++  /**
++   * 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>
++   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
++   * @throws NullPointerException if str is null
++   * @since 1.2
++   */
++  public CPStringBuffer replace(int start, int end, String str)
++  {
++    if (start < 0 || start > count || start > end)
++      throw new StringIndexOutOfBoundsException(start);
++
++    int len = str.count;
++    // 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)
++      VMSystem.arraycopy(value, end, value, end + delta, count - end);
++
++    str.getChars(0, len, value, start);
++    count += delta;
++    return this;
++  }
++
++  /**
++   * Insert a subarray of the <code>char[]</code> argument into this
++   * <code>StringBuffer</code>.
++   *
++   * @param offset the place to insert in this buffer
++   * @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>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @throws StringIndexOutOfBoundsException if any index is out of bounds
++   * @since 1.2
++   */
++  public CPStringBuffer insert(int offset, char[] str, int str_offset, int len)
++  {
++    if (offset < 0 || offset > count || len < 0
++        || str_offset < 0 || str_offset > str.length - len)
++      throw new StringIndexOutOfBoundsException();
++    ensureCapacity_unsynchronized(count + len);
++    VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
++    VMSystem.arraycopy(str, str_offset, value, offset, len);
++    count += len;
++    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 in this buffer
++   * @param obj the <code>Object</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @exception StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(Object)
++   */
++  public CPStringBuffer insert(int offset, Object obj)
++  {
++    return insert(offset, obj == null ? "null" : obj.toString());
++  }
++
++  /**
++   * Insert the <code>String</code> argument into this
++   * <code>StringBuffer</code>. If str is null, the String "null" is used
++   * instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param str the <code>String</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   */
++  public CPStringBuffer insert(int offset, String str)
++  {
++    if (offset < 0 || offset > count)
++      throw new StringIndexOutOfBoundsException(offset);
++    if (str == null)
++      str = "null";
++    int len = str.count;
++    ensureCapacity_unsynchronized(count + len);
++    VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
++    str.getChars(0, len, value, offset);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Insert the <code>CharSequence</code> argument into this
++   * <code>StringBuffer</code>.  If the sequence is null, the String
++   * "null" is used instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param sequence the <code>CharSequence</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws IndexOutOfBoundsException if offset is out of bounds
++   * @since 1.5
++   */
++  public CPStringBuffer insert(int offset, CharSequence sequence)
++  {
++    if (sequence == null)
++      sequence = "null";
++    return insert(offset, sequence, 0, sequence.length());
++  }
++
++  /**
++   * Insert a subsequence of the <code>CharSequence</code> argument into this
++   * <code>StringBuffer</code>.  If the sequence is null, the String
++   * "null" is used instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param sequence the <code>CharSequence</code> to insert
++   * @param start the starting index of the subsequence
++   * @param end one past the ending index of the subsequence
++   * @return this <code>StringBuffer</code>
++   * @throws IndexOutOfBoundsException if offset, start,
++   * or end are out of bounds
++   * @since 1.5
++   */
++  public CPStringBuffer insert(int offset, CharSequence sequence, int start, int end)
++  {
++    if (sequence == null)
++      sequence = "null";
++    if (start < 0 || end < 0 || start > end || end > sequence.length())
++      throw new IndexOutOfBoundsException();
++    int len = end - start;
++    ensureCapacity_unsynchronized(count + len);
++    VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
++    for (int i = start; i < end; ++i)
++      value[offset++] = sequence.charAt(i);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Insert the <code>char[]</code> argument into this
++   * <code>StringBuffer</code>.
++   *
++   * @param offset the place to insert in this buffer
++   * @param data the <code>char[]</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>data</code> is <code>null</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see #insert(int, char[], int, int)
++   */
++  public CPStringBuffer insert(int offset, char[] data)
++  {
++    return insert(offset, data, 0, data.length);
++  }
++
++  /**
++   * 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 in this buffer
++   * @param bool the <code>boolean</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(boolean)
++   */
++  public CPStringBuffer 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 in this buffer
++   * @param ch the <code>char</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   */
++  public CPStringBuffer insert(int offset, char ch)
++  {
++    if (offset < 0 || offset > count)
++      throw new StringIndexOutOfBoundsException(offset);
++    ensureCapacity_unsynchronized(count + 1);
++    VMSystem.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 in this buffer
++   * @param inum the <code>int</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(int)
++   */
++  public CPStringBuffer 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 in this buffer
++   * @param lnum the <code>long</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(long)
++   */
++  public CPStringBuffer insert(int offset, long lnum)
++  {
++    return insert(offset, Long.toString(lnum, 10));
++  }
++
++  /**
++   * 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 in this buffer
++   * @param fnum the <code>float</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(float)
++   */
++  public CPStringBuffer insert(int offset, float fnum)
++  {
++    return insert(offset, Float.toString(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 in this buffer
++   * @param dnum the <code>double</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(double)
++   */
++  public CPStringBuffer insert(int offset, double dnum)
++  {
++    return insert(offset, Double.toString(dnum));
++  }
++
++  /**
++   * Finds the first instance of a substring in this StringBuilder.
++   *
++   * @param str String to find
++   * @return location (base 0) of the String, or -1 if not found
++   * @throws NullPointerException if str is null
++   * @see #indexOf(String, int)
++   */
++  public int indexOf(String str)
++  {
++    return indexOf(str, 0);
++  }
++
++  /**
++   * Finds the first instance of a String in this StringBuffer, 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, or the substring is not found, -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
++   * @since 1.4
++   */
++  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))
++        return fromIndex;
++    return -1;
++  }
++
++  /**
++   * Finds the last instance of a substring in this StringBuffer.
++   *
++   * @param str String to find
++   * @return location (base 0) of the String, or -1 if not found
++   * @throws NullPointerException if str is null
++   * @see #lastIndexOf(String, int)
++   * @since 1.4
++   */
++  public int lastIndexOf(String str)
++  {
++    return lastIndexOf(str, count - str.count);
++  }
++
++  /**
++   * Finds the last instance of a String in this StringBuffer, 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, or the substring is not found, -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
++   * @since 1.4
++   */
++  public int lastIndexOf(String str, int fromIndex)
++  {
++    fromIndex = Math.min(fromIndex, count - str.count);
++    for ( ; fromIndex >= 0; fromIndex--)
++      if (regionMatches(fromIndex, str))
++        return fromIndex;
++    return -1;
++  }
++
++  /**
++   * Reverse the characters in this StringBuffer. The same sequence of
++   * characters exists, but in the reverse index ordering.
++   *
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuffer reverse()
++  {
++    // Call ensureCapacity to enforce copy-on-write.
++    ensureCapacity_unsynchronized(count);
++    for (int i = count >> 1, j = count - i; --i >= 0; ++j)
++      {
++        char c = value[i];
++        value[i] = value[j];
++        value[j] = c;
++      }
++    return this;
++  }
++
++  /**
++   * This may reduce the amount of memory used by the StringBuffer,
++   * by resizing the internal array to remove unused space.  However,
++   * this method is not required to resize, so this behavior cannot
++   * be relied upon.
++   * @since 1.5
++   */
++  public void trimToSize()
++  {
++    int wouldSave = value.length - count;
++    // Some random heuristics: if we save less than 20 characters, who
++    // cares.
++    if (wouldSave < 20)
++      return;
++    // If we save more than 200 characters, shrink.
++    // If we save more than 1/4 of the buffer, shrink.
++    if (wouldSave > 200 || wouldSave * 4 > value.length)
++      {
++	char[] newValue = new char[count];
++	VMSystem.arraycopy(value, 0, newValue, 0, count);
++	value = newValue;
++      }
++  }
++
++  /**
++   * Return the number of code points between two indices in the
++   * <code>StringBuffer</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 int codePointCount(int start, int end)
++  {
++    if (start < 0 || end >= count || start > end)
++      throw new StringIndexOutOfBoundsException();
++
++    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;
++  }
++
++  /**
++   * Starting at the given index, this counts forward by the indicated
++   * number of code points, and then returns the resulting index.  An
++   * unpaired surrogate counts as a single code point for this
++   * purpose.
++   *
++   * @param start the starting index
++   * @param codePoints the number of code points
++   * @return the resulting index
++   * @since 1.5
++   */
++  public int offsetByCodePoints(int start, int codePoints)
++  {
++    while (codePoints > 0)
++      {
++	char base = value[start];
++	if (base < Character.MIN_HIGH_SURROGATE
++	    || base > Character.MAX_HIGH_SURROGATE
++	    || start == count
++	    || value[start + 1] < Character.MIN_LOW_SURROGATE
++	    || value[start + 1] > Character.MAX_LOW_SURROGATE)
++	  {
++	    // Nothing.
++	  }
++	else
++	  {
++	    // Surrogate pair.
++	    ++start;
++	  }
++	++start;
++	--codePoints;
++      }
++    return start;
++  }
++
++  /**
++   * Increase the capacity of this <code>StringBuilder</code>. This will
++   * ensure that an expensive growing operation will not occur until
++   * <code>minimumCapacity</code> is reached. The buffer is grown to the
++   * larger of <code>minimumCapacity</code> and
++   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
++   *
++   * @param minimumCapacity the new capacity
++   * @see #capacity()
++   */
++  protected void ensureCapacity_unsynchronized(int minimumCapacity)
++  {
++    if (minimumCapacity > value.length)
++      {
++        int max = value.length * 2 + 2;
++        minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
++        char[] nb = new char[minimumCapacity];
++        VMSystem.arraycopy(value, 0, nb, 0, count);
++        value = nb;
++      }
++  }
++
++  /**
++   * Predicate which determines if a substring of this matches another String
++   * starting at a specified offset for each String and continuing for a
++   * specified length. This is more efficient than creating a String to call
++   * indexOf on.
++   *
++   * @param toffset index to start comparison at for this String
++   * @param other non-null String to compare to region of this
++   * @return true if regions match, false otherwise
++   * @see #indexOf(String, int)
++   * @see #lastIndexOf(String, int)
++   * @see String#regionMatches(boolean, int, String, int, int)
++   */
++  private boolean regionMatches(int toffset, String other)
++  {
++    int len = other.count;
++    int index = other.offset;
++    while (--len >= 0)
++      if (value[toffset++] != other.value[index++])
++        return false;
++    return true;
++  }
++
++  /**
++   * Get the length of the <code>String</code> this <code>StringBuilder</code>
++   * would create. Not to be confused with the <em>capacity</em> of the
++   * <code>StringBuilder</code>.
++   *
++   * @return the length of this <code>StringBuilder</code>
++   * @see #capacity()
++   * @see #setLength(int)
++   */
++  public int length()
++  {
++    return count;
++  }
++
++  /**
++   * Creates a substring of this StringBuilder, starting at a specified index
++   * and ending at one character before a specified index. This is implemented
++   * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
++   * the CharSequence interface.
++   *
++   * @param beginIndex index to start at (inclusive, base 0)
++   * @param endIndex index to end at (exclusive)
++   * @return new String which is a substring of this StringBuilder
++   * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
++   *         bounds
++   * @see #substring(int, int)
++   */
++  public CharSequence subSequence(int beginIndex, int endIndex)
++  {
++    return substring(beginIndex, endIndex);
++  }
++
++  /**
++   * Creates a substring of this StringBuilder, starting at a specified index
++   * and ending at one character before a specified index.
++   *
++   * @param beginIndex index to start at (inclusive, base 0)
++   * @param endIndex index to end at (exclusive)
++   * @return new String which is a substring of this StringBuilder
++   * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
++   *         of bounds
++   */
++  public String substring(int beginIndex, int endIndex)
++  {
++    int len = endIndex - beginIndex;
++    if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
++      throw new StringIndexOutOfBoundsException();
++    if (len == 0)
++      return "";
++    try
++      {
++	return cons.newInstance(value, beginIndex, len, true);
++      }
++    catch (InstantiationException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
++      }
++    catch (IllegalAccessException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not access no-copy String constructor").initCause(e);
++      }
++    catch (InvocationTargetException e)
++      {
++	throw (Error) 
++	  new InternalError("Error calling no-copy String constructor").initCause(e);
++      }
++  }
++
++  /**
++   * Convert this <code>StringBuilder</code> to a <code>String</code>. The
++   * String is composed of the characters currently in this StringBuilder. Note
++   * that the result is not a copy, so future modifications to this buffer
++   * do affect the String.
++   *
++   * @return the characters in this StringBuilder
++   */
++  public String toString()
++  {
++    try
++      {
++	return cons.newInstance(value, 0, count, true);
++      }
++    catch (InstantiationException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
++      }
++    catch (IllegalAccessException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not access no-copy String constructor").initCause(e);
++      }
++    catch (InvocationTargetException e)
++      {
++	throw (Error) 
++	  new InternalError("Error calling no-copy String constructor").initCause(e);
++      }
++  }
++
++}
Index: build/components/patches/classpath-web.RVM-266-02.patch
===================================================================
--- build/components/patches/classpath-web.RVM-266-02.patch	(revision 0)
+++ build/components/patches/classpath-web.RVM-266-02.patch	(revision 0)
@@ -0,0 +1,2512 @@
+Index: gnu/classpath/CPStringBuffer.java
+===================================================================
+RCS file: gnu/classpath/CPStringBuffer.java
+diff -N gnu/classpath/CPStringBuffer.java
+--- gnu/classpath/CPStringBuffer.java	29 Feb 2008 21:55:09 -0000	1.1
++++ /dev/null	1 Jan 1970 00:00:00 -0000
+@@ -1,1161 +0,0 @@
+-/* ClasspathStringBuffer.java -- Growable strings without locking or copying
+-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+-   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 gnu.classpath;
+-
+-import java.lang.reflect.Constructor;
+-import java.lang.reflect.InvocationTargetException;
+-
+-import java.io.Serializable;
+-
+-/**
+- * This class is based on java.lang.AbstractStringBuffer but
+- * without the copying of the string by toString.
+- * If you modify this, please consider also modifying that code.
+- * This code is not thread-safe; limit its use to internal use within
+- * methods.
+- */
+-public final class CPStringBuffer
+-  implements Serializable, CharSequence, Appendable
+-{
+-
+-  /**
+-   * Index of next available character (and thus the size of the current
+-   * string contents).  Note that this has permissions set this way so that
+-   * String can get the value.
+-   *
+-   * @serial the number of characters in the buffer
+-   */
+-  private int count;
+-
+-  /**
+-   * The buffer.  Note that this has permissions set this way so that String
+-   * can get the value.
+-   *
+-   * @serial the buffer
+-   */
+-  private char[] value;
+-
+-  /**
+-   * The package-private constructor for String objects without copying.
+-   */
+-  private static final Constructor<String> cons;
+-
+-  /**
+-   * The default capacity of a buffer.
+-   */
+-  private static final int DEFAULT_CAPACITY = 16;
+-
+-  static
+-  {
+-    try
+-      {
+-	cons = String.class.getDeclaredConstructor(char[].class, Integer.TYPE,
+-						   Integer.TYPE, Boolean.TYPE);
+-      }
+-    catch (NoSuchMethodException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not get no-copy String constructor").initCause(e);
+-      }
+-  }
+-
+-  /**
+-   * Create a new CPStringBuffer with default capacity 16.
+-   */
+-  CPStringBuffer()
+-  {
+-    this(DEFAULT_CAPACITY);
+-  }
+-
+-  /**
+-   * Create an empty <code>StringBuffer</code> with the specified initial
+-   * capacity.
+-   *
+-   * @param capacity the initial capacity
+-   * @throws NegativeArraySizeException if capacity is negative
+-   */
+-  CPStringBuffer(int capacity)
+-  {
+-    value = new char[capacity];
+-  }
+-
+-  /**
+-   * 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 convert
+-   * @throws NullPointerException if str is null
+-   */
+-  CPStringBuffer(String str)
+-  {
+-    count = str.count;
+-    value = new char[count + DEFAULT_CAPACITY];
+-    str.getChars(0, count, value, 0);
+-  }
+-
+-  /**
+-   * Create a new <code>StringBuffer</code> with the characters in the
+-   * specified <code>CharSequence</code>. Initial capacity will be the
+-   * length of the sequence plus 16; if the sequence reports a length
+-   * less than or equal to 0, then the initial capacity will be 16.
+-   *
+-   * @param seq the initializing <code>CharSequence</code>
+-   * @throws NullPointerException if str is null
+-   * @since 1.5
+-   */
+-  CPStringBuffer(CharSequence seq)
+-  {
+-    int len = seq.length();
+-    count = len <= 0 ? 0 : len;
+-    value = new char[count + DEFAULT_CAPACITY];
+-    for (int i = 0; i < len; ++i)
+-      value[i] = seq.charAt(i);
+-  }
+-
+-  /**
+-   * 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. The buffer is grown to the
+-   * larger of <code>minimumCapacity</code> and
+-   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+-   *
+-   * @param minimumCapacity the new capacity
+-   * @see #capacity()
+-   */
+-  public void ensureCapacity(int minimumCapacity)
+-  {
+-    ensureCapacity_unsynchronized(minimumCapacity);
+-  }
+-
+-  /**
+-   * Set the length of this StringBuffer. If the new length is greater than
+-   * the current length, all the new characters are set to '\0'. If the new
+-   * length is less than the current length, the first <code>newLength</code>
+-   * characters of the old array will be preserved, and the remaining
+-   * characters are truncated.
+-   *
+-   * @param newLength the new length
+-   * @throws IndexOutOfBoundsException if the new length is negative
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   * @see #length()
+-   */
+-  public void setLength(int newLength)
+-  {
+-    if (newLength < 0)
+-      throw new StringIndexOutOfBoundsException(newLength);
+-
+-    int valueLength = value.length;
+-
+-    /* Always call ensureCapacity_unsynchronized in order to preserve
+-       copy-on-write semantics.  */
+-    ensureCapacity_unsynchronized(newLength);
+-
+-    if (newLength < valueLength)
+-      {
+-        /* If the StringBuffer's value just grew, then we know that
+-           value is newly allocated and the region between count and
+-           newLength is filled with '\0'.  */
+-	count = newLength;
+-      }
+-    else
+-      {
+-	/* The StringBuffer's value doesn't need to grow.  However,
+-	   we should clear out any cruft that may exist.  */
+-	while (count < newLength)
+-          value[count++] = '\0';
+-      }
+-  }
+-
+-  /**
+-   * 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
+-   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   */
+-  public char charAt(int index)
+-  {
+-    if (index < 0 || index >= count)
+-      throw new StringIndexOutOfBoundsException(index);
+-    return value[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 int codePointAt(int index)
+-  {
+-    return Character.codePointAt(value, index, count);
+-  }
+-
+-  /**
+-   * 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()
+-   * @since 1.5
+-   */
+-  public int codePointBefore(int index)
+-  {
+-    // Character.codePointBefore() doesn't perform this check.  We
+-    // could use the CharSequence overload, but this is just as easy.
+-    if (index >= count)
+-      throw new IndexOutOfBoundsException();
+-    return Character.codePointBefore(value, index, 1);
+-  }
+-
+-  /**
+-   * Get the specified array of characters. <code>srcOffset - srcEnd</code>
+-   * characters will be copied into the array you pass in.
+-   *
+-   * @param srcOffset the index to start copying from (inclusive)
+-   * @param srcEnd the index to stop copying from (exclusive)
+-   * @param dst the array to copy into
+-   * @param dstOffset the index to start copying into
+-   * @throws NullPointerException if dst is null
+-   * @throws IndexOutOfBoundsException if any source or target indices are
+-   *         out of range (while unspecified, source problems cause a
+-   *         StringIndexOutOfBoundsException, and dest problems cause an
+-   *         ArrayIndexOutOfBoundsException)
+-   * @see System#arraycopy(Object, int, Object, int, int)
+-   */
+-  public void getChars(int srcOffset, int srcEnd,
+-		       char[] dst, int dstOffset)
+-  {
+-    if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
+-      throw new StringIndexOutOfBoundsException();
+-    VMSystem.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
+-  }
+-
+-  /**
+-   * 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
+-   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   */
+-  public 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;
+-  }
+-
+-  /**
+-   * 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 String#valueOf(Object)
+-   * @see #append(String)
+-   */
+-  public CPStringBuffer append(Object obj)
+-  {
+-    return append(String.valueOf(obj));
+-  }
+-
+-  /**
+-   * Append the <code>String</code> to this <code>StringBuffer</code>. If
+-   * str is null, the String "null" is appended.
+-   *
+-   * @param str the <code>String</code> to append
+-   * @return this <code>StringBuffer</code>
+-   */
+-  public CPStringBuffer append(String str)
+-  {
+-    if (str == null)
+-      str = "null";
+-    int len = str.count;
+-    ensureCapacity_unsynchronized(count + len);
+-    str.getChars(0, len, value, count);
+-    count += len;
+-    return this;
+-  }
+-
+-  /**
+-   * Append the <code>StringBuilder</code> value of the argument to this
+-   * <code>StringBuilder</code>. This behaves the same as
+-   * <code>append((Object) stringBuffer)</code>, except it is more efficient.
+-   *
+-   * @param stringBuffer the <code>StringBuilder</code> to convert and append
+-   * @return this <code>StringBuilder</code>
+-   * @see #append(Object)
+-   */
+-  public CPStringBuffer append(StringBuffer stringBuffer)
+-  {
+-    if (stringBuffer == null)
+-      return append("null");
+-    synchronized (stringBuffer)
+-      {
+-	int len = stringBuffer.count;
+-	ensureCapacity(count + len);
+-	VMSystem.arraycopy(stringBuffer.value, 0, value, count, len);
+-	count += len;
+-      }
+-    return this;
+-  }
+-
+-  /**
+-   * Append the <code>char</code> array to this <code>StringBuffer</code>.
+-   * This is similar (but more efficient) than
+-   * <code>append(new String(data))</code>, except in the case of null.
+-   *
+-   * @param data the <code>char[]</code> to append
+-   * @return this <code>StringBuffer</code>
+-   * @throws NullPointerException if <code>str</code> is <code>null</code>
+-   * @see #append(char[], int, int)
+-   */
+-  public CPStringBuffer append(char[] data)
+-  {
+-    return append(data, 0, data.length);
+-  }
+-
+-  /**
+-   * Append part of the <code>char</code> array to this
+-   * <code>StringBuffer</code>. This is similar (but more efficient) than
+-   * <code>append(new String(data, offset, count))</code>, except in the case
+-   * of null.
+-   *
+-   * @param data the <code>char[]</code> to append
+-   * @param offset the start location in <code>str</code>
+-   * @param count the number of characters to get from <code>str</code>
+-   * @return this <code>StringBuffer</code>
+-   * @throws NullPointerException if <code>str</code> is <code>null</code>
+-   * @throws IndexOutOfBoundsException if offset or count is out of range
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   */
+-  public CPStringBuffer append(char[] data, int offset, int count)
+-  {
+-    if (offset < 0 || count < 0 || offset > data.length - count)
+-      throw new StringIndexOutOfBoundsException();
+-    ensureCapacity_unsynchronized(this.count + count);
+-    VMSystem.arraycopy(data, offset, value, this.count, count);
+-    this.count += count;
+-    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 bool the <code>boolean</code> to convert and append
+-   * @return this <code>StringBuffer</code>
+-   * @see String#valueOf(boolean)
+-   */
+-  public CPStringBuffer append(boolean bool)
+-  {
+-    return append(bool ? "true" : "false");
+-  }
+-
+-  /**
+-   * Append the <code>char</code> to this <code>StringBuffer</code>.
+-   *
+-   * @param ch the <code>char</code> to append
+-   * @return this <code>StringBuffer</code>
+-   */
+-  public CPStringBuffer append(char ch)
+-  {
+-    ensureCapacity_unsynchronized(count + 1);
+-    value[count++] = ch;
+-    return this;
+-  }
+-
+-  /**
+-   * Append the characters in the <code>CharSequence</code> to this
+-   * buffer.
+-   *
+-   * @param seq the <code>CharSequence</code> providing the characters
+-   * @return this <code>StringBuffer</code>
+-   * @since 1.5
+-   */
+-  public CPStringBuffer append(CharSequence seq)
+-  {
+-    return append(seq, 0, seq.length());
+-  }
+-
+-  /**
+-   * Append some characters from the <code>CharSequence</code> to this
+-   * buffer.  If the argument is null, the four characters "null" are
+-   * appended.
+-   *
+-   * @param seq the <code>CharSequence</code> providing the characters
+-   * @param start the starting index
+-   * @param end one past the final index
+-   * @return this <code>StringBuffer</code>
+-   * @since 1.5
+-   */
+-  public CPStringBuffer append(CharSequence seq, int start, int end)
+-  {
+-    if (seq == null)
+-      return append("null");
+-    if (end - start > 0)
+-      {
+-	ensureCapacity_unsynchronized(count + end - start);
+-	for (; start < end; ++start)
+-	  value[count++] = seq.charAt(start);
+-      }
+-    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 String#valueOf(int)
+-   */
+-  // This is native in libgcj, for efficiency.
+-  public CPStringBuffer append(int inum)
+-  {
+-    return append(String.valueOf(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 String#valueOf(long)
+-   */
+-  public CPStringBuffer append(long lnum)
+-  {
+-    return append(Long.toString(lnum, 10));
+-  }
+-
+-  /**
+-   * 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 String#valueOf(float)
+-   */
+-  public CPStringBuffer append(float fnum)
+-  {
+-    return append(Float.toString(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 String#valueOf(double)
+-   */
+-  public CPStringBuffer append(double dnum)
+-  {
+-    return append(Double.toString(dnum));
+-  }
+-
+-  /**
+-   * Append the code point to this <code>StringBuffer</code>.
+-   * This is like #append(char), but will append two characters
+-   * if a supplementary code point is given.
+-   *
+-   * @param code the code point to append
+-   * @return this <code>StringBuffer</code>
+-   * @see Character#toChars(int, char[], int)
+-   * @since 1.5
+-   */
+-  public CPStringBuffer appendCodePoint(int code)
+-  {
+-    int len = Character.charCount(code);
+-    ensureCapacity_unsynchronized(count + len);
+-    Character.toChars(code, value, count);
+-    count += len;
+-    return this;
+-  }
+-
+-  /**
+-   * Delete characters from this <code>StringBuffer</code>.
+-   * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
+-   * harmless for end to be larger than length().
+-   *
+-   * @param start the first character to delete
+-   * @param end the index after the last character to delete
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+-   * @since 1.2
+-   */
+-  public CPStringBuffer delete(int start, int end)
+-  {
+-    if (start < 0 || start > count || start > end)
+-      throw new StringIndexOutOfBoundsException(start);
+-    if (end > count)
+-      end = count;
+-    ensureCapacity_unsynchronized(count);
+-    if (count - end != 0)
+-      VMSystem.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>
+-   * @throws StringIndexOutOfBoundsException if index is out of bounds
+-   * @since 1.2
+-   */
+-  public CPStringBuffer deleteCharAt(int index)
+-  {
+-    return delete(index, index + 1);
+-  }
+-
+-  /**
+-   * 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>
+-   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+-   * @throws NullPointerException if str is null
+-   * @since 1.2
+-   */
+-  public CPStringBuffer replace(int start, int end, String str)
+-  {
+-    if (start < 0 || start > count || start > end)
+-      throw new StringIndexOutOfBoundsException(start);
+-
+-    int len = str.count;
+-    // 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)
+-      VMSystem.arraycopy(value, end, value, end + delta, count - end);
+-
+-    str.getChars(0, len, value, start);
+-    count += delta;
+-    return this;
+-  }
+-
+-  /**
+-   * Insert a subarray of the <code>char[]</code> argument into this
+-   * <code>StringBuffer</code>.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @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>
+-   * @throws NullPointerException if <code>str</code> is <code>null</code>
+-   * @throws StringIndexOutOfBoundsException if any index is out of bounds
+-   * @since 1.2
+-   */
+-  public CPStringBuffer insert(int offset, char[] str, int str_offset, int len)
+-  {
+-    if (offset < 0 || offset > count || len < 0
+-        || str_offset < 0 || str_offset > str.length - len)
+-      throw new StringIndexOutOfBoundsException();
+-    ensureCapacity_unsynchronized(count + len);
+-    VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
+-    VMSystem.arraycopy(str, str_offset, value, offset, len);
+-    count += len;
+-    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 in this buffer
+-   * @param obj the <code>Object</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @exception StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(Object)
+-   */
+-  public CPStringBuffer insert(int offset, Object obj)
+-  {
+-    return insert(offset, obj == null ? "null" : obj.toString());
+-  }
+-
+-  /**
+-   * Insert the <code>String</code> argument into this
+-   * <code>StringBuffer</code>. If str is null, the String "null" is used
+-   * instead.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param str the <code>String</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   */
+-  public CPStringBuffer insert(int offset, String str)
+-  {
+-    if (offset < 0 || offset > count)
+-      throw new StringIndexOutOfBoundsException(offset);
+-    if (str == null)
+-      str = "null";
+-    int len = str.count;
+-    ensureCapacity_unsynchronized(count + len);
+-    VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
+-    str.getChars(0, len, value, offset);
+-    count += len;
+-    return this;
+-  }
+-
+-  /**
+-   * Insert the <code>CharSequence</code> argument into this
+-   * <code>StringBuffer</code>.  If the sequence is null, the String
+-   * "null" is used instead.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param sequence the <code>CharSequence</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws IndexOutOfBoundsException if offset is out of bounds
+-   * @since 1.5
+-   */
+-  public CPStringBuffer insert(int offset, CharSequence sequence)
+-  {
+-    if (sequence == null)
+-      sequence = "null";
+-    return insert(offset, sequence, 0, sequence.length());
+-  }
+-
+-  /**
+-   * Insert a subsequence of the <code>CharSequence</code> argument into this
+-   * <code>StringBuffer</code>.  If the sequence is null, the String
+-   * "null" is used instead.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param sequence the <code>CharSequence</code> to insert
+-   * @param start the starting index of the subsequence
+-   * @param end one past the ending index of the subsequence
+-   * @return this <code>StringBuffer</code>
+-   * @throws IndexOutOfBoundsException if offset, start,
+-   * or end are out of bounds
+-   * @since 1.5
+-   */
+-  public CPStringBuffer insert(int offset, CharSequence sequence, int start, int end)
+-  {
+-    if (sequence == null)
+-      sequence = "null";
+-    if (start < 0 || end < 0 || start > end || end > sequence.length())
+-      throw new IndexOutOfBoundsException();
+-    int len = end - start;
+-    ensureCapacity_unsynchronized(count + len);
+-    VMSystem.arraycopy(value, offset, value, offset + len, count - offset);
+-    for (int i = start; i < end; ++i)
+-      value[offset++] = sequence.charAt(i);
+-    count += len;
+-    return this;
+-  }
+-
+-  /**
+-   * Insert the <code>char[]</code> argument into this
+-   * <code>StringBuffer</code>.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param data the <code>char[]</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws NullPointerException if <code>data</code> is <code>null</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see #insert(int, char[], int, int)
+-   */
+-  public CPStringBuffer insert(int offset, char[] data)
+-  {
+-    return insert(offset, data, 0, data.length);
+-  }
+-
+-  /**
+-   * 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 in this buffer
+-   * @param bool the <code>boolean</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(boolean)
+-   */
+-  public CPStringBuffer 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 in this buffer
+-   * @param ch the <code>char</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   */
+-  public CPStringBuffer insert(int offset, char ch)
+-  {
+-    if (offset < 0 || offset > count)
+-      throw new StringIndexOutOfBoundsException(offset);
+-    ensureCapacity_unsynchronized(count + 1);
+-    VMSystem.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 in this buffer
+-   * @param inum the <code>int</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(int)
+-   */
+-  public CPStringBuffer 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 in this buffer
+-   * @param lnum the <code>long</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(long)
+-   */
+-  public CPStringBuffer insert(int offset, long lnum)
+-  {
+-    return insert(offset, Long.toString(lnum, 10));
+-  }
+-
+-  /**
+-   * 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 in this buffer
+-   * @param fnum the <code>float</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(float)
+-   */
+-  public CPStringBuffer insert(int offset, float fnum)
+-  {
+-    return insert(offset, Float.toString(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 in this buffer
+-   * @param dnum the <code>double</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(double)
+-   */
+-  public CPStringBuffer insert(int offset, double dnum)
+-  {
+-    return insert(offset, Double.toString(dnum));
+-  }
+-
+-  /**
+-   * Finds the first instance of a substring in this StringBuilder.
+-   *
+-   * @param str String to find
+-   * @return location (base 0) of the String, or -1 if not found
+-   * @throws NullPointerException if str is null
+-   * @see #indexOf(String, int)
+-   */
+-  public int indexOf(String str)
+-  {
+-    return indexOf(str, 0);
+-  }
+-
+-  /**
+-   * Finds the first instance of a String in this StringBuffer, 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, or the substring is not found, -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
+-   * @since 1.4
+-   */
+-  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))
+-        return fromIndex;
+-    return -1;
+-  }
+-
+-  /**
+-   * Finds the last instance of a substring in this StringBuffer.
+-   *
+-   * @param str String to find
+-   * @return location (base 0) of the String, or -1 if not found
+-   * @throws NullPointerException if str is null
+-   * @see #lastIndexOf(String, int)
+-   * @since 1.4
+-   */
+-  public int lastIndexOf(String str)
+-  {
+-    return lastIndexOf(str, count - str.count);
+-  }
+-
+-  /**
+-   * Finds the last instance of a String in this StringBuffer, 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, or the substring is not found, -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
+-   * @since 1.4
+-   */
+-  public int lastIndexOf(String str, int fromIndex)
+-  {
+-    fromIndex = Math.min(fromIndex, count - str.count);
+-    for ( ; fromIndex >= 0; fromIndex--)
+-      if (regionMatches(fromIndex, str))
+-        return fromIndex;
+-    return -1;
+-  }
+-
+-  /**
+-   * Reverse the characters in this StringBuffer. The same sequence of
+-   * characters exists, but in the reverse index ordering.
+-   *
+-   * @return this <code>StringBuffer</code>
+-   */
+-  public CPStringBuffer reverse()
+-  {
+-    // Call ensureCapacity to enforce copy-on-write.
+-    ensureCapacity_unsynchronized(count);
+-    for (int i = count >> 1, j = count - i; --i >= 0; ++j)
+-      {
+-        char c = value[i];
+-        value[i] = value[j];
+-        value[j] = c;
+-      }
+-    return this;
+-  }
+-
+-  /**
+-   * This may reduce the amount of memory used by the StringBuffer,
+-   * by resizing the internal array to remove unused space.  However,
+-   * this method is not required to resize, so this behavior cannot
+-   * be relied upon.
+-   * @since 1.5
+-   */
+-  public void trimToSize()
+-  {
+-    int wouldSave = value.length - count;
+-    // Some random heuristics: if we save less than 20 characters, who
+-    // cares.
+-    if (wouldSave < 20)
+-      return;
+-    // If we save more than 200 characters, shrink.
+-    // If we save more than 1/4 of the buffer, shrink.
+-    if (wouldSave > 200 || wouldSave * 4 > value.length)
+-      {
+-	char[] newValue = new char[count];
+-	VMSystem.arraycopy(value, 0, newValue, 0, count);
+-	value = newValue;
+-      }
+-  }
+-
+-  /**
+-   * Return the number of code points between two indices in the
+-   * <code>StringBuffer</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 int codePointCount(int start, int end)
+-  {
+-    if (start < 0 || end >= count || start > end)
+-      throw new StringIndexOutOfBoundsException();
+-
+-    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;
+-  }
+-
+-  /**
+-   * Starting at the given index, this counts forward by the indicated
+-   * number of code points, and then returns the resulting index.  An
+-   * unpaired surrogate counts as a single code point for this
+-   * purpose.
+-   *
+-   * @param start the starting index
+-   * @param codePoints the number of code points
+-   * @return the resulting index
+-   * @since 1.5
+-   */
+-  public int offsetByCodePoints(int start, int codePoints)
+-  {
+-    while (codePoints > 0)
+-      {
+-	char base = value[start];
+-	if (base < Character.MIN_HIGH_SURROGATE
+-	    || base > Character.MAX_HIGH_SURROGATE
+-	    || start == count
+-	    || value[start + 1] < Character.MIN_LOW_SURROGATE
+-	    || value[start + 1] > Character.MAX_LOW_SURROGATE)
+-	  {
+-	    // Nothing.
+-	  }
+-	else
+-	  {
+-	    // Surrogate pair.
+-	    ++start;
+-	  }
+-	++start;
+-	--codePoints;
+-      }
+-    return start;
+-  }
+-
+-  /**
+-   * Increase the capacity of this <code>StringBuilder</code>. This will
+-   * ensure that an expensive growing operation will not occur until
+-   * <code>minimumCapacity</code> is reached. The buffer is grown to the
+-   * larger of <code>minimumCapacity</code> and
+-   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+-   *
+-   * @param minimumCapacity the new capacity
+-   * @see #capacity()
+-   */
+-  protected void ensureCapacity_unsynchronized(int minimumCapacity)
+-  {
+-    if (minimumCapacity > value.length)
+-      {
+-        int max = value.length * 2 + 2;
+-        minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
+-        char[] nb = new char[minimumCapacity];
+-        VMSystem.arraycopy(value, 0, nb, 0, count);
+-        value = nb;
+-      }
+-  }
+-
+-  /**
+-   * Predicate which determines if a substring of this matches another String
+-   * starting at a specified offset for each String and continuing for a
+-   * specified length. This is more efficient than creating a String to call
+-   * indexOf on.
+-   *
+-   * @param toffset index to start comparison at for this String
+-   * @param other non-null String to compare to region of this
+-   * @return true if regions match, false otherwise
+-   * @see #indexOf(String, int)
+-   * @see #lastIndexOf(String, int)
+-   * @see String#regionMatches(boolean, int, String, int, int)
+-   */
+-  private boolean regionMatches(int toffset, String other)
+-  {
+-    int len = other.count;
+-    int index = other.offset;
+-    while (--len >= 0)
+-      if (value[toffset++] != other.value[index++])
+-        return false;
+-    return true;
+-  }
+-
+-  /**
+-   * Get the length of the <code>String</code> this <code>StringBuilder</code>
+-   * would create. Not to be confused with the <em>capacity</em> of the
+-   * <code>StringBuilder</code>.
+-   *
+-   * @return the length of this <code>StringBuilder</code>
+-   * @see #capacity()
+-   * @see #setLength(int)
+-   */
+-  public int length()
+-  {
+-    return count;
+-  }
+-
+-  /**
+-   * Creates a substring of this StringBuilder, starting at a specified index
+-   * and ending at one character before a specified index. This is implemented
+-   * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
+-   * the CharSequence interface.
+-   *
+-   * @param beginIndex index to start at (inclusive, base 0)
+-   * @param endIndex index to end at (exclusive)
+-   * @return new String which is a substring of this StringBuilder
+-   * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
+-   *         bounds
+-   * @see #substring(int, int)
+-   */
+-  public CharSequence subSequence(int beginIndex, int endIndex)
+-  {
+-    return substring(beginIndex, endIndex);
+-  }
+-
+-  /**
+-   * Creates a substring of this StringBuilder, starting at a specified index
+-   * and ending at one character before a specified index.
+-   *
+-   * @param beginIndex index to start at (inclusive, base 0)
+-   * @param endIndex index to end at (exclusive)
+-   * @return new String which is a substring of this StringBuilder
+-   * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
+-   *         of bounds
+-   */
+-  public String substring(int beginIndex, int endIndex)
+-  {
+-    int len = endIndex - beginIndex;
+-    if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
+-      throw new StringIndexOutOfBoundsException();
+-    if (len == 0)
+-      return "";
+-    try
+-      {
+-	return cons.newInstance(value, beginIndex, len, true);
+-      }
+-    catch (InstantiationException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
+-      }
+-    catch (IllegalAccessException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not access no-copy String constructor").initCause(e);
+-      }
+-    catch (InvocationTargetException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Error calling no-copy String constructor").initCause(e);
+-      }
+-  }
+-
+-  /**
+-   * Convert this <code>StringBuilder</code> to a <code>String</code>. The
+-   * String is composed of the characters currently in this StringBuilder. Note
+-   * that the result is not a copy, so future modifications to this buffer
+-   * do affect the String.
+-   *
+-   * @return the characters in this StringBuilder
+-   */
+-  public String toString()
+-  {
+-    try
+-      {
+-	return cons.newInstance(value, 0, count, true);
+-      }
+-    catch (InstantiationException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
+-      }
+-    catch (IllegalAccessException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not access no-copy String constructor").initCause(e);
+-      }
+-    catch (InvocationTargetException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Error calling no-copy String constructor").initCause(e);
+-      }
+-  }
+-
+-}
+Index: gnu/classpath/CPStringBuilder.java
+===================================================================
+RCS file: gnu/classpath/CPStringBuilder.java
+diff -N gnu/classpath/CPStringBuilder.java
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ gnu/classpath/CPStringBuilder.java	1 Mar 2008 09:12:09 -0000
+@@ -0,0 +1,1156 @@
++/* ClasspathStringBuffer.java -- Growable strings without locking or copying
++   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
++   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 gnu.classpath;
++
++import java.lang.reflect.Constructor;
++import java.lang.reflect.InvocationTargetException;
++
++import java.io.Serializable;
++
++/**
++ * This class is based on java.lang.AbstractStringBuffer but
++ * without the copying of the string by toString.
++ * If you modify this, please consider also modifying that code.
++ * This code is not thread-safe; limit its use to internal use within
++ * methods.
++ */
++public final class CPStringBuilder
++  implements Serializable, CharSequence, Appendable
++{
++
++  /**
++   * Index of next available character (and thus the size of the current
++   * string contents).  Note that this has permissions set this way so that
++   * String can get the value.
++   *
++   * @serial the number of characters in the buffer
++   */
++  int count;
++
++  /**
++   * The buffer.  Note that this has permissions set this way so that String
++   * can get the value.
++   *
++   * @serial the buffer
++   */
++  char[] value;
++
++  /**
++   * The package-private constructor for String objects without copying.
++   */
++  private static final Constructor<String> cons;
++
++  /**
++   * The default capacity of a buffer.
++   */
++  private static final int DEFAULT_CAPACITY = 16;
++
++  static
++  {
++    try
++      {
++	cons = String.class.getDeclaredConstructor(char[].class, Integer.TYPE,
++						   Integer.TYPE, Boolean.TYPE);
++      }
++    catch (NoSuchMethodException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not get no-copy String constructor").initCause(e);
++      }
++  }
++
++  /**
++   * Create a new CPStringBuilder with default capacity 16.
++   */
++  public CPStringBuilder()
++  {
++    this(DEFAULT_CAPACITY);
++  }
++
++  /**
++   * Create an empty <code>StringBuffer</code> with the specified initial
++   * capacity.
++   *
++   * @param capacity the initial capacity
++   * @throws NegativeArraySizeException if capacity is negative
++   */
++  public CPStringBuilder(int capacity)
++  {
++    value = new char[capacity];
++  }
++
++  /**
++   * 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 convert
++   * @throws NullPointerException if str is null
++   */
++  public CPStringBuilder(String str)
++  {
++    count = str.length();
++    value = new char[count + DEFAULT_CAPACITY];
++    str.getChars(0, count, value, 0);
++  }
++
++  /**
++   * Create a new <code>StringBuffer</code> with the characters in the
++   * specified <code>CharSequence</code>. Initial capacity will be the
++   * length of the sequence plus 16; if the sequence reports a length
++   * less than or equal to 0, then the initial capacity will be 16.
++   *
++   * @param seq the initializing <code>CharSequence</code>
++   * @throws NullPointerException if str is null
++   * @since 1.5
++   */
++  public CPStringBuilder(CharSequence seq)
++  {
++    int len = seq.length();
++    count = len <= 0 ? 0 : len;
++    value = new char[count + DEFAULT_CAPACITY];
++    for (int i = 0; i < len; ++i)
++      value[i] = seq.charAt(i);
++  }
++
++  /**
++   * 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. The buffer is grown to the
++   * larger of <code>minimumCapacity</code> and
++   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
++   *
++   * @param minimumCapacity the new capacity
++   * @see #capacity()
++   */
++  public void ensureCapacity(int minimumCapacity)
++  {
++    ensureCapacity_unsynchronized(minimumCapacity);
++  }
++
++  /**
++   * Set the length of this StringBuffer. If the new length is greater than
++   * the current length, all the new characters are set to '\0'. If the new
++   * length is less than the current length, the first <code>newLength</code>
++   * characters of the old array will be preserved, and the remaining
++   * characters are truncated.
++   *
++   * @param newLength the new length
++   * @throws IndexOutOfBoundsException if the new length is negative
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   * @see #length()
++   */
++  public void setLength(int newLength)
++  {
++    if (newLength < 0)
++      throw new StringIndexOutOfBoundsException(newLength);
++
++    int valueLength = value.length;
++
++    /* Always call ensureCapacity_unsynchronized in order to preserve
++       copy-on-write semantics.  */
++    ensureCapacity_unsynchronized(newLength);
++
++    if (newLength < valueLength)
++      {
++        /* If the StringBuffer's value just grew, then we know that
++           value is newly allocated and the region between count and
++           newLength is filled with '\0'.  */
++	count = newLength;
++      }
++    else
++      {
++	/* The StringBuffer's value doesn't need to grow.  However,
++	   we should clear out any cruft that may exist.  */
++	while (count < newLength)
++          value[count++] = '\0';
++      }
++  }
++
++  /**
++   * 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
++   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public char charAt(int index)
++  {
++    if (index < 0 || index >= count)
++      throw new StringIndexOutOfBoundsException(index);
++    return value[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 int codePointAt(int index)
++  {
++    return Character.codePointAt(value, index, count);
++  }
++
++  /**
++   * 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()
++   * @since 1.5
++   */
++  public int codePointBefore(int index)
++  {
++    // Character.codePointBefore() doesn't perform this check.  We
++    // could use the CharSequence overload, but this is just as easy.
++    if (index >= count)
++      throw new IndexOutOfBoundsException();
++    return Character.codePointBefore(value, index, 1);
++  }
++
++  /**
++   * Get the specified array of characters. <code>srcOffset - srcEnd</code>
++   * characters will be copied into the array you pass in.
++   *
++   * @param srcOffset the index to start copying from (inclusive)
++   * @param srcEnd the index to stop copying from (exclusive)
++   * @param dst the array to copy into
++   * @param dstOffset the index to start copying into
++   * @throws NullPointerException if dst is null
++   * @throws IndexOutOfBoundsException if any source or target indices are
++   *         out of range (while unspecified, source problems cause a
++   *         StringIndexOutOfBoundsException, and dest problems cause an
++   *         ArrayIndexOutOfBoundsException)
++   * @see System#arraycopy(Object, int, Object, int, int)
++   */
++  public void getChars(int srcOffset, int srcEnd,
++		       char[] dst, int dstOffset)
++  {
++    if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
++      throw new StringIndexOutOfBoundsException();
++    System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
++  }
++
++  /**
++   * 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
++   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public 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;
++  }
++
++  /**
++   * 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 String#valueOf(Object)
++   * @see #append(String)
++   */
++  public CPStringBuilder append(Object obj)
++  {
++    return append(String.valueOf(obj));
++  }
++
++  /**
++   * Append the <code>String</code> to this <code>StringBuffer</code>. If
++   * str is null, the String "null" is appended.
++   *
++   * @param str the <code>String</code> to append
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuilder 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>StringBuilder</code> value of the argument to this
++   * <code>StringBuilder</code>. This behaves the same as
++   * <code>append((Object) stringBuffer)</code>, except it is more efficient.
++   *
++   * @param stringBuffer the <code>StringBuilder</code> to convert and append
++   * @return this <code>StringBuilder</code>
++   * @see #append(Object)
++   */
++  public CPStringBuilder append(StringBuffer stringBuffer)
++  {
++    if (stringBuffer == null)
++      return append("null");
++    synchronized (stringBuffer)
++      {
++	int len = stringBuffer.length();
++	ensureCapacity(count + len);
++	stringBuffer.getChars(0, len, value, count);
++	count += len;
++      }
++    return this;
++  }
++
++  /**
++   * Append the <code>char</code> array to this <code>StringBuffer</code>.
++   * This is similar (but more efficient) than
++   * <code>append(new String(data))</code>, except in the case of null.
++   *
++   * @param data the <code>char[]</code> to append
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @see #append(char[], int, int)
++   */
++  public CPStringBuilder append(char[] data)
++  {
++    return append(data, 0, data.length);
++  }
++
++  /**
++   * Append part of the <code>char</code> array to this
++   * <code>StringBuffer</code>. This is similar (but more efficient) than
++   * <code>append(new String(data, offset, count))</code>, except in the case
++   * of null.
++   *
++   * @param data the <code>char[]</code> to append
++   * @param offset the start location in <code>str</code>
++   * @param count the number of characters to get from <code>str</code>
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @throws IndexOutOfBoundsException if offset or count is out of range
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public CPStringBuilder append(char[] data, int offset, int count)
++  {
++    if (offset < 0 || count < 0 || offset > data.length - count)
++      throw new StringIndexOutOfBoundsException();
++    ensureCapacity_unsynchronized(this.count + count);
++    System.arraycopy(data, offset, value, this.count, count);
++    this.count += count;
++    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 bool the <code>boolean</code> to convert and append
++   * @return this <code>StringBuffer</code>
++   * @see String#valueOf(boolean)
++   */
++  public CPStringBuilder append(boolean bool)
++  {
++    return append(bool ? "true" : "false");
++  }
++
++  /**
++   * Append the <code>char</code> to this <code>StringBuffer</code>.
++   *
++   * @param ch the <code>char</code> to append
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuilder append(char ch)
++  {
++    ensureCapacity_unsynchronized(count + 1);
++    value[count++] = ch;
++    return this;
++  }
++
++  /**
++   * Append the characters in the <code>CharSequence</code> to this
++   * buffer.
++   *
++   * @param seq the <code>CharSequence</code> providing the characters
++   * @return this <code>StringBuffer</code>
++   * @since 1.5
++   */
++  public CPStringBuilder append(CharSequence seq)
++  {
++    return append(seq, 0, seq.length());
++  }
++
++  /**
++   * Append some characters from the <code>CharSequence</code> to this
++   * buffer.  If the argument is null, the four characters "null" are
++   * appended.
++   *
++   * @param seq the <code>CharSequence</code> providing the characters
++   * @param start the starting index
++   * @param end one past the final index
++   * @return this <code>StringBuffer</code>
++   * @since 1.5
++   */
++  public CPStringBuilder append(CharSequence seq, int start, int end)
++  {
++    if (seq == null)
++      return append("null");
++    if (end - start > 0)
++      {
++	ensureCapacity_unsynchronized(count + end - start);
++	for (; start < end; ++start)
++	  value[count++] = seq.charAt(start);
++      }
++    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 String#valueOf(int)
++   */
++  // This is native in libgcj, for efficiency.
++  public CPStringBuilder append(int inum)
++  {
++    return append(String.valueOf(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 String#valueOf(long)
++   */
++  public CPStringBuilder append(long lnum)
++  {
++    return append(Long.toString(lnum, 10));
++  }
++
++  /**
++   * 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 String#valueOf(float)
++   */
++  public CPStringBuilder append(float fnum)
++  {
++    return append(Float.toString(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 String#valueOf(double)
++   */
++  public CPStringBuilder append(double dnum)
++  {
++    return append(Double.toString(dnum));
++  }
++
++  /**
++   * Append the code point to this <code>StringBuffer</code>.
++   * This is like #append(char), but will append two characters
++   * if a supplementary code point is given.
++   *
++   * @param code the code point to append
++   * @return this <code>StringBuffer</code>
++   * @see Character#toChars(int, char[], int)
++   * @since 1.5
++   */
++  public CPStringBuilder appendCodePoint(int code)
++  {
++    int len = Character.charCount(code);
++    ensureCapacity_unsynchronized(count + len);
++    Character.toChars(code, value, count);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Delete characters from this <code>StringBuffer</code>.
++   * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
++   * harmless for end to be larger than length().
++   *
++   * @param start the first character to delete
++   * @param end the index after the last character to delete
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
++   * @since 1.2
++   */
++  public CPStringBuilder delete(int start, int end)
++  {
++    if (start < 0 || start > count || start > end)
++      throw new StringIndexOutOfBoundsException(start);
++    if (end > count)
++      end = count;
++    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>
++   * @throws StringIndexOutOfBoundsException if index is out of bounds
++   * @since 1.2
++   */
++  public CPStringBuilder deleteCharAt(int index)
++  {
++    return delete(index, index + 1);
++  }
++
++  /**
++   * 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>
++   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
++   * @throws NullPointerException if str is null
++   * @since 1.2
++   */
++  public CPStringBuilder 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;
++  }
++
++  /**
++   * Insert a subarray of the <code>char[]</code> argument into this
++   * <code>StringBuffer</code>.
++   *
++   * @param offset the place to insert in this buffer
++   * @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>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @throws StringIndexOutOfBoundsException if any index is out of bounds
++   * @since 1.2
++   */
++  public CPStringBuilder insert(int offset, char[] str, int str_offset, int len)
++  {
++    if (offset < 0 || offset > count || len < 0
++        || str_offset < 0 || str_offset > str.length - len)
++      throw new StringIndexOutOfBoundsException();
++    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;
++  }
++
++  /**
++   * 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 in this buffer
++   * @param obj the <code>Object</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @exception StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(Object)
++   */
++  public CPStringBuilder insert(int offset, Object obj)
++  {
++    return insert(offset, obj == null ? "null" : obj.toString());
++  }
++
++  /**
++   * Insert the <code>String</code> argument into this
++   * <code>StringBuffer</code>. If str is null, the String "null" is used
++   * instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param str the <code>String</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   */
++  public CPStringBuilder insert(int offset, String str)
++  {
++    if (offset < 0 || offset > count)
++      throw new StringIndexOutOfBoundsException(offset);
++    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>CharSequence</code> argument into this
++   * <code>StringBuffer</code>.  If the sequence is null, the String
++   * "null" is used instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param sequence the <code>CharSequence</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws IndexOutOfBoundsException if offset is out of bounds
++   * @since 1.5
++   */
++  public CPStringBuilder insert(int offset, CharSequence sequence)
++  {
++    if (sequence == null)
++      sequence = "null";
++    return insert(offset, sequence, 0, sequence.length());
++  }
++
++  /**
++   * Insert a subsequence of the <code>CharSequence</code> argument into this
++   * <code>StringBuffer</code>.  If the sequence is null, the String
++   * "null" is used instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param sequence the <code>CharSequence</code> to insert
++   * @param start the starting index of the subsequence
++   * @param end one past the ending index of the subsequence
++   * @return this <code>StringBuffer</code>
++   * @throws IndexOutOfBoundsException if offset, start,
++   * or end are out of bounds
++   * @since 1.5
++   */
++  public CPStringBuilder insert(int offset, CharSequence sequence, int start, int end)
++  {
++    if (sequence == null)
++      sequence = "null";
++    if (start < 0 || end < 0 || start > end || end > sequence.length())
++      throw new IndexOutOfBoundsException();
++    int len = end - start;
++    ensureCapacity_unsynchronized(count + len);
++    System.arraycopy(value, offset, value, offset + len, count - offset);
++    for (int i = start; i < end; ++i)
++      value[offset++] = sequence.charAt(i);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Insert the <code>char[]</code> argument into this
++   * <code>StringBuffer</code>.
++   *
++   * @param offset the place to insert in this buffer
++   * @param data the <code>char[]</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>data</code> is <code>null</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see #insert(int, char[], int, int)
++   */
++  public CPStringBuilder insert(int offset, char[] data)
++  {
++    return insert(offset, data, 0, data.length);
++  }
++
++  /**
++   * 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 in this buffer
++   * @param bool the <code>boolean</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(boolean)
++   */
++  public CPStringBuilder 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 in this buffer
++   * @param ch the <code>char</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   */
++  public CPStringBuilder 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 in this buffer
++   * @param inum the <code>int</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(int)
++   */
++  public CPStringBuilder 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 in this buffer
++   * @param lnum the <code>long</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(long)
++   */
++  public CPStringBuilder insert(int offset, long lnum)
++  {
++    return insert(offset, Long.toString(lnum, 10));
++  }
++
++  /**
++   * 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 in this buffer
++   * @param fnum the <code>float</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(float)
++   */
++  public CPStringBuilder insert(int offset, float fnum)
++  {
++    return insert(offset, Float.toString(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 in this buffer
++   * @param dnum the <code>double</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(double)
++   */
++  public CPStringBuilder insert(int offset, double dnum)
++  {
++    return insert(offset, Double.toString(dnum));
++  }
++
++  /**
++   * Finds the first instance of a substring in this StringBuilder.
++   *
++   * @param str String to find
++   * @return location (base 0) of the String, or -1 if not found
++   * @throws NullPointerException if str is null
++   * @see #indexOf(String, int)
++   */
++  public int indexOf(String str)
++  {
++    return indexOf(str, 0);
++  }
++
++  /**
++   * Finds the first instance of a String in this StringBuffer, 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, or the substring is not found, -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
++   * @since 1.4
++   */
++  public int indexOf(String str, int fromIndex)
++  {
++    if (fromIndex < 0)
++      fromIndex = 0;
++    int limit = count - str.length();
++    for ( ; fromIndex <= limit; fromIndex++)
++      if (regionMatches(fromIndex, str))
++        return fromIndex;
++    return -1;
++  }
++
++  /**
++   * Finds the last instance of a substring in this StringBuffer.
++   *
++   * @param str String to find
++   * @return location (base 0) of the String, or -1 if not found
++   * @throws NullPointerException if str is null
++   * @see #lastIndexOf(String, int)
++   * @since 1.4
++   */
++  public int lastIndexOf(String str)
++  {
++    return lastIndexOf(str, count - str.length());
++  }
++
++  /**
++   * Finds the last instance of a String in this StringBuffer, 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, or the substring is not found, -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
++   * @since 1.4
++   */
++  public int lastIndexOf(String str, int fromIndex)
++  {
++    fromIndex = Math.min(fromIndex, count - str.length());
++    for ( ; fromIndex >= 0; fromIndex--)
++      if (regionMatches(fromIndex, str))
++        return fromIndex;
++    return -1;
++  }
++
++  /**
++   * Reverse the characters in this StringBuffer. The same sequence of
++   * characters exists, but in the reverse index ordering.
++   *
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuilder reverse()
++  {
++    // Call ensureCapacity to enforce copy-on-write.
++    ensureCapacity_unsynchronized(count);
++    for (int i = count >> 1, j = count - i; --i >= 0; ++j)
++      {
++        char c = value[i];
++        value[i] = value[j];
++        value[j] = c;
++      }
++    return this;
++  }
++
++  /**
++   * This may reduce the amount of memory used by the StringBuffer,
++   * by resizing the internal array to remove unused space.  However,
++   * this method is not required to resize, so this behavior cannot
++   * be relied upon.
++   * @since 1.5
++   */
++  public void trimToSize()
++  {
++    int wouldSave = value.length - count;
++    // Some random heuristics: if we save less than 20 characters, who
++    // cares.
++    if (wouldSave < 20)
++      return;
++    // If we save more than 200 characters, shrink.
++    // If we save more than 1/4 of the buffer, shrink.
++    if (wouldSave > 200 || wouldSave * 4 > value.length)
++      {
++	char[] newValue = new char[count];
++	System.arraycopy(value, 0, newValue, 0, count);
++	value = newValue;
++      }
++  }
++
++  /**
++   * Return the number of code points between two indices in the
++   * <code>StringBuffer</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 int codePointCount(int start, int end)
++  {
++    if (start < 0 || end >= count || start > end)
++      throw new StringIndexOutOfBoundsException();
++
++    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;
++  }
++
++  /**
++   * Starting at the given index, this counts forward by the indicated
++   * number of code points, and then returns the resulting index.  An
++   * unpaired surrogate counts as a single code point for this
++   * purpose.
++   *
++   * @param start the starting index
++   * @param codePoints the number of code points
++   * @return the resulting index
++   * @since 1.5
++   */
++  public int offsetByCodePoints(int start, int codePoints)
++  {
++    while (codePoints > 0)
++      {
++	char base = value[start];
++	if (base < Character.MIN_HIGH_SURROGATE
++	    || base > Character.MAX_HIGH_SURROGATE
++	    || start == count
++	    || value[start + 1] < Character.MIN_LOW_SURROGATE
++	    || value[start + 1] > Character.MAX_LOW_SURROGATE)
++	  {
++	    // Nothing.
++	  }
++	else
++	  {
++	    // Surrogate pair.
++	    ++start;
++	  }
++	++start;
++	--codePoints;
++      }
++    return start;
++  }
++
++  /**
++   * Increase the capacity of this <code>StringBuilder</code>. This will
++   * ensure that an expensive growing operation will not occur until
++   * <code>minimumCapacity</code> is reached. The buffer is grown to the
++   * larger of <code>minimumCapacity</code> and
++   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
++   *
++   * @param minimumCapacity the new capacity
++   * @see #capacity()
++   */
++  protected void ensureCapacity_unsynchronized(int minimumCapacity)
++  {
++    if (minimumCapacity > value.length)
++      {
++        int max = value.length * 2 + 2;
++        minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
++        char[] nb = new char[minimumCapacity];
++        System.arraycopy(value, 0, nb, 0, count);
++        value = nb;
++      }
++  }
++
++  /**
++   * Predicate which determines if a substring of this matches another String
++   * starting at a specified offset for each String and continuing for a
++   * specified length. This is more efficient than creating a String to call
++   * indexOf on.
++   *
++   * @param toffset index to start comparison at for this String
++   * @param other non-null String to compare to region of this
++   * @return true if regions match, false otherwise
++   * @see #indexOf(String, int)
++   * @see #lastIndexOf(String, int)
++   * @see String#regionMatches(boolean, int, String, int, int)
++   */
++  private boolean regionMatches(int toffset, String other)
++  {
++    return new String().regionMatches(toffset, other, 0, other.length());
++  }
++
++  /**
++   * Get the length of the <code>String</code> this <code>StringBuilder</code>
++   * would create. Not to be confused with the <em>capacity</em> of the
++   * <code>StringBuilder</code>.
++   *
++   * @return the length of this <code>StringBuilder</code>
++   * @see #capacity()
++   * @see #setLength(int)
++   */
++  public int length()
++  {
++    return count;
++  }
++
++  /**
++   * Creates a substring of this StringBuilder, starting at a specified index
++   * and ending at one character before a specified index. This is implemented
++   * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
++   * the CharSequence interface.
++   *
++   * @param beginIndex index to start at (inclusive, base 0)
++   * @param endIndex index to end at (exclusive)
++   * @return new String which is a substring of this StringBuilder
++   * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
++   *         bounds
++   * @see #substring(int, int)
++   */
++  public CharSequence subSequence(int beginIndex, int endIndex)
++  {
++    return substring(beginIndex, endIndex);
++  }
++
++  /**
++   * Creates a substring of this StringBuilder, starting at a specified index
++   * and ending at one character before a specified index.
++   *
++   * @param beginIndex index to start at (inclusive, base 0)
++   * @param endIndex index to end at (exclusive)
++   * @return new String which is a substring of this StringBuilder
++   * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
++   *         of bounds
++   */
++  public String substring(int beginIndex, int endIndex)
++  {
++    int len = endIndex - beginIndex;
++    if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
++      throw new StringIndexOutOfBoundsException();
++    if (len == 0)
++      return "";
++    try
++      {
++	return cons.newInstance(value, beginIndex, len, true);
++      }
++    catch (InstantiationException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
++      }
++    catch (IllegalAccessException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not access no-copy String constructor").initCause(e);
++      }
++    catch (InvocationTargetException e)
++      {
++	throw (Error) 
++	  new InternalError("Error calling no-copy String constructor").initCause(e);
++      }
++  }
++
++  /**
++   * Convert this <code>StringBuilder</code> to a <code>String</code>. The
++   * String is composed of the characters currently in this StringBuilder. Note
++   * that the result is not a copy, so future modifications to this buffer
++   * do affect the String.
++   *
++   * @return the characters in this StringBuilder
++   */
++  public String toString()
++  {
++    try
++      {
++	return cons.newInstance(value, 0, count, true);
++      }
++    catch (InstantiationException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
++      }
++    catch (IllegalAccessException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not access no-copy String constructor").initCause(e);
++      }
++    catch (InvocationTargetException e)
++      {
++	throw (Error) 
++	  new InternalError("Error calling no-copy String constructor").initCause(e);
++      }
++  }
++
++}
+Index: java/lang/reflect/Modifier.java
+===================================================================
+RCS file: /sources/classpath/classpath/java/lang/reflect/Modifier.java,v
+retrieving revision 1.12
+diff -u -3 -p -u -r1.12 Modifier.java
+--- java/lang/reflect/Modifier.java	22 Apr 2006 21:52:18 -0000	1.12
++++ java/lang/reflect/Modifier.java	1 Mar 2008 09:12:13 -0000
+@@ -1,5 +1,5 @@
+ /* java.lang.reflect.Modifier
+-   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
++   Copyright (C) 1998, 1999, 2001, 2002, 2005, 2008  Free Software Foundation, Inc.
+ 
+ This file is part of GNU Classpath.
+ 
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
++import gnu.classpath.CPStringBuilder;
++
+ /**
+  * Modifier is a helper class with static methods to determine whether an
+  * int returned from getModifiers() represents static, public, protected,
+@@ -308,28 +310,16 @@ public class Modifier
+    */
+   public static String toString(int mod)
+   {
+-    return toString(mod, new StringBuilder()).toString();
+-  }
+-
+-  /**
+-   * Package helper method that can take a StringBuilder.
+-   * @param mod the modifier
+-   * @param r the StringBuilder to which the String representation is appended
+-   * @return r, with information appended
+-   */
+-  static StringBuilder toString(int mod, StringBuilder r)
+-  {
+-    r.append(toString(mod, new StringBuffer()));
+-    return r;
++    return toString(mod, new CPStringBuilder()).toString();
+   }
+ 
+   /**
+-   * Package helper method that can take a StringBuffer.
++   * Package helper method that can take a CPStringBuilder.
+    * @param mod the modifier
+-   * @param r the StringBuffer to which the String representation is appended
++   * @param r the CPStringBuilder to which the String representation is appended
+    * @return r, with information appended
+    */
+-  static StringBuffer toString(int mod, StringBuffer r)
++  static CPStringBuilder toString(int mod, CPStringBuilder r)
+   {
+     if (isPublic(mod))
+       r.append("public ");
+Index: vm/reference/java/lang/reflect/Constructor.java
+===================================================================
+RCS file: /sources/classpath/classpath/vm/reference/java/lang/reflect/Constructor.java,v
+retrieving revision 1.22
+diff -u -3 -p -u -r1.22 Constructor.java
+--- vm/reference/java/lang/reflect/Constructor.java	18 Feb 2008 00:06:09 -0000	1.22
++++ vm/reference/java/lang/reflect/Constructor.java	1 Mar 2008 09:12:25 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
++import gnu.classpath.CPStringBuilder;
++
+ import gnu.java.lang.ClassHelper;
+ 
+ import gnu.java.lang.reflect.MethodSignatureParser;
+@@ -224,7 +226,7 @@ public final class Constructor<T>
+   public String toString()
+   {
+     // 128 is a reasonable buffer initial size for constructor
+-    StringBuilder sb = new StringBuilder(128);
++    CPStringBuilder sb = new CPStringBuilder(128);
+     Modifier.toString(getModifiers(), sb).append(' ');
+     sb.append(getDeclaringClass().getName()).append('(');
+     Class[] c = getParameterTypes();
+@@ -246,7 +248,7 @@ public final class Constructor<T>
+   }
+ 
+   static <X extends GenericDeclaration>
+-  void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs)
++  void addTypeParameters(CPStringBuilder sb, TypeVariable<X>[] typeArgs)
+   {
+     if (typeArgs.length == 0)
+       return;
+@@ -262,7 +264,7 @@ public final class Constructor<T>
+ 
+   public String toGenericString()
+   {
+-    StringBuilder sb = new StringBuilder(128);
++    CPStringBuilder sb = new CPStringBuilder(128);
+     Modifier.toString(getModifiers(), sb).append(' ');
+     addTypeParameters(sb, getTypeParameters());
+     sb.append(getDeclaringClass().getName()).append('(');
+Index: vm/reference/java/lang/reflect/Field.java
+===================================================================
+RCS file: /sources/classpath/classpath/vm/reference/java/lang/reflect/Field.java,v
+retrieving revision 1.15
+diff -u -3 -p -u -r1.15 Field.java
+--- vm/reference/java/lang/reflect/Field.java	10 Dec 2006 20:25:50 -0000	1.15
++++ vm/reference/java/lang/reflect/Field.java	1 Mar 2008 09:12:25 -0000
+@@ -1,5 +1,5 @@
+ /* java.lang.reflect.Field - reflection of Java fields
+-   Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
++   Copyright (C) 1998, 2001, 2005, 2008 Free Software Foundation, Inc.
+ 
+ This file is part of GNU Classpath.
+ 
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
++import gnu.classpath.CPStringBuilder;
++
+ import gnu.java.lang.ClassHelper;
+ 
+ import gnu.java.lang.reflect.FieldSignatureParser;
+@@ -206,7 +208,7 @@ extends AccessibleObject implements Memb
+   public String toString()
+   {
+     // 64 is a reasonable buffer initial size for field
+-    StringBuilder sb = new StringBuilder(64);
++    CPStringBuilder sb = new CPStringBuilder(64);
+     Modifier.toString(getModifiers(), sb).append(' ');
+     sb.append(ClassHelper.getUserName(getType())).append(' ');
+     sb.append(getDeclaringClass().getName()).append('.');
+@@ -216,7 +218,7 @@ extends AccessibleObject implements Memb
+ 
+   public String toGenericString()
+   {
+-    StringBuilder sb = new StringBuilder(64);
++    CPStringBuilder sb = new CPStringBuilder(64);
+     Modifier.toString(getModifiers(), sb).append(' ');
+     sb.append(getGenericType()).append(' ');
+     sb.append(getDeclaringClass().getName()).append('.');
+Index: vm/reference/java/lang/reflect/Method.java
+===================================================================
+RCS file: /sources/classpath/classpath/vm/reference/java/lang/reflect/Method.java,v
+retrieving revision 1.23
+diff -u -3 -p -u -r1.23 Method.java
+--- vm/reference/java/lang/reflect/Method.java	18 Feb 2008 00:06:09 -0000	1.23
++++ vm/reference/java/lang/reflect/Method.java	1 Mar 2008 09:12:25 -0000
+@@ -1,5 +1,5 @@
+ /* java.lang.reflect.Method - reflection of Java methods
+-   Copyright (C) 1998, 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
++   Copyright (C) 1998, 2001, 2002, 2005, 2007, 2008 Free Software Foundation, Inc.
+ 
+ This file is part of GNU Classpath.
+ 
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
++import gnu.classpath.CPStringBuilder;
++
+ import gnu.java.lang.ClassHelper;
+ 
+ import gnu.java.lang.reflect.MethodSignatureParser;
+@@ -259,7 +261,7 @@ extends AccessibleObject implements Memb
+   public String toString()
+   {
+     // 128 is a reasonable buffer initial size for constructor
+-    StringBuilder sb = new StringBuilder(128);
++    CPStringBuilder sb = new CPStringBuilder(128);
+     Modifier.toString(getModifiers(), sb).append(' ');
+     sb.append(ClassHelper.getUserName(getReturnType())).append(' ');
+     sb.append(getDeclaringClass().getName()).append('.');
+@@ -285,7 +287,7 @@ extends AccessibleObject implements Memb
+   public String toGenericString()
+   {
+     // 128 is a reasonable buffer initial size for constructor
+-    StringBuilder sb = new StringBuilder(128);
++    CPStringBuilder sb = new CPStringBuilder(128);
+     Modifier.toString(getModifiers(), sb).append(' ');
+     Constructor.addTypeParameters(sb, getTypeParameters());
+     sb.append(getGenericReturnType()).append(' ');
Index: build/components/patches/classpath-web.RVM-266-03.patch
===================================================================
--- build/components/patches/classpath-web.RVM-266-03.patch	(revision 0)
+++ build/components/patches/classpath-web.RVM-266-03.patch	(revision 0)
@@ -0,0 +1,2968 @@
+Index: gnu/classpath/CPStringBuilder.java
+===================================================================
+RCS file: gnu/classpath/CPStringBuilder.java
+diff -N gnu/classpath/CPStringBuilder.java
+--- gnu/classpath/CPStringBuilder.java	1 Mar 2008 09:16:40 -0000	1.1
++++ /dev/null	1 Jan 1970 00:00:00 -0000
+@@ -1,1156 +0,0 @@
+-/* ClasspathStringBuffer.java -- Growable strings without locking or copying
+-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+-   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 gnu.classpath;
+-
+-import java.lang.reflect.Constructor;
+-import java.lang.reflect.InvocationTargetException;
+-
+-import java.io.Serializable;
+-
+-/**
+- * This class is based on java.lang.AbstractStringBuffer but
+- * without the copying of the string by toString.
+- * If you modify this, please consider also modifying that code.
+- * This code is not thread-safe; limit its use to internal use within
+- * methods.
+- */
+-public final class CPStringBuilder
+-  implements Serializable, CharSequence, Appendable
+-{
+-
+-  /**
+-   * Index of next available character (and thus the size of the current
+-   * string contents).  Note that this has permissions set this way so that
+-   * String can get the value.
+-   *
+-   * @serial the number of characters in the buffer
+-   */
+-  int count;
+-
+-  /**
+-   * The buffer.  Note that this has permissions set this way so that String
+-   * can get the value.
+-   *
+-   * @serial the buffer
+-   */
+-  char[] value;
+-
+-  /**
+-   * The package-private constructor for String objects without copying.
+-   */
+-  private static final Constructor<String> cons;
+-
+-  /**
+-   * The default capacity of a buffer.
+-   */
+-  private static final int DEFAULT_CAPACITY = 16;
+-
+-  static
+-  {
+-    try
+-      {
+-	cons = String.class.getDeclaredConstructor(char[].class, Integer.TYPE,
+-						   Integer.TYPE, Boolean.TYPE);
+-      }
+-    catch (NoSuchMethodException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not get no-copy String constructor").initCause(e);
+-      }
+-  }
+-
+-  /**
+-   * Create a new CPStringBuilder with default capacity 16.
+-   */
+-  public CPStringBuilder()
+-  {
+-    this(DEFAULT_CAPACITY);
+-  }
+-
+-  /**
+-   * Create an empty <code>StringBuffer</code> with the specified initial
+-   * capacity.
+-   *
+-   * @param capacity the initial capacity
+-   * @throws NegativeArraySizeException if capacity is negative
+-   */
+-  public CPStringBuilder(int capacity)
+-  {
+-    value = new char[capacity];
+-  }
+-
+-  /**
+-   * 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 convert
+-   * @throws NullPointerException if str is null
+-   */
+-  public CPStringBuilder(String str)
+-  {
+-    count = str.length();
+-    value = new char[count + DEFAULT_CAPACITY];
+-    str.getChars(0, count, value, 0);
+-  }
+-
+-  /**
+-   * Create a new <code>StringBuffer</code> with the characters in the
+-   * specified <code>CharSequence</code>. Initial capacity will be the
+-   * length of the sequence plus 16; if the sequence reports a length
+-   * less than or equal to 0, then the initial capacity will be 16.
+-   *
+-   * @param seq the initializing <code>CharSequence</code>
+-   * @throws NullPointerException if str is null
+-   * @since 1.5
+-   */
+-  public CPStringBuilder(CharSequence seq)
+-  {
+-    int len = seq.length();
+-    count = len <= 0 ? 0 : len;
+-    value = new char[count + DEFAULT_CAPACITY];
+-    for (int i = 0; i < len; ++i)
+-      value[i] = seq.charAt(i);
+-  }
+-
+-  /**
+-   * 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. The buffer is grown to the
+-   * larger of <code>minimumCapacity</code> and
+-   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+-   *
+-   * @param minimumCapacity the new capacity
+-   * @see #capacity()
+-   */
+-  public void ensureCapacity(int minimumCapacity)
+-  {
+-    ensureCapacity_unsynchronized(minimumCapacity);
+-  }
+-
+-  /**
+-   * Set the length of this StringBuffer. If the new length is greater than
+-   * the current length, all the new characters are set to '\0'. If the new
+-   * length is less than the current length, the first <code>newLength</code>
+-   * characters of the old array will be preserved, and the remaining
+-   * characters are truncated.
+-   *
+-   * @param newLength the new length
+-   * @throws IndexOutOfBoundsException if the new length is negative
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   * @see #length()
+-   */
+-  public void setLength(int newLength)
+-  {
+-    if (newLength < 0)
+-      throw new StringIndexOutOfBoundsException(newLength);
+-
+-    int valueLength = value.length;
+-
+-    /* Always call ensureCapacity_unsynchronized in order to preserve
+-       copy-on-write semantics.  */
+-    ensureCapacity_unsynchronized(newLength);
+-
+-    if (newLength < valueLength)
+-      {
+-        /* If the StringBuffer's value just grew, then we know that
+-           value is newly allocated and the region between count and
+-           newLength is filled with '\0'.  */
+-	count = newLength;
+-      }
+-    else
+-      {
+-	/* The StringBuffer's value doesn't need to grow.  However,
+-	   we should clear out any cruft that may exist.  */
+-	while (count < newLength)
+-          value[count++] = '\0';
+-      }
+-  }
+-
+-  /**
+-   * 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
+-   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   */
+-  public char charAt(int index)
+-  {
+-    if (index < 0 || index >= count)
+-      throw new StringIndexOutOfBoundsException(index);
+-    return value[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 int codePointAt(int index)
+-  {
+-    return Character.codePointAt(value, index, count);
+-  }
+-
+-  /**
+-   * 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()
+-   * @since 1.5
+-   */
+-  public int codePointBefore(int index)
+-  {
+-    // Character.codePointBefore() doesn't perform this check.  We
+-    // could use the CharSequence overload, but this is just as easy.
+-    if (index >= count)
+-      throw new IndexOutOfBoundsException();
+-    return Character.codePointBefore(value, index, 1);
+-  }
+-
+-  /**
+-   * Get the specified array of characters. <code>srcOffset - srcEnd</code>
+-   * characters will be copied into the array you pass in.
+-   *
+-   * @param srcOffset the index to start copying from (inclusive)
+-   * @param srcEnd the index to stop copying from (exclusive)
+-   * @param dst the array to copy into
+-   * @param dstOffset the index to start copying into
+-   * @throws NullPointerException if dst is null
+-   * @throws IndexOutOfBoundsException if any source or target indices are
+-   *         out of range (while unspecified, source problems cause a
+-   *         StringIndexOutOfBoundsException, and dest problems cause an
+-   *         ArrayIndexOutOfBoundsException)
+-   * @see System#arraycopy(Object, int, Object, int, int)
+-   */
+-  public void getChars(int srcOffset, int srcEnd,
+-		       char[] dst, int dstOffset)
+-  {
+-    if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
+-      throw new StringIndexOutOfBoundsException();
+-    System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
+-  }
+-
+-  /**
+-   * 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
+-   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   */
+-  public 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;
+-  }
+-
+-  /**
+-   * 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 String#valueOf(Object)
+-   * @see #append(String)
+-   */
+-  public CPStringBuilder append(Object obj)
+-  {
+-    return append(String.valueOf(obj));
+-  }
+-
+-  /**
+-   * Append the <code>String</code> to this <code>StringBuffer</code>. If
+-   * str is null, the String "null" is appended.
+-   *
+-   * @param str the <code>String</code> to append
+-   * @return this <code>StringBuffer</code>
+-   */
+-  public CPStringBuilder 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>StringBuilder</code> value of the argument to this
+-   * <code>StringBuilder</code>. This behaves the same as
+-   * <code>append((Object) stringBuffer)</code>, except it is more efficient.
+-   *
+-   * @param stringBuffer the <code>StringBuilder</code> to convert and append
+-   * @return this <code>StringBuilder</code>
+-   * @see #append(Object)
+-   */
+-  public CPStringBuilder append(StringBuffer stringBuffer)
+-  {
+-    if (stringBuffer == null)
+-      return append("null");
+-    synchronized (stringBuffer)
+-      {
+-	int len = stringBuffer.length();
+-	ensureCapacity(count + len);
+-	stringBuffer.getChars(0, len, value, count);
+-	count += len;
+-      }
+-    return this;
+-  }
+-
+-  /**
+-   * Append the <code>char</code> array to this <code>StringBuffer</code>.
+-   * This is similar (but more efficient) than
+-   * <code>append(new String(data))</code>, except in the case of null.
+-   *
+-   * @param data the <code>char[]</code> to append
+-   * @return this <code>StringBuffer</code>
+-   * @throws NullPointerException if <code>str</code> is <code>null</code>
+-   * @see #append(char[], int, int)
+-   */
+-  public CPStringBuilder append(char[] data)
+-  {
+-    return append(data, 0, data.length);
+-  }
+-
+-  /**
+-   * Append part of the <code>char</code> array to this
+-   * <code>StringBuffer</code>. This is similar (but more efficient) than
+-   * <code>append(new String(data, offset, count))</code>, except in the case
+-   * of null.
+-   *
+-   * @param data the <code>char[]</code> to append
+-   * @param offset the start location in <code>str</code>
+-   * @param count the number of characters to get from <code>str</code>
+-   * @return this <code>StringBuffer</code>
+-   * @throws NullPointerException if <code>str</code> is <code>null</code>
+-   * @throws IndexOutOfBoundsException if offset or count is out of range
+-   *         (while unspecified, this is a StringIndexOutOfBoundsException)
+-   */
+-  public CPStringBuilder append(char[] data, int offset, int count)
+-  {
+-    if (offset < 0 || count < 0 || offset > data.length - count)
+-      throw new StringIndexOutOfBoundsException();
+-    ensureCapacity_unsynchronized(this.count + count);
+-    System.arraycopy(data, offset, value, this.count, count);
+-    this.count += count;
+-    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 bool the <code>boolean</code> to convert and append
+-   * @return this <code>StringBuffer</code>
+-   * @see String#valueOf(boolean)
+-   */
+-  public CPStringBuilder append(boolean bool)
+-  {
+-    return append(bool ? "true" : "false");
+-  }
+-
+-  /**
+-   * Append the <code>char</code> to this <code>StringBuffer</code>.
+-   *
+-   * @param ch the <code>char</code> to append
+-   * @return this <code>StringBuffer</code>
+-   */
+-  public CPStringBuilder append(char ch)
+-  {
+-    ensureCapacity_unsynchronized(count + 1);
+-    value[count++] = ch;
+-    return this;
+-  }
+-
+-  /**
+-   * Append the characters in the <code>CharSequence</code> to this
+-   * buffer.
+-   *
+-   * @param seq the <code>CharSequence</code> providing the characters
+-   * @return this <code>StringBuffer</code>
+-   * @since 1.5
+-   */
+-  public CPStringBuilder append(CharSequence seq)
+-  {
+-    return append(seq, 0, seq.length());
+-  }
+-
+-  /**
+-   * Append some characters from the <code>CharSequence</code> to this
+-   * buffer.  If the argument is null, the four characters "null" are
+-   * appended.
+-   *
+-   * @param seq the <code>CharSequence</code> providing the characters
+-   * @param start the starting index
+-   * @param end one past the final index
+-   * @return this <code>StringBuffer</code>
+-   * @since 1.5
+-   */
+-  public CPStringBuilder append(CharSequence seq, int start, int end)
+-  {
+-    if (seq == null)
+-      return append("null");
+-    if (end - start > 0)
+-      {
+-	ensureCapacity_unsynchronized(count + end - start);
+-	for (; start < end; ++start)
+-	  value[count++] = seq.charAt(start);
+-      }
+-    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 String#valueOf(int)
+-   */
+-  // This is native in libgcj, for efficiency.
+-  public CPStringBuilder append(int inum)
+-  {
+-    return append(String.valueOf(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 String#valueOf(long)
+-   */
+-  public CPStringBuilder append(long lnum)
+-  {
+-    return append(Long.toString(lnum, 10));
+-  }
+-
+-  /**
+-   * 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 String#valueOf(float)
+-   */
+-  public CPStringBuilder append(float fnum)
+-  {
+-    return append(Float.toString(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 String#valueOf(double)
+-   */
+-  public CPStringBuilder append(double dnum)
+-  {
+-    return append(Double.toString(dnum));
+-  }
+-
+-  /**
+-   * Append the code point to this <code>StringBuffer</code>.
+-   * This is like #append(char), but will append two characters
+-   * if a supplementary code point is given.
+-   *
+-   * @param code the code point to append
+-   * @return this <code>StringBuffer</code>
+-   * @see Character#toChars(int, char[], int)
+-   * @since 1.5
+-   */
+-  public CPStringBuilder appendCodePoint(int code)
+-  {
+-    int len = Character.charCount(code);
+-    ensureCapacity_unsynchronized(count + len);
+-    Character.toChars(code, value, count);
+-    count += len;
+-    return this;
+-  }
+-
+-  /**
+-   * Delete characters from this <code>StringBuffer</code>.
+-   * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
+-   * harmless for end to be larger than length().
+-   *
+-   * @param start the first character to delete
+-   * @param end the index after the last character to delete
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+-   * @since 1.2
+-   */
+-  public CPStringBuilder delete(int start, int end)
+-  {
+-    if (start < 0 || start > count || start > end)
+-      throw new StringIndexOutOfBoundsException(start);
+-    if (end > count)
+-      end = count;
+-    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>
+-   * @throws StringIndexOutOfBoundsException if index is out of bounds
+-   * @since 1.2
+-   */
+-  public CPStringBuilder deleteCharAt(int index)
+-  {
+-    return delete(index, index + 1);
+-  }
+-
+-  /**
+-   * 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>
+-   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+-   * @throws NullPointerException if str is null
+-   * @since 1.2
+-   */
+-  public CPStringBuilder 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;
+-  }
+-
+-  /**
+-   * Insert a subarray of the <code>char[]</code> argument into this
+-   * <code>StringBuffer</code>.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @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>
+-   * @throws NullPointerException if <code>str</code> is <code>null</code>
+-   * @throws StringIndexOutOfBoundsException if any index is out of bounds
+-   * @since 1.2
+-   */
+-  public CPStringBuilder insert(int offset, char[] str, int str_offset, int len)
+-  {
+-    if (offset < 0 || offset > count || len < 0
+-        || str_offset < 0 || str_offset > str.length - len)
+-      throw new StringIndexOutOfBoundsException();
+-    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;
+-  }
+-
+-  /**
+-   * 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 in this buffer
+-   * @param obj the <code>Object</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @exception StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(Object)
+-   */
+-  public CPStringBuilder insert(int offset, Object obj)
+-  {
+-    return insert(offset, obj == null ? "null" : obj.toString());
+-  }
+-
+-  /**
+-   * Insert the <code>String</code> argument into this
+-   * <code>StringBuffer</code>. If str is null, the String "null" is used
+-   * instead.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param str the <code>String</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   */
+-  public CPStringBuilder insert(int offset, String str)
+-  {
+-    if (offset < 0 || offset > count)
+-      throw new StringIndexOutOfBoundsException(offset);
+-    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>CharSequence</code> argument into this
+-   * <code>StringBuffer</code>.  If the sequence is null, the String
+-   * "null" is used instead.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param sequence the <code>CharSequence</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws IndexOutOfBoundsException if offset is out of bounds
+-   * @since 1.5
+-   */
+-  public CPStringBuilder insert(int offset, CharSequence sequence)
+-  {
+-    if (sequence == null)
+-      sequence = "null";
+-    return insert(offset, sequence, 0, sequence.length());
+-  }
+-
+-  /**
+-   * Insert a subsequence of the <code>CharSequence</code> argument into this
+-   * <code>StringBuffer</code>.  If the sequence is null, the String
+-   * "null" is used instead.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param sequence the <code>CharSequence</code> to insert
+-   * @param start the starting index of the subsequence
+-   * @param end one past the ending index of the subsequence
+-   * @return this <code>StringBuffer</code>
+-   * @throws IndexOutOfBoundsException if offset, start,
+-   * or end are out of bounds
+-   * @since 1.5
+-   */
+-  public CPStringBuilder insert(int offset, CharSequence sequence, int start, int end)
+-  {
+-    if (sequence == null)
+-      sequence = "null";
+-    if (start < 0 || end < 0 || start > end || end > sequence.length())
+-      throw new IndexOutOfBoundsException();
+-    int len = end - start;
+-    ensureCapacity_unsynchronized(count + len);
+-    System.arraycopy(value, offset, value, offset + len, count - offset);
+-    for (int i = start; i < end; ++i)
+-      value[offset++] = sequence.charAt(i);
+-    count += len;
+-    return this;
+-  }
+-
+-  /**
+-   * Insert the <code>char[]</code> argument into this
+-   * <code>StringBuffer</code>.
+-   *
+-   * @param offset the place to insert in this buffer
+-   * @param data the <code>char[]</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws NullPointerException if <code>data</code> is <code>null</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see #insert(int, char[], int, int)
+-   */
+-  public CPStringBuilder insert(int offset, char[] data)
+-  {
+-    return insert(offset, data, 0, data.length);
+-  }
+-
+-  /**
+-   * 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 in this buffer
+-   * @param bool the <code>boolean</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(boolean)
+-   */
+-  public CPStringBuilder 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 in this buffer
+-   * @param ch the <code>char</code> to insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   */
+-  public CPStringBuilder 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 in this buffer
+-   * @param inum the <code>int</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(int)
+-   */
+-  public CPStringBuilder 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 in this buffer
+-   * @param lnum the <code>long</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(long)
+-   */
+-  public CPStringBuilder insert(int offset, long lnum)
+-  {
+-    return insert(offset, Long.toString(lnum, 10));
+-  }
+-
+-  /**
+-   * 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 in this buffer
+-   * @param fnum the <code>float</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(float)
+-   */
+-  public CPStringBuilder insert(int offset, float fnum)
+-  {
+-    return insert(offset, Float.toString(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 in this buffer
+-   * @param dnum the <code>double</code> to convert and insert
+-   * @return this <code>StringBuffer</code>
+-   * @throws StringIndexOutOfBoundsException if offset is out of bounds
+-   * @see String#valueOf(double)
+-   */
+-  public CPStringBuilder insert(int offset, double dnum)
+-  {
+-    return insert(offset, Double.toString(dnum));
+-  }
+-
+-  /**
+-   * Finds the first instance of a substring in this StringBuilder.
+-   *
+-   * @param str String to find
+-   * @return location (base 0) of the String, or -1 if not found
+-   * @throws NullPointerException if str is null
+-   * @see #indexOf(String, int)
+-   */
+-  public int indexOf(String str)
+-  {
+-    return indexOf(str, 0);
+-  }
+-
+-  /**
+-   * Finds the first instance of a String in this StringBuffer, 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, or the substring is not found, -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
+-   * @since 1.4
+-   */
+-  public int indexOf(String str, int fromIndex)
+-  {
+-    if (fromIndex < 0)
+-      fromIndex = 0;
+-    int limit = count - str.length();
+-    for ( ; fromIndex <= limit; fromIndex++)
+-      if (regionMatches(fromIndex, str))
+-        return fromIndex;
+-    return -1;
+-  }
+-
+-  /**
+-   * Finds the last instance of a substring in this StringBuffer.
+-   *
+-   * @param str String to find
+-   * @return location (base 0) of the String, or -1 if not found
+-   * @throws NullPointerException if str is null
+-   * @see #lastIndexOf(String, int)
+-   * @since 1.4
+-   */
+-  public int lastIndexOf(String str)
+-  {
+-    return lastIndexOf(str, count - str.length());
+-  }
+-
+-  /**
+-   * Finds the last instance of a String in this StringBuffer, 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, or the substring is not found, -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
+-   * @since 1.4
+-   */
+-  public int lastIndexOf(String str, int fromIndex)
+-  {
+-    fromIndex = Math.min(fromIndex, count - str.length());
+-    for ( ; fromIndex >= 0; fromIndex--)
+-      if (regionMatches(fromIndex, str))
+-        return fromIndex;
+-    return -1;
+-  }
+-
+-  /**
+-   * Reverse the characters in this StringBuffer. The same sequence of
+-   * characters exists, but in the reverse index ordering.
+-   *
+-   * @return this <code>StringBuffer</code>
+-   */
+-  public CPStringBuilder reverse()
+-  {
+-    // Call ensureCapacity to enforce copy-on-write.
+-    ensureCapacity_unsynchronized(count);
+-    for (int i = count >> 1, j = count - i; --i >= 0; ++j)
+-      {
+-        char c = value[i];
+-        value[i] = value[j];
+-        value[j] = c;
+-      }
+-    return this;
+-  }
+-
+-  /**
+-   * This may reduce the amount of memory used by the StringBuffer,
+-   * by resizing the internal array to remove unused space.  However,
+-   * this method is not required to resize, so this behavior cannot
+-   * be relied upon.
+-   * @since 1.5
+-   */
+-  public void trimToSize()
+-  {
+-    int wouldSave = value.length - count;
+-    // Some random heuristics: if we save less than 20 characters, who
+-    // cares.
+-    if (wouldSave < 20)
+-      return;
+-    // If we save more than 200 characters, shrink.
+-    // If we save more than 1/4 of the buffer, shrink.
+-    if (wouldSave > 200 || wouldSave * 4 > value.length)
+-      {
+-	char[] newValue = new char[count];
+-	System.arraycopy(value, 0, newValue, 0, count);
+-	value = newValue;
+-      }
+-  }
+-
+-  /**
+-   * Return the number of code points between two indices in the
+-   * <code>StringBuffer</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 int codePointCount(int start, int end)
+-  {
+-    if (start < 0 || end >= count || start > end)
+-      throw new StringIndexOutOfBoundsException();
+-
+-    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;
+-  }
+-
+-  /**
+-   * Starting at the given index, this counts forward by the indicated
+-   * number of code points, and then returns the resulting index.  An
+-   * unpaired surrogate counts as a single code point for this
+-   * purpose.
+-   *
+-   * @param start the starting index
+-   * @param codePoints the number of code points
+-   * @return the resulting index
+-   * @since 1.5
+-   */
+-  public int offsetByCodePoints(int start, int codePoints)
+-  {
+-    while (codePoints > 0)
+-      {
+-	char base = value[start];
+-	if (base < Character.MIN_HIGH_SURROGATE
+-	    || base > Character.MAX_HIGH_SURROGATE
+-	    || start == count
+-	    || value[start + 1] < Character.MIN_LOW_SURROGATE
+-	    || value[start + 1] > Character.MAX_LOW_SURROGATE)
+-	  {
+-	    // Nothing.
+-	  }
+-	else
+-	  {
+-	    // Surrogate pair.
+-	    ++start;
+-	  }
+-	++start;
+-	--codePoints;
+-      }
+-    return start;
+-  }
+-
+-  /**
+-   * Increase the capacity of this <code>StringBuilder</code>. This will
+-   * ensure that an expensive growing operation will not occur until
+-   * <code>minimumCapacity</code> is reached. The buffer is grown to the
+-   * larger of <code>minimumCapacity</code> and
+-   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+-   *
+-   * @param minimumCapacity the new capacity
+-   * @see #capacity()
+-   */
+-  protected void ensureCapacity_unsynchronized(int minimumCapacity)
+-  {
+-    if (minimumCapacity > value.length)
+-      {
+-        int max = value.length * 2 + 2;
+-        minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
+-        char[] nb = new char[minimumCapacity];
+-        System.arraycopy(value, 0, nb, 0, count);
+-        value = nb;
+-      }
+-  }
+-
+-  /**
+-   * Predicate which determines if a substring of this matches another String
+-   * starting at a specified offset for each String and continuing for a
+-   * specified length. This is more efficient than creating a String to call
+-   * indexOf on.
+-   *
+-   * @param toffset index to start comparison at for this String
+-   * @param other non-null String to compare to region of this
+-   * @return true if regions match, false otherwise
+-   * @see #indexOf(String, int)
+-   * @see #lastIndexOf(String, int)
+-   * @see String#regionMatches(boolean, int, String, int, int)
+-   */
+-  private boolean regionMatches(int toffset, String other)
+-  {
+-    return new String().regionMatches(toffset, other, 0, other.length());
+-  }
+-
+-  /**
+-   * Get the length of the <code>String</code> this <code>StringBuilder</code>
+-   * would create. Not to be confused with the <em>capacity</em> of the
+-   * <code>StringBuilder</code>.
+-   *
+-   * @return the length of this <code>StringBuilder</code>
+-   * @see #capacity()
+-   * @see #setLength(int)
+-   */
+-  public int length()
+-  {
+-    return count;
+-  }
+-
+-  /**
+-   * Creates a substring of this StringBuilder, starting at a specified index
+-   * and ending at one character before a specified index. This is implemented
+-   * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
+-   * the CharSequence interface.
+-   *
+-   * @param beginIndex index to start at (inclusive, base 0)
+-   * @param endIndex index to end at (exclusive)
+-   * @return new String which is a substring of this StringBuilder
+-   * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
+-   *         bounds
+-   * @see #substring(int, int)
+-   */
+-  public CharSequence subSequence(int beginIndex, int endIndex)
+-  {
+-    return substring(beginIndex, endIndex);
+-  }
+-
+-  /**
+-   * Creates a substring of this StringBuilder, starting at a specified index
+-   * and ending at one character before a specified index.
+-   *
+-   * @param beginIndex index to start at (inclusive, base 0)
+-   * @param endIndex index to end at (exclusive)
+-   * @return new String which is a substring of this StringBuilder
+-   * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
+-   *         of bounds
+-   */
+-  public String substring(int beginIndex, int endIndex)
+-  {
+-    int len = endIndex - beginIndex;
+-    if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
+-      throw new StringIndexOutOfBoundsException();
+-    if (len == 0)
+-      return "";
+-    try
+-      {
+-	return cons.newInstance(value, beginIndex, len, true);
+-      }
+-    catch (InstantiationException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
+-      }
+-    catch (IllegalAccessException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not access no-copy String constructor").initCause(e);
+-      }
+-    catch (InvocationTargetException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Error calling no-copy String constructor").initCause(e);
+-      }
+-  }
+-
+-  /**
+-   * Convert this <code>StringBuilder</code> to a <code>String</code>. The
+-   * String is composed of the characters currently in this StringBuilder. Note
+-   * that the result is not a copy, so future modifications to this buffer
+-   * do affect the String.
+-   *
+-   * @return the characters in this StringBuilder
+-   */
+-  public String toString()
+-  {
+-    try
+-      {
+-	return cons.newInstance(value, 0, count, true);
+-      }
+-    catch (InstantiationException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
+-      }
+-    catch (IllegalAccessException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Could not access no-copy String constructor").initCause(e);
+-      }
+-    catch (InvocationTargetException e)
+-      {
+-	throw (Error) 
+-	  new InternalError("Error calling no-copy String constructor").initCause(e);
+-      }
+-  }
+-
+-}
+Index: gnu/java/awt/font/OpenTypeFontPeer.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/font/OpenTypeFontPeer.java,v
+retrieving revision 1.1
+diff -u -3 -p -u -r1.1 OpenTypeFontPeer.java
+--- gnu/java/awt/font/OpenTypeFontPeer.java	20 Sep 2007 14:01:07 -0000	1.1
++++ gnu/java/awt/font/OpenTypeFontPeer.java	1 Mar 2008 10:09:01 -0000
+@@ -37,6 +37,10 @@ exception statement from your version. *
+ 
+ package gnu.java.awt.font;
+ 
++
++import gnu.java.awt.peer.ClasspathFontPeer;
++import gnu.java.lang.CPStringBuilder;
++
+ import java.awt.Font;
+ import java.awt.FontMetrics;
+ import java.awt.font.FontRenderContext;
+@@ -61,8 +65,6 @@ import java.util.Map;
+ import java.util.Properties;
+ import java.util.Set;
+ 
+-import gnu.java.awt.peer.ClasspathFontPeer;
+-
+ public class OpenTypeFontPeer
+   extends ClasspathFontPeer
+ {
+@@ -422,7 +424,7 @@ public class OpenTypeFontPeer
+    */
+   static String encodeFont(String name, int style)
+   {
+-    StringBuilder key = new StringBuilder();
++    CPStringBuilder key = new CPStringBuilder();
+     key.append(validName(name));
+     key.append('/');
+     switch (style)
+Index: gnu/java/awt/font/autofit/Edge.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/font/autofit/Edge.java,v
+retrieving revision 1.3
+diff -u -3 -p -u -r1.3 Edge.java
+--- gnu/java/awt/font/autofit/Edge.java	15 Dec 2006 21:43:49 -0000	1.3
++++ gnu/java/awt/font/autofit/Edge.java	1 Mar 2008 10:09:01 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.awt.font.autofit;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ class Edge
+ {
+   int fpos;
+@@ -54,7 +56,7 @@ class Edge
+ 
+   public String toString()
+   {
+-    StringBuilder s = new StringBuilder();
++    CPStringBuilder s = new CPStringBuilder();
+     s.append("[Edge] id");
+     s.append(hashCode());
+     s.append(", fpos: ");
+Index: gnu/java/awt/font/autofit/LatinBlue.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/font/autofit/LatinBlue.java,v
+retrieving revision 1.2
+diff -u -3 -p -u -r1.2 LatinBlue.java
+--- gnu/java/awt/font/autofit/LatinBlue.java	15 Dec 2006 00:59:46 -0000	1.2
++++ gnu/java/awt/font/autofit/LatinBlue.java	1 Mar 2008 10:09:01 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.awt.font.autofit;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ public class LatinBlue
+ {
+   static final int FLAG_BLUE_ACTIVE = 1 << 0;
+@@ -48,7 +50,7 @@ public class LatinBlue
+   int flags;
+   public String toString()
+   {
+-    StringBuilder s = new StringBuilder();
++    CPStringBuilder s = new CPStringBuilder();
+     s.append("[BlueZone]");
+     s.append(" ref: ");
+     s.append(ref.org);
+Index: gnu/java/awt/font/autofit/Segment.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/font/autofit/Segment.java,v
+retrieving revision 1.3
+diff -u -3 -p -u -r1.3 Segment.java
+--- gnu/java/awt/font/autofit/Segment.java	14 Dec 2006 20:32:54 -0000	1.3
++++ gnu/java/awt/font/autofit/Segment.java	1 Mar 2008 10:09:01 -0000
+@@ -40,6 +40,8 @@ package gnu.java.awt.font.autofit;
+ 
+ import gnu.java.awt.font.opentype.truetype.Point;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ class Segment
+ {
+ 
+@@ -65,7 +67,7 @@ class Segment
+ 
+   public String toString()
+   {
+-    StringBuilder s = new StringBuilder();
++    CPStringBuilder s = new CPStringBuilder();
+     s.append("[Segment] id: ");
+     s.append(hashCode());
+     s.append(", len:");
+Index: gnu/java/awt/font/autofit/Width.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/font/autofit/Width.java,v
+retrieving revision 1.4
+diff -u -3 -p -u -r1.4 Width.java
+--- gnu/java/awt/font/autofit/Width.java	15 Dec 2006 21:43:49 -0000	1.4
++++ gnu/java/awt/font/autofit/Width.java	1 Mar 2008 10:09:01 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.awt.font.autofit;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ public class Width
+ {
+   int org;
+@@ -50,7 +52,7 @@ public class Width
+ 
+   public String toString()
+   {
+-    StringBuilder s = new StringBuilder();
++    CPStringBuilder s = new CPStringBuilder();
+     s.append("[Width] org: ");
+     s.append(org);
+     s.append(", cur: ");
+Index: gnu/java/awt/font/opentype/truetype/Point.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/font/opentype/truetype/Point.java,v
+retrieving revision 1.2
+diff -u -3 -p -u -r1.2 Point.java
+--- gnu/java/awt/font/opentype/truetype/Point.java	15 Dec 2006 21:43:49 -0000	1.2
++++ gnu/java/awt/font/opentype/truetype/Point.java	1 Mar 2008 10:09:01 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.awt.font.opentype.truetype;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ /**
+  * Encapsulates information regarding one point on a glyph outline.
+  */
+@@ -234,7 +236,7 @@ public class Point
+ 
+   public String toString()
+   {
+-    StringBuilder s = new StringBuilder();
++    CPStringBuilder s = new CPStringBuilder();
+     s.append("[Point] origX: ");
+     s.append(origX);
+     s.append(", origY: ");
+Index: gnu/java/awt/java2d/ActiveEdges.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/java2d/ActiveEdges.java,v
+retrieving revision 1.1
+diff -u -3 -p -u -r1.1 ActiveEdges.java
+--- gnu/java/awt/java2d/ActiveEdges.java	1 Jan 2007 23:28:01 -0000	1.1
++++ gnu/java/awt/java2d/ActiveEdges.java	1 Mar 2008 10:09:01 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.awt.java2d;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ /**
+  * A collection of active edges for scanline conversion.
+  */
+@@ -183,7 +185,7 @@ final class ActiveEdges
+ 
+   public String toString()
+   {
+-    StringBuilder s = new StringBuilder();
++    CPStringBuilder s = new CPStringBuilder();
+     s.append("[ActiveEdges] ");
+     for (int i = 0; i < numActiveEdges; i++)
+       {
+Index: gnu/java/awt/peer/GnomeDesktopPeer.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java,v
+retrieving revision 1.1
+diff -u -3 -p -u -r1.1 GnomeDesktopPeer.java
+--- gnu/java/awt/peer/GnomeDesktopPeer.java	2 Mar 2007 21:01:39 -0000	1.1
++++ gnu/java/awt/peer/GnomeDesktopPeer.java	1 Mar 2008 10:09:01 -0000
+@@ -37,6 +37,8 @@
+ 
+ package gnu.java.awt.peer;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.net.URI;
+@@ -124,7 +126,7 @@ public class GnomeDesktopPeer
+   protected String execQuery(String command) throws IOException
+   {
+     InputStream in = null;
+-    StringBuilder output = new StringBuilder();
++    CPStringBuilder output = new CPStringBuilder();
+ 
+     try
+       {
+Index: gnu/java/awt/peer/KDEDesktopPeer.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/peer/KDEDesktopPeer.java,v
+retrieving revision 1.3
+diff -u -3 -p -u -r1.3 KDEDesktopPeer.java
+--- gnu/java/awt/peer/KDEDesktopPeer.java	18 Sep 2007 21:52:27 -0000	1.3
++++ gnu/java/awt/peer/KDEDesktopPeer.java	1 Mar 2008 10:09:01 -0000
+@@ -37,6 +37,8 @@
+ 
+ package gnu.java.awt.peer;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import java.io.IOException;
+ import java.io.InputStream;
+ 
+@@ -104,7 +106,7 @@ public class KDEDesktopPeer
+   protected String execQuery(String command) throws IOException
+   {
+     InputStream in = null;
+-    StringBuilder output = new StringBuilder();
++    CPStringBuilder output = new CPStringBuilder();
+ 
+     try
+       {
+Index: gnu/java/awt/peer/x/XFontPeer.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/awt/peer/x/XFontPeer.java,v
+retrieving revision 1.5
+diff -u -3 -p -u -r1.5 XFontPeer.java
+--- gnu/java/awt/peer/x/XFontPeer.java	20 Sep 2007 14:01:08 -0000	1.5
++++ gnu/java/awt/peer/x/XFontPeer.java	1 Mar 2008 10:09:01 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.awt.peer.x;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import java.awt.AWTError;
+ import java.awt.Font;
+ import java.awt.FontMetrics;
+@@ -675,7 +677,7 @@ public class XFontPeer
+    */
+   static String encodeFont(String name, int style, int size)
+   {
+-    StringBuilder key = new StringBuilder();
++    CPStringBuilder key = new CPStringBuilder();
+     key.append(validName(name));
+     key.append('.');
+     switch (style)
+Index: gnu/java/lang/CPStringBuilder.java
+===================================================================
+RCS file: gnu/java/lang/CPStringBuilder.java
+diff -N gnu/java/lang/CPStringBuilder.java
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ gnu/java/lang/CPStringBuilder.java	1 Mar 2008 10:09:02 -0000
+@@ -0,0 +1,1156 @@
++/* ClasspathStringBuffer.java -- Growable strings without locking or copying
++   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
++   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 gnu.java.lang;
++
++import java.lang.reflect.Constructor;
++import java.lang.reflect.InvocationTargetException;
++
++import java.io.Serializable;
++
++/**
++ * This class is based on java.lang.AbstractStringBuffer but
++ * without the copying of the string by toString.
++ * If you modify this, please consider also modifying that code.
++ * This code is not thread-safe; limit its use to internal use within
++ * methods.
++ */
++public final class CPStringBuilder
++  implements Serializable, CharSequence, Appendable
++{
++
++  /**
++   * Index of next available character (and thus the size of the current
++   * string contents).  Note that this has permissions set this way so that
++   * String can get the value.
++   *
++   * @serial the number of characters in the buffer
++   */
++  int count;
++
++  /**
++   * The buffer.  Note that this has permissions set this way so that String
++   * can get the value.
++   *
++   * @serial the buffer
++   */
++  char[] value;
++
++  /**
++   * The package-private constructor for String objects without copying.
++   */
++  private static final Constructor<String> cons;
++
++  /**
++   * The default capacity of a buffer.
++   */
++  private static final int DEFAULT_CAPACITY = 16;
++
++  static
++  {
++    try
++      {
++	cons = String.class.getDeclaredConstructor(char[].class, Integer.TYPE,
++						   Integer.TYPE, Boolean.TYPE);
++      }
++    catch (NoSuchMethodException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not get no-copy String constructor").initCause(e);
++      }
++  }
++
++  /**
++   * Create a new CPStringBuilder with default capacity 16.
++   */
++  public CPStringBuilder()
++  {
++    this(DEFAULT_CAPACITY);
++  }
++
++  /**
++   * Create an empty <code>StringBuffer</code> with the specified initial
++   * capacity.
++   *
++   * @param capacity the initial capacity
++   * @throws NegativeArraySizeException if capacity is negative
++   */
++  public CPStringBuilder(int capacity)
++  {
++    value = new char[capacity];
++  }
++
++  /**
++   * 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 convert
++   * @throws NullPointerException if str is null
++   */
++  public CPStringBuilder(String str)
++  {
++    count = str.length();
++    value = new char[count + DEFAULT_CAPACITY];
++    str.getChars(0, count, value, 0);
++  }
++
++  /**
++   * Create a new <code>StringBuffer</code> with the characters in the
++   * specified <code>CharSequence</code>. Initial capacity will be the
++   * length of the sequence plus 16; if the sequence reports a length
++   * less than or equal to 0, then the initial capacity will be 16.
++   *
++   * @param seq the initializing <code>CharSequence</code>
++   * @throws NullPointerException if str is null
++   * @since 1.5
++   */
++  public CPStringBuilder(CharSequence seq)
++  {
++    int len = seq.length();
++    count = len <= 0 ? 0 : len;
++    value = new char[count + DEFAULT_CAPACITY];
++    for (int i = 0; i < len; ++i)
++      value[i] = seq.charAt(i);
++  }
++
++  /**
++   * 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. The buffer is grown to the
++   * larger of <code>minimumCapacity</code> and
++   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
++   *
++   * @param minimumCapacity the new capacity
++   * @see #capacity()
++   */
++  public void ensureCapacity(int minimumCapacity)
++  {
++    ensureCapacity_unsynchronized(minimumCapacity);
++  }
++
++  /**
++   * Set the length of this StringBuffer. If the new length is greater than
++   * the current length, all the new characters are set to '\0'. If the new
++   * length is less than the current length, the first <code>newLength</code>
++   * characters of the old array will be preserved, and the remaining
++   * characters are truncated.
++   *
++   * @param newLength the new length
++   * @throws IndexOutOfBoundsException if the new length is negative
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   * @see #length()
++   */
++  public void setLength(int newLength)
++  {
++    if (newLength < 0)
++      throw new StringIndexOutOfBoundsException(newLength);
++
++    int valueLength = value.length;
++
++    /* Always call ensureCapacity_unsynchronized in order to preserve
++       copy-on-write semantics.  */
++    ensureCapacity_unsynchronized(newLength);
++
++    if (newLength < valueLength)
++      {
++        /* If the StringBuffer's value just grew, then we know that
++           value is newly allocated and the region between count and
++           newLength is filled with '\0'.  */
++	count = newLength;
++      }
++    else
++      {
++	/* The StringBuffer's value doesn't need to grow.  However,
++	   we should clear out any cruft that may exist.  */
++	while (count < newLength)
++          value[count++] = '\0';
++      }
++  }
++
++  /**
++   * 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
++   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public char charAt(int index)
++  {
++    if (index < 0 || index >= count)
++      throw new StringIndexOutOfBoundsException(index);
++    return value[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 int codePointAt(int index)
++  {
++    return Character.codePointAt(value, index, count);
++  }
++
++  /**
++   * 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()
++   * @since 1.5
++   */
++  public int codePointBefore(int index)
++  {
++    // Character.codePointBefore() doesn't perform this check.  We
++    // could use the CharSequence overload, but this is just as easy.
++    if (index >= count)
++      throw new IndexOutOfBoundsException();
++    return Character.codePointBefore(value, index, 1);
++  }
++
++  /**
++   * Get the specified array of characters. <code>srcOffset - srcEnd</code>
++   * characters will be copied into the array you pass in.
++   *
++   * @param srcOffset the index to start copying from (inclusive)
++   * @param srcEnd the index to stop copying from (exclusive)
++   * @param dst the array to copy into
++   * @param dstOffset the index to start copying into
++   * @throws NullPointerException if dst is null
++   * @throws IndexOutOfBoundsException if any source or target indices are
++   *         out of range (while unspecified, source problems cause a
++   *         StringIndexOutOfBoundsException, and dest problems cause an
++   *         ArrayIndexOutOfBoundsException)
++   * @see System#arraycopy(Object, int, Object, int, int)
++   */
++  public void getChars(int srcOffset, int srcEnd,
++		       char[] dst, int dstOffset)
++  {
++    if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
++      throw new StringIndexOutOfBoundsException();
++    System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
++  }
++
++  /**
++   * 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
++   * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public 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;
++  }
++
++  /**
++   * 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 String#valueOf(Object)
++   * @see #append(String)
++   */
++  public CPStringBuilder append(Object obj)
++  {
++    return append(String.valueOf(obj));
++  }
++
++  /**
++   * Append the <code>String</code> to this <code>StringBuffer</code>. If
++   * str is null, the String "null" is appended.
++   *
++   * @param str the <code>String</code> to append
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuilder 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>StringBuilder</code> value of the argument to this
++   * <code>StringBuilder</code>. This behaves the same as
++   * <code>append((Object) stringBuffer)</code>, except it is more efficient.
++   *
++   * @param stringBuffer the <code>StringBuilder</code> to convert and append
++   * @return this <code>StringBuilder</code>
++   * @see #append(Object)
++   */
++  public CPStringBuilder append(StringBuffer stringBuffer)
++  {
++    if (stringBuffer == null)
++      return append("null");
++    synchronized (stringBuffer)
++      {
++	int len = stringBuffer.length();
++	ensureCapacity(count + len);
++	stringBuffer.getChars(0, len, value, count);
++	count += len;
++      }
++    return this;
++  }
++
++  /**
++   * Append the <code>char</code> array to this <code>StringBuffer</code>.
++   * This is similar (but more efficient) than
++   * <code>append(new String(data))</code>, except in the case of null.
++   *
++   * @param data the <code>char[]</code> to append
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @see #append(char[], int, int)
++   */
++  public CPStringBuilder append(char[] data)
++  {
++    return append(data, 0, data.length);
++  }
++
++  /**
++   * Append part of the <code>char</code> array to this
++   * <code>StringBuffer</code>. This is similar (but more efficient) than
++   * <code>append(new String(data, offset, count))</code>, except in the case
++   * of null.
++   *
++   * @param data the <code>char[]</code> to append
++   * @param offset the start location in <code>str</code>
++   * @param count the number of characters to get from <code>str</code>
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @throws IndexOutOfBoundsException if offset or count is out of range
++   *         (while unspecified, this is a StringIndexOutOfBoundsException)
++   */
++  public CPStringBuilder append(char[] data, int offset, int count)
++  {
++    if (offset < 0 || count < 0 || offset > data.length - count)
++      throw new StringIndexOutOfBoundsException();
++    ensureCapacity_unsynchronized(this.count + count);
++    System.arraycopy(data, offset, value, this.count, count);
++    this.count += count;
++    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 bool the <code>boolean</code> to convert and append
++   * @return this <code>StringBuffer</code>
++   * @see String#valueOf(boolean)
++   */
++  public CPStringBuilder append(boolean bool)
++  {
++    return append(bool ? "true" : "false");
++  }
++
++  /**
++   * Append the <code>char</code> to this <code>StringBuffer</code>.
++   *
++   * @param ch the <code>char</code> to append
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuilder append(char ch)
++  {
++    ensureCapacity_unsynchronized(count + 1);
++    value[count++] = ch;
++    return this;
++  }
++
++  /**
++   * Append the characters in the <code>CharSequence</code> to this
++   * buffer.
++   *
++   * @param seq the <code>CharSequence</code> providing the characters
++   * @return this <code>StringBuffer</code>
++   * @since 1.5
++   */
++  public CPStringBuilder append(CharSequence seq)
++  {
++    return append(seq, 0, seq.length());
++  }
++
++  /**
++   * Append some characters from the <code>CharSequence</code> to this
++   * buffer.  If the argument is null, the four characters "null" are
++   * appended.
++   *
++   * @param seq the <code>CharSequence</code> providing the characters
++   * @param start the starting index
++   * @param end one past the final index
++   * @return this <code>StringBuffer</code>
++   * @since 1.5
++   */
++  public CPStringBuilder append(CharSequence seq, int start, int end)
++  {
++    if (seq == null)
++      return append("null");
++    if (end - start > 0)
++      {
++	ensureCapacity_unsynchronized(count + end - start);
++	for (; start < end; ++start)
++	  value[count++] = seq.charAt(start);
++      }
++    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 String#valueOf(int)
++   */
++  // This is native in libgcj, for efficiency.
++  public CPStringBuilder append(int inum)
++  {
++    return append(String.valueOf(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 String#valueOf(long)
++   */
++  public CPStringBuilder append(long lnum)
++  {
++    return append(Long.toString(lnum, 10));
++  }
++
++  /**
++   * 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 String#valueOf(float)
++   */
++  public CPStringBuilder append(float fnum)
++  {
++    return append(Float.toString(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 String#valueOf(double)
++   */
++  public CPStringBuilder append(double dnum)
++  {
++    return append(Double.toString(dnum));
++  }
++
++  /**
++   * Append the code point to this <code>StringBuffer</code>.
++   * This is like #append(char), but will append two characters
++   * if a supplementary code point is given.
++   *
++   * @param code the code point to append
++   * @return this <code>StringBuffer</code>
++   * @see Character#toChars(int, char[], int)
++   * @since 1.5
++   */
++  public CPStringBuilder appendCodePoint(int code)
++  {
++    int len = Character.charCount(code);
++    ensureCapacity_unsynchronized(count + len);
++    Character.toChars(code, value, count);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Delete characters from this <code>StringBuffer</code>.
++   * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
++   * harmless for end to be larger than length().
++   *
++   * @param start the first character to delete
++   * @param end the index after the last character to delete
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
++   * @since 1.2
++   */
++  public CPStringBuilder delete(int start, int end)
++  {
++    if (start < 0 || start > count || start > end)
++      throw new StringIndexOutOfBoundsException(start);
++    if (end > count)
++      end = count;
++    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>
++   * @throws StringIndexOutOfBoundsException if index is out of bounds
++   * @since 1.2
++   */
++  public CPStringBuilder deleteCharAt(int index)
++  {
++    return delete(index, index + 1);
++  }
++
++  /**
++   * 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>
++   * @throws StringIndexOutOfBoundsException if start or end are out of bounds
++   * @throws NullPointerException if str is null
++   * @since 1.2
++   */
++  public CPStringBuilder 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;
++  }
++
++  /**
++   * Insert a subarray of the <code>char[]</code> argument into this
++   * <code>StringBuffer</code>.
++   *
++   * @param offset the place to insert in this buffer
++   * @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>
++   * @throws NullPointerException if <code>str</code> is <code>null</code>
++   * @throws StringIndexOutOfBoundsException if any index is out of bounds
++   * @since 1.2
++   */
++  public CPStringBuilder insert(int offset, char[] str, int str_offset, int len)
++  {
++    if (offset < 0 || offset > count || len < 0
++        || str_offset < 0 || str_offset > str.length - len)
++      throw new StringIndexOutOfBoundsException();
++    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;
++  }
++
++  /**
++   * 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 in this buffer
++   * @param obj the <code>Object</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @exception StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(Object)
++   */
++  public CPStringBuilder insert(int offset, Object obj)
++  {
++    return insert(offset, obj == null ? "null" : obj.toString());
++  }
++
++  /**
++   * Insert the <code>String</code> argument into this
++   * <code>StringBuffer</code>. If str is null, the String "null" is used
++   * instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param str the <code>String</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   */
++  public CPStringBuilder insert(int offset, String str)
++  {
++    if (offset < 0 || offset > count)
++      throw new StringIndexOutOfBoundsException(offset);
++    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>CharSequence</code> argument into this
++   * <code>StringBuffer</code>.  If the sequence is null, the String
++   * "null" is used instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param sequence the <code>CharSequence</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws IndexOutOfBoundsException if offset is out of bounds
++   * @since 1.5
++   */
++  public CPStringBuilder insert(int offset, CharSequence sequence)
++  {
++    if (sequence == null)
++      sequence = "null";
++    return insert(offset, sequence, 0, sequence.length());
++  }
++
++  /**
++   * Insert a subsequence of the <code>CharSequence</code> argument into this
++   * <code>StringBuffer</code>.  If the sequence is null, the String
++   * "null" is used instead.
++   *
++   * @param offset the place to insert in this buffer
++   * @param sequence the <code>CharSequence</code> to insert
++   * @param start the starting index of the subsequence
++   * @param end one past the ending index of the subsequence
++   * @return this <code>StringBuffer</code>
++   * @throws IndexOutOfBoundsException if offset, start,
++   * or end are out of bounds
++   * @since 1.5
++   */
++  public CPStringBuilder insert(int offset, CharSequence sequence, int start, int end)
++  {
++    if (sequence == null)
++      sequence = "null";
++    if (start < 0 || end < 0 || start > end || end > sequence.length())
++      throw new IndexOutOfBoundsException();
++    int len = end - start;
++    ensureCapacity_unsynchronized(count + len);
++    System.arraycopy(value, offset, value, offset + len, count - offset);
++    for (int i = start; i < end; ++i)
++      value[offset++] = sequence.charAt(i);
++    count += len;
++    return this;
++  }
++
++  /**
++   * Insert the <code>char[]</code> argument into this
++   * <code>StringBuffer</code>.
++   *
++   * @param offset the place to insert in this buffer
++   * @param data the <code>char[]</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws NullPointerException if <code>data</code> is <code>null</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see #insert(int, char[], int, int)
++   */
++  public CPStringBuilder insert(int offset, char[] data)
++  {
++    return insert(offset, data, 0, data.length);
++  }
++
++  /**
++   * 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 in this buffer
++   * @param bool the <code>boolean</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(boolean)
++   */
++  public CPStringBuilder 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 in this buffer
++   * @param ch the <code>char</code> to insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   */
++  public CPStringBuilder 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 in this buffer
++   * @param inum the <code>int</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(int)
++   */
++  public CPStringBuilder 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 in this buffer
++   * @param lnum the <code>long</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(long)
++   */
++  public CPStringBuilder insert(int offset, long lnum)
++  {
++    return insert(offset, Long.toString(lnum, 10));
++  }
++
++  /**
++   * 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 in this buffer
++   * @param fnum the <code>float</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(float)
++   */
++  public CPStringBuilder insert(int offset, float fnum)
++  {
++    return insert(offset, Float.toString(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 in this buffer
++   * @param dnum the <code>double</code> to convert and insert
++   * @return this <code>StringBuffer</code>
++   * @throws StringIndexOutOfBoundsException if offset is out of bounds
++   * @see String#valueOf(double)
++   */
++  public CPStringBuilder insert(int offset, double dnum)
++  {
++    return insert(offset, Double.toString(dnum));
++  }
++
++  /**
++   * Finds the first instance of a substring in this StringBuilder.
++   *
++   * @param str String to find
++   * @return location (base 0) of the String, or -1 if not found
++   * @throws NullPointerException if str is null
++   * @see #indexOf(String, int)
++   */
++  public int indexOf(String str)
++  {
++    return indexOf(str, 0);
++  }
++
++  /**
++   * Finds the first instance of a String in this StringBuffer, 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, or the substring is not found, -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
++   * @since 1.4
++   */
++  public int indexOf(String str, int fromIndex)
++  {
++    if (fromIndex < 0)
++      fromIndex = 0;
++    int limit = count - str.length();
++    for ( ; fromIndex <= limit; fromIndex++)
++      if (regionMatches(fromIndex, str))
++        return fromIndex;
++    return -1;
++  }
++
++  /**
++   * Finds the last instance of a substring in this StringBuffer.
++   *
++   * @param str String to find
++   * @return location (base 0) of the String, or -1 if not found
++   * @throws NullPointerException if str is null
++   * @see #lastIndexOf(String, int)
++   * @since 1.4
++   */
++  public int lastIndexOf(String str)
++  {
++    return lastIndexOf(str, count - str.length());
++  }
++
++  /**
++   * Finds the last instance of a String in this StringBuffer, 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, or the substring is not found, -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
++   * @since 1.4
++   */
++  public int lastIndexOf(String str, int fromIndex)
++  {
++    fromIndex = Math.min(fromIndex, count - str.length());
++    for ( ; fromIndex >= 0; fromIndex--)
++      if (regionMatches(fromIndex, str))
++        return fromIndex;
++    return -1;
++  }
++
++  /**
++   * Reverse the characters in this StringBuffer. The same sequence of
++   * characters exists, but in the reverse index ordering.
++   *
++   * @return this <code>StringBuffer</code>
++   */
++  public CPStringBuilder reverse()
++  {
++    // Call ensureCapacity to enforce copy-on-write.
++    ensureCapacity_unsynchronized(count);
++    for (int i = count >> 1, j = count - i; --i >= 0; ++j)
++      {
++        char c = value[i];
++        value[i] = value[j];
++        value[j] = c;
++      }
++    return this;
++  }
++
++  /**
++   * This may reduce the amount of memory used by the StringBuffer,
++   * by resizing the internal array to remove unused space.  However,
++   * this method is not required to resize, so this behavior cannot
++   * be relied upon.
++   * @since 1.5
++   */
++  public void trimToSize()
++  {
++    int wouldSave = value.length - count;
++    // Some random heuristics: if we save less than 20 characters, who
++    // cares.
++    if (wouldSave < 20)
++      return;
++    // If we save more than 200 characters, shrink.
++    // If we save more than 1/4 of the buffer, shrink.
++    if (wouldSave > 200 || wouldSave * 4 > value.length)
++      {
++	char[] newValue = new char[count];
++	System.arraycopy(value, 0, newValue, 0, count);
++	value = newValue;
++      }
++  }
++
++  /**
++   * Return the number of code points between two indices in the
++   * <code>StringBuffer</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 int codePointCount(int start, int end)
++  {
++    if (start < 0 || end >= count || start > end)
++      throw new StringIndexOutOfBoundsException();
++
++    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;
++  }
++
++  /**
++   * Starting at the given index, this counts forward by the indicated
++   * number of code points, and then returns the resulting index.  An
++   * unpaired surrogate counts as a single code point for this
++   * purpose.
++   *
++   * @param start the starting index
++   * @param codePoints the number of code points
++   * @return the resulting index
++   * @since 1.5
++   */
++  public int offsetByCodePoints(int start, int codePoints)
++  {
++    while (codePoints > 0)
++      {
++	char base = value[start];
++	if (base < Character.MIN_HIGH_SURROGATE
++	    || base > Character.MAX_HIGH_SURROGATE
++	    || start == count
++	    || value[start + 1] < Character.MIN_LOW_SURROGATE
++	    || value[start + 1] > Character.MAX_LOW_SURROGATE)
++	  {
++	    // Nothing.
++	  }
++	else
++	  {
++	    // Surrogate pair.
++	    ++start;
++	  }
++	++start;
++	--codePoints;
++      }
++    return start;
++  }
++
++  /**
++   * Increase the capacity of this <code>StringBuilder</code>. This will
++   * ensure that an expensive growing operation will not occur until
++   * <code>minimumCapacity</code> is reached. The buffer is grown to the
++   * larger of <code>minimumCapacity</code> and
++   * <code>capacity() * 2 + 2</code>, if it is not already large enough.
++   *
++   * @param minimumCapacity the new capacity
++   * @see #capacity()
++   */
++  protected void ensureCapacity_unsynchronized(int minimumCapacity)
++  {
++    if (minimumCapacity > value.length)
++      {
++        int max = value.length * 2 + 2;
++        minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
++        char[] nb = new char[minimumCapacity];
++        System.arraycopy(value, 0, nb, 0, count);
++        value = nb;
++      }
++  }
++
++  /**
++   * Predicate which determines if a substring of this matches another String
++   * starting at a specified offset for each String and continuing for a
++   * specified length. This is more efficient than creating a String to call
++   * indexOf on.
++   *
++   * @param toffset index to start comparison at for this String
++   * @param other non-null String to compare to region of this
++   * @return true if regions match, false otherwise
++   * @see #indexOf(String, int)
++   * @see #lastIndexOf(String, int)
++   * @see String#regionMatches(boolean, int, String, int, int)
++   */
++  private boolean regionMatches(int toffset, String other)
++  {
++    return new String().regionMatches(toffset, other, 0, other.length());
++  }
++
++  /**
++   * Get the length of the <code>String</code> this <code>StringBuilder</code>
++   * would create. Not to be confused with the <em>capacity</em> of the
++   * <code>StringBuilder</code>.
++   *
++   * @return the length of this <code>StringBuilder</code>
++   * @see #capacity()
++   * @see #setLength(int)
++   */
++  public int length()
++  {
++    return count;
++  }
++
++  /**
++   * Creates a substring of this StringBuilder, starting at a specified index
++   * and ending at one character before a specified index. This is implemented
++   * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
++   * the CharSequence interface.
++   *
++   * @param beginIndex index to start at (inclusive, base 0)
++   * @param endIndex index to end at (exclusive)
++   * @return new String which is a substring of this StringBuilder
++   * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
++   *         bounds
++   * @see #substring(int, int)
++   */
++  public CharSequence subSequence(int beginIndex, int endIndex)
++  {
++    return substring(beginIndex, endIndex);
++  }
++
++  /**
++   * Creates a substring of this StringBuilder, starting at a specified index
++   * and ending at one character before a specified index.
++   *
++   * @param beginIndex index to start at (inclusive, base 0)
++   * @param endIndex index to end at (exclusive)
++   * @return new String which is a substring of this StringBuilder
++   * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
++   *         of bounds
++   */
++  public String substring(int beginIndex, int endIndex)
++  {
++    int len = endIndex - beginIndex;
++    if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
++      throw new StringIndexOutOfBoundsException();
++    if (len == 0)
++      return "";
++    try
++      {
++	return cons.newInstance(value, beginIndex, len, true);
++      }
++    catch (InstantiationException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
++      }
++    catch (IllegalAccessException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not access no-copy String constructor").initCause(e);
++      }
++    catch (InvocationTargetException e)
++      {
++	throw (Error) 
++	  new InternalError("Error calling no-copy String constructor").initCause(e);
++      }
++  }
++
++  /**
++   * Convert this <code>StringBuilder</code> to a <code>String</code>. The
++   * String is composed of the characters currently in this StringBuilder. Note
++   * that the result is not a copy, so future modifications to this buffer
++   * do affect the String.
++   *
++   * @return the characters in this StringBuilder
++   */
++  public String toString()
++  {
++    try
++      {
++	return cons.newInstance(value, 0, count, true);
++      }
++    catch (InstantiationException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not instantiate no-copy String constructor").initCause(e);
++      }
++    catch (IllegalAccessException e)
++      {
++	throw (Error) 
++	  new InternalError("Could not access no-copy String constructor").initCause(e);
++      }
++    catch (InvocationTargetException e)
++      {
++	throw (Error) 
++	  new InternalError("Error calling no-copy String constructor").initCause(e);
++      }
++  }
++
++}
+Index: gnu/java/lang/ClassHelper.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/lang/ClassHelper.java,v
+retrieving revision 1.14
+diff -u -3 -p -u -r1.14 ClassHelper.java
+--- gnu/java/lang/ClassHelper.java	5 Mar 2006 18:20:02 -0000	1.14
++++ gnu/java/lang/ClassHelper.java	1 Mar 2008 10:09:02 -0000
+@@ -102,7 +102,7 @@ public class ClassHelper
+     String name = klass.getName();
+     if (arrayCount == 0)
+       return name;
+-    StringBuilder b = new StringBuilder(name.length() + 2 * arrayCount);
++    CPStringBuilder b = new CPStringBuilder(name.length() + 2 * arrayCount);
+     b.append(name);
+     for (int i = 0; i < arrayCount; ++i)
+       b.append("[]");
+Index: gnu/java/lang/reflect/GenericSignatureParser.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/lang/reflect/GenericSignatureParser.java,v
+retrieving revision 1.3
+diff -u -3 -p -u -r1.3 GenericSignatureParser.java
+--- gnu/java/lang/reflect/GenericSignatureParser.java	10 Dec 2006 20:25:42 -0000	1.3
++++ gnu/java/lang/reflect/GenericSignatureParser.java	1 Mar 2008 10:09:02 -0000
+@@ -38,7 +38,19 @@ exception statement from your version. *
+ 
+ package gnu.java.lang.reflect;
+ 
+-import java.lang.reflect.*;
++import gnu.java.lang.CPStringBuilder;
++
++import java.lang.reflect.Constructor;
++import java.lang.reflect.GenericArrayType;
++import java.lang.reflect.GenericDeclaration;
++import java.lang.reflect.GenericSignatureFormatError;
++import java.lang.reflect.MalformedParameterizedTypeException;
++import java.lang.reflect.Method;
++import java.lang.reflect.ParameterizedType;
++import java.lang.reflect.Type;
++import java.lang.reflect.TypeVariable;
++import java.lang.reflect.WildcardType;
++
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ 
+@@ -184,7 +196,7 @@ final class ParameterizedTypeImpl extend
+ 
+     public String toString()
+     {
+-        StringBuilder sb = new StringBuilder();
++        CPStringBuilder sb = new CPStringBuilder();
+         if (owner != null)
+         {
+             sb.append(owner);
+Index: gnu/java/lang/reflect/TypeSignature.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/lang/reflect/TypeSignature.java,v
+retrieving revision 1.15
+diff -u -3 -p -u -r1.15 TypeSignature.java
+--- gnu/java/lang/reflect/TypeSignature.java	5 Feb 2008 14:59:04 -0000	1.15
++++ gnu/java/lang/reflect/TypeSignature.java	1 Mar 2008 10:09:02 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.lang.reflect;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import java.lang.reflect.Constructor;
+ import java.lang.reflect.Field;
+ import java.lang.reflect.Member;
+@@ -239,7 +241,7 @@ public class TypeSignature
+   public static String getEncodingOfMethod(Method m)
+   {
+     Class[] paramTypes = m.getParameterTypes();
+-    StringBuilder buf = new StringBuilder("(");
++    CPStringBuilder buf = new CPStringBuilder("(");
+     for (int i = 0; i < paramTypes.length; i++)
+       buf.append(getEncodingOfClass(paramTypes[i].getName(), true));
+     buf.append(')').append(getEncodingOfClass(m.getReturnType().getName(),
+@@ -261,7 +263,7 @@ public class TypeSignature
+   public static String getEncodingOfConstructor(Constructor c)
+   {
+     Class[] paramTypes = c.getParameterTypes();
+-    StringBuilder buf = new StringBuilder("(");
++    CPStringBuilder buf = new CPStringBuilder("(");
+     for (int i = 0; i < paramTypes.length; i++)
+       buf.append(getEncodingOfClass(paramTypes[i].getName(), true));
+     buf.append(")V");
+Index: gnu/java/net/protocol/http/ChunkedInputStream.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java,v
+retrieving revision 1.8
+diff -u -3 -p -u -r1.8 ChunkedInputStream.java
+--- gnu/java/net/protocol/http/ChunkedInputStream.java	18 Dec 2006 21:37:38 -0000	1.8
++++ gnu/java/net/protocol/http/ChunkedInputStream.java	1 Mar 2008 10:09:02 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.net.protocol.http;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.net.ProtocolException;
+@@ -113,7 +115,7 @@ public class ChunkedInputStream
+         // Read chunk header
+         int c, last = 0;
+         boolean seenSemi = false;
+-        StringBuilder buf = new StringBuilder();
++        CPStringBuilder buf = new CPStringBuilder();
+         do
+           {
+             c = in.read();
+Index: gnu/java/net/protocol/http/Cookie.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/net/protocol/http/Cookie.java,v
+retrieving revision 1.4
+diff -u -3 -p -u -r1.4 Cookie.java
+--- gnu/java/net/protocol/http/Cookie.java	12 Oct 2005 19:48:25 -0000	1.4
++++ gnu/java/net/protocol/http/Cookie.java	1 Mar 2008 10:09:02 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.net.protocol.http;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import java.util.Date;
+ 
+ /**
+@@ -139,7 +141,7 @@ public class Cookie
+   
+   public String toString(boolean showPath, boolean showDomain)
+   {
+-    StringBuilder buf = new StringBuilder();
++    CPStringBuilder buf = new CPStringBuilder();
+     buf.append(name);
+     buf.append('=');
+     buf.append(value);
+Index: gnu/java/net/protocol/http/HTTPConnection.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/net/protocol/http/HTTPConnection.java,v
+retrieving revision 1.16
+diff -u -3 -p -u -r1.16 HTTPConnection.java
+--- gnu/java/net/protocol/http/HTTPConnection.java	18 Dec 2006 21:37:38 -0000	1.16
++++ gnu/java/net/protocol/http/HTTPConnection.java	1 Mar 2008 10:09:02 -0000
+@@ -39,6 +39,8 @@ exception statement from your version. *
+ package gnu.java.net.protocol.http;
+ 
+ import gnu.classpath.SystemProperties;
++
++import gnu.java.lang.CPStringBuilder;
+ import gnu.java.net.EmptyX509TrustManager;
+ 
+ import java.io.BufferedInputStream;
+@@ -668,7 +670,7 @@ public class HTTPConnection
+         Cookie[] cookies = cookieManager.getCookies(hostname, secure, path);
+         if (cookies != null && cookies.length > 0)
+           {
+-            StringBuilder buf = new StringBuilder();
++            CPStringBuilder buf = new CPStringBuilder();
+             buf.append("$Version=1");
+             for (int i = 0; i < cookies.length; i++)
+               {
+@@ -827,7 +829,7 @@ public class HTTPConnection
+    */
+   protected String getURI()
+   {
+-    StringBuilder buf = new StringBuilder();
++    CPStringBuilder buf = new CPStringBuilder();
+     buf.append(secure ? "https://"; : "http://";);
+     buf.append(hostname);
+     if (secure)
+Index: gnu/java/net/protocol/http/Headers.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/net/protocol/http/Headers.java,v
+retrieving revision 1.11
+diff -u -3 -p -u -r1.11 Headers.java
+--- gnu/java/net/protocol/http/Headers.java	22 Dec 2006 00:40:23 -0000	1.11
++++ gnu/java/net/protocol/http/Headers.java	1 Mar 2008 10:09:02 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package gnu.java.net.protocol.http;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import gnu.java.net.LineInputStream;
+ 
+ import java.io.IOException;
+@@ -280,7 +282,7 @@ class Headers implements Iterable<Header
+       (LineInputStream) in : new LineInputStream(in);
+     
+     String name = null;
+-    StringBuilder value = new StringBuilder();
++    CPStringBuilder value = new CPStringBuilder();
+     while (true)
+       {
+         String line = lin.readLine();
+Index: gnu/java/net/protocol/http/Request.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/net/protocol/http/Request.java,v
+retrieving revision 1.14
+diff -u -3 -p -u -r1.14 Request.java
+--- gnu/java/net/protocol/http/Request.java	18 Sep 2007 21:52:28 -0000	1.14
++++ gnu/java/net/protocol/http/Request.java	1 Mar 2008 10:09:03 -0000
+@@ -38,6 +38,7 @@ exception statement from your version. *
+ 
+ package gnu.java.net.protocol.http;
+ 
++import gnu.java.lang.CPStringBuilder;
+ import gnu.java.net.LineInputStream;
+ import gnu.java.util.Base64;
+ 
+@@ -628,7 +629,7 @@ public class Request
+   {
+     int len = text.length();
+     String key = null;
+-    StringBuilder buf = new StringBuilder();
++    CPStringBuilder buf = new CPStringBuilder();
+     Properties ret = new Properties();
+     boolean inQuote = false;
+     for (int i = 0; i < len; i++)
+@@ -681,7 +682,7 @@ public class Request
+   {
+     int nc = connection.getNonceCount(nonce);
+     String hex = Integer.toHexString(nc);
+-    StringBuilder buf = new StringBuilder();
++    CPStringBuilder buf = new CPStringBuilder();
+     for (int i = 8 - hex.length(); i > 0; i--)
+       {
+         buf.append('0');
+@@ -752,7 +753,7 @@ public class Request
+ 
+     int len = text.length();
+     String attr = null;
+-    StringBuilder buf = new StringBuilder();
++    CPStringBuilder buf = new CPStringBuilder();
+     boolean inQuote = false;
+     for (int i = 0; i <= len; i++)
+       {
+Index: java/lang/reflect/Modifier.java
+===================================================================
+RCS file: /sources/classpath/classpath/java/lang/reflect/Modifier.java,v
+retrieving revision 1.13
+diff -u -3 -p -u -r1.13 Modifier.java
+--- java/lang/reflect/Modifier.java	1 Mar 2008 09:16:40 -0000	1.13
++++ java/lang/reflect/Modifier.java	1 Mar 2008 10:09:07 -0000
+@@ -38,7 +38,7 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
+-import gnu.classpath.CPStringBuilder;
++import gnu.java.lang.CPStringBuilder;
+ 
+ /**
+  * Modifier is a helper class with static methods to determine whether an
+Index: java/util/Formatter.java
+===================================================================
+RCS file: /sources/classpath/classpath/java/util/Formatter.java,v
+retrieving revision 1.4
+diff -u -3 -p -u -r1.4 Formatter.java
+--- java/util/Formatter.java	7 Jan 2008 21:11:25 -0000	1.4
++++ java/util/Formatter.java	1 Mar 2008 10:09:12 -0000
+@@ -38,6 +38,8 @@ exception statement from your version. *
+ 
+ package java.util;
+ 
++import gnu.java.lang.CPStringBuilder;
++
+ import java.io.Closeable;
+ import java.io.File;
+ import java.io.FileNotFoundException;
+@@ -470,7 +472,7 @@ public final class Formatter 
+    * @param width the width of the numeric value.
+    * @param isNegative true if the value is negative.
+    */
+-  private void applyLocalization(StringBuilder builder, int flags, int width,
++  private void applyLocalization(CPStringBuilder builder, int flags, int width,
+ 				 boolean isNegative)
+   {
+     DecimalFormatSymbols dfsyms;
+@@ -741,9 +743,9 @@ public final class Formatter 
+    * @param conversion the conversion character.
+    * @return the result.
+    */
+-  private StringBuilder basicIntegralConversion(Object arg, int flags,
+-						int width, int precision,
+-						int radix, char conversion)
++  private CPStringBuilder basicIntegralConversion(Object arg, int flags,
++						  int width, int precision,
++						  int radix, char conversion)
+   {
+     assert radix == 8 || radix == 10 || radix == 16;
+     noPrecision(precision);
+@@ -798,7 +800,7 @@ public final class Formatter 
+     else
+       throw new IllegalFormatConversionException(conversion, arg.getClass());
+ 
+-    return new StringBuilder(result);
++    return new CPStringBuilder(result);
+   }
+ 
+   /** 
+@@ -819,9 +821,9 @@ public final class Formatter 
+   {
+     assert radix == 8 || radix == 16;
+ 
+-    StringBuilder builder = basicIntegralConversion(arg, flags, width,
+-						    precision, radix,
+-						    conversion);
++    CPStringBuilder builder = basicIntegralConversion(arg, flags, width,
++						      precision, radix,
++						      conversion);
+     int insertPoint = 0;
+ 
+     // Insert the sign.
+@@ -897,9 +899,9 @@ public final class Formatter 
+ 				 int precision, char conversion)
+     throws IOException
+   {
+-    StringBuilder builder = basicIntegralConversion(arg, flags, width,
+-						    precision, 10,
+-						    conversion);
++    CPStringBuilder builder = basicIntegralConversion(arg, flags, width,
++						      precision, 10,
++						      conversion);
+     boolean isNegative = false;
+     if (builder.charAt(0) == '-')
+       {
+Index: vm/reference/java/lang/reflect/Constructor.java
+===================================================================
+RCS file: /sources/classpath/classpath/vm/reference/java/lang/reflect/Constructor.java,v
+retrieving revision 1.23
+diff -u -3 -p -u -r1.23 Constructor.java
+--- vm/reference/java/lang/reflect/Constructor.java	1 Mar 2008 09:16:41 -0000	1.23
++++ vm/reference/java/lang/reflect/Constructor.java	1 Mar 2008 10:09:17 -0000
+@@ -38,9 +38,8 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
+-import gnu.classpath.CPStringBuilder;
+-
+ import gnu.java.lang.ClassHelper;
++import gnu.java.lang.CPStringBuilder;
+ 
+ import gnu.java.lang.reflect.MethodSignatureParser;
+ 
+Index: vm/reference/java/lang/reflect/Field.java
+===================================================================
+RCS file: /sources/classpath/classpath/vm/reference/java/lang/reflect/Field.java,v
+retrieving revision 1.16
+diff -u -3 -p -u -r1.16 Field.java
+--- vm/reference/java/lang/reflect/Field.java	1 Mar 2008 09:16:41 -0000	1.16
++++ vm/reference/java/lang/reflect/Field.java	1 Mar 2008 10:09:17 -0000
+@@ -38,9 +38,8 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
+-import gnu.classpath.CPStringBuilder;
+-
+ import gnu.java.lang.ClassHelper;
++import gnu.java.lang.CPStringBuilder;
+ 
+ import gnu.java.lang.reflect.FieldSignatureParser;
+ 
+Index: vm/reference/java/lang/reflect/Method.java
+===================================================================
+RCS file: /sources/classpath/classpath/vm/reference/java/lang/reflect/Method.java,v
+retrieving revision 1.24
+diff -u -3 -p -u -r1.24 Method.java
+--- vm/reference/java/lang/reflect/Method.java	1 Mar 2008 09:16:41 -0000	1.24
++++ vm/reference/java/lang/reflect/Method.java	1 Mar 2008 10:09:17 -0000
+@@ -38,9 +38,8 @@ exception statement from your version. *
+ 
+ package java.lang.reflect;
+ 
+-import gnu.classpath.CPStringBuilder;
+-
+ import gnu.java.lang.ClassHelper;
++import gnu.java.lang.CPStringBuilder;
+ 
+ import gnu.java.lang.reflect.MethodSignatureParser;
+ 
Index: build/components/patches/classpath-web.RVM-266-04.patch
===================================================================
--- build/components/patches/classpath-web.RVM-266-04.patch	(revision 0)
+++ build/components/patches/classpath-web.RVM-266-04.patch	(revision 0)
@@ -0,0 +1,15 @@
+Index: gnu/java/lang/CPStringBuilder.java
+===================================================================
+RCS file: /sources/classpath/classpath/gnu/java/lang/CPStringBuilder.java,v
+retrieving revision 1.1
+diff -u -3 -p -u -r1.1 CPStringBuilder.java
+--- gnu/java/lang/CPStringBuilder.java	1 Mar 2008 10:13:30 -0000	1.1
++++ gnu/java/lang/CPStringBuilder.java	1 Mar 2008 12:00:40 -0000
+@@ -87,6 +87,7 @@ public final class CPStringBuilder
+       {
+ 	cons = String.class.getDeclaredConstructor(char[].class, Integer.TYPE,
+ 						   Integer.TYPE, Boolean.TYPE);
++	cons.setAccessible(true);
+       }
+     catch (NoSuchMethodException e)
+       {
Index: libraries/javalib/vmspecific/java/lang/reflect/Constructor.java
===================================================================
RCS file: /cvs/kaffe/kaffe/libraries/javalib/vmspecific/java/lang/reflect/Constructor.java,v
retrieving revision 1.4
diff -u -3 -p -u -r1.4 Constructor.java
--- libraries/javalib/vmspecific/java/lang/reflect/Constructor.java	22 May 2006 15:22:55 -0000	1.4
+++ libraries/javalib/vmspecific/java/lang/reflect/Constructor.java	1 Mar 2008 12:17:04 -0000
@@ -39,6 +39,7 @@ exception statement from your version. *
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 
 import gnu.java.lang.reflect.MethodSignatureParser;
 
@@ -231,7 +232,7 @@ public final class Constructor
   public String toString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getDeclaringClass().getName()).append('(');
     Class[] c = getParameterTypes();
@@ -253,7 +254,7 @@ public final class Constructor
   }
 
   /* FIXME[GENERICS]: Add X extends GenericDeclaration and TypeVariable<X> */
-  static void addTypeParameters(StringBuilder sb, TypeVariable[] typeArgs)
+  static void addTypeParameters(CPStringBuilder sb, TypeVariable[] typeArgs)
   {
     if (typeArgs.length == 0)
       return;
@@ -269,7 +270,7 @@ public final class Constructor
 
   public String toGenericString()
   {
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     addTypeParameters(sb, getTypeParameters());
     sb.append(getDeclaringClass().getName()).append('(');
Index: libraries/javalib/vmspecific/java/lang/reflect/Field.java
===================================================================
RCS file: /cvs/kaffe/kaffe/libraries/javalib/vmspecific/java/lang/reflect/Field.java,v
retrieving revision 1.7
diff -u -3 -p -u -r1.7 Field.java
--- libraries/javalib/vmspecific/java/lang/reflect/Field.java	22 May 2006 15:22:55 -0000	1.7
+++ libraries/javalib/vmspecific/java/lang/reflect/Field.java	1 Mar 2008 12:17:04 -0000
@@ -39,6 +39,7 @@ exception statement from your version. *
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 
 import gnu.java.lang.reflect.FieldSignatureParser;
 
@@ -210,7 +211,7 @@ extends AccessibleObject implements Memb
   public String toString()
   {
     // 64 is a reasonable buffer initial size for field
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(ClassHelper.getUserName(getType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -220,7 +221,7 @@ extends AccessibleObject implements Memb
  
   public String toGenericString()
   {
-    StringBuilder sb = new StringBuilder(64);
+    CPStringBuilder sb = new CPStringBuilder(64);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(getGenericType()).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
Index: libraries/javalib/vmspecific/java/lang/reflect/Method.java
===================================================================
RCS file: /cvs/kaffe/kaffe/libraries/javalib/vmspecific/java/lang/reflect/Method.java,v
retrieving revision 1.4
diff -u -3 -p -u -r1.4 Method.java
--- libraries/javalib/vmspecific/java/lang/reflect/Method.java	22 May 2006 15:22:55 -0000	1.4
+++ libraries/javalib/vmspecific/java/lang/reflect/Method.java	1 Mar 2008 12:17:04 -0000
@@ -39,6 +39,7 @@ exception statement from your version. *
 package java.lang.reflect;
 
 import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
 
 import gnu.java.lang.reflect.MethodSignatureParser;
 
@@ -282,7 +283,7 @@ extends AccessibleObject implements Memb
   public String toString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     sb.append(ClassHelper.getUserName(getReturnType())).append(' ');
     sb.append(getDeclaringClass().getName()).append('.');
@@ -308,7 +309,7 @@ extends AccessibleObject implements Memb
   public String toGenericString()
   {
     // 128 is a reasonable buffer initial size for constructor
-    StringBuilder sb = new StringBuilder(128);
+    CPStringBuilder sb = new CPStringBuilder(128);
     Modifier.toString(getModifiers(), sb).append(' ');
     Constructor.addTypeParameters(sb, getTypeParameters());
     sb.append(getGenericReturnType()).append(' ');

[Index of Archives]     [Linux Kernel]     [Linux Cryptography]     [Fedora]     [Fedora Directory]     [Red Hat Development]

  Powered by Linux