This is the mail archive of the java-patches@sourceware.cygnus.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: StringBuffer fixes


I checked in the following patch to both libgcj and classpath. It fixes
a few problems I noticed with the new, merged implementation, including
the delete() bug reported by <MSlattery@searchsoft.net>.

I also checked a small regression test (attached) in to the libgcj
testsuite.

regards

  [ bryce ]

2000-05-10  Bryce McKinlay  <bryce@albatross.co.nz>

	* java/lang/StringBuffer.java (delete): Call arrayCopy() correctly.
	Avoid arrayCopy() call where possible. Update `count' _after_ calling
	arrayCopy().
	(replace): Reimplemented. Fix javadoc.
	(reverse): Call ensureCapacity_unsynchronized().
	(StringBuffer (String)): Use DEFAULT_CAPACITY.

Index: StringBuffer.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/StringBuffer.java,v
retrieving revision 1.5
diff -u -r1.5 StringBuffer.java
--- StringBuffer.java	2000/05/09 22:46:58	1.5
+++ StringBuffer.java	2000/05/10 09:39:38
@@ -227,8 +227,9 @@
       end = count;
     // This will unshare if required.
     ensureCapacity_unsynchronized (count);
+    if (count - end != 0)
+      System.arraycopy (value, end, value, start, count - end);
     count -= (end - start);
-    System.arraycopy (value, end - 1, value, start, end - start);
     return this;
   }
 
@@ -498,17 +499,31 @@
     return count;
   }
 
-  /** Delete a character from this <code>StringBuffer</code>.
-   *  @param index the index of the character to delete.
+  /** 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>.
-   *  @exception StringIndexOutOfBoundsException if <code>index</code>
-   *             is out of bounds.
    */
   public synchronized StringBuffer replace (int start, int end, String str)
   {
-    // FIXME: this is inefficient.
-    delete (start, end);
-    return insert (start, 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 - start);
+    
+    str.getChars (0, len, value, start);    
+    count += delta;    
+    return this;    
   }
 
   /** Reverse the characters in this StringBuffer.
@@ -516,6 +531,8 @@
    */
   public synchronized StringBuffer reverse ()
   {
+    // Call ensureCapacity to enforce copy-on-write.
+    ensureCapacity_unsynchronized (count);
     for (int i = 0; i < count / 2; ++i)
       {
 	char c = value[i];
@@ -594,7 +611,7 @@
     count = str.length();
     // JLS: The initial capacity of the string buffer is 16 plus the
     // length of the argument string.
-    value = new char[count + 16];
+    value = new char[count + DEFAULT_CAPACITY];
     str.getChars(0, count, value, 0);
     shared = false;
   }
// Test StringBuffer.replace(), reverse(), insert(String), append(String), 
// and delete().

public class StringBuffer_1
{
  public static void main(String args[])
  {
    StringBuffer sb = new StringBuffer("45");
    sb.insert(0, "123");
    sb.append("89");
    sb.insert(5, "6");
    sb.insert(6, '7');
    System.out.println (sb);
    
    sb.delete (3, 99);
    
    String foo = sb.toString();
    
    System.out.println (foo);
    sb.reverse();
    System.out.println (foo);

    System.out.println (sb);
    sb = new StringBuffer("1234");    
    System.out.println(sb.reverse());
    
    sb = new StringBuffer("123456789");
    sb.append ("0");
    System.out.println(sb);

    sb.replace (2, 99, "foo");
    System.out.println (sb);

    sb = new StringBuffer("123456789");
    sb.replace (1, 1, "XX");
    System.out.println (sb);

    sb = new StringBuffer("123456789");
    sb.replace (0, 2, "XX");
    System.out.println (sb);

    sb = new StringBuffer("123456789");
    sb.replace (5, 9, "54321");
    System.out.println (sb);

    sb = new StringBuffer("123456789");
    
    sb.delete (1,4);
    System.out.println (sb);    

    // Test bounds checks
    try
    {
      sb.insert (-2, "x");
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }

    try
    {
      sb.insert (96, "x");
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }

    try
    {
      sb.delete (-2, 2);
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }

    try
    {
      sb.delete (96, 418);
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }

    try
    {
      sb.delete (4, 2);
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }

    try
    {
      sb.replace (-2, 2, "54321");
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }

    try
    {
      sb.replace (4, 2, "54321");
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }

    try
    {
      sb.replace (12, 18, "54321");
    }
    catch (StringIndexOutOfBoundsException x)
    {
      System.out.println (x.getClass());
    }
  }
}
123456789
123
123
321
4321
1234567890
12foo
1XX23456789
XX3456789
1234554321
156789
class java.lang.StringIndexOutOfBoundsException
class java.lang.StringIndexOutOfBoundsException
class java.lang.StringIndexOutOfBoundsException
class java.lang.StringIndexOutOfBoundsException
class java.lang.StringIndexOutOfBoundsException
class java.lang.StringIndexOutOfBoundsException
class java.lang.StringIndexOutOfBoundsException
class java.lang.StringIndexOutOfBoundsException

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]