1 /* ClasspathStringBuffer.java -- Growable strings without locking or copying
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
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)
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.
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
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
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. */
39 package gnu.java.lang;
41 import gnu.classpath.SystemProperties;
43 import java.io.Serializable;
46 * This class is based on java.lang.AbstractStringBuffer but
47 * without the copying of the string by toString.
48 * If you modify this, please consider also modifying that code.
49 * This code is not thread-safe; limit its use to internal use within
52 public final class CPStringBuilder
53 implements Serializable, CharSequence, Appendable
57 * Index of next available character (and thus the size of the current
58 * string contents). Note that this has permissions set this way so that
59 * String can get the value.
61 * @serial the number of characters in the buffer
66 * The buffer. Note that this has permissions set this way so that String
74 * A flag to denote whether the string being created has been
75 * allocated to a {@link String} object. On construction,
76 * the character array, {@link #value} is referenced only
77 * by this class. Once {@link #toString()},
78 * {@link #substring(int)} or {@link #substring(int,int)}
79 * are called, the array is also referenced by a {@link String}
80 * object and this flag is set. Subsequent modifications to
81 * this buffer cause a new array to be allocated and the flag
84 private boolean allocated = false;
87 * The default capacity of a buffer.
88 * This can be configured using gnu.classpath.cpstringbuilder.capacity
90 private static final int DEFAULT_CAPACITY;
95 SystemProperties.getProperty("gnu.classpath.cpstringbuilder.capacity");
97 DEFAULT_CAPACITY = 32;
99 DEFAULT_CAPACITY = Integer.parseInt(cap);
103 * Create a new CPStringBuilder with the default capacity.
105 public CPStringBuilder()
107 this(DEFAULT_CAPACITY);
111 * Create an empty <code>CPStringBuilder</code> with the specified initial
114 * @param capacity the initial capacity
115 * @throws NegativeArraySizeException if capacity is negative
117 public CPStringBuilder(int capacity)
119 value = new char[capacity];
123 * Create a new <code>CPStringBuilder</code> with the characters in the
124 * specified <code>String</code>. Initial capacity will be the size of the
125 * String plus the default capacity.
127 * @param str the <code>String</code> to convert
128 * @throws NullPointerException if str is null
130 public CPStringBuilder(String str)
132 count = str.length();
133 value = new char[count + DEFAULT_CAPACITY];
134 str.getChars(0, count, value, 0);
138 * Create a new <code>CPStringBuilder</code> with the characters in the
139 * specified <code>StringBuffer</code>. Initial capacity will be the size of the
140 * String plus the default capacity.
142 * @param str the <code>String</code> to convert
143 * @throws NullPointerException if str is null
145 public CPStringBuilder(StringBuffer str)
147 count = str.length();
148 value = new char[count + DEFAULT_CAPACITY];
149 str.getChars(0, count, value, 0);
153 * Create a new <code>CPStringBuilder</code> with the characters in the
154 * specified <code>StringBuilder</code>. Initial capacity will be the size of the
155 * String plus the default capacity.
157 * @param str the <code>String</code> to convert
158 * @throws NullPointerException if str is null
160 public CPStringBuilder(StringBuilder str)
162 count = str.length();
163 value = new char[count + DEFAULT_CAPACITY];
164 str.getChars(0, count, value, 0);
168 * Create a new <code>CPStringBuilder</code> with the characters in the
169 * specified <code>CharSequence</code>. Initial capacity will be the
170 * length of the sequence plus the default capacity; if the sequence
171 * reports a length less than or equal to 0, then the initial capacity
172 * will be the default.
174 * @param seq the initializing <code>CharSequence</code>
175 * @throws NullPointerException if str is null
178 public CPStringBuilder(CharSequence seq)
180 int len = seq.length();
181 count = len <= 0 ? 0 : len;
182 value = new char[count + DEFAULT_CAPACITY];
183 for (int i = 0; i < len; ++i)
184 value[i] = seq.charAt(i);
188 * Set the length of this StringBuffer. If the new length is greater than
189 * the current length, all the new characters are set to '\0'. If the new
190 * length is less than the current length, the first <code>newLength</code>
191 * characters of the old array will be preserved, and the remaining
192 * characters are truncated.
194 * @param newLength the new length
195 * @throws IndexOutOfBoundsException if the new length is negative
196 * (while unspecified, this is a StringIndexOutOfBoundsException)
199 public void setLength(int newLength)
202 throw new StringIndexOutOfBoundsException(newLength);
204 int valueLength = value.length;
206 /* Always call ensureCapacity in order to preserve
207 copy-on-write semantics, except when the position
208 is simply being reset
211 ensureCapacity(newLength);
213 if (newLength < valueLength)
215 /* If the StringBuffer's value just grew, then we know that
216 value is newly allocated and the region between count and
217 newLength is filled with '\0'. */
222 /* The StringBuffer's value doesn't need to grow. However,
223 we should clear out any cruft that may exist. */
224 while (count < newLength)
225 value[count++] = '\0';
230 * Get the character at the specified index.
232 * @param index the index of the character to get, starting at 0
233 * @return the character at the specified index
234 * @throws IndexOutOfBoundsException if index is negative or >= length()
235 * (while unspecified, this is a StringIndexOutOfBoundsException)
237 public char charAt(int index)
239 if (index < 0 || index >= count)
240 throw new StringIndexOutOfBoundsException(index);
245 * Get the code point at the specified index. This is like #charAt(int),
246 * but if the character is the start of a surrogate pair, and the
247 * following character completes the pair, then the corresponding
248 * supplementary code point is returned.
249 * @param index the index of the codepoint to get, starting at 0
250 * @return the codepoint at the specified index
251 * @throws IndexOutOfBoundsException if index is negative or >= length()
254 public int codePointAt(int index)
256 return Character.codePointAt(value, index, count);
260 * Get the code point before the specified index. This is like
261 * #codePointAt(int), but checks the characters at <code>index-1</code> and
262 * <code>index-2</code> to see if they form a supplementary code point.
263 * @param index the index just past the codepoint to get, starting at 0
264 * @return the codepoint at the specified index
265 * @throws IndexOutOfBoundsException if index is negative or >= length()
268 public int codePointBefore(int index)
270 // Character.codePointBefore() doesn't perform this check. We
271 // could use the CharSequence overload, but this is just as easy.
273 throw new IndexOutOfBoundsException();
274 return Character.codePointBefore(value, index, 1);
278 * Get the specified array of characters. <code>srcOffset - srcEnd</code>
279 * characters will be copied into the array you pass in.
281 * @param srcOffset the index to start copying from (inclusive)
282 * @param srcEnd the index to stop copying from (exclusive)
283 * @param dst the array to copy into
284 * @param dstOffset the index to start copying into
285 * @throws NullPointerException if dst is null
286 * @throws IndexOutOfBoundsException if any source or target indices are
287 * out of range (while unspecified, source problems cause a
288 * StringIndexOutOfBoundsException, and dest problems cause an
289 * ArrayIndexOutOfBoundsException)
290 * @see System#arraycopy(Object, int, Object, int, int)
292 public void getChars(int srcOffset, int srcEnd,
293 char[] dst, int dstOffset)
295 if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
296 throw new StringIndexOutOfBoundsException();
297 System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
301 * Set the character at the specified index.
303 * @param index the index of the character to set starting at 0
304 * @param ch the value to set that character to
305 * @throws IndexOutOfBoundsException if index is negative or >= length()
306 * (while unspecified, this is a StringIndexOutOfBoundsException)
308 public void setCharAt(int index, char ch)
310 if (index < 0 || index >= count)
311 throw new StringIndexOutOfBoundsException(index);
312 // Call ensureCapacity to enforce copy-on-write.
313 ensureCapacity(count);
318 * Append the <code>String</code> value of the argument to this
319 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
320 * to <code>String</code>.
322 * @param obj the <code>Object</code> to convert and append
323 * @return this <code>StringBuffer</code>
324 * @see String#valueOf(Object)
325 * @see #append(String)
327 public CPStringBuilder append(Object obj)
329 return append(String.valueOf(obj));
333 * Append the <code>String</code> to this <code>StringBuffer</code>. If
334 * str is null, the String "null" is appended.
336 * @param str the <code>String</code> to append
337 * @return this <code>StringBuffer</code>
339 public CPStringBuilder append(String str)
343 int len = str.length();
344 ensureCapacity(count + len);
345 str.getChars(0, len, value, count);
351 * Append the <code>StringBuilder</code> value of the argument to this
352 * <code>StringBuilder</code>. This behaves the same as
353 * <code>append((Object) stringBuffer)</code>, except it is more efficient.
355 * @param stringBuffer the <code>StringBuilder</code> to convert and append
356 * @return this <code>StringBuilder</code>
357 * @see #append(Object)
359 public CPStringBuilder append(StringBuffer stringBuffer)
361 if (stringBuffer == null)
362 return append("null");
363 synchronized (stringBuffer)
365 int len = stringBuffer.length();
366 ensureCapacity(count + len);
367 stringBuffer.getChars(0, len, value, count);
374 * Append the <code>char</code> array to this <code>StringBuffer</code>.
375 * This is similar (but more efficient) than
376 * <code>append(new String(data))</code>, except in the case of null.
378 * @param data the <code>char[]</code> to append
379 * @return this <code>StringBuffer</code>
380 * @throws NullPointerException if <code>str</code> is <code>null</code>
381 * @see #append(char[], int, int)
383 public CPStringBuilder append(char[] data)
385 return append(data, 0, data.length);
389 * Append part of the <code>char</code> array to this
390 * <code>StringBuffer</code>. This is similar (but more efficient) than
391 * <code>append(new String(data, offset, count))</code>, except in the case
394 * @param data the <code>char[]</code> to append
395 * @param offset the start location in <code>str</code>
396 * @param count the number of characters to get from <code>str</code>
397 * @return this <code>StringBuffer</code>
398 * @throws NullPointerException if <code>str</code> is <code>null</code>
399 * @throws IndexOutOfBoundsException if offset or count is out of range
400 * (while unspecified, this is a StringIndexOutOfBoundsException)
402 public CPStringBuilder append(char[] data, int offset, int count)
404 if (offset < 0 || count < 0 || offset > data.length - count)
405 throw new StringIndexOutOfBoundsException();
406 ensureCapacity(this.count + count);
407 System.arraycopy(data, offset, value, this.count, count);
413 * Append the <code>String</code> value of the argument to this
414 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
415 * to <code>String</code>.
417 * @param bool the <code>boolean</code> to convert and append
418 * @return this <code>StringBuffer</code>
419 * @see String#valueOf(boolean)
421 public CPStringBuilder append(boolean bool)
423 return append(bool ? "true" : "false");
427 * Append the <code>char</code> to this <code>StringBuffer</code>.
429 * @param ch the <code>char</code> to append
430 * @return this <code>StringBuffer</code>
432 public CPStringBuilder append(char ch)
434 ensureCapacity(count + 1);
440 * Append the characters in the <code>CharSequence</code> to this
443 * @param seq the <code>CharSequence</code> providing the characters
444 * @return this <code>StringBuffer</code>
447 public CPStringBuilder append(CharSequence seq)
449 return append(seq, 0, seq.length());
453 * Append some characters from the <code>CharSequence</code> to this
454 * buffer. If the argument is null, the four characters "null" are
457 * @param seq the <code>CharSequence</code> providing the characters
458 * @param start the starting index
459 * @param end one past the final index
460 * @return this <code>StringBuffer</code>
463 public CPStringBuilder append(CharSequence seq, int start, int end)
466 return append("null");
469 ensureCapacity(count + end - start);
470 for (; start < end; ++start)
471 value[count++] = seq.charAt(start);
477 * Append the <code>String</code> value of the argument to this
478 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
479 * to <code>String</code>.
481 * @param inum the <code>int</code> to convert and append
482 * @return this <code>StringBuffer</code>
483 * @see String#valueOf(int)
485 // This is native in libgcj, for efficiency.
486 public CPStringBuilder append(int inum)
488 return append(String.valueOf(inum));
492 * Append the <code>String</code> value of the argument to this
493 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
494 * to <code>String</code>.
496 * @param lnum the <code>long</code> to convert and append
497 * @return this <code>StringBuffer</code>
498 * @see String#valueOf(long)
500 public CPStringBuilder append(long lnum)
502 return append(Long.toString(lnum, 10));
506 * Append the <code>String</code> value of the argument to this
507 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
508 * to <code>String</code>.
510 * @param fnum the <code>float</code> to convert and append
511 * @return this <code>StringBuffer</code>
512 * @see String#valueOf(float)
514 public CPStringBuilder append(float fnum)
516 return append(Float.toString(fnum));
520 * Append the <code>String</code> value of the argument to this
521 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
522 * to <code>String</code>.
524 * @param dnum the <code>double</code> to convert and append
525 * @return this <code>StringBuffer</code>
526 * @see String#valueOf(double)
528 public CPStringBuilder append(double dnum)
530 return append(Double.toString(dnum));
534 * Append the code point to this <code>StringBuffer</code>.
535 * This is like #append(char), but will append two characters
536 * if a supplementary code point is given.
538 * @param code the code point to append
539 * @return this <code>StringBuffer</code>
540 * @see Character#toChars(int, char[], int)
543 public CPStringBuilder appendCodePoint(int code)
545 int len = Character.charCount(code);
546 ensureCapacity(count + len);
547 Character.toChars(code, value, count);
553 * Delete characters from this <code>StringBuffer</code>.
554 * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
555 * harmless for end to be larger than length().
557 * @param start the first character to delete
558 * @param end the index after the last character to delete
559 * @return this <code>StringBuffer</code>
560 * @throws StringIndexOutOfBoundsException if start or end are out of bounds
563 public CPStringBuilder delete(int start, int end)
565 if (start < 0 || start > count || start > end)
566 throw new StringIndexOutOfBoundsException(start);
569 ensureCapacity(count);
570 if (count - end != 0)
571 System.arraycopy(value, end, value, start, count - end);
572 count -= end - start;
577 * Delete a character from this <code>StringBuffer</code>.
579 * @param index the index of the character to delete
580 * @return this <code>StringBuffer</code>
581 * @throws StringIndexOutOfBoundsException if index is out of bounds
584 public CPStringBuilder deleteCharAt(int index)
586 return delete(index, index + 1);
590 * Replace characters between index <code>start</code> (inclusive) and
591 * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
592 * is larger than the size of this StringBuffer, all characters after
593 * <code>start</code> are replaced.
595 * @param start the beginning index of characters to delete (inclusive)
596 * @param end the ending index of characters to delete (exclusive)
597 * @param str the new <code>String</code> to insert
598 * @return this <code>StringBuffer</code>
599 * @throws StringIndexOutOfBoundsException if start or end are out of bounds
600 * @throws NullPointerException if str is null
603 public CPStringBuilder replace(int start, int end, String str)
605 if (start < 0 || start > count || start > end)
606 throw new StringIndexOutOfBoundsException(start);
608 int len = str.length();
609 // Calculate the difference in 'count' after the replace.
610 int delta = len - (end > count ? count : end) + start;
611 ensureCapacity(count + delta);
613 if (delta != 0 && end < count)
614 System.arraycopy(value, end, value, end + delta, count - end);
616 str.getChars(0, len, value, start);
622 * Insert a subarray of the <code>char[]</code> argument into this
623 * <code>StringBuffer</code>.
625 * @param offset the place to insert in this buffer
626 * @param str the <code>char[]</code> to insert
627 * @param str_offset the index in <code>str</code> to start inserting from
628 * @param len the number of characters to insert
629 * @return this <code>StringBuffer</code>
630 * @throws NullPointerException if <code>str</code> is <code>null</code>
631 * @throws StringIndexOutOfBoundsException if any index is out of bounds
634 public CPStringBuilder insert(int offset, char[] str, int str_offset, int len)
636 if (offset < 0 || offset > count || len < 0
637 || str_offset < 0 || str_offset > str.length - len)
638 throw new StringIndexOutOfBoundsException();
639 ensureCapacity(count + len);
640 System.arraycopy(value, offset, value, offset + len, count - offset);
641 System.arraycopy(str, str_offset, value, offset, len);
647 * Insert the <code>String</code> value of the argument into this
648 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
649 * to <code>String</code>.
651 * @param offset the place to insert in this buffer
652 * @param obj the <code>Object</code> to convert and insert
653 * @return this <code>StringBuffer</code>
654 * @exception StringIndexOutOfBoundsException if offset is out of bounds
655 * @see String#valueOf(Object)
657 public CPStringBuilder insert(int offset, Object obj)
659 return insert(offset, obj == null ? "null" : obj.toString());
663 * Insert the <code>String</code> argument into this
664 * <code>StringBuffer</code>. If str is null, the String "null" is used
667 * @param offset the place to insert in this buffer
668 * @param str the <code>String</code> to insert
669 * @return this <code>StringBuffer</code>
670 * @throws StringIndexOutOfBoundsException if offset is out of bounds
672 public CPStringBuilder insert(int offset, String str)
674 if (offset < 0 || offset > count)
675 throw new StringIndexOutOfBoundsException(offset);
678 int len = str.length();
679 ensureCapacity(count + len);
680 System.arraycopy(value, offset, value, offset + len, count - offset);
681 str.getChars(0, len, value, offset);
687 * Insert the <code>CharSequence</code> argument into this
688 * <code>StringBuffer</code>. If the sequence is null, the String
689 * "null" is used instead.
691 * @param offset the place to insert in this buffer
692 * @param sequence the <code>CharSequence</code> to insert
693 * @return this <code>StringBuffer</code>
694 * @throws IndexOutOfBoundsException if offset is out of bounds
697 public CPStringBuilder insert(int offset, CharSequence sequence)
699 if (sequence == null)
701 return insert(offset, sequence, 0, sequence.length());
705 * Insert a subsequence of the <code>CharSequence</code> argument into this
706 * <code>StringBuffer</code>. If the sequence is null, the String
707 * "null" is used instead.
709 * @param offset the place to insert in this buffer
710 * @param sequence the <code>CharSequence</code> to insert
711 * @param start the starting index of the subsequence
712 * @param end one past the ending index of the subsequence
713 * @return this <code>StringBuffer</code>
714 * @throws IndexOutOfBoundsException if offset, start,
715 * or end are out of bounds
718 public CPStringBuilder insert(int offset, CharSequence sequence, int start, int end)
720 if (sequence == null)
722 if (start < 0 || end < 0 || start > end || end > sequence.length())
723 throw new IndexOutOfBoundsException();
724 int len = end - start;
725 ensureCapacity(count + len);
726 System.arraycopy(value, offset, value, offset + len, count - offset);
727 for (int i = start; i < end; ++i)
728 value[offset++] = sequence.charAt(i);
734 * Insert the <code>char[]</code> argument into this
735 * <code>StringBuffer</code>.
737 * @param offset the place to insert in this buffer
738 * @param data the <code>char[]</code> to insert
739 * @return this <code>StringBuffer</code>
740 * @throws NullPointerException if <code>data</code> is <code>null</code>
741 * @throws StringIndexOutOfBoundsException if offset is out of bounds
742 * @see #insert(int, char[], int, int)
744 public CPStringBuilder insert(int offset, char[] data)
746 return insert(offset, data, 0, data.length);
750 * Insert the <code>String</code> value of the argument into this
751 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
752 * to <code>String</code>.
754 * @param offset the place to insert in this buffer
755 * @param bool the <code>boolean</code> to convert and insert
756 * @return this <code>StringBuffer</code>
757 * @throws StringIndexOutOfBoundsException if offset is out of bounds
758 * @see String#valueOf(boolean)
760 public CPStringBuilder insert(int offset, boolean bool)
762 return insert(offset, bool ? "true" : "false");
766 * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
768 * @param offset the place to insert in this buffer
769 * @param ch the <code>char</code> to insert
770 * @return this <code>StringBuffer</code>
771 * @throws StringIndexOutOfBoundsException if offset is out of bounds
773 public CPStringBuilder insert(int offset, char ch)
775 if (offset < 0 || offset > count)
776 throw new StringIndexOutOfBoundsException(offset);
777 ensureCapacity(count + 1);
778 System.arraycopy(value, offset, value, offset + 1, count - offset);
785 * Insert the <code>String</code> value of the argument into this
786 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
787 * to <code>String</code>.
789 * @param offset the place to insert in this buffer
790 * @param inum the <code>int</code> to convert and insert
791 * @return this <code>StringBuffer</code>
792 * @throws StringIndexOutOfBoundsException if offset is out of bounds
793 * @see String#valueOf(int)
795 public CPStringBuilder insert(int offset, int inum)
797 return insert(offset, String.valueOf(inum));
801 * Insert the <code>String</code> value of the argument into this
802 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
803 * to <code>String</code>.
805 * @param offset the place to insert in this buffer
806 * @param lnum the <code>long</code> to convert and insert
807 * @return this <code>StringBuffer</code>
808 * @throws StringIndexOutOfBoundsException if offset is out of bounds
809 * @see String#valueOf(long)
811 public CPStringBuilder insert(int offset, long lnum)
813 return insert(offset, Long.toString(lnum, 10));
817 * Insert the <code>String</code> value of the argument into this
818 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
819 * to <code>String</code>.
821 * @param offset the place to insert in this buffer
822 * @param fnum the <code>float</code> to convert and insert
823 * @return this <code>StringBuffer</code>
824 * @throws StringIndexOutOfBoundsException if offset is out of bounds
825 * @see String#valueOf(float)
827 public CPStringBuilder insert(int offset, float fnum)
829 return insert(offset, Float.toString(fnum));
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>.
837 * @param offset the place to insert in this buffer
838 * @param dnum the <code>double</code> to convert and insert
839 * @return this <code>StringBuffer</code>
840 * @throws StringIndexOutOfBoundsException if offset is out of bounds
841 * @see String#valueOf(double)
843 public CPStringBuilder insert(int offset, double dnum)
845 return insert(offset, Double.toString(dnum));
849 * Finds the first instance of a substring in this StringBuilder.
851 * @param str String to find
852 * @return location (base 0) of the String, or -1 if not found
853 * @throws NullPointerException if str is null
854 * @see #indexOf(String, int)
856 public int indexOf(String str)
858 return indexOf(str, 0);
862 * Finds the first instance of a String in this StringBuffer, starting at
863 * a given index. If starting index is less than 0, the search starts at
864 * the beginning of this String. If the starting index is greater than the
865 * length of this String, or the substring is not found, -1 is returned.
867 * @param str String to find
868 * @param fromIndex index to start the search
869 * @return location (base 0) of the String, or -1 if not found
870 * @throws NullPointerException if str is null
873 public int indexOf(String str, int fromIndex)
877 int olength = str.length();
878 int limit = count - olength;
879 String s = VMCPStringBuilder.toString(value, 0, count);
880 for (; fromIndex <= limit; ++fromIndex)
881 if (s.regionMatches(fromIndex, str, 0, olength))
887 * Finds the last instance of a substring in this StringBuffer.
889 * @param str String to find
890 * @return location (base 0) of the String, or -1 if not found
891 * @throws NullPointerException if str is null
892 * @see #lastIndexOf(String, int)
895 public int lastIndexOf(String str)
897 return lastIndexOf(str, count - str.length());
901 * Finds the last instance of a String in this StringBuffer, starting at a
902 * given index. If starting index is greater than the maximum valid index,
903 * then the search begins at the end of this String. If the starting index
904 * is less than zero, or the substring is not found, -1 is returned.
906 * @param str String to find
907 * @param fromIndex index to start the search
908 * @return location (base 0) of the String, or -1 if not found
909 * @throws NullPointerException if str is null
912 public int lastIndexOf(String str, int fromIndex)
914 fromIndex = Math.min(fromIndex, count - str.length());
915 String s = VMCPStringBuilder.toString(value, 0, count);
916 int olength = str.length();
917 for ( ; fromIndex >= 0; fromIndex--)
918 if (s.regionMatches(fromIndex, str, 0, olength))
924 * Reverse the characters in this StringBuffer. The same sequence of
925 * characters exists, but in the reverse index ordering.
927 * @return this <code>StringBuffer</code>
929 public CPStringBuilder reverse()
931 // Call ensureCapacity to enforce copy-on-write.
932 ensureCapacity(count);
933 for (int i = count >> 1, j = count - i; --i >= 0; ++j)
943 * This may reduce the amount of memory used by the StringBuffer,
944 * by resizing the internal array to remove unused space. However,
945 * this method is not required to resize, so this behavior cannot
949 public void trimToSize()
951 int wouldSave = value.length - count;
952 // Some random heuristics: if we save less than 20 characters, who
956 // If we save more than 200 characters, shrink.
957 // If we save more than 1/4 of the buffer, shrink.
958 if (wouldSave > 200 || wouldSave * 4 > value.length)
959 allocateArray(count);
963 * Return the number of code points between two indices in the
964 * <code>StringBuffer</code>. An unpaired surrogate counts as a
965 * code point for this purpose. Characters outside the indicated
966 * range are not examined, even if the range ends in the middle of a
969 * @param start the starting index
970 * @param end one past the ending index
971 * @return the number of code points
974 public int codePointCount(int start, int end)
976 if (start < 0 || end >= count || start > end)
977 throw new StringIndexOutOfBoundsException();
982 char base = value[start];
983 if (base < Character.MIN_HIGH_SURROGATE
984 || base > Character.MAX_HIGH_SURROGATE
987 || value[start + 1] < Character.MIN_LOW_SURROGATE
988 || value[start + 1] > Character.MAX_LOW_SURROGATE)
1004 * Starting at the given index, this counts forward by the indicated
1005 * number of code points, and then returns the resulting index. An
1006 * unpaired surrogate counts as a single code point for this
1009 * @param start the starting index
1010 * @param codePoints the number of code points
1011 * @return the resulting index
1014 public int offsetByCodePoints(int start, int codePoints)
1016 while (codePoints > 0)
1018 char base = value[start];
1019 if (base < Character.MIN_HIGH_SURROGATE
1020 || base > Character.MAX_HIGH_SURROGATE
1022 || value[start + 1] < Character.MIN_LOW_SURROGATE
1023 || value[start + 1] > Character.MAX_LOW_SURROGATE)
1039 * Increase the capacity of this <code>StringBuilder</code>. This will
1040 * ensure that an expensive growing operation will not occur until either
1041 * <code>minimumCapacity</code> is reached or the array has been allocated.
1042 * The buffer is grown to either <code>minimumCapacity * 2</code>, if
1043 * the array has been allocated or the larger of <code>minimumCapacity</code> and
1044 * <code>capacity() * 2 + 2</code>, if it is not already large enough.
1046 * @param minimumCapacity the new capacity
1049 public void ensureCapacity(int minimumCapacity)
1051 if (allocated || minimumCapacity > value.length)
1053 if (minimumCapacity > value.length)
1055 int max = value.length * 2 + 2;
1056 minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
1059 minimumCapacity *= 2;
1060 allocateArray(minimumCapacity);
1065 * Allocates a new character array. This method is triggered when
1066 * a write is attempted after the array has been passed to a
1067 * {@link String} object, so that the builder does not modify
1068 * the immutable {@link String}.
1070 * @param capacity the size of the new array.
1072 private void allocateArray(int capacity)
1074 char[] nb = new char[capacity];
1075 System.arraycopy(value, 0, nb, 0, count);
1081 * Get the length of the <code>String</code> this <code>StringBuilder</code>
1082 * would create. Not to be confused with the <em>capacity</em> of the
1083 * <code>StringBuilder</code>.
1085 * @return the length of this <code>StringBuilder</code>
1087 * @see #setLength(int)
1095 * Creates a substring of this StringBuilder, starting at a specified index
1096 * and ending at one character before a specified index. This is implemented
1097 * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
1098 * the CharSequence interface.
1100 * @param beginIndex index to start at (inclusive, base 0)
1101 * @param endIndex index to end at (exclusive)
1102 * @return new String which is a substring of this StringBuilder
1103 * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
1105 * @see #substring(int, int)
1107 public CharSequence subSequence(int beginIndex, int endIndex)
1109 return substring(beginIndex, endIndex);
1113 * Creates a substring of this CPStringBuilder, starting at a specified index
1114 * and ending at the end of this StringBuilder.
1116 * @param beginIndex index to start substring (base 0)
1117 * @return new String which is a substring of this StringBuilder
1118 * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds
1119 * @see #substring(int, int)
1121 public String substring(int beginIndex)
1123 return substring(beginIndex, count);
1127 * Creates a substring of this CPStringBuilder, starting at a specified index
1128 * and ending at one character before a specified index.
1130 * @param beginIndex index to start at (inclusive, base 0)
1131 * @param endIndex index to end at (exclusive)
1132 * @return new String which is a substring of this StringBuilder
1133 * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
1136 public String substring(int beginIndex, int endIndex)
1138 if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
1139 throw new StringIndexOutOfBoundsException();
1140 int len = endIndex - beginIndex;
1144 return VMCPStringBuilder.toString(value, beginIndex, len);
1148 * Convert this <code>CPStringBuilder</code> to a <code>String</code>. The
1149 * String is composed of the characters currently in this StringBuilder. Note
1150 * that the result is not a copy, so we flag this here and make sure to
1151 * allocate a new array on the next write attempt (see {@link #ensureCapacity(int)}).
1153 * @return the characters in this StringBuilder
1155 public String toString()
1158 return VMCPStringBuilder.toString(value, 0, count);