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