]>
Commit | Line | Data |
---|---|---|
0cb757cc | 1 | /* StringBuilder.java -- Unsynchronized growable strings |
666ff4f6 | 2 | Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 |
0cb757cc TT |
3 | Free Software Foundation, Inc. |
4 | ||
5 | This file is part of GNU Classpath. | |
6 | ||
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) | |
10 | any later version. | |
11 | ||
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. | |
16 | ||
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 | |
917b04f4 KC |
19 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
20 | 02110-1301 USA. | |
0cb757cc TT |
21 | |
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 | |
25 | combination. | |
26 | ||
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. */ | |
38 | ||
39 | package java.lang; | |
40 | ||
41 | import java.io.Serializable; | |
42 | ||
43 | /** | |
44 | * <code>StringBuilder</code> represents a changeable <code>String</code>. | |
45 | * It provides the operations required to modify the | |
46 | * <code>StringBuilder</code>, including insert, replace, delete, append, | |
47 | * and reverse. It like <code>StringBuffer</code>, but is not | |
48 | * synchronized. It is ideal for use when it is known that the | |
49 | * object will only be used from a single thread. | |
50 | * | |
51 | * <p><code>StringBuilder</code>s are variable-length in nature, so even if | |
52 | * you initialize them to a certain size, they can still grow larger than | |
53 | * that. <em>Capacity</em> indicates the number of characters the | |
54 | * <code>StringBuilder</code> can have in it before it has to grow (growing | |
55 | * the char array is an expensive operation involving <code>new</code>). | |
56 | * | |
57 | * <p>Incidentally, compilers often implement the String operator "+" | |
58 | * by using a <code>StringBuilder</code> operation:<br> | |
59 | * <code>a + b</code><br> | |
60 | * is the same as<br> | |
61 | * <code>new StringBuilder().append(a).append(b).toString()</code>. | |
62 | * | |
63 | * <p>Classpath's StringBuilder is capable of sharing memory with Strings for | |
64 | * efficiency. This will help when a StringBuilder is converted to a String | |
65 | * and the StringBuilder is not changed after that (quite common when | |
66 | * performing string concatenation). | |
67 | * | |
68 | * @author Paul Fisher | |
69 | * @author John Keiser | |
70 | * @author Tom Tromey | |
71 | * @author Eric Blake (ebb9@email.byu.edu) | |
72 | * @see String | |
73 | * @see StringBuffer | |
74 | * | |
75 | * @since 1.5 | |
76 | */ | |
0cb757cc | 77 | public final class StringBuilder |
97b8365c | 78 | implements Serializable, CharSequence, Appendable |
0cb757cc TT |
79 | { |
80 | // Implementation note: if you change this class, you usually will | |
81 | // want to change StringBuffer as well. | |
82 | ||
83 | /** | |
84 | * For compatability with Sun's JDK | |
85 | */ | |
86 | private static final long serialVersionUID = 4383685877147921099L; | |
87 | ||
88 | /** | |
89 | * Index of next available character (and thus the size of the current | |
90 | * string contents). Note that this has permissions set this way so that | |
91 | * String can get the value. | |
92 | * | |
93 | * @serial the number of characters in the buffer | |
94 | */ | |
95 | int count; | |
96 | ||
97 | /** | |
98 | * The buffer. Note that this has permissions set this way so that String | |
99 | * can get the value. | |
100 | * | |
101 | * @serial the buffer | |
102 | */ | |
103 | char[] value; | |
104 | ||
105 | /** | |
106 | * The default capacity of a buffer. | |
107 | */ | |
108 | private static final int DEFAULT_CAPACITY = 16; | |
109 | ||
110 | /** | |
111 | * Create a new StringBuilder with default capacity 16. | |
112 | */ | |
113 | public StringBuilder() | |
114 | { | |
115 | this(DEFAULT_CAPACITY); | |
116 | } | |
117 | ||
118 | /** | |
119 | * Create an empty <code>StringBuilder</code> with the specified initial | |
120 | * capacity. | |
121 | * | |
122 | * @param capacity the initial capacity | |
123 | * @throws NegativeArraySizeException if capacity is negative | |
124 | */ | |
125 | public StringBuilder(int capacity) | |
126 | { | |
127 | value = new char[capacity]; | |
128 | } | |
129 | ||
130 | /** | |
131 | * Create a new <code>StringBuilder</code> with the characters in the | |
132 | * specified <code>String</code>. Initial capacity will be the size of the | |
133 | * String plus 16. | |
134 | * | |
135 | * @param str the <code>String</code> to convert | |
136 | * @throws NullPointerException if str is null | |
137 | */ | |
138 | public StringBuilder(String str) | |
139 | { | |
140 | // Unfortunately, because the size is 16 larger, we cannot share. | |
141 | count = str.count; | |
142 | value = new char[count + DEFAULT_CAPACITY]; | |
143 | str.getChars(0, count, value, 0); | |
144 | } | |
145 | ||
146 | /** | |
147 | * Create a new <code>StringBuilder</code> with the characters in the | |
148 | * specified <code>CharSequence</code>. Initial capacity will be the | |
149 | * length of the sequence plus 16; if the sequence reports a length | |
150 | * less than or equal to 0, then the initial capacity will be 16. | |
151 | * | |
152 | * @param seq the initializing <code>CharSequence</code> | |
153 | * @throws NullPointerException if str is null | |
154 | */ | |
155 | public StringBuilder(CharSequence seq) | |
156 | { | |
157 | int len = seq.length(); | |
158 | count = len <= 0 ? 0 : len; | |
159 | value = new char[count + DEFAULT_CAPACITY]; | |
160 | for (int i = 0; i < len; ++i) | |
161 | value[i] = seq.charAt(i); | |
162 | } | |
163 | ||
164 | /** | |
165 | * Get the length of the <code>String</code> this <code>StringBuilder</code> | |
166 | * would create. Not to be confused with the <em>capacity</em> of the | |
167 | * <code>StringBuilder</code>. | |
168 | * | |
169 | * @return the length of this <code>StringBuilder</code> | |
170 | * @see #capacity() | |
171 | * @see #setLength(int) | |
172 | */ | |
173 | public int length() | |
174 | { | |
175 | return count; | |
176 | } | |
177 | ||
178 | /** | |
179 | * Get the total number of characters this <code>StringBuilder</code> can | |
180 | * support before it must be grown. Not to be confused with <em>length</em>. | |
181 | * | |
182 | * @return the capacity of this <code>StringBuilder</code> | |
183 | * @see #length() | |
184 | * @see #ensureCapacity(int) | |
185 | */ | |
186 | public int capacity() | |
187 | { | |
188 | return value.length; | |
189 | } | |
190 | ||
191 | /** | |
192 | * Increase the capacity of this <code>StringBuilder</code>. This will | |
193 | * ensure that an expensive growing operation will not occur until | |
194 | * <code>minimumCapacity</code> is reached. The buffer is grown to the | |
195 | * larger of <code>minimumCapacity</code> and | |
196 | * <code>capacity() * 2 + 2</code>, if it is not already large enough. | |
197 | * | |
198 | * @param minimumCapacity the new capacity | |
199 | * @see #capacity() | |
200 | */ | |
201 | public void ensureCapacity(int minimumCapacity) | |
202 | { | |
203 | if (minimumCapacity > value.length) | |
204 | { | |
205 | int max = value.length * 2 + 2; | |
206 | minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); | |
207 | char[] nb = new char[minimumCapacity]; | |
208 | System.arraycopy(value, 0, nb, 0, count); | |
209 | value = nb; | |
210 | } | |
211 | } | |
212 | ||
213 | /** | |
214 | * Set the length of this StringBuilder. If the new length is greater than | |
215 | * the current length, all the new characters are set to '\0'. If the new | |
216 | * length is less than the current length, the first <code>newLength</code> | |
217 | * characters of the old array will be preserved, and the remaining | |
218 | * characters are truncated. | |
219 | * | |
220 | * @param newLength the new length | |
221 | * @throws IndexOutOfBoundsException if the new length is negative | |
222 | * (while unspecified, this is a StringIndexOutOfBoundsException) | |
223 | * @see #length() | |
224 | */ | |
225 | public void setLength(int newLength) | |
226 | { | |
227 | if (newLength < 0) | |
228 | throw new StringIndexOutOfBoundsException(newLength); | |
229 | ||
230 | int valueLength = value.length; | |
231 | ||
232 | /* Always call ensureCapacity in order to preserve copy-on-write | |
233 | semantics. */ | |
234 | ensureCapacity(newLength); | |
235 | ||
236 | if (newLength < valueLength) | |
237 | { | |
238 | /* If the StringBuilder's value just grew, then we know that | |
239 | value is newly allocated and the region between count and | |
240 | newLength is filled with '\0'. */ | |
241 | count = newLength; | |
242 | } | |
243 | else | |
244 | { | |
245 | /* The StringBuilder's value doesn't need to grow. However, | |
246 | we should clear out any cruft that may exist. */ | |
247 | while (count < newLength) | |
248 | value[count++] = '\0'; | |
249 | } | |
250 | } | |
251 | ||
252 | /** | |
253 | * Get the character at the specified index. | |
254 | * | |
255 | * @param index the index of the character to get, starting at 0 | |
256 | * @return the character at the specified index | |
257 | * @throws IndexOutOfBoundsException if index is negative or >= length() | |
258 | * (while unspecified, this is a StringIndexOutOfBoundsException) | |
259 | */ | |
260 | public char charAt(int index) | |
261 | { | |
262 | if (index < 0 || index >= count) | |
263 | throw new StringIndexOutOfBoundsException(index); | |
264 | return value[index]; | |
265 | } | |
266 | ||
267 | /** | |
268 | * Get the specified array of characters. <code>srcOffset - srcEnd</code> | |
269 | * characters will be copied into the array you pass in. | |
270 | * | |
271 | * @param srcOffset the index to start copying from (inclusive) | |
272 | * @param srcEnd the index to stop copying from (exclusive) | |
273 | * @param dst the array to copy into | |
274 | * @param dstOffset the index to start copying into | |
275 | * @throws NullPointerException if dst is null | |
276 | * @throws IndexOutOfBoundsException if any source or target indices are | |
277 | * out of range (while unspecified, source problems cause a | |
278 | * StringIndexOutOfBoundsException, and dest problems cause an | |
279 | * ArrayIndexOutOfBoundsException) | |
280 | * @see System#arraycopy(Object, int, Object, int, int) | |
281 | */ | |
282 | public void getChars(int srcOffset, int srcEnd, | |
283 | char[] dst, int dstOffset) | |
284 | { | |
285 | if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset) | |
286 | throw new StringIndexOutOfBoundsException(); | |
287 | System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset); | |
288 | } | |
289 | ||
290 | /** | |
291 | * Set the character at the specified index. | |
292 | * | |
293 | * @param index the index of the character to set starting at 0 | |
294 | * @param ch the value to set that character to | |
295 | * @throws IndexOutOfBoundsException if index is negative or >= length() | |
296 | * (while unspecified, this is a StringIndexOutOfBoundsException) | |
297 | */ | |
298 | public void setCharAt(int index, char ch) | |
299 | { | |
300 | if (index < 0 || index >= count) | |
301 | throw new StringIndexOutOfBoundsException(index); | |
302 | // Call ensureCapacity to enforce copy-on-write. | |
303 | ensureCapacity(count); | |
304 | value[index] = ch; | |
305 | } | |
306 | ||
307 | /** | |
308 | * Append the <code>String</code> value of the argument to this | |
309 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
310 | * to <code>String</code>. | |
311 | * | |
312 | * @param obj the <code>Object</code> to convert and append | |
313 | * @return this <code>StringBuilder</code> | |
314 | * @see String#valueOf(Object) | |
315 | * @see #append(String) | |
316 | */ | |
317 | public StringBuilder append(Object obj) | |
318 | { | |
319 | return append(obj == null ? "null" : obj.toString()); | |
320 | } | |
321 | ||
322 | /** | |
323 | * Append the <code>String</code> to this <code>StringBuilder</code>. If | |
324 | * str is null, the String "null" is appended. | |
325 | * | |
326 | * @param str the <code>String</code> to append | |
327 | * @return this <code>StringBuilder</code> | |
328 | */ | |
329 | public StringBuilder append(String str) | |
330 | { | |
331 | if (str == null) | |
332 | str = "null"; | |
333 | int len = str.count; | |
334 | ensureCapacity(count + len); | |
335 | str.getChars(0, len, value, count); | |
336 | count += len; | |
337 | return this; | |
338 | } | |
339 | ||
340 | /** | |
341 | * Append the <code>StringBuilder</code> value of the argument to this | |
342 | * <code>StringBuilder</code>. This behaves the same as | |
343 | * <code>append((Object) stringBuffer)</code>, except it is more efficient. | |
344 | * | |
345 | * @param stringBuffer the <code>StringBuilder</code> to convert and append | |
346 | * @return this <code>StringBuilder</code> | |
347 | * @see #append(Object) | |
348 | */ | |
349 | public StringBuilder append(StringBuffer stringBuffer) | |
350 | { | |
351 | if (stringBuffer == null) | |
352 | return append("null"); | |
353 | synchronized (stringBuffer) | |
354 | { | |
355 | int len = stringBuffer.count; | |
356 | ensureCapacity(count + len); | |
357 | System.arraycopy(stringBuffer.value, 0, value, count, len); | |
358 | count += len; | |
359 | } | |
360 | return this; | |
361 | } | |
362 | ||
363 | /** | |
364 | * Append the <code>char</code> array to this <code>StringBuilder</code>. | |
365 | * This is similar (but more efficient) than | |
366 | * <code>append(new String(data))</code>, except in the case of null. | |
367 | * | |
368 | * @param data the <code>char[]</code> to append | |
369 | * @return this <code>StringBuilder</code> | |
370 | * @throws NullPointerException if <code>str</code> is <code>null</code> | |
371 | * @see #append(char[], int, int) | |
372 | */ | |
373 | public StringBuilder append(char[] data) | |
374 | { | |
375 | return append(data, 0, data.length); | |
376 | } | |
377 | ||
378 | /** | |
379 | * Append part of the <code>char</code> array to this | |
380 | * <code>StringBuilder</code>. This is similar (but more efficient) than | |
381 | * <code>append(new String(data, offset, count))</code>, except in the case | |
382 | * of null. | |
383 | * | |
384 | * @param data the <code>char[]</code> to append | |
385 | * @param offset the start location in <code>str</code> | |
386 | * @param count the number of characters to get from <code>str</code> | |
387 | * @return this <code>StringBuilder</code> | |
388 | * @throws NullPointerException if <code>str</code> is <code>null</code> | |
389 | * @throws IndexOutOfBoundsException if offset or count is out of range | |
390 | * (while unspecified, this is a StringIndexOutOfBoundsException) | |
391 | */ | |
392 | public StringBuilder append(char[] data, int offset, int count) | |
393 | { | |
394 | if (offset < 0 || count < 0 || offset > data.length - count) | |
395 | throw new StringIndexOutOfBoundsException(); | |
396 | ensureCapacity(this.count + count); | |
397 | System.arraycopy(data, offset, value, this.count, count); | |
398 | this.count += count; | |
399 | return this; | |
400 | } | |
401 | ||
402 | /** | |
403 | * Append the <code>String</code> value of the argument to this | |
404 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
405 | * to <code>String</code>. | |
406 | * | |
407 | * @param bool the <code>boolean</code> to convert and append | |
408 | * @return this <code>StringBuilder</code> | |
409 | * @see String#valueOf(boolean) | |
410 | */ | |
411 | public StringBuilder append(boolean bool) | |
412 | { | |
413 | return append(bool ? "true" : "false"); | |
414 | } | |
415 | ||
416 | /** | |
417 | * Append the <code>char</code> to this <code>StringBuilder</code>. | |
418 | * | |
419 | * @param ch the <code>char</code> to append | |
420 | * @return this <code>StringBuilder</code> | |
421 | */ | |
422 | public StringBuilder append(char ch) | |
423 | { | |
424 | ensureCapacity(count + 1); | |
425 | value[count++] = ch; | |
426 | return this; | |
427 | } | |
428 | ||
429 | /** | |
430 | * Append the characters in the <code>CharSequence</code> to this | |
431 | * buffer. | |
432 | * | |
433 | * @param seq the <code>CharSequence</code> providing the characters | |
434 | * @return this <code>StringBuilder</code> | |
435 | */ | |
436 | public StringBuilder append(CharSequence seq) | |
437 | { | |
438 | return append(seq, 0, seq.length()); | |
439 | } | |
440 | ||
441 | /** | |
442 | * Append some characters from the <code>CharSequence</code> to this | |
443 | * buffer. If the argument is null, the four characters "null" are | |
444 | * appended. | |
445 | * | |
446 | * @param seq the <code>CharSequence</code> providing the characters | |
447 | * @param start the starting index | |
448 | * @param end one past the final index | |
449 | * @return this <code>StringBuilder</code> | |
450 | */ | |
451 | public StringBuilder append(CharSequence seq, int start, | |
452 | int end) | |
453 | { | |
454 | if (seq == null) | |
455 | return append("null"); | |
456 | if (end - start > 0) | |
457 | { | |
458 | ensureCapacity(count + end - start); | |
459 | for (; start < end; ++start) | |
460 | value[count++] = seq.charAt(start); | |
461 | } | |
462 | return this; | |
463 | } | |
464 | ||
a79cb46c TT |
465 | /** |
466 | * Append the code point to this <code>StringBuilder</code>. | |
467 | * This is like #append(char), but will append two characters | |
468 | * if a supplementary code point is given. | |
469 | * | |
470 | * @param code the code point to append | |
471 | * @return this <code>StringBuilder</code> | |
472 | * @see Character#toChars(int, char[], int) | |
473 | * @since 1.5 | |
474 | */ | |
475 | public synchronized StringBuilder appendCodePoint(int code) | |
476 | { | |
477 | int len = Character.charCount(code); | |
478 | ensureCapacity(count + len); | |
479 | Character.toChars(code, value, count); | |
480 | count += len; | |
481 | return this; | |
482 | } | |
483 | ||
0cb757cc TT |
484 | /** |
485 | * Append the <code>String</code> value of the argument to this | |
486 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
487 | * to <code>String</code>. | |
488 | * | |
489 | * @param inum the <code>int</code> to convert and append | |
490 | * @return this <code>StringBuilder</code> | |
491 | * @see String#valueOf(int) | |
492 | */ | |
493 | // FIXME: this is native in libgcj in StringBuffer. | |
494 | public StringBuilder append(int inum) | |
495 | { | |
496 | return append(String.valueOf(inum)); | |
497 | } | |
498 | ||
499 | /** | |
500 | * Append the <code>String</code> value of the argument to this | |
501 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
502 | * to <code>String</code>. | |
503 | * | |
504 | * @param lnum the <code>long</code> to convert and append | |
505 | * @return this <code>StringBuilder</code> | |
506 | * @see String#valueOf(long) | |
507 | */ | |
508 | public StringBuilder append(long lnum) | |
509 | { | |
510 | return append(Long.toString(lnum, 10)); | |
511 | } | |
512 | ||
513 | /** | |
514 | * Append the <code>String</code> value of the argument to this | |
515 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
516 | * to <code>String</code>. | |
517 | * | |
518 | * @param fnum the <code>float</code> to convert and append | |
519 | * @return this <code>StringBuilder</code> | |
520 | * @see String#valueOf(float) | |
521 | */ | |
522 | public StringBuilder append(float fnum) | |
523 | { | |
524 | return append(Float.toString(fnum)); | |
525 | } | |
526 | ||
527 | /** | |
528 | * Append the <code>String</code> value of the argument to this | |
529 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
530 | * to <code>String</code>. | |
531 | * | |
532 | * @param dnum the <code>double</code> to convert and append | |
533 | * @return this <code>StringBuilder</code> | |
534 | * @see String#valueOf(double) | |
535 | */ | |
536 | public StringBuilder append(double dnum) | |
537 | { | |
538 | return append(Double.toString(dnum)); | |
539 | } | |
540 | ||
541 | /** | |
542 | * Delete characters from this <code>StringBuilder</code>. | |
543 | * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is | |
544 | * harmless for end to be larger than length(). | |
545 | * | |
546 | * @param start the first character to delete | |
547 | * @param end the index after the last character to delete | |
548 | * @return this <code>StringBuilder</code> | |
549 | * @throws StringIndexOutOfBoundsException if start or end are out of bounds | |
550 | */ | |
551 | public StringBuilder delete(int start, int end) | |
552 | { | |
553 | if (start < 0 || start > count || start > end) | |
554 | throw new StringIndexOutOfBoundsException(start); | |
555 | if (end > count) | |
556 | end = count; | |
557 | // This will unshare if required. | |
558 | ensureCapacity(count); | |
559 | if (count - end != 0) | |
560 | System.arraycopy(value, end, value, start, count - end); | |
561 | count -= end - start; | |
562 | return this; | |
563 | } | |
564 | ||
565 | /** | |
566 | * Delete a character from this <code>StringBuilder</code>. | |
567 | * | |
568 | * @param index the index of the character to delete | |
569 | * @return this <code>StringBuilder</code> | |
570 | * @throws StringIndexOutOfBoundsException if index is out of bounds | |
571 | */ | |
572 | public StringBuilder deleteCharAt(int index) | |
573 | { | |
574 | return delete(index, index + 1); | |
575 | } | |
576 | ||
577 | /** | |
578 | * Replace characters between index <code>start</code> (inclusive) and | |
579 | * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> | |
580 | * is larger than the size of this StringBuilder, all characters after | |
581 | * <code>start</code> are replaced. | |
582 | * | |
583 | * @param start the beginning index of characters to delete (inclusive) | |
584 | * @param end the ending index of characters to delete (exclusive) | |
585 | * @param str the new <code>String</code> to insert | |
586 | * @return this <code>StringBuilder</code> | |
587 | * @throws StringIndexOutOfBoundsException if start or end are out of bounds | |
588 | * @throws NullPointerException if str is null | |
589 | */ | |
590 | public StringBuilder replace(int start, int end, String str) | |
591 | { | |
592 | if (start < 0 || start > count || start > end) | |
593 | throw new StringIndexOutOfBoundsException(start); | |
594 | ||
595 | int len = str.count; | |
596 | // Calculate the difference in 'count' after the replace. | |
597 | int delta = len - (end > count ? count : end) + start; | |
598 | ensureCapacity(count + delta); | |
599 | ||
600 | if (delta != 0 && end < count) | |
601 | System.arraycopy(value, end, value, end + delta, count - end); | |
602 | ||
603 | str.getChars(0, len, value, start); | |
604 | count += delta; | |
605 | return this; | |
606 | } | |
607 | ||
608 | /** | |
609 | * Creates a substring of this StringBuilder, starting at a specified index | |
610 | * and ending at the end of this StringBuilder. | |
611 | * | |
612 | * @param beginIndex index to start substring (base 0) | |
613 | * @return new String which is a substring of this StringBuilder | |
614 | * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds | |
615 | * @see #substring(int, int) | |
616 | */ | |
617 | public String substring(int beginIndex) | |
618 | { | |
619 | return substring(beginIndex, count); | |
620 | } | |
621 | ||
622 | /** | |
623 | * Creates a substring of this StringBuilder, starting at a specified index | |
624 | * and ending at one character before a specified index. This is implemented | |
625 | * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy | |
626 | * the CharSequence interface. | |
627 | * | |
628 | * @param beginIndex index to start at (inclusive, base 0) | |
629 | * @param endIndex index to end at (exclusive) | |
630 | * @return new String which is a substring of this StringBuilder | |
631 | * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of | |
632 | * bounds | |
633 | * @see #substring(int, int) | |
634 | */ | |
635 | public CharSequence subSequence(int beginIndex, int endIndex) | |
636 | { | |
637 | return substring(beginIndex, endIndex); | |
638 | } | |
639 | ||
640 | /** | |
641 | * Creates a substring of this StringBuilder, starting at a specified index | |
642 | * and ending at one character before a specified index. | |
643 | * | |
644 | * @param beginIndex index to start at (inclusive, base 0) | |
645 | * @param endIndex index to end at (exclusive) | |
646 | * @return new String which is a substring of this StringBuilder | |
647 | * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out | |
648 | * of bounds | |
649 | */ | |
650 | public String substring(int beginIndex, int endIndex) | |
651 | { | |
652 | int len = endIndex - beginIndex; | |
653 | if (beginIndex < 0 || endIndex > count || endIndex < beginIndex) | |
654 | throw new StringIndexOutOfBoundsException(); | |
655 | if (len == 0) | |
656 | return ""; | |
657 | return new String(value, beginIndex, len); | |
658 | } | |
659 | ||
660 | /** | |
661 | * Insert a subarray of the <code>char[]</code> argument into this | |
662 | * <code>StringBuilder</code>. | |
663 | * | |
664 | * @param offset the place to insert in this buffer | |
665 | * @param str the <code>char[]</code> to insert | |
666 | * @param str_offset the index in <code>str</code> to start inserting from | |
667 | * @param len the number of characters to insert | |
668 | * @return this <code>StringBuilder</code> | |
669 | * @throws NullPointerException if <code>str</code> is <code>null</code> | |
670 | * @throws StringIndexOutOfBoundsException if any index is out of bounds | |
671 | */ | |
672 | public StringBuilder insert(int offset, | |
673 | char[] str, int str_offset, int len) | |
674 | { | |
675 | if (offset < 0 || offset > count || len < 0 | |
676 | || str_offset < 0 || str_offset > str.length - len) | |
677 | throw new StringIndexOutOfBoundsException(); | |
678 | ensureCapacity(count + len); | |
679 | System.arraycopy(value, offset, value, offset + len, count - offset); | |
680 | System.arraycopy(str, str_offset, value, offset, len); | |
681 | count += len; | |
682 | return this; | |
683 | } | |
684 | ||
685 | /** | |
686 | * Insert the <code>String</code> value of the argument into this | |
687 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
688 | * to <code>String</code>. | |
689 | * | |
690 | * @param offset the place to insert in this buffer | |
691 | * @param obj the <code>Object</code> to convert and insert | |
692 | * @return this <code>StringBuilder</code> | |
693 | * @exception StringIndexOutOfBoundsException if offset is out of bounds | |
694 | * @see String#valueOf(Object) | |
695 | */ | |
696 | public StringBuilder insert(int offset, Object obj) | |
697 | { | |
698 | return insert(offset, obj == null ? "null" : obj.toString()); | |
699 | } | |
700 | ||
701 | /** | |
702 | * Insert the <code>String</code> argument into this | |
703 | * <code>StringBuilder</code>. If str is null, the String "null" is used | |
704 | * instead. | |
705 | * | |
706 | * @param offset the place to insert in this buffer | |
707 | * @param str the <code>String</code> to insert | |
708 | * @return this <code>StringBuilder</code> | |
709 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
710 | */ | |
711 | public StringBuilder insert(int offset, String str) | |
712 | { | |
713 | if (offset < 0 || offset > count) | |
714 | throw new StringIndexOutOfBoundsException(offset); | |
715 | if (str == null) | |
716 | str = "null"; | |
717 | int len = str.count; | |
718 | ensureCapacity(count + len); | |
719 | System.arraycopy(value, offset, value, offset + len, count - offset); | |
720 | str.getChars(0, len, value, offset); | |
721 | count += len; | |
722 | return this; | |
723 | } | |
724 | ||
a79cb46c TT |
725 | /** |
726 | * Insert the <code>CharSequence</code> argument into this | |
727 | * <code>StringBuilder</code>. If the sequence is null, the String | |
728 | * "null" is used instead. | |
729 | * | |
730 | * @param offset the place to insert in this buffer | |
731 | * @param sequence the <code>CharSequence</code> to insert | |
732 | * @return this <code>StringBuilder</code> | |
733 | * @throws IndexOutOfBoundsException if offset is out of bounds | |
734 | */ | |
735 | public synchronized StringBuilder insert(int offset, CharSequence sequence) | |
736 | { | |
737 | if (sequence == null) | |
738 | sequence = "null"; | |
739 | return insert(offset, sequence, 0, sequence.length()); | |
740 | } | |
741 | ||
742 | /** | |
743 | * Insert a subsequence of the <code>CharSequence</code> argument into this | |
744 | * <code>StringBuilder</code>. If the sequence is null, the String | |
745 | * "null" is used instead. | |
746 | * | |
747 | * @param offset the place to insert in this buffer | |
748 | * @param sequence the <code>CharSequence</code> to insert | |
749 | * @param start the starting index of the subsequence | |
750 | * @param end one past the ending index of the subsequence | |
751 | * @return this <code>StringBuilder</code> | |
752 | * @throws IndexOutOfBoundsException if offset, start, | |
753 | * or end are out of bounds | |
754 | */ | |
755 | public synchronized StringBuilder insert(int offset, CharSequence sequence, | |
756 | int start, int end) | |
757 | { | |
758 | if (sequence == null) | |
759 | sequence = "null"; | |
760 | if (start < 0 || end < 0 || start > end || end > sequence.length()) | |
761 | throw new IndexOutOfBoundsException(); | |
762 | int len = end - start; | |
763 | ensureCapacity(count + len); | |
764 | System.arraycopy(value, offset, value, offset + len, count - offset); | |
765 | for (int i = start; i < end; ++i) | |
766 | value[offset++] = sequence.charAt(i); | |
767 | count += len; | |
768 | return this; | |
769 | } | |
770 | ||
0cb757cc TT |
771 | /** |
772 | * Insert the <code>char[]</code> argument into this | |
773 | * <code>StringBuilder</code>. | |
774 | * | |
775 | * @param offset the place to insert in this buffer | |
776 | * @param data the <code>char[]</code> to insert | |
777 | * @return this <code>StringBuilder</code> | |
778 | * @throws NullPointerException if <code>data</code> is <code>null</code> | |
779 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
780 | * @see #insert(int, char[], int, int) | |
781 | */ | |
782 | public StringBuilder insert(int offset, char[] data) | |
783 | { | |
784 | return insert(offset, data, 0, data.length); | |
785 | } | |
786 | ||
787 | /** | |
788 | * Insert the <code>String</code> value of the argument into this | |
789 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
790 | * to <code>String</code>. | |
791 | * | |
792 | * @param offset the place to insert in this buffer | |
793 | * @param bool the <code>boolean</code> to convert and insert | |
794 | * @return this <code>StringBuilder</code> | |
795 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
796 | * @see String#valueOf(boolean) | |
797 | */ | |
798 | public StringBuilder insert(int offset, boolean bool) | |
799 | { | |
800 | return insert(offset, bool ? "true" : "false"); | |
801 | } | |
802 | ||
803 | /** | |
804 | * Insert the <code>char</code> argument into this <code>StringBuilder</code>. | |
805 | * | |
806 | * @param offset the place to insert in this buffer | |
807 | * @param ch the <code>char</code> to insert | |
808 | * @return this <code>StringBuilder</code> | |
809 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
810 | */ | |
811 | public StringBuilder insert(int offset, char ch) | |
812 | { | |
813 | if (offset < 0 || offset > count) | |
814 | throw new StringIndexOutOfBoundsException(offset); | |
815 | ensureCapacity(count + 1); | |
816 | System.arraycopy(value, offset, value, offset + 1, count - offset); | |
817 | value[offset] = ch; | |
818 | count++; | |
819 | return this; | |
820 | } | |
821 | ||
822 | /** | |
823 | * Insert the <code>String</code> value of the argument into this | |
824 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
825 | * to <code>String</code>. | |
826 | * | |
827 | * @param offset the place to insert in this buffer | |
828 | * @param inum the <code>int</code> to convert and insert | |
829 | * @return this <code>StringBuilder</code> | |
830 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
831 | * @see String#valueOf(int) | |
832 | */ | |
833 | public StringBuilder insert(int offset, int inum) | |
834 | { | |
835 | return insert(offset, String.valueOf(inum)); | |
836 | } | |
837 | ||
838 | /** | |
839 | * Insert the <code>String</code> value of the argument into this | |
840 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
841 | * to <code>String</code>. | |
842 | * | |
843 | * @param offset the place to insert in this buffer | |
844 | * @param lnum the <code>long</code> to convert and insert | |
845 | * @return this <code>StringBuilder</code> | |
846 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
847 | * @see String#valueOf(long) | |
848 | */ | |
849 | public StringBuilder insert(int offset, long lnum) | |
850 | { | |
851 | return insert(offset, Long.toString(lnum, 10)); | |
852 | } | |
853 | ||
854 | /** | |
855 | * Insert the <code>String</code> value of the argument into this | |
856 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
857 | * to <code>String</code>. | |
858 | * | |
859 | * @param offset the place to insert in this buffer | |
860 | * @param fnum the <code>float</code> to convert and insert | |
861 | * @return this <code>StringBuilder</code> | |
862 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
863 | * @see String#valueOf(float) | |
864 | */ | |
865 | public StringBuilder insert(int offset, float fnum) | |
866 | { | |
867 | return insert(offset, Float.toString(fnum)); | |
868 | } | |
869 | ||
870 | /** | |
871 | * Insert the <code>String</code> value of the argument into this | |
872 | * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert | |
873 | * to <code>String</code>. | |
874 | * | |
875 | * @param offset the place to insert in this buffer | |
876 | * @param dnum the <code>double</code> to convert and insert | |
877 | * @return this <code>StringBuilder</code> | |
878 | * @throws StringIndexOutOfBoundsException if offset is out of bounds | |
879 | * @see String#valueOf(double) | |
880 | */ | |
881 | public StringBuilder insert(int offset, double dnum) | |
882 | { | |
883 | return insert(offset, Double.toString(dnum)); | |
884 | } | |
885 | ||
886 | /** | |
887 | * Finds the first instance of a substring in this StringBuilder. | |
888 | * | |
889 | * @param str String to find | |
890 | * @return location (base 0) of the String, or -1 if not found | |
891 | * @throws NullPointerException if str is null | |
892 | * @see #indexOf(String, int) | |
893 | */ | |
894 | public int indexOf(String str) | |
895 | { | |
896 | return indexOf(str, 0); | |
897 | } | |
898 | ||
899 | /** | |
900 | * Finds the first instance of a String in this StringBuilder, starting at | |
901 | * a given index. If starting index is less than 0, the search starts at | |
902 | * the beginning of this String. If the starting index is greater than the | |
903 | * length of this String, or the substring is not found, -1 is returned. | |
904 | * | |
905 | * @param str String to find | |
906 | * @param fromIndex index to start the search | |
907 | * @return location (base 0) of the String, or -1 if not found | |
908 | * @throws NullPointerException if str is null | |
909 | */ | |
910 | public int indexOf(String str, int fromIndex) | |
911 | { | |
912 | if (fromIndex < 0) | |
913 | fromIndex = 0; | |
914 | int limit = count - str.count; | |
915 | for ( ; fromIndex <= limit; fromIndex++) | |
916 | if (regionMatches(fromIndex, str)) | |
917 | return fromIndex; | |
918 | return -1; | |
919 | } | |
920 | ||
921 | /** | |
922 | * Finds the last instance of a substring in this StringBuilder. | |
923 | * | |
924 | * @param str String to find | |
925 | * @return location (base 0) of the String, or -1 if not found | |
926 | * @throws NullPointerException if str is null | |
927 | * @see #lastIndexOf(String, int) | |
928 | */ | |
929 | public int lastIndexOf(String str) | |
930 | { | |
931 | return lastIndexOf(str, count - str.count); | |
932 | } | |
933 | ||
934 | /** | |
935 | * Finds the last instance of a String in this StringBuilder, starting at a | |
936 | * given index. If starting index is greater than the maximum valid index, | |
937 | * then the search begins at the end of this String. If the starting index | |
938 | * is less than zero, or the substring is not found, -1 is returned. | |
939 | * | |
940 | * @param str String to find | |
941 | * @param fromIndex index to start the search | |
942 | * @return location (base 0) of the String, or -1 if not found | |
943 | * @throws NullPointerException if str is null | |
944 | */ | |
945 | public int lastIndexOf(String str, int fromIndex) | |
946 | { | |
947 | fromIndex = Math.min(fromIndex, count - str.count); | |
948 | for ( ; fromIndex >= 0; fromIndex--) | |
949 | if (regionMatches(fromIndex, str)) | |
950 | return fromIndex; | |
951 | return -1; | |
952 | } | |
953 | ||
954 | /** | |
955 | * Reverse the characters in this StringBuilder. The same sequence of | |
956 | * characters exists, but in the reverse index ordering. | |
957 | * | |
958 | * @return this <code>StringBuilder</code> | |
959 | */ | |
960 | public StringBuilder reverse() | |
961 | { | |
962 | // Call ensureCapacity to enforce copy-on-write. | |
963 | ensureCapacity(count); | |
964 | for (int i = count >> 1, j = count - i; --i >= 0; ++j) | |
965 | { | |
966 | char c = value[i]; | |
967 | value[i] = value[j]; | |
968 | value[j] = c; | |
969 | } | |
970 | return this; | |
971 | } | |
972 | ||
973 | /** | |
974 | * Convert this <code>StringBuilder</code> to a <code>String</code>. The | |
975 | * String is composed of the characters currently in this StringBuilder. Note | |
976 | * that the result is a copy, and that future modifications to this buffer | |
977 | * do not affect the String. | |
978 | * | |
979 | * @return the characters in this StringBuilder | |
980 | */ | |
981 | public String toString() | |
982 | { | |
983 | return new String(this); | |
984 | } | |
985 | ||
986 | /** | |
987 | * Predicate which determines if a substring of this matches another String | |
988 | * starting at a specified offset for each String and continuing for a | |
989 | * specified length. This is more efficient than creating a String to call | |
990 | * indexOf on. | |
991 | * | |
992 | * @param toffset index to start comparison at for this String | |
993 | * @param other non-null String to compare to region of this | |
994 | * @return true if regions match, false otherwise | |
995 | * @see #indexOf(String, int) | |
996 | * @see #lastIndexOf(String, int) | |
997 | * @see String#regionMatches(boolean, int, String, int, int) | |
998 | */ | |
999 | // GCJ LOCAL: Native to access String internals properly. | |
1000 | private native boolean regionMatches(int toffset, String other); | |
666ff4f6 MW |
1001 | |
1002 | /** | |
1003 | * Get the code point at the specified index. This is like #charAt(int), | |
1004 | * but if the character is the start of a surrogate pair, and the | |
1005 | * following character completes the pair, then the corresponding | |
1006 | * supplementary code point is returned. | |
1007 | * @param index the index of the codepoint to get, starting at 0 | |
1008 | * @return the codepoint at the specified index | |
1009 | * @throws IndexOutOfBoundsException if index is negative or >= length() | |
1010 | * @since 1.5 | |
1011 | */ | |
1012 | public int codePointAt(int index) | |
1013 | { | |
1014 | return Character.codePointAt(value, index, count); | |
1015 | } | |
1016 | ||
1017 | /** | |
1018 | * Get the code point before the specified index. This is like | |
1019 | * #codePointAt(int), but checks the characters at <code>index-1</code> and | |
1020 | * <code>index-2</code> to see if they form a supplementary code point. | |
1021 | * @param index the index just past the codepoint to get, starting at 0 | |
1022 | * @return the codepoint at the specified index | |
1023 | * @throws IndexOutOfBoundsException if index is negative or >= length() | |
1024 | * @since 1.5 | |
1025 | */ | |
1026 | public int codePointBefore(int index) | |
1027 | { | |
1028 | // Character.codePointBefore() doesn't perform this check. We | |
1029 | // could use the CharSequence overload, but this is just as easy. | |
1030 | if (index >= count) | |
1031 | throw new IndexOutOfBoundsException(); | |
1032 | return Character.codePointBefore(value, index, 1); | |
1033 | } | |
1034 | ||
1035 | /** | |
1036 | * Returns the number of Unicode code points in the specified sub sequence. | |
1037 | * Surrogate pairs count as one code point. | |
1038 | * @param beginIndex the start of the subarray | |
1039 | * @param endIndex the index after the last char in the subarray | |
1040 | * @return the number of code points | |
1041 | * @throws IndexOutOfBoundsException if beginIndex is less than zero or | |
1042 | * greater than endIndex or if endIndex is greater than the length of this | |
1043 | * StringBuilder | |
1044 | */ | |
1045 | public int codePointCount(int beginIndex,int endIndex) | |
1046 | { | |
1047 | if (beginIndex < 0 || beginIndex > endIndex || endIndex > count) | |
1048 | throw new IndexOutOfBoundsException("invalid indices: " + beginIndex | |
1049 | + ", " + endIndex); | |
1050 | return Character.codePointCount(value, beginIndex, endIndex - beginIndex); | |
1051 | } | |
1052 | ||
1053 | public void trimToSize() | |
1054 | { | |
1055 | if (count < value.length) | |
1056 | { | |
1057 | char[] newValue = new char[count]; | |
1058 | System.arraycopy(value, 0, newValue, 0, count); | |
1059 | value = newValue; | |
1060 | } | |
1061 | } | |
0cb757cc | 1062 | } |