Source code
Description: source: package: org.apache.commons.text, class: StrBuilder

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