001 /* StringBuilder.java -- Unsynchronized growable strings 002 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 003 Free Software Foundation, Inc. 004 005 This file is part of GNU Classpath. 006 007 GNU Classpath is free software; you can redistribute it and/or modify 008 it under the terms of the GNU General Public License as published by 009 the Free Software Foundation; either version 2, or (at your option) 010 any later version. 011 012 GNU Classpath is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of 014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 General Public License for more details. 016 017 You should have received a copy of the GNU General Public License 018 along with GNU Classpath; see the file COPYING. If not, write to the 019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 020 02110-1301 USA. 021 022 Linking this library statically or dynamically with other modules is 023 making a combined work based on this library. Thus, the terms and 024 conditions of the GNU General Public License cover the whole 025 combination. 026 027 As a special exception, the copyright holders of this library give you 028 permission to link this library with independent modules to produce an 029 executable, regardless of the license terms of these independent 030 modules, and to copy and distribute the resulting executable under 031 terms of your choice, provided that you also meet, for each linked 032 independent module, the terms and conditions of the license of that 033 module. An independent module is a module which is not derived from 034 or based on this library. If you modify this library, you may extend 035 this exception to your version of the library, but you are not 036 obligated to do so. If you do not wish to do so, delete this 037 exception statement from your version. */ 038 039 package java.lang; 040 041 import java.io.Serializable; 042 043 /** 044 * <code>StringBuilder</code> represents a changeable <code>String</code>. 045 * It provides the operations required to modify the 046 * <code>StringBuilder</code>, including insert, replace, delete, append, 047 * and reverse. It like <code>StringBuffer</code>, but is not 048 * synchronized. It is ideal for use when it is known that the 049 * object will only be used from a single thread. 050 * 051 * <p><code>StringBuilder</code>s are variable-length in nature, so even if 052 * you initialize them to a certain size, they can still grow larger than 053 * that. <em>Capacity</em> indicates the number of characters the 054 * <code>StringBuilder</code> can have in it before it has to grow (growing 055 * the char array is an expensive operation involving <code>new</code>). 056 * 057 * <p>Incidentally, compilers often implement the String operator "+" 058 * by using a <code>StringBuilder</code> operation:<br> 059 * <code>a + b</code><br> 060 * is the same as<br> 061 * <code>new StringBuilder().append(a).append(b).toString()</code>. 062 * 063 * <p>Classpath's StringBuilder is capable of sharing memory with Strings for 064 * efficiency. This will help when a StringBuilder is converted to a String 065 * and the StringBuilder is not changed after that (quite common when 066 * performing string concatenation). 067 * 068 * @author Paul Fisher 069 * @author John Keiser 070 * @author Tom Tromey 071 * @author Eric Blake (ebb9@email.byu.edu) 072 * @see String 073 * @see StringBuffer 074 * 075 * @since 1.5 076 */ 077 public final class StringBuilder 078 implements Serializable, CharSequence, Appendable 079 { 080 // Implementation note: if you change this class, you usually will 081 // want to change StringBuffer as well. 082 083 /** 084 * For compatability with Sun's JDK 085 */ 086 private static final long serialVersionUID = 4383685877147921099L; 087 088 /** 089 * Index of next available character (and thus the size of the current 090 * string contents). Note that this has permissions set this way so that 091 * String can get the value. 092 * 093 * @serial the number of characters in the buffer 094 */ 095 int count; 096 097 /** 098 * The buffer. Note that this has permissions set this way so that String 099 * can get the value. 100 * 101 * @serial the buffer 102 */ 103 char[] value; 104 105 /** 106 * The default capacity of a buffer. 107 */ 108 private static final int DEFAULT_CAPACITY = 16; 109 110 /** 111 * Create a new StringBuilder with default capacity 16. 112 */ 113 public StringBuilder() 114 { 115 this(DEFAULT_CAPACITY); 116 } 117 118 /** 119 * Create an empty <code>StringBuilder</code> with the specified initial 120 * capacity. 121 * 122 * @param capacity the initial capacity 123 * @throws NegativeArraySizeException if capacity is negative 124 */ 125 public StringBuilder(int capacity) 126 { 127 value = new char[capacity]; 128 } 129 130 /** 131 * Create a new <code>StringBuilder</code> with the characters in the 132 * specified <code>String</code>. Initial capacity will be the size of the 133 * String plus 16. 134 * 135 * @param str the <code>String</code> to convert 136 * @throws NullPointerException if str is null 137 */ 138 public StringBuilder(String str) 139 { 140 // Unfortunately, because the size is 16 larger, we cannot share. 141 count = str.count; 142 value = new char[count + DEFAULT_CAPACITY]; 143 str.getChars(0, count, value, 0); 144 } 145 146 /** 147 * Create a new <code>StringBuilder</code> with the characters in the 148 * specified <code>CharSequence</code>. Initial capacity will be the 149 * length of the sequence plus 16; if the sequence reports a length 150 * less than or equal to 0, then the initial capacity will be 16. 151 * 152 * @param seq the initializing <code>CharSequence</code> 153 * @throws NullPointerException if str is null 154 */ 155 public StringBuilder(CharSequence seq) 156 { 157 int len = seq.length(); 158 count = len <= 0 ? 0 : len; 159 value = new char[count + DEFAULT_CAPACITY]; 160 for (int i = 0; i < len; ++i) 161 value[i] = seq.charAt(i); 162 } 163 164 /** 165 * Get the length of the <code>String</code> this <code>StringBuilder</code> 166 * would create. Not to be confused with the <em>capacity</em> of the 167 * <code>StringBuilder</code>. 168 * 169 * @return the length of this <code>StringBuilder</code> 170 * @see #capacity() 171 * @see #setLength(int) 172 */ 173 public int length() 174 { 175 return count; 176 } 177 178 /** 179 * Get the total number of characters this <code>StringBuilder</code> can 180 * support before it must be grown. Not to be confused with <em>length</em>. 181 * 182 * @return the capacity of this <code>StringBuilder</code> 183 * @see #length() 184 * @see #ensureCapacity(int) 185 */ 186 public int capacity() 187 { 188 return value.length; 189 } 190 191 /** 192 * Increase the capacity of this <code>StringBuilder</code>. This will 193 * ensure that an expensive growing operation will not occur until 194 * <code>minimumCapacity</code> is reached. The buffer is grown to the 195 * larger of <code>minimumCapacity</code> and 196 * <code>capacity() * 2 + 2</code>, if it is not already large enough. 197 * 198 * @param minimumCapacity the new capacity 199 * @see #capacity() 200 */ 201 public void ensureCapacity(int minimumCapacity) 202 { 203 if (minimumCapacity > value.length) 204 { 205 int max = value.length * 2 + 2; 206 minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); 207 char[] nb = new char[minimumCapacity]; 208 System.arraycopy(value, 0, nb, 0, count); 209 value = nb; 210 } 211 } 212 213 /** 214 * Set the length of this StringBuilder. If the new length is greater than 215 * the current length, all the new characters are set to '\0'. If the new 216 * length is less than the current length, the first <code>newLength</code> 217 * characters of the old array will be preserved, and the remaining 218 * characters are truncated. 219 * 220 * @param newLength the new length 221 * @throws IndexOutOfBoundsException if the new length is negative 222 * (while unspecified, this is a StringIndexOutOfBoundsException) 223 * @see #length() 224 */ 225 public void setLength(int newLength) 226 { 227 if (newLength < 0) 228 throw new StringIndexOutOfBoundsException(newLength); 229 230 int valueLength = value.length; 231 232 /* Always call ensureCapacity in order to preserve copy-on-write 233 semantics. */ 234 ensureCapacity(newLength); 235 236 if (newLength < valueLength) 237 { 238 /* If the StringBuilder's value just grew, then we know that 239 value is newly allocated and the region between count and 240 newLength is filled with '\0'. */ 241 count = newLength; 242 } 243 else 244 { 245 /* The StringBuilder's value doesn't need to grow. However, 246 we should clear out any cruft that may exist. */ 247 while (count < newLength) 248 value[count++] = '\0'; 249 } 250 } 251 252 /** 253 * Get the character at the specified index. 254 * 255 * @param index the index of the character to get, starting at 0 256 * @return the character at the specified index 257 * @throws IndexOutOfBoundsException if index is negative or >= length() 258 * (while unspecified, this is a StringIndexOutOfBoundsException) 259 */ 260 public char charAt(int index) 261 { 262 if (index < 0 || index >= count) 263 throw new StringIndexOutOfBoundsException(index); 264 return value[index]; 265 } 266 267 /** 268 * Get the specified array of characters. <code>srcOffset - srcEnd</code> 269 * characters will be copied into the array you pass in. 270 * 271 * @param srcOffset the index to start copying from (inclusive) 272 * @param srcEnd the index to stop copying from (exclusive) 273 * @param dst the array to copy into 274 * @param dstOffset the index to start copying into 275 * @throws NullPointerException if dst is null 276 * @throws IndexOutOfBoundsException if any source or target indices are 277 * out of range (while unspecified, source problems cause a 278 * StringIndexOutOfBoundsException, and dest problems cause an 279 * ArrayIndexOutOfBoundsException) 280 * @see System#arraycopy(Object, int, Object, int, int) 281 */ 282 public void getChars(int srcOffset, int srcEnd, 283 char[] dst, int dstOffset) 284 { 285 if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset) 286 throw new StringIndexOutOfBoundsException(); 287 System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset); 288 } 289 290 /** 291 * Set the character at the specified index. 292 * 293 * @param index the index of the character to set starting at 0 294 * @param ch the value to set that character to 295 * @throws IndexOutOfBoundsException if index is negative or >= length() 296 * (while unspecified, this is a StringIndexOutOfBoundsException) 297 */ 298 public void setCharAt(int index, char ch) 299 { 300 if (index < 0 || index >= count) 301 throw new StringIndexOutOfBoundsException(index); 302 // Call ensureCapacity to enforce copy-on-write. 303 ensureCapacity(count); 304 value[index] = ch; 305 } 306 307 /** 308 * Append the <code>String</code> value of the argument to this 309 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 310 * to <code>String</code>. 311 * 312 * @param obj the <code>Object</code> to convert and append 313 * @return this <code>StringBuilder</code> 314 * @see String#valueOf(Object) 315 * @see #append(String) 316 */ 317 public StringBuilder append(Object obj) 318 { 319 return append(obj == null ? "null" : obj.toString()); 320 } 321 322 /** 323 * Append the <code>String</code> to this <code>StringBuilder</code>. If 324 * str is null, the String "null" is appended. 325 * 326 * @param str the <code>String</code> to append 327 * @return this <code>StringBuilder</code> 328 */ 329 public StringBuilder append(String str) 330 { 331 if (str == null) 332 str = "null"; 333 int len = str.count; 334 ensureCapacity(count + len); 335 str.getChars(0, len, value, count); 336 count += len; 337 return this; 338 } 339 340 /** 341 * Append the <code>StringBuilder</code> value of the argument to this 342 * <code>StringBuilder</code>. This behaves the same as 343 * <code>append((Object) stringBuffer)</code>, except it is more efficient. 344 * 345 * @param stringBuffer the <code>StringBuilder</code> to convert and append 346 * @return this <code>StringBuilder</code> 347 * @see #append(Object) 348 */ 349 public StringBuilder append(StringBuffer stringBuffer) 350 { 351 if (stringBuffer == null) 352 return append("null"); 353 synchronized (stringBuffer) 354 { 355 int len = stringBuffer.count; 356 ensureCapacity(count + len); 357 System.arraycopy(stringBuffer.value, 0, value, count, len); 358 count += len; 359 } 360 return this; 361 } 362 363 /** 364 * Append the <code>char</code> array to this <code>StringBuilder</code>. 365 * This is similar (but more efficient) than 366 * <code>append(new String(data))</code>, except in the case of null. 367 * 368 * @param data the <code>char[]</code> to append 369 * @return this <code>StringBuilder</code> 370 * @throws NullPointerException if <code>str</code> is <code>null</code> 371 * @see #append(char[], int, int) 372 */ 373 public StringBuilder append(char[] data) 374 { 375 return append(data, 0, data.length); 376 } 377 378 /** 379 * Append part of the <code>char</code> array to this 380 * <code>StringBuilder</code>. This is similar (but more efficient) than 381 * <code>append(new String(data, offset, count))</code>, except in the case 382 * of null. 383 * 384 * @param data the <code>char[]</code> to append 385 * @param offset the start location in <code>str</code> 386 * @param count the number of characters to get from <code>str</code> 387 * @return this <code>StringBuilder</code> 388 * @throws NullPointerException if <code>str</code> is <code>null</code> 389 * @throws IndexOutOfBoundsException if offset or count is out of range 390 * (while unspecified, this is a StringIndexOutOfBoundsException) 391 */ 392 public StringBuilder append(char[] data, int offset, int count) 393 { 394 if (offset < 0 || count < 0 || offset > data.length - count) 395 throw new StringIndexOutOfBoundsException(); 396 ensureCapacity(this.count + count); 397 System.arraycopy(data, offset, value, this.count, count); 398 this.count += count; 399 return this; 400 } 401 402 /** 403 * Append the <code>String</code> value of the argument to this 404 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 405 * to <code>String</code>. 406 * 407 * @param bool the <code>boolean</code> to convert and append 408 * @return this <code>StringBuilder</code> 409 * @see String#valueOf(boolean) 410 */ 411 public StringBuilder append(boolean bool) 412 { 413 return append(bool ? "true" : "false"); 414 } 415 416 /** 417 * Append the <code>char</code> to this <code>StringBuilder</code>. 418 * 419 * @param ch the <code>char</code> to append 420 * @return this <code>StringBuilder</code> 421 */ 422 public StringBuilder append(char ch) 423 { 424 ensureCapacity(count + 1); 425 value[count++] = ch; 426 return this; 427 } 428 429 /** 430 * Append the characters in the <code>CharSequence</code> to this 431 * buffer. 432 * 433 * @param seq the <code>CharSequence</code> providing the characters 434 * @return this <code>StringBuilder</code> 435 */ 436 public StringBuilder append(CharSequence seq) 437 { 438 return append(seq, 0, seq.length()); 439 } 440 441 /** 442 * Append some characters from the <code>CharSequence</code> to this 443 * buffer. If the argument is null, the four characters "null" are 444 * appended. 445 * 446 * @param seq the <code>CharSequence</code> providing the characters 447 * @param start the starting index 448 * @param end one past the final index 449 * @return this <code>StringBuilder</code> 450 */ 451 public StringBuilder append(CharSequence seq, int start, 452 int end) 453 { 454 if (seq == null) 455 return append("null"); 456 if (end - start > 0) 457 { 458 ensureCapacity(count + end - start); 459 for (; start < end; ++start) 460 value[count++] = seq.charAt(start); 461 } 462 return this; 463 } 464 465 /** 466 * Append the code point to this <code>StringBuilder</code>. 467 * This is like #append(char), but will append two characters 468 * if a supplementary code point is given. 469 * 470 * @param code the code point to append 471 * @return this <code>StringBuilder</code> 472 * @see Character#toChars(int, char[], int) 473 * @since 1.5 474 */ 475 public synchronized StringBuilder appendCodePoint(int code) 476 { 477 int len = Character.charCount(code); 478 ensureCapacity(count + len); 479 Character.toChars(code, value, count); 480 count += len; 481 return this; 482 } 483 484 /** 485 * Append the <code>String</code> value of the argument to this 486 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 487 * to <code>String</code>. 488 * 489 * @param inum the <code>int</code> to convert and append 490 * @return this <code>StringBuilder</code> 491 * @see String#valueOf(int) 492 */ 493 // FIXME: this is native in libgcj in StringBuffer. 494 public StringBuilder append(int inum) 495 { 496 return append(String.valueOf(inum)); 497 } 498 499 /** 500 * Append the <code>String</code> value of the argument to this 501 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 502 * to <code>String</code>. 503 * 504 * @param lnum the <code>long</code> to convert and append 505 * @return this <code>StringBuilder</code> 506 * @see String#valueOf(long) 507 */ 508 public StringBuilder append(long lnum) 509 { 510 return append(Long.toString(lnum, 10)); 511 } 512 513 /** 514 * Append the <code>String</code> value of the argument to this 515 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 516 * to <code>String</code>. 517 * 518 * @param fnum the <code>float</code> to convert and append 519 * @return this <code>StringBuilder</code> 520 * @see String#valueOf(float) 521 */ 522 public StringBuilder append(float fnum) 523 { 524 return append(Float.toString(fnum)); 525 } 526 527 /** 528 * Append the <code>String</code> value of the argument to this 529 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 530 * to <code>String</code>. 531 * 532 * @param dnum the <code>double</code> to convert and append 533 * @return this <code>StringBuilder</code> 534 * @see String#valueOf(double) 535 */ 536 public StringBuilder append(double dnum) 537 { 538 return append(Double.toString(dnum)); 539 } 540 541 /** 542 * Delete characters from this <code>StringBuilder</code>. 543 * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is 544 * harmless for end to be larger than length(). 545 * 546 * @param start the first character to delete 547 * @param end the index after the last character to delete 548 * @return this <code>StringBuilder</code> 549 * @throws StringIndexOutOfBoundsException if start or end are out of bounds 550 */ 551 public StringBuilder delete(int start, int end) 552 { 553 if (start < 0 || start > count || start > end) 554 throw new StringIndexOutOfBoundsException(start); 555 if (end > count) 556 end = count; 557 // This will unshare if required. 558 ensureCapacity(count); 559 if (count - end != 0) 560 System.arraycopy(value, end, value, start, count - end); 561 count -= end - start; 562 return this; 563 } 564 565 /** 566 * Delete a character from this <code>StringBuilder</code>. 567 * 568 * @param index the index of the character to delete 569 * @return this <code>StringBuilder</code> 570 * @throws StringIndexOutOfBoundsException if index is out of bounds 571 */ 572 public StringBuilder deleteCharAt(int index) 573 { 574 return delete(index, index + 1); 575 } 576 577 /** 578 * Replace characters between index <code>start</code> (inclusive) and 579 * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> 580 * is larger than the size of this StringBuilder, all characters after 581 * <code>start</code> are replaced. 582 * 583 * @param start the beginning index of characters to delete (inclusive) 584 * @param end the ending index of characters to delete (exclusive) 585 * @param str the new <code>String</code> to insert 586 * @return this <code>StringBuilder</code> 587 * @throws StringIndexOutOfBoundsException if start or end are out of bounds 588 * @throws NullPointerException if str is null 589 */ 590 public StringBuilder replace(int start, int end, String str) 591 { 592 if (start < 0 || start > count || start > end) 593 throw new StringIndexOutOfBoundsException(start); 594 595 int len = str.count; 596 // Calculate the difference in 'count' after the replace. 597 int delta = len - (end > count ? count : end) + start; 598 ensureCapacity(count + delta); 599 600 if (delta != 0 && end < count) 601 System.arraycopy(value, end, value, end + delta, count - end); 602 603 str.getChars(0, len, value, start); 604 count += delta; 605 return this; 606 } 607 608 /** 609 * Creates a substring of this StringBuilder, starting at a specified index 610 * and ending at the end of this StringBuilder. 611 * 612 * @param beginIndex index to start substring (base 0) 613 * @return new String which is a substring of this StringBuilder 614 * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds 615 * @see #substring(int, int) 616 */ 617 public String substring(int beginIndex) 618 { 619 return substring(beginIndex, count); 620 } 621 622 /** 623 * Creates a substring of this StringBuilder, starting at a specified index 624 * and ending at one character before a specified index. This is implemented 625 * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy 626 * the CharSequence interface. 627 * 628 * @param beginIndex index to start at (inclusive, base 0) 629 * @param endIndex index to end at (exclusive) 630 * @return new String which is a substring of this StringBuilder 631 * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of 632 * bounds 633 * @see #substring(int, int) 634 */ 635 public CharSequence subSequence(int beginIndex, int endIndex) 636 { 637 return substring(beginIndex, endIndex); 638 } 639 640 /** 641 * Creates a substring of this StringBuilder, starting at a specified index 642 * and ending at one character before a specified index. 643 * 644 * @param beginIndex index to start at (inclusive, base 0) 645 * @param endIndex index to end at (exclusive) 646 * @return new String which is a substring of this StringBuilder 647 * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out 648 * of bounds 649 */ 650 public String substring(int beginIndex, int endIndex) 651 { 652 int len = endIndex - beginIndex; 653 if (beginIndex < 0 || endIndex > count || endIndex < beginIndex) 654 throw new StringIndexOutOfBoundsException(); 655 if (len == 0) 656 return ""; 657 return new String(value, beginIndex, len); 658 } 659 660 /** 661 * Insert a subarray of the <code>char[]</code> argument into this 662 * <code>StringBuilder</code>. 663 * 664 * @param offset the place to insert in this buffer 665 * @param str the <code>char[]</code> to insert 666 * @param str_offset the index in <code>str</code> to start inserting from 667 * @param len the number of characters to insert 668 * @return this <code>StringBuilder</code> 669 * @throws NullPointerException if <code>str</code> is <code>null</code> 670 * @throws StringIndexOutOfBoundsException if any index is out of bounds 671 */ 672 public StringBuilder insert(int offset, 673 char[] str, int str_offset, int len) 674 { 675 if (offset < 0 || offset > count || len < 0 676 || str_offset < 0 || str_offset > str.length - len) 677 throw new StringIndexOutOfBoundsException(); 678 ensureCapacity(count + len); 679 System.arraycopy(value, offset, value, offset + len, count - offset); 680 System.arraycopy(str, str_offset, value, offset, len); 681 count += len; 682 return this; 683 } 684 685 /** 686 * Insert the <code>String</code> value of the argument into this 687 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 688 * to <code>String</code>. 689 * 690 * @param offset the place to insert in this buffer 691 * @param obj the <code>Object</code> to convert and insert 692 * @return this <code>StringBuilder</code> 693 * @exception StringIndexOutOfBoundsException if offset is out of bounds 694 * @see String#valueOf(Object) 695 */ 696 public StringBuilder insert(int offset, Object obj) 697 { 698 return insert(offset, obj == null ? "null" : obj.toString()); 699 } 700 701 /** 702 * Insert the <code>String</code> argument into this 703 * <code>StringBuilder</code>. If str is null, the String "null" is used 704 * instead. 705 * 706 * @param offset the place to insert in this buffer 707 * @param str the <code>String</code> to insert 708 * @return this <code>StringBuilder</code> 709 * @throws StringIndexOutOfBoundsException if offset is out of bounds 710 */ 711 public StringBuilder insert(int offset, String str) 712 { 713 if (offset < 0 || offset > count) 714 throw new StringIndexOutOfBoundsException(offset); 715 if (str == null) 716 str = "null"; 717 int len = str.count; 718 ensureCapacity(count + len); 719 System.arraycopy(value, offset, value, offset + len, count - offset); 720 str.getChars(0, len, value, offset); 721 count += len; 722 return this; 723 } 724 725 /** 726 * Insert the <code>CharSequence</code> argument into this 727 * <code>StringBuilder</code>. If the sequence is null, the String 728 * "null" is used instead. 729 * 730 * @param offset the place to insert in this buffer 731 * @param sequence the <code>CharSequence</code> to insert 732 * @return this <code>StringBuilder</code> 733 * @throws IndexOutOfBoundsException if offset is out of bounds 734 */ 735 public synchronized StringBuilder insert(int offset, CharSequence sequence) 736 { 737 if (sequence == null) 738 sequence = "null"; 739 return insert(offset, sequence, 0, sequence.length()); 740 } 741 742 /** 743 * Insert a subsequence of the <code>CharSequence</code> argument into this 744 * <code>StringBuilder</code>. If the sequence is null, the String 745 * "null" is used instead. 746 * 747 * @param offset the place to insert in this buffer 748 * @param sequence the <code>CharSequence</code> to insert 749 * @param start the starting index of the subsequence 750 * @param end one past the ending index of the subsequence 751 * @return this <code>StringBuilder</code> 752 * @throws IndexOutOfBoundsException if offset, start, 753 * or end are out of bounds 754 */ 755 public synchronized StringBuilder insert(int offset, CharSequence sequence, 756 int start, int end) 757 { 758 if (sequence == null) 759 sequence = "null"; 760 if (start < 0 || end < 0 || start > end || end > sequence.length()) 761 throw new IndexOutOfBoundsException(); 762 int len = end - start; 763 ensureCapacity(count + len); 764 System.arraycopy(value, offset, value, offset + len, count - offset); 765 for (int i = start; i < end; ++i) 766 value[offset++] = sequence.charAt(i); 767 count += len; 768 return this; 769 } 770 771 /** 772 * Insert the <code>char[]</code> argument into this 773 * <code>StringBuilder</code>. 774 * 775 * @param offset the place to insert in this buffer 776 * @param data the <code>char[]</code> to insert 777 * @return this <code>StringBuilder</code> 778 * @throws NullPointerException if <code>data</code> is <code>null</code> 779 * @throws StringIndexOutOfBoundsException if offset is out of bounds 780 * @see #insert(int, char[], int, int) 781 */ 782 public StringBuilder insert(int offset, char[] data) 783 { 784 return insert(offset, data, 0, data.length); 785 } 786 787 /** 788 * Insert the <code>String</code> value of the argument into this 789 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 790 * to <code>String</code>. 791 * 792 * @param offset the place to insert in this buffer 793 * @param bool the <code>boolean</code> to convert and insert 794 * @return this <code>StringBuilder</code> 795 * @throws StringIndexOutOfBoundsException if offset is out of bounds 796 * @see String#valueOf(boolean) 797 */ 798 public StringBuilder insert(int offset, boolean bool) 799 { 800 return insert(offset, bool ? "true" : "false"); 801 } 802 803 /** 804 * Insert the <code>char</code> argument into this <code>StringBuilder</code>. 805 * 806 * @param offset the place to insert in this buffer 807 * @param ch the <code>char</code> to insert 808 * @return this <code>StringBuilder</code> 809 * @throws StringIndexOutOfBoundsException if offset is out of bounds 810 */ 811 public StringBuilder insert(int offset, char ch) 812 { 813 if (offset < 0 || offset > count) 814 throw new StringIndexOutOfBoundsException(offset); 815 ensureCapacity(count + 1); 816 System.arraycopy(value, offset, value, offset + 1, count - offset); 817 value[offset] = ch; 818 count++; 819 return this; 820 } 821 822 /** 823 * Insert the <code>String</code> value of the argument into this 824 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 825 * to <code>String</code>. 826 * 827 * @param offset the place to insert in this buffer 828 * @param inum the <code>int</code> to convert and insert 829 * @return this <code>StringBuilder</code> 830 * @throws StringIndexOutOfBoundsException if offset is out of bounds 831 * @see String#valueOf(int) 832 */ 833 public StringBuilder insert(int offset, int inum) 834 { 835 return insert(offset, String.valueOf(inum)); 836 } 837 838 /** 839 * Insert the <code>String</code> value of the argument into this 840 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 841 * to <code>String</code>. 842 * 843 * @param offset the place to insert in this buffer 844 * @param lnum the <code>long</code> to convert and insert 845 * @return this <code>StringBuilder</code> 846 * @throws StringIndexOutOfBoundsException if offset is out of bounds 847 * @see String#valueOf(long) 848 */ 849 public StringBuilder insert(int offset, long lnum) 850 { 851 return insert(offset, Long.toString(lnum, 10)); 852 } 853 854 /** 855 * Insert the <code>String</code> value of the argument into this 856 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 857 * to <code>String</code>. 858 * 859 * @param offset the place to insert in this buffer 860 * @param fnum the <code>float</code> to convert and insert 861 * @return this <code>StringBuilder</code> 862 * @throws StringIndexOutOfBoundsException if offset is out of bounds 863 * @see String#valueOf(float) 864 */ 865 public StringBuilder insert(int offset, float fnum) 866 { 867 return insert(offset, Float.toString(fnum)); 868 } 869 870 /** 871 * Insert the <code>String</code> value of the argument into this 872 * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert 873 * to <code>String</code>. 874 * 875 * @param offset the place to insert in this buffer 876 * @param dnum the <code>double</code> to convert and insert 877 * @return this <code>StringBuilder</code> 878 * @throws StringIndexOutOfBoundsException if offset is out of bounds 879 * @see String#valueOf(double) 880 */ 881 public StringBuilder insert(int offset, double dnum) 882 { 883 return insert(offset, Double.toString(dnum)); 884 } 885 886 /** 887 * Finds the first instance of a substring in this StringBuilder. 888 * 889 * @param str String to find 890 * @return location (base 0) of the String, or -1 if not found 891 * @throws NullPointerException if str is null 892 * @see #indexOf(String, int) 893 */ 894 public int indexOf(String str) 895 { 896 return indexOf(str, 0); 897 } 898 899 /** 900 * Finds the first instance of a String in this StringBuilder, starting at 901 * a given index. If starting index is less than 0, the search starts at 902 * the beginning of this String. If the starting index is greater than the 903 * length of this String, or the substring is not found, -1 is returned. 904 * 905 * @param str String to find 906 * @param fromIndex index to start the search 907 * @return location (base 0) of the String, or -1 if not found 908 * @throws NullPointerException if str is null 909 */ 910 public int indexOf(String str, int fromIndex) 911 { 912 if (fromIndex < 0) 913 fromIndex = 0; 914 int limit = count - str.count; 915 for ( ; fromIndex <= limit; fromIndex++) 916 if (regionMatches(fromIndex, str)) 917 return fromIndex; 918 return -1; 919 } 920 921 /** 922 * Finds the last instance of a substring in this StringBuilder. 923 * 924 * @param str String to find 925 * @return location (base 0) of the String, or -1 if not found 926 * @throws NullPointerException if str is null 927 * @see #lastIndexOf(String, int) 928 */ 929 public int lastIndexOf(String str) 930 { 931 return lastIndexOf(str, count - str.count); 932 } 933 934 /** 935 * Finds the last instance of a String in this StringBuilder, starting at a 936 * given index. If starting index is greater than the maximum valid index, 937 * then the search begins at the end of this String. If the starting index 938 * is less than zero, or the substring is not found, -1 is returned. 939 * 940 * @param str String to find 941 * @param fromIndex index to start the search 942 * @return location (base 0) of the String, or -1 if not found 943 * @throws NullPointerException if str is null 944 */ 945 public int lastIndexOf(String str, int fromIndex) 946 { 947 fromIndex = Math.min(fromIndex, count - str.count); 948 for ( ; fromIndex >= 0; fromIndex--) 949 if (regionMatches(fromIndex, str)) 950 return fromIndex; 951 return -1; 952 } 953 954 /** 955 * Reverse the characters in this StringBuilder. The same sequence of 956 * characters exists, but in the reverse index ordering. 957 * 958 * @return this <code>StringBuilder</code> 959 */ 960 public StringBuilder reverse() 961 { 962 // Call ensureCapacity to enforce copy-on-write. 963 ensureCapacity(count); 964 for (int i = count >> 1, j = count - i; --i >= 0; ++j) 965 { 966 char c = value[i]; 967 value[i] = value[j]; 968 value[j] = c; 969 } 970 return this; 971 } 972 973 /** 974 * Convert this <code>StringBuilder</code> to a <code>String</code>. The 975 * String is composed of the characters currently in this StringBuilder. Note 976 * that the result is a copy, and that future modifications to this buffer 977 * do not affect the String. 978 * 979 * @return the characters in this StringBuilder 980 */ 981 public String toString() 982 { 983 return new String(this); 984 } 985 986 /** 987 * Predicate which determines if a substring of this matches another String 988 * starting at a specified offset for each String and continuing for a 989 * specified length. This is more efficient than creating a String to call 990 * indexOf on. 991 * 992 * @param toffset index to start comparison at for this String 993 * @param other non-null String to compare to region of this 994 * @return true if regions match, false otherwise 995 * @see #indexOf(String, int) 996 * @see #lastIndexOf(String, int) 997 * @see String#regionMatches(boolean, int, String, int, int) 998 */ 999 // GCJ LOCAL: Native to access String internals properly. 1000 private native boolean regionMatches(int toffset, String other); 1001 1002 /** 1003 * Get the code point at the specified index. This is like #charAt(int), 1004 * but if the character is the start of a surrogate pair, and the 1005 * following character completes the pair, then the corresponding 1006 * supplementary code point is returned. 1007 * @param index the index of the codepoint to get, starting at 0 1008 * @return the codepoint at the specified index 1009 * @throws IndexOutOfBoundsException if index is negative or >= length() 1010 * @since 1.5 1011 */ 1012 public int codePointAt(int index) 1013 { 1014 return Character.codePointAt(value, index, count); 1015 } 1016 1017 /** 1018 * Get the code point before the specified index. This is like 1019 * #codePointAt(int), but checks the characters at <code>index-1</code> and 1020 * <code>index-2</code> to see if they form a supplementary code point. 1021 * @param index the index just past the codepoint to get, starting at 0 1022 * @return the codepoint at the specified index 1023 * @throws IndexOutOfBoundsException if index is negative or >= length() 1024 * @since 1.5 1025 */ 1026 public int codePointBefore(int index) 1027 { 1028 // Character.codePointBefore() doesn't perform this check. We 1029 // could use the CharSequence overload, but this is just as easy. 1030 if (index >= count) 1031 throw new IndexOutOfBoundsException(); 1032 return Character.codePointBefore(value, index, 1); 1033 } 1034 1035 /** 1036 * Returns the number of Unicode code points in the specified sub sequence. 1037 * Surrogate pairs count as one code point. 1038 * @param beginIndex the start of the subarray 1039 * @param endIndex the index after the last char in the subarray 1040 * @return the number of code points 1041 * @throws IndexOutOfBoundsException if beginIndex is less than zero or 1042 * greater than endIndex or if endIndex is greater than the length of this 1043 * StringBuilder 1044 */ 1045 public int codePointCount(int beginIndex,int endIndex) 1046 { 1047 if (beginIndex < 0 || beginIndex > endIndex || endIndex > count) 1048 throw new IndexOutOfBoundsException("invalid indices: " + beginIndex 1049 + ", " + endIndex); 1050 return Character.codePointCount(value, beginIndex, endIndex - beginIndex); 1051 } 1052 1053 public void trimToSize() 1054 { 1055 if (count < value.length) 1056 { 1057 char[] newValue = new char[count]; 1058 System.arraycopy(value, 0, newValue, 0, count); 1059 value = newValue; 1060 } 1061 } 1062 }