blob: 4ba130b498913e7bbb2df578c6da6d6c850ea6d9 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.lang;
27
28import sun.misc.FloatingDecimal;
29import java.util.Arrays;
30
31/**
32 * A mutable sequence of characters.
33 * <p>
34 * Implements a modifiable string. At any point in time it contains some
35 * particular sequence of characters, but the length and content of the
36 * sequence can be changed through certain method calls.
37 *
38 * @author Michael McCloskey
39 * @since 1.5
40 */
41abstract class AbstractStringBuilder implements Appendable, CharSequence {
42 /**
43 * The value is used for character storage.
44 */
45 char value[];
46
47 /**
48 * The count is the number of characters used.
49 */
50 int count;
51
52 /**
53 * This no-arg constructor is necessary for serialization of subclasses.
54 */
55 AbstractStringBuilder() {
56 }
57
58 /**
59 * Creates an AbstractStringBuilder of the specified capacity.
60 */
61 AbstractStringBuilder(int capacity) {
62 value = new char[capacity];
63 }
64
65 /**
66 * Returns the length (character count).
67 *
68 * @return the length of the sequence of characters currently
69 * represented by this object
70 */
71 public int length() {
72 return count;
73 }
74
75 /**
76 * Returns the current capacity. The capacity is the amount of storage
77 * available for newly inserted characters, beyond which an allocation
78 * will occur.
79 *
80 * @return the current capacity
81 */
82 public int capacity() {
83 return value.length;
84 }
85
86 /**
87 * Ensures that the capacity is at least equal to the specified minimum.
88 * If the current capacity is less than the argument, then a new internal
89 * array is allocated with greater capacity. The new capacity is the
90 * larger of:
91 * <ul>
92 * <li>The <code>minimumCapacity</code> argument.
93 * <li>Twice the old capacity, plus <code>2</code>.
94 * </ul>
95 * If the <code>minimumCapacity</code> argument is nonpositive, this
96 * method takes no action and simply returns.
97 *
98 * @param minimumCapacity the minimum desired capacity.
99 */
100 public void ensureCapacity(int minimumCapacity) {
101 if (minimumCapacity > value.length) {
102 expandCapacity(minimumCapacity);
103 }
104 }
105
106 /**
107 * This implements the expansion semantics of ensureCapacity with no
108 * size check or synchronization.
109 */
110 void expandCapacity(int minimumCapacity) {
111 int newCapacity = (value.length + 1) * 2;
112 if (newCapacity < 0) {
113 newCapacity = Integer.MAX_VALUE;
114 } else if (minimumCapacity > newCapacity) {
115 newCapacity = minimumCapacity;
116 }
117 value = Arrays.copyOf(value, newCapacity);
118 }
119
120 /**
121 * Attempts to reduce storage used for the character sequence.
122 * If the buffer is larger than necessary to hold its current sequence of
123 * characters, then it may be resized to become more space efficient.
124 * Calling this method may, but is not required to, affect the value
125 * returned by a subsequent call to the {@link #capacity()} method.
126 */
127 public void trimToSize() {
128 if (count < value.length) {
129 value = Arrays.copyOf(value, count);
130 }
131 }
132
133 /**
134 * Sets the length of the character sequence.
135 * The sequence is changed to a new character sequence
136 * whose length is specified by the argument. For every nonnegative
137 * index <i>k</i> less than <code>newLength</code>, the character at
138 * index <i>k</i> in the new character sequence is the same as the
139 * character at index <i>k</i> in the old sequence if <i>k</i> is less
140 * than the length of the old character sequence; otherwise, it is the
141 * null character <code>'&#92;u0000'</code>.
142 *
143 * In other words, if the <code>newLength</code> argument is less than
144 * the current length, the length is changed to the specified length.
145 * <p>
146 * If the <code>newLength</code> argument is greater than or equal
147 * to the current length, sufficient null characters
148 * (<code>'&#92;u0000'</code>) are appended so that
149 * length becomes the <code>newLength</code> argument.
150 * <p>
151 * The <code>newLength</code> argument must be greater than or equal
152 * to <code>0</code>.
153 *
154 * @param newLength the new length
155 * @throws IndexOutOfBoundsException if the
156 * <code>newLength</code> argument is negative.
157 */
158 public void setLength(int newLength) {
159 if (newLength < 0)
160 throw new StringIndexOutOfBoundsException(newLength);
161 if (newLength > value.length)
162 expandCapacity(newLength);
163
164 if (count < newLength) {
165 for (; count < newLength; count++)
166 value[count] = '\0';
167 } else {
168 count = newLength;
169 }
170 }
171
172 /**
173 * Returns the <code>char</code> value in this sequence at the specified index.
174 * The first <code>char</code> value is at index <code>0</code>, the next at index
175 * <code>1</code>, and so on, as in array indexing.
176 * <p>
177 * The index argument must be greater than or equal to
178 * <code>0</code>, and less than the length of this sequence.
179 *
180 * <p>If the <code>char</code> value specified by the index is a
181 * <a href="Character.html#unicode">surrogate</a>, the surrogate
182 * value is returned.
183 *
184 * @param index the index of the desired <code>char</code> value.
185 * @return the <code>char</code> value at the specified index.
186 * @throws IndexOutOfBoundsException if <code>index</code> is
187 * negative or greater than or equal to <code>length()</code>.
188 */
189 public char charAt(int index) {
190 if ((index < 0) || (index >= count))
191 throw new StringIndexOutOfBoundsException(index);
192 return value[index];
193 }
194
195 /**
196 * Returns the character (Unicode code point) at the specified
197 * index. The index refers to <code>char</code> values
198 * (Unicode code units) and ranges from <code>0</code> to
199 * {@link #length()}<code> - 1</code>.
200 *
201 * <p> If the <code>char</code> value specified at the given index
202 * is in the high-surrogate range, the following index is less
203 * than the length of this sequence, and the
204 * <code>char</code> value at the following index is in the
205 * low-surrogate range, then the supplementary code point
206 * corresponding to this surrogate pair is returned. Otherwise,
207 * the <code>char</code> value at the given index is returned.
208 *
209 * @param index the index to the <code>char</code> values
210 * @return the code point value of the character at the
211 * <code>index</code>
212 * @exception IndexOutOfBoundsException if the <code>index</code>
213 * argument is negative or not less than the length of this
214 * sequence.
215 */
216 public int codePointAt(int index) {
217 if ((index < 0) || (index >= count)) {
218 throw new StringIndexOutOfBoundsException(index);
219 }
220 return Character.codePointAt(value, index);
221 }
222
223 /**
224 * Returns the character (Unicode code point) before the specified
225 * index. The index refers to <code>char</code> values
226 * (Unicode code units) and ranges from <code>1</code> to {@link
227 * #length()}.
228 *
229 * <p> If the <code>char</code> value at <code>(index - 1)</code>
230 * is in the low-surrogate range, <code>(index - 2)</code> is not
231 * negative, and the <code>char</code> value at <code>(index -
232 * 2)</code> is in the high-surrogate range, then the
233 * supplementary code point value of the surrogate pair is
234 * returned. If the <code>char</code> value at <code>index -
235 * 1</code> is an unpaired low-surrogate or a high-surrogate, the
236 * surrogate value is returned.
237 *
238 * @param index the index following the code point that should be returned
239 * @return the Unicode code point value before the given index.
240 * @exception IndexOutOfBoundsException if the <code>index</code>
241 * argument is less than 1 or greater than the length
242 * of this sequence.
243 */
244 public int codePointBefore(int index) {
245 int i = index - 1;
246 if ((i < 0) || (i >= count)) {
247 throw new StringIndexOutOfBoundsException(index);
248 }
249 return Character.codePointBefore(value, index);
250 }
251
252 /**
253 * Returns the number of Unicode code points in the specified text
254 * range of this sequence. The text range begins at the specified
255 * <code>beginIndex</code> and extends to the <code>char</code> at
256 * index <code>endIndex - 1</code>. Thus the length (in
257 * <code>char</code>s) of the text range is
258 * <code>endIndex-beginIndex</code>. Unpaired surrogates within
259 * this sequence count as one code point each.
260 *
261 * @param beginIndex the index to the first <code>char</code> of
262 * the text range.
263 * @param endIndex the index after the last <code>char</code> of
264 * the text range.
265 * @return the number of Unicode code points in the specified text
266 * range
267 * @exception IndexOutOfBoundsException if the
268 * <code>beginIndex</code> is negative, or <code>endIndex</code>
269 * is larger than the length of this sequence, or
270 * <code>beginIndex</code> is larger than <code>endIndex</code>.
271 */
272 public int codePointCount(int beginIndex, int endIndex) {
273 if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
274 throw new IndexOutOfBoundsException();
275 }
276 return Character.codePointCountImpl(value, beginIndex, endIndex-beginIndex);
277 }
278
279 /**
280 * Returns the index within this sequence that is offset from the
281 * given <code>index</code> by <code>codePointOffset</code> code
282 * points. Unpaired surrogates within the text range given by
283 * <code>index</code> and <code>codePointOffset</code> count as
284 * one code point each.
285 *
286 * @param index the index to be offset
287 * @param codePointOffset the offset in code points
288 * @return the index within this sequence
289 * @exception IndexOutOfBoundsException if <code>index</code>
290 * is negative or larger then the length of this sequence,
291 * or if <code>codePointOffset</code> is positive and the subsequence
292 * starting with <code>index</code> has fewer than
293 * <code>codePointOffset</code> code points,
294 * or if <code>codePointOffset</code> is negative and the subsequence
295 * before <code>index</code> has fewer than the absolute value of
296 * <code>codePointOffset</code> code points.
297 */
298 public int offsetByCodePoints(int index, int codePointOffset) {
299 if (index < 0 || index > count) {
300 throw new IndexOutOfBoundsException();
301 }
302 return Character.offsetByCodePointsImpl(value, 0, count,
303 index, codePointOffset);
304 }
305
306 /**
307 * Characters are copied from this sequence into the
308 * destination character array <code>dst</code>. The first character to
309 * be copied is at index <code>srcBegin</code>; the last character to
310 * be copied is at index <code>srcEnd-1</code>. The total number of
311 * characters to be copied is <code>srcEnd-srcBegin</code>. The
312 * characters are copied into the subarray of <code>dst</code> starting
313 * at index <code>dstBegin</code> and ending at index:
314 * <p><blockquote><pre>
315 * dstbegin + (srcEnd-srcBegin) - 1
316 * </pre></blockquote>
317 *
318 * @param srcBegin start copying at this offset.
319 * @param srcEnd stop copying at this offset.
320 * @param dst the array to copy the data into.
321 * @param dstBegin offset into <code>dst</code>.
322 * @throws NullPointerException if <code>dst</code> is
323 * <code>null</code>.
324 * @throws IndexOutOfBoundsException if any of the following is true:
325 * <ul>
326 * <li><code>srcBegin</code> is negative
327 * <li><code>dstBegin</code> is negative
328 * <li>the <code>srcBegin</code> argument is greater than
329 * the <code>srcEnd</code> argument.
330 * <li><code>srcEnd</code> is greater than
331 * <code>this.length()</code>.
332 * <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
333 * <code>dst.length</code>
334 * </ul>
335 */
336 public void getChars(int srcBegin, int srcEnd, char dst[],
337 int dstBegin)
338 {
339 if (srcBegin < 0)
340 throw new StringIndexOutOfBoundsException(srcBegin);
341 if ((srcEnd < 0) || (srcEnd > count))
342 throw new StringIndexOutOfBoundsException(srcEnd);
343 if (srcBegin > srcEnd)
344 throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
345 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
346 }
347
348 /**
349 * The character at the specified index is set to <code>ch</code>. This
350 * sequence is altered to represent a new character sequence that is
351 * identical to the old character sequence, except that it contains the
352 * character <code>ch</code> at position <code>index</code>.
353 * <p>
354 * The index argument must be greater than or equal to
355 * <code>0</code>, and less than the length of this sequence.
356 *
357 * @param index the index of the character to modify.
358 * @param ch the new character.
359 * @throws IndexOutOfBoundsException if <code>index</code> is
360 * negative or greater than or equal to <code>length()</code>.
361 */
362 public void setCharAt(int index, char ch) {
363 if ((index < 0) || (index >= count))
364 throw new StringIndexOutOfBoundsException(index);
365 value[index] = ch;
366 }
367
368 /**
369 * Appends the string representation of the <code>Object</code>
370 * argument.
371 * <p>
372 * The argument is converted to a string as if by the method
373 * <code>String.valueOf</code>, and the characters of that
374 * string are then appended to this sequence.
375 *
376 * @param obj an <code>Object</code>.
377 * @return a reference to this object.
378 */
379 public AbstractStringBuilder append(Object obj) {
380 return append(String.valueOf(obj));
381 }
382
383 /**
384 * Appends the specified string to this character sequence.
385 * <p>
386 * The characters of the <code>String</code> argument are appended, in
387 * order, increasing the length of this sequence by the length of the
388 * argument. If <code>str</code> is <code>null</code>, then the four
389 * characters <code>"null"</code> are appended.
390 * <p>
391 * Let <i>n</i> be the length of this character sequence just prior to
392 * execution of the <code>append</code> method. Then the character at
393 * index <i>k</i> in the new character sequence is equal to the character
394 * at index <i>k</i> in the old character sequence, if <i>k</i> is less
395 * than <i>n</i>; otherwise, it is equal to the character at index
396 * <i>k-n</i> in the argument <code>str</code>.
397 *
398 * @param str a string.
399 * @return a reference to this object.
400 */
401 public AbstractStringBuilder append(String str) {
402 if (str == null) str = "null";
403 int len = str.length();
404 if (len == 0) return this;
405 int newCount = count + len;
406 if (newCount > value.length)
407 expandCapacity(newCount);
408 str.getChars(0, len, value, count);
409 count = newCount;
410 return this;
411 }
412
413 // Documentation in subclasses because of synchro difference
414 public AbstractStringBuilder append(StringBuffer sb) {
415 if (sb == null)
416 return append("null");
417 int len = sb.length();
418 int newCount = count + len;
419 if (newCount > value.length)
420 expandCapacity(newCount);
421 sb.getChars(0, len, value, count);
422 count = newCount;
423 return this;
424 }
425
426 // Documentation in subclasses because of synchro difference
427 public AbstractStringBuilder append(CharSequence s) {
428 if (s == null)
429 s = "null";
430 if (s instanceof String)
431 return this.append((String)s);
432 if (s instanceof StringBuffer)
433 return this.append((StringBuffer)s);
434 return this.append(s, 0, s.length());
435 }
436
437 /**
438 * Appends a subsequence of the specified <code>CharSequence</code> to this
439 * sequence.
440 * <p>
441 * Characters of the argument <code>s</code>, starting at
442 * index <code>start</code>, are appended, in order, to the contents of
443 * this sequence up to the (exclusive) index <code>end</code>. The length
444 * of this sequence is increased by the value of <code>end - start</code>.
445 * <p>
446 * Let <i>n</i> be the length of this character sequence just prior to
447 * execution of the <code>append</code> method. Then the character at
448 * index <i>k</i> in this character sequence becomes equal to the
449 * character at index <i>k</i> in this sequence, if <i>k</i> is less than
450 * <i>n</i>; otherwise, it is equal to the character at index
451 * <i>k+start-n</i> in the argument <code>s</code>.
452 * <p>
453 * If <code>s</code> is <code>null</code>, then this method appends
454 * characters as if the s parameter was a sequence containing the four
455 * characters <code>"null"</code>.
456 *
457 * @param s the sequence to append.
458 * @param start the starting index of the subsequence to be appended.
459 * @param end the end index of the subsequence to be appended.
460 * @return a reference to this object.
461 * @throws IndexOutOfBoundsException if
462 * <code>start</code> or <code>end</code> are negative, or
463 * <code>start</code> is greater than <code>end</code> or
464 * <code>end</code> is greater than <code>s.length()</code>
465 */
466 public AbstractStringBuilder append(CharSequence s, int start, int end) {
467 if (s == null)
468 s = "null";
469 if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
470 throw new IndexOutOfBoundsException(
471 "start " + start + ", end " + end + ", s.length() "
472 + s.length());
473 int len = end - start;
474 if (len == 0)
475 return this;
476 int newCount = count + len;
477 if (newCount > value.length)
478 expandCapacity(newCount);
479 for (int i=start; i<end; i++)
480 value[count++] = s.charAt(i);
481 count = newCount;
482 return this;
483 }
484
485 /**
486 * Appends the string representation of the <code>char</code> array
487 * argument to this sequence.
488 * <p>
489 * The characters of the array argument are appended, in order, to
490 * the contents of this sequence. The length of this sequence
491 * increases by the length of the argument.
492 * <p>
493 * The overall effect is exactly as if the argument were converted to
494 * a string by the method {@link String#valueOf(char[])} and the
495 * characters of that string were then {@link #append(String) appended}
496 * to this character sequence.
497 *
498 * @param str the characters to be appended.
499 * @return a reference to this object.
500 */
501 public AbstractStringBuilder append(char str[]) {
502 int newCount = count + str.length;
503 if (newCount > value.length)
504 expandCapacity(newCount);
505 System.arraycopy(str, 0, value, count, str.length);
506 count = newCount;
507 return this;
508 }
509
510 /**
511 * Appends the string representation of a subarray of the
512 * <code>char</code> array argument to this sequence.
513 * <p>
514 * Characters of the <code>char</code> array <code>str</code>, starting at
515 * index <code>offset</code>, are appended, in order, to the contents
516 * of this sequence. The length of this sequence increases
517 * by the value of <code>len</code>.
518 * <p>
519 * The overall effect is exactly as if the arguments were converted to
520 * a string by the method {@link String#valueOf(char[],int,int)} and the
521 * characters of that string were then {@link #append(String) appended}
522 * to this character sequence.
523 *
524 * @param str the characters to be appended.
525 * @param offset the index of the first <code>char</code> to append.
526 * @param len the number of <code>char</code>s to append.
527 * @return a reference to this object.
528 */
529 public AbstractStringBuilder append(char str[], int offset, int len) {
530 int newCount = count + len;
531 if (newCount > value.length)
532 expandCapacity(newCount);
533 System.arraycopy(str, offset, value, count, len);
534 count = newCount;
535 return this;
536 }
537
538 /**
539 * Appends the string representation of the <code>boolean</code>
540 * argument to the sequence.
541 * <p>
542 * The argument is converted to a string as if by the method
543 * <code>String.valueOf</code>, and the characters of that
544 * string are then appended to this sequence.
545 *
546 * @param b a <code>boolean</code>.
547 * @return a reference to this object.
548 */
549 public AbstractStringBuilder append(boolean b) {
550 if (b) {
551 int newCount = count + 4;
552 if (newCount > value.length)
553 expandCapacity(newCount);
554 value[count++] = 't';
555 value[count++] = 'r';
556 value[count++] = 'u';
557 value[count++] = 'e';
558 } else {
559 int newCount = count + 5;
560 if (newCount > value.length)
561 expandCapacity(newCount);
562 value[count++] = 'f';
563 value[count++] = 'a';
564 value[count++] = 'l';
565 value[count++] = 's';
566 value[count++] = 'e';
567 }
568 return this;
569 }
570
571 /**
572 * Appends the string representation of the <code>char</code>
573 * argument to this sequence.
574 * <p>
575 * The argument is appended to the contents of this sequence.
576 * The length of this sequence increases by <code>1</code>.
577 * <p>
578 * The overall effect is exactly as if the argument were converted to
579 * a string by the method {@link String#valueOf(char)} and the character
580 * in that string were then {@link #append(String) appended} to this
581 * character sequence.
582 *
583 * @param c a <code>char</code>.
584 * @return a reference to this object.
585 */
586 public AbstractStringBuilder append(char c) {
587 int newCount = count + 1;
588 if (newCount > value.length)
589 expandCapacity(newCount);
590 value[count++] = c;
591 return this;
592 }
593
594 /**
595 * Appends the string representation of the <code>int</code>
596 * argument to this sequence.
597 * <p>
598 * The argument is converted to a string as if by the method
599 * <code>String.valueOf</code>, and the characters of that
600 * string are then appended to this sequence.
601 *
602 * @param i an <code>int</code>.
603 * @return a reference to this object.
604 */
605 public AbstractStringBuilder append(int i) {
606 if (i == Integer.MIN_VALUE) {
607 append("-2147483648");
608 return this;
609 }
610 int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
611 : Integer.stringSize(i);
612 int spaceNeeded = count + appendedLength;
613 if (spaceNeeded > value.length)
614 expandCapacity(spaceNeeded);
615 Integer.getChars(i, spaceNeeded, value);
616 count = spaceNeeded;
617 return this;
618 }
619
620 /**
621 * Appends the string representation of the <code>long</code>
622 * argument to this sequence.
623 * <p>
624 * The argument is converted to a string as if by the method
625 * <code>String.valueOf</code>, and the characters of that
626 * string are then appended to this sequence.
627 *
628 * @param l a <code>long</code>.
629 * @return a reference to this object.
630 */
631 public AbstractStringBuilder append(long l) {
632 if (l == Long.MIN_VALUE) {
633 append("-9223372036854775808");
634 return this;
635 }
636 int appendedLength = (l < 0) ? Long.stringSize(-l) + 1
637 : Long.stringSize(l);
638 int spaceNeeded = count + appendedLength;
639 if (spaceNeeded > value.length)
640 expandCapacity(spaceNeeded);
641 Long.getChars(l, spaceNeeded, value);
642 count = spaceNeeded;
643 return this;
644 }
645
646 /**
647 * Appends the string representation of the <code>float</code>
648 * argument to this sequence.
649 * <p>
650 * The argument is converted to a string as if by the method
651 * <code>String.valueOf</code>, and the characters of that
652 * string are then appended to this string sequence.
653 *
654 * @param f a <code>float</code>.
655 * @return a reference to this object.
656 */
657 public AbstractStringBuilder append(float f) {
658 new FloatingDecimal(f).appendTo(this);
659 return this;
660 }
661
662 /**
663 * Appends the string representation of the <code>double</code>
664 * argument to this sequence.
665 * <p>
666 * The argument is converted to a string as if by the method
667 * <code>String.valueOf</code>, and the characters of that
668 * string are then appended to this sequence.
669 *
670 * @param d a <code>double</code>.
671 * @return a reference to this object.
672 */
673 public AbstractStringBuilder append(double d) {
674 new FloatingDecimal(d).appendTo(this);
675 return this;
676 }
677
678 /**
679 * Removes the characters in a substring of this sequence.
680 * The substring begins at the specified <code>start</code> and extends to
681 * the character at index <code>end - 1</code> or to the end of the
682 * sequence if no such character exists. If
683 * <code>start</code> is equal to <code>end</code>, no changes are made.
684 *
685 * @param start The beginning index, inclusive.
686 * @param end The ending index, exclusive.
687 * @return This object.
688 * @throws StringIndexOutOfBoundsException if <code>start</code>
689 * is negative, greater than <code>length()</code>, or
690 * greater than <code>end</code>.
691 */
692 public AbstractStringBuilder delete(int start, int end) {
693 if (start < 0)
694 throw new StringIndexOutOfBoundsException(start);
695 if (end > count)
696 end = count;
697 if (start > end)
698 throw new StringIndexOutOfBoundsException();
699 int len = end - start;
700 if (len > 0) {
701 System.arraycopy(value, start+len, value, start, count-end);
702 count -= len;
703 }
704 return this;
705 }
706
707 /**
708 * Appends the string representation of the <code>codePoint</code>
709 * argument to this sequence.
710 *
711 * <p> The argument is appended to the contents of this sequence.
712 * The length of this sequence increases by
713 * {@link Character#charCount(int) Character.charCount(codePoint)}.
714 *
715 * <p> The overall effect is exactly as if the argument were
716 * converted to a <code>char</code> array by the method {@link
717 * Character#toChars(int)} and the character in that array were
718 * then {@link #append(char[]) appended} to this character
719 * sequence.
720 *
721 * @param codePoint a Unicode code point
722 * @return a reference to this object.
723 * @exception IllegalArgumentException if the specified
724 * <code>codePoint</code> isn't a valid Unicode code point
725 */
726 public AbstractStringBuilder appendCodePoint(int codePoint) {
727 if (!Character.isValidCodePoint(codePoint)) {
728 throw new IllegalArgumentException();
729 }
730 int n = 1;
731 if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
732 n++;
733 }
734 int newCount = count + n;
735 if (newCount > value.length) {
736 expandCapacity(newCount);
737 }
738 if (n == 1) {
739 value[count++] = (char) codePoint;
740 } else {
741 Character.toSurrogates(codePoint, value, count);
742 count += n;
743 }
744 return this;
745 }
746
747 /**
748 * Removes the <code>char</code> at the specified position in this
749 * sequence. This sequence is shortened by one <code>char</code>.
750 *
751 * <p>Note: If the character at the given index is a supplementary
752 * character, this method does not remove the entire character. If
753 * correct handling of supplementary characters is required,
754 * determine the number of <code>char</code>s to remove by calling
755 * <code>Character.charCount(thisSequence.codePointAt(index))</code>,
756 * where <code>thisSequence</code> is this sequence.
757 *
758 * @param index Index of <code>char</code> to remove
759 * @return This object.
760 * @throws StringIndexOutOfBoundsException if the <code>index</code>
761 * is negative or greater than or equal to
762 * <code>length()</code>.
763 */
764 public AbstractStringBuilder deleteCharAt(int index) {
765 if ((index < 0) || (index >= count))
766 throw new StringIndexOutOfBoundsException(index);
767 System.arraycopy(value, index+1, value, index, count-index-1);
768 count--;
769 return this;
770 }
771
772 /**
773 * Replaces the characters in a substring of this sequence
774 * with characters in the specified <code>String</code>. The substring
775 * begins at the specified <code>start</code> and extends to the character
776 * at index <code>end - 1</code> or to the end of the
777 * sequence if no such character exists. First the
778 * characters in the substring are removed and then the specified
779 * <code>String</code> is inserted at <code>start</code>. (This
780 * sequence will be lengthened to accommodate the
781 * specified String if necessary.)
782 *
783 * @param start The beginning index, inclusive.
784 * @param end The ending index, exclusive.
785 * @param str String that will replace previous contents.
786 * @return This object.
787 * @throws StringIndexOutOfBoundsException if <code>start</code>
788 * is negative, greater than <code>length()</code>, or
789 * greater than <code>end</code>.
790 */
791 public AbstractStringBuilder replace(int start, int end, String str) {
792 if (start < 0)
793 throw new StringIndexOutOfBoundsException(start);
794 if (start > count)
795 throw new StringIndexOutOfBoundsException("start > length()");
796 if (start > end)
797 throw new StringIndexOutOfBoundsException("start > end");
798
799 if (end > count)
800 end = count;
801 int len = str.length();
802 int newCount = count + len - (end - start);
803 if (newCount > value.length)
804 expandCapacity(newCount);
805
806 System.arraycopy(value, end, value, start + len, count - end);
807 str.getChars(value, start);
808 count = newCount;
809 return this;
810 }
811
812 /**
813 * Returns a new <code>String</code> that contains a subsequence of
814 * characters currently contained in this character sequence. The
815 * substring begins at the specified index and extends to the end of
816 * this sequence.
817 *
818 * @param start The beginning index, inclusive.
819 * @return The new string.
820 * @throws StringIndexOutOfBoundsException if <code>start</code> is
821 * less than zero, or greater than the length of this object.
822 */
823 public String substring(int start) {
824 return substring(start, count);
825 }
826
827 /**
828 * Returns a new character sequence that is a subsequence of this sequence.
829 *
830 * <p> An invocation of this method of the form
831 *
832 * <blockquote><pre>
833 * sb.subSequence(begin,&nbsp;end)</pre></blockquote>
834 *
835 * behaves in exactly the same way as the invocation
836 *
837 * <blockquote><pre>
838 * sb.substring(begin,&nbsp;end)</pre></blockquote>
839 *
840 * This method is provided so that this class can
841 * implement the {@link CharSequence} interface. </p>
842 *
843 * @param start the start index, inclusive.
844 * @param end the end index, exclusive.
845 * @return the specified subsequence.
846 *
847 * @throws IndexOutOfBoundsException
848 * if <tt>start</tt> or <tt>end</tt> are negative,
849 * if <tt>end</tt> is greater than <tt>length()</tt>,
850 * or if <tt>start</tt> is greater than <tt>end</tt>
851 * @spec JSR-51
852 */
853 public CharSequence subSequence(int start, int end) {
854 return substring(start, end);
855 }
856
857 /**
858 * Returns a new <code>String</code> that contains a subsequence of
859 * characters currently contained in this sequence. The
860 * substring begins at the specified <code>start</code> and
861 * extends to the character at index <code>end - 1</code>.
862 *
863 * @param start The beginning index, inclusive.
864 * @param end The ending index, exclusive.
865 * @return The new string.
866 * @throws StringIndexOutOfBoundsException if <code>start</code>
867 * or <code>end</code> are negative or greater than
868 * <code>length()</code>, or <code>start</code> is
869 * greater than <code>end</code>.
870 */
871 public String substring(int start, int end) {
872 if (start < 0)
873 throw new StringIndexOutOfBoundsException(start);
874 if (end > count)
875 throw new StringIndexOutOfBoundsException(end);
876 if (start > end)
877 throw new StringIndexOutOfBoundsException(end - start);
878 return new String(value, start, end - start);
879 }
880
881 /**
882 * Inserts the string representation of a subarray of the <code>str</code>
883 * array argument into this sequence. The subarray begins at the
884 * specified <code>offset</code> and extends <code>len</code> <code>char</code>s.
885 * The characters of the subarray are inserted into this sequence at
886 * the position indicated by <code>index</code>. The length of this
887 * sequence increases by <code>len</code> <code>char</code>s.
888 *
889 * @param index position at which to insert subarray.
890 * @param str A <code>char</code> array.
891 * @param offset the index of the first <code>char</code> in subarray to
892 * be inserted.
893 * @param len the number of <code>char</code>s in the subarray to
894 * be inserted.
895 * @return This object
896 * @throws StringIndexOutOfBoundsException if <code>index</code>
897 * is negative or greater than <code>length()</code>, or
898 * <code>offset</code> or <code>len</code> are negative, or
899 * <code>(offset+len)</code> is greater than
900 * <code>str.length</code>.
901 */
902 public AbstractStringBuilder insert(int index, char str[], int offset,
903 int len)
904 {
905 if ((index < 0) || (index > length()))
906 throw new StringIndexOutOfBoundsException(index);
907 if ((offset < 0) || (len < 0) || (offset > str.length - len))
908 throw new StringIndexOutOfBoundsException(
909 "offset " + offset + ", len " + len + ", str.length "
910 + str.length);
911 int newCount = count + len;
912 if (newCount > value.length)
913 expandCapacity(newCount);
914 System.arraycopy(value, index, value, index + len, count - index);
915 System.arraycopy(str, offset, value, index, len);
916 count = newCount;
917 return this;
918 }
919
920 /**
921 * Inserts the string representation of the <code>Object</code>
922 * argument into this character sequence.
923 * <p>
924 * The second argument is converted to a string as if by the method
925 * <code>String.valueOf</code>, and the characters of that
926 * string are then inserted into this sequence at the indicated
927 * offset.
928 * <p>
929 * The offset argument must be greater than or equal to
930 * <code>0</code>, and less than or equal to the length of this
931 * sequence.
932 *
933 * @param offset the offset.
934 * @param obj an <code>Object</code>.
935 * @return a reference to this object.
936 * @throws StringIndexOutOfBoundsException if the offset is invalid.
937 */
938 public AbstractStringBuilder insert(int offset, Object obj) {
939 return insert(offset, String.valueOf(obj));
940 }
941
942 /**
943 * Inserts the string into this character sequence.
944 * <p>
945 * The characters of the <code>String</code> argument are inserted, in
946 * order, into this sequence at the indicated offset, moving up any
947 * characters originally above that position and increasing the length
948 * of this sequence by the length of the argument. If
949 * <code>str</code> is <code>null</code>, then the four characters
950 * <code>"null"</code> are inserted into this sequence.
951 * <p>
952 * The character at index <i>k</i> in the new character sequence is
953 * equal to:
954 * <ul>
955 * <li>the character at index <i>k</i> in the old character sequence, if
956 * <i>k</i> is less than <code>offset</code>
957 * <li>the character at index <i>k</i><code>-offset</code> in the
958 * argument <code>str</code>, if <i>k</i> is not less than
959 * <code>offset</code> but is less than <code>offset+str.length()</code>
960 * <li>the character at index <i>k</i><code>-str.length()</code> in the
961 * old character sequence, if <i>k</i> is not less than
962 * <code>offset+str.length()</code>
963 * </ul><p>
964 * The offset argument must be greater than or equal to
965 * <code>0</code>, and less than or equal to the length of this
966 * sequence.
967 *
968 * @param offset the offset.
969 * @param str a string.
970 * @return a reference to this object.
971 * @throws StringIndexOutOfBoundsException if the offset is invalid.
972 */
973 public AbstractStringBuilder insert(int offset, String str) {
974 if ((offset < 0) || (offset > length()))
975 throw new StringIndexOutOfBoundsException(offset);
976 if (str == null)
977 str = "null";
978 int len = str.length();
979 int newCount = count + len;
980 if (newCount > value.length)
981 expandCapacity(newCount);
982 System.arraycopy(value, offset, value, offset + len, count - offset);
983 str.getChars(value, offset);
984 count = newCount;
985 return this;
986 }
987
988 /**
989 * Inserts the string representation of the <code>char</code> array
990 * argument into this sequence.
991 * <p>
992 * The characters of the array argument are inserted into the
993 * contents of this sequence at the position indicated by
994 * <code>offset</code>. The length of this sequence increases by
995 * the length of the argument.
996 * <p>
997 * The overall effect is exactly as if the argument were converted to
998 * a string by the method {@link String#valueOf(char[])} and the
999 * characters of that string were then
1000 * {@link #insert(int,String) inserted} into this
1001 * character sequence at the position indicated by
1002 * <code>offset</code>.
1003 *
1004 * @param offset the offset.
1005 * @param str a character array.
1006 * @return a reference to this object.
1007 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1008 */
1009 public AbstractStringBuilder insert(int offset, char str[]) {
1010 if ((offset < 0) || (offset > length()))
1011 throw new StringIndexOutOfBoundsException(offset);
1012 int len = str.length;
1013 int newCount = count + len;
1014 if (newCount > value.length)
1015 expandCapacity(newCount);
1016 System.arraycopy(value, offset, value, offset + len, count - offset);
1017 System.arraycopy(str, 0, value, offset, len);
1018 count = newCount;
1019 return this;
1020 }
1021
1022 /**
1023 * Inserts the specified <code>CharSequence</code> into this sequence.
1024 * <p>
1025 * The characters of the <code>CharSequence</code> argument are inserted,
1026 * in order, into this sequence at the indicated offset, moving up
1027 * any characters originally above that position and increasing the length
1028 * of this sequence by the length of the argument s.
1029 * <p>
1030 * The result of this method is exactly the same as if it were an
1031 * invocation of this object's insert(dstOffset, s, 0, s.length()) method.
1032 *
1033 * <p>If <code>s</code> is <code>null</code>, then the four characters
1034 * <code>"null"</code> are inserted into this sequence.
1035 *
1036 * @param dstOffset the offset.
1037 * @param s the sequence to be inserted
1038 * @return a reference to this object.
1039 * @throws IndexOutOfBoundsException if the offset is invalid.
1040 */
1041 public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
1042 if (s == null)
1043 s = "null";
1044 if (s instanceof String)
1045 return this.insert(dstOffset, (String)s);
1046 return this.insert(dstOffset, s, 0, s.length());
1047 }
1048
1049 /**
1050 * Inserts a subsequence of the specified <code>CharSequence</code> into
1051 * this sequence.
1052 * <p>
1053 * The subsequence of the argument <code>s</code> specified by
1054 * <code>start</code> and <code>end</code> are inserted,
1055 * in order, into this sequence at the specified destination offset, moving
1056 * up any characters originally above that position. The length of this
1057 * sequence is increased by <code>end - start</code>.
1058 * <p>
1059 * The character at index <i>k</i> in this sequence becomes equal to:
1060 * <ul>
1061 * <li>the character at index <i>k</i> in this sequence, if
1062 * <i>k</i> is less than <code>dstOffset</code>
1063 * <li>the character at index <i>k</i><code>+start-dstOffset</code> in
1064 * the argument <code>s</code>, if <i>k</i> is greater than or equal to
1065 * <code>dstOffset</code> but is less than <code>dstOffset+end-start</code>
1066 * <li>the character at index <i>k</i><code>-(end-start)</code> in this
1067 * sequence, if <i>k</i> is greater than or equal to
1068 * <code>dstOffset+end-start</code>
1069 * </ul><p>
1070 * The dstOffset argument must be greater than or equal to
1071 * <code>0</code>, and less than or equal to the length of this
1072 * sequence.
1073 * <p>The start argument must be nonnegative, and not greater than
1074 * <code>end</code>.
1075 * <p>The end argument must be greater than or equal to
1076 * <code>start</code>, and less than or equal to the length of s.
1077 *
1078 * <p>If <code>s</code> is <code>null</code>, then this method inserts
1079 * characters as if the s parameter was a sequence containing the four
1080 * characters <code>"null"</code>.
1081 *
1082 * @param dstOffset the offset in this sequence.
1083 * @param s the sequence to be inserted.
1084 * @param start the starting index of the subsequence to be inserted.
1085 * @param end the end index of the subsequence to be inserted.
1086 * @return a reference to this object.
1087 * @throws IndexOutOfBoundsException if <code>dstOffset</code>
1088 * is negative or greater than <code>this.length()</code>, or
1089 * <code>start</code> or <code>end</code> are negative, or
1090 * <code>start</code> is greater than <code>end</code> or
1091 * <code>end</code> is greater than <code>s.length()</code>
1092 */
1093 public AbstractStringBuilder insert(int dstOffset, CharSequence s,
1094 int start, int end) {
1095 if (s == null)
1096 s = "null";
1097 if ((dstOffset < 0) || (dstOffset > this.length()))
1098 throw new IndexOutOfBoundsException("dstOffset "+dstOffset);
1099 if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
1100 throw new IndexOutOfBoundsException(
1101 "start " + start + ", end " + end + ", s.length() "
1102 + s.length());
1103 int len = end - start;
1104 if (len == 0)
1105 return this;
1106 int newCount = count + len;
1107 if (newCount > value.length)
1108 expandCapacity(newCount);
1109 System.arraycopy(value, dstOffset, value, dstOffset + len,
1110 count - dstOffset);
1111 for (int i=start; i<end; i++)
1112 value[dstOffset++] = s.charAt(i);
1113 count = newCount;
1114 return this;
1115 }
1116
1117 /**
1118 * Inserts the string representation of the <code>boolean</code>
1119 * argument into this sequence.
1120 * <p>
1121 * The second argument is converted to a string as if by the method
1122 * <code>String.valueOf</code>, and the characters of that
1123 * string are then inserted into this sequence at the indicated
1124 * offset.
1125 * <p>
1126 * The offset argument must be greater than or equal to
1127 * <code>0</code>, and less than or equal to the length of this
1128 * sequence.
1129 *
1130 * @param offset the offset.
1131 * @param b a <code>boolean</code>.
1132 * @return a reference to this object.
1133 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1134 */
1135 public AbstractStringBuilder insert(int offset, boolean b) {
1136 return insert(offset, String.valueOf(b));
1137 }
1138
1139 /**
1140 * Inserts the string representation of the <code>char</code>
1141 * argument into this sequence.
1142 * <p>
1143 * The second argument is inserted into the contents of this sequence
1144 * at the position indicated by <code>offset</code>. The length
1145 * of this sequence increases by one.
1146 * <p>
1147 * The overall effect is exactly as if the argument were converted to
1148 * a string by the method {@link String#valueOf(char)} and the character
1149 * in that string were then {@link #insert(int, String) inserted} into
1150 * this character sequence at the position indicated by
1151 * <code>offset</code>.
1152 * <p>
1153 * The offset argument must be greater than or equal to
1154 * <code>0</code>, and less than or equal to the length of this
1155 * sequence.
1156 *
1157 * @param offset the offset.
1158 * @param c a <code>char</code>.
1159 * @return a reference to this object.
1160 * @throws IndexOutOfBoundsException if the offset is invalid.
1161 */
1162 public AbstractStringBuilder insert(int offset, char c) {
1163 int newCount = count + 1;
1164 if (newCount > value.length)
1165 expandCapacity(newCount);
1166 System.arraycopy(value, offset, value, offset + 1, count - offset);
1167 value[offset] = c;
1168 count = newCount;
1169 return this;
1170 }
1171
1172 /**
1173 * Inserts the string representation of the second <code>int</code>
1174 * argument into this sequence.
1175 * <p>
1176 * The second argument is converted to a string as if by the method
1177 * <code>String.valueOf</code>, and the characters of that
1178 * string are then inserted into this sequence at the indicated
1179 * offset.
1180 * <p>
1181 * The offset argument must be greater than or equal to
1182 * <code>0</code>, and less than or equal to the length of this
1183 * sequence.
1184 *
1185 * @param offset the offset.
1186 * @param i an <code>int</code>.
1187 * @return a reference to this object.
1188 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1189 */
1190 public AbstractStringBuilder insert(int offset, int i) {
1191 return insert(offset, String.valueOf(i));
1192 }
1193
1194 /**
1195 * Inserts the string representation of the <code>long</code>
1196 * argument into this sequence.
1197 * <p>
1198 * The second argument is converted to a string as if by the method
1199 * <code>String.valueOf</code>, and the characters of that
1200 * string are then inserted into this sequence at the position
1201 * indicated by <code>offset</code>.
1202 * <p>
1203 * The offset argument must be greater than or equal to
1204 * <code>0</code>, and less than or equal to the length of this
1205 * sequence.
1206 *
1207 * @param offset the offset.
1208 * @param l a <code>long</code>.
1209 * @return a reference to this object.
1210 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1211 */
1212 public AbstractStringBuilder insert(int offset, long l) {
1213 return insert(offset, String.valueOf(l));
1214 }
1215
1216 /**
1217 * Inserts the string representation of the <code>float</code>
1218 * argument into this sequence.
1219 * <p>
1220 * The second argument is converted to a string as if by the method
1221 * <code>String.valueOf</code>, and the characters of that
1222 * string are then inserted into this sequence at the indicated
1223 * offset.
1224 * <p>
1225 * The offset argument must be greater than or equal to
1226 * <code>0</code>, and less than or equal to the length of this
1227 * sequence.
1228 *
1229 * @param offset the offset.
1230 * @param f a <code>float</code>.
1231 * @return a reference to this object.
1232 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1233 */
1234 public AbstractStringBuilder insert(int offset, float f) {
1235 return insert(offset, String.valueOf(f));
1236 }
1237
1238 /**
1239 * Inserts the string representation of the <code>double</code>
1240 * argument into this sequence.
1241 * <p>
1242 * The second argument is converted to a string as if by the method
1243 * <code>String.valueOf</code>, and the characters of that
1244 * string are then inserted into this sequence at the indicated
1245 * offset.
1246 * <p>
1247 * The offset argument must be greater than or equal to
1248 * <code>0</code>, and less than or equal to the length of this
1249 * sequence.
1250 *
1251 * @param offset the offset.
1252 * @param d a <code>double</code>.
1253 * @return a reference to this object.
1254 * @throws StringIndexOutOfBoundsException if the offset is invalid.
1255 */
1256 public AbstractStringBuilder insert(int offset, double d) {
1257 return insert(offset, String.valueOf(d));
1258 }
1259
1260 /**
1261 * Returns the index within this string of the first occurrence of the
1262 * specified substring. The integer returned is the smallest value
1263 * <i>k</i> such that:
1264 * <blockquote><pre>
1265 * this.toString().startsWith(str, <i>k</i>)
1266 * </pre></blockquote>
1267 * is <code>true</code>.
1268 *
1269 * @param str any string.
1270 * @return if the string argument occurs as a substring within this
1271 * object, then the index of the first character of the first
1272 * such substring is returned; if it does not occur as a
1273 * substring, <code>-1</code> is returned.
1274 * @throws java.lang.NullPointerException if <code>str</code> is
1275 * <code>null</code>.
1276 */
1277 public int indexOf(String str) {
1278 return indexOf(str, 0);
1279 }
1280
1281 /**
1282 * Returns the index within this string of the first occurrence of the
1283 * specified substring, starting at the specified index. The integer
1284 * returned is the smallest value <tt>k</tt> for which:
1285 * <blockquote><pre>
1286 * k >= Math.min(fromIndex, str.length()) &&
1287 * this.toString().startsWith(str, k)
1288 * </pre></blockquote>
1289 * If no such value of <i>k</i> exists, then -1 is returned.
1290 *
1291 * @param str the substring for which to search.
1292 * @param fromIndex the index from which to start the search.
1293 * @return the index within this string of the first occurrence of the
1294 * specified substring, starting at the specified index.
1295 * @throws java.lang.NullPointerException if <code>str</code> is
1296 * <code>null</code>.
1297 */
1298 public int indexOf(String str, int fromIndex) {
1299 return String.indexOf(value, 0, count,
1300 str.toCharArray(), 0, str.length(), fromIndex);
1301 }
1302
1303 /**
1304 * Returns the index within this string of the rightmost occurrence
1305 * of the specified substring. The rightmost empty string "" is
1306 * considered to occur at the index value <code>this.length()</code>.
1307 * The returned index is the largest value <i>k</i> such that
1308 * <blockquote><pre>
1309 * this.toString().startsWith(str, k)
1310 * </pre></blockquote>
1311 * is true.
1312 *
1313 * @param str the substring to search for.
1314 * @return if the string argument occurs one or more times as a substring
1315 * within this object, then the index of the first character of
1316 * the last such substring is returned. If it does not occur as
1317 * a substring, <code>-1</code> is returned.
1318 * @throws java.lang.NullPointerException if <code>str</code> is
1319 * <code>null</code>.
1320 */
1321 public int lastIndexOf(String str) {
1322 return lastIndexOf(str, count);
1323 }
1324
1325 /**
1326 * Returns the index within this string of the last occurrence of the
1327 * specified substring. The integer returned is the largest value <i>k</i>
1328 * such that:
1329 * <blockquote><pre>
1330 * k <= Math.min(fromIndex, str.length()) &&
1331 * this.toString().startsWith(str, k)
1332 * </pre></blockquote>
1333 * If no such value of <i>k</i> exists, then -1 is returned.
1334 *
1335 * @param str the substring to search for.
1336 * @param fromIndex the index to start the search from.
1337 * @return the index within this sequence of the last occurrence of the
1338 * specified substring.
1339 * @throws java.lang.NullPointerException if <code>str</code> is
1340 * <code>null</code>.
1341 */
1342 public int lastIndexOf(String str, int fromIndex) {
1343 return String.lastIndexOf(value, 0, count,
1344 str.toCharArray(), 0, str.length(), fromIndex);
1345 }
1346
1347 /**
1348 * Causes this character sequence to be replaced by the reverse of
1349 * the sequence. If there are any surrogate pairs included in the
1350 * sequence, these are treated as single characters for the
1351 * reverse operation. Thus, the order of the high-low surrogates
1352 * is never reversed.
1353 *
1354 * Let <i>n</i> be the character length of this character sequence
1355 * (not the length in <code>char</code> values) just prior to
1356 * execution of the <code>reverse</code> method. Then the
1357 * character at index <i>k</i> in the new character sequence is
1358 * equal to the character at index <i>n-k-1</i> in the old
1359 * character sequence.
1360 *
1361 * <p>Note that the reverse operation may result in producing
1362 * surrogate pairs that were unpaired low-surrogates and
1363 * high-surrogates before the operation. For example, reversing
1364 * "&#92;uDC00&#92;uD800" produces "&#92;uD800&#92;uDC00" which is
1365 * a valid surrogate pair.
1366 *
1367 * @return a reference to this object.
1368 */
1369 public AbstractStringBuilder reverse() {
1370 boolean hasSurrogate = false;
1371 int n = count - 1;
1372 for (int j = (n-1) >> 1; j >= 0; --j) {
1373 char temp = value[j];
1374 char temp2 = value[n - j];
1375 if (!hasSurrogate) {
1376 hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
1377 || (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
1378 }
1379 value[j] = temp2;
1380 value[n - j] = temp;
1381 }
1382 if (hasSurrogate) {
1383 // Reverse back all valid surrogate pairs
1384 for (int i = 0; i < count - 1; i++) {
1385 char c2 = value[i];
1386 if (Character.isLowSurrogate(c2)) {
1387 char c1 = value[i + 1];
1388 if (Character.isHighSurrogate(c1)) {
1389 value[i++] = c1;
1390 value[i] = c2;
1391 }
1392 }
1393 }
1394 }
1395 return this;
1396 }
1397
1398 /**
1399 * Returns a string representing the data in this sequence.
1400 * A new <code>String</code> object is allocated and initialized to
1401 * contain the character sequence currently represented by this
1402 * object. This <code>String</code> is then returned. Subsequent
1403 * changes to this sequence do not affect the contents of the
1404 * <code>String</code>.
1405 *
1406 * @return a string representation of this sequence of characters.
1407 */
1408 public abstract String toString();
1409
1410 /**
1411 * Needed by <tt>String</tt> for the contentEquals method.
1412 */
1413 final char[] getValue() {
1414 return value;
1415 }
1416
1417}