GNU Classpath (0.95) | |
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: public final class StringBuilder 78: implements Serializable, CharSequence, Appendable 79: { 80: // Implementation note: if you change this class, you usually will 81: // want to change StringBuffer as well. 82: 83: /** 84: * For compatability with Sun's JDK 85: */ 86: private static final long serialVersionUID = 4383685877147921099L; 87: 88: /** 89: * Index of next available character (and thus the size of the current 90: * string contents). Note that this has permissions set this way so that 91: * String can get the value. 92: * 93: * @serial the number of characters in the buffer 94: */ 95: int count; 96: 97: /** 98: * The buffer. Note that this has permissions set this way so that String 99: * 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: VMSystem.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: VMSystem.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: VMSystem.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: VMSystem.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: // This is native in libgcj, for efficiency. 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: VMSystem.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: VMSystem.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: VMSystem.arraycopy(value, offset, value, offset + len, count - offset); 680: VMSystem.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: VMSystem.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: VMSystem.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: VMSystem.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: private boolean regionMatches(int toffset, String other) 1000: { 1001: int len = other.count; 1002: int index = other.offset; 1003: while (--len >= 0) 1004: if (value[toffset++] != other.value[index++]) 1005: return false; 1006: return true; 1007: } 1008: 1009: /** 1010: * Get the code point at the specified index. This is like #charAt(int), 1011: * but if the character is the start of a surrogate pair, and the 1012: * following character completes the pair, then the corresponding 1013: * supplementary code point is returned. 1014: * @param index the index of the codepoint to get, starting at 0 1015: * @return the codepoint at the specified index 1016: * @throws IndexOutOfBoundsException if index is negative or >= length() 1017: * @since 1.5 1018: */ 1019: public int codePointAt(int index) 1020: { 1021: return Character.codePointAt(value, index, count); 1022: } 1023: 1024: /** 1025: * Get the code point before the specified index. This is like 1026: * #codePointAt(int), but checks the characters at <code>index-1</code> and 1027: * <code>index-2</code> to see if they form a supplementary code point. 1028: * @param index the index just past the codepoint to get, starting at 0 1029: * @return the codepoint at the specified index 1030: * @throws IndexOutOfBoundsException if index is negative or >= length() 1031: * @since 1.5 1032: */ 1033: public int codePointBefore(int index) 1034: { 1035: // Character.codePointBefore() doesn't perform this check. We 1036: // could use the CharSequence overload, but this is just as easy. 1037: if (index >= count) 1038: throw new IndexOutOfBoundsException(); 1039: return Character.codePointBefore(value, index, 1); 1040: } 1041: 1042: /** 1043: * Returns the number of Unicode code points in the specified sub sequence. 1044: * Surrogate pairs count as one code point. 1045: * @param beginIndex the start of the subarray 1046: * @param endIndex the index after the last char in the subarray 1047: * @return the number of code points 1048: * @throws IndexOutOfBoundsException if beginIndex is less than zero or 1049: * greater than endIndex or if endIndex is greater than the length of this 1050: * StringBuilder 1051: */ 1052: public int codePointCount(int beginIndex,int endIndex) 1053: { 1054: if (beginIndex < 0 || beginIndex > endIndex || endIndex > count) 1055: throw new IndexOutOfBoundsException("invalid indices: " + beginIndex 1056: + ", " + endIndex); 1057: return Character.codePointCount(value, beginIndex, endIndex - beginIndex); 1058: } 1059: 1060: public void trimToSize() 1061: { 1062: if (count < value.length) 1063: { 1064: char[] newValue = new char[count]; 1065: VMSystem.arraycopy(value, 0, newValue, 0, count); 1066: value = newValue; 1067: } 1068: } 1069: }
GNU Classpath (0.95) |