2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / lang / StringBuffer.java
blob92f961534a13bab006517d1c6859e0b692bcd167
1 /* StringBuffer.java -- Growable strings
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
38 package java.lang;
40 import java.io.Serializable;
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.
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>).
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>.
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).
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
74 public final class StringBuffer implements Serializable, CharSequence
76 /**
77 * Compatible with JDK 1.0+.
79 private static final long serialVersionUID = 3388685877147921107L;
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.
86 * @serial the number of characters in the buffer
88 int count;
90 /**
91 * The buffer. Note that this has permissions set this way so that String
92 * can get the value.
94 * @serial the buffer
96 char[] value;
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.
104 * @serial whether the buffer is shared
106 boolean shared;
109 * The default capacity of a buffer.
111 private final static int DEFAULT_CAPACITY = 16;
114 * Create a new StringBuffer with default capacity 16.
116 public StringBuffer()
118 this(DEFAULT_CAPACITY);
122 * Create an empty <code>StringBuffer</code> with the specified initial
123 * capacity.
125 * @param capacity the initial capacity
126 * @throws NegativeArraySizeException if capacity is negative
128 public StringBuffer(int capacity)
130 value = new char[capacity];
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.
138 * @param str the <code>String</code> to convert
139 * @throws NullPointerException if str is null
141 public StringBuffer(String str)
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);
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>.
154 * @return the length of this <code>StringBuffer</code>
155 * @see #capacity()
156 * @see #setLength(int)
158 public synchronized int length()
160 return count;
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>.
167 * @return the capacity of this <code>StringBuffer</code>
168 * @see #length()
169 * @see #ensureCapacity(int)
171 public synchronized int capacity()
173 return value.length;
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.
183 * @param minimumCapacity the new capacity
184 * @see #capacity()
186 public synchronized void ensureCapacity(int minimumCapacity)
188 ensureCapacity_unsynchronized(minimumCapacity);
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.
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()
203 public synchronized void setLength(int newLength)
205 if (newLength < 0)
206 throw new StringIndexOutOfBoundsException(newLength);
208 ensureCapacity_unsynchronized(newLength);
209 while (count < newLength)
210 value[count++] = '\0';
211 count = newLength;
215 * Get the character at the specified index.
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)
222 public synchronized char charAt(int index)
224 if (index < 0 || index >= count)
225 throw new StringIndexOutOfBoundsException(index);
226 return value[index];
230 * Get the specified array of characters. <code>srcOffset - srcEnd</code>
231 * characters will be copied into the array you pass in.
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)
244 public synchronized void getChars(int srcOffset, int srcEnd,
245 char[] dst, int dstOffset)
247 if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
248 throw new StringIndexOutOfBoundsException();
249 System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
253 * Set the character at the specified index.
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)
260 public synchronized void setCharAt(int index, char ch)
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;
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>.
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)
279 public StringBuffer append(Object obj)
281 return append(obj == null ? "null" : obj.toString());
285 * Append the <code>String</code> to this <code>StringBuffer</code>. If
286 * str is null, the String "null" is appended.
288 * @param str the <code>String</code> to append
289 * @return this <code>StringBuffer</code>
291 public synchronized StringBuffer append(String str)
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;
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.
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
312 public synchronized StringBuffer append(StringBuffer stringBuffer)
314 if (stringBuffer == null)
315 return append("null");
316 synchronized (stringBuffer)
318 int len = stringBuffer.count;
319 ensureCapacity_unsynchronized(count + len);
320 System.arraycopy(stringBuffer.value, 0, value, count, len);
321 count += len;
323 return this;
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.
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)
336 public StringBuffer append(char[] data)
338 return append(data, 0, data.length);
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.
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)
355 public synchronized StringBuffer append(char[] data, int offset, int count)
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;
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>.
370 * @param bool the <code>boolean</code> to convert and append
371 * @return this <code>StringBuffer</code>
372 * @see String#valueOf(boolean)
374 public StringBuffer append(boolean bool)
376 return append(bool ? "true" : "false");
380 * Append the <code>char</code> to this <code>StringBuffer</code>.
382 * @param c the <code>char</code> to append
383 * @return this <code>StringBuffer</code>
385 public synchronized StringBuffer append(char ch)
387 ensureCapacity_unsynchronized(count + 1);
388 value[count++] = ch;
389 return this;
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>.
397 * @param inum the <code>int</code> to convert and append
398 * @return this <code>StringBuffer</code>
399 * @see String#valueOf(int)
401 // GCJ LOCAL: this is native for efficiency.
402 public native StringBuffer append (int inum);
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>.
409 * @param lnum the <code>long</code> to convert and append
410 * @return this <code>StringBuffer</code>
411 * @see String#valueOf(long)
413 public StringBuffer append(long lnum)
415 return append(Long.toString(lnum, 10));
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>.
423 * @param fnum the <code>float</code> to convert and append
424 * @return this <code>StringBuffer</code>
425 * @see String#valueOf(float)
427 public StringBuffer append(float fnum)
429 return append(Float.toString(fnum));
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>.
437 * @param dnum the <code>double</code> to convert and append
438 * @return this <code>StringBuffer</code>
439 * @see String#valueOf(double)
441 public StringBuffer append(double dnum)
443 return append(Double.toString(dnum));
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().
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
457 public synchronized StringBuffer delete(int start, int end)
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;
472 * Delete a character from this <code>StringBuffer</code>.
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
479 public StringBuffer deleteCharAt(int index)
481 return delete(index, index + 1);
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.
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
498 public synchronized StringBuffer replace(int start, int end, String str)
500 if (start < 0 || start > count || start > end)
501 throw new StringIndexOutOfBoundsException(start);
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);
508 if (delta != 0 && end < count)
509 System.arraycopy(value, end, value, end + delta, count - end);
511 str.getChars(0, len, value, start);
512 count += delta;
513 return this;
517 * Creates a substring of this StringBuffer, starting at a specified index
518 * and ending at the end of this StringBuffer.
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
526 public String substring(int beginIndex)
528 return substring(beginIndex, count);
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.
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
545 public CharSequence subSequence(int beginIndex, int endIndex)
547 return substring(beginIndex, endIndex);
551 * Creates a substring of this StringBuffer, starting at a specified index
552 * and ending at one character before a specified index.
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
561 public synchronized String substring(int beginIndex, int endIndex)
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);
577 * Insert a subarray of the <code>char[]</code> argument into this
578 * <code>StringBuffer</code>.
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
589 public synchronized StringBuffer insert(int offset,
590 char[] str, int str_offset, int len)
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;
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>.
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)
613 public StringBuffer insert(int offset, Object obj)
615 return insert(offset, obj == null ? "null" : obj.toString());
619 * Insert the <code>String</code> argument into this
620 * <code>StringBuffer</code>. If str is null, the String "null" is used
621 * instead.
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
628 public synchronized StringBuffer insert(int offset, String str)
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;
643 * Insert the <code>char[]</code> argument into this
644 * <code>StringBuffer</code>.
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)
653 public StringBuffer insert(int offset, char[] data)
655 return insert(offset, data, 0, data.length);
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>.
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)
669 public StringBuffer insert(int offset, boolean bool)
671 return insert(offset, bool ? "true" : "false");
675 * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
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
682 public synchronized StringBuffer insert(int offset, char ch)
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;
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>.
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)
704 public StringBuffer insert(int offset, int inum)
706 return insert(offset, String.valueOf(inum));
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>.
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)
720 public StringBuffer insert(int offset, long lnum)
722 return insert(offset, Long.toString(lnum, 10));
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>.
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)
736 public StringBuffer insert(int offset, float fnum)
738 return insert(offset, Float.toString(fnum));
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>.
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)
752 public StringBuffer insert(int offset, double dnum)
754 return insert(offset, Double.toString(dnum));
758 * Finds the first instance of a substring in this StringBuffer.
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
766 public int indexOf(String str)
768 return indexOf(str, 0);
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.
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
783 public synchronized int indexOf(String str, int fromIndex)
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;
795 * Finds the last instance of a substring in this StringBuffer.
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
803 public int lastIndexOf(String str)
805 return lastIndexOf(str, count - str.count);
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.
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
820 public synchronized int lastIndexOf(String str, int fromIndex)
822 fromIndex = Math.min(fromIndex, count - str.count);
823 for ( ; fromIndex >= 0; fromIndex--)
824 if (regionMatches(fromIndex, str))
825 return fromIndex;
826 return -1;
830 * Reverse the characters in this StringBuffer. The same sequence of
831 * characters exists, but in the reverse index ordering.
833 * @return this <code>StringBuffer</code>
835 public synchronized StringBuffer reverse()
837 // Call ensureCapacity to enforce copy-on-write.
838 ensureCapacity_unsynchronized(count);
839 for (int i = count >> 1, j = count - i; --i >= 0; ++j)
841 char c = value[i];
842 value[i] = value[j];
843 value[j] = c;
845 return this;
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.
854 * @return the characters in this StringBuffer
856 public String toString()
858 // The string will set this.shared = true.
859 return new String(this);
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).
868 * @param minimumCapacity the minimum capacity
869 * @see #ensureCapacity(int)
871 private void ensureCapacity_unsynchronized(int minimumCapacity)
873 if (shared || minimumCapacity > value.length)
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;
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.
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)
902 // GCJ LOCAL: native for gcj.
903 private native boolean regionMatches(int toffset, String other);