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