Frames | No Frames |
1: /* StringBuffer.java -- Growable strings 2: Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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>StringBuffer</code> represents a changeable <code>String</code>. 45: * It provides the operations required to modify the 46: * <code>StringBuffer</code>, including insert, replace, delete, append, 47: * and reverse. It is thread-safe; meaning that all modifications to a buffer 48: * are in synchronized methods. 49: * 50: * <p><code>StringBuffer</code>s are variable-length in nature, so even if 51: * you initialize them to a certain size, they can still grow larger than 52: * that. <em>Capacity</em> indicates the number of characters the 53: * <code>StringBuffer</code> can have in it before it has to grow (growing 54: * the char array is an expensive operation involving <code>new</code>). 55: * 56: * <p>Incidentally, compilers often implement the String operator "+" 57: * by using a <code>StringBuffer</code> operation:<br> 58: * <code>a + b</code><br> 59: * is the same as<br> 60: * <code>new StringBuffer().append(a).append(b).toString()</code>. 61: * 62: * <p>Classpath's StringBuffer is capable of sharing memory with Strings for 63: * efficiency. This will help when a StringBuffer is converted to a String 64: * and the StringBuffer is not changed after that (quite common when performing 65: * string concatenation). 66: * 67: * @author Paul Fisher 68: * @author John Keiser 69: * @author Tom Tromey 70: * @author Eric Blake (ebb9@email.byu.edu) 71: * @see String 72: * @since 1.0 73: * @status updated to 1.4 74: */ 75: public final class StringBuffer implements Serializable, CharSequence 76: { 77: /** 78: * Compatible with JDK 1.0+. 79: */ 80: private static final long serialVersionUID = 3388685877147921107L; 81: 82: /** 83: * Index of next available character (and thus the size of the current 84: * string contents). Note that this has permissions set this way so that 85: * String can get the value. 86: * 87: * @serial the number of characters in the buffer 88: */ 89: int count; 90: 91: /** 92: * The buffer. Note that this has permissions set this way so that String 93: * can get the value. 94: * 95: * @serial the buffer 96: */ 97: char[] value; 98: 99: /** 100: * True if the buffer is shared with another object (StringBuffer or 101: * String); this means the buffer must be copied before writing to it again. 102: * Note that this has permissions set this way so that String can get the 103: * value. 104: * 105: * @serial whether the buffer is shared 106: */ 107: boolean shared; 108: 109: /** 110: * The default capacity of a buffer. 111: */ 112: private static final int DEFAULT_CAPACITY = 16; 113: 114: /** 115: * Create a new StringBuffer with default capacity 16. 116: */ 117: public StringBuffer() 118: { 119: this(DEFAULT_CAPACITY); 120: } 121: 122: /** 123: * Create an empty <code>StringBuffer</code> with the specified initial 124: * capacity. 125: * 126: * @param capacity the initial capacity 127: * @throws NegativeArraySizeException if capacity is negative 128: */ 129: public StringBuffer(int capacity) 130: { 131: value = new char[capacity]; 132: } 133: 134: /** 135: * Create a new <code>StringBuffer</code> with the characters in the 136: * specified <code>String</code>. Initial capacity will be the size of the 137: * String plus 16. 138: * 139: * @param str the <code>String</code> to convert 140: * @throws NullPointerException if str is null 141: */ 142: public StringBuffer(String str) 143: { 144: // Unfortunately, because the size is 16 larger, we cannot share. 145: count = str.count; 146: value = new char[count + DEFAULT_CAPACITY]; 147: str.getChars(0, count, value, 0); 148: } 149: 150: /** 151: * Create a new <code>StringBuffer</code> with the characters from the 152: * specified <code>CharSequence</code>. Initial capacity will be the 153: * size of the CharSequence plus 16. 154: * 155: * @param sequence the <code>String</code> to convert 156: * @throws NullPointerException if str is null 157: * 158: * @since 1.5 159: */ 160: public StringBuffer(CharSequence sequence) 161: { 162: count = Math.max(0, sequence.length()); 163: value = new char[count + DEFAULT_CAPACITY]; 164: for (int i = 0; i < count; ++i) 165: value[i] = sequence.charAt(i); 166: } 167: 168: /** 169: * Get the length of the <code>String</code> this <code>StringBuffer</code> 170: * would create. Not to be confused with the <em>capacity</em> of the 171: * <code>StringBuffer</code>. 172: * 173: * @return the length of this <code>StringBuffer</code> 174: * @see #capacity() 175: * @see #setLength(int) 176: */ 177: public synchronized int length() 178: { 179: return count; 180: } 181: 182: /** 183: * Get the total number of characters this <code>StringBuffer</code> can 184: * support before it must be grown. Not to be confused with <em>length</em>. 185: * 186: * @return the capacity of this <code>StringBuffer</code> 187: * @see #length() 188: * @see #ensureCapacity(int) 189: */ 190: public synchronized int capacity() 191: { 192: return value.length; 193: } 194: 195: /** 196: * Increase the capacity of this <code>StringBuffer</code>. This will 197: * ensure that an expensive growing operation will not occur until 198: * <code>minimumCapacity</code> is reached. The buffer is grown to the 199: * larger of <code>minimumCapacity</code> and 200: * <code>capacity() * 2 + 2</code>, if it is not already large enough. 201: * 202: * @param minimumCapacity the new capacity 203: * @see #capacity() 204: */ 205: public synchronized void ensureCapacity(int minimumCapacity) 206: { 207: ensureCapacity_unsynchronized(minimumCapacity); 208: } 209: 210: /** 211: * Set the length of this StringBuffer. If the new length is greater than 212: * the current length, all the new characters are set to '\0'. If the new 213: * length is less than the current length, the first <code>newLength</code> 214: * characters of the old array will be preserved, and the remaining 215: * characters are truncated. 216: * 217: * @param newLength the new length 218: * @throws IndexOutOfBoundsException if the new length is negative 219: * (while unspecified, this is a StringIndexOutOfBoundsException) 220: * @see #length() 221: */ 222: public synchronized void setLength(int newLength) 223: { 224: if (newLength < 0) 225: throw new StringIndexOutOfBoundsException(newLength); 226: 227: int valueLength = value.length; 228: 229: /* Always call ensureCapacity_unsynchronized in order to preserve 230: copy-on-write semantics. */ 231: ensureCapacity_unsynchronized(newLength); 232: 233: if (newLength < valueLength) 234: { 235: /* If the StringBuffer's value just grew, then we know that 236: value is newly allocated and the region between count and 237: newLength is filled with '\0'. */ 238: count = newLength; 239: } 240: else 241: { 242: /* The StringBuffer's value doesn't need to grow. However, 243: we should clear out any cruft that may exist. */ 244: while (count < newLength) 245: value[count++] = '\0'; 246: } 247: } 248: 249: /** 250: * Get the character at the specified index. 251: * 252: * @param index the index of the character to get, starting at 0 253: * @return the character at the specified index 254: * @throws IndexOutOfBoundsException if index is negative or >= length() 255: */ 256: public synchronized char charAt(int index) 257: { 258: if (index < 0 || index >= count) 259: throw new StringIndexOutOfBoundsException(index); 260: return value[index]; 261: } 262: 263: /** 264: * Get the code point at the specified index. This is like #charAt(int), 265: * but if the character is the start of a surrogate pair, and the 266: * following character completes the pair, then the corresponding 267: * supplementary code point is returned. 268: * @param index the index of the codepoint to get, starting at 0 269: * @return the codepoint at the specified index 270: * @throws IndexOutOfBoundsException if index is negative or >= length() 271: * @since 1.5 272: */ 273: public synchronized int codePointAt(int index) 274: { 275: return Character.codePointAt(value, index, count); 276: } 277: 278: /** 279: * Get the code point before the specified index. This is like 280: * #codePointAt(int), but checks the characters at <code>index-1</code> and 281: * <code>index-2</code> to see if they form a supplementary code point. 282: * @param index the index just past the codepoint to get, starting at 0 283: * @return the codepoint at the specified index 284: * @throws IndexOutOfBoundsException if index is negative or >= length() 285: * @since 1.5 286: */ 287: public synchronized int codePointBefore(int index) 288: { 289: // Character.codePointBefore() doesn't perform this check. We 290: // could use the CharSequence overload, but this is just as easy. 291: if (index >= count) 292: throw new IndexOutOfBoundsException(); 293: return Character.codePointBefore(value, index, 1); 294: } 295: 296: /** 297: * Get the specified array of characters. <code>srcOffset - srcEnd</code> 298: * characters will be copied into the array you pass in. 299: * 300: * @param srcOffset the index to start copying from (inclusive) 301: * @param srcEnd the index to stop copying from (exclusive) 302: * @param dst the array to copy into 303: * @param dstOffset the index to start copying into 304: * @throws NullPointerException if dst is null 305: * @throws IndexOutOfBoundsException if any source or target indices are 306: * out of range (while unspecified, source problems cause a 307: * StringIndexOutOfBoundsException, and dest problems cause an 308: * ArrayIndexOutOfBoundsException) 309: * @see System#arraycopy(Object, int, Object, int, int) 310: */ 311: public synchronized void getChars(int srcOffset, int srcEnd, 312: char[] dst, int dstOffset) 313: { 314: if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset) 315: throw new StringIndexOutOfBoundsException(); 316: System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset); 317: } 318: 319: /** 320: * Set the character at the specified index. 321: * 322: * @param index the index of the character to set starting at 0 323: * @param ch the value to set that character to 324: * @throws IndexOutOfBoundsException if index is negative or >= length() 325: * (while unspecified, this is a StringIndexOutOfBoundsException) 326: */ 327: public synchronized void setCharAt(int index, char ch) 328: { 329: if (index < 0 || index >= count) 330: throw new StringIndexOutOfBoundsException(index); 331: // Call ensureCapacity to enforce copy-on-write. 332: ensureCapacity_unsynchronized(count); 333: value[index] = ch; 334: } 335: 336: /** 337: * Append the <code>String</code> value of the argument to this 338: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 339: * to <code>String</code>. 340: * 341: * @param obj the <code>Object</code> to convert and append 342: * @return this <code>StringBuffer</code> 343: * @see String#valueOf(Object) 344: * @see #append(String) 345: */ 346: public StringBuffer append(Object obj) 347: { 348: return append(obj == null ? "null" : obj.toString()); 349: } 350: 351: /** 352: * Append the <code>String</code> to this <code>StringBuffer</code>. If 353: * str is null, the String "null" is appended. 354: * 355: * @param str the <code>String</code> to append 356: * @return this <code>StringBuffer</code> 357: */ 358: public synchronized StringBuffer append(String str) 359: { 360: if (str == null) 361: str = "null"; 362: int len = str.count; 363: ensureCapacity_unsynchronized(count + len); 364: str.getChars(0, len, value, count); 365: count += len; 366: return this; 367: } 368: 369: /** 370: * Append the <code>StringBuffer</code> value of the argument to this 371: * <code>StringBuffer</code>. This behaves the same as 372: * <code>append((Object) stringBuffer)</code>, except it is more efficient. 373: * 374: * @param stringBuffer the <code>StringBuffer</code> to convert and append 375: * @return this <code>StringBuffer</code> 376: * @see #append(Object) 377: * @since 1.4 378: */ 379: public synchronized StringBuffer append(StringBuffer stringBuffer) 380: { 381: if (stringBuffer == null) 382: return append("null"); 383: synchronized (stringBuffer) 384: { 385: int len = stringBuffer.count; 386: ensureCapacity_unsynchronized(count + len); 387: System.arraycopy(stringBuffer.value, 0, value, count, len); 388: count += len; 389: } 390: return this; 391: } 392: 393: /** 394: * Append the <code>CharSequence</code> value of the argument to this 395: * <code>StringBuffer</code>. 396: * 397: * @param sequence the <code>CharSequence</code> to append 398: * @return this <code>StringBuffer</code> 399: * @see #append(Object) 400: * @since 1.5 401: */ 402: public synchronized StringBuffer append(CharSequence sequence) 403: { 404: if (sequence == null) 405: sequence = "null"; 406: return append(sequence, 0, sequence.length()); 407: } 408: 409: /** 410: * Append the specified subsequence of the <code>CharSequence</code> 411: * argument to this <code>StringBuffer</code>. 412: * 413: * @param sequence the <code>CharSequence</code> to append 414: * @param start the starting index 415: * @param end one past the ending index 416: * @return this <code>StringBuffer</code> 417: * @see #append(Object) 418: * @since 1.5 419: */ 420: public synchronized StringBuffer append(CharSequence sequence, 421: int start, int end) 422: { 423: if (sequence == null) 424: sequence = "null"; 425: if (start < 0 || end < 0 || start > end || end > sequence.length()) 426: throw new IndexOutOfBoundsException(); 427: ensureCapacity_unsynchronized(this.count + end - start); 428: for (int i = start; i < end; ++i) 429: value[count++] = sequence.charAt(i); 430: return this; 431: } 432: 433: /** 434: * Append the <code>char</code> array to this <code>StringBuffer</code>. 435: * This is similar (but more efficient) than 436: * <code>append(new String(data))</code>, except in the case of null. 437: * 438: * @param data the <code>char[]</code> to append 439: * @return this <code>StringBuffer</code> 440: * @throws NullPointerException if <code>str</code> is <code>null</code> 441: * @see #append(char[], int, int) 442: */ 443: public StringBuffer append(char[] data) 444: { 445: return append(data, 0, data.length); 446: } 447: 448: /** 449: * Append part of the <code>char</code> array to this 450: * <code>StringBuffer</code>. This is similar (but more efficient) than 451: * <code>append(new String(data, offset, count))</code>, except in the case 452: * of null. 453: * 454: * @param data the <code>char[]</code> to append 455: * @param offset the start location in <code>str</code> 456: * @param count the number of characters to get from <code>str</code> 457: * @return this <code>StringBuffer</code> 458: * @throws NullPointerException if <code>str</code> is <code>null</code> 459: * @throws IndexOutOfBoundsException if offset or count is out of range 460: * (while unspecified, this is a StringIndexOutOfBoundsException) 461: */ 462: public synchronized StringBuffer append(char[] data, int offset, int count) 463: { 464: if (offset < 0 || count < 0 || offset > data.length - count) 465: throw new StringIndexOutOfBoundsException(); 466: ensureCapacity_unsynchronized(this.count + count); 467: System.arraycopy(data, offset, value, this.count, count); 468: this.count += count; 469: return this; 470: } 471: 472: /** 473: * Append the <code>String</code> value of the argument to this 474: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 475: * to <code>String</code>. 476: * 477: * @param bool the <code>boolean</code> to convert and append 478: * @return this <code>StringBuffer</code> 479: * @see String#valueOf(boolean) 480: */ 481: public StringBuffer append(boolean bool) 482: { 483: return append(bool ? "true" : "false"); 484: } 485: 486: /** 487: * Append the <code>char</code> to this <code>StringBuffer</code>. 488: * 489: * @param ch the <code>char</code> to append 490: * @return this <code>StringBuffer</code> 491: */ 492: public synchronized StringBuffer append(char ch) 493: { 494: ensureCapacity_unsynchronized(count + 1); 495: value[count++] = ch; 496: return this; 497: } 498: 499: /** 500: * Append the code point to this <code>StringBuffer</code>. 501: * This is like #append(char), but will append two characters 502: * if a supplementary code point is given. 503: * 504: * @param code the code point to append 505: * @return this <code>StringBuffer</code> 506: * @see Character#toChars(int, char[], int) 507: * @since 1.5 508: */ 509: public synchronized StringBuffer appendCodePoint(int code) 510: { 511: int len = Character.charCount(code); 512: ensureCapacity_unsynchronized(count + len); 513: Character.toChars(code, value, count); 514: count += len; 515: return this; 516: } 517: 518: /** 519: * Append the <code>String</code> value of the argument to this 520: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 521: * to <code>String</code>. 522: * 523: * @param inum the <code>int</code> to convert and append 524: * @return this <code>StringBuffer</code> 525: * @see String#valueOf(int) 526: */ 527: // GCJ LOCAL: this is native for efficiency. 528: public native StringBuffer append (int inum); 529: 530: /** 531: * Append the <code>String</code> value of the argument to this 532: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 533: * to <code>String</code>. 534: * 535: * @param lnum the <code>long</code> to convert and append 536: * @return this <code>StringBuffer</code> 537: * @see String#valueOf(long) 538: */ 539: public StringBuffer append(long lnum) 540: { 541: return append(Long.toString(lnum, 10)); 542: } 543: 544: /** 545: * Append the <code>String</code> value of the argument to this 546: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 547: * to <code>String</code>. 548: * 549: * @param fnum the <code>float</code> to convert and append 550: * @return this <code>StringBuffer</code> 551: * @see String#valueOf(float) 552: */ 553: public StringBuffer append(float fnum) 554: { 555: return append(Float.toString(fnum)); 556: } 557: 558: /** 559: * Append the <code>String</code> value of the argument to this 560: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 561: * to <code>String</code>. 562: * 563: * @param dnum the <code>double</code> to convert and append 564: * @return this <code>StringBuffer</code> 565: * @see String#valueOf(double) 566: */ 567: public StringBuffer append(double dnum) 568: { 569: return append(Double.toString(dnum)); 570: } 571: 572: /** 573: * Delete characters from this <code>StringBuffer</code>. 574: * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is 575: * harmless for end to be larger than length(). 576: * 577: * @param start the first character to delete 578: * @param end the index after the last character to delete 579: * @return this <code>StringBuffer</code> 580: * @throws StringIndexOutOfBoundsException if start or end are out of bounds 581: * @since 1.2 582: */ 583: public synchronized StringBuffer delete(int start, int end) 584: { 585: if (start < 0 || start > count || start > end) 586: throw new StringIndexOutOfBoundsException(start); 587: if (end > count) 588: end = count; 589: // This will unshare if required. 590: ensureCapacity_unsynchronized(count); 591: if (count - end != 0) 592: System.arraycopy(value, end, value, start, count - end); 593: count -= end - start; 594: return this; 595: } 596: 597: /** 598: * Delete a character from this <code>StringBuffer</code>. 599: * 600: * @param index the index of the character to delete 601: * @return this <code>StringBuffer</code> 602: * @throws StringIndexOutOfBoundsException if index is out of bounds 603: * @since 1.2 604: */ 605: public StringBuffer deleteCharAt(int index) 606: { 607: return delete(index, index + 1); 608: } 609: 610: /** 611: * Replace characters between index <code>start</code> (inclusive) and 612: * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> 613: * is larger than the size of this StringBuffer, all characters after 614: * <code>start</code> are replaced. 615: * 616: * @param start the beginning index of characters to delete (inclusive) 617: * @param end the ending index of characters to delete (exclusive) 618: * @param str the new <code>String</code> to insert 619: * @return this <code>StringBuffer</code> 620: * @throws StringIndexOutOfBoundsException if start or end are out of bounds 621: * @throws NullPointerException if str is null 622: * @since 1.2 623: */ 624: public synchronized StringBuffer replace(int start, int end, String str) 625: { 626: if (start < 0 || start > count || start > end) 627: throw new StringIndexOutOfBoundsException(start); 628: 629: int len = str.count; 630: // Calculate the difference in 'count' after the replace. 631: int delta = len - (end > count ? count : end) + start; 632: ensureCapacity_unsynchronized(count + delta); 633: 634: if (delta != 0 && end < count) 635: System.arraycopy(value, end, value, end + delta, count - end); 636: 637: str.getChars(0, len, value, start); 638: count += delta; 639: return this; 640: } 641: 642: /** 643: * Creates a substring of this StringBuffer, starting at a specified index 644: * and ending at the end of this StringBuffer. 645: * 646: * @param beginIndex index to start substring (base 0) 647: * @return new String which is a substring of this StringBuffer 648: * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds 649: * @see #substring(int, int) 650: * @since 1.2 651: */ 652: public String substring(int beginIndex) 653: { 654: return substring(beginIndex, count); 655: } 656: 657: /** 658: * Creates a substring of this StringBuffer, starting at a specified index 659: * and ending at one character before a specified index. This is implemented 660: * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy 661: * the CharSequence interface. 662: * 663: * @param beginIndex index to start at (inclusive, base 0) 664: * @param endIndex index to end at (exclusive) 665: * @return new String which is a substring of this StringBuffer 666: * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of 667: * bounds 668: * @see #substring(int, int) 669: * @since 1.4 670: */ 671: public CharSequence subSequence(int beginIndex, int endIndex) 672: { 673: return substring(beginIndex, endIndex); 674: } 675: 676: /** 677: * Creates a substring of this StringBuffer, starting at a specified index 678: * and ending at one character before a specified index. 679: * 680: * @param beginIndex index to start at (inclusive, base 0) 681: * @param endIndex index to end at (exclusive) 682: * @return new String which is a substring of this StringBuffer 683: * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out 684: * of bounds 685: * @since 1.2 686: */ 687: public synchronized String substring(int beginIndex, int endIndex) 688: { 689: int len = endIndex - beginIndex; 690: if (beginIndex < 0 || endIndex > count || endIndex < beginIndex) 691: throw new StringIndexOutOfBoundsException(); 692: if (len == 0) 693: return ""; 694: // Don't copy unless substring is smaller than 1/4 of the buffer. 695: boolean share_buffer = ((len << 2) >= value.length); 696: if (share_buffer) 697: this.shared = true; 698: // Package constructor avoids an array copy. 699: return new String(value, beginIndex, len, share_buffer); 700: } 701: 702: /** 703: * Insert a subarray of the <code>char[]</code> argument into this 704: * <code>StringBuffer</code>. 705: * 706: * @param offset the place to insert in this buffer 707: * @param str the <code>char[]</code> to insert 708: * @param str_offset the index in <code>str</code> to start inserting from 709: * @param len the number of characters to insert 710: * @return this <code>StringBuffer</code> 711: * @throws NullPointerException if <code>str</code> is <code>null</code> 712: * @throws StringIndexOutOfBoundsException if any index is out of bounds 713: * @since 1.2 714: */ 715: public synchronized StringBuffer insert(int offset, 716: char[] str, int str_offset, int len) 717: { 718: if (offset < 0 || offset > count || len < 0 719: || str_offset < 0 || str_offset > str.length - len) 720: throw new StringIndexOutOfBoundsException(); 721: ensureCapacity_unsynchronized(count + len); 722: System.arraycopy(value, offset, value, offset + len, count - offset); 723: System.arraycopy(str, str_offset, value, offset, len); 724: count += len; 725: return this; 726: } 727: 728: /** 729: * Insert the <code>String</code> value of the argument into this 730: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 731: * to <code>String</code>. 732: * 733: * @param offset the place to insert in this buffer 734: * @param obj the <code>Object</code> to convert and insert 735: * @return this <code>StringBuffer</code> 736: * @exception StringIndexOutOfBoundsException if offset is out of bounds 737: * @see String#valueOf(Object) 738: */ 739: public StringBuffer insert(int offset, Object obj) 740: { 741: return insert(offset, obj == null ? "null" : obj.toString()); 742: } 743: 744: /** 745: * Insert the <code>String</code> argument into this 746: * <code>StringBuffer</code>. If str is null, the String "null" is used 747: * instead. 748: * 749: * @param offset the place to insert in this buffer 750: * @param str the <code>String</code> to insert 751: * @return this <code>StringBuffer</code> 752: * @throws StringIndexOutOfBoundsException if offset is out of bounds 753: */ 754: public synchronized StringBuffer insert(int offset, String str) 755: { 756: if (offset < 0 || offset > count) 757: throw new StringIndexOutOfBoundsException(offset); 758: if (str == null) 759: str = "null"; 760: int len = str.count; 761: ensureCapacity_unsynchronized(count + len); 762: System.arraycopy(value, offset, value, offset + len, count - offset); 763: str.getChars(0, len, value, offset); 764: count += len; 765: return this; 766: } 767: 768: /** 769: * Insert the <code>CharSequence</code> argument into this 770: * <code>StringBuffer</code>. If the sequence is null, the String 771: * "null" is used instead. 772: * 773: * @param offset the place to insert in this buffer 774: * @param sequence the <code>CharSequence</code> to insert 775: * @return this <code>StringBuffer</code> 776: * @throws IndexOutOfBoundsException if offset is out of bounds 777: * @since 1.5 778: */ 779: public synchronized StringBuffer insert(int offset, CharSequence sequence) 780: { 781: if (sequence == null) 782: sequence = "null"; 783: return insert(offset, sequence, 0, sequence.length()); 784: } 785: 786: /** 787: * Insert a subsequence of the <code>CharSequence</code> argument into this 788: * <code>StringBuffer</code>. If the sequence is null, the String 789: * "null" is used instead. 790: * 791: * @param offset the place to insert in this buffer 792: * @param sequence the <code>CharSequence</code> to insert 793: * @param start the starting index of the subsequence 794: * @param end one past the ending index of the subsequence 795: * @return this <code>StringBuffer</code> 796: * @throws IndexOutOfBoundsException if offset, start, 797: * or end are out of bounds 798: * @since 1.5 799: */ 800: public synchronized StringBuffer insert(int offset, CharSequence sequence, 801: int start, int end) 802: { 803: if (sequence == null) 804: sequence = "null"; 805: if (start < 0 || end < 0 || start > end || end > sequence.length()) 806: throw new IndexOutOfBoundsException(); 807: int len = end - start; 808: ensureCapacity_unsynchronized(count + len); 809: System.arraycopy(value, offset, value, offset + len, count - offset); 810: for (int i = start; i < end; ++i) 811: value[offset++] = sequence.charAt(i); 812: count += len; 813: return this; 814: } 815: 816: /** 817: * Insert the <code>char[]</code> argument into this 818: * <code>StringBuffer</code>. 819: * 820: * @param offset the place to insert in this buffer 821: * @param data the <code>char[]</code> to insert 822: * @return this <code>StringBuffer</code> 823: * @throws NullPointerException if <code>data</code> is <code>null</code> 824: * @throws StringIndexOutOfBoundsException if offset is out of bounds 825: * @see #insert(int, char[], int, int) 826: */ 827: public StringBuffer insert(int offset, char[] data) 828: { 829: return insert(offset, data, 0, data.length); 830: } 831: 832: /** 833: * Insert the <code>String</code> value of the argument into this 834: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 835: * to <code>String</code>. 836: * 837: * @param offset the place to insert in this buffer 838: * @param bool the <code>boolean</code> to convert and insert 839: * @return this <code>StringBuffer</code> 840: * @throws StringIndexOutOfBoundsException if offset is out of bounds 841: * @see String#valueOf(boolean) 842: */ 843: public StringBuffer insert(int offset, boolean bool) 844: { 845: return insert(offset, bool ? "true" : "false"); 846: } 847: 848: /** 849: * Insert the <code>char</code> argument into this <code>StringBuffer</code>. 850: * 851: * @param offset the place to insert in this buffer 852: * @param ch the <code>char</code> to insert 853: * @return this <code>StringBuffer</code> 854: * @throws StringIndexOutOfBoundsException if offset is out of bounds 855: */ 856: public synchronized StringBuffer insert(int offset, char ch) 857: { 858: if (offset < 0 || offset > count) 859: throw new StringIndexOutOfBoundsException(offset); 860: ensureCapacity_unsynchronized(count + 1); 861: System.arraycopy(value, offset, value, offset + 1, count - offset); 862: value[offset] = ch; 863: count++; 864: return this; 865: } 866: 867: /** 868: * Insert the <code>String</code> value of the argument into this 869: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 870: * to <code>String</code>. 871: * 872: * @param offset the place to insert in this buffer 873: * @param inum the <code>int</code> to convert and insert 874: * @return this <code>StringBuffer</code> 875: * @throws StringIndexOutOfBoundsException if offset is out of bounds 876: * @see String#valueOf(int) 877: */ 878: public StringBuffer insert(int offset, int inum) 879: { 880: return insert(offset, String.valueOf(inum)); 881: } 882: 883: /** 884: * Insert the <code>String</code> value of the argument into this 885: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 886: * to <code>String</code>. 887: * 888: * @param offset the place to insert in this buffer 889: * @param lnum the <code>long</code> to convert and insert 890: * @return this <code>StringBuffer</code> 891: * @throws StringIndexOutOfBoundsException if offset is out of bounds 892: * @see String#valueOf(long) 893: */ 894: public StringBuffer insert(int offset, long lnum) 895: { 896: return insert(offset, Long.toString(lnum, 10)); 897: } 898: 899: /** 900: * Insert the <code>String</code> value of the argument into this 901: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 902: * to <code>String</code>. 903: * 904: * @param offset the place to insert in this buffer 905: * @param fnum the <code>float</code> to convert and insert 906: * @return this <code>StringBuffer</code> 907: * @throws StringIndexOutOfBoundsException if offset is out of bounds 908: * @see String#valueOf(float) 909: */ 910: public StringBuffer insert(int offset, float fnum) 911: { 912: return insert(offset, Float.toString(fnum)); 913: } 914: 915: /** 916: * Insert the <code>String</code> value of the argument into this 917: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 918: * to <code>String</code>. 919: * 920: * @param offset the place to insert in this buffer 921: * @param dnum the <code>double</code> to convert and insert 922: * @return this <code>StringBuffer</code> 923: * @throws StringIndexOutOfBoundsException if offset is out of bounds 924: * @see String#valueOf(double) 925: */ 926: public StringBuffer insert(int offset, double dnum) 927: { 928: return insert(offset, Double.toString(dnum)); 929: } 930: 931: /** 932: * Finds the first instance of a substring in this StringBuffer. 933: * 934: * @param str String to find 935: * @return location (base 0) of the String, or -1 if not found 936: * @throws NullPointerException if str is null 937: * @see #indexOf(String, int) 938: * @since 1.4 939: */ 940: public int indexOf(String str) 941: { 942: return indexOf(str, 0); 943: } 944: 945: /** 946: * Finds the first instance of a String in this StringBuffer, starting at 947: * a given index. If starting index is less than 0, the search starts at 948: * the beginning of this String. If the starting index is greater than the 949: * length of this String, or the substring is not found, -1 is returned. 950: * 951: * @param str String to find 952: * @param fromIndex index to start the search 953: * @return location (base 0) of the String, or -1 if not found 954: * @throws NullPointerException if str is null 955: * @since 1.4 956: */ 957: public synchronized int indexOf(String str, int fromIndex) 958: { 959: if (fromIndex < 0) 960: fromIndex = 0; 961: int limit = count - str.count; 962: for ( ; fromIndex <= limit; fromIndex++) 963: if (regionMatches(fromIndex, str)) 964: return fromIndex; 965: return -1; 966: } 967: 968: /** 969: * Finds the last instance of a substring in this StringBuffer. 970: * 971: * @param str String to find 972: * @return location (base 0) of the String, or -1 if not found 973: * @throws NullPointerException if str is null 974: * @see #lastIndexOf(String, int) 975: * @since 1.4 976: */ 977: public int lastIndexOf(String str) 978: { 979: return lastIndexOf(str, count - str.count); 980: } 981: 982: /** 983: * Finds the last instance of a String in this StringBuffer, starting at a 984: * given index. If starting index is greater than the maximum valid index, 985: * then the search begins at the end of this String. If the starting index 986: * is less than zero, or the substring is not found, -1 is returned. 987: * 988: * @param str String to find 989: * @param fromIndex index to start the search 990: * @return location (base 0) of the String, or -1 if not found 991: * @throws NullPointerException if str is null 992: * @since 1.4 993: */ 994: public synchronized int lastIndexOf(String str, int fromIndex) 995: { 996: fromIndex = Math.min(fromIndex, count - str.count); 997: for ( ; fromIndex >= 0; fromIndex--) 998: if (regionMatches(fromIndex, str)) 999: return fromIndex; 1000: return -1; 1001: } 1002: 1003: /** 1004: * Reverse the characters in this StringBuffer. The same sequence of 1005: * characters exists, but in the reverse index ordering. 1006: * 1007: * @return this <code>StringBuffer</code> 1008: */ 1009: public synchronized StringBuffer reverse() 1010: { 1011: // Call ensureCapacity to enforce copy-on-write. 1012: ensureCapacity_unsynchronized(count); 1013: for (int i = count >> 1, j = count - i; --i >= 0; ++j) 1014: { 1015: char c = value[i]; 1016: value[i] = value[j]; 1017: value[j] = c; 1018: } 1019: return this; 1020: } 1021: 1022: /** 1023: * Convert this <code>StringBuffer</code> to a <code>String</code>. The 1024: * String is composed of the characters currently in this StringBuffer. Note 1025: * that the result is a copy, and that future modifications to this buffer 1026: * do not affect the String. 1027: * 1028: * @return the characters in this StringBuffer 1029: */ 1030: public String toString() 1031: { 1032: // The string will set this.shared = true. 1033: return new String(this); 1034: } 1035: 1036: /** 1037: * This may reduce the amount of memory used by the StringBuffer, 1038: * by resizing the internal array to remove unused space. However, 1039: * this method is not required to resize, so this behavior cannot 1040: * be relied upon. 1041: * @since 1.5 1042: */ 1043: public synchronized void trimToSize() 1044: { 1045: int wouldSave = value.length - count; 1046: // Some random heuristics: if we save less than 20 characters, who 1047: // cares. 1048: if (wouldSave < 20) 1049: return; 1050: // If we save more than 200 characters, shrink. 1051: // If we save more than 1/4 of the buffer, shrink. 1052: if (wouldSave > 200 || wouldSave * 4 > value.length) 1053: { 1054: char[] newValue = new char[count]; 1055: System.arraycopy(value, 0, newValue, 0, count); 1056: value = newValue; 1057: } 1058: } 1059: 1060: /** 1061: * Return the number of code points between two indices in the 1062: * <code>StringBuffer</code>. An unpaired surrogate counts as a 1063: * code point for this purpose. Characters outside the indicated 1064: * range are not examined, even if the range ends in the middle of a 1065: * surrogate pair. 1066: * 1067: * @param start the starting index 1068: * @param end one past the ending index 1069: * @return the number of code points 1070: * @since 1.5 1071: */ 1072: public synchronized int codePointCount(int start, int end) 1073: { 1074: if (start < 0 || end >= count || start > end) 1075: throw new StringIndexOutOfBoundsException(); 1076: 1077: int count = 0; 1078: while (start < end) 1079: { 1080: char base = value[start]; 1081: if (base < Character.MIN_HIGH_SURROGATE 1082: || base > Character.MAX_HIGH_SURROGATE 1083: || start == end 1084: || start == count 1085: || value[start + 1] < Character.MIN_LOW_SURROGATE 1086: || value[start + 1] > Character.MAX_LOW_SURROGATE) 1087: { 1088: // Nothing. 1089: } 1090: else 1091: { 1092: // Surrogate pair. 1093: ++start; 1094: } 1095: ++start; 1096: ++count; 1097: } 1098: return count; 1099: } 1100: 1101: /** 1102: * Starting at the given index, this counts forward by the indicated 1103: * number of code points, and then returns the resulting index. An 1104: * unpaired surrogate counts as a single code point for this 1105: * purpose. 1106: * 1107: * @param start the starting index 1108: * @param codePoints the number of code points 1109: * @return the resulting index 1110: * @since 1.5 1111: */ 1112: public synchronized int offsetByCodePoints(int start, int codePoints) 1113: { 1114: while (codePoints > 0) 1115: { 1116: char base = value[start]; 1117: if (base < Character.MIN_HIGH_SURROGATE 1118: || base > Character.MAX_HIGH_SURROGATE 1119: || start == count 1120: || value[start + 1] < Character.MIN_LOW_SURROGATE 1121: || value[start + 1] > Character.MAX_LOW_SURROGATE) 1122: { 1123: // Nothing. 1124: } 1125: else 1126: { 1127: // Surrogate pair. 1128: ++start; 1129: } 1130: ++start; 1131: --codePoints; 1132: } 1133: return start; 1134: } 1135: 1136: /** 1137: * An unsynchronized version of ensureCapacity, used internally to avoid 1138: * the cost of a second lock on the same object. This also has the side 1139: * effect of duplicating the array, if it was shared (to form copy-on-write 1140: * semantics). 1141: * 1142: * @param minimumCapacity the minimum capacity 1143: * @see #ensureCapacity(int) 1144: */ 1145: private void ensureCapacity_unsynchronized(int minimumCapacity) 1146: { 1147: if (shared || minimumCapacity > value.length) 1148: { 1149: // We don't want to make a larger vector when `shared' is 1150: // set. If we do, then setLength becomes very inefficient 1151: // when repeatedly reusing a StringBuffer in a loop. 1152: int max = (minimumCapacity > value.length 1153: ? value.length * 2 + 2 1154: : value.length); 1155: minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); 1156: char[] nb = new char[minimumCapacity]; 1157: System.arraycopy(value, 0, nb, 0, count); 1158: value = nb; 1159: shared = false; 1160: } 1161: } 1162: 1163: /** 1164: * Predicate which determines if a substring of this matches another String 1165: * starting at a specified offset for each String and continuing for a 1166: * specified length. This is more efficient than creating a String to call 1167: * indexOf on. 1168: * 1169: * @param toffset index to start comparison at for this String 1170: * @param other non-null String to compare to region of this 1171: * @return true if regions match, false otherwise 1172: * @see #indexOf(String, int) 1173: * @see #lastIndexOf(String, int) 1174: * @see String#regionMatches(boolean, int, String, int, int) 1175: */ 1176: // GCJ LOCAL: native for gcj. 1177: private native boolean regionMatches(int toffset, String other); 1178: }