View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.text;
18  
19  import java.io.Reader;
20  import java.io.Serializable;
21  import java.io.Writer;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import org.apache.commons.lang3.ArrayUtils;
26  import org.apache.commons.lang3.ObjectUtils;
27  import org.apache.commons.lang3.SystemUtils;
28  import org.apache.commons.lang3.builder.Builder;
29  
30  /**
31   * Builds a string from constituent parts providing a more flexible and powerful API
32   * than StringBuffer.
33   * <p>
34   * The main differences from StringBuffer/StringBuilder are:
35   * </p>
36   * <ul>
37   * <li>Not synchronized</li>
38   * <li>Not final</li>
39   * <li>Subclasses have direct access to character array</li>
40   * <li>Additional methods
41   *  <ul>
42   *   <li>appendWithSeparators - adds an array of values, with a separator</li>
43   *   <li>appendPadding - adds a length padding characters</li>
44   *   <li>appendFixedLength - adds a fixed width field to the builder</li>
45   *   <li>toCharArray/getChars - simpler ways to get a range of the character array</li>
46   *   <li>delete - delete char or string</li>
47   *   <li>replace - search and replace for a char or string</li>
48   *   <li>leftString/rightString/midString - substring without exceptions</li>
49   *   <li>contains - whether the builder contains a char or string</li>
50   *   <li>size/clear/isEmpty - collections style API methods</li>
51   *  </ul>
52   * </li>
53   * <li>Views
54   *  <ul>
55   *   <li>asTokenizer - uses the internal buffer as the source of a StrTokenizer</li>
56   *   <li>asReader - uses the internal buffer as the source of a Reader</li>
57   *   <li>asWriter - allows a Writer to write directly to the internal buffer</li>
58   *  </ul>
59   * </li>
60   * </ul>
61   * <p>
62   * The aim has been to provide an API that mimics very closely what StringBuffer
63   * provides, but with additional methods. It should be noted that some edge cases,
64   * with invalid indices or null input, have been altered - see individual methods.
65   * The biggest of these changes is that by default, null will not output the text
66   * 'null'. This can be controlled by a property, {@link #setNullText(String)}.
67   * <p>
68   * Prior to 3.0, this class implemented Cloneable but did not implement the 
69   * clone method so could not be used. From 3.0 onwards it no longer implements 
70   * the interface. 
71   *
72   * @since 2.2
73   * @version $Id: StrBuilder.java 1583482 2014-03-31 22:54:57Z niallp $
74   */
75  public class StrBuilder implements CharSequence, Appendable, Serializable, Builder<String> {
76  
77      /**
78       * The extra capacity for new builders.
79       */
80      static final int CAPACITY = 32;
81  
82      /**
83       * Required for serialization support.
84       * 
85       * @see java.io.Serializable
86       */
87      private static final long serialVersionUID = 7628716375283629643L;
88  
89      /** Internal data storage. */
90      protected char[] buffer; // TODO make private?
91      /** Current size of the buffer. */
92      protected int size; // TODO make private?
93      /** The new line. */
94      private String newLine;
95      /** The null text. */
96      private String nullText;
97  
98      //-----------------------------------------------------------------------
99      /**
100      * Constructor that creates an empty builder initial capacity 32 characters.
101      */
102     public StrBuilder() {
103         this(CAPACITY);
104     }
105 
106     /**
107      * Constructor that creates an empty builder the specified initial capacity.
108      *
109      * @param initialCapacity  the initial capacity, zero or less will be converted to 32
110      */
111     public StrBuilder(int initialCapacity) {
112         super();
113         if (initialCapacity <= 0) {
114             initialCapacity = CAPACITY;
115         }
116         buffer = new char[initialCapacity];
117     }
118 
119     /**
120      * Constructor that creates a builder from the string, allocating
121      * 32 extra characters for growth.
122      *
123      * @param str  the string to copy, null treated as blank string
124      */
125     public StrBuilder(final String str) {
126         super();
127         if (str == null) {
128             buffer = new char[CAPACITY];
129         } else {
130             buffer = new char[str.length() + CAPACITY];
131             append(str);
132         }
133     }
134 
135     //-----------------------------------------------------------------------
136     /**
137      * Gets the text to be appended when a new line is added.
138      *
139      * @return the new line text, null means use system default
140      */
141     public String getNewLineText() {
142         return newLine;
143     }
144 
145     /**
146      * Sets the text to be appended when a new line is added.
147      *
148      * @param newLine  the new line text, null means use system default
149      * @return this, to enable chaining
150      */
151     public StrBuilder setNewLineText(final String newLine) {
152         this.newLine = newLine;
153         return this;
154     }
155 
156     //-----------------------------------------------------------------------
157     /**
158      * Gets the text to be appended when null is added.
159      *
160      * @return the null text, null means no append
161      */
162     public String getNullText() {
163         return nullText;
164     }
165 
166     /**
167      * Sets the text to be appended when null is added.
168      *
169      * @param nullText  the null text, null means no append
170      * @return this, to enable chaining
171      */
172     public StrBuilder setNullText(String nullText) {
173         if (nullText != null && nullText.isEmpty()) {
174             nullText = null;
175         }
176         this.nullText = nullText;
177         return this;
178     }
179 
180     //-----------------------------------------------------------------------
181     /**
182      * Gets the length of the string builder.
183      *
184      * @return the length
185      */
186     @Override
187     public int length() {
188         return size;
189     }
190 
191     /**
192      * Updates the length of the builder by either dropping the last characters
193      * or adding filler of Unicode zero.
194      *
195      * @param length  the length to set to, must be zero or positive
196      * @return this, to enable chaining
197      * @throws IndexOutOfBoundsException if the length is negative
198      */
199     public StrBuilder setLength(final int length) {
200         if (length < 0) {
201             throw new StringIndexOutOfBoundsException(length);
202         }
203         if (length < size) {
204             size = length;
205         } else if (length > size) {
206             ensureCapacity(length);
207             final int oldEnd = size;
208             final int newEnd = length;
209             size = length;
210             for (int i = oldEnd; i < newEnd; i++) {
211                 buffer[i] = '\0';
212             }
213         }
214         return this;
215     }
216 
217     //-----------------------------------------------------------------------
218     /**
219      * Gets the current size of the internal character array buffer.
220      *
221      * @return the capacity
222      */
223     public int capacity() {
224         return buffer.length;
225     }
226 
227     /**
228      * Checks the capacity and ensures that it is at least the size specified.
229      *
230      * @param capacity  the capacity to ensure
231      * @return this, to enable chaining
232      */
233     public StrBuilder ensureCapacity(final int capacity) {
234         if (capacity > buffer.length) {
235             final char[] old = buffer;
236             buffer = new char[capacity * 2];
237             System.arraycopy(old, 0, buffer, 0, size);
238         }
239         return this;
240     }
241 
242     /**
243      * Minimizes the capacity to the actual length of the string.
244      *
245      * @return this, to enable chaining
246      */
247     public StrBuilder minimizeCapacity() {
248         if (buffer.length > length()) {
249             final char[] old = buffer;
250             buffer = new char[length()];
251             System.arraycopy(old, 0, buffer, 0, size);
252         }
253         return this;
254     }
255 
256     //-----------------------------------------------------------------------
257     /**
258      * Gets the length of the string builder.
259      * <p>
260      * This method is the same as {@link #length()} and is provided to match the
261      * API of Collections.
262      *
263      * @return the length
264      */
265     public int size() {
266         return size;
267     }
268 
269     /**
270      * Checks is the string builder is empty (convenience Collections API style method).
271      * <p>
272      * This method is the same as checking {@link #length()} and is provided to match the
273      * API of Collections.
274      *
275      * @return <code>true</code> if the size is <code>0</code>.
276      */
277     public boolean isEmpty() {
278         return size == 0;
279     }
280 
281     /**
282      * Clears the string builder (convenience Collections API style method).
283      * <p>
284      * This method does not reduce the size of the internal character buffer.
285      * To do that, call <code>clear()</code> followed by {@link #minimizeCapacity()}.
286      * <p>
287      * This method is the same as {@link #setLength(int)} called with zero
288      * and is provided to match the API of Collections.
289      *
290      * @return this, to enable chaining
291      */
292     public StrBuilder clear() {
293         size = 0;
294         return this;
295     }
296 
297     //-----------------------------------------------------------------------
298     /**
299      * Gets the character at the specified index.
300      *
301      * @see #setCharAt(int, char)
302      * @see #deleteCharAt(int)
303      * @param index  the index to retrieve, must be valid
304      * @return the character at the index
305      * @throws IndexOutOfBoundsException if the index is invalid
306      */
307     @Override
308     public char charAt(final int index) {
309         if (index < 0 || index >= length()) {
310             throw new StringIndexOutOfBoundsException(index);
311         }
312         return buffer[index];
313     }
314 
315     /**
316      * Sets the character at the specified index.
317      *
318      * @see #charAt(int)
319      * @see #deleteCharAt(int)
320      * @param index  the index to set
321      * @param ch  the new character
322      * @return this, to enable chaining
323      * @throws IndexOutOfBoundsException if the index is invalid
324      */
325     public StrBuilder setCharAt(final int index, final char ch) {
326         if (index < 0 || index >= length()) {
327             throw new StringIndexOutOfBoundsException(index);
328         }
329         buffer[index] = ch;
330         return this;
331     }
332 
333     /**
334      * Deletes the character at the specified index.
335      *
336      * @see #charAt(int)
337      * @see #setCharAt(int, char)
338      * @param index  the index to delete
339      * @return this, to enable chaining
340      * @throws IndexOutOfBoundsException if the index is invalid
341      */
342     public StrBuilder deleteCharAt(final int index) {
343         if (index < 0 || index >= size) {
344             throw new StringIndexOutOfBoundsException(index);
345         }
346         deleteImpl(index, index + 1, 1);
347         return this;
348     }
349 
350     //-----------------------------------------------------------------------
351     /**
352      * Copies the builder's character array into a new character array.
353      * 
354      * @return a new array that represents the contents of the builder
355      */
356     public char[] toCharArray() {
357         if (size == 0) {
358             return ArrayUtils.EMPTY_CHAR_ARRAY;
359         }
360         final char chars[] = new char[size];
361         System.arraycopy(buffer, 0, chars, 0, size);
362         return chars;
363     }
364 
365     /**
366      * Copies part of the builder's character array into a new character array.
367      * 
368      * @param startIndex  the start index, inclusive, must be valid
369      * @param endIndex  the end index, exclusive, must be valid except that
370      *  if too large it is treated as end of string
371      * @return a new array that holds part of the contents of the builder
372      * @throws IndexOutOfBoundsException if startIndex is invalid,
373      *  or if endIndex is invalid (but endIndex greater than size is valid)
374      */
375     public char[] toCharArray(final int startIndex, int endIndex) {
376         endIndex = validateRange(startIndex, endIndex);
377         final int len = endIndex - startIndex;
378         if (len == 0) {
379             return ArrayUtils.EMPTY_CHAR_ARRAY;
380         }
381         final char chars[] = new char[len];
382         System.arraycopy(buffer, startIndex, chars, 0, len);
383         return chars;
384     }
385 
386     /**
387      * Copies the character array into the specified array.
388      * 
389      * @param destination  the destination array, null will cause an array to be created
390      * @return the input array, unless that was null or too small
391      */
392     public char[] getChars(char[] destination) {
393         final int len = length();
394         if (destination == null || destination.length < len) {
395             destination = new char[len];
396         }
397         System.arraycopy(buffer, 0, destination, 0, len);
398         return destination;
399     }
400 
401     /**
402      * Copies the character array into the specified array.
403      *
404      * @param startIndex  first index to copy, inclusive, must be valid
405      * @param endIndex  last index, exclusive, must be valid
406      * @param destination  the destination array, must not be null or too small
407      * @param destinationIndex  the index to start copying in destination
408      * @throws NullPointerException if the array is null
409      * @throws IndexOutOfBoundsException if any index is invalid
410      */
411     public void getChars(final int startIndex, final int endIndex, final char destination[], final int destinationIndex) {
412         if (startIndex < 0) {
413             throw new StringIndexOutOfBoundsException(startIndex);
414         }
415         if (endIndex < 0 || endIndex > length()) {
416             throw new StringIndexOutOfBoundsException(endIndex);
417         }
418         if (startIndex > endIndex) {
419             throw new StringIndexOutOfBoundsException("end < start");
420         }
421         System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex);
422     }
423 
424     //-----------------------------------------------------------------------
425     /**
426      * Appends the new line string to this string builder.
427      * <p>
428      * The new line string can be altered using {@link #setNewLineText(String)}.
429      * This might be used to force the output to always use Unix line endings
430      * even when on Windows.
431      *
432      * @return this, to enable chaining
433      */
434     public StrBuilder appendNewLine() {
435         if (newLine == null)  {
436             append(SystemUtils.LINE_SEPARATOR);
437             return this;
438         }
439         return append(newLine);
440     }
441 
442     /**
443      * Appends the text representing <code>null</code> to this string builder.
444      *
445      * @return this, to enable chaining
446      */
447     public StrBuilder appendNull() {
448         if (nullText == null)  {
449             return this;
450         }
451         return append(nullText);
452     }
453 
454     /**
455      * Appends an object to this string builder.
456      * Appending null will call {@link #appendNull()}.
457      *
458      * @param obj  the object to append
459      * @return this, to enable chaining
460      */
461     public StrBuilder append(final Object obj) {
462         if (obj == null) {
463             return appendNull();
464         } 
465         return append(obj.toString());        
466     }
467 
468     /**
469      * Appends a CharSequence to this string builder.
470      * Appending null will call {@link #appendNull()}.
471      *
472      * @param seq  the CharSequence to append
473      * @return this, to enable chaining
474      * @since 3.0
475      */
476     @Override
477     public StrBuilder append(final CharSequence seq) {
478         if (seq == null) {
479             return appendNull();
480         } 
481         return append(seq.toString());        
482     }
483 
484     /**
485      * Appends part of a CharSequence to this string builder.
486      * Appending null will call {@link #appendNull()}.
487      *
488      * @param seq  the CharSequence to append
489      * @param startIndex  the start index, inclusive, must be valid
490      * @param length  the length to append, must be valid
491      * @return this, to enable chaining
492      * @since 3.0
493      */
494     @Override
495     public StrBuilder append(final CharSequence seq, final int startIndex, final int length) {
496         if (seq == null) {
497             return appendNull();
498         } 
499         return append(seq.toString(), startIndex, length);
500     }
501     
502     /**
503      * Appends a string to this string builder.
504      * Appending null will call {@link #appendNull()}.
505      *
506      * @param str  the string to append
507      * @return this, to enable chaining
508      */
509     public StrBuilder append(final String str) {
510         if (str == null) {
511             return appendNull();
512         }
513         final int strLen = str.length();
514         if (strLen > 0) {
515             final int len = length();
516             ensureCapacity(len + strLen);
517             str.getChars(0, strLen, buffer, len);
518             size += strLen;
519         }
520         return this;
521     }
522    
523 
524     /**
525      * Appends part of a string to this string builder.
526      * Appending null will call {@link #appendNull()}.
527      *
528      * @param str  the string to append
529      * @param startIndex  the start index, inclusive, must be valid
530      * @param length  the length to append, must be valid
531      * @return this, to enable chaining
532      */
533     public StrBuilder append(final String str, final int startIndex, final int length) {
534         if (str == null) {
535             return appendNull();
536         }
537         if (startIndex < 0 || startIndex > str.length()) {
538             throw new StringIndexOutOfBoundsException("startIndex must be valid");
539         }
540         if (length < 0 || (startIndex + length) > str.length()) {
541             throw new StringIndexOutOfBoundsException("length must be valid");
542         }
543         if (length > 0) {
544             final int len = length();
545             ensureCapacity(len + length);
546             str.getChars(startIndex, startIndex + length, buffer, len);
547             size += length;
548         }
549         return this;
550     }
551 
552     /**
553      * Calls {@link String#format(String, Object...)} and appends the result.
554      *
555      * @param format the format string
556      * @param objs the objects to use in the format string
557      * @return {@code this} to enable chaining
558      * @see String#format(String, Object...)
559      * @since 3.2
560      */
561     public StrBuilder append(final String format, final Object... objs) {
562         return append(String.format(format, objs));
563     }
564 
565     /**
566      * Appends a string buffer to this string builder.
567      * Appending null will call {@link #appendNull()}.
568      *
569      * @param str  the string buffer to append
570      * @return this, to enable chaining
571      */
572     public StrBuilder append(final StringBuffer str) {
573         if (str == null) {
574             return appendNull();
575         }
576         final int strLen = str.length();
577         if (strLen > 0) {
578             final int len = length();
579             ensureCapacity(len + strLen);
580             str.getChars(0, strLen, buffer, len);
581             size += strLen;
582         }
583         return this;
584     }
585 
586     /**
587      * Appends part of a string buffer to this string builder.
588      * Appending null will call {@link #appendNull()}.
589      *
590      * @param str  the string to append
591      * @param startIndex  the start index, inclusive, must be valid
592      * @param length  the length to append, must be valid
593      * @return this, to enable chaining
594      */
595     public StrBuilder append(final StringBuffer str, final int startIndex, final int length) {
596         if (str == null) {
597             return appendNull();
598         }
599         if (startIndex < 0 || startIndex > str.length()) {
600             throw new StringIndexOutOfBoundsException("startIndex must be valid");
601         }
602         if (length < 0 || (startIndex + length) > str.length()) {
603             throw new StringIndexOutOfBoundsException("length must be valid");
604         }
605         if (length > 0) {
606             final int len = length();
607             ensureCapacity(len + length);
608             str.getChars(startIndex, startIndex + length, buffer, len);
609             size += length;
610         }
611         return this;
612     }
613 
614     /**
615      * Appends a StringBuilder to this string builder.
616      * Appending null will call {@link #appendNull()}.
617      *
618      * @param str the StringBuilder to append
619      * @return this, to enable chaining
620      * @since 3.2
621      */
622     public StrBuilder append(final StringBuilder str) {
623         if (str == null) {
624             return appendNull();
625         }
626         final int strLen = str.length();
627         if (strLen > 0) {
628             final int len = length();
629             ensureCapacity(len + strLen);
630             str.getChars(0, strLen, buffer, len);
631             size += strLen;
632         }
633         return this;
634     }
635     
636     /**
637      * Appends part of a StringBuilder to this string builder.
638      * Appending null will call {@link #appendNull()}.
639      *
640      * @param str the StringBuilder to append
641      * @param startIndex the start index, inclusive, must be valid
642      * @param length the length to append, must be valid
643      * @return this, to enable chaining
644      * @since 3.2
645      */
646     public StrBuilder append(final StringBuilder str, final int startIndex, final int length) {
647         if (str == null) {
648             return appendNull();
649         }
650         if (startIndex < 0 || startIndex > str.length()) {
651             throw new StringIndexOutOfBoundsException("startIndex must be valid");
652         }
653         if (length < 0 || (startIndex + length) > str.length()) {
654             throw new StringIndexOutOfBoundsException("length must be valid");
655         }
656         if (length > 0) {
657             final int len = length();
658             ensureCapacity(len + length);
659             str.getChars(startIndex, startIndex + length, buffer, len);
660             size += length;
661         }
662         return this;
663     }
664 
665     /**
666      * Appends another string builder to this string builder.
667      * Appending null will call {@link #appendNull()}.
668      *
669      * @param str  the string builder to append
670      * @return this, to enable chaining
671      */
672     public StrBuilder append(final StrBuilder str) {
673         if (str == null) {
674             return appendNull();
675         }
676         final int strLen = str.length();
677         if (strLen > 0) {
678             final int len = length();
679             ensureCapacity(len + strLen);
680             System.arraycopy(str.buffer, 0, buffer, len, strLen);
681             size += strLen;
682         }
683         return this;
684     }
685 
686     /**
687      * Appends part of a string builder to this string builder.
688      * Appending null will call {@link #appendNull()}.
689      *
690      * @param str  the string to append
691      * @param startIndex  the start index, inclusive, must be valid
692      * @param length  the length to append, must be valid
693      * @return this, to enable chaining
694      */
695     public StrBuilder append(final StrBuilder str, final int startIndex, final int length) {
696         if (str == null) {
697             return appendNull();
698         }
699         if (startIndex < 0 || startIndex > str.length()) {
700             throw new StringIndexOutOfBoundsException("startIndex must be valid");
701         }
702         if (length < 0 || (startIndex + length) > str.length()) {
703             throw new StringIndexOutOfBoundsException("length must be valid");
704         }
705         if (length > 0) {
706             final int len = length();
707             ensureCapacity(len + length);
708             str.getChars(startIndex, startIndex + length, buffer, len);
709             size += length;
710         }
711         return this;
712     }
713 
714     /**
715      * Appends a char array to the string builder.
716      * Appending null will call {@link #appendNull()}.
717      *
718      * @param chars  the char array to append
719      * @return this, to enable chaining
720      */
721     public StrBuilder append(final char[] chars) {
722         if (chars == null) {
723             return appendNull();
724         }
725         final int strLen = chars.length;
726         if (strLen > 0) {
727             final int len = length();
728             ensureCapacity(len + strLen);
729             System.arraycopy(chars, 0, buffer, len, strLen);
730             size += strLen;
731         }
732         return this;
733     }
734 
735     /**
736      * Appends a char array to the string builder.
737      * Appending null will call {@link #appendNull()}.
738      *
739      * @param chars  the char array to append
740      * @param startIndex  the start index, inclusive, must be valid
741      * @param length  the length to append, must be valid
742      * @return this, to enable chaining
743      */
744     public StrBuilder append(final char[] chars, final int startIndex, final int length) {
745         if (chars == null) {
746             return appendNull();
747         }
748         if (startIndex < 0 || startIndex > chars.length) {
749             throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length);
750         }
751         if (length < 0 || (startIndex + length) > chars.length) {
752             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
753         }
754         if (length > 0) {
755             final int len = length();
756             ensureCapacity(len + length);
757             System.arraycopy(chars, startIndex, buffer, len, length);
758             size += length;
759         }
760         return this;
761     }
762 
763     /**
764      * Appends a boolean value to the string builder.
765      *
766      * @param value  the value to append
767      * @return this, to enable chaining
768      */
769     public StrBuilder append(final boolean value) {
770         if (value) {
771             ensureCapacity(size + 4);
772             buffer[size++] = 't';
773             buffer[size++] = 'r';
774             buffer[size++] = 'u';
775             buffer[size++] = 'e';
776         } else {
777             ensureCapacity(size + 5);
778             buffer[size++] = 'f';
779             buffer[size++] = 'a';
780             buffer[size++] = 'l';
781             buffer[size++] = 's';
782             buffer[size++] = 'e';
783         }
784         return this;
785     }
786 
787     /**
788      * Appends a char value to the string builder.
789      *
790      * @param ch  the value to append
791      * @return this, to enable chaining
792      * @since 3.0
793      */
794     @Override
795     public StrBuilder append(final char ch) {
796         final int len = length();
797         ensureCapacity(len + 1);
798         buffer[size++] = ch;
799         return this;
800     }
801 
802     /**
803      * Appends an int value to the string builder using <code>String.valueOf</code>.
804      *
805      * @param value  the value to append
806      * @return this, to enable chaining
807      */
808     public StrBuilder append(final int value) {
809         return append(String.valueOf(value));
810     }
811 
812     /**
813      * Appends a long value to the string builder using <code>String.valueOf</code>.
814      *
815      * @param value  the value to append
816      * @return this, to enable chaining
817      */
818     public StrBuilder append(final long value) {
819         return append(String.valueOf(value));
820     }
821 
822     /**
823      * Appends a float value to the string builder using <code>String.valueOf</code>.
824      *
825      * @param value  the value to append
826      * @return this, to enable chaining
827      */
828     public StrBuilder append(final float value) {
829         return append(String.valueOf(value));
830     }
831 
832     /**
833      * Appends a double value to the string builder using <code>String.valueOf</code>.
834      *
835      * @param value  the value to append
836      * @return this, to enable chaining
837      */
838     public StrBuilder append(final double value) {
839         return append(String.valueOf(value));
840     }
841 
842     //-----------------------------------------------------------------------
843     /**
844      * Appends an object followed by a new line to this string builder.
845      * Appending null will call {@link #appendNull()}.
846      *
847      * @param obj  the object to append
848      * @return this, to enable chaining
849      * @since 2.3
850      */
851     public StrBuilder appendln(final Object obj) {
852         return append(obj).appendNewLine();
853     }
854 
855     /**
856      * Appends a string followed by a new line to this string builder.
857      * Appending null will call {@link #appendNull()}.
858      *
859      * @param str  the string to append
860      * @return this, to enable chaining
861      * @since 2.3
862      */
863     public StrBuilder appendln(final String str) {
864         return append(str).appendNewLine();
865     }
866 
867     /**
868      * Appends part of a string followed by a new line to this string builder.
869      * Appending null will call {@link #appendNull()}.
870      *
871      * @param str  the string to append
872      * @param startIndex  the start index, inclusive, must be valid
873      * @param length  the length to append, must be valid
874      * @return this, to enable chaining
875      * @since 2.3
876      */
877     public StrBuilder appendln(final String str, final int startIndex, final int length) {
878         return append(str, startIndex, length).appendNewLine();
879     }
880 
881     /**
882      * Calls {@link String#format(String, Object...)} and appends the result.
883      *
884      * @param format the format string
885      * @param objs the objects to use in the format string
886      * @return {@code this} to enable chaining
887      * @see String#format(String, Object...)
888      * @since 3.2
889      */
890     public StrBuilder appendln(final String format, final Object... objs) {
891         return append(format, objs).appendNewLine();
892     }
893 
894     /**
895      * Appends a string buffer followed by a new line to this string builder.
896      * Appending null will call {@link #appendNull()}.
897      *
898      * @param str  the string buffer to append
899      * @return this, to enable chaining
900      * @since 2.3
901      */
902     public StrBuilder appendln(final StringBuffer str) {
903         return append(str).appendNewLine();
904     }
905 
906     /**
907      * Appends a string builder followed by a new line to this string builder.
908      * Appending null will call {@link #appendNull()}.
909      *
910      * @param str  the string builder to append
911      * @return this, to enable chaining
912      * @since 3.2
913      */
914     public StrBuilder appendln(final StringBuilder str) {
915         return append(str).appendNewLine();
916     }
917 
918     /**
919      * Appends part of a string builder followed by a new line to this string builder.
920      * Appending null will call {@link #appendNull()}.
921      *
922      * @param str  the string builder to append
923      * @param startIndex  the start index, inclusive, must be valid
924      * @param length  the length to append, must be valid
925      * @return this, to enable chaining
926      * @since 3.2
927      */
928     public StrBuilder appendln(final StringBuilder str, final int startIndex, final int length) {
929         return append(str, startIndex, length).appendNewLine();
930     }
931 
932     /**
933      * Appends part of a string buffer followed by a new line to this string builder.
934      * Appending null will call {@link #appendNull()}.
935      *
936      * @param str  the string to append
937      * @param startIndex  the start index, inclusive, must be valid
938      * @param length  the length to append, must be valid
939      * @return this, to enable chaining
940      * @since 2.3
941      */
942     public StrBuilder appendln(final StringBuffer str, final int startIndex, final int length) {
943         return append(str, startIndex, length).appendNewLine();
944     }
945 
946     /**
947      * Appends another string builder followed by a new line to this string builder.
948      * Appending null will call {@link #appendNull()}.
949      *
950      * @param str  the string builder to append
951      * @return this, to enable chaining
952      * @since 2.3
953      */
954     public StrBuilder appendln(final StrBuilder str) {
955         return append(str).appendNewLine();
956     }
957 
958     /**
959      * Appends part of a string builder followed by a new line to this string builder.
960      * Appending null will call {@link #appendNull()}.
961      *
962      * @param str  the string to append
963      * @param startIndex  the start index, inclusive, must be valid
964      * @param length  the length to append, must be valid
965      * @return this, to enable chaining
966      * @since 2.3
967      */
968     public StrBuilder appendln(final StrBuilder str, final int startIndex, final int length) {
969         return append(str, startIndex, length).appendNewLine();
970     }
971 
972     /**
973      * Appends a char array followed by a new line to the string builder.
974      * Appending null will call {@link #appendNull()}.
975      *
976      * @param chars  the char array to append
977      * @return this, to enable chaining
978      * @since 2.3
979      */
980     public StrBuilder appendln(final char[] chars) {
981         return append(chars).appendNewLine();
982     }
983 
984     /**
985      * Appends a char array followed by a new line to the string builder.
986      * Appending null will call {@link #appendNull()}.
987      *
988      * @param chars  the char array to append
989      * @param startIndex  the start index, inclusive, must be valid
990      * @param length  the length to append, must be valid
991      * @return this, to enable chaining
992      * @since 2.3
993      */
994     public StrBuilder appendln(final char[] chars, final int startIndex, final int length) {
995         return append(chars, startIndex, length).appendNewLine();
996     }
997 
998     /**
999      * Appends a boolean value followed by a new line to the string builder.
1000      *
1001      * @param value  the value to append
1002      * @return this, to enable chaining
1003      * @since 2.3
1004      */
1005     public StrBuilder appendln(final boolean value) {
1006         return append(value).appendNewLine();
1007     }
1008 
1009     /**
1010      * Appends a char value followed by a new line to the string builder.
1011      *
1012      * @param ch  the value to append
1013      * @return this, to enable chaining
1014      * @since 2.3
1015      */
1016     public StrBuilder appendln(final char ch) {
1017         return append(ch).appendNewLine();
1018     }
1019 
1020     /**
1021      * Appends an int value followed by a new line to the string builder using <code>String.valueOf</code>.
1022      *
1023      * @param value  the value to append
1024      * @return this, to enable chaining
1025      * @since 2.3
1026      */
1027     public StrBuilder appendln(final int value) {
1028         return append(value).appendNewLine();
1029     }
1030 
1031     /**
1032      * Appends a long value followed by a new line to the string builder using <code>String.valueOf</code>.
1033      *
1034      * @param value  the value to append
1035      * @return this, to enable chaining
1036      * @since 2.3
1037      */
1038     public StrBuilder appendln(final long value) {
1039         return append(value).appendNewLine();
1040     }
1041 
1042     /**
1043      * Appends a float value followed by a new line to the string builder using <code>String.valueOf</code>.
1044      *
1045      * @param value  the value to append
1046      * @return this, to enable chaining
1047      * @since 2.3
1048      */
1049     public StrBuilder appendln(final float value) {
1050         return append(value).appendNewLine();
1051     }
1052 
1053     /**
1054      * Appends a double value followed by a new line to the string builder using <code>String.valueOf</code>.
1055      *
1056      * @param value  the value to append
1057      * @return this, to enable chaining
1058      * @since 2.3
1059      */
1060     public StrBuilder appendln(final double value) {
1061         return append(value).appendNewLine();
1062     }
1063 
1064     //-----------------------------------------------------------------------
1065     /**
1066      * Appends each item in an array to the builder without any separators.
1067      * Appending a null array will have no effect.
1068      * Each object is appended using {@link #append(Object)}.
1069      *
1070      * @param <T>  the element type
1071      * @param array  the array to append
1072      * @return this, to enable chaining
1073      * @since 2.3
1074      */
1075     public <T> StrBuilder appendAll(final T... array) {
1076         if (array != null && array.length > 0) {
1077             for (final Object element : array) {
1078                 append(element);
1079             }
1080         }
1081         return this;
1082     }
1083 
1084     /**
1085      * Appends each item in a iterable to the builder without any separators.
1086      * Appending a null iterable will have no effect.
1087      * Each object is appended using {@link #append(Object)}.
1088      *
1089      * @param iterable  the iterable to append
1090      * @return this, to enable chaining
1091      * @since 2.3
1092      */
1093     public StrBuilder appendAll(final Iterable<?> iterable) {
1094         if (iterable != null) {
1095             for (final Object o : iterable) {
1096                 append(o);
1097             }
1098         }
1099         return this;
1100     }
1101 
1102     /**
1103      * Appends each item in an iterator to the builder without any separators.
1104      * Appending a null iterator will have no effect.
1105      * Each object is appended using {@link #append(Object)}.
1106      *
1107      * @param it  the iterator to append
1108      * @return this, to enable chaining
1109      * @since 2.3
1110      */
1111     public StrBuilder appendAll(final Iterator<?> it) {
1112         if (it != null) {
1113             while (it.hasNext()) {
1114                 append(it.next());
1115             }
1116         }
1117         return this;
1118     }
1119 
1120     //-----------------------------------------------------------------------
1121     /**
1122      * Appends an array placing separators between each value, but
1123      * not before the first or after the last.
1124      * Appending a null array will have no effect.
1125      * Each object is appended using {@link #append(Object)}.
1126      *
1127      * @param array  the array to append
1128      * @param separator  the separator to use, null means no separator
1129      * @return this, to enable chaining
1130      */
1131     public StrBuilder appendWithSeparators(final Object[] array, final String separator) {
1132         if (array != null && array.length > 0) {
1133             @SuppressWarnings( "deprecation" ) // ObjectUtils.toString(Object) has been deprecated in 3.2
1134             final String sep = ObjectUtils.toString(separator);
1135             append(array[0]);
1136             for (int i = 1; i < array.length; i++) {
1137                 append(sep);
1138                 append(array[i]);
1139             }
1140         }
1141         return this;
1142     }
1143 
1144     /**
1145      * Appends a iterable placing separators between each value, but
1146      * not before the first or after the last.
1147      * Appending a null iterable will have no effect.
1148      * Each object is appended using {@link #append(Object)}.
1149      *
1150      * @param iterable  the iterable to append
1151      * @param separator  the separator to use, null means no separator
1152      * @return this, to enable chaining
1153      */
1154     public StrBuilder appendWithSeparators(final Iterable<?> iterable, final String separator) {
1155         if (iterable != null) {
1156             @SuppressWarnings( "deprecation" ) // ObjectUtils.toString(Object) has been deprecated in 3.2
1157             final String sep = ObjectUtils.toString(separator);
1158             final Iterator<?> it = iterable.iterator();
1159             while (it.hasNext()) {
1160                 append(it.next());
1161                 if (it.hasNext()) {
1162                     append(sep);
1163                 }
1164             }
1165         }
1166         return this;
1167     }
1168 
1169     /**
1170      * Appends an iterator placing separators between each value, but
1171      * not before the first or after the last.
1172      * Appending a null iterator will have no effect.
1173      * Each object is appended using {@link #append(Object)}.
1174      *
1175      * @param it  the iterator to append
1176      * @param separator  the separator to use, null means no separator
1177      * @return this, to enable chaining
1178      */
1179     public StrBuilder appendWithSeparators(final Iterator<?> it, final String separator) {
1180         if (it != null) {
1181             @SuppressWarnings( "deprecation" ) // ObjectUtils.toString(Object) has been deprecated in 3.2
1182             final String sep = ObjectUtils.toString(separator);
1183             while (it.hasNext()) {
1184                 append(it.next());
1185                 if (it.hasNext()) {
1186                     append(sep);
1187                 }
1188             }
1189         }
1190         return this;
1191     }
1192 
1193     //-----------------------------------------------------------------------
1194     /**
1195      * Appends a separator if the builder is currently non-empty.
1196      * Appending a null separator will have no effect.
1197      * The separator is appended using {@link #append(String)}.
1198      * <p>
1199      * This method is useful for adding a separator each time around the
1200      * loop except the first.
1201      * <pre>
1202      * for (Iterator it = list.iterator(); it.hasNext(); ) {
1203      *   appendSeparator(",");
1204      *   append(it.next());
1205      * }
1206      * </pre>
1207      * Note that for this simple example, you should use
1208      * {@link #appendWithSeparators(Iterable, String)}.
1209      * 
1210      * @param separator  the separator to use, null means no separator
1211      * @return this, to enable chaining
1212      * @since 2.3
1213      */
1214     public StrBuilder appendSeparator(final String separator) {
1215         return appendSeparator(separator, null);
1216     }
1217 
1218     /**
1219      * Appends one of both separators to the StrBuilder.
1220      * If the builder is currently empty it will append the defaultIfEmpty-separator
1221      * Otherwise it will append the standard-separator
1222      * 
1223      * Appending a null separator will have no effect.
1224      * The separator is appended using {@link #append(String)}.
1225      * <p>
1226      * This method is for example useful for constructing queries
1227      * <pre>
1228      * StrBuilder whereClause = new StrBuilder();
1229      * if(searchCommand.getPriority() != null) {
1230      *  whereClause.appendSeparator(" and", " where");
1231      *  whereClause.append(" priority = ?")
1232      * }
1233      * if(searchCommand.getComponent() != null) {
1234      *  whereClause.appendSeparator(" and", " where");
1235      *  whereClause.append(" component = ?")
1236      * }
1237      * selectClause.append(whereClause)
1238      * </pre>
1239      * 
1240      * @param standard the separator if builder is not empty, null means no separator
1241      * @param defaultIfEmpty the separator if builder is empty, null means no separator
1242      * @return this, to enable chaining
1243      * @since 2.5
1244      */
1245     public StrBuilder appendSeparator(final String standard, final String defaultIfEmpty) {
1246         final String str = isEmpty() ? defaultIfEmpty : standard;
1247         if (str != null) {
1248             append(str);
1249         }
1250         return this;
1251     }
1252 
1253     /**
1254      * Appends a separator if the builder is currently non-empty.
1255      * The separator is appended using {@link #append(char)}.
1256      * <p>
1257      * This method is useful for adding a separator each time around the
1258      * loop except the first.
1259      * <pre>
1260      * for (Iterator it = list.iterator(); it.hasNext(); ) {
1261      *   appendSeparator(',');
1262      *   append(it.next());
1263      * }
1264      * </pre>
1265      * Note that for this simple example, you should use
1266      * {@link #appendWithSeparators(Iterable, String)}.
1267      * 
1268      * @param separator  the separator to use
1269      * @return this, to enable chaining
1270      * @since 2.3
1271      */
1272     public StrBuilder appendSeparator(final char separator) {
1273         if (size() > 0) {
1274             append(separator);
1275         }
1276         return this;
1277     }
1278 
1279     /**
1280      * Append one of both separators to the builder
1281      * If the builder is currently empty it will append the defaultIfEmpty-separator
1282      * Otherwise it will append the standard-separator
1283      *
1284      * The separator is appended using {@link #append(char)}.
1285      * @param standard the separator if builder is not empty
1286      * @param defaultIfEmpty the separator if builder is empty
1287      * @return this, to enable chaining
1288      * @since 2.5
1289      */
1290     public StrBuilder appendSeparator(final char standard, final char defaultIfEmpty) {
1291         if (size() > 0) {
1292             append(standard);
1293         } else {
1294             append(defaultIfEmpty);
1295         }
1296         return this;
1297     }
1298     /**
1299      * Appends a separator to the builder if the loop index is greater than zero.
1300      * Appending a null separator will have no effect.
1301      * The separator is appended using {@link #append(String)}.
1302      * <p>
1303      * This method is useful for adding a separator each time around the
1304      * loop except the first.
1305      * </p>
1306      * <pre>
1307      * for (int i = 0; i &lt; list.size(); i++) {
1308      *   appendSeparator(",", i);
1309      *   append(list.get(i));
1310      * }
1311      * </pre>
1312      * Note that for this simple example, you should use
1313      * {@link #appendWithSeparators(Iterable, String)}.
1314      * 
1315      * @param separator  the separator to use, null means no separator
1316      * @param loopIndex  the loop index
1317      * @return this, to enable chaining
1318      * @since 2.3
1319      */
1320     public StrBuilder appendSeparator(final String separator, final int loopIndex) {
1321         if (separator != null && loopIndex > 0) {
1322             append(separator);
1323         }
1324         return this;
1325     }
1326 
1327     /**
1328      * Appends a separator to the builder if the loop index is greater than zero.
1329      * The separator is appended using {@link #append(char)}.
1330      * <p>
1331      * This method is useful for adding a separator each time around the
1332      * loop except the first.
1333      * </p>
1334      * <pre>
1335      * for (int i = 0; i &lt; list.size(); i++) {
1336      *   appendSeparator(",", i);
1337      *   append(list.get(i));
1338      * }
1339      * </pre>
1340      * Note that for this simple example, you should use
1341      * {@link #appendWithSeparators(Iterable, String)}.
1342      * 
1343      * @param separator  the separator to use
1344      * @param loopIndex  the loop index
1345      * @return this, to enable chaining
1346      * @since 2.3
1347      */
1348     public StrBuilder appendSeparator(final char separator, final int loopIndex) {
1349         if (loopIndex > 0) {
1350             append(separator);
1351         }
1352         return this;
1353     }
1354 
1355     //-----------------------------------------------------------------------
1356     /**
1357      * Appends the pad character to the builder the specified number of times.
1358      * 
1359      * @param length  the length to append, negative means no append
1360      * @param padChar  the character to append
1361      * @return this, to enable chaining
1362      */
1363     public StrBuilder appendPadding(final int length, final char padChar) {
1364         if (length >= 0) {
1365             ensureCapacity(size + length);
1366             for (int i = 0; i < length; i++) {
1367                 buffer[size++] = padChar;
1368             }
1369         }
1370         return this;
1371     }
1372 
1373     //-----------------------------------------------------------------------
1374     /**
1375      * Appends an object to the builder padding on the left to a fixed width.
1376      * The <code>toString</code> of the object is used.
1377      * If the object is larger than the length, the left hand side is lost.
1378      * If the object is null, the null text value is used.
1379      * 
1380      * @param obj  the object to append, null uses null text
1381      * @param width  the fixed field width, zero or negative has no effect
1382      * @param padChar  the pad character to use
1383      * @return this, to enable chaining
1384      */
1385     public StrBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) {
1386         if (width > 0) {
1387             ensureCapacity(size + width);
1388             String str = (obj == null ? getNullText() : obj.toString());
1389             if (str == null) {
1390                 str = "";
1391             }
1392             final int strLen = str.length();
1393             if (strLen >= width) {
1394                 str.getChars(strLen - width, strLen, buffer, size);
1395             } else {
1396                 final int padLen = width - strLen;
1397                 for (int i = 0; i < padLen; i++) {
1398                     buffer[size + i] = padChar;
1399                 }
1400                 str.getChars(0, strLen, buffer, size + padLen);
1401             }
1402             size += width;
1403         }
1404         return this;
1405     }
1406 
1407     /**
1408      * Appends an object to the builder padding on the left to a fixed width.
1409      * The <code>String.valueOf</code> of the <code>int</code> value is used.
1410      * If the formatted value is larger than the length, the left hand side is lost.
1411      * 
1412      * @param value  the value to append
1413      * @param width  the fixed field width, zero or negative has no effect
1414      * @param padChar  the pad character to use
1415      * @return this, to enable chaining
1416      */
1417     public StrBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) {
1418         return appendFixedWidthPadLeft(String.valueOf(value), width, padChar);
1419     }
1420 
1421     /**
1422      * Appends an object to the builder padding on the right to a fixed length.
1423      * The <code>toString</code> of the object is used.
1424      * If the object is larger than the length, the right hand side is lost.
1425      * If the object is null, null text value is used.
1426      * 
1427      * @param obj  the object to append, null uses null text
1428      * @param width  the fixed field width, zero or negative has no effect
1429      * @param padChar  the pad character to use
1430      * @return this, to enable chaining
1431      */
1432     public StrBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) {
1433         if (width > 0) {
1434             ensureCapacity(size + width);
1435             String str = (obj == null ? getNullText() : obj.toString());
1436             if (str == null) {
1437                 str = "";
1438             }
1439             final int strLen = str.length();
1440             if (strLen >= width) {
1441                 str.getChars(0, width, buffer, size);
1442             } else {
1443                 final int padLen = width - strLen;
1444                 str.getChars(0, strLen, buffer, size);
1445                 for (int i = 0; i < padLen; i++) {
1446                     buffer[size + strLen + i] = padChar;
1447                 }
1448             }
1449             size += width;
1450         }
1451         return this;
1452     }
1453 
1454     /**
1455      * Appends an object to the builder padding on the right to a fixed length.
1456      * The <code>String.valueOf</code> of the <code>int</code> value is used.
1457      * If the object is larger than the length, the right hand side is lost.
1458      * 
1459      * @param value  the value to append
1460      * @param width  the fixed field width, zero or negative has no effect
1461      * @param padChar  the pad character to use
1462      * @return this, to enable chaining
1463      */
1464     public StrBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) {
1465         return appendFixedWidthPadRight(String.valueOf(value), width, padChar);
1466     }
1467 
1468     //-----------------------------------------------------------------------
1469     /**
1470      * Inserts the string representation of an object into this builder.
1471      * Inserting null will use the stored null text value.
1472      *
1473      * @param index  the index to add at, must be valid
1474      * @param obj  the object to insert
1475      * @return this, to enable chaining
1476      * @throws IndexOutOfBoundsException if the index is invalid
1477      */
1478     public StrBuilder insert(final int index, final Object obj) {
1479         if (obj == null) {
1480             return insert(index, nullText);
1481         }
1482         return insert(index, obj.toString());
1483     }
1484 
1485     /**
1486      * Inserts the string into this builder.
1487      * Inserting null will use the stored null text value.
1488      *
1489      * @param index  the index to add at, must be valid
1490      * @param str  the string to insert
1491      * @return this, to enable chaining
1492      * @throws IndexOutOfBoundsException if the index is invalid
1493      */
1494     public StrBuilder insert(final int index, String str) {
1495         validateIndex(index);
1496         if (str == null) {
1497             str = nullText;
1498         }
1499         if (str != null) {
1500             final int strLen = str.length();
1501             if (strLen > 0) {
1502                 final int newSize = size + strLen;
1503                 ensureCapacity(newSize);
1504                 System.arraycopy(buffer, index, buffer, index + strLen, size - index);
1505                 size = newSize;
1506                 str.getChars(0, strLen, buffer, index);
1507             }
1508         }
1509         return this;
1510     }
1511 
1512     /**
1513      * Inserts the character array into this builder.
1514      * Inserting null will use the stored null text value.
1515      *
1516      * @param index  the index to add at, must be valid
1517      * @param chars  the char array to insert
1518      * @return this, to enable chaining
1519      * @throws IndexOutOfBoundsException if the index is invalid
1520      */
1521     public StrBuilder insert(final int index, final char chars[]) {
1522         validateIndex(index);
1523         if (chars == null) {
1524             return insert(index, nullText);
1525         }
1526         final int len = chars.length;
1527         if (len > 0) {
1528             ensureCapacity(size + len);
1529             System.arraycopy(buffer, index, buffer, index + len, size - index);
1530             System.arraycopy(chars, 0, buffer, index, len);
1531             size += len;
1532         }
1533         return this;
1534     }
1535 
1536     /**
1537      * Inserts part of the character array into this builder.
1538      * Inserting null will use the stored null text value.
1539      *
1540      * @param index  the index to add at, must be valid
1541      * @param chars  the char array to insert
1542      * @param offset  the offset into the character array to start at, must be valid
1543      * @param length  the length of the character array part to copy, must be positive
1544      * @return this, to enable chaining
1545      * @throws IndexOutOfBoundsException if any index is invalid
1546      */
1547     public StrBuilder insert(final int index, final char chars[], final int offset, final int length) {
1548         validateIndex(index);
1549         if (chars == null) {
1550             return insert(index, nullText);
1551         }
1552         if (offset < 0 || offset > chars.length) {
1553             throw new StringIndexOutOfBoundsException("Invalid offset: " + offset);
1554         }
1555         if (length < 0 || offset + length > chars.length) {
1556             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
1557         }
1558         if (length > 0) {
1559             ensureCapacity(size + length);
1560             System.arraycopy(buffer, index, buffer, index + length, size - index);
1561             System.arraycopy(chars, offset, buffer, index, length);
1562             size += length;
1563         }
1564         return this;
1565     }
1566 
1567     /**
1568      * Inserts the value into this builder.
1569      *
1570      * @param index  the index to add at, must be valid
1571      * @param value  the value to insert
1572      * @return this, to enable chaining
1573      * @throws IndexOutOfBoundsException if the index is invalid
1574      */
1575     public StrBuilder insert(int index, final boolean value) {
1576         validateIndex(index);
1577         if (value) {
1578             ensureCapacity(size + 4);
1579             System.arraycopy(buffer, index, buffer, index + 4, size - index);
1580             buffer[index++] = 't';
1581             buffer[index++] = 'r';
1582             buffer[index++] = 'u';
1583             buffer[index] = 'e';
1584             size += 4;
1585         } else {
1586             ensureCapacity(size + 5);
1587             System.arraycopy(buffer, index, buffer, index + 5, size - index);
1588             buffer[index++] = 'f';
1589             buffer[index++] = 'a';
1590             buffer[index++] = 'l';
1591             buffer[index++] = 's';
1592             buffer[index] = 'e';
1593             size += 5;
1594         }
1595         return this;
1596     }
1597 
1598     /**
1599      * Inserts the value into this builder.
1600      *
1601      * @param index  the index to add at, must be valid
1602      * @param value  the value to insert
1603      * @return this, to enable chaining
1604      * @throws IndexOutOfBoundsException if the index is invalid
1605      */
1606     public StrBuilder insert(final int index, final char value) {
1607         validateIndex(index);
1608         ensureCapacity(size + 1);
1609         System.arraycopy(buffer, index, buffer, index + 1, size - index);
1610         buffer[index] = value;
1611         size++;
1612         return this;
1613     }
1614 
1615     /**
1616      * Inserts the value into this builder.
1617      *
1618      * @param index  the index to add at, must be valid
1619      * @param value  the value to insert
1620      * @return this, to enable chaining
1621      * @throws IndexOutOfBoundsException if the index is invalid
1622      */
1623     public StrBuilder insert(final int index, final int value) {
1624         return insert(index, String.valueOf(value));
1625     }
1626 
1627     /**
1628      * Inserts the value into this builder.
1629      *
1630      * @param index  the index to add at, must be valid
1631      * @param value  the value to insert
1632      * @return this, to enable chaining
1633      * @throws IndexOutOfBoundsException if the index is invalid
1634      */
1635     public StrBuilder insert(final int index, final long value) {
1636         return insert(index, String.valueOf(value));
1637     }
1638 
1639     /**
1640      * Inserts the value into this builder.
1641      *
1642      * @param index  the index to add at, must be valid
1643      * @param value  the value to insert
1644      * @return this, to enable chaining
1645      * @throws IndexOutOfBoundsException if the index is invalid
1646      */
1647     public StrBuilder insert(final int index, final float value) {
1648         return insert(index, String.valueOf(value));
1649     }
1650 
1651     /**
1652      * Inserts the value into this builder.
1653      *
1654      * @param index  the index to add at, must be valid
1655      * @param value  the value to insert
1656      * @return this, to enable chaining
1657      * @throws IndexOutOfBoundsException if the index is invalid
1658      */
1659     public StrBuilder insert(final int index, final double value) {
1660         return insert(index, String.valueOf(value));
1661     }
1662 
1663     //-----------------------------------------------------------------------
1664     /**
1665      * Internal method to delete a range without validation.
1666      *
1667      * @param startIndex  the start index, must be valid
1668      * @param endIndex  the end index (exclusive), must be valid
1669      * @param len  the length, must be valid
1670      * @throws IndexOutOfBoundsException if any index is invalid
1671      */
1672     private void deleteImpl(final int startIndex, final int endIndex, final int len) {
1673         System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex);
1674         size -= len;
1675     }
1676 
1677     /**
1678      * Deletes the characters between the two specified indices.
1679      *
1680      * @param startIndex  the start index, inclusive, must be valid
1681      * @param endIndex  the end index, exclusive, must be valid except
1682      *  that if too large it is treated as end of string
1683      * @return this, to enable chaining
1684      * @throws IndexOutOfBoundsException if the index is invalid
1685      */
1686     public StrBuilder delete(final int startIndex, int endIndex) {
1687         endIndex = validateRange(startIndex, endIndex);
1688         final int len = endIndex - startIndex;
1689         if (len > 0) {
1690             deleteImpl(startIndex, endIndex, len);
1691         }
1692         return this;
1693     }
1694 
1695     //-----------------------------------------------------------------------
1696     /**
1697      * Deletes the character wherever it occurs in the builder.
1698      *
1699      * @param ch  the character to delete
1700      * @return this, to enable chaining
1701      */
1702     public StrBuilder deleteAll(final char ch) {
1703         for (int i = 0; i < size; i++) {
1704             if (buffer[i] == ch) {
1705                 final int start = i;
1706                 while (++i < size) {
1707                     if (buffer[i] != ch) {
1708                         break;
1709                     }
1710                 }
1711                 final int len = i - start;
1712                 deleteImpl(start, i, len);
1713                 i -= len;
1714             }
1715         }
1716         return this;
1717     }
1718 
1719     /**
1720      * Deletes the character wherever it occurs in the builder.
1721      *
1722      * @param ch  the character to delete
1723      * @return this, to enable chaining
1724      */
1725     public StrBuilder deleteFirst(final char ch) {
1726         for (int i = 0; i < size; i++) {
1727             if (buffer[i] == ch) {
1728                 deleteImpl(i, i + 1, 1);
1729                 break;
1730             }
1731         }
1732         return this;
1733     }
1734 
1735     //-----------------------------------------------------------------------
1736     /**
1737      * Deletes the string wherever it occurs in the builder.
1738      *
1739      * @param str  the string to delete, null causes no action
1740      * @return this, to enable chaining
1741      */
1742     public StrBuilder deleteAll(final String str) {
1743         final int len = (str == null ? 0 : str.length());
1744         if (len > 0) {
1745             int index = indexOf(str, 0);
1746             while (index >= 0) {
1747                 deleteImpl(index, index + len, len);
1748                 index = indexOf(str, index);
1749             }
1750         }
1751         return this;
1752     }
1753 
1754     /**
1755      * Deletes the string wherever it occurs in the builder.
1756      *
1757      * @param str  the string to delete, null causes no action
1758      * @return this, to enable chaining
1759      */
1760     public StrBuilder deleteFirst(final String str) {
1761         final int len = (str == null ? 0 : str.length());
1762         if (len > 0) {
1763             final int index = indexOf(str, 0);
1764             if (index >= 0) {
1765                 deleteImpl(index, index + len, len);
1766             }
1767         }
1768         return this;
1769     }
1770 
1771     //-----------------------------------------------------------------------
1772     /**
1773      * Deletes all parts of the builder that the matcher matches.
1774      * <p>
1775      * Matchers can be used to perform advanced deletion behaviour.
1776      * For example you could write a matcher to delete all occurrences
1777      * where the character 'a' is followed by a number.
1778      *
1779      * @param matcher  the matcher to use to find the deletion, null causes no action
1780      * @return this, to enable chaining
1781      */
1782     public StrBuilder deleteAll(final StrMatcher matcher) {
1783         return replace(matcher, null, 0, size, -1);
1784     }
1785 
1786     /**
1787      * Deletes the first match within the builder using the specified matcher.
1788      * <p>
1789      * Matchers can be used to perform advanced deletion behaviour.
1790      * For example you could write a matcher to delete
1791      * where the character 'a' is followed by a number.
1792      *
1793      * @param matcher  the matcher to use to find the deletion, null causes no action
1794      * @return this, to enable chaining
1795      */
1796     public StrBuilder deleteFirst(final StrMatcher matcher) {
1797         return replace(matcher, null, 0, size, 1);
1798     }
1799 
1800     //-----------------------------------------------------------------------
1801     /**
1802      * Internal method to delete a range without validation.
1803      *
1804      * @param startIndex  the start index, must be valid
1805      * @param endIndex  the end index (exclusive), must be valid
1806      * @param removeLen  the length to remove (endIndex - startIndex), must be valid
1807      * @param insertStr  the string to replace with, null means delete range
1808      * @param insertLen  the length of the insert string, must be valid
1809      * @throws IndexOutOfBoundsException if any index is invalid
1810      */
1811     private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, final int insertLen) {
1812         final int newSize = size - removeLen + insertLen;
1813         if (insertLen != removeLen) {
1814             ensureCapacity(newSize);
1815             System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex);
1816             size = newSize;
1817         }
1818         if (insertLen > 0) {
1819             insertStr.getChars(0, insertLen, buffer, startIndex);
1820         }
1821     }
1822 
1823     /**
1824      * Replaces a portion of the string builder with another string.
1825      * The length of the inserted string does not have to match the removed length.
1826      *
1827      * @param startIndex  the start index, inclusive, must be valid
1828      * @param endIndex  the end index, exclusive, must be valid except
1829      *  that if too large it is treated as end of string
1830      * @param replaceStr  the string to replace with, null means delete range
1831      * @return this, to enable chaining
1832      * @throws IndexOutOfBoundsException if the index is invalid
1833      */
1834     public StrBuilder replace(final int startIndex, int endIndex, final String replaceStr) {
1835         endIndex = validateRange(startIndex, endIndex);
1836         final int insertLen = (replaceStr == null ? 0 : replaceStr.length());
1837         replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen);
1838         return this;
1839     }
1840 
1841     //-----------------------------------------------------------------------
1842     /**
1843      * Replaces the search character with the replace character
1844      * throughout the builder.
1845      *
1846      * @param search  the search character
1847      * @param replace  the replace character
1848      * @return this, to enable chaining
1849      */
1850     public StrBuilder replaceAll(final char search, final char replace) {
1851         if (search != replace) {
1852             for (int i = 0; i < size; i++) {
1853                 if (buffer[i] == search) {
1854                     buffer[i] = replace;
1855                 }
1856             }
1857         }
1858         return this;
1859     }
1860 
1861     /**
1862      * Replaces the first instance of the search character with the
1863      * replace character in the builder.
1864      *
1865      * @param search  the search character
1866      * @param replace  the replace character
1867      * @return this, to enable chaining
1868      */
1869     public StrBuilder replaceFirst(final char search, final char replace) {
1870         if (search != replace) {
1871             for (int i = 0; i < size; i++) {
1872                 if (buffer[i] == search) {
1873                     buffer[i] = replace;
1874                     break;
1875                 }
1876             }
1877         }
1878         return this;
1879     }
1880 
1881     //-----------------------------------------------------------------------
1882     /**
1883      * Replaces the search string with the replace string throughout the builder.
1884      *
1885      * @param searchStr  the search string, null causes no action to occur
1886      * @param replaceStr  the replace string, null is equivalent to an empty string
1887      * @return this, to enable chaining
1888      */
1889     public StrBuilder replaceAll(final String searchStr, final String replaceStr) {
1890         final int searchLen = (searchStr == null ? 0 : searchStr.length());
1891         if (searchLen > 0) {
1892             final int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
1893             int index = indexOf(searchStr, 0);
1894             while (index >= 0) {
1895                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
1896                 index = indexOf(searchStr, index + replaceLen);
1897             }
1898         }
1899         return this;
1900     }
1901 
1902     /**
1903      * Replaces the first instance of the search string with the replace string.
1904      *
1905      * @param searchStr  the search string, null causes no action to occur
1906      * @param replaceStr  the replace string, null is equivalent to an empty string
1907      * @return this, to enable chaining
1908      */
1909     public StrBuilder replaceFirst(final String searchStr, final String replaceStr) {
1910         final int searchLen = (searchStr == null ? 0 : searchStr.length());
1911         if (searchLen > 0) {
1912             final int index = indexOf(searchStr, 0);
1913             if (index >= 0) {
1914                 final int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
1915                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
1916             }
1917         }
1918         return this;
1919     }
1920 
1921     //-----------------------------------------------------------------------
1922     /**
1923      * Replaces all matches within the builder with the replace string.
1924      * <p>
1925      * Matchers can be used to perform advanced replace behaviour.
1926      * For example you could write a matcher to replace all occurrences
1927      * where the character 'a' is followed by a number.
1928      *
1929      * @param matcher  the matcher to use to find the deletion, null causes no action
1930      * @param replaceStr  the replace string, null is equivalent to an empty string
1931      * @return this, to enable chaining
1932      */
1933     public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) {
1934         return replace(matcher, replaceStr, 0, size, -1);
1935     }
1936 
1937     /**
1938      * Replaces the first match within the builder with the replace string.
1939      * <p>
1940      * Matchers can be used to perform advanced replace behaviour.
1941      * For example you could write a matcher to replace
1942      * where the character 'a' is followed by a number.
1943      *
1944      * @param matcher  the matcher to use to find the deletion, null causes no action
1945      * @param replaceStr  the replace string, null is equivalent to an empty string
1946      * @return this, to enable chaining
1947      */
1948     public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr) {
1949         return replace(matcher, replaceStr, 0, size, 1);
1950     }
1951 
1952     // -----------------------------------------------------------------------
1953     /**
1954      * Advanced search and replaces within the builder using a matcher.
1955      * <p>
1956      * Matchers can be used to perform advanced behaviour.
1957      * For example you could write a matcher to delete all occurrences
1958      * where the character 'a' is followed by a number.
1959      *
1960      * @param matcher  the matcher to use to find the deletion, null causes no action
1961      * @param replaceStr  the string to replace the match with, null is a delete
1962      * @param startIndex  the start index, inclusive, must be valid
1963      * @param endIndex  the end index, exclusive, must be valid except
1964      *  that if too large it is treated as end of string
1965      * @param replaceCount  the number of times to replace, -1 for replace all
1966      * @return this, to enable chaining
1967      * @throws IndexOutOfBoundsException if start index is invalid
1968      */
1969     public StrBuilder replace(
1970             final StrMatcher matcher, final String replaceStr,
1971             final int startIndex, int endIndex, final int replaceCount) {
1972         endIndex = validateRange(startIndex, endIndex);
1973         return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount);
1974     }
1975 
1976     /**
1977      * Replaces within the builder using a matcher.
1978      * <p>
1979      * Matchers can be used to perform advanced behaviour.
1980      * For example you could write a matcher to delete all occurrences
1981      * where the character 'a' is followed by a number.
1982      *
1983      * @param matcher  the matcher to use to find the deletion, null causes no action
1984      * @param replaceStr  the string to replace the match with, null is a delete
1985      * @param from  the start index, must be valid
1986      * @param to  the end index (exclusive), must be valid
1987      * @param replaceCount  the number of times to replace, -1 for replace all
1988      * @return this, to enable chaining
1989      * @throws IndexOutOfBoundsException if any index is invalid
1990      */
1991     private StrBuilder replaceImpl(
1992             final StrMatcher matcher, final String replaceStr,
1993             final int from, int to, int replaceCount) {
1994         if (matcher == null || size == 0) {
1995             return this;
1996         }
1997         final int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
1998         final char[] buf = buffer;
1999         for (int i = from; i < to && replaceCount != 0; i++) {
2000             final int removeLen = matcher.isMatch(buf, i, from, to);
2001             if (removeLen > 0) {
2002                 replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen);
2003                 to = to - removeLen + replaceLen;
2004                 i = i + replaceLen - 1;
2005                 if (replaceCount > 0) {
2006                     replaceCount--;
2007                 }
2008             }
2009         }
2010         return this;
2011     }
2012 
2013     //-----------------------------------------------------------------------
2014     /**
2015      * Reverses the string builder placing each character in the opposite index.
2016      * 
2017      * @return this, to enable chaining
2018      */
2019     public StrBuilder reverse() {
2020         if (size == 0) {
2021             return this;
2022         }
2023         
2024         final int half = size / 2;
2025         final char[] buf = buffer;
2026         for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++,rightIdx--) {
2027             final char swap = buf[leftIdx];
2028             buf[leftIdx] = buf[rightIdx];
2029             buf[rightIdx] = swap;
2030         }
2031         return this;
2032     }
2033 
2034     //-----------------------------------------------------------------------
2035     /**
2036      * Trims the builder by removing characters less than or equal to a space
2037      * from the beginning and end.
2038      *
2039      * @return this, to enable chaining
2040      */
2041     public StrBuilder trim() {
2042         if (size == 0) {
2043             return this;
2044         }
2045         int len = size;
2046         final char[] buf = buffer;
2047         int pos = 0;
2048         while (pos < len && buf[pos] <= ' ') {
2049             pos++;
2050         }
2051         while (pos < len && buf[len - 1] <= ' ') {
2052             len--;
2053         }
2054         if (len < size) {
2055             delete(len, size);
2056         }
2057         if (pos > 0) {
2058             delete(0, pos);
2059         }
2060         return this;
2061     }
2062 
2063     //-----------------------------------------------------------------------
2064     /**
2065      * Checks whether this builder starts with the specified string.
2066      * <p>
2067      * Note that this method handles null input quietly, unlike String.
2068      * 
2069      * @param str  the string to search for, null returns false
2070      * @return true if the builder starts with the string
2071      */
2072     public boolean startsWith(final String str) {
2073         if (str == null) {
2074             return false;
2075         }
2076         final int len = str.length();
2077         if (len == 0) {
2078             return true;
2079         }
2080         if (len > size) {
2081             return false;
2082         }
2083         for (int i = 0; i < len; i++) {
2084             if (buffer[i] != str.charAt(i)) {
2085                 return false;
2086             }
2087         }
2088         return true;
2089     }
2090 
2091     /**
2092      * Checks whether this builder ends with the specified string.
2093      * <p>
2094      * Note that this method handles null input quietly, unlike String.
2095      * 
2096      * @param str  the string to search for, null returns false
2097      * @return true if the builder ends with the string
2098      */
2099     public boolean endsWith(final String str) {
2100         if (str == null) {
2101             return false;
2102         }
2103         final int len = str.length();
2104         if (len == 0) {
2105             return true;
2106         }
2107         if (len > size) {
2108             return false;
2109         }
2110         int pos = size - len;
2111         for (int i = 0; i < len; i++,pos++) {
2112             if (buffer[pos] != str.charAt(i)) {
2113                 return false;
2114             }
2115         }
2116         return true;
2117     }
2118 
2119     //-----------------------------------------------------------------------
2120     /**
2121      * {@inheritDoc}
2122      * @since 3.0
2123      */
2124     @Override
2125     public CharSequence subSequence(final int startIndex, final int endIndex) {
2126       if (startIndex < 0) {
2127           throw new StringIndexOutOfBoundsException(startIndex);
2128       }
2129       if (endIndex > size) {
2130           throw new StringIndexOutOfBoundsException(endIndex);
2131       }
2132       if (startIndex > endIndex) {
2133           throw new StringIndexOutOfBoundsException(endIndex - startIndex);
2134       }
2135       return substring(startIndex, endIndex);
2136     }
2137 
2138     /**
2139      * Extracts a portion of this string builder as a string.
2140      * 
2141      * @param start  the start index, inclusive, must be valid
2142      * @return the new string
2143      * @throws IndexOutOfBoundsException if the index is invalid
2144      */
2145     public String substring(final int start) {
2146         return substring(start, size);
2147     }
2148 
2149     /**
2150      * Extracts a portion of this string builder as a string.
2151      * <p>
2152      * Note: This method treats an endIndex greater than the length of the
2153      * builder as equal to the length of the builder, and continues
2154      * without error, unlike StringBuffer or String.
2155      * 
2156      * @param startIndex  the start index, inclusive, must be valid
2157      * @param endIndex  the end index, exclusive, must be valid except
2158      *  that if too large it is treated as end of string
2159      * @return the new string
2160      * @throws IndexOutOfBoundsException if the index is invalid
2161      */
2162     public String substring(final int startIndex, int endIndex) {
2163         endIndex = validateRange(startIndex, endIndex);
2164         return new String(buffer, startIndex, endIndex - startIndex);
2165     }
2166 
2167     /**
2168      * Extracts the leftmost characters from the string builder without
2169      * throwing an exception.
2170      * <p>
2171      * This method extracts the left <code>length</code> characters from
2172      * the builder. If this many characters are not available, the whole
2173      * builder is returned. Thus the returned string may be shorter than the
2174      * length requested.
2175      * 
2176      * @param length  the number of characters to extract, negative returns empty string
2177      * @return the new string
2178      */
2179     public String leftString(final int length) {
2180         if (length <= 0) {
2181             return "";
2182         } else if (length >= size) {
2183             return new String(buffer, 0, size);
2184         } else {
2185             return new String(buffer, 0, length);
2186         }
2187     }
2188 
2189     /**
2190      * Extracts the rightmost characters from the string builder without
2191      * throwing an exception.
2192      * <p>
2193      * This method extracts the right <code>length</code> characters from
2194      * the builder. If this many characters are not available, the whole
2195      * builder is returned. Thus the returned string may be shorter than the
2196      * length requested.
2197      * 
2198      * @param length  the number of characters to extract, negative returns empty string
2199      * @return the new string
2200      */
2201     public String rightString(final int length) {
2202         if (length <= 0) {
2203             return "";
2204         } else if (length >= size) {
2205             return new String(buffer, 0, size);
2206         } else {
2207             return new String(buffer, size - length, length);
2208         }
2209     }
2210 
2211     /**
2212      * Extracts some characters from the middle of the string builder without
2213      * throwing an exception.
2214      * <p>
2215      * This method extracts <code>length</code> characters from the builder
2216      * at the specified index.
2217      * If the index is negative it is treated as zero.
2218      * If the index is greater than the builder size, it is treated as the builder size.
2219      * If the length is negative, the empty string is returned.
2220      * If insufficient characters are available in the builder, as much as possible is returned.
2221      * Thus the returned string may be shorter than the length requested.
2222      * 
2223      * @param index  the index to start at, negative means zero
2224      * @param length  the number of characters to extract, negative returns empty string
2225      * @return the new string
2226      */
2227     public String midString(int index, final int length) {
2228         if (index < 0) {
2229             index = 0;
2230         }
2231         if (length <= 0 || index >= size) {
2232             return "";
2233         }
2234         if (size <= index + length) {
2235             return new String(buffer, index, size - index);
2236         }
2237         return new String(buffer, index, length);
2238     }
2239 
2240     //-----------------------------------------------------------------------
2241     /**
2242      * Checks if the string builder contains the specified char.
2243      *
2244      * @param ch  the character to find
2245      * @return true if the builder contains the character
2246      */
2247     public boolean contains(final char ch) {
2248         final char[] thisBuf = buffer;
2249         for (int i = 0; i < this.size; i++) {
2250             if (thisBuf[i] == ch) {
2251                 return true;
2252             }
2253         }
2254         return false;
2255     }
2256 
2257     /**
2258      * Checks if the string builder contains the specified string.
2259      *
2260      * @param str  the string to find
2261      * @return true if the builder contains the string
2262      */
2263     public boolean contains(final String str) {
2264         return indexOf(str, 0) >= 0;
2265     }
2266 
2267     /**
2268      * Checks if the string builder contains a string matched using the
2269      * specified matcher.
2270      * <p>
2271      * Matchers can be used to perform advanced searching behaviour.
2272      * For example you could write a matcher to search for the character
2273      * 'a' followed by a number.
2274      *
2275      * @param matcher  the matcher to use, null returns -1
2276      * @return true if the matcher finds a match in the builder
2277      */
2278     public boolean contains(final StrMatcher matcher) {
2279         return indexOf(matcher, 0) >= 0;
2280     }
2281 
2282     //-----------------------------------------------------------------------
2283     /**
2284      * Searches the string builder to find the first reference to the specified char.
2285      * 
2286      * @param ch  the character to find
2287      * @return the first index of the character, or -1 if not found
2288      */
2289     public int indexOf(final char ch) {
2290         return indexOf(ch, 0);
2291     }
2292 
2293     /**
2294      * Searches the string builder to find the first reference to the specified char.
2295      * 
2296      * @param ch  the character to find
2297      * @param startIndex  the index to start at, invalid index rounded to edge
2298      * @return the first index of the character, or -1 if not found
2299      */
2300     public int indexOf(final char ch, int startIndex) {
2301         startIndex = (startIndex < 0 ? 0 : startIndex);
2302         if (startIndex >= size) {
2303             return -1;
2304         }
2305         final char[] thisBuf = buffer;
2306         for (int i = startIndex; i < size; i++) {
2307             if (thisBuf[i] == ch) {
2308                 return i;
2309             }
2310         }
2311         return -1;
2312     }
2313 
2314     /**
2315      * Searches the string builder to find the first reference to the specified string.
2316      * <p>
2317      * Note that a null input string will return -1, whereas the JDK throws an exception.
2318      * 
2319      * @param str  the string to find, null returns -1
2320      * @return the first index of the string, or -1 if not found
2321      */
2322     public int indexOf(final String str) {
2323         return indexOf(str, 0);
2324     }
2325 
2326     /**
2327      * Searches the string builder to find the first reference to the specified
2328      * string starting searching from the given index.
2329      * <p>
2330      * Note that a null input string will return -1, whereas the JDK throws an exception.
2331      * 
2332      * @param str  the string to find, null returns -1
2333      * @param startIndex  the index to start at, invalid index rounded to edge
2334      * @return the first index of the string, or -1 if not found
2335      */
2336     public int indexOf(final String str, int startIndex) {
2337         startIndex = (startIndex < 0 ? 0 : startIndex);
2338         if (str == null || startIndex >= size) {
2339             return -1;
2340         }
2341         final int strLen = str.length();
2342         if (strLen == 1) {
2343             return indexOf(str.charAt(0), startIndex);
2344         }
2345         if (strLen == 0) {
2346             return startIndex;
2347         }
2348         if (strLen > size) {
2349             return -1;
2350         }
2351         final char[] thisBuf = buffer;
2352         final int len = size - strLen + 1;
2353         outer:
2354         for (int i = startIndex; i < len; i++) {
2355             for (int j = 0; j < strLen; j++) {
2356                 if (str.charAt(j) != thisBuf[i + j]) {
2357                     continue outer;
2358                 }
2359             }
2360             return i;
2361         }
2362         return -1;
2363     }
2364 
2365     /**
2366      * Searches the string builder using the matcher to find the first match.
2367      * <p>
2368      * Matchers can be used to perform advanced searching behaviour.
2369      * For example you could write a matcher to find the character 'a'
2370      * followed by a number.
2371      *
2372      * @param matcher  the matcher to use, null returns -1
2373      * @return the first index matched, or -1 if not found
2374      */
2375     public int indexOf(final StrMatcher matcher) {
2376         return indexOf(matcher, 0);
2377     }
2378 
2379     /**
2380      * Searches the string builder using the matcher to find the first
2381      * match searching from the given index.
2382      * <p>
2383      * Matchers can be used to perform advanced searching behaviour.
2384      * For example you could write a matcher to find the character 'a'
2385      * followed by a number.
2386      *
2387      * @param matcher  the matcher to use, null returns -1
2388      * @param startIndex  the index to start at, invalid index rounded to edge
2389      * @return the first index matched, or -1 if not found
2390      */
2391     public int indexOf(final StrMatcher matcher, int startIndex) {
2392         startIndex = (startIndex < 0 ? 0 : startIndex);
2393         if (matcher == null || startIndex >= size) {
2394             return -1;
2395         }
2396         final int len = size;
2397         final char[] buf = buffer;
2398         for (int i = startIndex; i < len; i++) {
2399             if (matcher.isMatch(buf, i, startIndex, len) > 0) {
2400                 return i;
2401             }
2402         }
2403         return -1;
2404     }
2405 
2406     //-----------------------------------------------------------------------
2407     /**
2408      * Searches the string builder to find the last reference to the specified char.
2409      * 
2410      * @param ch  the character to find
2411      * @return the last index of the character, or -1 if not found
2412      */
2413     public int lastIndexOf(final char ch) {
2414         return lastIndexOf(ch, size - 1);
2415     }
2416 
2417     /**
2418      * Searches the string builder to find the last reference to the specified char.
2419      * 
2420      * @param ch  the character to find
2421      * @param startIndex  the index to start at, invalid index rounded to edge
2422      * @return the last index of the character, or -1 if not found
2423      */
2424     public int lastIndexOf(final char ch, int startIndex) {
2425         startIndex = (startIndex >= size ? size - 1 : startIndex);
2426         if (startIndex < 0) {
2427             return -1;
2428         }
2429         for (int i = startIndex; i >= 0; i--) {
2430             if (buffer[i] == ch) {
2431                 return i;
2432             }
2433         }
2434         return -1;
2435     }
2436 
2437     /**
2438      * Searches the string builder to find the last reference to the specified string.
2439      * <p>
2440      * Note that a null input string will return -1, whereas the JDK throws an exception.
2441      * 
2442      * @param str  the string to find, null returns -1
2443      * @return the last index of the string, or -1 if not found
2444      */
2445     public int lastIndexOf(final String str) {
2446         return lastIndexOf(str, size - 1);
2447     }
2448 
2449     /**
2450      * Searches the string builder to find the last reference to the specified
2451      * string starting searching from the given index.
2452      * <p>
2453      * Note that a null input string will return -1, whereas the JDK throws an exception.
2454      * 
2455      * @param str  the string to find, null returns -1
2456      * @param startIndex  the index to start at, invalid index rounded to edge
2457      * @return the last index of the string, or -1 if not found
2458      */
2459     public int lastIndexOf(final String str, int startIndex) {
2460         startIndex = (startIndex >= size ? size - 1 : startIndex);
2461         if (str == null || startIndex < 0) {
2462             return -1;
2463         }
2464         final int strLen = str.length();
2465         if (strLen > 0 && strLen <= size) {
2466             if (strLen == 1) {
2467                 return lastIndexOf(str.charAt(0), startIndex);
2468             }
2469 
2470             outer:
2471             for (int i = startIndex - strLen + 1; i >= 0; i--) {
2472                 for (int j = 0; j < strLen; j++) {
2473                     if (str.charAt(j) != buffer[i + j]) {
2474                         continue outer;
2475                     }
2476                 }
2477                 return i;
2478             }
2479             
2480         } else if (strLen == 0) {
2481             return startIndex;
2482         }
2483         return -1;
2484     }
2485 
2486     /**
2487      * Searches the string builder using the matcher to find the last match.
2488      * <p>
2489      * Matchers can be used to perform advanced searching behaviour.
2490      * For example you could write a matcher to find the character 'a'
2491      * followed by a number.
2492      *
2493      * @param matcher  the matcher to use, null returns -1
2494      * @return the last index matched, or -1 if not found
2495      */
2496     public int lastIndexOf(final StrMatcher matcher) {
2497         return lastIndexOf(matcher, size);
2498     }
2499 
2500     /**
2501      * Searches the string builder using the matcher to find the last
2502      * match searching from the given index.
2503      * <p>
2504      * Matchers can be used to perform advanced searching behaviour.
2505      * For example you could write a matcher to find the character 'a'
2506      * followed by a number.
2507      *
2508      * @param matcher  the matcher to use, null returns -1
2509      * @param startIndex  the index to start at, invalid index rounded to edge
2510      * @return the last index matched, or -1 if not found
2511      */
2512     public int lastIndexOf(final StrMatcher matcher, int startIndex) {
2513         startIndex = (startIndex >= size ? size - 1 : startIndex);
2514         if (matcher == null || startIndex < 0) {
2515             return -1;
2516         }
2517         final char[] buf = buffer;
2518         final int endIndex = startIndex + 1;
2519         for (int i = startIndex; i >= 0; i--) {
2520             if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
2521                 return i;
2522             }
2523         }
2524         return -1;
2525     }
2526 
2527     //-----------------------------------------------------------------------
2528     /**
2529      * Creates a tokenizer that can tokenize the contents of this builder.
2530      * <p>
2531      * This method allows the contents of this builder to be tokenized.
2532      * The tokenizer will be setup by default to tokenize on space, tab,
2533      * newline and formfeed (as per StringTokenizer). These values can be
2534      * changed on the tokenizer class, before retrieving the tokens.
2535      * <p>
2536      * The returned tokenizer is linked to this builder. You may intermix
2537      * calls to the buider and tokenizer within certain limits, however
2538      * there is no synchronization. Once the tokenizer has been used once,
2539      * it must be {@link StrTokenizer#reset() reset} to pickup the latest
2540      * changes in the builder. For example:
2541      * <pre>
2542      * StrBuilder b = new StrBuilder();
2543      * b.append("a b ");
2544      * StrTokenizer t = b.asTokenizer();
2545      * String[] tokens1 = t.getTokenArray();  // returns a,b
2546      * b.append("c d ");
2547      * String[] tokens2 = t.getTokenArray();  // returns a,b (c and d ignored)
2548      * t.reset();              // reset causes builder changes to be picked up
2549      * String[] tokens3 = t.getTokenArray();  // returns a,b,c,d
2550      * </pre>
2551      * In addition to simply intermixing appends and tokenization, you can also
2552      * call the set methods on the tokenizer to alter how it tokenizes. Just
2553      * remember to call reset when you want to pickup builder changes.
2554      * <p>
2555      * Calling {@link StrTokenizer#reset(String)} or {@link StrTokenizer#reset(char[])}
2556      * with a non-null value will break the link with the builder.
2557      *
2558      * @return a tokenizer that is linked to this builder
2559      */
2560     public StrTokenizer asTokenizer() {
2561         return new StrBuilderTokenizer();
2562     }
2563 
2564     //-----------------------------------------------------------------------
2565     /**
2566      * Gets the contents of this builder as a Reader.
2567      * <p>
2568      * This method allows the contents of the builder to be read
2569      * using any standard method that expects a Reader.
2570      * <p>
2571      * To use, simply create a <code>StrBuilder</code>, populate it with
2572      * data, call <code>asReader</code>, and then read away.
2573      * <p>
2574      * The internal character array is shared between the builder and the reader.
2575      * This allows you to append to the builder after creating the reader,
2576      * and the changes will be picked up.
2577      * Note however, that no synchronization occurs, so you must perform
2578      * all operations with the builder and the reader in one thread.
2579      * <p>
2580      * The returned reader supports marking, and ignores the flush method.
2581      *
2582      * @return a reader that reads from this builder
2583      */
2584     public Reader asReader() {
2585         return new StrBuilderReader();
2586     }
2587 
2588     //-----------------------------------------------------------------------
2589     /**
2590      * Gets this builder as a Writer that can be written to.
2591      * <p>
2592      * This method allows you to populate the contents of the builder
2593      * using any standard method that takes a Writer.
2594      * <p>
2595      * To use, simply create a <code>StrBuilder</code>,
2596      * call <code>asWriter</code>, and populate away. The data is available
2597      * at any time using the methods of the <code>StrBuilder</code>.
2598      * <p>
2599      * The internal character array is shared between the builder and the writer.
2600      * This allows you to intermix calls that append to the builder and
2601      * write using the writer and the changes will be occur correctly.
2602      * Note however, that no synchronization occurs, so you must perform
2603      * all operations with the builder and the writer in one thread.
2604      * <p>
2605      * The returned writer ignores the close and flush methods.
2606      *
2607      * @return a writer that populates this builder
2608      */
2609     public Writer asWriter() {
2610         return new StrBuilderWriter();
2611     }
2612 
2613     //-----------------------------------------------------------------------
2614 //    /**
2615 //     * Gets a String version of the string builder by calling the internal
2616 //     * constructor of String by reflection.
2617 //     * <p>
2618 //     * WARNING: You must not use the StrBuilder after calling this method
2619 //     * as the buffer is now shared with the String object. To ensure this,
2620 //     * the internal character array is set to null, so you will get
2621 //     * NullPointerExceptions on all method calls.
2622 //     *
2623 //     * @return the builder as a String
2624 //     */
2625 //    public String toSharedString() {
2626 //        try {
2627 //            Constructor con = String.class.getDeclaredConstructor(
2628 //                new Class[] {int.class, int.class, char[].class});
2629 //            con.setAccessible(true);
2630 //            char[] buffer = buf;
2631 //            buf = null;
2632 //            size = -1;
2633 //            nullText = null;
2634 //            return (String) con.newInstance(
2635 //                new Object[] {Integer.valueOf(0), Integer.valueOf(size), buffer});
2636 //            
2637 //        } catch (Exception ex) {
2638 //            ex.printStackTrace();
2639 //            throw new UnsupportedOperationException("StrBuilder.toSharedString is unsupported: " + ex.getMessage());
2640 //        }
2641 //    }
2642 
2643     //-----------------------------------------------------------------------
2644     /**
2645      * Checks the contents of this builder against another to see if they
2646      * contain the same character content ignoring case.
2647      *
2648      * @param other  the object to check, null returns false
2649      * @return true if the builders contain the same characters in the same order
2650      */
2651     public boolean equalsIgnoreCase(final StrBuilder other) {
2652         if (this == other) {
2653             return true;
2654         }
2655         if (this.size != other.size) {
2656             return false;
2657         }
2658         final char thisBuf[] = this.buffer;
2659         final char otherBuf[] = other.buffer;
2660         for (int i = size - 1; i >= 0; i--) {
2661             final char c1 = thisBuf[i];
2662             final char c2 = otherBuf[i];
2663             if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) {
2664                 return false;
2665             }
2666         }
2667         return true;
2668     }
2669 
2670     /**
2671      * Checks the contents of this builder against another to see if they
2672      * contain the same character content.
2673      *
2674      * @param other  the object to check, null returns false
2675      * @return true if the builders contain the same characters in the same order
2676      */
2677     public boolean equals(final StrBuilder other) {
2678         if (this == other) {
2679             return true;
2680         }
2681         if (this.size != other.size) {
2682             return false;
2683         }
2684         final char thisBuf[] = this.buffer;
2685         final char otherBuf[] = other.buffer;
2686         for (int i = size - 1; i >= 0; i--) {
2687             if (thisBuf[i] != otherBuf[i]) {
2688                 return false;
2689             }
2690         }
2691         return true;
2692     }
2693 
2694     /**
2695      * Checks the contents of this builder against another to see if they
2696      * contain the same character content.
2697      *
2698      * @param obj  the object to check, null returns false
2699      * @return true if the builders contain the same characters in the same order
2700      */
2701     @Override
2702     public boolean equals(final Object obj) {
2703         if (obj instanceof StrBuilder) {
2704             return equals((StrBuilder) obj);
2705         }
2706         return false;
2707     }
2708 
2709     /**
2710      * Gets a suitable hash code for this builder.
2711      *
2712      * @return a hash code
2713      */
2714     @Override
2715     public int hashCode() {
2716         final char buf[] = buffer;
2717         int hash = 0;
2718         for (int i = size - 1; i >= 0; i--) {
2719             hash = 31 * hash + buf[i];
2720         }
2721         return hash;
2722     }
2723 
2724     //-----------------------------------------------------------------------
2725     /**
2726      * Gets a String version of the string builder, creating a new instance
2727      * each time the method is called.
2728      * <p>
2729      * Note that unlike StringBuffer, the string version returned is
2730      * independent of the string builder.
2731      *
2732      * @return the builder as a String
2733      */
2734     @Override
2735     public String toString() {
2736         return new String(buffer, 0, size);
2737     }
2738 
2739     /**
2740      * Gets a StringBuffer version of the string builder, creating a
2741      * new instance each time the method is called.
2742      *
2743      * @return the builder as a StringBuffer
2744      */
2745     public StringBuffer toStringBuffer() {
2746         return new StringBuffer(size).append(buffer, 0, size);
2747     }
2748 
2749     /**
2750      * Gets a StringBuilder version of the string builder, creating a
2751      * new instance each time the method is called.
2752      *
2753      * @return the builder as a StringBuilder
2754      * @since 3.2
2755      */
2756     public StringBuilder toStringBuilder() {
2757         return new StringBuilder(size).append(buffer, 0, size);
2758     }
2759 
2760     /**
2761      * Implement the {@link Builder} interface.
2762      * @return the builder as a String
2763      * @since 3.2
2764      * @see #toString()
2765      */
2766     @Override
2767     public String build() {
2768         return toString();
2769     }
2770 
2771     //-----------------------------------------------------------------------
2772     /**
2773      * Validates parameters defining a range of the builder.
2774      * 
2775      * @param startIndex  the start index, inclusive, must be valid
2776      * @param endIndex  the end index, exclusive, must be valid except
2777      *  that if too large it is treated as end of string
2778      * @return the new string
2779      * @throws IndexOutOfBoundsException if the index is invalid
2780      */
2781     protected int validateRange(final int startIndex, int endIndex) {
2782         if (startIndex < 0) {
2783             throw new StringIndexOutOfBoundsException(startIndex);
2784         }
2785         if (endIndex > size) {
2786             endIndex = size;
2787         }
2788         if (startIndex > endIndex) {
2789             throw new StringIndexOutOfBoundsException("end < start");
2790         }
2791         return endIndex;
2792     }
2793 
2794     /**
2795      * Validates parameters defining a single index in the builder.
2796      * 
2797      * @param index  the index, must be valid
2798      * @throws IndexOutOfBoundsException if the index is invalid
2799      */
2800     protected void validateIndex(final int index) {
2801         if (index < 0 || index > size) {
2802             throw new StringIndexOutOfBoundsException(index);
2803         }
2804     }
2805 
2806     //-----------------------------------------------------------------------
2807     /**
2808      * Inner class to allow StrBuilder to operate as a tokenizer.
2809      */
2810     class StrBuilderTokenizer extends StrTokenizer {
2811 
2812         /**
2813          * Default constructor.
2814          */
2815         StrBuilderTokenizer() {
2816             super();
2817         }
2818 
2819         /** {@inheritDoc} */
2820         @Override
2821         protected List<String> tokenize(final char[] chars, final int offset, final int count) {
2822             if (chars == null) {
2823                 return super.tokenize(StrBuilder.this.buffer, 0, StrBuilder.this.size());
2824             }
2825             return super.tokenize(chars, offset, count);
2826         }
2827 
2828         /** {@inheritDoc} */
2829         @Override
2830         public String getContent() {
2831             final String str = super.getContent();
2832             if (str == null) {
2833                 return StrBuilder.this.toString();
2834             }
2835             return str;
2836         }
2837     }
2838 
2839     //-----------------------------------------------------------------------
2840     /**
2841      * Inner class to allow StrBuilder to operate as a reader.
2842      */
2843     class StrBuilderReader extends Reader {
2844         /** The current stream position. */
2845         private int pos;
2846         /** The last mark position. */
2847         private int mark;
2848 
2849         /**
2850          * Default constructor.
2851          */
2852         StrBuilderReader() {
2853             super();
2854         }
2855 
2856         /** {@inheritDoc} */
2857         @Override
2858         public void close() {
2859             // do nothing
2860         }
2861 
2862         /** {@inheritDoc} */
2863         @Override
2864         public int read() {
2865             if (ready() == false) {
2866                 return -1;
2867             }
2868             return StrBuilder.this.charAt(pos++);
2869         }
2870 
2871         /** {@inheritDoc} */
2872         @Override
2873         public int read(final char b[], final int off, int len) {
2874             if (off < 0 || len < 0 || off > b.length ||
2875                     (off + len) > b.length || (off + len) < 0) {
2876                 throw new IndexOutOfBoundsException();
2877             }
2878             if (len == 0) {
2879                 return 0;
2880             }
2881             if (pos >= StrBuilder.this.size()) {
2882                 return -1;
2883             }
2884             if (pos + len > size()) {
2885                 len = StrBuilder.this.size() - pos;
2886             }
2887             StrBuilder.this.getChars(pos, pos + len, b, off);
2888             pos += len;
2889             return len;
2890         }
2891 
2892         /** {@inheritDoc} */
2893         @Override
2894         public long skip(long n) {
2895             if (pos + n > StrBuilder.this.size()) {
2896                 n = StrBuilder.this.size() - pos;
2897             }
2898             if (n < 0) {
2899                 return 0;
2900             }
2901             pos += n;
2902             return n;
2903         }
2904 
2905         /** {@inheritDoc} */
2906         @Override
2907         public boolean ready() {
2908             return pos < StrBuilder.this.size();
2909         }
2910 
2911         /** {@inheritDoc} */
2912         @Override
2913         public boolean markSupported() {
2914             return true;
2915         }
2916 
2917         /** {@inheritDoc} */
2918         @Override
2919         public void mark(final int readAheadLimit) {
2920             mark = pos;
2921         }
2922 
2923         /** {@inheritDoc} */
2924         @Override
2925         public void reset() {
2926             pos = mark;
2927         }
2928     }
2929 
2930     //-----------------------------------------------------------------------
2931     /**
2932      * Inner class to allow StrBuilder to operate as a writer.
2933      */
2934     class StrBuilderWriter extends Writer {
2935 
2936         /**
2937          * Default constructor.
2938          */
2939         StrBuilderWriter() {
2940             super();
2941         }
2942 
2943         /** {@inheritDoc} */
2944         @Override
2945         public void close() {
2946             // do nothing
2947         }
2948 
2949         /** {@inheritDoc} */
2950         @Override
2951         public void flush() {
2952             // do nothing
2953         }
2954 
2955         /** {@inheritDoc} */
2956         @Override
2957         public void write(final int c) {
2958             StrBuilder.this.append((char) c);
2959         }
2960 
2961         /** {@inheritDoc} */
2962         @Override
2963         public void write(final char[] cbuf) {
2964             StrBuilder.this.append(cbuf);
2965         }
2966 
2967         /** {@inheritDoc} */
2968         @Override
2969         public void write(final char[] cbuf, final int off, final int len) {
2970             StrBuilder.this.append(cbuf, off, len);
2971         }
2972 
2973         /** {@inheritDoc} */
2974         @Override
2975         public void write(final String str) {
2976             StrBuilder.this.append(str);
2977         }
2978 
2979         /** {@inheritDoc} */
2980         @Override
2981         public void write(final String str, final int off, final int len) {
2982             StrBuilder.this.append(str, off, len);
2983         }
2984     }
2985 
2986 }