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