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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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(' ');