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. */
208 ensureCapacity(newLength);
210 if (newLength < valueLength)
212 /* If the StringBuffer's value just grew, then we know that
213 value is newly allocated and the region between count and
214 newLength is filled with '\0'. */
219 /* The StringBuffer's value doesn't need to grow. However,
220 we should clear out any cruft that may exist. */
221 while (count < newLength)
222 value[count++] = '\0';
227 * Get the character at the specified index.
229 * @param index the index of the character to get, starting at 0
230 * @return the character at the specified index
231 * @throws IndexOutOfBoundsException if index is negative or >= length()
232 * (while unspecified, this is a StringIndexOutOfBoundsException)
234 public char charAt(int index)
236 if (index < 0 || index >= count)
237 throw new StringIndexOutOfBoundsException(index);
242 * Get the code point at the specified index. This is like #charAt(int),
243 * but if the character is the start of a surrogate pair, and the
244 * following character completes the pair, then the corresponding
245 * supplementary code point is returned.
246 * @param index the index of the codepoint to get, starting at 0
247 * @return the codepoint at the specified index
248 * @throws IndexOutOfBoundsException if index is negative or >= length()
251 public int codePointAt(int index)
253 return Character.codePointAt(value, index, count);
257 * Get the code point before the specified index. This is like
258 * #codePointAt(int), but checks the characters at <code>index-1</code> and
259 * <code>index-2</code> to see if they form a supplementary code point.
260 * @param index the index just past the codepoint to get, starting at 0
261 * @return the codepoint at the specified index
262 * @throws IndexOutOfBoundsException if index is negative or >= length()
265 public int codePointBefore(int index)
267 // Character.codePointBefore() doesn't perform this check. We
268 // could use the CharSequence overload, but this is just as easy.
270 throw new IndexOutOfBoundsException();
271 return Character.codePointBefore(value, index, 1);
275 * Get the specified array of characters. <code>srcOffset - srcEnd</code>
276 * characters will be copied into the array you pass in.
278 * @param srcOffset the index to start copying from (inclusive)
279 * @param srcEnd the index to stop copying from (exclusive)
280 * @param dst the array to copy into
281 * @param dstOffset the index to start copying into
282 * @throws NullPointerException if dst is null
283 * @throws IndexOutOfBoundsException if any source or target indices are
284 * out of range (while unspecified, source problems cause a
285 * StringIndexOutOfBoundsException, and dest problems cause an
286 * ArrayIndexOutOfBoundsException)
287 * @see System#arraycopy(Object, int, Object, int, int)
289 public void getChars(int srcOffset, int srcEnd,
290 char[] dst, int dstOffset)
292 if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
293 throw new StringIndexOutOfBoundsException();
294 System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
298 * Set the character at the specified index.
300 * @param index the index of the character to set starting at 0
301 * @param ch the value to set that character to
302 * @throws IndexOutOfBoundsException if index is negative or >= length()
303 * (while unspecified, this is a StringIndexOutOfBoundsException)
305 public void setCharAt(int index, char ch)
307 if (index < 0 || index >= count)
308 throw new StringIndexOutOfBoundsException(index);
309 // Call ensureCapacity to enforce copy-on-write.
310 ensureCapacity(count);
315 * Append the <code>String</code> value of the argument to this
316 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
317 * to <code>String</code>.
319 * @param obj the <code>Object</code> to convert and append
320 * @return this <code>StringBuffer</code>
321 * @see String#valueOf(Object)
322 * @see #append(String)
324 public CPStringBuilder append(Object obj)
326 return append(String.valueOf(obj));
330 * Append the <code>String</code> to this <code>StringBuffer</code>. If
331 * str is null, the String "null" is appended.
333 * @param str the <code>String</code> to append
334 * @return this <code>StringBuffer</code>
336 public CPStringBuilder append(String str)
340 int len = str.length();
341 ensureCapacity(count + len);
342 str.getChars(0, len, value, count);
348 * Append the <code>StringBuilder</code> value of the argument to this
349 * <code>StringBuilder</code>. This behaves the same as
350 * <code>append((Object) stringBuffer)</code>, except it is more efficient.
352 * @param stringBuffer the <code>StringBuilder</code> to convert and append
353 * @return this <code>StringBuilder</code>
354 * @see #append(Object)
356 public CPStringBuilder append(StringBuffer stringBuffer)
358 if (stringBuffer == null)
359 return append("null");
360 synchronized (stringBuffer)
362 int len = stringBuffer.length();
363 ensureCapacity(count + len);
364 stringBuffer.getChars(0, len, value, count);
371 * Append the <code>char</code> array to this <code>StringBuffer</code>.
372 * This is similar (but more efficient) than
373 * <code>append(new String(data))</code>, except in the case of null.
375 * @param data the <code>char[]</code> to append
376 * @return this <code>StringBuffer</code>
377 * @throws NullPointerException if <code>str</code> is <code>null</code>
378 * @see #append(char[], int, int)
380 public CPStringBuilder append(char[] data)
382 return append(data, 0, data.length);
386 * Append part of the <code>char</code> array to this
387 * <code>StringBuffer</code>. This is similar (but more efficient) than
388 * <code>append(new String(data, offset, count))</code>, except in the case
391 * @param data the <code>char[]</code> to append
392 * @param offset the start location in <code>str</code>
393 * @param count the number of characters to get from <code>str</code>
394 * @return this <code>StringBuffer</code>
395 * @throws NullPointerException if <code>str</code> is <code>null</code>
396 * @throws IndexOutOfBoundsException if offset or count is out of range
397 * (while unspecified, this is a StringIndexOutOfBoundsException)
399 public CPStringBuilder append(char[] data, int offset, int count)
401 if (offset < 0 || count < 0 || offset > data.length - count)
402 throw new StringIndexOutOfBoundsException();
403 ensureCapacity(this.count + count);
404 System.arraycopy(data, offset, value, this.count, count);
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>.
414 * @param bool the <code>boolean</code> to convert and append
415 * @return this <code>StringBuffer</code>
416 * @see String#valueOf(boolean)
418 public CPStringBuilder append(boolean bool)
420 return append(bool ? "true" : "false");
424 * Append the <code>char</code> to this <code>StringBuffer</code>.
426 * @param ch the <code>char</code> to append
427 * @return this <code>StringBuffer</code>
429 public CPStringBuilder append(char ch)
431 ensureCapacity(count + 1);
437 * Append the characters in the <code>CharSequence</code> to this
440 * @param seq the <code>CharSequence</code> providing the characters
441 * @return this <code>StringBuffer</code>
444 public CPStringBuilder append(CharSequence seq)
446 return append(seq, 0, seq.length());
450 * Append some characters from the <code>CharSequence</code> to this
451 * buffer. If the argument is null, the four characters "null" are
454 * @param seq the <code>CharSequence</code> providing the characters
455 * @param start the starting index
456 * @param end one past the final index
457 * @return this <code>StringBuffer</code>
460 public CPStringBuilder append(CharSequence seq, int start, int end)
463 return append("null");
466 ensureCapacity(count + end - start);
467 for (; start < end; ++start)
468 value[count++] = seq.charAt(start);
474 * Append the <code>String</code> value of the argument to this
475 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
476 * to <code>String</code>.
478 * @param inum the <code>int</code> to convert and append
479 * @return this <code>StringBuffer</code>
480 * @see String#valueOf(int)
482 // This is native in libgcj, for efficiency.
483 public CPStringBuilder append(int inum)
485 return append(String.valueOf(inum));
489 * Append the <code>String</code> value of the argument to this
490 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
491 * to <code>String</code>.
493 * @param lnum the <code>long</code> to convert and append
494 * @return this <code>StringBuffer</code>
495 * @see String#valueOf(long)
497 public CPStringBuilder append(long lnum)
499 return append(Long.toString(lnum, 10));
503 * Append the <code>String</code> value of the argument to this
504 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
505 * to <code>String</code>.
507 * @param fnum the <code>float</code> to convert and append
508 * @return this <code>StringBuffer</code>
509 * @see String#valueOf(float)
511 public CPStringBuilder append(float fnum)
513 return append(Float.toString(fnum));
517 * Append the <code>String</code> value of the argument to this
518 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
519 * to <code>String</code>.
521 * @param dnum the <code>double</code> to convert and append
522 * @return this <code>StringBuffer</code>
523 * @see String#valueOf(double)
525 public CPStringBuilder append(double dnum)
527 return append(Double.toString(dnum));
531 * Append the code point to this <code>StringBuffer</code>.
532 * This is like #append(char), but will append two characters
533 * if a supplementary code point is given.
535 * @param code the code point to append
536 * @return this <code>StringBuffer</code>
537 * @see Character#toChars(int, char[], int)
540 public CPStringBuilder appendCodePoint(int code)
542 int len = Character.charCount(code);
543 ensureCapacity(count + len);
544 Character.toChars(code, value, count);
550 * Delete characters from this <code>StringBuffer</code>.
551 * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
552 * harmless for end to be larger than length().
554 * @param start the first character to delete
555 * @param end the index after the last character to delete
556 * @return this <code>StringBuffer</code>
557 * @throws StringIndexOutOfBoundsException if start or end are out of bounds
560 public CPStringBuilder delete(int start, int end)
562 if (start < 0 || start > count || start > end)
563 throw new StringIndexOutOfBoundsException(start);
566 ensureCapacity(count);
567 if (count - end != 0)
568 System.arraycopy(value, end, value, start, count - end);
569 count -= end - start;
574 * Delete a character from this <code>StringBuffer</code>.
576 * @param index the index of the character to delete
577 * @return this <code>StringBuffer</code>
578 * @throws StringIndexOutOfBoundsException if index is out of bounds
581 public CPStringBuilder deleteCharAt(int index)
583 return delete(index, index + 1);
587 * Replace characters between index <code>start</code> (inclusive) and
588 * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
589 * is larger than the size of this StringBuffer, all characters after
590 * <code>start</code> are replaced.
592 * @param start the beginning index of characters to delete (inclusive)
593 * @param end the ending index of characters to delete (exclusive)
594 * @param str the new <code>String</code> to insert
595 * @return this <code>StringBuffer</code>
596 * @throws StringIndexOutOfBoundsException if start or end are out of bounds
597 * @throws NullPointerException if str is null
600 public CPStringBuilder replace(int start, int end, String str)
602 if (start < 0 || start > count || start > end)
603 throw new StringIndexOutOfBoundsException(start);
605 int len = str.length();
606 // Calculate the difference in 'count' after the replace.
607 int delta = len - (end > count ? count : end) + start;
608 ensureCapacity(count + delta);
610 if (delta != 0 && end < count)
611 System.arraycopy(value, end, value, end + delta, count - end);
613 str.getChars(0, len, value, start);
619 * Insert a subarray of the <code>char[]</code> argument into this
620 * <code>StringBuffer</code>.
622 * @param offset the place to insert in this buffer
623 * @param str the <code>char[]</code> to insert
624 * @param str_offset the index in <code>str</code> to start inserting from
625 * @param len the number of characters to insert
626 * @return this <code>StringBuffer</code>
627 * @throws NullPointerException if <code>str</code> is <code>null</code>
628 * @throws StringIndexOutOfBoundsException if any index is out of bounds
631 public CPStringBuilder insert(int offset, char[] str, int str_offset, int len)
633 if (offset < 0 || offset > count || len < 0
634 || str_offset < 0 || str_offset > str.length - len)
635 throw new StringIndexOutOfBoundsException();
636 ensureCapacity(count + len);
637 System.arraycopy(value, offset, value, offset + len, count - offset);
638 System.arraycopy(str, str_offset, value, offset, len);
644 * Insert the <code>String</code> value of the argument into this
645 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
646 * to <code>String</code>.
648 * @param offset the place to insert in this buffer
649 * @param obj the <code>Object</code> to convert and insert
650 * @return this <code>StringBuffer</code>
651 * @exception StringIndexOutOfBoundsException if offset is out of bounds
652 * @see String#valueOf(Object)
654 public CPStringBuilder insert(int offset, Object obj)
656 return insert(offset, obj == null ? "null" : obj.toString());
660 * Insert the <code>String</code> argument into this
661 * <code>StringBuffer</code>. If str is null, the String "null" is used
664 * @param offset the place to insert in this buffer
665 * @param str the <code>String</code> to insert
666 * @return this <code>StringBuffer</code>
667 * @throws StringIndexOutOfBoundsException if offset is out of bounds
669 public CPStringBuilder insert(int offset, String str)
671 if (offset < 0 || offset > count)
672 throw new StringIndexOutOfBoundsException(offset);
675 int len = str.length();
676 ensureCapacity(count + len);
677 System.arraycopy(value, offset, value, offset + len, count - offset);
678 str.getChars(0, len, value, offset);
684 * Insert the <code>CharSequence</code> argument into this
685 * <code>StringBuffer</code>. If the sequence is null, the String
686 * "null" is used instead.
688 * @param offset the place to insert in this buffer
689 * @param sequence the <code>CharSequence</code> to insert
690 * @return this <code>StringBuffer</code>
691 * @throws IndexOutOfBoundsException if offset is out of bounds
694 public CPStringBuilder insert(int offset, CharSequence sequence)
696 if (sequence == null)
698 return insert(offset, sequence, 0, sequence.length());
702 * Insert a subsequence of the <code>CharSequence</code> argument into this
703 * <code>StringBuffer</code>. If the sequence is null, the String
704 * "null" is used instead.
706 * @param offset the place to insert in this buffer
707 * @param sequence the <code>CharSequence</code> to insert
708 * @param start the starting index of the subsequence
709 * @param end one past the ending index of the subsequence
710 * @return this <code>StringBuffer</code>
711 * @throws IndexOutOfBoundsException if offset, start,
712 * or end are out of bounds
715 public CPStringBuilder insert(int offset, CharSequence sequence, int start, int end)
717 if (sequence == null)
719 if (start < 0 || end < 0 || start > end || end > sequence.length())
720 throw new IndexOutOfBoundsException();
721 int len = end - start;
722 ensureCapacity(count + len);
723 System.arraycopy(value, offset, value, offset + len, count - offset);
724 for (int i = start; i < end; ++i)
725 value[offset++] = sequence.charAt(i);
731 * Insert the <code>char[]</code> argument into this
732 * <code>StringBuffer</code>.
734 * @param offset the place to insert in this buffer
735 * @param data the <code>char[]</code> to insert
736 * @return this <code>StringBuffer</code>
737 * @throws NullPointerException if <code>data</code> is <code>null</code>
738 * @throws StringIndexOutOfBoundsException if offset is out of bounds
739 * @see #insert(int, char[], int, int)
741 public CPStringBuilder insert(int offset, char[] data)
743 return insert(offset, data, 0, data.length);
747 * Insert the <code>String</code> value of the argument into this
748 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
749 * to <code>String</code>.
751 * @param offset the place to insert in this buffer
752 * @param bool the <code>boolean</code> to convert and insert
753 * @return this <code>StringBuffer</code>
754 * @throws StringIndexOutOfBoundsException if offset is out of bounds
755 * @see String#valueOf(boolean)
757 public CPStringBuilder insert(int offset, boolean bool)
759 return insert(offset, bool ? "true" : "false");
763 * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
765 * @param offset the place to insert in this buffer
766 * @param ch the <code>char</code> to insert
767 * @return this <code>StringBuffer</code>
768 * @throws StringIndexOutOfBoundsException if offset is out of bounds
770 public CPStringBuilder insert(int offset, char ch)
772 if (offset < 0 || offset > count)
773 throw new StringIndexOutOfBoundsException(offset);
774 ensureCapacity(count + 1);
775 System.arraycopy(value, offset, value, offset + 1, count - offset);
782 * Insert the <code>String</code> value of the argument into this
783 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
784 * to <code>String</code>.
786 * @param offset the place to insert in this buffer
787 * @param inum the <code>int</code> to convert and insert
788 * @return this <code>StringBuffer</code>
789 * @throws StringIndexOutOfBoundsException if offset is out of bounds
790 * @see String#valueOf(int)
792 public CPStringBuilder insert(int offset, int inum)
794 return insert(offset, String.valueOf(inum));
798 * Insert the <code>String</code> value of the argument into this
799 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
800 * to <code>String</code>.
802 * @param offset the place to insert in this buffer
803 * @param lnum the <code>long</code> to convert and insert
804 * @return this <code>StringBuffer</code>
805 * @throws StringIndexOutOfBoundsException if offset is out of bounds
806 * @see String#valueOf(long)
808 public CPStringBuilder insert(int offset, long lnum)
810 return insert(offset, Long.toString(lnum, 10));
814 * Insert the <code>String</code> value of the argument into this
815 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
816 * to <code>String</code>.
818 * @param offset the place to insert in this buffer
819 * @param fnum the <code>float</code> to convert and insert
820 * @return this <code>StringBuffer</code>
821 * @throws StringIndexOutOfBoundsException if offset is out of bounds
822 * @see String#valueOf(float)
824 public CPStringBuilder insert(int offset, float fnum)
826 return insert(offset, Float.toString(fnum));
830 * Insert the <code>String</code> value of the argument into this
831 * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
832 * to <code>String</code>.
834 * @param offset the place to insert in this buffer
835 * @param dnum the <code>double</code> to convert and insert
836 * @return this <code>StringBuffer</code>
837 * @throws StringIndexOutOfBoundsException if offset is out of bounds
838 * @see String#valueOf(double)
840 public CPStringBuilder insert(int offset, double dnum)
842 return insert(offset, Double.toString(dnum));
846 * Finds the first instance of a substring in this StringBuilder.
848 * @param str String to find
849 * @return location (base 0) of the String, or -1 if not found
850 * @throws NullPointerException if str is null
851 * @see #indexOf(String, int)
853 public int indexOf(String str)
855 return indexOf(str, 0);
859 * Finds the first instance of a String in this StringBuffer, starting at
860 * a given index. If starting index is less than 0, the search starts at
861 * the beginning of this String. If the starting index is greater than the
862 * length of this String, or the substring is not found, -1 is returned.
864 * @param str String to find
865 * @param fromIndex index to start the search
866 * @return location (base 0) of the String, or -1 if not found
867 * @throws NullPointerException if str is null
870 public int indexOf(String str, int fromIndex)
874 int olength = str.length();
875 int limit = count - olength;
876 String s = VMCPStringBuilder.toString(value, 0, count);
877 for (; fromIndex <= limit; ++fromIndex)
878 if (s.regionMatches(fromIndex, str, 0, olength))
884 * Finds the last instance of a substring in this StringBuffer.
886 * @param str String to find
887 * @return location (base 0) of the String, or -1 if not found
888 * @throws NullPointerException if str is null
889 * @see #lastIndexOf(String, int)
892 public int lastIndexOf(String str)
894 return lastIndexOf(str, count - str.length());
898 * Finds the last instance of a String in this StringBuffer, starting at a
899 * given index. If starting index is greater than the maximum valid index,
900 * then the search begins at the end of this String. If the starting index
901 * is less than zero, or the substring is not found, -1 is returned.
903 * @param str String to find
904 * @param fromIndex index to start the search
905 * @return location (base 0) of the String, or -1 if not found
906 * @throws NullPointerException if str is null
909 public int lastIndexOf(String str, int fromIndex)
911 fromIndex = Math.min(fromIndex, count - str.length());
912 String s = VMCPStringBuilder.toString(value, 0, count);
913 int olength = str.length();
914 for ( ; fromIndex >= 0; fromIndex--)
915 if (s.regionMatches(fromIndex, str, 0, olength))
921 * Reverse the characters in this StringBuffer. The same sequence of
922 * characters exists, but in the reverse index ordering.
924 * @return this <code>StringBuffer</code>
926 public CPStringBuilder reverse()
928 // Call ensureCapacity to enforce copy-on-write.
929 ensureCapacity(count);
930 for (int i = count >> 1, j = count - i; --i >= 0; ++j)
940 * This may reduce the amount of memory used by the StringBuffer,
941 * by resizing the internal array to remove unused space. However,
942 * this method is not required to resize, so this behavior cannot
946 public void trimToSize()
948 int wouldSave = value.length - count;
949 // Some random heuristics: if we save less than 20 characters, who
953 // If we save more than 200 characters, shrink.
954 // If we save more than 1/4 of the buffer, shrink.
955 if (wouldSave > 200 || wouldSave * 4 > value.length)
956 allocateArray(count);
960 * Return the number of code points between two indices in the
961 * <code>StringBuffer</code>. An unpaired surrogate counts as a
962 * code point for this purpose. Characters outside the indicated
963 * range are not examined, even if the range ends in the middle of a
966 * @param start the starting index
967 * @param end one past the ending index
968 * @return the number of code points
971 public int codePointCount(int start, int end)
973 if (start < 0 || end >= count || start > end)
974 throw new StringIndexOutOfBoundsException();
979 char base = value[start];
980 if (base < Character.MIN_HIGH_SURROGATE
981 || base > Character.MAX_HIGH_SURROGATE
984 || value[start + 1] < Character.MIN_LOW_SURROGATE
985 || value[start + 1] > Character.MAX_LOW_SURROGATE)
1001 * Starting at the given index, this counts forward by the indicated
1002 * number of code points, and then returns the resulting index. An
1003 * unpaired surrogate counts as a single code point for this
1006 * @param start the starting index
1007 * @param codePoints the number of code points
1008 * @return the resulting index
1011 public int offsetByCodePoints(int start, int codePoints)
1013 while (codePoints > 0)
1015 char base = value[start];
1016 if (base < Character.MIN_HIGH_SURROGATE
1017 || base > Character.MAX_HIGH_SURROGATE
1019 || value[start + 1] < Character.MIN_LOW_SURROGATE
1020 || value[start + 1] > Character.MAX_LOW_SURROGATE)
1036 * Increase the capacity of this <code>StringBuilder</code>. This will
1037 * ensure that an expensive growing operation will not occur until either
1038 * <code>minimumCapacity</code> is reached or the array has been allocated.
1039 * The buffer is grown to the larger of <code>minimumCapacity</code> and
1040 * <code>capacity() * 2 + 2</code>, if it is not already large enough.
1042 * @param minimumCapacity the new capacity
1045 public void ensureCapacity(int minimumCapacity)
1047 if (allocated || minimumCapacity > value.length)
1049 int max = value.length * 2 + 2;
1050 minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
1051 allocateArray(minimumCapacity);
1056 * Allocates a new character array. This method is triggered when
1057 * a write is attempted after the array has been passed to a
1058 * {@link String} object, so that the builder does not modify
1059 * the immutable {@link String}.
1061 * @param capacity the size of the new array.
1063 private void allocateArray(int capacity)
1065 char[] nb = new char[capacity];
1066 System.arraycopy(value, 0, nb, 0, count);
1072 * Get the length of the <code>String</code> this <code>StringBuilder</code>
1073 * would create. Not to be confused with the <em>capacity</em> of the
1074 * <code>StringBuilder</code>.
1076 * @return the length of this <code>StringBuilder</code>
1078 * @see #setLength(int)
1086 * Creates a substring of this StringBuilder, starting at a specified index
1087 * and ending at one character before a specified index. This is implemented
1088 * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
1089 * the CharSequence interface.
1091 * @param beginIndex index to start at (inclusive, base 0)
1092 * @param endIndex index to end at (exclusive)
1093 * @return new String which is a substring of this StringBuilder
1094 * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
1096 * @see #substring(int, int)
1098 public CharSequence subSequence(int beginIndex, int endIndex)
1100 return substring(beginIndex, endIndex);
1104 * Creates a substring of this CPStringBuilder, starting at a specified index
1105 * and ending at the end of this StringBuilder.
1107 * @param beginIndex index to start substring (base 0)
1108 * @return new String which is a substring of this StringBuilder
1109 * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds
1110 * @see #substring(int, int)
1112 public String substring(int beginIndex)
1114 return substring(beginIndex, count);
1118 * Creates a substring of this CPStringBuilder, starting at a specified index
1119 * and ending at one character before a specified index.
1121 * @param beginIndex index to start at (inclusive, base 0)
1122 * @param endIndex index to end at (exclusive)
1123 * @return new String which is a substring of this StringBuilder
1124 * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
1127 public String substring(int beginIndex, int endIndex)
1129 if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
1130 throw new StringIndexOutOfBoundsException();
1131 int len = endIndex - beginIndex;
1135 return VMCPStringBuilder.toString(value, beginIndex, len);
1139 * Convert this <code>CPStringBuilder</code> to a <code>String</code>. The
1140 * String is composed of the characters currently in this StringBuilder. Note
1141 * that the result is not a copy, so we flag this here and make sure to
1142 * allocate a new array on the next write attempt (see {@link #ensureCapacity(int)}).
1144 * @return the characters in this StringBuilder
1146 public String toString()
1149 return VMCPStringBuilder.toString(value, 0, count);