211574a5b7eb25fadc7693fae950ffd9c631eb49
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 native StringBuffer
append (int inum
);
94 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
95 * Uses <code>String.valueOf()</code> to convert to
96 * <code>String</code>.
97 * @param lnum the <code>long</code> to convert and append.
98 * @return this <code>StringBuffer</code>.
99 * @see java.lang.String#valueOf(long)
101 public StringBuffer
append (long lnum
)
103 return append (String
.valueOf(lnum
));
106 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
107 * Uses <code>String.valueOf()</code> to convert to
108 * <code>String</code>.
109 * @param fnum the <code>float</code> to convert and append.
110 * @return this <code>StringBuffer</code>.
111 * @see java.lang.String#valueOf(float)
113 public StringBuffer
append (float fnum
)
115 return append (String
.valueOf(fnum
));
118 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
119 * Uses <code>String.valueOf()</code> to convert to
120 * <code>String</code>.
121 * @param dnum the <code>double</code> to convert and append.
122 * @return this <code>StringBuffer</code>.
123 * @see java.lang.String#valueOf(double)
125 public StringBuffer
append (double dnum
)
127 return append (String
.valueOf(dnum
));
130 /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>.
131 * Uses <code>String.valueOf()</code> to convert to
132 * <code>String</code>.
133 * @param obj the <code>Object</code> to convert and append.
134 * @return this <code>StringBuffer</code>.
135 * @see java.lang.String#valueOf(java.lang.Object)
137 public StringBuffer
append (Object obj
)
139 return append (String
.valueOf(obj
));
142 /** Append the <code>String</code> to this <code>StringBuffer</code>.
143 * @param str the <code>String</code> to append.
144 * @return this <code>StringBuffer</code>.
146 public synchronized StringBuffer
append (String str
)
150 int len
= str
.length();
151 ensureCapacity_unsynchronized (count
+ len
);
152 str
.getChars(0, len
, value
, count
);
157 /** Append the <code>char</code> array to this <code>StringBuffer</code>.
158 * @param data the <code>char[]</code> to append.
159 * @return this <code>StringBuffer</code>.
160 * @exception NullPointerException if <code>str</code> is <code>null</code>.
162 public StringBuffer
append (char[] data
)
164 return append (data
, 0, data
.length
);
167 /** Append the <code>char</code> array to this <code>StringBuffer</code>.
168 * @param data the <code>char[]</code> to append.
169 * @param offset the place to start grabbing characters from
171 * @param count the number of characters to get from <code>str</code>.
172 * @return this <code>StringBuffer</code>.
173 * @exception NullPointerException if <code>str</code> is <code>null</code>.
174 * @exception IndexOutOfBoundsException if <code>offset</code> or
175 * <code>offset+len</code> is out of range.
177 public synchronized StringBuffer
append (char[] data
, int offset
, int count
)
179 ensureCapacity_unsynchronized (this.count
+ count
);
180 System
.arraycopy(data
, offset
, value
, this.count
, count
);
185 /** Get the total number of characters this <code>StringBuffer</code>
186 * can support before it must be grown. Not to be confused with
188 * @return the capacity of this <code>StringBuffer</code>
190 * @see #ensureCapacity(int)
192 public int capacity ()
197 /** Get the character at the specified index.
198 * @param index the index of the character to get, starting at 0.
199 * @return the character at the specified index.
200 * @exception IndexOutOfBoundsException if the desired character index
201 * is not between 0 and length() - 1 (inclusive).
203 public synchronized char charAt (int index
)
206 throw new StringIndexOutOfBoundsException (index
);
210 /** Delete characters from this <code>StringBuffer</code>.
211 * <code>delete(10, 12)</code> will delete 10 and 11, but not 12.
212 * @param start the first character to delete.
213 * @param end the index after the last character to delete.
214 * @return this <code>StringBuffer</code>.
215 * @exception StringIndexOutOfBoundsException if <code>start</code>
216 * or <code>end-1</code> are out of bounds, or if
217 * <code>start > end</code>.
219 public synchronized StringBuffer
delete (int start
, int end
)
221 if (start
< 0 || start
> count
|| start
> end
)
222 throw new StringIndexOutOfBoundsException (start
);
225 // This will unshare if required.
226 ensureCapacity_unsynchronized (count
);
227 if (count
- end
!= 0)
228 System
.arraycopy (value
, end
, value
, start
, count
- end
);
229 count
-= (end
- start
);
233 /** Delete a character from this <code>StringBuffer</code>.
234 * @param index the index of the character to delete.
235 * @return this <code>StringBuffer</code>.
236 * @exception StringIndexOutOfBoundsException if <code>index</code>
239 public StringBuffer
deleteCharAt(int index
)
241 return delete (index
, index
+ 1);
244 /** Increase the capacity of this <code>StringBuffer</code>.
245 * This will ensure that an expensive growing operation will not occur
246 * until <code>minimumCapacity</code> is reached.
247 * If the capacity is actually already greater than <code>minimumCapacity</code>
248 * @param minimumCapacity the new capacity.
251 public synchronized void ensureCapacity (int minimumCapacity
)
253 if (shared
|| minimumCapacity
> value
.length
)
255 // We don't want to make a larger vector when `shared' is
256 // set. If we do, then setLength becomes very inefficient
257 // when repeatedly reusing a StringBuffer in a loop.
258 int max
= (minimumCapacity
> value
.length
261 minimumCapacity
= (minimumCapacity
< max ? max
: minimumCapacity
);
262 char[] nb
= new char[minimumCapacity
];
263 System
.arraycopy(value
, 0, nb
, 0, count
);
269 // ensureCapacity is used by several synchronized methods in StringBuffer.
270 // There's no need to synchronize again.
271 private void ensureCapacity_unsynchronized (int minimumCapacity
)
273 if (shared
|| minimumCapacity
> value
.length
)
275 // We don't want to make a larger vector when `shared' is
276 // set. If we do, then setLength becomes very inefficient
277 // when repeatedly reusing a StringBuffer in a loop.
278 int max
= (minimumCapacity
> value
.length
281 minimumCapacity
= (minimumCapacity
< max ? max
: minimumCapacity
);
282 char[] nb
= new char[minimumCapacity
];
283 System
.arraycopy(value
, 0, nb
, 0, count
);
289 /** Get the specified array of characters.
290 * The characters will be copied into the array you pass in.
291 * @param srcOffset the index to start copying from in the
292 * <code>StringBuffer</code>.
293 * @param srcEnd the number of characters to copy.
294 * @param dst the array to copy into.
295 * @param dstOffset the index to start copying into <code>dst</code>.
296 * @exception NullPointerException if dst is null.
297 * @exception IndexOutOfBoundsException if any source or target
298 * indices are out of range.
299 * @see java.lang.System#arraycopy(java.lang.Object,int,java.lang.Object,int,int)
301 public synchronized void getChars (int srcOffset
, int srcEnd
,
302 char[] dst
, int dstOffset
)
304 if (srcOffset
< 0 || srcOffset
> srcEnd
)
305 throw new StringIndexOutOfBoundsException (srcOffset
);
306 int todo
= srcEnd
- srcOffset
;
307 if (srcEnd
> count
|| dstOffset
+ todo
> count
)
308 throw new StringIndexOutOfBoundsException (srcEnd
);
309 System
.arraycopy(value
, srcOffset
, dst
, dstOffset
, todo
);
312 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
313 * Uses <code>String.valueOf()</code> to convert to
314 * <code>String</code>.
315 * @param offset the place to insert.
316 * @param bool the <code>boolean</code> to convert and insert.
317 * @return this <code>StringBuffer</code>.
318 * @exception IndexOutOfBoundsException if <code>offset</code> is out
319 * of range for this <code>StringBuffer</code>.
320 * @see java.lang.String#valueOf(boolean)
322 public StringBuffer
insert (int offset
, boolean bool
)
324 return insert (offset
, bool ?
"true" : "false");
327 /** Insert the <code>char</code> argument into this <code>StringBuffer</code>.
328 * @param offset the place to insert.
329 * @param ch the <code>char</code> to insert.
330 * @return this <code>StringBuffer</code>.
331 * @exception IndexOutOfBoundsException if <code>offset</code> is out
332 * of range for this <code>StringBuffer</code>.
334 public synchronized StringBuffer
insert (int offset
, char ch
)
336 if (offset
< 0 || offset
> count
)
337 throw new StringIndexOutOfBoundsException (offset
);
338 ensureCapacity_unsynchronized (count
+1);
339 System
.arraycopy(value
, offset
, value
, offset
+1, count
-offset
);
345 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
346 * Uses <code>String.valueOf()</code> to convert to
347 * <code>String</code>.
348 * @param offset the place to insert.
349 * @param inum the <code>int</code> to convert and insert.
350 * @return this <code>StringBuffer</code>.
351 * @exception IndexOutOfBoundsException if <code>offset</code> is out
352 * of range for this <code>StringBuffer</code>.
353 * @see java.lang.String#valueOf(int)
355 public StringBuffer
insert (int offset
, int inum
)
357 return insert (offset
, String
.valueOf(inum
));
360 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
361 * Uses <code>String.valueOf()</code> to convert to
362 * <code>String</code>.
363 * @param offset the place to insert.
364 * @param lnum the <code>long</code> to convert and insert.
365 * @return this <code>StringBuffer</code>.
366 * @exception IndexOutOfBoundsException if <code>offset</code> is out
367 * of range for this <code>StringBuffer</code>.
368 * @see java.lang.String#valueOf(long)
370 public StringBuffer
insert (int offset
, long lnum
)
372 return insert (offset
, String
.valueOf(lnum
));
375 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
376 * Uses <code>String.valueOf()</code> to convert to
377 * <code>String</code>.
378 * @param offset the place to insert.
379 * @param fnum the <code>float</code> to convert and insert.
380 * @return this <code>StringBuffer</code>.
381 * @exception IndexOutOfBoundsException if <code>offset</code> is out
382 * of range for this <code>StringBuffer</code>.
383 * @see java.lang.String#valueOf(float)
385 public StringBuffer
insert (int offset
, float fnum
)
387 return insert (offset
, String
.valueOf(fnum
));
390 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
391 * Uses <code>String.valueOf()</code> to convert to
392 * <code>String</code>.
393 * @param offset the place to insert.
394 * @param dnum the <code>double</code> to convert and insert.
395 * @return this <code>StringBuffer</code>.
396 * @exception IndexOutOfBoundsException if <code>offset</code> is out
397 * of range for this <code>StringBuffer</code>.
398 * @see java.lang.String#valueOf(double)
400 public StringBuffer
insert (int offset
, double dnum
)
402 return insert (offset
, String
.valueOf(dnum
));
405 /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>.
406 * Uses <code>String.valueOf()</code> to convert to
407 * <code>String</code>.
408 * @param offset the place to insert.
409 * @param obj the <code>Object</code> to convert and insert.
410 * @return this <code>StringBuffer</code>.
411 * @exception IndexOutOfBoundsException if <code>offset</code> is out
412 * of range for this <code>StringBuffer</code>.
413 * @see java.lang.String#valueOf(java.lang.Object)
415 public StringBuffer
insert (int offset
, Object obj
)
417 return insert (offset
, String
.valueOf(obj
));
420 /** Insert the <code>String</code> argument into this <code>StringBuffer</code>.
421 * @param offset the place to insert.
422 * @param str the <code>String</code> to insert.
423 * @return this <code>StringBuffer</code>.
424 * @exception IndexOutOfBoundsException if <code>offset</code> is out
425 * of range for this <code>StringBuffer</code>.
427 public synchronized StringBuffer
insert (int offset
, String str
)
429 if (offset
< 0 || offset
> count
)
430 throw new StringIndexOutOfBoundsException (offset
);
431 // Note that using `null' is from JDK 1.2.
434 int len
= str
.length();
435 ensureCapacity_unsynchronized (count
+len
);
436 System
.arraycopy(value
, offset
, value
, offset
+len
, count
-offset
);
437 str
.getChars(0, len
, value
, offset
);
442 /** Insert the <code>char[]</code> argument into this
443 * <code>StringBuffer</code>.
444 * @param offset the place to insert.
445 * @param data the <code>char[]</code> to insert.
446 * @return this <code>StringBuffer</code>.
447 * @exception NullPointerException if <code>data</code> is
449 * @exception IndexOutOfBoundsException if <code>offset</code> is out
450 * of range for this <code>StringBuffer</code>.
452 public StringBuffer
insert (int offset
, char[] data
)
454 // One could check if offset is invalid here instead of making sure that
455 // data isn't null before dereferencing, but this works just as well.
456 return insert (offset
, data
, 0, data
== null ?
0 : data
.length
);
459 /** Insert the <code>char[]</code> argument into this
460 * <code>StringBuffer</code>.
461 * @param offset the place to insert.
462 * @param str the <code>char[]</code> to insert.
463 * @param str_offset the index in <code>str</code> to start inserting
465 * @param len the number of characters to insert.
466 * @return this <code>StringBuffer</code>.
467 * @exception NullPointerException if <code>str</code> is <code>null</code>.
468 * @exception IndexOutOfBoundsException if <code>offset</code> is out
469 * of range, for this <code>StringBuffer</code>, or if
470 * <code>str_offset</code> or <code>str_offset+len</code>
471 * are out of range for <code>str</code>.
473 public synchronized StringBuffer
insert(int offset
, char[] str
,
474 int str_offset
, int len
)
476 if (offset
< 0 || offset
> count
)
477 throw new StringIndexOutOfBoundsException (offset
);
479 throw new StringIndexOutOfBoundsException (len
);
480 if (str_offset
< 0 || str_offset
+ len
> str
.length
)
481 throw new StringIndexOutOfBoundsException (str_offset
);
482 ensureCapacity_unsynchronized (count
+ len
);
483 System
.arraycopy(value
, offset
, value
, offset
+ len
, count
- offset
);
484 System
.arraycopy(str
, str_offset
, value
, offset
, len
);
489 /** Get the length of the <code>String</code> this
490 * <code>StringBuffer</code> would create. Not to be confused with the
491 * <em>capacity</em> of the <code>StringBuffer</code>.
492 * @return the length of this <code>StringBuffer</code>.
494 * @see #setLength(int)
501 /** Replace characters between index <code>start</code> (inclusive) and
502 * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
503 * is larger than the size of this StringBuffer, all characters after
504 * <code>start</code> are replaced.
505 * @param start the beginning index of characters to delete (inclusive).
506 * @param end the ending index of characters to delete (exclusive).
507 * @param str the new <code>String</code> to insert.
508 * @return this <code>StringBuffer</code>.
510 public synchronized StringBuffer
replace (int start
, int end
, String str
)
512 if (start
< 0 || start
> count
|| start
> end
)
513 throw new StringIndexOutOfBoundsException (start
);
515 int len
= str
.length();
516 // Calculate the difference in 'count' after the replace.
517 int delta
= len
- ((end
> count ? count
: end
) - start
);
518 ensureCapacity_unsynchronized (count
+ delta
);
520 if (delta
!= 0 && end
< count
)
521 System
.arraycopy(value
, end
, value
, end
+ delta
, count
- end
);
523 str
.getChars (0, len
, value
, start
);
528 /** Reverse the characters in this StringBuffer.
529 * @return this <code>StringBuffer</code>.
531 public synchronized StringBuffer
reverse ()
533 // Call ensureCapacity to enforce copy-on-write.
534 ensureCapacity_unsynchronized (count
);
535 for (int i
= 0; i
< count
/ 2; ++i
)
538 value
[i
] = value
[count
- i
- 1];
539 value
[count
- i
- 1] = c
;
544 /** Set the character at the specified index.
545 * @param index the index of the character to set starting at 0.
546 * @param ch the value to set that character to.
547 * @exception IndexOutOfBoundsException if the specified character
548 * index is not between 0 and length() - 1 (inclusive).
550 public synchronized void setCharAt (int index
, char ch
)
552 if (index
< 0 || index
>= count
)
553 throw new StringIndexOutOfBoundsException (index
);
554 // Call ensureCapacity to enforce copy-on-write.
555 ensureCapacity_unsynchronized (count
);
559 /** Set the length of this StringBuffer.
561 * If the new length is greater than the current length, all the new
562 * characters are set to '\0'.
564 * If the new length is less than the current length, the first
565 * <code>newLength</code> characters of the old array will be
566 * @param newLength the new length
567 * @exception IndexOutOfBoundsException if the new length is
571 public synchronized void setLength (int newLength
)
574 throw new StringIndexOutOfBoundsException (newLength
);
576 ensureCapacity_unsynchronized (newLength
);
577 for (int i
= count
; i
< newLength
; ++i
)
582 /** Create a new StringBuffer with default capacity 16.
585 public StringBuffer ()
587 this (DEFAULT_CAPACITY
);
590 /** Create an empty <code>StringBuffer</code> with the specified initial capacity.
591 * @param capacity the initial capacity.
593 public StringBuffer (int capacity
)
596 value
= new char[capacity
];
600 /** Create a new <code>StringBuffer</code> with the characters in the specified <code>String</code>.
601 * Initial capacity will be the size of the String plus 16.
602 * @param str the <code>String</code> to make a <code>StringBuffer</code> out of.
603 * @XXX optimize for sharing.
605 public StringBuffer (String str
)
607 // The documentation is not clear, but experimentation with
608 // other implementations indicates that StringBuffer(null)
609 // should throw a NullPointerException.
610 count
= str
.length();
611 // JLS: The initial capacity of the string buffer is 16 plus the
612 // length of the argument string.
613 value
= new char[count
+ DEFAULT_CAPACITY
];
614 str
.getChars(0, count
, value
, 0);
619 * Creates a substring of this StringBuffer, starting at a specified index
620 * and ending at the end of this StringBuffer.
622 * @param beginIndex index to start substring (base 0)
624 * @return new String which is a substring of this StringBuffer
626 * @exception StringIndexOutOfBoundsException
627 * if (beginIndex < 0 || beginIndex > this.length())
629 public String
substring (int beginIndex
)
631 return substring (beginIndex
, count
);
635 * Creates a substring of this StringBuffer, starting at a specified index
636 * and ending at one character before a specified index.
638 * @param beginIndex index to start substring (base 0)
639 * @param endIndex index after the last character to be
640 * copied into the substring
642 * @return new String which is a substring of this StringBuffer
644 * @exception StringIndexOutOfBoundsException
645 * if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex)
647 public synchronized String
substring (int beginIndex
, int endIndex
)
649 if (beginIndex
< 0 || endIndex
> count
|| beginIndex
> endIndex
)
650 throw new StringIndexOutOfBoundsException ();
651 // FIXME: for libgcj it would be possible, and more efficient, to
652 // enable sharing here.
653 return new String (value
, beginIndex
, endIndex
- beginIndex
);
656 /** Convert this <code>StringBuffer</code> to a <code>String</code>.
657 * @return the characters in this StringBuffer
659 public String
toString ()
661 // Note: in libgcj this causes the StringBuffer to be shared. In
662 // Classpath it does not.
663 return new String (this);
666 // Index of next available character. Note that this has
667 // permissions set this way so that String can get the value.
670 // The buffer. Note that this has permissions set this way so that
671 // String can get the value.
674 // True if we need to copy the buffer before writing to it again.
675 // FIXME: JDK 1.2 doesn't specify this. The new buffer-growing
676 // semantics make this less useful in that case, too. Note that
677 // this has permissions set this way so that String can get the
681 static final long serialVersionUID
= 3388685877147921107L;
682 private final static int DEFAULT_CAPACITY
= 16; // JLS 20.13.1