Merged with tip.
[cacao.git] / src / classes / gnuclasspath / gnu / java / lang / CPStringBuilder.java
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.
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 gnu.java.lang;
40
41 import gnu.classpath.SystemProperties;
42
43 import java.io.Serializable;
44
45 /**
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
50  * methods.
51  */
52 public final class CPStringBuilder
53   implements Serializable, CharSequence, Appendable
54 {
55
56   /**
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.
60    *
61    * @serial the number of characters in the buffer
62    */
63   private int count;
64
65   /**
66    * The buffer.  Note that this has permissions set this way so that String
67    * can get the value.
68    *
69    * @serial the buffer
70    */
71   private char[] value;
72
73   /**
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
82    * to be reset.
83    */
84   private boolean allocated = false;
85
86   /**
87    * The default capacity of a buffer.
88    * This can be configured using gnu.classpath.cpstringbuilder.capacity
89    */
90   private static final int DEFAULT_CAPACITY;
91
92   static
93   {
94     String cap =
95       SystemProperties.getProperty("gnu.classpath.cpstringbuilder.capacity");
96     if (cap == null)
97       DEFAULT_CAPACITY = 32;
98     else
99       DEFAULT_CAPACITY = Integer.parseInt(cap);
100   }
101
102   /**
103    * Create a new CPStringBuilder with the default capacity.
104    */
105   public CPStringBuilder()
106   {
107     this(DEFAULT_CAPACITY);
108   }
109
110   /**
111    * Create an empty <code>CPStringBuilder</code> with the specified initial
112    * capacity.
113    *
114    * @param capacity the initial capacity
115    * @throws NegativeArraySizeException if capacity is negative
116    */
117   public CPStringBuilder(int capacity)
118   {
119     value = new char[capacity];
120   }
121
122   /**
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.
126    *
127    * @param str the <code>String</code> to convert
128    * @throws NullPointerException if str is null
129    */
130   public CPStringBuilder(String str)
131   {
132     count = str.length();
133     value = new char[count + DEFAULT_CAPACITY];
134     str.getChars(0, count, value, 0);
135   }
136
137   /**
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.
141    *
142    * @param str the <code>String</code> to convert
143    * @throws NullPointerException if str is null
144    */
145   public CPStringBuilder(StringBuffer str)
146   {
147     count = str.length();
148     value = new char[count + DEFAULT_CAPACITY];
149     str.getChars(0, count, value, 0);
150   }
151
152   /**
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.
156    *
157    * @param str the <code>String</code> to convert
158    * @throws NullPointerException if str is null
159    */
160   public CPStringBuilder(StringBuilder str)
161   {
162     count = str.length();
163     value = new char[count + DEFAULT_CAPACITY];
164     str.getChars(0, count, value, 0);
165   }
166
167   /**
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.
173    *
174    * @param seq the initializing <code>CharSequence</code>
175    * @throws NullPointerException if str is null
176    * @since 1.5
177    */
178   public CPStringBuilder(CharSequence seq)
179   {
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);
185   }
186
187   /**
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.
193    *
194    * @param newLength the new length
195    * @throws IndexOutOfBoundsException if the new length is negative
196    *         (while unspecified, this is a StringIndexOutOfBoundsException)
197    * @see #length()
198    */
199   public void setLength(int newLength)
200   {
201     if (newLength < 0)
202       throw new StringIndexOutOfBoundsException(newLength);
203
204     int valueLength = value.length;
205
206     /* Always call ensureCapacity in order to preserve
207        copy-on-write semantics, except when the position
208        is simply being reset
209     */
210     if (newLength > 0)
211       ensureCapacity(newLength);
212
213     if (newLength < valueLength)
214       {
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'.  */
218         count = newLength;
219       }
220     else
221       {
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';
226       }
227   }
228
229   /**
230    * Get the character at the specified index.
231    *
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 &gt;= length()
235    *         (while unspecified, this is a StringIndexOutOfBoundsException)
236    */
237   public char charAt(int index)
238   {
239     if (index < 0 || index >= count)
240       throw new StringIndexOutOfBoundsException(index);
241     return value[index];
242   }
243
244   /**
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 &gt;= length()
252    * @since 1.5
253    */
254   public int codePointAt(int index)
255   {
256     return Character.codePointAt(value, index, count);
257   }
258
259   /**
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 &gt;= length()
266    * @since 1.5
267    */
268   public int codePointBefore(int index)
269   {
270     // Character.codePointBefore() doesn't perform this check.  We
271     // could use the CharSequence overload, but this is just as easy.
272     if (index >= count)
273       throw new IndexOutOfBoundsException();
274     return Character.codePointBefore(value, index, 1);
275   }
276
277   /**
278    * Get the specified array of characters. <code>srcOffset - srcEnd</code>
279    * characters will be copied into the array you pass in.
280    *
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)
291    */
292   public void getChars(int srcOffset, int srcEnd,
293                        char[] dst, int dstOffset)
294   {
295     if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
296       throw new StringIndexOutOfBoundsException();
297     System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
298   }
299
300   /**
301    * Set the character at the specified index.
302    *
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 &gt;= length()
306    *         (while unspecified, this is a StringIndexOutOfBoundsException)
307    */
308   public void setCharAt(int index, char ch)
309   {
310     if (index < 0 || index >= count)
311       throw new StringIndexOutOfBoundsException(index);
312     // Call ensureCapacity to enforce copy-on-write.
313     ensureCapacity(count);
314     value[index] = ch;
315   }
316
317   /**
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>.
321    *
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)
326    */
327   public CPStringBuilder append(Object obj)
328   {
329     return append(String.valueOf(obj));
330   }
331
332   /**
333    * Append the <code>String</code> to this <code>StringBuffer</code>. If
334    * str is null, the String "null" is appended.
335    *
336    * @param str the <code>String</code> to append
337    * @return this <code>StringBuffer</code>
338    */
339   public CPStringBuilder append(String str)
340   {
341     if (str == null)
342       str = "null";
343     int len = str.length();
344     ensureCapacity(count + len);
345     str.getChars(0, len, value, count);
346     count += len;
347     return this;
348   }
349
350   /**
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.
354    *
355    * @param stringBuffer the <code>StringBuilder</code> to convert and append
356    * @return this <code>StringBuilder</code>
357    * @see #append(Object)
358    */
359   public CPStringBuilder append(StringBuffer stringBuffer)
360   {
361     if (stringBuffer == null)
362       return append("null");
363     synchronized (stringBuffer)
364       {
365         int len = stringBuffer.length();
366         ensureCapacity(count + len);
367         stringBuffer.getChars(0, len, value, count);
368         count += len;
369       }
370     return this;
371   }
372
373   /**
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.
377    *
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)
382    */
383   public CPStringBuilder append(char[] data)
384   {
385     return append(data, 0, data.length);
386   }
387
388   /**
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
392    * of null.
393    *
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)
401    */
402   public CPStringBuilder append(char[] data, int offset, int count)
403   {
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);
408     this.count += count;
409     return this;
410   }
411
412   /**
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>.
416    *
417    * @param bool the <code>boolean</code> to convert and append
418    * @return this <code>StringBuffer</code>
419    * @see String#valueOf(boolean)
420    */
421   public CPStringBuilder append(boolean bool)
422   {
423     return append(bool ? "true" : "false");
424   }
425
426   /**
427    * Append the <code>char</code> to this <code>StringBuffer</code>.
428    *
429    * @param ch the <code>char</code> to append
430    * @return this <code>StringBuffer</code>
431    */
432   public CPStringBuilder append(char ch)
433   {
434     ensureCapacity(count + 1);
435     value[count++] = ch;
436     return this;
437   }
438
439   /**
440    * Append the characters in the <code>CharSequence</code> to this
441    * buffer.
442    *
443    * @param seq the <code>CharSequence</code> providing the characters
444    * @return this <code>StringBuffer</code>
445    * @since 1.5
446    */
447   public CPStringBuilder append(CharSequence seq)
448   {
449     return append(seq, 0, seq.length());
450   }
451
452   /**
453    * Append some characters from the <code>CharSequence</code> to this
454    * buffer.  If the argument is null, the four characters "null" are
455    * appended.
456    *
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>
461    * @since 1.5
462    */
463   public CPStringBuilder append(CharSequence seq, int start, int end)
464   {
465     if (seq == null)
466       return append("null");
467     if (end - start > 0)
468       {
469         ensureCapacity(count + end - start);
470         for (; start < end; ++start)
471           value[count++] = seq.charAt(start);
472       }
473     return this;
474   }
475
476   /**
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>.
480    *
481    * @param inum the <code>int</code> to convert and append
482    * @return this <code>StringBuffer</code>
483    * @see String#valueOf(int)
484    */
485   // This is native in libgcj, for efficiency.
486   public CPStringBuilder append(int inum)
487   {
488     return append(String.valueOf(inum));
489   }
490
491   /**
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>.
495    *
496    * @param lnum the <code>long</code> to convert and append
497    * @return this <code>StringBuffer</code>
498    * @see String#valueOf(long)
499    */
500   public CPStringBuilder append(long lnum)
501   {
502     return append(Long.toString(lnum, 10));
503   }
504
505   /**
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>.
509    *
510    * @param fnum the <code>float</code> to convert and append
511    * @return this <code>StringBuffer</code>
512    * @see String#valueOf(float)
513    */
514   public CPStringBuilder append(float fnum)
515   {
516     return append(Float.toString(fnum));
517   }
518
519   /**
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>.
523    *
524    * @param dnum the <code>double</code> to convert and append
525    * @return this <code>StringBuffer</code>
526    * @see String#valueOf(double)
527    */
528   public CPStringBuilder append(double dnum)
529   {
530     return append(Double.toString(dnum));
531   }
532
533   /**
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.
537    *
538    * @param code the code point to append
539    * @return this <code>StringBuffer</code>
540    * @see Character#toChars(int, char[], int)
541    * @since 1.5
542    */
543   public CPStringBuilder appendCodePoint(int code)
544   {
545     int len = Character.charCount(code);
546     ensureCapacity(count + len);
547     Character.toChars(code, value, count);
548     count += len;
549     return this;
550   }
551
552   /**
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().
556    *
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
561    * @since 1.2
562    */
563   public CPStringBuilder delete(int start, int end)
564   {
565     if (start < 0 || start > count || start > end)
566       throw new StringIndexOutOfBoundsException(start);
567     if (end > count)
568       end = count;
569     ensureCapacity(count);
570     if (count - end != 0)
571       System.arraycopy(value, end, value, start, count - end);
572     count -= end - start;
573     return this;
574   }
575
576   /**
577    * Delete a character from this <code>StringBuffer</code>.
578    *
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
582    * @since 1.2
583    */
584   public CPStringBuilder deleteCharAt(int index)
585   {
586     return delete(index, index + 1);
587   }
588
589   /**
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.
594    *
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
601    * @since 1.2
602    */
603   public CPStringBuilder replace(int start, int end, String str)
604   {
605     if (start < 0 || start > count || start > end)
606       throw new StringIndexOutOfBoundsException(start);
607
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);
612
613     if (delta != 0 && end < count)
614       System.arraycopy(value, end, value, end + delta, count - end);
615
616     str.getChars(0, len, value, start);
617     count += delta;
618     return this;
619   }
620
621   /**
622    * Insert a subarray of the <code>char[]</code> argument into this
623    * <code>StringBuffer</code>.
624    *
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
632    * @since 1.2
633    */
634   public CPStringBuilder insert(int offset, char[] str, int str_offset, int len)
635   {
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);
642     count += len;
643     return this;
644   }
645
646   /**
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>.
650    *
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)
656    */
657   public CPStringBuilder insert(int offset, Object obj)
658   {
659     return insert(offset, obj == null ? "null" : obj.toString());
660   }
661
662   /**
663    * Insert the <code>String</code> argument into this
664    * <code>StringBuffer</code>. If str is null, the String "null" is used
665    * instead.
666    *
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
671    */
672   public CPStringBuilder insert(int offset, String str)
673   {
674     if (offset < 0 || offset > count)
675       throw new StringIndexOutOfBoundsException(offset);
676     if (str == null)
677       str = "null";
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);
682     count += len;
683     return this;
684   }
685
686   /**
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.
690    *
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
695    * @since 1.5
696    */
697   public CPStringBuilder insert(int offset, CharSequence sequence)
698   {
699     if (sequence == null)
700       sequence = "null";
701     return insert(offset, sequence, 0, sequence.length());
702   }
703
704   /**
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.
708    *
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
716    * @since 1.5
717    */
718   public CPStringBuilder insert(int offset, CharSequence sequence, int start, int end)
719   {
720     if (sequence == null)
721       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);
729     count += len;
730     return this;
731   }
732
733   /**
734    * Insert the <code>char[]</code> argument into this
735    * <code>StringBuffer</code>.
736    *
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)
743    */
744   public CPStringBuilder insert(int offset, char[] data)
745   {
746     return insert(offset, data, 0, data.length);
747   }
748
749   /**
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>.
753    *
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)
759    */
760   public CPStringBuilder insert(int offset, boolean bool)
761   {
762     return insert(offset, bool ? "true" : "false");
763   }
764
765   /**
766    * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
767    *
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
772    */
773   public CPStringBuilder insert(int offset, char ch)
774   {
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);
779     value[offset] = ch;
780     count++;
781     return this;
782   }
783
784   /**
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>.
788    *
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)
794    */
795   public CPStringBuilder insert(int offset, int inum)
796   {
797     return insert(offset, String.valueOf(inum));
798   }
799
800   /**
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>.
804    *
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)
810    */
811   public CPStringBuilder insert(int offset, long lnum)
812   {
813     return insert(offset, Long.toString(lnum, 10));
814   }
815
816   /**
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>.
820    *
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)
826    */
827   public CPStringBuilder insert(int offset, float fnum)
828   {
829     return insert(offset, Float.toString(fnum));
830   }
831
832   /**
833    * Insert the <code>String</code> value of the argument into this
834    * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
835    * to <code>String</code>.
836    *
837    * @param offset the place to insert in this buffer
838    * @param 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)
842    */
843   public CPStringBuilder insert(int offset, double dnum)
844   {
845     return insert(offset, Double.toString(dnum));
846   }
847
848   /**
849    * Finds the first instance of a substring in this StringBuilder.
850    *
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)
855    */
856   public int indexOf(String str)
857   {
858     return indexOf(str, 0);
859   }
860
861   /**
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.
866    *
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
871    * @since 1.4
872    */
873   public int indexOf(String str, int fromIndex)
874   {
875     if (fromIndex < 0)
876       fromIndex = 0;
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))
882         return fromIndex;
883     return -1;
884   }
885
886   /**
887    * Finds the last instance of a substring in this StringBuffer.
888    *
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)
893    * @since 1.4
894    */
895   public int lastIndexOf(String str)
896   {
897     return lastIndexOf(str, count - str.length());
898   }
899
900   /**
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.
905    *
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
910    * @since 1.4
911    */
912   public int lastIndexOf(String str, int fromIndex)
913   {
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))
919         return fromIndex;
920     return -1;
921   }
922
923   /**
924    * Reverse the characters in this StringBuffer. The same sequence of
925    * characters exists, but in the reverse index ordering.
926    *
927    * @return this <code>StringBuffer</code>
928    */
929   public CPStringBuilder reverse()
930   {
931     // Call ensureCapacity to enforce copy-on-write.
932     ensureCapacity(count);
933     for (int i = count >> 1, j = count - i; --i >= 0; ++j)
934       {
935         char c = value[i];
936         value[i] = value[j];
937         value[j] = c;
938       }
939     return this;
940   }
941
942   /**
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
946    * be relied upon.
947    * @since 1.5
948    */
949   public void trimToSize()
950   {
951     int wouldSave = value.length - count;
952     // Some random heuristics: if we save less than 20 characters, who
953     // cares.
954     if (wouldSave < 20)
955       return;
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);
960   }
961
962   /**
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
967    * surrogate pair.
968    *
969    * @param start the starting index
970    * @param end one past the ending index
971    * @return the number of code points
972    * @since 1.5
973    */
974   public int codePointCount(int start, int end)
975   {
976     if (start < 0 || end >= count || start > end)
977       throw new StringIndexOutOfBoundsException();
978
979     int count = 0;
980     while (start < end)
981       {
982         char base = value[start];
983         if (base < Character.MIN_HIGH_SURROGATE
984             || base > Character.MAX_HIGH_SURROGATE
985             || start == end
986             || start == count
987             || value[start + 1] < Character.MIN_LOW_SURROGATE
988             || value[start + 1] > Character.MAX_LOW_SURROGATE)
989           {
990             // Nothing.
991           }
992         else
993           {
994             // Surrogate pair.
995             ++start;
996           }
997         ++start;
998         ++count;
999       }
1000     return count;
1001   }
1002
1003   /**
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
1007    * purpose.
1008    *
1009    * @param start the starting index
1010    * @param codePoints the number of code points
1011    * @return the resulting index
1012    * @since 1.5
1013    */
1014   public int offsetByCodePoints(int start, int codePoints)
1015   {
1016     while (codePoints > 0)
1017       {
1018         char base = value[start];
1019         if (base < Character.MIN_HIGH_SURROGATE
1020             || base > Character.MAX_HIGH_SURROGATE
1021             || start == count
1022             || value[start + 1] < Character.MIN_LOW_SURROGATE
1023             || value[start + 1] > Character.MAX_LOW_SURROGATE)
1024           {
1025             // Nothing.
1026           }
1027         else
1028           {
1029             // Surrogate pair.
1030             ++start;
1031           }
1032         ++start;
1033         --codePoints;
1034       }
1035     return start;
1036   }
1037
1038   /**
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.
1045    *
1046    * @param minimumCapacity the new capacity
1047    * @see #length()
1048    */
1049   public void ensureCapacity(int minimumCapacity)
1050   {
1051     if (allocated || minimumCapacity > value.length)
1052       {
1053         if (minimumCapacity > value.length)
1054           {
1055             int max = value.length * 2 + 2;
1056             minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
1057           }
1058         else
1059           minimumCapacity *= 2;
1060         allocateArray(minimumCapacity);
1061       }
1062   }
1063
1064   /**
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}.
1069    *
1070    * @param capacity the size of the new array.
1071    */
1072   private void allocateArray(int capacity)
1073   {
1074     char[] nb = new char[capacity];
1075     System.arraycopy(value, 0, nb, 0, count);
1076     value = nb;
1077     allocated = false;
1078   }
1079     
1080   /**
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>.
1084    *
1085    * @return the length of this <code>StringBuilder</code>
1086    * @see #capacity()
1087    * @see #setLength(int)
1088    */
1089   public int length()
1090   {
1091     return count;
1092   }
1093
1094   /**
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.
1099    *
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
1104    *         bounds
1105    * @see #substring(int, int)
1106    */
1107   public CharSequence subSequence(int beginIndex, int endIndex)
1108   {
1109     return substring(beginIndex, endIndex);
1110   }
1111
1112   /**
1113    * Creates a substring of this CPStringBuilder, starting at a specified index
1114    * and ending at the end of this StringBuilder.
1115    *
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)
1120    */
1121   public String substring(int beginIndex)
1122   {
1123     return substring(beginIndex, count);
1124   }
1125
1126   /**
1127    * Creates a substring of this CPStringBuilder, starting at a specified index
1128    * and ending at one character before a specified index.
1129    *
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
1134    *         of bounds
1135    */
1136   public String substring(int beginIndex, int endIndex)
1137   {
1138     if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
1139       throw new StringIndexOutOfBoundsException();
1140     int len = endIndex - beginIndex;
1141     if (len == 0)
1142       return "";
1143     allocated = true;
1144     return VMCPStringBuilder.toString(value, beginIndex, len);
1145   }
1146
1147   /**
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)}).
1152    *
1153    * @return the characters in this StringBuilder
1154    */
1155   public String toString()
1156   {
1157     allocated = true;
1158     return VMCPStringBuilder.toString(value, 0, count);
1159   }
1160
1161 }