- adds StringBuilder to the Java emulation classes,
  using the existing implementation from StringBuffer
- makes the emulated StringBuffer be simply a wrapper
  around StringBuilder
- adds some methods to StringBuffer and StringBuilder that
  are new to Java 1.5

Review by: scottb (postmortem)




git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2074 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/super/com/google/gwt/emul/java/lang/StringBuffer.java b/user/super/com/google/gwt/emul/java/lang/StringBuffer.java
index 55b601b..fdfedb6 100644
--- a/user/super/com/google/gwt/emul/java/lang/StringBuffer.java
+++ b/user/super/com/google/gwt/emul/java/lang/StringBuffer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
@@ -16,243 +16,228 @@
 package java.lang;
 
 /**
- * A fast way to create strings using multiple appends. This implementation is
- * optimized for fast appends. Most methods will give expected performance
- * results, with the notable exception of {@link #setCharAt(int, char)}, which
- * is extremely slow and should be avoided if possible.
+ * A fast way to create strings using multiple appends. This is implemented
+ * using {@link StringBuilder}, so see that class for implementation notes and
+ * performance characteristics.
  */
-public final class StringBuffer implements CharSequence {
-
-  private static native String setLength(String[] stringArray, int length) /*-{
-    stringArray.length = length;
-  }-*/;
-
-  private static native String join(String[] stringArray) /*-{
-    return stringArray.join('');
-  }-*/;
-
-  private String[] stringArray = new String[0];
-
-  private int arrayLen = 0;
-
-  private int stringLength = 0;
+public class StringBuffer implements CharSequence {
+  private final StringBuilder builder = new StringBuilder();
 
   public StringBuffer() {
   }
 
-  /**
-   * This implementation does not track capacity; using this constructor is
-   * functionally equivalent to using the zero-argument constructor.
-   */
   public StringBuffer(int ignoredLength) {
   }
 
+  public StringBuffer(CharSequence s) {
+    this(s.toString());
+  }
+
   public StringBuffer(String s) {
     append(s);
   }
 
   public StringBuffer append(boolean x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(char x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(char[] x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(char[] x, int start, int len) {
-    return append(String.valueOf(x, start, len));
+    builder.append(x, start, len);
+    return this;
+  }
+
+  public StringBuffer append(CharSequence x) {
+    builder.append(x);
+    return this;
+  }
+
+  public StringBuffer append(CharSequence x, int start, int end) {
+    builder.append(x, start, end);
+    return this;
   }
 
   public StringBuffer append(double x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(float x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(int x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(long x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(Object x) {
-    return append(String.valueOf(x));
+    builder.append(x);
+    return this;
   }
 
   public StringBuffer append(String toAppend) {
-    // Coerce to "null" if null.
-    if (toAppend == null) {
-      toAppend = "null";
-    }
-    int appendLength = toAppend.length();
-    if (appendLength > 0) {
-      stringArray[arrayLen++] = toAppend;
-      stringLength += appendLength;
-      /*
-       * If we hit 1k elements, let's do a join to reduce the array size. This
-       * number was arrived at experimentally through benchmarking.
-       */
-      if (arrayLen > 1024) {
-        toString();
-        // Preallocate the next 1024 (faster on FF).
-        setLength(stringArray, 1024);
-      }
-    }
+    builder.append(toAppend);
     return this;
   };
 
   public StringBuffer append(StringBuffer x) {
-    return append(String.valueOf(x));
-  }
-
-  public char charAt(int index) {
-    return toString().charAt(index);
-  }
-
-  public StringBuffer delete(int start, int end) {
-    return replace(start, end, "");
-  }
-
-  public StringBuffer deleteCharAt(int start) {
-    return delete(start, start + 1);
-  }
-
-  public void getChars(int srcStart, int srcEnd, char[] dst, int dstStart) {
-    String.__checkBounds(stringLength, srcStart, srcEnd);
-    String.__checkBounds(dst.length, dstStart, dstStart + (srcEnd - srcStart));
-    String s = toString();
-    while (srcStart < srcEnd) {
-      dst[dstStart++] = s.charAt(srcStart++);
-    }
-  }
-
-  public int indexOf(String x) {
-    return toString().indexOf(x);
-  }
-
-  public int indexOf(String x, int start) {
-    return toString().indexOf(x, start);
-  }
-
-  public StringBuffer insert(int index, boolean x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, char x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, char[] x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, char[] x, int offset, int len) {
-    return insert(index, String.valueOf(x, offset, len));
-  }
-
-  public StringBuffer insert(int index, double x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, float x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, int x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, long x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, Object x) {
-    return insert(index, String.valueOf(x));
-  }
-
-  public StringBuffer insert(int index, String x) {
-    return replace(index, index, x);
-  }
-
-  public int lastIndexOf(String s) {
-    return toString().lastIndexOf(s);
-  }
-
-  public int lastIndexOf(String s, int start) {
-    return toString().lastIndexOf(s, start);
-  }
-
-  public int length() {
-    return stringLength;
-  }
-
-  public StringBuffer replace(int start, int end, String toInsert) {
-    // Get the joined string.
-    String s = toString();
-
-    // Build a new buffer in pieces (will throw exceptions).
-    stringArray = new String[] {
-        s.substring(0, start), toInsert, s.substring(end)};
-    arrayLen = 3;
-
-    // Calculate the new string length.
-    stringLength += toInsert.length() - (end - start);
-
+    builder.append(x);
     return this;
   }
 
-  /**
-   * Warning! This method is <b>much</b> slower than the JRE implementation. If
-   * you need to do character level manipulation, you are strongly advised to
-   * use a char[] directly.
-   */
+  public int capacity() {
+    return builder.capacity();
+  }
+
+  public char charAt(int index) {
+    return builder.charAt(index);
+  }
+
+  public StringBuffer delete(int start, int end) {
+    builder.delete(start, end);
+    return this;
+  }
+
+  public StringBuffer deleteCharAt(int start) {
+    builder.deleteCharAt(start);
+    return this;
+  }
+
+  public void ensureCapacity(int ignored) {
+  }
+
+  public void getChars(int srcStart, int srcEnd, char[] dst, int dstStart) {
+    builder.getChars(srcStart, srcEnd, dst, dstStart);
+  }
+
+  public int indexOf(String x) {
+    return builder.indexOf(x);
+  }
+
+  public int indexOf(String x, int start) {
+    return builder.indexOf(x, start);
+  }
+
+  public StringBuffer insert(int index, boolean x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, char x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, char[] x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, char[] x, int offset, int len) {
+    builder.insert(index, x, offset, len);
+    return this;
+  }
+
+  public StringBuffer insert(int index, CharSequence chars) {
+    builder.insert(index, chars);
+    return this;
+  }
+
+  public StringBuffer insert(int index, CharSequence chars, int start, int end) {
+    builder.insert(index, chars, start, end);
+    return this;
+  }
+
+  public StringBuffer insert(int index, double x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, float x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, int x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, long x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, Object x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public StringBuffer insert(int index, String x) {
+    builder.insert(index, x);
+    return this;
+  }
+
+  public int lastIndexOf(String s) {
+    return builder.lastIndexOf(s);
+  }
+
+  public int lastIndexOf(String s, int start) {
+    return builder.lastIndexOf(s, start);
+  }
+
+  public int length() {
+    return builder.length();
+  }
+
+  public StringBuffer replace(int start, int end, String toInsert) {
+    builder.replace(start, end, toInsert);
+    return this;
+  }
+
   public void setCharAt(int index, char x) {
-    replace(index, index + 1, String.valueOf(x));
+    builder.setCharAt(index, x);
   }
 
   public void setLength(int newLength) {
-    int oldLength = stringLength;
-    if (newLength < oldLength) {
-      delete(newLength, oldLength);
-    } else if (newLength > oldLength) {
-      append(new char[newLength - oldLength]);
-    }
+    builder.setLength(newLength);
   }
 
   public CharSequence subSequence(int start, int end) {
-    return this.substring(start, end);
+    return builder.subSequence(start, end);
   }
 
   public String substring(int begin) {
-    return toString().substring(begin);
+    return builder.substring(begin);
   }
 
   public String substring(int begin, int end) {
-    return toString().substring(begin, end);
+    return builder.substring(begin, end);
   }
 
   @Override
   public String toString() {
-    /*
-     * Normalize the array to exactly one element (even if it's completely
-     * empty), so we can unconditionally grab the first element.
-     */
-    if (arrayLen != 1) {
-      setLength(stringArray, arrayLen);
-      String s = join(stringArray);
-      // Create a new array to allow everything to get GC'd.
-      stringArray = new String[] {s};
-      arrayLen = 1;
-    }
-    return stringArray[0];
+    return builder.toString();
   }
 
+  public void trimToSize() {
+    builder.trimToSize();
+  }
 }
diff --git a/user/super/com/google/gwt/emul/java/lang/StringBuilder.java b/user/super/com/google/gwt/emul/java/lang/StringBuilder.java
new file mode 100644
index 0000000..84a6368
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/lang/StringBuilder.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package java.lang;
+
+/**
+ * A fast way to create strings using multiple appends. This
+ * implementation is optimized for fast appends. Most methods will give expected
+ * performance results, with the notable exception of
+ * {@link #setCharAt(int, char)}, which is extremely slow and should be avoided
+ * if possible.
+ */
+public class StringBuilder implements CharSequence {
+
+  private static native String setLength(String[] stringArray, int length) /*-{
+    stringArray.length = length;
+  }-*/;
+
+  private static native String join(String[] stringArray) /*-{
+    return stringArray.join('');
+  }-*/;
+
+  private String[] stringArray = new String[0];
+
+  private int arrayLen = 0;
+
+  private int stringLength = 0;
+
+  public StringBuilder() {
+  }
+
+  /**
+   * This implementation does not track capacity; using this constructor is
+   * functionally equivalent to using the zero-argument constructor.
+   */
+  public StringBuilder(int ignoredLength) {
+  }
+
+  public StringBuilder(CharSequence s) {
+    this(s.toString());
+  }
+
+  public StringBuilder(String s) {
+    append(s);
+  }
+
+  public StringBuilder append(boolean x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(char x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(char[] x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(char[] x, int start, int len) {
+    return append(String.valueOf(x, start, len));
+  }
+
+  public StringBuilder append(CharSequence x) {
+    return append(x.toString());
+  }
+
+  public StringBuilder append(CharSequence x, int start, int end) {
+    return append(x.subSequence(start, end));
+  }
+
+  public StringBuilder append(double x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(float x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(int x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(long x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(Object x) {
+    return append(String.valueOf(x));
+  }
+
+  public StringBuilder append(String toAppend) {
+    // Coerce to "null" if null.
+    if (toAppend == null) {
+      toAppend = "null";
+    }
+    int appendLength = toAppend.length();
+    if (appendLength > 0) {
+      stringArray[arrayLen++] = toAppend;
+      stringLength += appendLength;
+      /*
+       * If we hit 1k elements, let's do a join to reduce the array size. This
+       * number was arrived at experimentally through benchmarking.
+       */
+      if (arrayLen > 1024) {
+        toString();
+        // Preallocate the next 1024 (faster on FF).
+        setLength(stringArray, 1024);
+      }
+    }
+    return this;
+  };
+
+  public StringBuilder append(StringBuffer x) {
+    return append(String.valueOf(x));
+  }
+
+  public int capacity() {
+    return length() * 2 + 1000;
+  }
+
+  public char charAt(int index) {
+    return toString().charAt(index);
+  }
+
+  public StringBuilder delete(int start, int end) {
+    return replace(start, end, "");
+  }
+
+  public StringBuilder deleteCharAt(int start) {
+    return delete(start, start + 1);
+  }
+
+  public void ensureCapacity(int ignored) {
+  }
+
+  public void getChars(int srcStart, int srcEnd, char[] dst, int dstStart) {
+    String.__checkBounds(stringLength, srcStart, srcEnd);
+    String.__checkBounds(dst.length, dstStart, dstStart + (srcEnd - srcStart));
+    String s = toString();
+    while (srcStart < srcEnd) {
+      dst[dstStart++] = s.charAt(srcStart++);
+    }
+  }
+
+  public int indexOf(String x) {
+    return toString().indexOf(x);
+  }
+
+  public int indexOf(String x, int start) {
+    return toString().indexOf(x, start);
+  }
+
+  public StringBuilder insert(int index, boolean x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, char x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, char[] x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, char[] x, int offset, int len) {
+    return insert(index, String.valueOf(x, offset, len));
+  }
+
+  public StringBuilder insert(int index, CharSequence chars) {
+    return insert(index, chars.toString());
+  }
+
+  public StringBuilder insert(int index, CharSequence chars, int start, int end) {
+    return insert(index, chars.subSequence(start, end).toString());
+  }
+
+  public StringBuilder insert(int index, double x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, float x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, int x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, long x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, Object x) {
+    return insert(index, String.valueOf(x));
+  }
+
+  public StringBuilder insert(int index, String x) {
+    return replace(index, index, x);
+  }
+
+  public int lastIndexOf(String s) {
+    return toString().lastIndexOf(s);
+  }
+
+  public int lastIndexOf(String s, int start) {
+    return toString().lastIndexOf(s, start);
+  }
+
+  public int length() {
+    return stringLength;
+  }
+
+  public StringBuilder replace(int start, int end, String toInsert) {
+    // Get the joined string.
+    String s = toString();
+
+    // Build a new buffer in pieces (will throw exceptions).
+    stringArray = new String[] {
+        s.substring(0, start), toInsert, s.substring(end)};
+    arrayLen = 3;
+
+    // Calculate the new string length.
+    stringLength += toInsert.length() - (end - start);
+
+    return this;
+  }
+
+  /**
+   * Warning! This method is <b>much</b> slower than the JRE implementation. If
+   * you need to do character level manipulation, you are strongly advised to
+   * use a char[] directly.
+   */
+  public void setCharAt(int index, char x) {
+    replace(index, index + 1, String.valueOf(x));
+  }
+
+  public void setLength(int newLength) {
+    int oldLength = stringLength;
+    if (newLength < oldLength) {
+      delete(newLength, oldLength);
+    } else if (newLength > oldLength) {
+      append(new char[newLength - oldLength]);
+    }
+  }
+
+  public CharSequence subSequence(int start, int end) {
+    return this.substring(start, end);
+  }
+
+  public String substring(int begin) {
+    return toString().substring(begin);
+  }
+
+  public String substring(int begin, int end) {
+    return toString().substring(begin, end);
+  }
+
+  @Override
+  public String toString() {
+    /*
+     * Normalize the array to exactly one element (even if it's completely
+     * empty), so we can unconditionally grab the first element.
+     */
+    if (arrayLen != 1) {
+      setLength(stringArray, arrayLen);
+      String s = join(stringArray);
+      // Create a new array to allow everything to get GC'd.
+      stringArray = new String[] {s};
+      arrayLen = 1;
+    }
+    return stringArray[0];
+  }
+
+  public void trimToSize() {
+  }
+}
diff --git a/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java b/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java
index 685cdcd..27b568a 100644
--- a/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
@@ -18,10 +18,9 @@
 import com.google.gwt.junit.client.GWTTestCase;
 
 /**
- * This class tests StringBuffer.
+ * This class tests classes StringBuffer and StringBuilder.
  */
 public class StringBufferTest extends GWTTestCase {
-
   /**
    * This method gets the module name.
    * 
@@ -66,6 +65,23 @@
     x = new StringBuffer();
     x.append((String) null);
     assertEquals("null", x.toString());
+    x = new StringBuffer();
+    x.append((CharSequence) "abc");
+    assertEquals("abc", x.toString());
+    x = new StringBuffer();
+    x.append((CharSequence) "abcde", 2, 3);
+    assertEquals("c", x.toString());
+  }
+
+  /**
+   * Check that capacity methods are present, even though
+   * they do nothing.
+   */
+  public void testCapacity() {
+    StringBuffer buf = new StringBuffer();
+    buf.ensureCapacity(100);
+    assertTrue(buf.capacity() >= 0);
+    buf.trimToSize();
   }
 
   /**
@@ -82,6 +98,7 @@
     String constant = "abcdef";
     assertEquals(new StringBuffer(constant).toString(), constant);
     assertEquals(new StringBuffer().toString(), "");
+    assertEquals(new StringBuffer((CharSequence) constant).toString(), constant);
   }
 
   /**
@@ -149,6 +166,12 @@
     x = new StringBuffer("!");
     x.insert(1, C.CHAR_ARRAY_VALUE, 1, 4);
     assertEquals("!" + C.CHAR_ARRAY_STRING.substring(1, 5), x.toString());
+    x = new StringBuffer("01234");
+    x.insert(2, (CharSequence) "abcde");
+    assertEquals("01abcde234", x.toString());
+    x = new StringBuffer("01234");
+    x.insert(2, (CharSequence) "abcde", 2, 4);
+    assertEquals("01cd234", x.toString());
     x = new StringBuffer("!");
     x.insert(1, C.FALSE_VALUE);
     assertEquals("!" + C.FALSE_STRING, x.toString());
@@ -272,7 +295,195 @@
   }
 
   /**
-   * This method tests <code>ubstring</code>.
+   * A smoke test that StringBuilder's methods are available and basically work.
+   * The implementation is currently shared with StringBuffer, so all the tricky
+   * test cases are not repeated.
+   */
+  public void testStringBuilder() {
+    StringBuilder bld = new StringBuilder();
+    bld = new StringBuilder(100);
+    bld = new StringBuilder("abc");
+    assertEquals("abc", bld.toString());
+
+    bld = new StringBuilder((CharSequence) "abc");
+    assertEquals("abc", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(true);
+    assertEquals("true", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append('a');
+    assertEquals("a", bld.toString());
+
+    bld = new StringBuilder();
+    char[] abcde = {'a', 'b', 'c', 'd', 'e'};
+    bld.append(abcde);
+    assertEquals("abcde", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(abcde, 1, 3);
+    assertEquals("bcd", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append((CharSequence) "abcde");
+    assertEquals("abcde", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append((CharSequence) "abcde", 2, 4);
+    assertEquals("cd", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(1.0);
+    assertEquals("1.0", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(1.0F);
+    assertEquals("1.0", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(5);
+    assertEquals("5", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(5L);
+    assertEquals("5", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(new Object() {
+      public String toString() {
+        return "obj";
+      }
+    });
+    assertEquals("obj", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append("abc");
+    assertEquals("abc", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append(new StringBuffer("abc"));
+    assertEquals("abc", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append("abcde");
+    assertEquals('c', bld.charAt(2));
+
+    bld = new StringBuilder();
+    bld.append("abcde");
+    bld.delete(1, 2);
+    assertEquals("acde", bld.toString());
+
+    bld = new StringBuilder();
+    bld.append("abcde");
+    bld.deleteCharAt(2);
+    assertEquals("abde", bld.toString());
+
+    // check that capacity methods are present
+    bld = new StringBuilder();
+    assertTrue(bld.capacity() >= 0);
+    bld.ensureCapacity(100);
+    bld.trimToSize();
+
+    bld = new StringBuilder();
+    bld.append("abcde");
+    char[] chars = {'0', '0', '0', '0', '0'};
+    bld.getChars(2, 4, chars, 2);
+    assertEquals('0', chars[0]);
+    assertEquals('0', chars[1]);
+    assertEquals('c', chars[2]);
+    assertEquals('d', chars[3]);
+    assertEquals('0', chars[4]);
+
+    bld = new StringBuilder("01234");
+    assertEquals(2, bld.indexOf("23"));
+
+    bld = new StringBuilder();
+    bld.append("0123401234");
+    assertEquals(5, bld.indexOf("0123", 1));
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, true);
+    assertEquals("01true234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, 'X');
+    assertEquals("01X234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    char[] chars2 = {'a', 'b', 'c', 'd', 'e'};
+    bld.insert(2, chars2, 3, 2);
+    assertEquals("01de234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, (CharSequence) "abcde");
+    assertEquals("01abcde234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, (CharSequence) "abcde", 2, 4);
+    assertEquals("01cd234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, 1.0);
+    assertEquals("011.0234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, 1.0F);
+    assertEquals("011.0234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, 99);
+    assertEquals("0199234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, 99L);
+    assertEquals("0199234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, new Object() {
+      public String toString() {
+        return "obj";
+      }
+    });
+    assertEquals("01obj234", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.insert(2, "XX");
+    assertEquals("01XX234", bld.toString());
+
+    bld = new StringBuilder("0123401234");
+    assertEquals(5, bld.lastIndexOf("0123"));
+
+    bld = new StringBuilder("0123401234");
+    assertEquals(0, bld.lastIndexOf("0123", 4));
+
+    bld = new StringBuilder("01234");
+    assertEquals(5, bld.length());
+
+    bld = new StringBuilder("01234");
+    bld.replace(2, 3, "XYZ");
+    assertEquals("01XYZ34", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.setCharAt(2, 'X');
+    assertEquals("01X34", bld.toString());
+
+    bld = new StringBuilder("01234");
+    bld.setLength(2);
+    assertEquals("01", bld.toString());
+
+    bld = new StringBuilder("01234");
+    assertEquals("23", bld.subSequence(2, 4));
+
+    bld = new StringBuilder("01234");
+    assertEquals("234", bld.substring(2));
+
+    bld = new StringBuilder("01234");
+    assertEquals("23", bld.substring(2, 4));
+  }
+
+  /**
+   * This method tests <code>substring</code>.
    */
   public void testSubstring() {
     StringBuffer haystack = new StringBuffer("abcdefghi");