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