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