svn merge -r108665:108708 svn+ssh://gcc.gnu.org/svn/gcc/trunk
[official-gcc.git] / libjava / java / lang / StringBuffer.java
blobd93fed5fd40ac7115a82f313511021aecb0906c8
1 /* StringBuffer.java -- Growable strings
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
39 package java.lang;
41 import java.io.Serializable;
43 /**
44 * <code>StringBuffer</code> represents a changeable <code>String</code>.
45 * It provides the operations required to modify the
46 * <code>StringBuffer</code>, including insert, replace, delete, append,
47 * and reverse. It is thread-safe; meaning that all modifications to a buffer
48 * are in synchronized methods.
50 * <p><code>StringBuffer</code>s are variable-length in nature, so even if
51 * you initialize them to a certain size, they can still grow larger than
52 * that. <em>Capacity</em> indicates the number of characters the
53 * <code>StringBuffer</code> can have in it before it has to grow (growing
54 * the char array is an expensive operation involving <code>new</code>).
56 * <p>Incidentally, compilers often implement the String operator "+"
57 * by using a <code>StringBuffer</code> operation:<br>
58 * <code>a + b</code><br>
59 * is the same as<br>
60 * <code>new StringBuffer().append(a).append(b).toString()</code>.
62 * <p>Classpath's StringBuffer is capable of sharing memory with Strings for
63 * efficiency. This will help when a StringBuffer is converted to a String
64 * and the StringBuffer is not changed after that (quite common when performing
65 * string concatenation).
67 * @author Paul Fisher
68 * @author John Keiser
69 * @author Tom Tromey
70 * @author Eric Blake (ebb9@email.byu.edu)
71 * @see String
72 * @since 1.0
73 * @status updated to 1.4
75 public final class StringBuffer implements Serializable, CharSequence
77 /**
78 * Compatible with JDK 1.0+.
80 private static final long serialVersionUID = 3388685877147921107L;
82 /**
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.
87 * @serial the number of characters in the buffer
89 int count;
91 /**
92 * The buffer. Note that this has permissions set this way so that String
93 * can get the value.
95 * @serial the buffer
97 char[] value;
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.
105 * @serial whether the buffer is shared
107 boolean shared;
110 * The default capacity of a buffer.
112 private static final int DEFAULT_CAPACITY = 16;
115 * Create a new StringBuffer with default capacity 16.
117 public StringBuffer()
119 this(DEFAULT_CAPACITY);
123 * Create an empty <code>StringBuffer</code> with the specified initial
124 * capacity.
126 * @param capacity the initial capacity
127 * @throws NegativeArraySizeException if capacity is negative
129 public StringBuffer(int capacity)
131 value = new char[capacity];
135 * Create a new <code>StringBuffer</code> with the characters in the
136 * specified <code>String</code>. Initial capacity will be the size of the
137 * String plus 16.
139 * @param str the <code>String</code> to convert
140 * @throws NullPointerException if str is null
142 public StringBuffer(String str)
144 // Unfortunately, because the size is 16 larger, we cannot share.
145 count = str.count;
146 value = new char[count + DEFAULT_CAPACITY];
147 str.getChars(0, count, value, 0);
151 * Get the length of the <code>String</code> this <code>StringBuffer</code>
152 * would create. Not to be confused with the <em>capacity</em> of the
153 * <code>StringBuffer</code>.
155 * @return the length of this <code>StringBuffer</code>
156 * @see #capacity()
157 * @see #setLength(int)
159 public synchronized int length()
161 return count;
165 * Get the total number of characters this <code>StringBuffer</code> can
166 * support before it must be grown. Not to be confused with <em>length</em>.
168 * @return the capacity of this <code>StringBuffer</code>
169 * @see #length()
170 * @see #ensureCapacity(int)
172 public synchronized int capacity()
174 return value.length;
178 * Increase the capacity of this <code>StringBuffer</code>. This will
179 * ensure that an expensive growing operation will not occur until
180 * <code>minimumCapacity</code> is reached. The buffer is grown to the
181 * larger of <code>minimumCapacity</code> and
182 * <code>capacity() * 2 + 2</code>, if it is not already large enough.
184 * @param minimumCapacity the new capacity
185 * @see #capacity()
187 public synchronized void ensureCapacity(int minimumCapacity)
189 ensureCapacity_unsynchronized(minimumCapacity);
193 * Set the length of this StringBuffer. If the new length is greater than
194 * the current length, all the new characters are set to '\0'. If the new
195 * 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.
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()
204 public synchronized void setLength(int newLength)
206 if (newLength < 0)
207 throw new StringIndexOutOfBoundsException(newLength);
209 int valueLength = value.length;
211 /* Always call ensureCapacity_unsynchronized in order to preserve
212 copy-on-write semantics. */
213 ensureCapacity_unsynchronized(newLength);
215 if (newLength < valueLength)
217 /* If the StringBuffer's value just grew, then we know that
218 value is newly allocated and the region between count and
219 newLength is filled with '\0'. */
220 count = newLength;
222 else
224 /* The StringBuffer's value doesn't need to grow. However,
225 we should clear out any cruft that may exist. */
226 while (count < newLength)
227 value[count++] = '\0';
232 * Get the character at the specified index.
234 * @param index the index of the character to get, starting at 0
235 * @return the character at the specified index
236 * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
237 * (while unspecified, this is a StringIndexOutOfBoundsException)
239 public synchronized char charAt(int index)
241 if (index < 0 || index >= count)
242 throw new StringIndexOutOfBoundsException(index);
243 return value[index];
247 * Get the specified array of characters. <code>srcOffset - srcEnd</code>
248 * characters will be copied into the array you pass in.
250 * @param srcOffset the index to start copying from (inclusive)
251 * @param srcEnd the index to stop copying from (exclusive)
252 * @param dst the array to copy into
253 * @param dstOffset the index to start copying into
254 * @throws NullPointerException if dst is null
255 * @throws IndexOutOfBoundsException if any source or target indices are
256 * out of range (while unspecified, source problems cause a
257 * StringIndexOutOfBoundsException, and dest problems cause an
258 * ArrayIndexOutOfBoundsException)
259 * @see System#arraycopy(Object, int, Object, int, int)
261 public synchronized void getChars(int srcOffset, int srcEnd,
262 char[] dst, int dstOffset)
264 if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
265 throw new StringIndexOutOfBoundsException();
266 System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
270 * Set the character at the specified index.
272 * @param index the index of the character to set starting at 0
273 * @param ch the value to set that character to
274 * @throws IndexOutOfBoundsException if index is negative or &gt;= length()
275 * (while unspecified, this is a StringIndexOutOfBoundsException)
277 public synchronized void setCharAt(int index, char ch)
279 if (index < 0 || index >= count)
280 throw new StringIndexOutOfBoundsException(index);
281 // Call ensureCapacity to enforce copy-on-write.
282 ensureCapacity_unsynchronized(count);
283 value[index] = ch;
287 * Append the <code>String</code> value of the argument to this
288 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
289 * to <code>String</code>.
291 * @param obj the <code>Object</code> to convert and append
292 * @return this <code>StringBuffer</code>
293 * @see String#valueOf(Object)
294 * @see #append(String)
296 public StringBuffer append(Object obj)
298 return append(obj == null ? "null" : obj.toString());
302 * Append the <code>String</code> to this <code>StringBuffer</code>. If
303 * str is null, the String "null" is appended.
305 * @param str the <code>String</code> to append
306 * @return this <code>StringBuffer</code>
308 public synchronized StringBuffer append(String str)
310 if (str == null)
311 str = "null";
312 int len = str.count;
313 ensureCapacity_unsynchronized(count + len);
314 str.getChars(0, len, value, count);
315 count += len;
316 return this;
320 * Append the <code>StringBuffer</code> value of the argument to this
321 * <code>StringBuffer</code>. This behaves the same as
322 * <code>append((Object) stringBuffer)</code>, except it is more efficient.
324 * @param stringBuffer the <code>StringBuffer</code> to convert and append
325 * @return this <code>StringBuffer</code>
326 * @see #append(Object)
327 * @since 1.4
329 public synchronized StringBuffer append(StringBuffer stringBuffer)
331 if (stringBuffer == null)
332 return append("null");
333 synchronized (stringBuffer)
335 int len = stringBuffer.count;
336 ensureCapacity_unsynchronized(count + len);
337 System.arraycopy(stringBuffer.value, 0, value, count, len);
338 count += len;
340 return this;
344 * Append the <code>char</code> array to this <code>StringBuffer</code>.
345 * This is similar (but more efficient) than
346 * <code>append(new String(data))</code>, except in the case of null.
348 * @param data the <code>char[]</code> to append
349 * @return this <code>StringBuffer</code>
350 * @throws NullPointerException if <code>str</code> is <code>null</code>
351 * @see #append(char[], int, int)
353 public StringBuffer append(char[] data)
355 return append(data, 0, data.length);
359 * Append part of the <code>char</code> array to this
360 * <code>StringBuffer</code>. This is similar (but more efficient) than
361 * <code>append(new String(data, offset, count))</code>, except in the case
362 * of null.
364 * @param data the <code>char[]</code> to append
365 * @param offset the start location in <code>str</code>
366 * @param count the number of characters to get from <code>str</code>
367 * @return this <code>StringBuffer</code>
368 * @throws NullPointerException if <code>str</code> is <code>null</code>
369 * @throws IndexOutOfBoundsException if offset or count is out of range
370 * (while unspecified, this is a StringIndexOutOfBoundsException)
372 public synchronized StringBuffer append(char[] data, int offset, int count)
374 if (offset < 0 || count < 0 || offset > data.length - count)
375 throw new StringIndexOutOfBoundsException();
376 ensureCapacity_unsynchronized(this.count + count);
377 System.arraycopy(data, offset, value, this.count, count);
378 this.count += count;
379 return this;
383 * Append the <code>String</code> value of the argument to this
384 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
385 * to <code>String</code>.
387 * @param bool the <code>boolean</code> to convert and append
388 * @return this <code>StringBuffer</code>
389 * @see String#valueOf(boolean)
391 public StringBuffer append(boolean bool)
393 return append(bool ? "true" : "false");
397 * Append the <code>char</code> to this <code>StringBuffer</code>.
399 * @param ch the <code>char</code> to append
400 * @return this <code>StringBuffer</code>
402 public synchronized StringBuffer append(char ch)
404 ensureCapacity_unsynchronized(count + 1);
405 value[count++] = ch;
406 return this;
410 * Append the <code>String</code> value of the argument to this
411 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
412 * to <code>String</code>.
414 * @param inum the <code>int</code> to convert and append
415 * @return this <code>StringBuffer</code>
416 * @see String#valueOf(int)
418 // GCJ LOCAL: this is native for efficiency.
419 public native StringBuffer append (int inum);
422 * Append the <code>String</code> value of the argument to this
423 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
424 * to <code>String</code>.
426 * @param lnum the <code>long</code> to convert and append
427 * @return this <code>StringBuffer</code>
428 * @see String#valueOf(long)
430 public StringBuffer append(long lnum)
432 return append(Long.toString(lnum, 10));
436 * Append the <code>String</code> value of the argument to this
437 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
438 * to <code>String</code>.
440 * @param fnum the <code>float</code> to convert and append
441 * @return this <code>StringBuffer</code>
442 * @see String#valueOf(float)
444 public StringBuffer append(float fnum)
446 return append(Float.toString(fnum));
450 * Append the <code>String</code> value of the argument to this
451 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
452 * to <code>String</code>.
454 * @param dnum the <code>double</code> to convert and append
455 * @return this <code>StringBuffer</code>
456 * @see String#valueOf(double)
458 public StringBuffer append(double dnum)
460 return append(Double.toString(dnum));
464 * Delete characters from this <code>StringBuffer</code>.
465 * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
466 * harmless for end to be larger than length().
468 * @param start the first character to delete
469 * @param end the index after the last character to delete
470 * @return this <code>StringBuffer</code>
471 * @throws StringIndexOutOfBoundsException if start or end are out of bounds
472 * @since 1.2
474 public synchronized StringBuffer delete(int start, int end)
476 if (start < 0 || start > count || start > end)
477 throw new StringIndexOutOfBoundsException(start);
478 if (end > count)
479 end = count;
480 // This will unshare if required.
481 ensureCapacity_unsynchronized(count);
482 if (count - end != 0)
483 System.arraycopy(value, end, value, start, count - end);
484 count -= end - start;
485 return this;
489 * Delete a character from this <code>StringBuffer</code>.
491 * @param index the index of the character to delete
492 * @return this <code>StringBuffer</code>
493 * @throws StringIndexOutOfBoundsException if index is out of bounds
494 * @since 1.2
496 public StringBuffer deleteCharAt(int index)
498 return delete(index, index + 1);
502 * Replace characters between index <code>start</code> (inclusive) and
503 * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
504 * is larger than the size of this StringBuffer, all characters after
505 * <code>start</code> are replaced.
507 * @param start the beginning index of characters to delete (inclusive)
508 * @param end the ending index of characters to delete (exclusive)
509 * @param str the new <code>String</code> to insert
510 * @return this <code>StringBuffer</code>
511 * @throws StringIndexOutOfBoundsException if start or end are out of bounds
512 * @throws NullPointerException if str is null
513 * @since 1.2
515 public synchronized StringBuffer replace(int start, int end, String str)
517 if (start < 0 || start > count || start > end)
518 throw new StringIndexOutOfBoundsException(start);
520 int len = str.count;
521 // Calculate the difference in 'count' after the replace.
522 int delta = len - (end > count ? count : end) + start;
523 ensureCapacity_unsynchronized(count + delta);
525 if (delta != 0 && end < count)
526 System.arraycopy(value, end, value, end + delta, count - end);
528 str.getChars(0, len, value, start);
529 count += delta;
530 return this;
534 * Creates a substring of this StringBuffer, starting at a specified index
535 * and ending at the end of this StringBuffer.
537 * @param beginIndex index to start substring (base 0)
538 * @return new String which is a substring of this StringBuffer
539 * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds
540 * @see #substring(int, int)
541 * @since 1.2
543 public String substring(int beginIndex)
545 return substring(beginIndex, count);
549 * Creates a substring of this StringBuffer, starting at a specified index
550 * and ending at one character before a specified index. This is implemented
551 * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
552 * the CharSequence interface.
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 IndexOutOfBoundsException if beginIndex or endIndex is out of
558 * bounds
559 * @see #substring(int, int)
560 * @since 1.4
562 public CharSequence subSequence(int beginIndex, int endIndex)
564 return substring(beginIndex, endIndex);
568 * Creates a substring of this StringBuffer, starting at a specified index
569 * and ending at one character before a specified index.
571 * @param beginIndex index to start at (inclusive, base 0)
572 * @param endIndex index to end at (exclusive)
573 * @return new String which is a substring of this StringBuffer
574 * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
575 * of bounds
576 * @since 1.2
578 public synchronized String substring(int beginIndex, int endIndex)
580 int len = endIndex - beginIndex;
581 if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
582 throw new StringIndexOutOfBoundsException();
583 if (len == 0)
584 return "";
585 // Don't copy unless substring is smaller than 1/4 of the buffer.
586 boolean share_buffer = ((len << 2) >= value.length);
587 if (share_buffer)
588 this.shared = true;
589 // Package constructor avoids an array copy.
590 return new String(value, beginIndex, len, share_buffer);
594 * Insert a subarray of the <code>char[]</code> argument into this
595 * <code>StringBuffer</code>.
597 * @param offset the place to insert in this buffer
598 * @param str the <code>char[]</code> to insert
599 * @param str_offset the index in <code>str</code> to start inserting from
600 * @param len the number of characters to insert
601 * @return this <code>StringBuffer</code>
602 * @throws NullPointerException if <code>str</code> is <code>null</code>
603 * @throws StringIndexOutOfBoundsException if any index is out of bounds
604 * @since 1.2
606 public synchronized StringBuffer insert(int offset,
607 char[] str, int str_offset, int len)
609 if (offset < 0 || offset > count || len < 0
610 || str_offset < 0 || str_offset > str.length - len)
611 throw new StringIndexOutOfBoundsException();
612 ensureCapacity_unsynchronized(count + len);
613 System.arraycopy(value, offset, value, offset + len, count - offset);
614 System.arraycopy(str, str_offset, value, offset, len);
615 count += len;
616 return this;
620 * Insert the <code>String</code> value of the argument into this
621 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
622 * to <code>String</code>.
624 * @param offset the place to insert in this buffer
625 * @param obj the <code>Object</code> to convert and insert
626 * @return this <code>StringBuffer</code>
627 * @exception StringIndexOutOfBoundsException if offset is out of bounds
628 * @see String#valueOf(Object)
630 public StringBuffer insert(int offset, Object obj)
632 return insert(offset, obj == null ? "null" : obj.toString());
636 * Insert the <code>String</code> argument into this
637 * <code>StringBuffer</code>. If str is null, the String "null" is used
638 * instead.
640 * @param offset the place to insert in this buffer
641 * @param str the <code>String</code> to insert
642 * @return this <code>StringBuffer</code>
643 * @throws StringIndexOutOfBoundsException if offset is out of bounds
645 public synchronized StringBuffer insert(int offset, String str)
647 if (offset < 0 || offset > count)
648 throw new StringIndexOutOfBoundsException(offset);
649 if (str == null)
650 str = "null";
651 int len = str.count;
652 ensureCapacity_unsynchronized(count + len);
653 System.arraycopy(value, offset, value, offset + len, count - offset);
654 str.getChars(0, len, value, offset);
655 count += len;
656 return this;
660 * Insert the <code>char[]</code> argument into this
661 * <code>StringBuffer</code>.
663 * @param offset the place to insert in this buffer
664 * @param data the <code>char[]</code> to insert
665 * @return this <code>StringBuffer</code>
666 * @throws NullPointerException if <code>data</code> is <code>null</code>
667 * @throws StringIndexOutOfBoundsException if offset is out of bounds
668 * @see #insert(int, char[], int, int)
670 public StringBuffer insert(int offset, char[] data)
672 return insert(offset, data, 0, data.length);
676 * Insert the <code>String</code> value of the argument into this
677 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
678 * to <code>String</code>.
680 * @param offset the place to insert in this buffer
681 * @param bool the <code>boolean</code> to convert and insert
682 * @return this <code>StringBuffer</code>
683 * @throws StringIndexOutOfBoundsException if offset is out of bounds
684 * @see String#valueOf(boolean)
686 public StringBuffer insert(int offset, boolean bool)
688 return insert(offset, bool ? "true" : "false");
692 * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
694 * @param offset the place to insert in this buffer
695 * @param ch the <code>char</code> to insert
696 * @return this <code>StringBuffer</code>
697 * @throws StringIndexOutOfBoundsException if offset is out of bounds
699 public synchronized StringBuffer insert(int offset, char ch)
701 if (offset < 0 || offset > count)
702 throw new StringIndexOutOfBoundsException(offset);
703 ensureCapacity_unsynchronized(count + 1);
704 System.arraycopy(value, offset, value, offset + 1, count - offset);
705 value[offset] = ch;
706 count++;
707 return this;
711 * Insert the <code>String</code> value of the argument into this
712 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
713 * to <code>String</code>.
715 * @param offset the place to insert in this buffer
716 * @param inum the <code>int</code> to convert and insert
717 * @return this <code>StringBuffer</code>
718 * @throws StringIndexOutOfBoundsException if offset is out of bounds
719 * @see String#valueOf(int)
721 public StringBuffer insert(int offset, int inum)
723 return insert(offset, String.valueOf(inum));
727 * Insert the <code>String</code> value of the argument into this
728 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
729 * to <code>String</code>.
731 * @param offset the place to insert in this buffer
732 * @param lnum the <code>long</code> to convert and insert
733 * @return this <code>StringBuffer</code>
734 * @throws StringIndexOutOfBoundsException if offset is out of bounds
735 * @see String#valueOf(long)
737 public StringBuffer insert(int offset, long lnum)
739 return insert(offset, Long.toString(lnum, 10));
743 * Insert the <code>String</code> value of the argument into this
744 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
745 * to <code>String</code>.
747 * @param offset the place to insert in this buffer
748 * @param fnum the <code>float</code> to convert and insert
749 * @return this <code>StringBuffer</code>
750 * @throws StringIndexOutOfBoundsException if offset is out of bounds
751 * @see String#valueOf(float)
753 public StringBuffer insert(int offset, float fnum)
755 return insert(offset, Float.toString(fnum));
759 * Insert the <code>String</code> value of the argument into this
760 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
761 * to <code>String</code>.
763 * @param offset the place to insert in this buffer
764 * @param dnum the <code>double</code> to convert and insert
765 * @return this <code>StringBuffer</code>
766 * @throws StringIndexOutOfBoundsException if offset is out of bounds
767 * @see String#valueOf(double)
769 public StringBuffer insert(int offset, double dnum)
771 return insert(offset, Double.toString(dnum));
775 * Finds the first instance of a substring in this StringBuffer.
777 * @param str String to find
778 * @return location (base 0) of the String, or -1 if not found
779 * @throws NullPointerException if str is null
780 * @see #indexOf(String, int)
781 * @since 1.4
783 public int indexOf(String str)
785 return indexOf(str, 0);
789 * Finds the first instance of a String in this StringBuffer, starting at
790 * a given index. If starting index is less than 0, the search starts at
791 * the beginning of this String. If the starting index is greater than the
792 * length of this String, or the substring is not found, -1 is returned.
794 * @param str String to find
795 * @param fromIndex index to start the search
796 * @return location (base 0) of the String, or -1 if not found
797 * @throws NullPointerException if str is null
798 * @since 1.4
800 public synchronized int indexOf(String str, int fromIndex)
802 if (fromIndex < 0)
803 fromIndex = 0;
804 int limit = count - str.count;
805 for ( ; fromIndex <= limit; fromIndex++)
806 if (regionMatches(fromIndex, str))
807 return fromIndex;
808 return -1;
812 * Finds the last instance of a substring in this StringBuffer.
814 * @param str String to find
815 * @return location (base 0) of the String, or -1 if not found
816 * @throws NullPointerException if str is null
817 * @see #lastIndexOf(String, int)
818 * @since 1.4
820 public int lastIndexOf(String str)
822 return lastIndexOf(str, count - str.count);
826 * Finds the last instance of a String in this StringBuffer, starting at a
827 * given index. If starting index is greater than the maximum valid index,
828 * then the search begins at the end of this String. If the starting index
829 * is less than zero, or the substring is not found, -1 is returned.
831 * @param str String to find
832 * @param fromIndex index to start the search
833 * @return location (base 0) of the String, or -1 if not found
834 * @throws NullPointerException if str is null
835 * @since 1.4
837 public synchronized int lastIndexOf(String str, int fromIndex)
839 fromIndex = Math.min(fromIndex, count - str.count);
840 for ( ; fromIndex >= 0; fromIndex--)
841 if (regionMatches(fromIndex, str))
842 return fromIndex;
843 return -1;
847 * Reverse the characters in this StringBuffer. The same sequence of
848 * characters exists, but in the reverse index ordering.
850 * @return this <code>StringBuffer</code>
852 public synchronized StringBuffer reverse()
854 // Call ensureCapacity to enforce copy-on-write.
855 ensureCapacity_unsynchronized(count);
856 for (int i = count >> 1, j = count - i; --i >= 0; ++j)
858 char c = value[i];
859 value[i] = value[j];
860 value[j] = c;
862 return this;
866 * Convert this <code>StringBuffer</code> to a <code>String</code>. The
867 * String is composed of the characters currently in this StringBuffer. Note
868 * that the result is a copy, and that future modifications to this buffer
869 * do not affect the String.
871 * @return the characters in this StringBuffer
873 public String toString()
875 // The string will set this.shared = true.
876 return new String(this);
880 * An unsynchronized version of ensureCapacity, used internally to avoid
881 * the cost of a second lock on the same object. This also has the side
882 * effect of duplicating the array, if it was shared (to form copy-on-write
883 * semantics).
885 * @param minimumCapacity the minimum capacity
886 * @see #ensureCapacity(int)
888 private void ensureCapacity_unsynchronized(int minimumCapacity)
890 if (shared || minimumCapacity > value.length)
892 // We don't want to make a larger vector when `shared' is
893 // set. If we do, then setLength becomes very inefficient
894 // when repeatedly reusing a StringBuffer in a loop.
895 int max = (minimumCapacity > value.length
896 ? value.length * 2 + 2
897 : value.length);
898 minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
899 char[] nb = new char[minimumCapacity];
900 System.arraycopy(value, 0, nb, 0, count);
901 value = nb;
902 shared = false;
907 * Predicate which determines if a substring of this matches another String
908 * starting at a specified offset for each String and continuing for a
909 * specified length. This is more efficient than creating a String to call
910 * indexOf on.
912 * @param toffset index to start comparison at for this String
913 * @param other non-null String to compare to region of this
914 * @return true if regions match, false otherwise
915 * @see #indexOf(String, int)
916 * @see #lastIndexOf(String, int)
917 * @see String#regionMatches(boolean, int, String, int, int)
919 // GCJ LOCAL: native for gcj.
920 private native boolean regionMatches(int toffset, String other);