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