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