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