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