1 // StringBuffer.java - Growable strings.
3 /* Copyright (C) 1998, 1999, 2000 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
12 import java.io.Serializable;
15 * @author Tom Tromey <tromey@cygnus.com>
16 * @date October 23, 1998.
19 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
20 * Updated using online JDK 1.2 docs.
21 * Believed complete and correct to JDK 1.2.
22 * Merged with Classpath.
26 * <code>StringBuffer</code> represents a changeable <code>String</code>.
27 * It provides the operations required to modify the
28 * <code>StringBuffer</code> including insert, replace, delete, append,
32 * <code>StringBuffer</code>s are variable-length in nature, so even if
33 * you initialize them to a certain size, they can still grow larger than
34 * that. <EM>Capacity</EM> indicates the number of characters the
35 * <code>StringBuffer</code> can have in it before it has to grow (growing
36 * the char array is an expensive operation involving <code>new</code>).
39 * Incidentally, the String operator "+" actually is turned into a
40 * <code>StringBuffer</code> operation:
46 * <code>new StringBuffer(a).append(b).toString()</code>.
48 * @implnote Classpath's StringBuffer is capable of sharing memory with
49 * Strings for efficiency. This will help in two instances:
50 * first, when a StringBuffer is created from a String but is
51 * never changed, and second, when a StringBuffer is converted
52 * to a String and the StringBuffer is not changed after that.
58 * @see java.lang.String
60 public final class StringBuffer implements Serializable
62 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
63 * Uses <code>String.valueOf()</code> to convert to
64 * <code>String</code>.
65 * @param bool the <code>boolean</code> to convert and append.
66 * @return this <code>StringBuffer</code>.
67 * @see java.lang.String#valueOf(boolean)
69 public StringBuffer append (boolean bool)
71 return append (String.valueOf(bool));
74 /** Append the <code>char</code> to this <code>StringBuffer</code>.
75 * @param c the <code>char</code> to append.
76 * @return this <code>StringBuffer</code>.
78 public synchronized StringBuffer append (char ch)
80 ensureCapacity_unsynchronized (count + 1);
85 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
86 * Uses <code>String.valueOf()</code> to convert to
87 * <code>String</code>.
88 * @param inum the <code>int</code> to convert and append.
89 * @return this <code>StringBuffer</code>.
90 * @see java.lang.String#valueOf(int)
92 public StringBuffer append (int inum)
94 return append (String.valueOf(inum));
97 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
98 * Uses <code>String.valueOf()</code> to convert to
99 * <code>String</code>.
100 * @param lnum the <code>long</code> to convert and append.
101 * @return this <code>StringBuffer</code>.
102 * @see java.lang.String#valueOf(long)
104 public StringBuffer append (long lnum)
106 return append (String.valueOf(lnum));
109 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
110 * Uses <code>String.valueOf()</code> to convert to
111 * <code>String</code>.
112 * @param fnum the <code>float</code> to convert and append.
113 * @return this <code>StringBuffer</code>.
114 * @see java.lang.String#valueOf(float)
116 public StringBuffer append (float fnum)
118 return append (String.valueOf(fnum));
121 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
122 * Uses <code>String.valueOf()</code> to convert to
123 * <code>String</code>.
124 * @param dnum the <code>double</code> to convert and append.
125 * @return this <code>StringBuffer</code>.
126 * @see java.lang.String#valueOf(double)
128 public StringBuffer append (double dnum)
130 return append (String.valueOf(dnum));
133 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
134 * Uses <code>String.valueOf()</code> to convert to
135 * <code>String</code>.
136 * @param obj the <code>Object</code> to convert and append.
137 * @return this <code>StringBuffer</code>.
138 * @see java.lang.String#valueOf(java.lang.Object)
140 public StringBuffer append (Object obj)
142 return append (String.valueOf(obj));
145 /** Append the <code>String</code> to this <code>StringBuffer</code>.
146 * @param str the <code>String</code> to append.
147 * @return this <code>StringBuffer</code>.
149 public synchronized StringBuffer append (String str)
153 int len = str.length();
154 ensureCapacity_unsynchronized (count + len);
155 str.getChars(0, len, value, count);
160 /** Append the <code>char</code> array to this <code>StringBuffer</code>.
161 * @param data the <code>char[]</code> to append.
162 * @return this <code>StringBuffer</code>.
163 * @exception NullPointerException if <code>str</code> is <code>null</code>.
165 public StringBuffer append (char[] data)
167 return append (data, 0, data.length);
170 /** Append the <code>char</code> array to this <code>StringBuffer</code>.
171 * @param data the <code>char[]</code> to append.
172 * @param offset the place to start grabbing characters from
174 * @param count the number of characters to get from <code>str</code>.
175 * @return this <code>StringBuffer</code>.
176 * @exception NullPointerException if <code>str</code> is <code>null</code>.
177 * @exception IndexOutOfBoundsException if <code>offset</code> or
178 * <code>offset+len</code> is out of range.
180 public synchronized StringBuffer append (char[] data, int offset, int count)
182 ensureCapacity_unsynchronized (this.count + count);
183 System.arraycopy(data, offset, value, this.count, count);
188 /** Get the total number of characters this <code>StringBuffer</code>
189 * can support before it must be grown. Not to be confused with
191 * @return the capacity of this <code>StringBuffer</code>
193 * @see #ensureCapacity(int)
195 public int capacity ()
200 /** Get the character at the specified index.
201 * @param index the index of the character to get, starting at 0.
202 * @return the character at the specified index.
203 * @exception IndexOutOfBoundsException if the desired character index
204 * is not between 0 and length() - 1 (inclusive).
206 public synchronized char charAt (int index)
209 throw new StringIndexOutOfBoundsException (index);
213 /** Delete characters from this <code>StringBuffer</code>.
214 * <code>delete(10, 12)</code> will delete 10 and 11, but not 12.
215 * @param start the first character to delete.
216 * @param end the index after the last character to delete.
217 * @return this <code>StringBuffer</code>.
218 * @exception StringIndexOutOfBoundsException if <code>start</code>
219 * or <code>end-1</code> are out of bounds, or if
220 * <code>start > end</code>.
222 public synchronized StringBuffer delete (int start, int end)
224 if (start < 0 || start > count || start > end)
225 throw new StringIndexOutOfBoundsException (start);
228 // This will unshare if required.
229 ensureCapacity_unsynchronized (count);
230 if (count - end != 0)
231 System.arraycopy (value, end, value, start, count - end);
232 count -= (end - start);
236 /** Delete a character from this <code>StringBuffer</code>.
237 * @param index the index of the character to delete.
238 * @return this <code>StringBuffer</code>.
239 * @exception StringIndexOutOfBoundsException if <code>index</code>
242 public StringBuffer deleteCharAt(int index)
244 return delete (index, index + 1);
247 /** Increase the capacity of this <code>StringBuffer</code>.
248 * This will ensure that an expensive growing operation will not occur
249 * until <code>minimumCapacity</code> is reached.
250 * If the capacity is actually already greater than <code>minimumCapacity</code>
251 * @param minimumCapacity the new capacity.
254 public synchronized void ensureCapacity (int minimumCapacity)
256 if (shared || minimumCapacity > value.length)
258 // We don't want to make a larger vector when `shared' is
259 // set. If we do, then setLength becomes very inefficient
260 // when repeatedly reusing a StringBuffer in a loop.
261 int max = (minimumCapacity > value.length
264 minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
265 char[] nb = new char[minimumCapacity];
266 System.arraycopy(value, 0, nb, 0, count);
272 // ensureCapacity is used by several synchronized methods in StringBuffer.
273 // There's no need to synchronize again.
274 private void ensureCapacity_unsynchronized (int minimumCapacity)
276 if (shared || minimumCapacity > value.length)
278 // We don't want to make a larger vector when `shared' is
279 // set. If we do, then setLength becomes very inefficient
280 // when repeatedly reusing a StringBuffer in a loop.
281 int max = (minimumCapacity > value.length
284 minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
285 char[] nb = new char[minimumCapacity];
286 System.arraycopy(value, 0, nb, 0, count);
292 /** Get the specified array of characters.
293 * The characters will be copied into the array you pass in.
294 * @param srcOffset the index to start copying from in the
295 * <code>StringBuffer</code>.
296 * @param srcEnd the number of characters to copy.
297 * @param dst the array to copy into.
298 * @param dstOffset the index to start copying into <code>dst</code>.
299 * @exception NullPointerException if dst is null.
300 * @exception IndexOutOfBoundsException if any source or target
301 * indices are out of range.
302 * @see java.lang.System#arrayCopy(java.lang.Object,int,java.lang.Object,int,int)
304 public synchronized void getChars (int srcOffset, int srcEnd,
305 char[] dst, int dstOffset)
307 if (srcOffset < 0 || srcOffset > srcEnd)
308 throw new StringIndexOutOfBoundsException (srcOffset);
309 int todo = srcEnd - srcOffset;
310 if (srcEnd > count || dstOffset + todo > count)
311 throw new StringIndexOutOfBoundsException (srcEnd);
312 System.arraycopy(value, srcOffset, dst, dstOffset, todo);
315 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
316 * Uses <code>String.valueOf()</code> to convert to
317 * <code>String</code>.
318 * @param offset the place to insert.
319 * @param bool the <code>boolean</code> to convert and insert.
320 * @return this <code>StringBuffer</code>.
321 * @exception IndexOutOfBoundsException if <code>offset</code> is out
322 * of range for this <code>StringBuffer</code>.
323 * @see java.lang.String#valueOf(boolean)
325 public StringBuffer insert (int offset, boolean bool)
327 return insert (offset, bool ? "true" : "false");
330 /** Insert the <code>char</code> argument into this <code>StringBuffer</code>.
331 * @param offset the place to insert.
332 * @param ch the <code>char</code> to insert.
333 * @return this <code>StringBuffer</code>.
334 * @exception IndexOutOfBoundsException if <code>offset</code> is out
335 * of range for this <code>StringBuffer</code>.
337 public synchronized StringBuffer insert (int offset, char ch)
339 if (offset < 0 || offset > count)
340 throw new StringIndexOutOfBoundsException (offset);
341 ensureCapacity_unsynchronized (count+1);
342 System.arraycopy(value, offset, value, offset+1, count-offset);
348 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
349 * Uses <code>String.valueOf()</code> to convert to
350 * <code>String</code>.
351 * @param offset the place to insert.
352 * @param inum the <code>int</code> to convert and insert.
353 * @return this <code>StringBuffer</code>.
354 * @exception IndexOutOfBoundsException if <code>offset</code> is out
355 * of range for this <code>StringBuffer</code>.
356 * @see java.lang.String#valueOf(int)
358 public StringBuffer insert (int offset, int inum)
360 return insert (offset, String.valueOf(inum));
363 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
364 * Uses <code>String.valueOf()</code> to convert to
365 * <code>String</code>.
366 * @param offset the place to insert.
367 * @param lnum the <code>long</code> to convert and insert.
368 * @return this <code>StringBuffer</code>.
369 * @exception IndexOutOfBoundsException if <code>offset</code> is out
370 * of range for this <code>StringBuffer</code>.
371 * @see java.lang.String#valueOf(long)
373 public StringBuffer insert (int offset, long lnum)
375 return insert (offset, String.valueOf(lnum));
378 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
379 * Uses <code>String.valueOf()</code> to convert to
380 * <code>String</code>.
381 * @param offset the place to insert.
382 * @param fnum the <code>float</code> to convert and insert.
383 * @return this <code>StringBuffer</code>.
384 * @exception IndexOutOfBoundsException if <code>offset</code> is out
385 * of range for this <code>StringBuffer</code>.
386 * @see java.lang.String#valueOf(float)
388 public StringBuffer insert (int offset, float fnum)
390 return insert (offset, String.valueOf(fnum));
393 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
394 * Uses <code>String.valueOf()</code> to convert to
395 * <code>String</code>.
396 * @param offset the place to insert.
397 * @param dnum the <code>double</code> to convert and insert.
398 * @return this <code>StringBuffer</code>.
399 * @exception IndexOutOfBoundsException if <code>offset</code> is out
400 * of range for this <code>StringBuffer</code>.
401 * @see java.lang.String#valueOf(double)
403 public StringBuffer insert (int offset, double dnum)
405 return insert (offset, String.valueOf(dnum));
408 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
409 * Uses <code>String.valueOf()</code> to convert to
410 * <code>String</code>.
411 * @param offset the place to insert.
412 * @param obj the <code>Object</code> to convert and insert.
413 * @return this <code>StringBuffer</code>.
414 * @exception IndexOutOfBoundsException if <code>offset</code> is out
415 * of range for this <code>StringBuffer</code>.
416 * @see java.lang.String#valueOf(java.lang.Object)
418 public StringBuffer insert (int offset, Object obj)
420 return insert (offset, String.valueOf(obj));
423 /** Insert the <code>String</code> argument into this <code>StringBuffer</code>.
424 * @param offset the place to insert.
425 * @param str the <code>String</code> to insert.
426 * @return this <code>StringBuffer</code>.
427 * @exception IndexOutOfBoundsException if <code>offset</code> is out
428 * of range for this <code>StringBuffer</code>.
430 public synchronized StringBuffer insert (int offset, String str)
432 if (offset < 0 || offset > count)
433 throw new StringIndexOutOfBoundsException (offset);
434 // Note that using `null' is from JDK 1.2.
437 int len = str.length();
438 ensureCapacity_unsynchronized (count+len);
439 System.arraycopy(value, offset, value, offset+len, count-offset);
440 str.getChars(0, len, value, offset);
445 /** Insert the <code>char[]</code> argument into this
446 * <code>StringBuffer</code>.
447 * @param offset the place to insert.
448 * @param data the <code>char[]</code> to insert.
449 * @return this <code>StringBuffer</code>.
450 * @exception NullPointerException if <code>data</code> is
452 * @exception IndexOutOfBoundsException if <code>offset</code> is out
453 * of range for this <code>StringBuffer</code>.
455 public StringBuffer insert (int offset, char[] data)
457 return insert (offset, data, 0, data.length);
460 /** Insert the <code>char[]</code> argument into this
461 * <code>StringBuffer</code>.
462 * @param offset the place to insert.
463 * @param str the <code>char[]</code> to insert.
464 * @param str_offset the index in <code>str</code> to start inserting
466 * @param len the number of characters to insert.
467 * @return this <code>StringBuffer</code>.
468 * @exception NullPointerException if <code>str</code> is <code>null</code>.
469 * @exception IndexOutOfBoundsException if <code>offset</code> is out
470 * of range, for this <code>StringBuffer</code>, or if
471 * <code>str_offset</code> or <code>str_offset+len</code>
472 * are out of range for <code>str</code>.
474 public synchronized StringBuffer insert(int offset, char[] str,
475 int str_offset, int len)
477 if (offset < 0 || offset > count)
478 throw new StringIndexOutOfBoundsException (offset);
480 throw new StringIndexOutOfBoundsException (len);
481 if (str_offset < 0 || str_offset + len > str.length)
482 throw new StringIndexOutOfBoundsException (str_offset);
483 ensureCapacity_unsynchronized (count + len);
484 System.arraycopy(value, offset, value, offset + len, count - offset);
485 System.arraycopy(str, str_offset, value, offset, len);
490 /** Get the length of the <code>String</code> this
491 * <code>StringBuffer</code> would create. Not to be confused with the
492 * <em>capacity</em> of the <code>StringBuffer</code>.
493 * @return the length of this <code>StringBuffer</code>.
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.
506 * @param start the beginning index of characters to delete (inclusive).
507 * @param end the ending index of characters to delete (exclusive).
508 * @param str the new <code>String</code> to insert.
509 * @return this <code>StringBuffer</code>.
511 public synchronized StringBuffer replace (int start, int end, String str)
513 if (start < 0 || start > count || start > end)
514 throw new StringIndexOutOfBoundsException (start);
516 int len = str.length();
517 // Calculate the difference in 'count' after the replace.
518 int delta = len - ((end > count ? count : end) - start);
519 ensureCapacity_unsynchronized (count + delta);
521 if (delta != 0 && end < count)
522 System.arraycopy(value, end, value, end + delta, count - end);
524 str.getChars (0, len, value, start);
529 /** Reverse the characters in this StringBuffer.
530 * @return this <code>StringBuffer</code>.
532 public synchronized StringBuffer reverse ()
534 // Call ensureCapacity to enforce copy-on-write.
535 ensureCapacity_unsynchronized (count);
536 for (int i = 0; i < count / 2; ++i)
539 value[i] = value[count - i - 1];
540 value[count - i - 1] = c;
545 /** Set the character at the specified index.
546 * @param index the index of the character to set starting at 0.
547 * @param ch the value to set that character to.
548 * @exception IndexOutOfBoundsException if the specified character
549 * index is not between 0 and length() - 1 (inclusive).
551 public synchronized void setCharAt (int index, char ch)
553 if (index < 0 || index >= count)
554 throw new StringIndexOutOfBoundsException (index);
555 // Call ensureCapacity to enforce copy-on-write.
556 ensureCapacity_unsynchronized (count);
560 /** Set the length of this StringBuffer.
562 * If the new length is greater than the current length, all the new
563 * characters are set to '\0'.
565 * If the new length is less than the current length, the first
566 * <code>newLength</code> characters of the old array will be
567 * @param newLength the new length
568 * @exception IndexOutOfBoundsException if the new length is
572 public synchronized void setLength (int newLength)
575 throw new StringIndexOutOfBoundsException (newLength);
577 ensureCapacity_unsynchronized (newLength);
578 for (int i = count; i < newLength; ++i)
583 /** Create a new StringBuffer with default capacity 16.
586 public StringBuffer ()
588 this (DEFAULT_CAPACITY);
591 /** Create an empty <code>StringBuffer</code> with the specified initial capacity.
592 * @param capacity the initial capacity.
594 public StringBuffer (int capacity)
597 value = new char[capacity];
601 /** Create a new <code>StringBuffer</code> with the characters in the specified <code>String</code>.
602 * Initial capacity will be the size of the String plus 16.
603 * @param str the <code>String</code> to make a <code>StringBuffer</code> out of.
604 * @XXX optimize for sharing.
606 public StringBuffer (String str)
608 // The documentation is not clear, but experimentation with
609 // other implementations indicates that StringBuffer(null)
610 // should throw a NullPointerException.
611 count = str.length();
612 // JLS: The initial capacity of the string buffer is 16 plus the
613 // length of the argument string.
614 value = new char[count + DEFAULT_CAPACITY];
615 str.getChars(0, count, value, 0);
620 * Creates a substring of this StringBuffer, starting at a specified index
621 * and ending at the end of this StringBuffer.
623 * @param beginIndex index to start substring (base 0)
625 * @return new String which is a substring of this StringBuffer
627 * @exception StringIndexOutOfBoundsException
628 * if (beginIndex < 0 || beginIndex > this.length())
630 public String substring (int beginIndex)
632 return substring (beginIndex, count);
636 * Creates a substring of this StringBuffer, starting at a specified index
637 * and ending at one character before a specified index.
639 * @param beginIndex index to start substring (base 0)
640 * @param endIndex index after the last character to be
641 * copied into the substring
643 * @return new String which is a substring of this StringBuffer
645 * @exception StringIndexOutOfBoundsException
646 * if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)
648 public synchronized String substring (int beginIndex, int endIndex)
650 if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
651 throw new StringIndexOutOfBoundsException ();
652 // FIXME: for libgcj it would be possible, and more efficient, to
653 // enable sharing here.
654 return new String (value, beginIndex, endIndex - beginIndex);
657 /** Convert this <code>StringBuffer</code> to a <code>String</code>.
658 * @return the characters in this StringBuffer
660 public String toString ()
662 // Note: in libgcj this causes the StringBuffer to be shared. In
663 // Classpath it does not.
664 return new String (this);
667 // Index of next available character. Note that this has
668 // permissions set this way so that String can get the value.
671 // The buffer. Note that this has permissions set this way so that
672 // String can get the value.
675 // True if we need to copy the buffer before writing to it again.
676 // FIXME: JDK 1.2 doesn't specify this. The new buffer-growing
677 // semantics make this less useful in that case, too. Note that
678 // this has permissions set this way so that String can get the
682 static final long serialVersionUID = 3388685877147921107L;
683 private final static int DEFAULT_CAPACITY = 16; // JLS 20.13.1