OSDN Git Service

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