1 /* StringBuilder.java -- Unsynchronized growable strings
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
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. */
43 * <code>StringBuilder</code> represents a changeable <code>String</code>.
44 * It provides the operations required to modify the
45 * <code>StringBuilder</code>, including insert, replace, delete, append,
46 * and reverse. It like <code>StringBuffer</code>, but is not
47 * synchronized. It is ideal for use when it is known that the
48 * object will only be used from a single thread.
50 * <p><code>StringBuilder</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>StringBuilder</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>StringBuilder</code> operation:<br>
58 * <code>a + b</code><br>
60 * <code>new StringBuilder().append(a).append(b).toString()</code>.
62 * <p>Classpath's StringBuilder is capable of sharing memory with Strings for
63 * efficiency. This will help when a StringBuilder is converted to a String
64 * and the StringBuilder is not changed after that (quite common when
65 * performing string concatenation).
70 * @author Eric Blake (ebb9@email.byu.edu)
76 public final class StringBuilder
78 // Implementation note: if you change this class, you usually will
79 // want to change StringBuffer as well.
83 * The buffer. Note that this has permissions set this way so that String
91 * The default capacity of a buffer.
93 private static final int DEFAULT_CAPACITY = 16;
96 * For compatability with Sun's JDK
98 private static final long serialVersionUID = 4383685877147921099L;
101 * Create a new StringBuilder with default capacity 16.
103 public StringBuilder()
105 value = new char[this.DEFAULT_CAPACITY];
110 * Create an empty <code>StringBuilder</code> with the specified initial
113 * @param capacity the initial capacity
114 * @throws NegativeArraySizeException if capacity is negative
116 public StringBuilder(int capacity)
118 value = new char[capacity];
123 * Create a new <code>StringBuilder</code> with the characters in the
124 * specified <code>String</code>. Initial capacity will be the size of the
127 * @param str the <code>String</code> to convert
128 * @throws NullPointerException if str is null
130 public StringBuilder(String str)
133 value = new char[count + DEFAULT_CAPACITY];
134 str.getChars(0, count, value, 0);
138 * Get the length of the <code>String</code> this <code>StringBuilder</code>
139 * would create. Not to be confused with the <em>capacity</em> of the
140 * <code>StringBuilder</code>.
142 * @return the length of this <code>StringBuilder</code>
144 * @see #setLength(int)
152 * Get the total number of characters this <code>StringBuilder</code> can
153 * support before it must be grown. Not to be confused with <em>length</em>.
155 * @return the capacity of this <code>StringBuilder</code>
157 * @see #ensureCapacity(int)
159 public int capacity()
164 void ensureCapacity_unsynchronized(int minimumCapacity)
166 if (minimumCapacity > value.length)
168 int max = value.length * 2 + 2;
169 minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
170 char[] nb = new char[minimumCapacity];
171 System.arraycopy(value, 0, nb, 0, count);
177 * Append the <code>String</code> value of the argument to this
178 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
179 * to <code>String</code>.
181 * @param obj the <code>Object</code> to convert and append
182 * @return this <code>StringBuilder</code>
183 * @see String#valueOf(Object)
184 * @see #append(String)
186 public StringBuilder append(Object obj)
188 append(String.valueOf(obj));
193 * Append the <code>String</code> to this <code>StringBuilder</code>. If
194 * str is null, the String "null" is appended.
196 * @param str the <code>String</code> to append
197 * @return this <code>StringBuilder</code>
199 public StringBuilder append(String str)
204 ensureCapacity_unsynchronized(count + len);
205 str.getChars(0, len, value, count);
211 * Append the <code>StringBuilder</code> value of the argument to this
212 * <code>StringBuilder</code>. This behaves the same as
213 * <code>append((Object) stringBuffer)</code>, except it is more efficient.
215 * @param stringBuffer the <code>StringBuilder</code> to convert and append
216 * @return this <code>StringBuilder</code>
217 * @see #append(Object)
219 public StringBuilder append(StringBuffer stringBuffer)
221 if (stringBuffer == null)
222 return append("null");
223 synchronized (stringBuffer)
225 int len = stringBuffer.count;
226 ensureCapacity(count + len);
227 System.arraycopy(stringBuffer.value, 0, value, count, len);
233 public void ensureCapacity(int minimumCapacity)
235 ensureCapacity_unsynchronized(minimumCapacity);
239 * Append the <code>char</code> array to this <code>StringBuilder</code>.
240 * This is similar (but more efficient) than
241 * <code>append(new String(data))</code>, except in the case of null.
243 * @param data the <code>char[]</code> to append
244 * @return this <code>StringBuilder</code>
245 * @throws NullPointerException if <code>str</code> is <code>null</code>
246 * @see #append(char[], int, int)
248 public StringBuilder append(char[] data)
250 append(data, 0, data.length);
255 * Append part of the <code>char</code> array to this
256 * <code>StringBuilder</code>. This is similar (but more efficient) than
257 * <code>append(new String(data, offset, count))</code>, except in the case
260 * @param data the <code>char[]</code> to append
261 * @param offset the start location in <code>str</code>
262 * @param count the number of characters to get from <code>str</code>
263 * @return this <code>StringBuilder</code>
264 * @throws NullPointerException if <code>str</code> is <code>null</code>
265 * @throws IndexOutOfBoundsException if offset or count is out of range
266 * (while unspecified, this is a StringIndexOutOfBoundsException)
268 public StringBuilder append(char[] data, int offset, int count)
270 if (offset < 0 || count < 0 || offset > data.length - count)
271 throw new /*StringIndexOutOfBounds*/Exception("StringIndexOutOfBoundsException");
272 ensureCapacity_unsynchronized(this.count + count);
273 System.arraycopy(data, offset, value, this.count, count);
279 * Append the <code>String</code> value of the argument to this
280 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
281 * to <code>String</code>.
283 * @param bool the <code>boolean</code> to convert and append
284 * @return this <code>StringBuilder</code>
285 * @see String#valueOf(boolean)
287 public StringBuilder append(boolean bool)
289 append(bool?"true":"false");
294 * Append the <code>char</code> to this <code>StringBuilder</code>.
296 * @param ch the <code>char</code> to append
297 * @return this <code>StringBuilder</code>
299 public StringBuilder append(char ch)
301 ensureCapacity_unsynchronized(count + 1);
307 * Append the <code>String</code> value of the argument to this
308 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
309 * to <code>String</code>.
311 * @param inum the <code>int</code> to convert and append
312 * @return this <code>StringBuilder</code>
313 * @see String#valueOf(int)
315 // This is native in libgcj, for efficiency.
316 public StringBuilder append(int inum)
318 append(String.valueOf(inum));
323 * Append the <code>String</code> value of the argument to this
324 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
325 * to <code>String</code>.
327 * @param lnum the <code>long</code> to convert and append
328 * @return this <code>StringBuilder</code>
329 * @see String#valueOf(long)
331 public StringBuilder append(long lnum)
333 append(String.valueOf(lnum));
338 * Append the <code>String</code> value of the argument to this
339 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
340 * to <code>String</code>.
342 * @param fnum the <code>float</code> to convert and append
343 * @return this <code>StringBuilder</code>
344 * @see String#valueOf(float)
346 public StringBuilder append(float fnum)
348 append(String.valueOf((double)fnum));
353 * Append the <code>String</code> value of the argument to this
354 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert
355 * to <code>String</code>.
357 * @param dnum the <code>double</code> to convert and append
358 * @return this <code>StringBuilder</code>
359 * @see String#valueOf(double)
361 public StringBuilder append(double dnum)
363 append(String.valueOf(dnum));
368 * Convert this <code>StringBuilder</code> to a <code>String</code>. The
369 * String is composed of the characters currently in this StringBuilder. Note
370 * that the result is a copy, and that future modifications to this buffer
371 * do not affect the String.
373 * @return the characters in this StringBuilder
375 public String toString()
377 return new String(this.value, 0, this.count);
381 * Get the character at the specified index.
383 * @param index the index of the character to get, starting at 0
384 * @return the character at the specified index
385 * @throws IndexOutOfBoundsException if index is negative or >= length()
386 * (while unspecified, this is a StringIndexOutOfBoundsException)
388 public char charAt(int index)
390 if (index < 0 || index >= count)
391 throw new /*StringIndexOutOfBounds*/Exception("StringIndexOutOfBounds " + index);
396 * Set the character at the specified index.
398 * @param index the index of the character to set starting at 0
399 * @param ch the value to set that character to
400 * @throws IndexOutOfBoundsException if index is negative or >= length()
401 * (while unspecified, this is a StringIndexOutOfBoundsException)
403 public void setCharAt(int index, char ch)
405 if (index < 0 || index >= count)
406 throw new /*StringIndexOutOfBounds*/Exception("StringIndexOutOfBounds " + index);
407 // Call ensureCapacity to enforce copy-on-write.
408 ensureCapacity_unsynchronized(count);
413 * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
415 * @param offset the place to insert in this buffer
416 * @param ch the <code>char</code> to insert
417 * @return this <code>StringBuffer</code>
418 * @throws StringIndexOutOfBoundsException if offset is out of bounds
420 public StringBuffer insert(int offset, char ch)
422 if (offset < 0 || offset > count)
423 throw new /*StringIndexOutOfBounds*/Exception("StringIndexOutOfBounds " + offset);
424 ensureCapacity_unsynchronized(count + 1);
425 System.arraycopy(value, offset, value, offset + 1, count - offset);