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)
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
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
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. */
41 import java
.io
.Serializable
;
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>
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).
70 * @author Eric Blake (ebb9@email.byu.edu)
73 * @status updated to 1.4
75 public final class StringBuffer
implements Serializable
, CharSequence
78 * Compatible with JDK 1.0+.
80 private static final long serialVersionUID
= 3388685877147921107L;
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
92 * The buffer. Note that this has permissions set this way so that String
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
105 * @serial whether the buffer is 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
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
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.
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>
157 * @see #setLength(int)
159 public synchronized int length()
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>
170 * @see #ensureCapacity(int)
172 public synchronized int capacity()
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
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)
204 public synchronized void setLength(int newLength
)
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'. */
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 >= 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
);
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 >= 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
);
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
)
313 ensureCapacity_unsynchronized(count
+ len
);
314 str
.getChars(0, len
, value
, count
);
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)
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
);
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
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
);
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);
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
474 public synchronized StringBuffer
delete(int start
, int end
)
476 if (start
< 0 || start
> count
|| start
> end
)
477 throw new StringIndexOutOfBoundsException(start
);
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
;
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
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
515 public synchronized StringBuffer
replace(int start
, int end
, String str
)
517 if (start
< 0 || start
> count
|| start
> end
)
518 throw new StringIndexOutOfBoundsException(start
);
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
);
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)
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
559 * @see #substring(int, int)
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
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();
585 // Don't copy unless substring is smaller than 1/4 of the buffer.
586 boolean share_buffer
= ((len
<< 2) >= value
.length
);
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
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
);
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
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
);
652 ensureCapacity_unsynchronized(count
+ len
);
653 System
.arraycopy(value
, offset
, value
, offset
+ len
, count
- offset
);
654 str
.getChars(0, len
, value
, offset
);
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
);
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)
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
800 public synchronized int indexOf(String str
, int fromIndex
)
804 int limit
= count
- str
.count
;
805 for ( ; fromIndex
<= limit
; fromIndex
++)
806 if (regionMatches(fromIndex
, str
))
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)
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
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
))
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
)
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
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
898 minimumCapacity
= (minimumCapacity
< max ? max
: minimumCapacity
);
899 char[] nb
= new char[minimumCapacity
];
900 System
.arraycopy(value
, 0, nb
, 0, count
);
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
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
);