GNU Classpath (0.17) | ||
Frames | No Frames |
1: /* StringBuffer.java -- 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>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: * Get the length of the <code>String</code> this <code>StringBuffer</code> 152: * would create. Not to be confused with the <em>capacity</em> of the 153: * <code>StringBuffer</code>. 154: * 155: * @return the length of this <code>StringBuffer</code> 156: * @see #capacity() 157: * @see #setLength(int) 158: */ 159: public synchronized int length() 160: { 161: return count; 162: } 163: 164: /** 165: * Get the total number of characters this <code>StringBuffer</code> can 166: * support before it must be grown. Not to be confused with <em>length</em>. 167: * 168: * @return the capacity of this <code>StringBuffer</code> 169: * @see #length() 170: * @see #ensureCapacity(int) 171: */ 172: public synchronized int capacity() 173: { 174: return value.length; 175: } 176: 177: /** 178: * Increase the capacity of this <code>StringBuffer</code>. This will 179: * ensure that an expensive growing operation will not occur until 180: * <code>minimumCapacity</code> is reached. The buffer is grown to the 181: * larger of <code>minimumCapacity</code> and 182: * <code>capacity() * 2 + 2</code>, if it is not already large enough. 183: * 184: * @param minimumCapacity the new capacity 185: * @see #capacity() 186: */ 187: public synchronized void ensureCapacity(int minimumCapacity) 188: { 189: ensureCapacity_unsynchronized(minimumCapacity); 190: } 191: 192: /** 193: * Set the length of this StringBuffer. If the new length is greater than 194: * the current length, all the new characters are set to '\0'. If the new 195: * length is less than the current length, the first <code>newLength</code> 196: * characters of the old array will be preserved, and the remaining 197: * characters are truncated. 198: * 199: * @param newLength the new length 200: * @throws IndexOutOfBoundsException if the new length is negative 201: * (while unspecified, this is a StringIndexOutOfBoundsException) 202: * @see #length() 203: */ 204: public synchronized void setLength(int newLength) 205: { 206: if (newLength < 0) 207: throw new StringIndexOutOfBoundsException(newLength); 208: 209: int valueLength = value.length; 210: 211: /* Always call ensureCapacity_unsynchronized in order to preserve 212: copy-on-write semantics. */ 213: ensureCapacity_unsynchronized(newLength); 214: 215: if (newLength < valueLength) 216: { 217: /* If the StringBuffer's value just grew, then we know that 218: value is newly allocated and the region between count and 219: newLength is filled with '\0'. */ 220: count = newLength; 221: } 222: else 223: { 224: /* The StringBuffer's value doesn't need to grow. However, 225: we should clear out any cruft that may exist. */ 226: while (count < newLength) 227: value[count++] = '\0'; 228: } 229: } 230: 231: /** 232: * Get the character at the specified index. 233: * 234: * @param index the index of the character to get, starting at 0 235: * @return the character at the specified index 236: * @throws IndexOutOfBoundsException if index is negative or >= length() 237: * (while unspecified, this is a StringIndexOutOfBoundsException) 238: */ 239: public synchronized char charAt(int index) 240: { 241: if (index < 0 || index >= count) 242: throw new StringIndexOutOfBoundsException(index); 243: return value[index]; 244: } 245: 246: /** 247: * Get the specified array of characters. <code>srcOffset - srcEnd</code> 248: * characters will be copied into the array you pass in. 249: * 250: * @param srcOffset the index to start copying from (inclusive) 251: * @param srcEnd the index to stop copying from (exclusive) 252: * @param dst the array to copy into 253: * @param dstOffset the index to start copying into 254: * @throws NullPointerException if dst is null 255: * @throws IndexOutOfBoundsException if any source or target indices are 256: * out of range (while unspecified, source problems cause a 257: * StringIndexOutOfBoundsException, and dest problems cause an 258: * ArrayIndexOutOfBoundsException) 259: * @see System#arraycopy(Object, int, Object, int, int) 260: */ 261: public synchronized void getChars(int srcOffset, int srcEnd, 262: char[] dst, int dstOffset) 263: { 264: if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset) 265: throw new StringIndexOutOfBoundsException(); 266: VMSystem.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset); 267: } 268: 269: /** 270: * Set the character at the specified index. 271: * 272: * @param index the index of the character to set starting at 0 273: * @param ch the value to set that character to 274: * @throws IndexOutOfBoundsException if index is negative or >= length() 275: * (while unspecified, this is a StringIndexOutOfBoundsException) 276: */ 277: public synchronized void setCharAt(int index, char ch) 278: { 279: if (index < 0 || index >= count) 280: throw new StringIndexOutOfBoundsException(index); 281: // Call ensureCapacity to enforce copy-on-write. 282: ensureCapacity_unsynchronized(count); 283: value[index] = ch; 284: } 285: 286: /** 287: * Append the <code>String</code> value of the argument to this 288: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 289: * to <code>String</code>. 290: * 291: * @param obj the <code>Object</code> to convert and append 292: * @return this <code>StringBuffer</code> 293: * @see String#valueOf(Object) 294: * @see #append(String) 295: */ 296: public StringBuffer append(Object obj) 297: { 298: return append(obj == null ? "null" : obj.toString()); 299: } 300: 301: /** 302: * Append the <code>String</code> to this <code>StringBuffer</code>. If 303: * str is null, the String "null" is appended. 304: * 305: * @param str the <code>String</code> to append 306: * @return this <code>StringBuffer</code> 307: */ 308: public synchronized StringBuffer append(String str) 309: { 310: if (str == null) 311: str = "null"; 312: int len = str.count; 313: ensureCapacity_unsynchronized(count + len); 314: str.getChars(0, len, value, count); 315: count += len; 316: return this; 317: } 318: 319: /** 320: * Append the <code>StringBuffer</code> value of the argument to this 321: * <code>StringBuffer</code>. This behaves the same as 322: * <code>append((Object) stringBuffer)</code>, except it is more efficient. 323: * 324: * @param stringBuffer the <code>StringBuffer</code> to convert and append 325: * @return this <code>StringBuffer</code> 326: * @see #append(Object) 327: * @since 1.4 328: */ 329: public synchronized StringBuffer append(StringBuffer stringBuffer) 330: { 331: if (stringBuffer == null) 332: return append("null"); 333: synchronized (stringBuffer) 334: { 335: int len = stringBuffer.count; 336: ensureCapacity_unsynchronized(count + len); 337: VMSystem.arraycopy(stringBuffer.value, 0, value, count, len); 338: count += len; 339: } 340: return this; 341: } 342: 343: /** 344: * Append the <code>char</code> array to this <code>StringBuffer</code>. 345: * This is similar (but more efficient) than 346: * <code>append(new String(data))</code>, except in the case of null. 347: * 348: * @param data the <code>char[]</code> to append 349: * @return this <code>StringBuffer</code> 350: * @throws NullPointerException if <code>str</code> is <code>null</code> 351: * @see #append(char[], int, int) 352: */ 353: public StringBuffer append(char[] data) 354: { 355: return append(data, 0, data.length); 356: } 357: 358: /** 359: * Append part of the <code>char</code> array to this 360: * <code>StringBuffer</code>. This is similar (but more efficient) than 361: * <code>append(new String(data, offset, count))</code>, except in the case 362: * of null. 363: * 364: * @param data the <code>char[]</code> to append 365: * @param offset the start location in <code>str</code> 366: * @param count the number of characters to get from <code>str</code> 367: * @return this <code>StringBuffer</code> 368: * @throws NullPointerException if <code>str</code> is <code>null</code> 369: * @throws IndexOutOfBoundsException if offset or count is out of range 370: * (while unspecified, this is a StringIndexOutOfBoundsException) 371: */ 372: public synchronized StringBuffer append(char[] data, int offset, int count) 373: { 374: if (offset < 0 || count < 0 || offset > data.length - count) 375: throw new StringIndexOutOfBoundsException(); 376: ensureCapacity_unsynchronized(this.count + count); 377: VMSystem.arraycopy(data, offset, value, this.count, count); 378: this.count += count; 379: return this; 380: } 381: 382: /** 383: * Append the <code>String</code> value of the argument to this 384: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 385: * to <code>String</code>. 386: * 387: * @param bool the <code>boolean</code> to convert and append 388: * @return this <code>StringBuffer</code> 389: * @see String#valueOf(boolean) 390: */ 391: public StringBuffer append(boolean bool) 392: { 393: return append(bool ? "true" : "false"); 394: } 395: 396: /** 397: * Append the <code>char</code> to this <code>StringBuffer</code>. 398: * 399: * @param ch the <code>char</code> to append 400: * @return this <code>StringBuffer</code> 401: */ 402: public synchronized StringBuffer append(char ch) 403: { 404: ensureCapacity_unsynchronized(count + 1); 405: value[count++] = ch; 406: return this; 407: } 408: 409: /** 410: * Append the <code>String</code> value of the argument to this 411: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 412: * to <code>String</code>. 413: * 414: * @param inum the <code>int</code> to convert and append 415: * @return this <code>StringBuffer</code> 416: * @see String#valueOf(int) 417: */ 418: // This is native in libgcj, for efficiency. 419: public StringBuffer append(int inum) 420: { 421: return append(String.valueOf(inum)); 422: } 423: 424: /** 425: * Append the <code>String</code> value of the argument to this 426: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 427: * to <code>String</code>. 428: * 429: * @param lnum the <code>long</code> to convert and append 430: * @return this <code>StringBuffer</code> 431: * @see String#valueOf(long) 432: */ 433: public StringBuffer append(long lnum) 434: { 435: return append(Long.toString(lnum, 10)); 436: } 437: 438: /** 439: * Append the <code>String</code> value of the argument to this 440: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 441: * to <code>String</code>. 442: * 443: * @param fnum the <code>float</code> to convert and append 444: * @return this <code>StringBuffer</code> 445: * @see String#valueOf(float) 446: */ 447: public StringBuffer append(float fnum) 448: { 449: return append(Float.toString(fnum)); 450: } 451: 452: /** 453: * Append the <code>String</code> value of the argument to this 454: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 455: * to <code>String</code>. 456: * 457: * @param dnum the <code>double</code> to convert and append 458: * @return this <code>StringBuffer</code> 459: * @see String#valueOf(double) 460: */ 461: public StringBuffer append(double dnum) 462: { 463: return append(Double.toString(dnum)); 464: } 465: 466: /** 467: * Delete characters from this <code>StringBuffer</code>. 468: * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is 469: * harmless for end to be larger than length(). 470: * 471: * @param start the first character to delete 472: * @param end the index after the last character to delete 473: * @return this <code>StringBuffer</code> 474: * @throws StringIndexOutOfBoundsException if start or end are out of bounds 475: * @since 1.2 476: */ 477: public synchronized StringBuffer delete(int start, int end) 478: { 479: if (start < 0 || start > count || start > end) 480: throw new StringIndexOutOfBoundsException(start); 481: if (end > count) 482: end = count; 483: // This will unshare if required. 484: ensureCapacity_unsynchronized(count); 485: if (count - end != 0) 486: VMSystem.arraycopy(value, end, value, start, count - end); 487: count -= end - start; 488: return this; 489: } 490: 491: /** 492: * Delete a character from this <code>StringBuffer</code>. 493: * 494: * @param index the index of the character to delete 495: * @return this <code>StringBuffer</code> 496: * @throws StringIndexOutOfBoundsException if index is out of bounds 497: * @since 1.2 498: */ 499: public StringBuffer deleteCharAt(int index) 500: { 501: return delete(index, index + 1); 502: } 503: 504: /** 505: * Replace characters between index <code>start</code> (inclusive) and 506: * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> 507: * is larger than the size of this StringBuffer, all characters after 508: * <code>start</code> are replaced. 509: * 510: * @param start the beginning index of characters to delete (inclusive) 511: * @param end the ending index of characters to delete (exclusive) 512: * @param str the new <code>String</code> to insert 513: * @return this <code>StringBuffer</code> 514: * @throws StringIndexOutOfBoundsException if start or end are out of bounds 515: * @throws NullPointerException if str is null 516: * @since 1.2 517: */ 518: public synchronized StringBuffer replace(int start, int end, String str) 519: { 520: if (start < 0 || start > count || start > end) 521: throw new StringIndexOutOfBoundsException(start); 522: 523: int len = str.count; 524: // Calculate the difference in 'count' after the replace. 525: int delta = len - (end > count ? count : end) + start; 526: ensureCapacity_unsynchronized(count + delta); 527: 528: if (delta != 0 && end < count) 529: VMSystem.arraycopy(value, end, value, end + delta, count - end); 530: 531: str.getChars(0, len, value, start); 532: count += delta; 533: return this; 534: } 535: 536: /** 537: * Creates a substring of this StringBuffer, starting at a specified index 538: * and ending at the end of this StringBuffer. 539: * 540: * @param beginIndex index to start substring (base 0) 541: * @return new String which is a substring of this StringBuffer 542: * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds 543: * @see #substring(int, int) 544: * @since 1.2 545: */ 546: public String substring(int beginIndex) 547: { 548: return substring(beginIndex, count); 549: } 550: 551: /** 552: * Creates a substring of this StringBuffer, starting at a specified index 553: * and ending at one character before a specified index. This is implemented 554: * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy 555: * the CharSequence interface. 556: * 557: * @param beginIndex index to start at (inclusive, base 0) 558: * @param endIndex index to end at (exclusive) 559: * @return new String which is a substring of this StringBuffer 560: * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of 561: * bounds 562: * @see #substring(int, int) 563: * @since 1.4 564: */ 565: public CharSequence subSequence(int beginIndex, int endIndex) 566: { 567: return substring(beginIndex, endIndex); 568: } 569: 570: /** 571: * Creates a substring of this StringBuffer, starting at a specified index 572: * and ending at one character before a specified index. 573: * 574: * @param beginIndex index to start at (inclusive, base 0) 575: * @param endIndex index to end at (exclusive) 576: * @return new String which is a substring of this StringBuffer 577: * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out 578: * of bounds 579: * @since 1.2 580: */ 581: public synchronized String substring(int beginIndex, int endIndex) 582: { 583: int len = endIndex - beginIndex; 584: if (beginIndex < 0 || endIndex > count || endIndex < beginIndex) 585: throw new StringIndexOutOfBoundsException(); 586: if (len == 0) 587: return ""; 588: // Don't copy unless substring is smaller than 1/4 of the buffer. 589: boolean share_buffer = ((len << 2) >= value.length); 590: if (share_buffer) 591: this.shared = true; 592: // Package constructor avoids an array copy. 593: return new String(value, beginIndex, len, share_buffer); 594: } 595: 596: /** 597: * Insert a subarray of the <code>char[]</code> argument into this 598: * <code>StringBuffer</code>. 599: * 600: * @param offset the place to insert in this buffer 601: * @param str the <code>char[]</code> to insert 602: * @param str_offset the index in <code>str</code> to start inserting from 603: * @param len the number of characters to insert 604: * @return this <code>StringBuffer</code> 605: * @throws NullPointerException if <code>str</code> is <code>null</code> 606: * @throws StringIndexOutOfBoundsException if any index is out of bounds 607: * @since 1.2 608: */ 609: public synchronized StringBuffer insert(int offset, 610: char[] str, int str_offset, int len) 611: { 612: if (offset < 0 || offset > count || len < 0 613: || str_offset < 0 || str_offset > str.length - len) 614: throw new StringIndexOutOfBoundsException(); 615: ensureCapacity_unsynchronized(count + len); 616: VMSystem.arraycopy(value, offset, value, offset + len, count - offset); 617: VMSystem.arraycopy(str, str_offset, value, offset, len); 618: count += len; 619: return this; 620: } 621: 622: /** 623: * Insert the <code>String</code> value of the argument into this 624: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 625: * to <code>String</code>. 626: * 627: * @param offset the place to insert in this buffer 628: * @param obj the <code>Object</code> to convert and insert 629: * @return this <code>StringBuffer</code> 630: * @exception StringIndexOutOfBoundsException if offset is out of bounds 631: * @see String#valueOf(Object) 632: */ 633: public StringBuffer insert(int offset, Object obj) 634: { 635: return insert(offset, obj == null ? "null" : obj.toString()); 636: } 637: 638: /** 639: * Insert the <code>String</code> argument into this 640: * <code>StringBuffer</code>. If str is null, the String "null" is used 641: * instead. 642: * 643: * @param offset the place to insert in this buffer 644: * @param str the <code>String</code> to insert 645: * @return this <code>StringBuffer</code> 646: * @throws StringIndexOutOfBoundsException if offset is out of bounds 647: */ 648: public synchronized StringBuffer insert(int offset, String str) 649: { 650: if (offset < 0 || offset > count) 651: throw new StringIndexOutOfBoundsException(offset); 652: if (str == null) 653: str = "null"; 654: int len = str.count; 655: ensureCapacity_unsynchronized(count + len); 656: VMSystem.arraycopy(value, offset, value, offset + len, count - offset); 657: str.getChars(0, len, value, offset); 658: count += len; 659: return this; 660: } 661: 662: /** 663: * Insert the <code>char[]</code> argument into this 664: * <code>StringBuffer</code>. 665: * 666: * @param offset the place to insert in this buffer 667: * @param data the <code>char[]</code> to insert 668: * @return this <code>StringBuffer</code> 669: * @throws NullPointerException if <code>data</code> is <code>null</code> 670: * @throws StringIndexOutOfBoundsException if offset is out of bounds 671: * @see #insert(int, char[], int, int) 672: */ 673: public StringBuffer insert(int offset, char[] data) 674: { 675: return insert(offset, data, 0, data.length); 676: } 677: 678: /** 679: * Insert the <code>String</code> value of the argument into this 680: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 681: * to <code>String</code>. 682: * 683: * @param offset the place to insert in this buffer 684: * @param bool the <code>boolean</code> to convert and insert 685: * @return this <code>StringBuffer</code> 686: * @throws StringIndexOutOfBoundsException if offset is out of bounds 687: * @see String#valueOf(boolean) 688: */ 689: public StringBuffer insert(int offset, boolean bool) 690: { 691: return insert(offset, bool ? "true" : "false"); 692: } 693: 694: /** 695: * Insert the <code>char</code> argument into this <code>StringBuffer</code>. 696: * 697: * @param offset the place to insert in this buffer 698: * @param ch the <code>char</code> to insert 699: * @return this <code>StringBuffer</code> 700: * @throws StringIndexOutOfBoundsException if offset is out of bounds 701: */ 702: public synchronized StringBuffer insert(int offset, char ch) 703: { 704: if (offset < 0 || offset > count) 705: throw new StringIndexOutOfBoundsException(offset); 706: ensureCapacity_unsynchronized(count + 1); 707: VMSystem.arraycopy(value, offset, value, offset + 1, count - offset); 708: value[offset] = ch; 709: count++; 710: return this; 711: } 712: 713: /** 714: * Insert the <code>String</code> value of the argument into this 715: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 716: * to <code>String</code>. 717: * 718: * @param offset the place to insert in this buffer 719: * @param inum the <code>int</code> to convert and insert 720: * @return this <code>StringBuffer</code> 721: * @throws StringIndexOutOfBoundsException if offset is out of bounds 722: * @see String#valueOf(int) 723: */ 724: public StringBuffer insert(int offset, int inum) 725: { 726: return insert(offset, String.valueOf(inum)); 727: } 728: 729: /** 730: * Insert the <code>String</code> value of the argument into this 731: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 732: * to <code>String</code>. 733: * 734: * @param offset the place to insert in this buffer 735: * @param lnum the <code>long</code> to convert and insert 736: * @return this <code>StringBuffer</code> 737: * @throws StringIndexOutOfBoundsException if offset is out of bounds 738: * @see String#valueOf(long) 739: */ 740: public StringBuffer insert(int offset, long lnum) 741: { 742: return insert(offset, Long.toString(lnum, 10)); 743: } 744: 745: /** 746: * Insert the <code>String</code> value of the argument into this 747: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 748: * to <code>String</code>. 749: * 750: * @param offset the place to insert in this buffer 751: * @param fnum the <code>float</code> to convert and insert 752: * @return this <code>StringBuffer</code> 753: * @throws StringIndexOutOfBoundsException if offset is out of bounds 754: * @see String#valueOf(float) 755: */ 756: public StringBuffer insert(int offset, float fnum) 757: { 758: return insert(offset, Float.toString(fnum)); 759: } 760: 761: /** 762: * Insert the <code>String</code> value of the argument into this 763: * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert 764: * to <code>String</code>. 765: * 766: * @param offset the place to insert in this buffer 767: * @param dnum the <code>double</code> to convert and insert 768: * @return this <code>StringBuffer</code> 769: * @throws StringIndexOutOfBoundsException if offset is out of bounds 770: * @see String#valueOf(double) 771: */ 772: public StringBuffer insert(int offset, double dnum) 773: { 774: return insert(offset, Double.toString(dnum)); 775: } 776: 777: /** 778: * Finds the first instance of a substring in this StringBuffer. 779: * 780: * @param str String to find 781: * @return location (base 0) of the String, or -1 if not found 782: * @throws NullPointerException if str is null 783: * @see #indexOf(String, int) 784: * @since 1.4 785: */ 786: public int indexOf(String str) 787: { 788: return indexOf(str, 0); 789: } 790: 791: /** 792: * Finds the first instance of a String in this StringBuffer, starting at 793: * a given index. If starting index is less than 0, the search starts at 794: * the beginning of this String. If the starting index is greater than the 795: * length of this String, or the substring is not found, -1 is returned. 796: * 797: * @param str String to find 798: * @param fromIndex index to start the search 799: * @return location (base 0) of the String, or -1 if not found 800: * @throws NullPointerException if str is null 801: * @since 1.4 802: */ 803: public synchronized int indexOf(String str, int fromIndex) 804: { 805: if (fromIndex < 0) 806: fromIndex = 0; 807: int limit = count - str.count; 808: for ( ; fromIndex <= limit; fromIndex++) 809: if (regionMatches(fromIndex, str)) 810: return fromIndex; 811: return -1; 812: } 813: 814: /** 815: * Finds the last instance of a substring in this StringBuffer. 816: * 817: * @param str String to find 818: * @return location (base 0) of the String, or -1 if not found 819: * @throws NullPointerException if str is null 820: * @see #lastIndexOf(String, int) 821: * @since 1.4 822: */ 823: public int lastIndexOf(String str) 824: { 825: return lastIndexOf(str, count - str.count); 826: } 827: 828: /** 829: * Finds the last instance of a String in this StringBuffer, starting at a 830: * given index. If starting index is greater than the maximum valid index, 831: * then the search begins at the end of this String. If the starting index 832: * is less than zero, or the substring is not found, -1 is returned. 833: * 834: * @param str String to find 835: * @param fromIndex index to start the search 836: * @return location (base 0) of the String, or -1 if not found 837: * @throws NullPointerException if str is null 838: * @since 1.4 839: */ 840: public synchronized int lastIndexOf(String str, int fromIndex) 841: { 842: fromIndex = Math.min(fromIndex, count - str.count); 843: for ( ; fromIndex >= 0; fromIndex--) 844: if (regionMatches(fromIndex, str)) 845: return fromIndex; 846: return -1; 847: } 848: 849: /** 850: * Reverse the characters in this StringBuffer. The same sequence of 851: * characters exists, but in the reverse index ordering. 852: * 853: * @return this <code>StringBuffer</code> 854: */ 855: public synchronized StringBuffer reverse() 856: { 857: // Call ensureCapacity to enforce copy-on-write. 858: ensureCapacity_unsynchronized(count); 859: for (int i = count >> 1, j = count - i; --i >= 0; ++j) 860: { 861: char c = value[i]; 862: value[i] = value[j]; 863: value[j] = c; 864: } 865: return this; 866: } 867: 868: /** 869: * Convert this <code>StringBuffer</code> to a <code>String</code>. The 870: * String is composed of the characters currently in this StringBuffer. Note 871: * that the result is a copy, and that future modifications to this buffer 872: * do not affect the String. 873: * 874: * @return the characters in this StringBuffer 875: */ 876: public String toString() 877: { 878: // The string will set this.shared = true. 879: return new String(this); 880: } 881: 882: /** 883: * An unsynchronized version of ensureCapacity, used internally to avoid 884: * the cost of a second lock on the same object. This also has the side 885: * effect of duplicating the array, if it was shared (to form copy-on-write 886: * semantics). 887: * 888: * @param minimumCapacity the minimum capacity 889: * @see #ensureCapacity(int) 890: */ 891: private void ensureCapacity_unsynchronized(int minimumCapacity) 892: { 893: if (shared || minimumCapacity > value.length) 894: { 895: // We don't want to make a larger vector when `shared' is 896: // set. If we do, then setLength becomes very inefficient 897: // when repeatedly reusing a StringBuffer in a loop. 898: int max = (minimumCapacity > value.length 899: ? value.length * 2 + 2 900: : value.length); 901: minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); 902: char[] nb = new char[minimumCapacity]; 903: VMSystem.arraycopy(value, 0, nb, 0, count); 904: value = nb; 905: shared = false; 906: } 907: } 908: 909: /** 910: * Predicate which determines if a substring of this matches another String 911: * starting at a specified offset for each String and continuing for a 912: * specified length. This is more efficient than creating a String to call 913: * indexOf on. 914: * 915: * @param toffset index to start comparison at for this String 916: * @param other non-null String to compare to region of this 917: * @return true if regions match, false otherwise 918: * @see #indexOf(String, int) 919: * @see #lastIndexOf(String, int) 920: * @see String#regionMatches(boolean, int, String, int, int) 921: */ 922: private boolean regionMatches(int toffset, String other) 923: { 924: int len = other.count; 925: int index = other.offset; 926: while (--len >= 0) 927: if (value[toffset++] != other.value[index++]) 928: return false; 929: return true; 930: } 931: }
GNU Classpath (0.17) |