001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.text;
018
019import java.io.IOException;
020import java.io.Reader;
021import java.io.Serializable;
022import java.io.Writer;
023import java.nio.CharBuffer;
024import java.util.Arrays;
025import java.util.Iterator;
026import java.util.List;
027import java.util.Objects;
028
029import org.apache.commons.lang3.ArrayUtils;
030import org.apache.commons.lang3.CharUtils;
031import org.apache.commons.lang3.StringUtils;
032
033/**
034 * Builds a string from constituent parts providing a more flexible and powerful API than {@link StringBuffer} and {@link StringBuilder}.
035 * <p>
036 * The main differences from {@link StrBuilder} and {@link StringBuilder} are:
037 * </p>
038 * <ul>
039 * <li>Not synchronized</li>
040 * <li>Not final</li>
041 * <li>Subclasses have direct access to character array</li>
042 * <li>Additional methods
043 * <ul>
044 * <li>appendWithSeparators - adds an array of values, with a separator</li>
045 * <li>appendPadding - adds a length padding characters</li>
046 * <li>appendFixedLength - adds a fixed width field to the builder</li>
047 * <li>toCharArray/getChars - simpler ways to get a range of the character array</li>
048 * <li>delete - delete char or string</li>
049 * <li>replace - search and replace for a char or string</li>
050 * <li>leftString/rightString/midString - substring without exceptions</li>
051 * <li>contains - whether the builder contains a char or string</li>
052 * <li>size/clear/isEmpty - collections style API methods</li>
053 * </ul>
054 * </li>
055 * <li>Views
056 * <ul>
057 * <li>asTokenizer - uses the internal buffer as the source of a StrTokenizer</li>
058 * <li>asReader - uses the internal buffer as the source of a Reader</li>
059 * <li>asWriter - allows a Writer to write directly to the internal buffer</li>
060 * </ul>
061 * </li>
062 * </ul>
063 * <p>
064 * 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,
065 * 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
066 * text 'null'. This can be controlled by a property, {@link #setNullText(String)}.
067 * </p>
068 *
069 * @since 1.0
070 * @deprecated Deprecated as of 1.3, use {@link TextStringBuilder} instead. This class will be removed in 2.0.
071 */
072@Deprecated
073public class StrBuilder implements CharSequence, Appendable, Serializable, Builder<String> {
074
075    /**
076     * Inner class to allow StrBuilder to operate as a reader.
077     */
078    final class StrBuilderReader extends Reader {
079
080        /** The current stream position. */
081        private int pos;
082
083        /** The last mark position. */
084        private int mark;
085
086        /**
087         * Default constructor.
088         */
089        StrBuilderReader() {
090        }
091
092        /** {@inheritDoc} */
093        @Override
094        public void close() {
095            // do nothing
096        }
097
098        /** {@inheritDoc} */
099        @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}