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