/[classpath]/classpath/java/lang/StringBuffer.java
ViewVC logotype

Diff of /classpath/java/lang/StringBuffer.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.18 by mark, Fri Feb 15 14:39:27 2002 UTC revision 1.19 by ericb, Thu Mar 7 07:33:32 2002 UTC
# Line 7  GNU Classpath is free software; you can Line 7  GNU Classpath is free software; you can
7  it under the terms of the GNU General Public License as published by  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2, or (at your option)  the Free Software Foundation; either version 2, or (at your option)
9  any later version.  any later version.
10    
11  GNU Classpath is distributed in the hope that it will be useful, but  GNU Classpath is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Line 36  obligated to do so.  If you do not wish Line 36  obligated to do so.  If you do not wish
36  exception statement from your version. */  exception statement from your version. */
37    
38  package java.lang;  package java.lang;
 import java.io.Serializable;  
39    
40  /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3  import java.io.Serializable;
  * Updated using online JDK 1.2 docs.  
  * Believed complete and correct to JDK 1.2.  
  * 1.4 compatibility August 22, 2001 - Isaac Jones  
  * Merged with Classpath.  
  */  
41    
42  /**  /**
43   * <code>StringBuffer</code> represents a changeable <code>String</code>.   * <code>StringBuffer</code> represents a changeable <code>String</code>.
44   * It provides the operations required to modify the   * It provides the operations required to modify the
45   * <code>StringBuffer</code> including insert, replace, delete, append,   * <code>StringBuffer</code>, including insert, replace, delete, append,
46   * and reverse.   * and reverse. It is thread-safe; meaning that all modifications to a buffer
47   * <P>   * are in synchronized methods.
48   *   *
49   * <code>StringBuffer</code>s are variable-length in nature, so even if   * <p><code>StringBuffer</code>s are variable-length in nature, so even if
50   * you initialize them to a certain size, they can still grow larger than   * you initialize them to a certain size, they can still grow larger than
51   * that.  <EM>Capacity</EM> indicates the number of characters the   * that. <em>Capacity</em> indicates the number of characters the
52   * <code>StringBuffer</code> can have in it before it has to grow (growing   * <code>StringBuffer</code> can have in it before it has to grow (growing
53   * the char array is an expensive operation involving <code>new</code>).   * the char array is an expensive operation involving <code>new</code>).
  * <P>  
54   *   *
55   * Incidentally, the String operator "+" actually is turned into a   * <p>Incidentally, compilers often implement the String operator "+"
56   * <code>StringBuffer</code> operation:   * by using a <code>StringBuffer</code> operation:<br>
57   * <BR>   * <code>a + b</code><br>
58   * <code>a + b</code>   * is the same as<br>
59   * <BR>   * <code>new StringBuffer().append(a).append(b).toString()</code>.
  * is the same as  
  * <BR>  
  * <code>new StringBuffer(a).append(b).toString()</code>.  
60   *   *
61   * @implnote Classpath's StringBuffer is capable of sharing memory with   * <p>Classpath's StringBuffer is capable of sharing memory with Strings for
62   *           Strings for efficiency.  This will help in two instances:   * efficiency.  This will help in two instances: first, when a StringBuffer
63   *           first, when a StringBuffer is created from a String but is   * is created from a String but is never changed, and second, when a
64   *           never changed, and second, when a StringBuffer is converted   * StringBuffer is converted to a String and the StringBuffer is not changed
65   *           to a String and the StringBuffer is not changed after that.   * after that.
66   *   *
  * @since JDK1.0  
67   * @author Paul Fisher   * @author Paul Fisher
68   * @author John Keiser   * @author John Keiser
69   * @author Tom Tromey   * @author Tom Tromey
70   * @see java.lang.String   * @author Eric Blake <ebb9@email.byu.edu>
71     * @see String
72     * @since 1.0
73     * @status updated to 1.4
74   */   */
75  public final class StringBuffer implements Serializable, CharSequence  public final class StringBuffer implements Serializable, CharSequence
76  {  {
77    /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.    /**
78     *  Uses <code>String.valueOf()</code> to convert to     * Compatible with JDK 1.0+.
79     *  <code>String</code>.     */
80     *  @param bool the <code>boolean</code> to convert and append.    private static final long serialVersionUID = 3388685877147921107L;
81     *  @return this <code>StringBuffer</code>.  
82     *  @see java.lang.String#valueOf(boolean)    /**
83       * Index of next available character (and thus the size of the current
84       * string contents).  Note that this has permissions set this way so that
85       * String can get the value.
86       *
87       * @serial the number of characters in the buffer
88       */
89      int count;
90    
91      /**
92       * The buffer.  Note that this has permissions set this way so that String
93       * can get the value.
94       *
95       * @serial the buffer
96       */
97      char[] value;
98    
99      /**
100       * True if the buffer is shared with another object (StringBuffer or
101       * String); this means the buffer must be copied before writing to it again.
102       * Note that this has permissions set this way so that String can get the
103       * value.
104       *
105       * @serial whether the buffer is shared
106     */     */
107    public StringBuffer append (boolean bool)    boolean shared;
108    
109      /**
110       * The default capacity of a buffer.
111       */
112      private final static int DEFAULT_CAPACITY = 16;
113    
114      /**
115       * Create a new StringBuffer with default capacity 16.
116       */
117      public StringBuffer()
118    {    {
119      return append (String.valueOf(bool));      this(DEFAULT_CAPACITY);
120    }    }
121    
122    /** Append the <code>char</code> to this <code>StringBuffer</code>.    /**
123     *  @param c the <code>char</code> to append.     * Create an empty <code>StringBuffer</code> with the specified initial
124     *  @return this <code>StringBuffer</code>.     * capacity.
125       *
126       * @param capacity the initial capacity
127       * @throws NegativeArraySizeException if capacity is negative
128     */     */
129    public synchronized StringBuffer append (char ch)    public StringBuffer(int capacity)
130    {    {
131      ensureCapacity_unsynchronized (count + 1);      value = new char[capacity];
     value[count++] = ch;  
     return this;  
132    }    }
133    
134    /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.    /**
135     *  Uses <code>String.valueOf()</code> to convert to     * Create a new <code>StringBuffer</code> with the characters in the
136     *  <code>String</code>.     * specified <code>String</code>. Initial capacity will be the size of the
137     *  @param inum the <code>int</code> to convert and append.     * String plus 16.
138     *  @return this <code>StringBuffer</code>.     *
139     *  @see java.lang.String#valueOf(int)     * @param str the <code>String</code> to convert
140       * @throws NullPointerException if str is null
141       * @XXX Optimize for sharing.
142     */     */
143    public StringBuffer append (int inum)    public StringBuffer(String str)
144    {    {
145      return append (String.valueOf(inum));      count = str.length();
146        value = new char[count + DEFAULT_CAPACITY];
147        str.getChars(0, count, value, 0);
148    }    }
149    
150    /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.    /**
151     *  Uses <code>String.valueOf()</code> to convert to     * Get the length of the <code>String</code> this <code>StringBuffer</code>
152     *  <code>String</code>.     * would create. Not to be confused with the <em>capacity</em> of the
153     *  @param lnum the <code>long</code> to convert and append.     * <code>StringBuffer</code>.
154     *  @return this <code>StringBuffer</code>.     *
155     *  @see java.lang.String#valueOf(long)     * @return the length of this <code>StringBuffer</code>
156       * @see #capacity()
157       * @see #setLength(int)
158     */     */
159    public StringBuffer append (long lnum)    public synchronized int length()
160    {    {
161      return append (String.valueOf(lnum));      return count;
162    }    }
163    
164    /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.    /**
165     *  Uses <code>String.valueOf()</code> to convert to     * Get the total number of characters this <code>StringBuffer</code> can
166     *  <code>String</code>.     * support before it must be grown.  Not to be confused with <em>length</em>.
167     *  @param fnum the <code>float</code> to convert and append.     *
168     *  @return this <code>StringBuffer</code>.     * @return the capacity of this <code>StringBuffer</code>
169     *  @see java.lang.String#valueOf(float)     * @see #length()
170       * @see #ensureCapacity(int)
171     */     */
172    public StringBuffer append (float fnum)    public synchronized int capacity()
173    {    {
174      return append (String.valueOf(fnum));      return value.length;
175    }    }
176    
177    /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.    /**
178     *  Uses <code>String.valueOf()</code> to convert to     * Increase the capacity of this <code>StringBuffer</code>. This will
179     *  <code>String</code>.     * ensure that an expensive growing operation will not occur until
180     *  @param dnum the <code>double</code> to convert and append.     * <code>minimumCapacity</code> is reached. The buffer is grown to the
181     *  @return this <code>StringBuffer</code>.     * larger of <code>minimumCapacity</code> and
182     *  @see java.lang.String#valueOf(double)     * <code>capacity() * 2 + 2</code>, if it is not already large enough.
183       *
184       * @param minimumCapacity the new capacity
185       * @see #capacity()
186     */     */
187    public StringBuffer append (double dnum)    public synchronized void ensureCapacity(int minimumCapacity)
188    {    {
189      return append (String.valueOf(dnum));      ensureCapacity_unsynchronized(minimumCapacity);
190    }    }
191        
192    /** Append the <code>StringBuffer</code> value of the argument to this    /**
193     * <code>StringBuffer</code>.     * Set the length of this StringBuffer. If the new length is greater than
194     *  Uses <code>StringBuffer.toString()</code> to convert to     * the current length, all the new characters are set to '\0'. If the new
195     *  <code>String</code>.     * length is less than the current length, the first <code>newLength</code>
196       * characters of the old array will be preserved, and the remaining
197       * characters are truncated.
198       *
199       * @param newLength the new length
200       * @throws IndexOutOfBoundsException if the new length is negative
201       *         (while unspecified, this is a StringIndexOutOfBoundsException)
202       * @see #length()
203       */
204      public synchronized void setLength(int newLength)
205      {
206        if (newLength < 0)
207          throw new StringIndexOutOfBoundsException(newLength);
208    
209        ensureCapacity_unsynchronized(newLength);
210        for (int i = count; i < newLength; ++i)
211          value[i] = '\0';
212        count = newLength;
213      }
214    
215      /**
216       * Get the character at the specified index.
217     *     *
218     *  @param stringBuffer the <code>StringBuffer</code> to convert and append.     * @param index the index of the character to get, starting at 0
219     *  @return this <code>StringBuffer</code>.     * @return the character at the specified index
220     *  @see java.lang.StringBuffer.toString()     * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
221     *  @since 1.4     *         (while unspecified, this is a StringIndexOutOfBoundsException)
222     */     */
223    public StringBuffer append (StringBuffer stringBuffer)    public synchronized char charAt(int index)
224    {    {
225      return append (stringBuffer.toString());      if (index >= count)
226          throw new StringIndexOutOfBoundsException(index);
227        return value[index];
228    }    }
229    
230    /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.    /**
231     *  Uses <code>String.valueOf()</code> to convert to     * Get the specified array of characters. <code>srcOffset - srcEnd</code>
232     *  <code>String</code>.     * characters will be copied into the array you pass in.
233     *  @param obj the <code>Object</code> to convert and append.     *
234     *  @return this <code>StringBuffer</code>.     * @param srcOffset the index to start copying from (inclusive)
235     *  @see java.lang.String#valueOf(java.lang.Object)     * @param srcEnd the index to stop copying from (exclusive)
236       * @param dst the array to copy into
237       * @param dstOffset the index to start copying into
238       * @throws NullPointerException if dst is null
239       * @throws IndexOutOfBoundsException if any source or target indices are
240       *         out of range (while unspecified, this is a
241       *         StringIndexOutOfBoundsException)
242       * @see System#arraycopy(Object, int, Object, int, int)
243     */     */
244    public StringBuffer append (Object obj)    public synchronized void getChars(int srcOffset, int srcEnd,
245                                        char[] dst, int dstOffset)
246    {    {
247      return append (String.valueOf(obj));      if (srcOffset < 0 || srcOffset > srcEnd)
248          throw new StringIndexOutOfBoundsException(srcOffset);
249        int todo = srcEnd - srcOffset;
250        if (srcEnd > count || dstOffset + todo > count)
251          throw new StringIndexOutOfBoundsException(srcEnd);
252        System.arraycopy(value, srcOffset, dst, dstOffset, todo);
253    }    }
254    
255    /** Append the <code>String</code> to this <code>StringBuffer</code>.    /**
256     *  @param str the <code>String</code> to append.     * Set the character at the specified index.
257     *  @return this <code>StringBuffer</code>.     *
258       * @param index the index of the character to set starting at 0
259       * @param ch the value to set that character to
260       * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
261       *         (while unspecified, this is a StringIndexOutOfBoundsException)
262     */     */
263    public synchronized StringBuffer append (String str)    public synchronized void setCharAt(int index, char ch)
264      {
265        if (index < 0 || index >= count)
266          throw new StringIndexOutOfBoundsException(index);
267        // Call ensureCapacity to enforce copy-on-write.
268        ensureCapacity_unsynchronized(count);
269        value[index] = ch;
270      }
271    
272      /**
273       * Append the <code>String</code> value of the argument to this
274       * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
275       * to <code>String</code>.
276       *
277       * @param obj the <code>Object</code> to convert and append
278       * @return this <code>StringBuffer</code>
279       * @see String#valueOf(Object)
280       * @see #append(String)
281       */
282      public StringBuffer append(Object obj)
283      {
284        return append(String.valueOf(obj));
285      }
286    
287      /**
288       * Append the <code>String</code> to this <code>StringBuffer</code>. If
289       * str is null, the String "null" is appended.
290       *
291       * @param str the <code>String</code> to append
292       * @return this <code>StringBuffer</code>
293       */
294      public synchronized StringBuffer append(String str)
295    {    {
296      if (str == null)      if (str == null)
297        str = "null";        str = "null";
298      int len = str.length();      int len = str.length();
299      ensureCapacity_unsynchronized (count + len);      ensureCapacity_unsynchronized(count + len);
300      str.getChars(0, len, value, count);      str.getChars(0, len, value, count);
301      count += len;      count += len;
302      return this;      return this;
303    }    }
304    
305    /** Append the <code>char</code> array to this <code>StringBuffer</code>.    /**
306     *  @param data the <code>char[]</code> to append.     * Append the <code>StringBuffer</code> value of the argument to this
307     *  @return this <code>StringBuffer</code>.     * <code>StringBuffer</code>. This behaves the same as
308     *  @exception NullPointerException if <code>str</code> is <code>null</code>.     * <code>append((Object) stringBuffer)</code>, except it is more efficient.
309       *
310       * @param stringBuffer the <code>StringBuffer</code> to convert and append
311       * @return this <code>StringBuffer</code>
312       * @see #append(Object)
313       * @since 1.4
314     */     */
315    public StringBuffer append (char[] data)    public StringBuffer append(StringBuffer stringBuffer)
316    {    {
317      return append (data, 0, data.length);      // XXX The point of this method was to AVOID creating the String...
318        return append(stringBuffer.toString());
319    }    }
320    
321    /** Append the <code>char</code> array to this <code>StringBuffer</code>.    /**
322     *  @param data the <code>char[]</code> to append.     * Append the <code>char</code> array to this <code>StringBuffer</code>.
323     *  @param offset the place to start grabbing characters from     * This is similar (but more efficient) than
324     *         <code>str</code>.     * <code>append(new String(data))</code>, except in the case of null.
325     *  @param count the number of characters to get from <code>str</code>.     *
326     *  @return this <code>StringBuffer</code>.     * @param data the <code>char[]</code> to append
327     *  @exception NullPointerException if <code>str</code> is <code>null</code>.     * @return this <code>StringBuffer</code>
328     *  @exception IndexOutOfBoundsException if <code>offset</code> or     * @throws NullPointerException if <code>str</code> is <code>null</code>
329     *             <code>offset+len</code> is out of range.     * @see #append(char[], int, int)
330     */     */
331    public synchronized StringBuffer append (char[] data, int offset, int count)    public StringBuffer append(char[] data)
332    {    {
333      ensureCapacity_unsynchronized (this.count + count);      return append(data, 0, data.length);
334      System.arraycopy(data, offset, value, this.count, count);    }
     this.count += count;  
     return this;  
   }  
335    
336    /** Get the total number of characters this <code>StringBuffer</code>    /**
337     *  can support before it must be grown.  Not to be confused with     * Append part of the <code>char</code> array to this
338     *  <em>length</em>.     * <code>StringBuffer</code>. This is similar (but more efficient) than
339     *  @return the capacity of this <code>StringBuffer</code>     * <code>append(new String(data, offset, count))</code>, except in the case
340     *  @see #length()     * of null.
341     *  @see #ensureCapacity(int)     *
342       * @param data the <code>char[]</code> to append
343       * @param offset the start location in <code>str</code>
344       * @param count the number of characters to get from <code>str</code>
345       * @return this <code>StringBuffer</code>
346       * @throws NullPointerException if <code>str</code> is <code>null</code>
347       * @throws IndexOutOfBoundsException if offset or count is out of range
348       *         (while unspecified, this is a StringIndexOutOfBoundsException)
349     */     */
350    public int capacity ()    public synchronized StringBuffer append(char[] data, int offset, int count)
351    {    {
352      return value.length;      ensureCapacity_unsynchronized(this.count + count);
353        System.arraycopy(data, offset, value, this.count, count);
354        this.count += count;
355        return this;
356    }    }
357    
358    /** Get the character at the specified index.    /**
359     *  @param index the index of the character to get, starting at 0.     * Append the <code>String</code> value of the argument to this
360     *  @return the character at the specified index.     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
361     *  @exception IndexOutOfBoundsException if the desired character index     * to <code>String</code>.
362     *             is negative or greater then length() - 1.     *
363       * @param bool the <code>boolean</code> to convert and append
364       * @return this <code>StringBuffer</code>
365       * @see String#valueOf(boolean)
366     */     */
367    public synchronized char charAt (int index)    public StringBuffer append(boolean bool)
368    {    {
369      if (index >= count)      return append(String.valueOf(bool));
       throw new StringIndexOutOfBoundsException (index);  
     return value[index];  
370    }    }
371    
372    /** Delete characters from this <code>StringBuffer</code>.    /**
373     *  <code>delete(10, 12)</code> will delete 10 and 11, but not 12.     * Append the <code>char</code> to this <code>StringBuffer</code>.
374     *  @param start the first character to delete.     *
375     *  @param end the index after the last character to delete.     * @param c the <code>char</code> to append
376     *  @return this <code>StringBuffer</code>.     * @return this <code>StringBuffer</code>
    *  @exception StringIndexOutOfBoundsException if <code>start</code>  
    *             or <code>end-1</code> are out of bounds, or if  
    *             <code>start > end</code>.  
377     */     */
378    public synchronized StringBuffer delete (int start, int end)    public synchronized StringBuffer append(char ch)
379    {    {
380      if (start < 0 || start > count || start > end)      ensureCapacity_unsynchronized(count + 1);
381        throw new StringIndexOutOfBoundsException (start);      value[count++] = ch;
     if (end > count)  
       end = count;  
     // This will unshare if required.  
     ensureCapacity_unsynchronized (count);  
     if (count - end != 0)  
       System.arraycopy (value, end, value, start, count - end);  
     count -= (end - start);  
382      return this;      return this;
383    }    }
384    
385    /** Delete a character from this <code>StringBuffer</code>.    /**
386     *  @param index the index of the character to delete.     * Append the <code>String</code> value of the argument to this
387     *  @return this <code>StringBuffer</code>.     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
388     *  @exception StringIndexOutOfBoundsException if <code>index</code>     * to <code>String</code>.
389     *             is out of bounds.     *
390       * @param inum the <code>int</code> to convert and append
391       * @return this <code>StringBuffer</code>
392       * @see String#valueOf(int)
393     */     */
394    public StringBuffer deleteCharAt(int index)    public StringBuffer append(int inum)
395    {    {
396      return delete (index, index + 1);      return append(String.valueOf(inum));
397    }    }
398    
399    /** Increase the capacity of this <code>StringBuffer</code>.    /**
400     *  This will ensure that an expensive growing operation will not occur     * Append the <code>String</code> value of the argument to this
401     *  until <code>minimumCapacity</code> is reached.     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
402     *  If the capacity is actually already greater than <code>minimumCapacity</code>     * to <code>String</code>.
403     *  @param minimumCapacity the new capacity.     *
404     *  @see #capacity()     * @param lnum the <code>long</code> to convert and append
405       * @return this <code>StringBuffer</code>
406       * @see String#valueOf(long)
407     */     */
408    public synchronized void ensureCapacity (int minimumCapacity)    public StringBuffer append(long lnum)
409    {    {
410      if (shared || minimumCapacity > value.length)      return append(String.valueOf(lnum));
       {  
         // We don't want to make a larger vector when `shared' is  
         // set.  If we do, then setLength becomes very inefficient  
         // when repeatedly reusing a StringBuffer in a loop.  
         int max = (minimumCapacity > value.length  
                    ? value.length*2+2  
                    : value.length);  
         minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);  
         char[] nb = new char[minimumCapacity];  
         System.arraycopy(value, 0, nb, 0, count);  
         value = nb;  
         shared = false;  
       }  
411    }    }
412    
413    // ensureCapacity is used by several synchronized methods in StringBuffer.    /**
414    // There's no need to synchronize again.     * Append the <code>String</code> value of the argument to this
415    private void ensureCapacity_unsynchronized (int minimumCapacity)     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
416       * to <code>String</code>.
417       *
418       * @param fnum the <code>float</code> to convert and append
419       * @return this <code>StringBuffer</code>
420       * @see String#valueOf(float)
421       */
422      public StringBuffer append(float fnum)
423    {    {
424      if (shared || minimumCapacity > value.length)      return append(String.valueOf(fnum));
       {  
         // We don't want to make a larger vector when `shared' is  
         // set.  If we do, then setLength becomes very inefficient  
         // when repeatedly reusing a StringBuffer in a loop.  
         int max = (minimumCapacity > value.length  
                    ? value.length*2+2  
                    : value.length);  
         minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);  
         char[] nb = new char[minimumCapacity];  
         System.arraycopy(value, 0, nb, 0, count);  
         value = nb;  
         shared = false;  
       }  
425    }    }
426    
427    /** Get the specified array of characters.    /**
428     *  The characters will be copied into the array you pass in.     * Append the <code>String</code> value of the argument to this
429     *  @param srcOffset the index to start copying from in the     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
430     *         <code>StringBuffer</code>.     * to <code>String</code>.
431     *  @param srcEnd the number of characters to copy.     *
432     *  @param dst the array to copy into.     * @param dnum the <code>double</code> to convert and append
433     *  @param dstOffset the index to start copying into <code>dst</code>.     * @return this <code>StringBuffer</code>
434     *  @exception NullPointerException if dst is null.     * @see String#valueOf(double)
    *  @exception IndexOutOfBoundsException if any source or target  
    *             indices are out of range.  
    *  @see java.lang.System#arraycopy(java.lang.Object,int,java.lang.Object,int,int)  
435     */     */
436    public synchronized void getChars (int srcOffset, int srcEnd,    public StringBuffer append(double dnum)
                                      char[] dst, int dstOffset)  
437    {    {
438      if (srcOffset < 0 || srcOffset > srcEnd)      return append(String.valueOf(dnum));
       throw new StringIndexOutOfBoundsException (srcOffset);  
     int todo = srcEnd - srcOffset;  
     if (srcEnd > count || dstOffset + todo > count)  
       throw new StringIndexOutOfBoundsException (srcEnd);  
     System.arraycopy(value, srcOffset, dst, dstOffset, todo);  
439    }    }
440    
441    /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.    /**
442     *  Uses <code>String.valueOf()</code> to convert to     * Delete characters from this <code>StringBuffer</code>.
443     *  <code>String</code>.     * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
444     *  @param offset the place to insert.     * harmless for end to be larger than length().
445     *  @param bool the <code>boolean</code> to convert and insert.     *
446     *  @return this <code>StringBuffer</code>.     * @param start the first character to delete
447     *  @exception IndexOutOfBoundsException if <code>offset</code> is out     * @param end the index after the last character to delete
448     *             of range for this <code>StringBuffer</code>.     * @return this <code>StringBuffer</code>
449     *  @see java.lang.String#valueOf(boolean)     * @throws StringIndexOutOfBoundsException if start or end are out of bounds
450     */     * @since 1.2
   public StringBuffer insert (int offset, boolean bool)  
   {  
     return insert (offset, bool ? "true" : "false");  
   }  
   
   /** Insert the <code>char</code> argument into this <code>StringBuffer</code>.  
    *  @param offset the place to insert.  
    *  @param ch the <code>char</code> to insert.  
    *  @return this <code>StringBuffer</code>.  
    *  @exception IndexOutOfBoundsException if <code>offset</code> is out  
    *             of range for this <code>StringBuffer</code>.  
451     */     */
452    public synchronized StringBuffer insert (int offset, char ch)    public synchronized StringBuffer delete(int start, int end)
453    {    {
454      if (offset < 0 || offset > count)      if (start < 0 || start > count || start > end)
455        throw new StringIndexOutOfBoundsException (offset);        throw new StringIndexOutOfBoundsException(start);
456      ensureCapacity_unsynchronized (count+1);      if (end > count)
457      System.arraycopy(value, offset, value, offset+1, count-offset);        end = count;
458      value[offset] = ch;      // This will unshare if required.
459      count++;      ensureCapacity_unsynchronized(count);
460        if (count - end != 0)
461          System.arraycopy(value, end, value, start, count - end);
462        count -= end - start;
463      return this;      return this;
464    }    }
465    
466    /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.    /**
467     *  Uses <code>String.valueOf()</code> to convert to     * Delete a character from this <code>StringBuffer</code>.
468     *  <code>String</code>.     *
469     *  @param offset the place to insert.     * @param index the index of the character to delete
470     *  @param inum the <code>int</code> to convert and insert.     * @return this <code>StringBuffer</code>
471     *  @return this <code>StringBuffer</code>.     * @throws StringIndexOutOfBoundsException if index is out of bounds
472     *  @exception IndexOutOfBoundsException if <code>offset</code> is out     * @since 1.2
    *             of range for this <code>StringBuffer</code>.  
    *  @see java.lang.String#valueOf(int)  
473     */     */
474    public StringBuffer insert (int offset, int inum)    public StringBuffer deleteCharAt(int index)
475    {    {
476      return insert (offset, String.valueOf(inum));      return delete(index, index + 1);
477    }    }
478    
479    /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.    /**
480     *  Uses <code>String.valueOf()</code> to convert to     * Replace characters between index <code>start</code> (inclusive) and
481     *  <code>String</code>.     * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
482     *  @param offset the place to insert.     * is larger than the size of this StringBuffer, all characters after
483     *  @param lnum the <code>long</code> to convert and insert.     * <code>start</code> are replaced.
484     *  @return this <code>StringBuffer</code>.     *
485     *  @exception IndexOutOfBoundsException if <code>offset</code> is out     * @param start the beginning index of characters to delete (inclusive)
486     *             of range for this <code>StringBuffer</code>.     * @param end the ending index of characters to delete (exclusive)
487     *  @see java.lang.String#valueOf(long)     * @param str the new <code>String</code> to insert
488       * @return this <code>StringBuffer</code>
489       * @throws StringIndexOutOfBoundsException if start or end are out of bounds
490       * @throws NullPointerException if str is null
491       * @since 1.2
492     */     */
493    public StringBuffer insert (int offset, long lnum)    public synchronized StringBuffer replace(int start, int end, String str)
494    {    {
495      return insert (offset, String.valueOf(lnum));      if (start < 0 || start > count || start > end)
496    }        throw new StringIndexOutOfBoundsException(start);
497    
498    /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.      int len = str.length();
499     *  Uses <code>String.valueOf()</code> to convert to      // Calculate the difference in 'count' after the replace.
500     *  <code>String</code>.      int delta = len - ((end > count ? count : end) - start);
501     *  @param offset the place to insert.      ensureCapacity_unsynchronized(count + delta);
502     *  @param fnum the <code>float</code> to convert and insert.  
503     *  @return this <code>StringBuffer</code>.      if (delta != 0 && end < count)
504     *  @exception IndexOutOfBoundsException if <code>offset</code> is out        System.arraycopy(value, end, value, end + delta, count - end);
505     *             of range for this <code>StringBuffer</code>.  
506     *  @see java.lang.String#valueOf(float)      str.getChars(0, len, value, start);
507     */      count += delta;
508    public StringBuffer insert (int offset, float fnum)      return this;
   {  
     return insert (offset, String.valueOf(fnum));  
509    }    }
510    
511    /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.    /**
512     *  Uses <code>String.valueOf()</code> to convert to     * Creates a substring of this StringBuffer, starting at a specified index
513     *  <code>String</code>.     * and ending at the end of this StringBuffer.
514     *  @param offset the place to insert.     *
515     *  @param dnum the <code>double</code> to convert and insert.     * @param beginIndex index to start substring (base 0)
516     *  @return this <code>StringBuffer</code>.     * @return new String which is a substring of this StringBuffer
517     *  @exception IndexOutOfBoundsException if <code>offset</code> is out     * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds
518     *             of range for this <code>StringBuffer</code>.     * @see #substring(int, int)
519     *  @see java.lang.String#valueOf(double)     * @since 1.2
520     */     */
521    public StringBuffer insert (int offset, double dnum)    public String substring(int beginIndex)
522    {    {
523      return insert (offset, String.valueOf(dnum));      return substring(beginIndex, count);
524    }    }
525    
526    /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.    /**
527     *  Uses <code>String.valueOf()</code> to convert to     * Creates a substring of this StringBuffer, starting at a specified index
528     *  <code>String</code>.     * and ending at one character before a specified index. This is implemented
529     *  @param offset the place to insert.     * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
530     *  @param obj the <code>Object</code> to convert and insert.     * the CharSequence interface.
531     *  @return this <code>StringBuffer</code>.     *
532     *  @exception IndexOutOfBoundsException if <code>offset</code> is out     * @param beginIndex index to start at (inclusive, base 0)
533     *             of range for this <code>StringBuffer</code>.     * @param endIndex index to end at (exclusive)
534     *  @see java.lang.String#valueOf(java.lang.Object)     * @return new String which is a substring of this StringBuffer
535       * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
536       *         bounds
537       * @see #substring(int, int)
538       * @since 1.4
539     */     */
540    public StringBuffer insert (int offset, Object obj)    public CharSequence subSequence(int beginIndex, int endIndex)
541    {    {
542      return insert (offset, String.valueOf(obj));      return substring(beginIndex, endIndex);
543    }    }
544    
545    /** Insert the <code>String</code> argument into this <code>StringBuffer</code>.    /**
546     *  @param offset the place to insert.     * Creates a substring of this StringBuffer, starting at a specified index
547     *  @param str the <code>String</code> to insert.     * and ending at one character before a specified index.
548     *  @return this <code>StringBuffer</code>.     *
549     *  @exception IndexOutOfBoundsException if <code>offset</code> is out     * @param beginIndex index to start at (inclusive, base 0)
550     *             of range for this <code>StringBuffer</code>.     * @param endIndex index to end at (exclusive)
551       * @return new String which is a substring of this StringBuffer
552       * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
553       *         of bounds
554       * @since 1.2
555     */     */
556    public synchronized StringBuffer insert (int offset, String str)    public synchronized String substring(int beginIndex, int endIndex)
557    {    {
558      if (offset < 0 || offset > count)      if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
559        throw new StringIndexOutOfBoundsException (offset);        throw new StringIndexOutOfBoundsException();
560      // Note that using `null' is from JDK 1.2.      // XXX FIXME: for libgcj it would be possible, and more efficient, to
561      if (str == null)      // enable sharing here.
562        str = "null";      return new String(value, beginIndex, endIndex - beginIndex);
     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;  
563    }    }
564    
565    /** Insert the <code>char[]</code> argument into this    /**
566     *  <code>StringBuffer</code>.     * Insert a subarray of the <code>char[]</code> argument into this
567     *  @param offset the place to insert.     * <code>StringBuffer</code>.
568     *  @param data the <code>char[]</code> to insert.     *
569     *  @return this <code>StringBuffer</code>.     * @param offset the place to insert in this buffer
570     *  @exception NullPointerException if <code>data</code> is     * @param str the <code>char[]</code> to insert
571     *             <code>null</code>.     * @param str_offset the index in <code>str</code> to start inserting from
572     *  @exception IndexOutOfBoundsException if <code>offset</code> is out     * @param len the number of characters to insert
573     *             of range for this <code>StringBuffer</code>.     * @return this <code>StringBuffer</code>
574     */     * @throws NullPointerException if <code>str</code> is <code>null</code>
575    public StringBuffer insert (int offset, char[] data)     * @throws StringIndexOutOfBoundsException if any index is out of bounds
576    {     * @since 1.2
     // One could check if offset is invalid here instead of making sure that  
     // data isn't null before dereferencing, but this works just as well.  
     return insert (offset, data, 0, data == null ? 0 : data.length);  
   }  
   
   /** Insert the <code>char[]</code> argument into this  
    *  <code>StringBuffer</code>.  
    *  @param offset the place to insert.  
    *  @param str the <code>char[]</code> to insert.  
    *  @param str_offset the index in <code>str</code> to start inserting  
    *         from.  
    *  @param len the number of characters to insert.  
    *  @return this <code>StringBuffer</code>.  
    *  @exception NullPointerException if <code>str</code> is <code>null</code>.  
    *  @exception IndexOutOfBoundsException if <code>offset</code> is out  
    *             of range, for this <code>StringBuffer</code>, or if  
    *             <code>str_offset</code> or <code>str_offset+len</code>  
    *             are out of range for <code>str</code>.  
577     */     */
578    public synchronized StringBuffer insert(int offset, char[] str,    public synchronized StringBuffer insert(int offset,
579                                            int str_offset, int len)                                            char[] str, int str_offset, int len)
580    {    {
581      if (offset < 0 || offset > count)      if (offset < 0 || offset > count)
582        throw new StringIndexOutOfBoundsException (offset);        throw new StringIndexOutOfBoundsException(offset);
583      if (len < 0)      if (len < 0)
584        throw new StringIndexOutOfBoundsException (len);        throw new StringIndexOutOfBoundsException(len);
585      if (str_offset < 0 || str_offset + len > str.length)      if (str_offset < 0 || str_offset + len > str.length)
586        throw new StringIndexOutOfBoundsException (str_offset);        throw new StringIndexOutOfBoundsException(str_offset);
587      ensureCapacity_unsynchronized (count + len);      ensureCapacity_unsynchronized(count + len);
588      System.arraycopy(value, offset, value, offset + len, count - offset);      System.arraycopy(value, offset, value, offset + len, count - offset);
589      System.arraycopy(str, str_offset, value, offset, len);      System.arraycopy(str, str_offset, value, offset, len);
590      count += len;      count += len;
591      return this;      return this;
592    }    }
593    
594    /** Get the length of the <code>String</code> this    /**
595     *  <code>StringBuffer</code> would create.  Not to be confused with the     * Insert the <code>String</code> value of the argument into this
596     *  <em>capacity</em> of the <code>StringBuffer</code>.     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
597     *  @return the length of this <code>StringBuffer</code>.     * to <code>String</code>.
598     *  @see #capacity()     *
599     *  @see #setLength(int)     * @param offset the place to insert in this buffer
600       * @param obj the <code>Object</code> to convert and insert
601       * @return this <code>StringBuffer</code>
602       * @exception StringIndexOutOfBoundsException if offset is out of bounds
603       * @see String#valueOf(Object)
604     */     */
605    public int length ()    public StringBuffer insert(int offset, Object obj)
606    {    {
607      return count;      return insert(offset, String.valueOf(obj));
608    }    }
609    
610    /** Replace characters between index <code>start</code> (inclusive) and    /**
611     *  <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>     * Insert the <code>String</code> argument into this
612     *  is larger than the size of this StringBuffer, all characters after     * <code>StringBuffer</code>. If str is null, the String "null" is used
613     *  <code>start</code> are replaced.     * instead.
614     *  @param start the beginning index of characters to delete (inclusive).     *
615     *  @param end the ending index of characters to delete (exclusive).     * @param offset the place to insert in this buffer
616     *  @param str the new <code>String</code> to insert.     * @param str the <code>String</code> to insert
617     *  @return this <code>StringBuffer</code>.     * @return this <code>StringBuffer</code>
618       * @throws StringIndexOutOfBoundsException if offset is out of bounds
619     */     */
620    public synchronized StringBuffer replace (int start, int end, String str)    public synchronized StringBuffer insert(int offset, String str)
621    {    {
622      if (start < 0 || start > count || start > end)      if (offset < 0 || offset > count)
623        throw new StringIndexOutOfBoundsException (start);        throw new StringIndexOutOfBoundsException(offset);
624          if (str == null)
625          str = "null";
626      int len = str.length();      int len = str.length();
627      // Calculate the difference in 'count' after the replace.      ensureCapacity_unsynchronized(count + len);
628      int delta = len - ((end > count ? count : end) - start);      System.arraycopy(value, offset, value, offset + len, count - offset);
629      ensureCapacity_unsynchronized (count + delta);      str.getChars(0, len, value, offset);
630                count += len;
631      if (delta != 0 && end < count)      return this;
       System.arraycopy(value, end, value, end + delta, count - end);  
       
     str.getChars (0, len, value, start);      
     count += delta;      
     return this;      
632    }    }
633    
634    /** Reverse the characters in this StringBuffer.    /**
635     *  @return this <code>StringBuffer</code>.     * Insert the <code>char[]</code> argument into this
636     */     * <code>StringBuffer</code>.
637    public synchronized StringBuffer reverse ()     *
638    {     * @param offset the place to insert in this buffer
639      // Call ensureCapacity to enforce copy-on-write.     * @param data the <code>char[]</code> to insert
640      ensureCapacity_unsynchronized (count);     * @return this <code>StringBuffer</code>
641      for (int i = 0; i < count / 2; ++i)     * @throws NullPointerException if <code>data</code> is <code>null</code>
642        {     * @throws StringIndexOutOfBoundsException if offset is out of bounds
643          char c = value[i];     * @see #insert(int, char[], int, int)
644          value[i] = value[count - i - 1];     */
645          value[count - i - 1] = c;    public StringBuffer insert(int offset, char[] data)
646        }    {
647      return this;      // Sun checks offset before checking if data is null, hence this delay
648        // of dereferencing data.
649        return insert(offset, data, 0, data == null ? 0 : data.length);
650    }    }
651    
652    /** Set the character at the specified index.    /**
653     *  @param index the index of the character to set starting at 0.     * Insert the <code>String</code> value of the argument into this
654     *  @param ch the value to set that character to.     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
655     *  @exception IndexOutOfBoundsException if the specified character     * to <code>String</code>.
656     *             index is not between 0 and length() - 1 (inclusive).     *
657       * @param offset the place to insert in this buffer
658       * @param bool the <code>boolean</code> to convert and insert
659       * @return this <code>StringBuffer</code>
660       * @throws StringIndexOutOfBoundsException if offset is out of bounds
661       * @see String#valueOf(boolean)
662     */     */
663    public synchronized void setCharAt (int index, char ch)    public StringBuffer insert(int offset, boolean bool)
664    {    {
665      if (index < 0 || index >= count)      return insert(offset, bool ? "true" : "false");
       throw new StringIndexOutOfBoundsException (index);  
     // Call ensureCapacity to enforce copy-on-write.  
     ensureCapacity_unsynchronized (count);  
     value[index] = ch;  
666    }    }
667    
668    /** Set the length of this StringBuffer.    /**
669     *  <P>     * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
670     *  If the new length is greater than the current length, all the new     *
671     *  characters are set to '\0'.     * @param offset the place to insert in this buffer
672     *  <P>     * @param ch the <code>char</code> to insert
673     *  If the new length is less than the current length, the first     * @return this <code>StringBuffer</code>
674     *  <code>newLength</code> characters of the old array will be     * @throws StringIndexOutOfBoundsException if offset is out of bounds
    * @param newLength the new length  
    * @exception IndexOutOfBoundsException if the new length is  
    *            negative.  
    * @see #length()  
675     */     */
676    public synchronized void setLength (int newLength)    public synchronized StringBuffer insert(int offset, char ch)
677    {    {
678      if (newLength < 0)      if (offset < 0 || offset > count)
679        throw new StringIndexOutOfBoundsException (newLength);        throw new StringIndexOutOfBoundsException(offset);
680        ensureCapacity_unsynchronized(count + 1);
681      ensureCapacity_unsynchronized (newLength);      System.arraycopy(value, offset, value, offset + 1, count - offset);
682      for (int i = count; i < newLength; ++i)      value[offset] = ch;
683        value[i] = '\0';      count++;
684      count = newLength;      return this;
685    }    }
686    
687    /** Create a new StringBuffer with default capacity 16.    /**
688     *  @see JLS 20.13.1     * Insert the <code>String</code> value of the argument into this
689       * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
690       * to <code>String</code>.
691       *
692       * @param offset the place to insert in this buffer
693       * @param inum the <code>int</code> to convert and insert
694       * @return this <code>StringBuffer</code>
695       * @throws StringIndexOutOfBoundsException if offset is out of bounds
696       * @see String#valueOf(int)
697     */     */
698    public StringBuffer ()    public StringBuffer insert(int offset, int inum)
699    {    {
700      this (DEFAULT_CAPACITY);      return insert(offset, String.valueOf(inum));
701    }    }
702    
703    /** Create an empty <code>StringBuffer</code> with the specified initial capacity.    /**
704     *  @param capacity the initial capacity.     * Insert the <code>String</code> value of the argument into this
705       * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
706       * to <code>String</code>.
707       *
708       * @param offset the place to insert in this buffer
709       * @param lnum the <code>long</code> to convert and insert
710       * @return this <code>StringBuffer</code>
711       * @throws StringIndexOutOfBoundsException if offset is out of bounds
712       * @see String#valueOf(long)
713     */     */
714    public StringBuffer (int capacity)    public StringBuffer insert(int offset, long lnum)
715    {    {
716      count = 0;      return insert(offset, String.valueOf(lnum));
     value = new char[capacity];  
     shared = false;  
717    }    }
718    
719    /** Create a new <code>StringBuffer</code> with the characters in the specified <code>String</code>.    /**
720     *  Initial capacity will be the size of the String plus 16.     * Insert the <code>String</code> value of the argument into this
721     *  @param str the <code>String</code> to make a <code>StringBuffer</code> out of.     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
722     *  @XXX optimize for sharing.     * to <code>String</code>.
723       *
724       * @param offset the place to insert in this buffer
725       * @param fnum the <code>float</code> to convert and insert
726       * @return this <code>StringBuffer</code>
727       * @throws StringIndexOutOfBoundsException if offset is out of bounds
728       * @see String#valueOf(float)
729     */     */
730    public StringBuffer (String str)    public StringBuffer insert(int offset, float fnum)
731    {    {
732      // The documentation is not clear, but experimentation with      return insert(offset, String.valueOf(fnum));
     // other implementations indicates that StringBuffer(null)  
     // should throw a NullPointerException.  
     count = str.length();  
     // JLS: The initial capacity of the string buffer is 16 plus the  
     // length of the argument string.  
     value = new char[count + DEFAULT_CAPACITY];  
     str.getChars(0, count, value, 0);  
     shared = false;  
733    }    }
734    
735    /**    /**
736     * Creates a substring of this StringBuffer, starting at a specified index     * Insert the <code>String</code> value of the argument into this
737     * and ending at the end of this StringBuffer.     * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
738     *     * to <code>String</code>.
739     * @param beginIndex index to start substring (base 0)     *
740     *     * @param offset the place to insert in this buffer
741     * @return new String which is a substring of this StringBuffer     * @param dnum the <code>double</code> to convert and insert
742     *     * @return this <code>StringBuffer</code>
743     * @exception StringIndexOutOfBoundsException     * @throws StringIndexOutOfBoundsException if offset is out of bounds
744     *   if (beginIndex < 0 || beginIndex > this.length())     * @see String#valueOf(double)
745     */     */
746    public String substring (int beginIndex)    public StringBuffer insert(int offset, double dnum)
747    {    {
748      return substring (beginIndex, count);      return insert(offset, String.valueOf(dnum));
749    }    }
750    
751    /**    /**
752     * Creates a substring of this StringBuffer, starting at a specified index     * Finds the first instance of a substring in this StringBuffer.
    * and ending at one character before a specified index.  
753     *     *
754     * @param beginIndex index to start substring (base 0)     * @param str String to find
755     * @param endIndex index after the last character to be     * @return location (base 0) of the String, or -1 if not found
756     *   copied into the substring     * @throws NullPointerException if str is null
757     *     * @see #indexOf(String, int)
758     * @return new String which is a substring of this StringBuffer     * @since 1.4
    *  
    * @exception StringIndexOutOfBoundsException  
    *   if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)  
759     */     */
760    public synchronized String substring (int beginIndex, int endIndex)    public int indexOf(String str)
761    {    {
762      if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)      return indexOf(str, 0);
       throw new StringIndexOutOfBoundsException ();  
     // FIXME: for libgcj it would be possible, and more efficient, to  
     // enable sharing here.  
     return new String (value, beginIndex, endIndex - beginIndex);  
763    }    }
764    
765    /**    /**
766     * Creates a substring of this StringBuffer, starting at a specified index     * Finds the first instance of a String in this StringBuffer, starting at
767     * and ending at one character before a specified index.     * a given index.  If starting index is less than 0, the search starts at
768     * <p>     * the beginning of this String.  If the starting index is greater than the
769     * To implement <code>CharSequence</code>.     * length of this String, or the substring is not found, -1 is returned.
770     * Calls <code>substring(beginIndex, endIndex)</code>.     *
771     *     * @param str String to find
772     * @param beginIndex index to start substring (base 0)     * @param fromIndex index to start the search
773     * @param endIndex index after the last character to be     * @return location (base 0) of the String, or -1 if not found
774     *   copied into the substring     * @throws NullPointerException if str is null
    *  
    * @return new String which is a substring of this StringBuffer  
    *  
    * @exception IndexOutOfBoundsException  
    *   if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)  
    *  
775     * @since 1.4     * @since 1.4
776     */     */
777    public CharSequence subSequence (int beginIndex, int endIndex)    public synchronized int indexOf(String str, int fromIndex)
778    {    {
779      return substring(beginIndex, endIndex);      // XXX Avoid the object creation here.
780        return this.toString().indexOf(str, fromIndex);
781    }    }
782    
783    /** Convert this <code>StringBuffer</code> to a <code>String</code>.    /**
784     *  @return the characters in this StringBuffer     * Finds the last instance of a substring in this StringBuffer.
785       *
786       * @param str String to find
787       * @return location (base 0) of the String, or -1 if not found
788       * @throws NullPointerException if str is null
789       * @see #lastIndexOf(String, int)
790       * @since 1.4
791     */     */
792    public String toString ()    public int lastIndexOf(String str)
793    {    {
794      // Note: in libgcj this causes the StringBuffer to be shared.  In      return lastIndexOf(str, count - str.count);
     // Classpath it does not.  
     return new String (this);  
795    }    }
796    
797    /** Finds the first instance of a String in this StringBuffer.    /**
798     *     * Finds the last instance of a String in this StringBuffer, starting at a
799     *  @param str String to find     * given index.  If starting index is greater than the maximum valid index,
800     *     * then the search begins at the end of this String.  If the starting index
801     *  @return location (base 0) of the String, or -1 if not found     * is less than zero, or the substring is not found, -1 is returned.
802     *     *
803     *  @exception NullPointerException if `str' is null     * @param str String to find
804     *     * @param fromIndex index to start the search
805     *  @since 1.4     * @return location (base 0) of the String, or -1 if not found
806       * @throws NullPointerException if str is null
807       * @since 1.4
808     */     */
809    public int indexOf (String string)    public synchronized int lastIndexOf(String str, int fromIndex)
810    {    {
811      return this.toString().indexOf(string, 0);      // XXX Avoid the object creation here.
812      //save a call in String.java by passing second argument      return this.toString().lastIndexOf(str, fromIndex);
813    }    }
814      
815    /** Finds the first instance of a String in this StringBuffer,    /**
816     *  starting at a given index.  If starting index is less than 0,     * Reverse the characters in this StringBuffer. The same sequence of
817     *  the search starts at the beginning of this String.  If the     * characters exists, but in the reverse index ordering.
    *  starting index is greater than the length of this String, -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  
    *  
    *  @exception NullPointerException if `str' is null  
818     *     *
819     *  @since 1.4     * @return this <code>StringBuffer</code>
820     */     */
821    public int indexOf (String string,    public synchronized StringBuffer reverse()
                       int fromIndex)  
822    {    {
823      return this.toString().indexOf(string, fromIndex);      // Call ensureCapacity to enforce copy-on-write.
824        ensureCapacity_unsynchronized(count);
825        for (int i = 0; i < count / 2; ++i)
826          {
827            char c = value[i];
828            value[i] = value[count - i - 1];
829            value[count - i - 1] = c;
830          }
831        return this;
832    }    }
833    
834    /** Finds the last instance of a String in this StringBuffer.    /**
835     *     * Convert this <code>StringBuffer</code> to a <code>String</code>. The
836     *  @param str String to find     * String is composed of the characters currently in this StringBuffer. Note
837     *     * that the result is a copy, and that future modifications to this buffer
838     *  @return location (base 0) of the String, or -1 if not found     * do not affect the String.
    *  
    *  @exception NullPointerException if `str' is null  
839     *     *
840     *  @since 1.4     * @return the characters in this StringBuffer
841     */     */
842    public int lastIndexOf(String str) throws NullPointerException    public String toString()
843    {    {
844      return this.toString().lastIndexOf(str, count-str.count);      // XXX Implement sharing with this call, to match libgcj.
845        return new String(this);
846    }    }
847    
848    /** Finds the last instance of a String in this StringBuffer,    /**
849     *  starting at a given index.  If starting index is greater than the     * An unsynchronized version of ensureCapacity, used internally to avoid
850     *  maximum valid index, then the search begins at the end of this     * the cost of a second lock on the same object. This also has the side
851     *  String.  If the starting index is less than zero, -1 is returned.     * effect of duplicating the array, if it was shared (to form copy-on-write
852     *     * semantics).
    *  @param str String to find  
    *  @param fromIndex index to start the search  
    *  
    *  @return location (base 0) of the String, or -1 if not found  
853     *     *
854     *  @exception NullPointerException if `str' is null     * @param minimumCapacity the minimum capacity
855     *     * @see #ensureCapacity(int)
    *  @since 1.4  
856     */     */
857    public int lastIndexOf(String str, int fromIndex)    private void ensureCapacity_unsynchronized(int minimumCapacity)
     throws NullPointerException  
858    {    {
859      return this.toString().lastIndexOf(str, fromIndex);      if (shared || minimumCapacity > value.length)
860          {
861            // We don't want to make a larger vector when `shared' is
862            // set.  If we do, then setLength becomes very inefficient
863            // when repeatedly reusing a StringBuffer in a loop.
864            int max = (minimumCapacity > value.length
865                       ? value.length * 2 + 2
866                       : value.length);
867            minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
868            char[] nb = new char[minimumCapacity];
869            System.arraycopy(value, 0, nb, 0, count);
870            value = nb;
871            shared = false;
872          }
873    }    }
   
   // Index of next available character.  Note that this has  
   // permissions set this way so that String can get the value.  
   int count;  
   
   // The buffer.  Note that this has permissions set this way so that  
   // String can get the value.  
   char[] value;  
   
   // True if we need to copy the buffer before writing to it again.  
   // FIXME: JDK 1.2 doesn't specify this.  The new buffer-growing  
   // semantics make this less useful in that case, too.  Note that  
   // this has permissions set this way so that String can get the  
   // value.  
   boolean shared;  
   
   static final long serialVersionUID = 3388685877147921107L;  
   private final static int DEFAULT_CAPACITY = 16; // JLS 20.13.1  
874  }  }

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.19

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26