TextStringBuilder.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.text;

  18. import java.io.IOException;
  19. import java.io.Reader;
  20. import java.io.Serializable;
  21. import java.io.Writer;
  22. import java.nio.CharBuffer;
  23. import java.util.Arrays;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Objects;

  27. import org.apache.commons.lang3.ArrayUtils;
  28. import org.apache.commons.lang3.StringUtils;
  29. import org.apache.commons.text.matcher.StringMatcher;

  30. /**
  31.  * Builds a string from constituent parts providing a more flexible and powerful API than {@link StringBuffer} and
  32.  * {@link StringBuilder}.
  33.  * <p>
  34.  * The main differences from StringBuffer/StringBuilder are:
  35.  * </p>
  36.  * <ul>
  37.  * <li>Not synchronized</li>
  38.  * <li>Not final</li>
  39.  * <li>Subclasses have direct access to character array</li>
  40.  * <li>Additional methods
  41.  * <ul>
  42.  * <li>appendWithSeparators - adds an array of values, with a separator</li>
  43.  * <li>appendPadding - adds a length padding characters</li>
  44.  * <li>appendFixedLength - adds a fixed width field to the builder</li>
  45.  * <li>toCharArray/getChars - simpler ways to get a range of the character array</li>
  46.  * <li>delete - delete char or string</li>
  47.  * <li>replace - search and replace for a char or string</li>
  48.  * <li>leftString/rightString/midString - substring without exceptions</li>
  49.  * <li>contains - whether the builder contains a char or string</li>
  50.  * <li>size/clear/isEmpty - collections style API methods</li>
  51.  * </ul>
  52.  * </li>
  53.  * <li>Views
  54.  * <ul>
  55.  * <li>asTokenizer - uses the internal buffer as the source of a StrTokenizer</li>
  56.  * <li>asReader - uses the internal buffer as the source of a Reader</li>
  57.  * <li>asWriter - allows a Writer to write directly to the internal buffer</li>
  58.  * </ul>
  59.  * </li>
  60.  * </ul>
  61.  * <p>
  62.  * The aim has been to provide an API that mimics very closely what StringBuffer provides, but with additional methods.
  63.  * It should be noted that some edge cases, with invalid indices or null input, have been altered - see individual
  64.  * methods. The biggest of these changes is that by default, null will not output the text 'null'. This can be
  65.  * controlled by a property, {@link #setNullText(String)}.
  66.  * </p>
  67.  * <p>
  68.  * This class is called {@code TextStringBuilder} instead of {@code StringBuilder} to avoid clashing with
  69.  * {@link StringBuilder}.
  70.  * </p>
  71.  *
  72.  * @since 1.3
  73.  */
  74. public class TextStringBuilder implements CharSequence, Appendable, Serializable, Builder<String> {

  75.     /**
  76.      * Inner class to allow StrBuilder to operate as a reader.
  77.      */
  78.     final class TextStringBuilderReader extends Reader {

  79.         /** The last mark position. */
  80.         private int mark;

  81.         /** The current stream position. */
  82.         private int pos;

  83.         /**
  84.          * Default constructor.
  85.          */
  86.         TextStringBuilderReader() {
  87.         }

  88.         /** {@inheritDoc} */
  89.         @Override
  90.         public void close() {
  91.             // do nothing
  92.         }

  93.         /** {@inheritDoc} */
  94.         @Override
  95.         public void mark(final int readAheadLimit) {
  96.             mark = pos;
  97.         }

  98.         /** {@inheritDoc} */
  99.         @Override
  100.         public boolean markSupported() {
  101.             return true;
  102.         }

  103.         /** {@inheritDoc} */
  104.         @Override
  105.         public int read() {
  106.             if (!ready()) {
  107.                 return -1;
  108.             }
  109.             return charAt(pos++);
  110.         }

  111.         /** {@inheritDoc} */
  112.         @Override
  113.         public int read(final char[] b, final int off, int len) {
  114.             if (off < 0 || len < 0 || off > b.length || off + len > b.length || off + len < 0) {
  115.                 throw new IndexOutOfBoundsException();
  116.             }
  117.             if (len == 0) {
  118.                 return 0;
  119.             }
  120.             if (pos >= size()) {
  121.                 return -1;
  122.             }
  123.             if (pos + len > size()) {
  124.                 len = size() - pos;
  125.             }
  126.             TextStringBuilder.this.getChars(pos, pos + len, b, off);
  127.             pos += len;
  128.             return len;
  129.         }

  130.         /** {@inheritDoc} */
  131.         @Override
  132.         public boolean ready() {
  133.             return pos < size();
  134.         }

  135.         /** {@inheritDoc} */
  136.         @Override
  137.         public void reset() {
  138.             pos = mark;
  139.         }

  140.         /** {@inheritDoc} */
  141.         @Override
  142.         public long skip(long n) {
  143.             if (pos + n > size()) {
  144.                 n = size() - pos;
  145.             }
  146.             if (n < 0) {
  147.                 return 0;
  148.             }
  149.             pos = Math.addExact(pos, Math.toIntExact(n));
  150.             return n;
  151.         }
  152.     }

  153.     /**
  154.      * Inner class to allow StrBuilder to operate as a tokenizer.
  155.      */
  156.     final class TextStringBuilderTokenizer extends StringTokenizer {

  157.         /**
  158.          * Default constructor.
  159.          */
  160.         TextStringBuilderTokenizer() {
  161.         }

  162.         /** {@inheritDoc} */
  163.         @Override
  164.         public String getContent() {
  165.             final String str = super.getContent();
  166.             if (str == null) {
  167.                 return TextStringBuilder.this.toString();
  168.             }
  169.             return str;
  170.         }

  171.         /** {@inheritDoc} */
  172.         @Override
  173.         protected List<String> tokenize(final char[] chars, final int offset, final int count) {
  174.             if (chars == null) {
  175.                 return super.tokenize(getBuffer(), 0, TextStringBuilder.this.size());
  176.             }
  177.             return super.tokenize(chars, offset, count);
  178.         }
  179.     }

  180.     /**
  181.      * Inner class to allow StrBuilder to operate as a writer.
  182.      */
  183.     final class TextStringBuilderWriter extends Writer {

  184.         /**
  185.          * Default constructor.
  186.          */
  187.         TextStringBuilderWriter() {
  188.         }

  189.         /** {@inheritDoc} */
  190.         @Override
  191.         public void close() {
  192.             // do nothing
  193.         }

  194.         /** {@inheritDoc} */
  195.         @Override
  196.         public void flush() {
  197.             // do nothing
  198.         }

  199.         /** {@inheritDoc} */
  200.         @Override
  201.         public void write(final char[] cbuf) {
  202.             TextStringBuilder.this.append(cbuf);
  203.         }

  204.         /** {@inheritDoc} */
  205.         @Override
  206.         public void write(final char[] cbuf, final int off, final int len) {
  207.             TextStringBuilder.this.append(cbuf, off, len);
  208.         }

  209.         /** {@inheritDoc} */
  210.         @Override
  211.         public void write(final int c) {
  212.             TextStringBuilder.this.append((char) c);
  213.         }

  214.         /** {@inheritDoc} */
  215.         @Override
  216.         public void write(final String str) {
  217.             TextStringBuilder.this.append(str);
  218.         }

  219.         /** {@inheritDoc} */
  220.         @Override
  221.         public void write(final String str, final int off, final int len) {
  222.             TextStringBuilder.this.append(str, off, len);
  223.         }
  224.     }

  225.     /** The space character. */
  226.     private static final char SPACE = ' ';

  227.     /**
  228.      * The extra capacity for new builders.
  229.      */
  230.     static final int CAPACITY = 32;

  231.     /**
  232.      * End-Of-Stream.
  233.      */
  234.     private static final int EOS = -1;

  235.     /**
  236.      * The size of the string {@code "false"}.
  237.      */
  238.     private static final int FALSE_STRING_SIZE = Boolean.FALSE.toString().length();

  239.     /**
  240.      * Required for serialization support.
  241.      *
  242.      * @see java.io.Serializable
  243.      */
  244.     private static final long serialVersionUID = 1L;

  245.     /**
  246.      * The size of the string {@code "true"}.
  247.      */
  248.     private static final int TRUE_STRING_SIZE = Boolean.TRUE.toString().length();

  249.     /**
  250.      * The maximum size buffer to allocate.
  251.      *
  252.      * <p>This is set to the same size used in the JDK {@link java.util.ArrayList}:</p>
  253.      * <blockquote>
  254.      * Some VMs reserve some header words in an array.
  255.      * Attempts to allocate larger arrays may result in
  256.      * OutOfMemoryError: Requested array size exceeds VM limit.
  257.      * </blockquote>
  258.      */
  259.     private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;

  260.     /**
  261.      * Creates a positive capacity at least as large the minimum required capacity.
  262.      * If the minimum capacity is negative then this throws an OutOfMemoryError as no array
  263.      * can be allocated.
  264.      *
  265.      * @param minCapacity the minimum capacity
  266.      * @return the capacity
  267.      * @throws OutOfMemoryError if the {@code minCapacity} is negative
  268.      */
  269.     private static int createPositiveCapacity(final int minCapacity) {
  270.         if (minCapacity < 0) {
  271.             // overflow
  272.             throw new OutOfMemoryError("Unable to allocate array size: " + Integer.toUnsignedString(minCapacity));
  273.         }
  274.         // This is called when we require buffer expansion to a very big array.
  275.         // Use the conservative maximum buffer size if possible, otherwise the biggest required.
  276.         //
  277.         // Note: In this situation JDK 1.8 java.util.ArrayList returns Integer.MAX_VALUE.
  278.         // This excludes some VMs that can exceed MAX_BUFFER_SIZE but not allocate a full
  279.         // Integer.MAX_VALUE length array.
  280.         // The result is that we may have to allocate an array of this size more than once if
  281.         // the capacity must be expanded again.
  282.         return Math.max(minCapacity, MAX_BUFFER_SIZE);
  283.     }

  284.     /**
  285.      * Constructs an instance from a reference to a character array. Changes to the input chars are reflected in this
  286.      * instance until the internal buffer needs to be reallocated. Using a reference to an array allows the instance to
  287.      * be initialized without copying the input array.
  288.      *
  289.      * @param initialBuffer The initial array that will back the new builder.
  290.      * @return A new instance.
  291.      * @since 1.9
  292.      */
  293.     public static TextStringBuilder wrap(final char[] initialBuffer) {
  294.         Objects.requireNonNull(initialBuffer, "initialBuffer");
  295.         return new TextStringBuilder(initialBuffer, initialBuffer.length);
  296.     }

  297.     /**
  298.      * Constructs an instance from a reference to a character array. Changes to the input chars are reflected in this
  299.      * instance until the internal buffer needs to be reallocated. Using a reference to an array allows the instance to
  300.      * be initialized without copying the input array.
  301.      *
  302.      * @param initialBuffer The initial array that will back the new builder.
  303.      * @param length The length of the subarray to be used; must be non-negative and no larger than
  304.      *        {@code initialBuffer.length}. The new builder's size will be set to {@code length}.
  305.      * @return A new instance.
  306.      * @since 1.9
  307.      */
  308.     public static TextStringBuilder wrap(final char[] initialBuffer, final int length) {
  309.         return new TextStringBuilder(initialBuffer, length);
  310.     }

  311.     /** Internal data storage. */
  312.     private char[] buffer;

  313.     /**
  314.      * The new line, {@code null} means use the system default from {@link System#lineSeparator()}.
  315.      */
  316.     private String newLine;

  317.     /** The null text. */
  318.     private String nullText;

  319.     /** Incremented when the buffer is reallocated. */
  320.     private int reallocations;

  321.     /** Current size of the buffer. */
  322.     private int size;

  323.     /**
  324.      * Constructs an empty builder with an initial capacity of 32 characters.
  325.      */
  326.     public TextStringBuilder() {
  327.         this(CAPACITY);
  328.     }

  329.     /**
  330.      * Constructs an instance from a reference to a character array.
  331.      *
  332.      * @param initialBuffer a reference to a character array, must not be null.
  333.      * @param length The length of the subarray to be used; must be non-negative and no larger than
  334.      *        {@code initialBuffer.length}. The new builder's size will be set to {@code length}.
  335.      * @throws NullPointerException If {@code initialBuffer} is null.
  336.      * @throws IllegalArgumentException if {@code length} is bad.
  337.      */
  338.     private TextStringBuilder(final char[] initialBuffer, final int length) {
  339.         this.buffer = Objects.requireNonNull(initialBuffer, "initialBuffer");
  340.         if (length < 0 || length > initialBuffer.length) {
  341.             throw new IllegalArgumentException("initialBuffer.length=" + initialBuffer.length + ", length=" + length);
  342.         }
  343.         this.size = length;
  344.     }

  345.     /**
  346.      * Constructs an instance from a character sequence, allocating 32 extra characters for growth.
  347.      *
  348.      * @param seq the string to copy, null treated as blank string
  349.      * @since 1.9
  350.      */
  351.     public TextStringBuilder(final CharSequence seq) {
  352.         this(StringUtils.length(seq) + CAPACITY);
  353.         if (seq != null) {
  354.             append(seq);
  355.         }
  356.     }

  357.     /**
  358.      * Constructs an instance with the specified initial capacity.
  359.      *
  360.      * @param initialCapacity the initial capacity, zero or less will be converted to 32
  361.      */
  362.     public TextStringBuilder(final int initialCapacity) {
  363.         buffer = new char[initialCapacity <= 0 ? CAPACITY : initialCapacity];
  364.     }

  365.     /**
  366.      * Constructs an instance from a string, allocating 32 extra characters for growth.
  367.      *
  368.      * @param str the string to copy, null treated as blank string
  369.      */
  370.     public TextStringBuilder(final String str) {
  371.         this(StringUtils.length(str) + CAPACITY);
  372.         if (str != null) {
  373.             append(str);
  374.         }
  375.     }

  376.     /**
  377.      * Appends a boolean value to the string builder.
  378.      *
  379.      * @param value the value to append
  380.      * @return this, to enable chaining
  381.      */
  382.     public TextStringBuilder append(final boolean value) {
  383.         if (value) {
  384.             ensureCapacityInternal(size + TRUE_STRING_SIZE);
  385.             appendTrue(size);
  386.         } else {
  387.             ensureCapacityInternal(size + FALSE_STRING_SIZE);
  388.             appendFalse(size);
  389.         }
  390.         return this;
  391.     }

  392.     /**
  393.      * Appends a char value to the string builder.
  394.      *
  395.      * @param ch the value to append
  396.      * @return this, to enable chaining
  397.      */
  398.     @Override
  399.     public TextStringBuilder append(final char ch) {
  400.         final int len = length();
  401.         ensureCapacityInternal(len + 1);
  402.         buffer[size++] = ch;
  403.         return this;
  404.     }

  405.     /**
  406.      * Appends a char array to the string builder. Appending null will call {@link #appendNull()}.
  407.      *
  408.      * @param chars the char array to append
  409.      * @return this, to enable chaining
  410.      */
  411.     public TextStringBuilder append(final char[] chars) {
  412.         if (chars == null) {
  413.             return appendNull();
  414.         }
  415.         final int strLen = chars.length;
  416.         if (strLen > 0) {
  417.             final int len = length();
  418.             ensureCapacityInternal(len + strLen);
  419.             System.arraycopy(chars, 0, buffer, len, strLen);
  420.             size += strLen;
  421.         }
  422.         return this;
  423.     }

  424.     /**
  425.      * Appends a char array to the string builder. Appending null will call {@link #appendNull()}.
  426.      *
  427.      * @param chars the char array to append
  428.      * @param startIndex the start index, inclusive, must be valid
  429.      * @param length the length to append, must be valid
  430.      * @return this, to enable chaining
  431.      * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the
  432.      *  range {@code 0 <= startIndex <= chars.length}
  433.      * @throws StringIndexOutOfBoundsException if {@code length < 0}
  434.      * @throws StringIndexOutOfBoundsException if {@code startIndex + length > chars.length}
  435.      */
  436.     public TextStringBuilder append(final char[] chars, final int startIndex, final int length) {
  437.         if (chars == null) {
  438.             return appendNull();
  439.         }
  440.         if (startIndex < 0 || startIndex > chars.length) {
  441.             throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length);
  442.         }
  443.         if (length < 0 || startIndex + length > chars.length) {
  444.             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
  445.         }
  446.         if (length > 0) {
  447.             final int len = length();
  448.             ensureCapacityInternal(len + length);
  449.             System.arraycopy(chars, startIndex, buffer, len, length);
  450.             size += length;
  451.         }
  452.         return this;
  453.     }

  454.     /**
  455.      * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}.
  456.      *
  457.      * @param str the char buffer to append
  458.      * @return this, to enable chaining
  459.      */
  460.     public TextStringBuilder append(final CharBuffer str) {
  461.         return append(str, 0, StringUtils.length(str));
  462.     }

  463.     /**
  464.      * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}.
  465.      *
  466.      * @param buf the char buffer to append
  467.      * @param startIndex the start index, inclusive, must be valid
  468.      * @param length the length to append, must be valid
  469.      * @return this, to enable chaining
  470.      */
  471.     public TextStringBuilder append(final CharBuffer buf, final int startIndex, final int length) {
  472.         if (buf == null) {
  473.             return appendNull();
  474.         }
  475.         if (buf.hasArray()) {
  476.             final int totalLength = buf.remaining();
  477.             if (startIndex < 0 || startIndex > totalLength) {
  478.                 throw new StringIndexOutOfBoundsException("startIndex must be valid");
  479.             }
  480.             if (length < 0 || startIndex + length > totalLength) {
  481.                 throw new StringIndexOutOfBoundsException("length must be valid");
  482.             }
  483.             final int len = length();
  484.             ensureCapacityInternal(len + length);
  485.             System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length);
  486.             size += length;
  487.         } else {
  488.             append(buf.toString(), startIndex, length);
  489.         }
  490.         return this;
  491.     }

  492.     /**
  493.      * Appends a CharSequence to this string builder. Appending null will call {@link #appendNull()}.
  494.      *
  495.      * @param seq the CharSequence to append
  496.      * @return this, to enable chaining
  497.      */
  498.     @Override
  499.     public TextStringBuilder append(final CharSequence seq) {
  500.         if (seq == null) {
  501.             return appendNull();
  502.         }
  503.         if (seq instanceof TextStringBuilder) {
  504.             return append((TextStringBuilder) seq);
  505.         }
  506.         if (seq instanceof StringBuilder) {
  507.             return append((StringBuilder) seq);
  508.         }
  509.         if (seq instanceof StringBuffer) {
  510.             return append((StringBuffer) seq);
  511.         }
  512.         if (seq instanceof CharBuffer) {
  513.             return append((CharBuffer) seq);
  514.         }
  515.         return append(seq.toString());
  516.     }

  517.     /**
  518.      * Appends part of a CharSequence to this string builder. Appending null will call {@link #appendNull()}.
  519.      *
  520.      * @param seq the CharSequence to append
  521.      * @param startIndex the start index, inclusive, must be valid
  522.      * @param endIndex the end index, exclusive, must be valid
  523.      * @return this, to enable chaining
  524.      */
  525.     @Override
  526.     public TextStringBuilder append(final CharSequence seq, final int startIndex, final int endIndex) {
  527.         if (seq == null) {
  528.             return appendNull();
  529.         }
  530.         if (endIndex <= 0) {
  531.             throw new StringIndexOutOfBoundsException("endIndex must be valid");
  532.         }
  533.         if (startIndex >= endIndex) {
  534.             throw new StringIndexOutOfBoundsException("endIndex must be greater than startIndex");
  535.         }
  536.         return append(seq.toString(), startIndex, endIndex - startIndex);
  537.     }

  538.     /**
  539.      * Appends a double value to the string builder using {@code String.valueOf}.
  540.      *
  541.      * @param value the value to append
  542.      * @return this, to enable chaining
  543.      */
  544.     public TextStringBuilder append(final double value) {
  545.         return append(String.valueOf(value));
  546.     }

  547.     /**
  548.      * Appends a float value to the string builder using {@code String.valueOf}.
  549.      *
  550.      * @param value the value to append
  551.      * @return this, to enable chaining
  552.      */
  553.     public TextStringBuilder append(final float value) {
  554.         return append(String.valueOf(value));
  555.     }

  556.     /**
  557.      * Appends an int value to the string builder using {@code String.valueOf}.
  558.      *
  559.      * @param value the value to append
  560.      * @return this, to enable chaining
  561.      */
  562.     public TextStringBuilder append(final int value) {
  563.         return append(String.valueOf(value));
  564.     }

  565.     /**
  566.      * Appends a long value to the string builder using {@code String.valueOf}.
  567.      *
  568.      * @param value the value to append
  569.      * @return this, to enable chaining
  570.      */
  571.     public TextStringBuilder append(final long value) {
  572.         return append(String.valueOf(value));
  573.     }

  574.     /**
  575.      * Appends an object to this string builder. Appending null will call {@link #appendNull()}.
  576.      *
  577.      * @param obj the object to append
  578.      * @return this, to enable chaining
  579.      */
  580.     public TextStringBuilder append(final Object obj) {
  581.         if (obj == null) {
  582.             return appendNull();
  583.         }
  584.         if (obj instanceof CharSequence) {
  585.             return append((CharSequence) obj);
  586.         }
  587.         return append(obj.toString());
  588.     }

  589.     /**
  590.      * Appends a string to this string builder. Appending null will call {@link #appendNull()}.
  591.      *
  592.      * @param str the string to append
  593.      * @return this, to enable chaining
  594.      */
  595.     public TextStringBuilder append(final String str) {
  596.         return append(str, 0, StringUtils.length(str));
  597.     }

  598.     /**
  599.      * Appends part of a string to this string builder. Appending null will call {@link #appendNull()}.
  600.      *
  601.      * @param str the string to append
  602.      * @param startIndex the start index, inclusive, must be valid
  603.      * @param length the length to append, must be valid
  604.      * @return this, to enable chaining
  605.      * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the
  606.      *  range {@code 0 <= startIndex <= str.length()}
  607.      * @throws StringIndexOutOfBoundsException if {@code length < 0}
  608.      * @throws StringIndexOutOfBoundsException if {@code startIndex + length > str.length()}
  609.      */
  610.     public TextStringBuilder append(final String str, final int startIndex, final int length) {
  611.         if (str == null) {
  612.             return appendNull();
  613.         }
  614.         if (startIndex < 0 || startIndex > str.length()) {
  615.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  616.         }
  617.         if (length < 0 || startIndex + length > str.length()) {
  618.             throw new StringIndexOutOfBoundsException("length must be valid");
  619.         }
  620.         if (length > 0) {
  621.             final int len = length();
  622.             ensureCapacityInternal(len + length);
  623.             str.getChars(startIndex, startIndex + length, buffer, len);
  624.             size += length;
  625.         }
  626.         return this;
  627.     }

  628.     /**
  629.      * Calls {@link String#format(String, Object...)} and appends the result.
  630.      *
  631.      * @param format the format string
  632.      * @param objs the objects to use in the format string
  633.      * @return {@code this} to enable chaining
  634.      * @see String#format(String, Object...)
  635.      */
  636.     public TextStringBuilder append(final String format, final Object... objs) {
  637.         return append(String.format(format, objs));
  638.     }

  639.     /**
  640.      * Appends a string buffer to this string builder. Appending null will call {@link #appendNull()}.
  641.      *
  642.      * @param str the string buffer to append
  643.      * @return this, to enable chaining
  644.      */
  645.     public TextStringBuilder append(final StringBuffer str) {
  646.         return append(str, 0, StringUtils.length(str));
  647.     }

  648.     /**
  649.      * Appends part of a string buffer to this string builder. Appending null will call {@link #appendNull()}.
  650.      *
  651.      * @param str the string to append
  652.      * @param startIndex the start index, inclusive, must be valid
  653.      * @param length the length to append, must be valid
  654.      * @return this, to enable chaining
  655.      */
  656.     public TextStringBuilder append(final StringBuffer str, final int startIndex, final int length) {
  657.         if (str == null) {
  658.             return appendNull();
  659.         }
  660.         if (startIndex < 0 || startIndex > str.length()) {
  661.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  662.         }
  663.         if (length < 0 || startIndex + length > str.length()) {
  664.             throw new StringIndexOutOfBoundsException("length must be valid");
  665.         }
  666.         if (length > 0) {
  667.             final int len = length();
  668.             ensureCapacityInternal(len + length);
  669.             str.getChars(startIndex, startIndex + length, buffer, len);
  670.             size += length;
  671.         }
  672.         return this;
  673.     }

  674.     /**
  675.      * Appends a StringBuilder to this string builder. Appending null will call {@link #appendNull()}.
  676.      *
  677.      * @param str the StringBuilder to append
  678.      * @return this, to enable chaining
  679.      */
  680.     public TextStringBuilder append(final StringBuilder str) {
  681.         return append(str, 0, StringUtils.length(str));
  682.     }

  683.     /**
  684.      * Appends part of a StringBuilder to this string builder. Appending null will call {@link #appendNull()}.
  685.      *
  686.      * @param str the StringBuilder to append
  687.      * @param startIndex the start index, inclusive, must be valid
  688.      * @param length the length to append, must be valid
  689.      * @return this, to enable chaining
  690.      */
  691.     public TextStringBuilder append(final StringBuilder str, final int startIndex, final int length) {
  692.         if (str == null) {
  693.             return appendNull();
  694.         }
  695.         if (startIndex < 0 || startIndex > str.length()) {
  696.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  697.         }
  698.         if (length < 0 || startIndex + length > str.length()) {
  699.             throw new StringIndexOutOfBoundsException("length must be valid");
  700.         }
  701.         if (length > 0) {
  702.             final int len = length();
  703.             ensureCapacityInternal(len + length);
  704.             str.getChars(startIndex, startIndex + length, buffer, len);
  705.             size += length;
  706.         }
  707.         return this;
  708.     }

  709.     /**
  710.      * Appends another string builder to this string builder. Appending null will call {@link #appendNull()}.
  711.      *
  712.      * @param str the string builder to append
  713.      * @return this, to enable chaining
  714.      */
  715.     public TextStringBuilder append(final TextStringBuilder str) {
  716.         return append(str, 0, StringUtils.length(str));
  717.     }

  718.     /**
  719.      * Appends part of a string builder to this string builder. Appending null will call {@link #appendNull()}.
  720.      *
  721.      * @param str the string to append
  722.      * @param startIndex the start index, inclusive, must be valid
  723.      * @param length the length to append, must be valid
  724.      * @return this, to enable chaining
  725.      */
  726.     public TextStringBuilder append(final TextStringBuilder str, final int startIndex, final int length) {
  727.         if (str == null) {
  728.             return appendNull();
  729.         }
  730.         if (startIndex < 0 || startIndex > str.length()) {
  731.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  732.         }
  733.         if (length < 0 || startIndex + length > str.length()) {
  734.             throw new StringIndexOutOfBoundsException("length must be valid");
  735.         }
  736.         if (length > 0) {
  737.             final int len = length();
  738.             ensureCapacityInternal(len + length);
  739.             str.getChars(startIndex, startIndex + length, buffer, len);
  740.             size += length;
  741.         }
  742.         return this;
  743.     }

  744.     /**
  745.      * Appends each item in an iterable to the builder without any separators. Appending a null iterable will have no
  746.      * effect. Each object is appended using {@link #append(Object)}.
  747.      *
  748.      * @param iterable the iterable to append
  749.      * @return this, to enable chaining
  750.      */
  751.     public TextStringBuilder appendAll(final Iterable<?> iterable) {
  752.         if (iterable != null) {
  753.             iterable.forEach(this::append);
  754.         }
  755.         return this;
  756.     }

  757.     /**
  758.      * Appends each item in an iterator to the builder without any separators. Appending a null iterator will have no
  759.      * effect. Each object is appended using {@link #append(Object)}.
  760.      *
  761.      * @param it the iterator to append
  762.      * @return this, to enable chaining
  763.      */
  764.     public TextStringBuilder appendAll(final Iterator<?> it) {
  765.         if (it != null) {
  766.             it.forEachRemaining(this::append);
  767.         }
  768.         return this;
  769.     }

  770.     /**
  771.      * Appends each item in an array to the builder without any separators. Appending a null array will have no effect.
  772.      * Each object is appended using {@link #append(Object)}.
  773.      *
  774.      * @param <T> the element type
  775.      * @param array the array to append
  776.      * @return this, to enable chaining
  777.      */
  778.     public <T> TextStringBuilder appendAll(@SuppressWarnings("unchecked") final T... array) {
  779.         /*
  780.          * @SuppressWarnings used to hide warning about vararg usage. We cannot use @SafeVarargs, since this method is
  781.          * not final. Using @SuppressWarnings is fine, because it isn't inherited by subclasses, so each subclass must
  782.          * vouch for itself whether its use of 'array' is safe.
  783.          */
  784.         if (array != null && array.length > 0) {
  785.             for (final Object element : array) {
  786.                 append(element);
  787.             }
  788.         }
  789.         return this;
  790.     }

  791.     /** Appends {@code "false"}. */
  792.     private void appendFalse(int index) {
  793.         buffer[index++] = 'f';
  794.         buffer[index++] = 'a';
  795.         buffer[index++] = 'l';
  796.         buffer[index++] = 's';
  797.         buffer[index] = 'e';
  798.         size += FALSE_STRING_SIZE;
  799.     }

  800.     /**
  801.      * Appends an object to the builder padding on the left to a fixed width. The {@code String.valueOf} of the
  802.      * {@code int} value is used. If the formatted value is larger than the length, the left hand side is lost.
  803.      *
  804.      * @param value the value to append
  805.      * @param width the fixed field width, zero or negative has no effect
  806.      * @param padChar the pad character to use
  807.      * @return this, to enable chaining
  808.      */
  809.     public TextStringBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) {
  810.         return appendFixedWidthPadLeft(String.valueOf(value), width, padChar);
  811.     }

  812.     /**
  813.      * Appends an object to the builder padding on the left to a fixed width. The {@code toString} of the object is
  814.      * used. If the object is larger than the length, the left hand side is lost. If the object is null, the null text
  815.      * value is used.
  816.      *
  817.      * @param obj the object to append, null uses null text
  818.      * @param width the fixed field width, zero or negative has no effect
  819.      * @param padChar the pad character to use
  820.      * @return this, to enable chaining
  821.      */
  822.     public TextStringBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) {
  823.         if (width > 0) {
  824.             ensureCapacityInternal(size + width);
  825.             String str = Objects.toString(obj, getNullText());
  826.             if (str == null) {
  827.                 str = StringUtils.EMPTY;
  828.             }
  829.             final int strLen = str.length();
  830.             if (strLen >= width) {
  831.                 str.getChars(strLen - width, strLen, buffer, size);
  832.             } else {
  833.                 final int padLen = width - strLen;
  834.                 final int toIndex = size + padLen;
  835.                 Arrays.fill(buffer, size, toIndex, padChar);
  836.                 str.getChars(0, strLen, buffer, toIndex);
  837.             }
  838.             size += width;
  839.         }
  840.         return this;
  841.     }

  842.     /**
  843.      * Appends an object to the builder padding on the right to a fixed length. The {@code String.valueOf} of the
  844.      * {@code int} value is used. If the object is larger than the length, the right hand side is lost.
  845.      *
  846.      * @param value the value to append
  847.      * @param width the fixed field width, zero or negative has no effect
  848.      * @param padChar the pad character to use
  849.      * @return this, to enable chaining
  850.      */
  851.     public TextStringBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) {
  852.         return appendFixedWidthPadRight(String.valueOf(value), width, padChar);
  853.     }

  854.     /**
  855.      * Appends an object to the builder padding on the right to a fixed length. The {@code toString} of the object is
  856.      * used. If the object is larger than the length, the right hand side is lost. If the object is null, null text
  857.      * value is used.
  858.      *
  859.      * @param obj the object to append, null uses null text
  860.      * @param width the fixed field width, zero or negative has no effect
  861.      * @param padChar the pad character to use
  862.      * @return this, to enable chaining
  863.      */
  864.     public TextStringBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) {
  865.         if (width > 0) {
  866.             ensureCapacityInternal(size + width);
  867.             String str = Objects.toString(obj, getNullText());
  868.             if (str == null) {
  869.                 str = StringUtils.EMPTY;
  870.             }
  871.             final int strLen = str.length();
  872.             if (strLen >= width) {
  873.                 str.getChars(0, width, buffer, size);
  874.             } else {
  875.                 str.getChars(0, strLen, buffer, size);
  876.                 final int fromIndex = size + strLen;
  877.                 Arrays.fill(buffer, fromIndex, fromIndex + width - strLen, padChar);
  878.             }
  879.             size += width;
  880.         }
  881.         return this;
  882.     }

  883.     /**
  884.      * Appends a boolean value followed by a new line to the string builder.
  885.      *
  886.      * @param value the value to append
  887.      * @return this, to enable chaining
  888.      */
  889.     public TextStringBuilder appendln(final boolean value) {
  890.         return append(value).appendNewLine();
  891.     }

  892.     /**
  893.      * Appends a char value followed by a new line to the string builder.
  894.      *
  895.      * @param ch the value to append
  896.      * @return this, to enable chaining
  897.      */
  898.     public TextStringBuilder appendln(final char ch) {
  899.         return append(ch).appendNewLine();
  900.     }

  901.     /**
  902.      * Appends a char array followed by a new line to the string builder. Appending null will call
  903.      * {@link #appendNull()}.
  904.      *
  905.      * @param chars the char array to append
  906.      * @return this, to enable chaining
  907.      */
  908.     public TextStringBuilder appendln(final char[] chars) {
  909.         return append(chars).appendNewLine();
  910.     }

  911.     /**
  912.      * Appends a char array followed by a new line to the string builder. Appending null will call
  913.      * {@link #appendNull()}.
  914.      *
  915.      * @param chars the char array to append
  916.      * @param startIndex the start index, inclusive, must be valid
  917.      * @param length the length to append, must be valid
  918.      * @return this, to enable chaining
  919.      */
  920.     public TextStringBuilder appendln(final char[] chars, final int startIndex, final int length) {
  921.         return append(chars, startIndex, length).appendNewLine();
  922.     }

  923.     /**
  924.      * Appends a double value followed by a new line to the string builder using {@code String.valueOf}.
  925.      *
  926.      * @param value the value to append
  927.      * @return this, to enable chaining
  928.      */
  929.     public TextStringBuilder appendln(final double value) {
  930.         return append(value).appendNewLine();
  931.     }

  932.     /**
  933.      * Appends a float value followed by a new line 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 TextStringBuilder appendln(final float value) {
  939.         return append(value).appendNewLine();
  940.     }

  941.     /**
  942.      * Appends an int value followed by a new line to the string builder using {@code String.valueOf}.
  943.      *
  944.      * @param value the value to append
  945.      * @return this, to enable chaining
  946.      */
  947.     public TextStringBuilder appendln(final int value) {
  948.         return append(value).appendNewLine();
  949.     }

  950.     /**
  951.      * Appends a long value followed by a new line to the string builder using {@code String.valueOf}.
  952.      *
  953.      * @param value the value to append
  954.      * @return this, to enable chaining
  955.      */
  956.     public TextStringBuilder appendln(final long value) {
  957.         return append(value).appendNewLine();
  958.     }

  959.     /**
  960.      * Appends an object followed by a new line to this string builder. Appending null will call {@link #appendNull()}.
  961.      *
  962.      * @param obj the object to append
  963.      * @return this, to enable chaining
  964.      */
  965.     public TextStringBuilder appendln(final Object obj) {
  966.         return append(obj).appendNewLine();
  967.     }

  968.     /**
  969.      * Appends a string followed by a new line to this string builder. Appending null will call {@link #appendNull()}.
  970.      *
  971.      * @param str the string to append
  972.      * @return this, to enable chaining
  973.      */
  974.     public TextStringBuilder appendln(final String str) {
  975.         return append(str).appendNewLine();
  976.     }

  977.     /**
  978.      * Appends part of a string followed by a new line to this string builder. Appending null will call
  979.      * {@link #appendNull()}.
  980.      *
  981.      * @param str the string to append
  982.      * @param startIndex the start index, inclusive, must be valid
  983.      * @param length the length to append, must be valid
  984.      * @return this, to enable chaining
  985.      */
  986.     public TextStringBuilder appendln(final String str, final int startIndex, final int length) {
  987.         return append(str, startIndex, length).appendNewLine();
  988.     }

  989.     /**
  990.      * Calls {@link String#format(String, Object...)} and appends the result.
  991.      *
  992.      * @param format the format string
  993.      * @param objs the objects to use in the format string
  994.      * @return {@code this} to enable chaining
  995.      * @see String#format(String, Object...)
  996.      */
  997.     public TextStringBuilder appendln(final String format, final Object... objs) {
  998.         return append(format, objs).appendNewLine();
  999.     }

  1000.     /**
  1001.      * Appends a string buffer followed by a new line to this string builder. Appending null will call
  1002.      * {@link #appendNull()}.
  1003.      *
  1004.      * @param str the string buffer to append
  1005.      * @return this, to enable chaining
  1006.      */
  1007.     public TextStringBuilder appendln(final StringBuffer str) {
  1008.         return append(str).appendNewLine();
  1009.     }

  1010.     /**
  1011.      * Appends part of a string buffer followed by a new line to this string builder. Appending null will call
  1012.      * {@link #appendNull()}.
  1013.      *
  1014.      * @param str the string to append
  1015.      * @param startIndex the start index, inclusive, must be valid
  1016.      * @param length the length to append, must be valid
  1017.      * @return this, to enable chaining
  1018.      */
  1019.     public TextStringBuilder appendln(final StringBuffer str, final int startIndex, final int length) {
  1020.         return append(str, startIndex, length).appendNewLine();
  1021.     }

  1022.     /**
  1023.      * Appends a string builder followed by a new line to this string builder. Appending null will call
  1024.      * {@link #appendNull()}.
  1025.      *
  1026.      * @param str the string builder to append
  1027.      * @return this, to enable chaining
  1028.      */
  1029.     public TextStringBuilder appendln(final StringBuilder str) {
  1030.         return append(str).appendNewLine();
  1031.     }

  1032.     /**
  1033.      * Appends part of a string builder followed by a new line to this string builder. Appending null will call
  1034.      * {@link #appendNull()}.
  1035.      *
  1036.      * @param str the string builder to append
  1037.      * @param startIndex the start index, inclusive, must be valid
  1038.      * @param length the length to append, must be valid
  1039.      * @return this, to enable chaining
  1040.      */
  1041.     public TextStringBuilder appendln(final StringBuilder str, final int startIndex, final int length) {
  1042.         return append(str, startIndex, length).appendNewLine();
  1043.     }

  1044.     /**
  1045.      * Appends another string builder followed by a new line to this string builder. Appending null will call
  1046.      * {@link #appendNull()}.
  1047.      *
  1048.      * @param str the string builder to append
  1049.      * @return this, to enable chaining
  1050.      */
  1051.     public TextStringBuilder appendln(final TextStringBuilder str) {
  1052.         return append(str).appendNewLine();
  1053.     }

  1054.     /**
  1055.      * Appends part of a string builder followed by a new line to this string builder. Appending null will call
  1056.      * {@link #appendNull()}.
  1057.      *
  1058.      * @param str the string to append
  1059.      * @param startIndex the start index, inclusive, must be valid
  1060.      * @param length the length to append, must be valid
  1061.      * @return this, to enable chaining
  1062.      */
  1063.     public TextStringBuilder appendln(final TextStringBuilder str, final int startIndex, final int length) {
  1064.         return append(str, startIndex, length).appendNewLine();
  1065.     }

  1066.     /**
  1067.      * Appends this builder's new line string to this builder.
  1068.      * <p>
  1069.      * By default, the new line is the system default from {@link System#lineSeparator()}.
  1070.      * </p>
  1071.      * <p>
  1072.      * The new line string can be changed using {@link #setNewLineText(String)}. For example, you can use this to force the output to always use Unix line
  1073.      * endings even when on Windows.
  1074.      * </p>
  1075.      *
  1076.      * @return this
  1077.      * @see #getNewLineText()
  1078.      * @see #setNewLineText(String)
  1079.      */
  1080.     public TextStringBuilder appendNewLine() {
  1081.         if (newLine == null) {
  1082.             append(System.lineSeparator());
  1083.             return this;
  1084.         }
  1085.         return append(newLine);
  1086.     }

  1087.     /**
  1088.      * Appends the text representing {@code null} to this string builder.
  1089.      *
  1090.      * @return this, to enable chaining
  1091.      */
  1092.     public TextStringBuilder appendNull() {
  1093.         if (nullText == null) {
  1094.             return this;
  1095.         }
  1096.         return append(nullText);
  1097.     }

  1098.     /**
  1099.      * Appends the pad character to the builder the specified number of times.
  1100.      *
  1101.      * @param length the length to append, negative means no append
  1102.      * @param padChar the character to append
  1103.      * @return this, to enable chaining
  1104.      */
  1105.     public TextStringBuilder appendPadding(final int length, final char padChar) {
  1106.         if (length >= 0) {
  1107.             ensureCapacityInternal(size + length);
  1108.             for (int i = 0; i < length; i++) {
  1109.                 buffer[size++] = padChar;
  1110.             }
  1111.         }
  1112.         return this;
  1113.     }

  1114.     /**
  1115.      * Appends a separator if the builder is currently non-empty. The separator is appended using {@link #append(char)}.
  1116.      * <p>
  1117.      * This method is useful for adding a separator each time around the loop except the first.
  1118.      * </p>
  1119.      *
  1120.      * <pre>
  1121.      * for (Iterator it = list.iterator(); it.hasNext();) {
  1122.      *     appendSeparator(',');
  1123.      *     append(it.next());
  1124.      * }
  1125.      * </pre>
  1126.      *
  1127.      * <p>
  1128.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1129.      * </p>
  1130.      *
  1131.      * @param separator the separator to use
  1132.      * @return this, to enable chaining
  1133.      */
  1134.     public TextStringBuilder appendSeparator(final char separator) {
  1135.         if (isNotEmpty()) {
  1136.             append(separator);
  1137.         }
  1138.         return this;
  1139.     }

  1140.     /**
  1141.      * Appends one of both separators to the builder If the builder is currently empty it will append the
  1142.      * defaultIfEmpty-separator Otherwise it will append the standard-separator
  1143.      *
  1144.      * The separator is appended using {@link #append(char)}.
  1145.      *
  1146.      * @param standard the separator if builder is not empty
  1147.      * @param defaultIfEmpty the separator if builder is empty
  1148.      * @return this, to enable chaining
  1149.      */
  1150.     public TextStringBuilder appendSeparator(final char standard, final char defaultIfEmpty) {
  1151.         if (isEmpty()) {
  1152.             append(defaultIfEmpty);
  1153.         } else {
  1154.             append(standard);
  1155.         }
  1156.         return this;
  1157.     }

  1158.     /**
  1159.      * Appends a separator to the builder if the loop index is greater than zero. The separator is appended using
  1160.      * {@link #append(char)}.
  1161.      * <p>
  1162.      * This method is useful for adding a separator each time around the loop except the first.
  1163.      * </p>
  1164.      *
  1165.      * <pre>
  1166.      * for (int i = 0; i &lt; list.size(); i++) {
  1167.      *     appendSeparator(",", i);
  1168.      *     append(list.get(i));
  1169.      * }
  1170.      * </pre>
  1171.      *
  1172.      * <p>
  1173.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1174.      * </p>
  1175.      *
  1176.      * @param separator the separator to use
  1177.      * @param loopIndex the loop index
  1178.      * @return this, to enable chaining
  1179.      */
  1180.     public TextStringBuilder appendSeparator(final char separator, final int loopIndex) {
  1181.         if (loopIndex > 0) {
  1182.             append(separator);
  1183.         }
  1184.         return this;
  1185.     }

  1186.     /**
  1187.      * Appends a separator if the builder is currently non-empty. Appending a null separator will have no effect. The
  1188.      * separator is appended using {@link #append(String)}.
  1189.      * <p>
  1190.      * This method is useful for adding a separator each time around the loop except the first.
  1191.      * </p>
  1192.      *
  1193.      * <pre>
  1194.      * for (Iterator it = list.iterator(); it.hasNext();) {
  1195.      *     appendSeparator(",");
  1196.      *     append(it.next());
  1197.      * }
  1198.      * </pre>
  1199.      *
  1200.      * <p>
  1201.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1202.      * </p>
  1203.      *
  1204.      * @param separator the separator to use, null means no separator
  1205.      * @return this, to enable chaining
  1206.      */
  1207.     public TextStringBuilder appendSeparator(final String separator) {
  1208.         return appendSeparator(separator, null);
  1209.     }

  1210.     /**
  1211.      * Appends a separator to the builder if the loop index is greater than zero. Appending a null separator will have
  1212.      * no effect. The separator is appended using {@link #append(String)}.
  1213.      * <p>
  1214.      * This method is useful for adding a separator each time around the loop except the first.
  1215.      * </p>
  1216.      *
  1217.      * <pre>
  1218.      * for (int i = 0; i &lt; list.size(); i++) {
  1219.      *     appendSeparator(",", i);
  1220.      *     append(list.get(i));
  1221.      * }
  1222.      * </pre>
  1223.      *
  1224.      * <p>
  1225.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1226.      * </p>
  1227.      *
  1228.      * @param separator the separator to use, null means no separator
  1229.      * @param loopIndex the loop index
  1230.      * @return this, to enable chaining
  1231.      */
  1232.     public TextStringBuilder appendSeparator(final String separator, final int loopIndex) {
  1233.         if (separator != null && loopIndex > 0) {
  1234.             append(separator);
  1235.         }
  1236.         return this;
  1237.     }

  1238.     /**
  1239.      * Appends one of both separators to the StrBuilder. If the builder is currently empty, it will append the
  1240.      * defaultIfEmpty-separator, otherwise it will append the standard-separator.
  1241.      * <p>
  1242.      * Appending a null separator will have no effect. The separator is appended using {@link #append(String)}.
  1243.      * </p>
  1244.      * <p>
  1245.      * This method is for example useful for constructing queries
  1246.      * </p>
  1247.      *
  1248.      * <pre>
  1249.      * StrBuilder whereClause = new StrBuilder();
  1250.      * if (searchCommand.getPriority() != null) {
  1251.      *  whereClause.appendSeparator(" and", " where");
  1252.      *  whereClause.append(" priority = ?")
  1253.      * }
  1254.      * if (searchCommand.getComponent() != null) {
  1255.      *  whereClause.appendSeparator(" and", " where");
  1256.      *  whereClause.append(" component = ?")
  1257.      * }
  1258.      * selectClause.append(whereClause)
  1259.      * </pre>
  1260.      *
  1261.      * @param standard the separator if builder is not empty, null means no separator
  1262.      * @param defaultIfEmpty the separator if builder is empty, null means no separator
  1263.      * @return this, to enable chaining
  1264.      */
  1265.     public TextStringBuilder appendSeparator(final String standard, final String defaultIfEmpty) {
  1266.         final String str = isEmpty() ? defaultIfEmpty : standard;
  1267.         if (str != null) {
  1268.             append(str);
  1269.         }
  1270.         return this;
  1271.     }

  1272.     /**
  1273.      * Appends current contents of this {@code StrBuilder} to the provided {@link Appendable}.
  1274.      * <p>
  1275.      * This method tries to avoid doing any extra copies of contents.
  1276.      * </p>
  1277.      *
  1278.      * @param appendable the appendable to append data to
  1279.      * @throws IOException if an I/O error occurs.
  1280.      * @see #readFrom(Readable)
  1281.      */
  1282.     public void appendTo(final Appendable appendable) throws IOException {
  1283.         if (appendable instanceof Writer) {
  1284.             ((Writer) appendable).write(buffer, 0, size);
  1285.         } else if (appendable instanceof StringBuilder) {
  1286.             ((StringBuilder) appendable).append(buffer, 0, size);
  1287.         } else if (appendable instanceof StringBuffer) {
  1288.             ((StringBuffer) appendable).append(buffer, 0, size);
  1289.         } else if (appendable instanceof CharBuffer) {
  1290.             ((CharBuffer) appendable).put(buffer, 0, size);
  1291.         } else {
  1292.             appendable.append(this);
  1293.         }
  1294.     }

  1295.     /** Appends {@code "true"}. */
  1296.     private void appendTrue(int index) {
  1297.         buffer[index++] = 't';
  1298.         buffer[index++] = 'r';
  1299.         buffer[index++] = 'u';
  1300.         buffer[index] = 'e';
  1301.         size += TRUE_STRING_SIZE;
  1302.     }

  1303.     /**
  1304.      * Appends an iterable placing separators between each value, but not before the first or after the last. Appending
  1305.      * a null iterable will have no effect. Each object is appended using {@link #append(Object)}.
  1306.      *
  1307.      * @param iterable the iterable to append
  1308.      * @param separator the separator to use, null means no separator
  1309.      * @return this, to enable chaining
  1310.      */
  1311.     public TextStringBuilder appendWithSeparators(final Iterable<?> iterable, final String separator) {
  1312.         if (iterable != null) {
  1313.             appendWithSeparators(iterable.iterator(), separator);
  1314.         }
  1315.         return this;
  1316.     }

  1317.     /**
  1318.      * Appends an iterator placing separators between each value, but not before the first or after the last. Appending
  1319.      * a null iterator will have no effect. Each object is appended using {@link #append(Object)}.
  1320.      *
  1321.      * @param it the iterator to append
  1322.      * @param separator the separator to use, null means no separator
  1323.      * @return this, to enable chaining
  1324.      */
  1325.     public TextStringBuilder appendWithSeparators(final Iterator<?> it, final String separator) {
  1326.         if (it != null) {
  1327.             final String sep = Objects.toString(separator, StringUtils.EMPTY);
  1328.             while (it.hasNext()) {
  1329.                 append(it.next());
  1330.                 if (it.hasNext()) {
  1331.                     append(sep);
  1332.                 }
  1333.             }
  1334.         }
  1335.         return this;
  1336.     }

  1337.     /**
  1338.      * Appends an array placing separators between each value, but not before the first or after the last. Appending a
  1339.      * null array will have no effect. Each object is appended using {@link #append(Object)}.
  1340.      *
  1341.      * @param array the array to append
  1342.      * @param separator the separator to use, null means no separator
  1343.      * @return this, to enable chaining
  1344.      */
  1345.     public TextStringBuilder appendWithSeparators(final Object[] array, final String separator) {
  1346.         if (array != null && array.length > 0) {
  1347.             final String sep = Objects.toString(separator, StringUtils.EMPTY);
  1348.             append(array[0]);
  1349.             for (int i = 1; i < array.length; i++) {
  1350.                 append(sep);
  1351.                 append(array[i]);
  1352.             }
  1353.         }
  1354.         return this;
  1355.     }

  1356.     /**
  1357.      * Gets the contents of this builder as a Reader.
  1358.      * <p>
  1359.      * This method allows the contents of the builder to be read using any standard method that expects a Reader.
  1360.      * </p>
  1361.      * <p>
  1362.      * To use, simply create a {@code StrBuilder}, populate it with data, call {@code asReader}, and then read away.
  1363.      * </p>
  1364.      * <p>
  1365.      * The internal character array is shared between the builder and the reader. This allows you to append to the
  1366.      * builder after creating the reader, and the changes will be picked up. Note however, that no synchronization
  1367.      * occurs, so you must perform all operations with the builder and the reader in one thread.
  1368.      * </p>
  1369.      * <p>
  1370.      * The returned reader supports marking, and ignores the flush method.
  1371.      * </p>
  1372.      *
  1373.      * @return a reader that reads from this builder
  1374.      */
  1375.     public Reader asReader() {
  1376.         return new TextStringBuilderReader();
  1377.     }

  1378.     /**
  1379.      * Creates a tokenizer that can tokenize the contents of this builder.
  1380.      * <p>
  1381.      * This method allows the contents of this builder to be tokenized. The tokenizer will be setup by default to
  1382.      * tokenize on space, tab, newline and form feed (as per StringTokenizer). These values can be changed on the
  1383.      * tokenizer class, before retrieving the tokens.
  1384.      * </p>
  1385.      * <p>
  1386.      * The returned tokenizer is linked to this builder. You may intermix calls to the builder and tokenizer within
  1387.      * certain limits, however there is no synchronization. Once the tokenizer has been used once, it must be
  1388.      * {@link StringTokenizer#reset() reset} to pickup the latest changes in the builder. For example:
  1389.      * </p>
  1390.      *
  1391.      * <pre>
  1392.      * StrBuilder b = new StrBuilder();
  1393.      * b.append("a b ");
  1394.      * StrTokenizer t = b.asTokenizer();
  1395.      * String[] tokens1 = t.getTokenArray(); // returns a,b
  1396.      * b.append("c d ");
  1397.      * String[] tokens2 = t.getTokenArray(); // returns a,b (c and d ignored)
  1398.      * t.reset(); // reset causes builder changes to be picked up
  1399.      * String[] tokens3 = t.getTokenArray(); // returns a,b,c,d
  1400.      * </pre>
  1401.      *
  1402.      * <p>
  1403.      * In addition to simply intermixing appends and tokenization, you can also call the set methods on the tokenizer to
  1404.      * alter how it tokenizes. Just remember to call reset when you want to pickup builder changes.
  1405.      * </p>
  1406.      * <p>
  1407.      * Calling {@link StringTokenizer#reset(String)} or {@link StringTokenizer#reset(char[])} with a non-null value will
  1408.      * break the link with the builder.
  1409.      * </p>
  1410.      *
  1411.      * @return a tokenizer that is linked to this builder
  1412.      */
  1413.     public StringTokenizer asTokenizer() {
  1414.         return new TextStringBuilderTokenizer();
  1415.     }

  1416.     /**
  1417.      * Gets this builder as a Writer that can be written to.
  1418.      * <p>
  1419.      * This method allows you to populate the contents of the builder using any standard method that takes a Writer.
  1420.      * </p>
  1421.      * <p>
  1422.      * To use, simply create a {@code StrBuilder}, call {@code asWriter}, and populate away. The data is available at
  1423.      * any time using the methods of the {@code StrBuilder}.
  1424.      * </p>
  1425.      * <p>
  1426.      * The internal character array is shared between the builder and the writer. This allows you to intermix calls that
  1427.      * append to the builder and write using the writer and the changes will be occur correctly. Note however, that no
  1428.      * synchronization occurs, so you must perform all operations with the builder and the writer in one thread.
  1429.      * </p>
  1430.      * <p>
  1431.      * The returned writer ignores the close and flush methods.
  1432.      * </p>
  1433.      *
  1434.      * @return a writer that populates this builder
  1435.      */
  1436.     public Writer asWriter() {
  1437.         return new TextStringBuilderWriter();
  1438.     }

  1439.     /**
  1440.      * Converts this instance to a String.
  1441.      *
  1442.      * @return This instance as a String
  1443.      * @see #toString()
  1444.      * @deprecated Use {@link #get()}.
  1445.      */
  1446.     @Deprecated
  1447.     @Override
  1448.     public String build() {
  1449.         return toString();
  1450.     }

  1451.     /**
  1452.      * Gets the current size of the internal character array buffer.
  1453.      *
  1454.      * @return The capacity
  1455.      */
  1456.     public int capacity() {
  1457.         return buffer.length;
  1458.     }

  1459.     /**
  1460.      * Gets the character at the specified index.
  1461.      *
  1462.      * @see #setCharAt(int, char)
  1463.      * @see #deleteCharAt(int)
  1464.      * @param index the index to retrieve, must be valid
  1465.      * @return The character at the index
  1466.      * @throws IndexOutOfBoundsException if the index is invalid
  1467.      */
  1468.     @Override
  1469.     public char charAt(final int index) {
  1470.         validateIndex(index);
  1471.         return buffer[index];
  1472.     }

  1473.     /**
  1474.      * Clears the string builder (convenience Collections API style method).
  1475.      * <p>
  1476.      * This method does not reduce the size of the internal character buffer. To do that, call {@code clear()} followed
  1477.      * by {@link #minimizeCapacity()}.
  1478.      * </p>
  1479.      * <p>
  1480.      * This method is the same as {@link #setLength(int)} called with zero and is provided to match the API of
  1481.      * Collections.
  1482.      * </p>
  1483.      *
  1484.      * @return this, to enable chaining
  1485.      */
  1486.     public TextStringBuilder clear() {
  1487.         size = 0;
  1488.         return this;
  1489.     }

  1490.     /**
  1491.      * Tests if the string builder contains the specified char.
  1492.      *
  1493.      * @param ch the character to find
  1494.      * @return true if the builder contains the character
  1495.      */
  1496.     public boolean contains(final char ch) {
  1497.         final char[] thisBuf = buffer;
  1498.         for (int i = 0; i < this.size; i++) {
  1499.             if (thisBuf[i] == ch) {
  1500.                 return true;
  1501.             }
  1502.         }
  1503.         return false;
  1504.     }

  1505.     /**
  1506.      * Tests if the string builder contains the specified string.
  1507.      *
  1508.      * @param str the string to find
  1509.      * @return true if the builder contains the string
  1510.      */
  1511.     public boolean contains(final String str) {
  1512.         return indexOf(str, 0) >= 0;
  1513.     }

  1514.     /**
  1515.      * Tests if the string builder contains a string matched using the specified matcher.
  1516.      * <p>
  1517.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to search for
  1518.      * the character 'a' followed by a number.
  1519.      * </p>
  1520.      *
  1521.      * @param matcher the matcher to use, null returns -1
  1522.      * @return true if the matcher finds a match in the builder
  1523.      */
  1524.     public boolean contains(final StringMatcher matcher) {
  1525.         return indexOf(matcher, 0) >= 0;
  1526.     }

  1527.     /**
  1528.      * Deletes the characters between the two specified indices.
  1529.      *
  1530.      * @param startIndex the start index, inclusive, must be valid
  1531.      * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string
  1532.      * @return this, to enable chaining
  1533.      * @throws IndexOutOfBoundsException if the index is invalid
  1534.      */
  1535.     public TextStringBuilder delete(final int startIndex, final int endIndex) {
  1536.         final int actualEndIndex = validateRange(startIndex, endIndex);
  1537.         final int len = actualEndIndex - startIndex;
  1538.         if (len > 0) {
  1539.             deleteImpl(startIndex, actualEndIndex, len);
  1540.         }
  1541.         return this;
  1542.     }

  1543.     /**
  1544.      * Deletes the character wherever it occurs in the builder.
  1545.      *
  1546.      * @param ch the character to delete
  1547.      * @return this, to enable chaining
  1548.      */
  1549.     public TextStringBuilder deleteAll(final char ch) {
  1550.         for (int i = 0; i < size; i++) {
  1551.             if (buffer[i] == ch) {
  1552.                 final int start = i;
  1553.                 while (++i < size) {
  1554.                     if (buffer[i] != ch) {
  1555.                         break;
  1556.                     }
  1557.                 }
  1558.                 final int len = i - start;
  1559.                 deleteImpl(start, i, len);
  1560.                 i -= len;
  1561.             }
  1562.         }
  1563.         return this;
  1564.     }

  1565.     /**
  1566.      * Deletes the string wherever it occurs in the builder.
  1567.      *
  1568.      * @param str the string to delete, null causes no action
  1569.      * @return this, to enable chaining
  1570.      */
  1571.     public TextStringBuilder deleteAll(final String str) {
  1572.         final int len = str == null ? 0 : str.length();
  1573.         if (len > 0) {
  1574.             int index = indexOf(str, 0);
  1575.             while (index >= 0) {
  1576.                 deleteImpl(index, index + len, len);
  1577.                 index = indexOf(str, index);
  1578.             }
  1579.         }
  1580.         return this;
  1581.     }

  1582.     /**
  1583.      * Deletes all parts of the builder that the matcher matches.
  1584.      * <p>
  1585.      * Matchers can be used to perform advanced deletion behavior. For example you could write a matcher to delete all
  1586.      * occurrences where the character 'a' is followed by a number.
  1587.      * </p>
  1588.      *
  1589.      * @param matcher the matcher to use to find the deletion, null causes no action
  1590.      * @return this, to enable chaining
  1591.      */
  1592.     public TextStringBuilder deleteAll(final StringMatcher matcher) {
  1593.         return replace(matcher, null, 0, size, -1);
  1594.     }

  1595.     /**
  1596.      * Deletes the character at the specified index.
  1597.      *
  1598.      * @see #charAt(int)
  1599.      * @see #setCharAt(int, char)
  1600.      * @param index the index to delete
  1601.      * @return this, to enable chaining
  1602.      * @throws IndexOutOfBoundsException if the index is invalid
  1603.      */
  1604.     public TextStringBuilder deleteCharAt(final int index) {
  1605.         validateIndex(index);
  1606.         deleteImpl(index, index + 1, 1);
  1607.         return this;
  1608.     }

  1609.     /**
  1610.      * Deletes the character wherever it occurs in the builder.
  1611.      *
  1612.      * @param ch the character to delete
  1613.      * @return this, to enable chaining
  1614.      */
  1615.     public TextStringBuilder deleteFirst(final char ch) {
  1616.         for (int i = 0; i < size; i++) {
  1617.             if (buffer[i] == ch) {
  1618.                 deleteImpl(i, i + 1, 1);
  1619.                 break;
  1620.             }
  1621.         }
  1622.         return this;
  1623.     }

  1624.     /**
  1625.      * Deletes the string wherever it occurs in the builder.
  1626.      *
  1627.      * @param str the string to delete, null causes no action
  1628.      * @return this, to enable chaining
  1629.      */
  1630.     public TextStringBuilder deleteFirst(final String str) {
  1631.         final int len = str == null ? 0 : str.length();
  1632.         if (len > 0) {
  1633.             final int index = indexOf(str, 0);
  1634.             if (index >= 0) {
  1635.                 deleteImpl(index, index + len, len);
  1636.             }
  1637.         }
  1638.         return this;
  1639.     }

  1640.     /**
  1641.      * Deletes the first match within the builder using the specified matcher.
  1642.      * <p>
  1643.      * Matchers can be used to perform advanced deletion behavior. For example you could write a matcher to delete where
  1644.      * the character 'a' is followed by a number.
  1645.      * </p>
  1646.      *
  1647.      * @param matcher the matcher to use to find the deletion, null causes no action
  1648.      * @return this, to enable chaining
  1649.      */
  1650.     public TextStringBuilder deleteFirst(final StringMatcher matcher) {
  1651.         return replace(matcher, null, 0, size, 1);
  1652.     }

  1653.     /**
  1654.      * Internal method to delete a range without validation.
  1655.      *
  1656.      * @param startIndex the start index, must be valid
  1657.      * @param endIndex the end index (exclusive), must be valid
  1658.      * @param len the length, must be valid
  1659.      * @throws IndexOutOfBoundsException if any index is invalid
  1660.      */
  1661.     private void deleteImpl(final int startIndex, final int endIndex, final int len) {
  1662.         System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex);
  1663.         size -= len;
  1664.     }

  1665.     /**
  1666.      * Gets the character at the specified index before deleting it.
  1667.      *
  1668.      * @see #charAt(int)
  1669.      * @see #deleteCharAt(int)
  1670.      * @param index the index to retrieve, must be valid
  1671.      * @return The character at the index
  1672.      * @throws IndexOutOfBoundsException if the index is invalid
  1673.      * @since 1.9
  1674.      */
  1675.     public char drainChar(final int index) {
  1676.         validateIndex(index);
  1677.         final char c = buffer[index];
  1678.         deleteCharAt(index);
  1679.         return c;
  1680.     }

  1681.     /**
  1682.      * Drains (copies, then deletes) this character sequence into the specified array. This is equivalent to copying the
  1683.      * characters from this sequence into the target and then deleting those character from this sequence.
  1684.      *
  1685.      * @param startIndex first index to copy, inclusive.
  1686.      * @param endIndex last index to copy, exclusive.
  1687.      * @param target the target array, must not be {@code null}.
  1688.      * @param targetIndex the index to start copying in the target.
  1689.      * @return How many characters where copied (then deleted). If this builder is empty, return {@code 0}.
  1690.      * @since 1.9
  1691.      */
  1692.     public int drainChars(final int startIndex, final int endIndex, final char[] target, final int targetIndex) {
  1693.         final int length = endIndex - startIndex;
  1694.         if (isEmpty() || length == 0 || target.length == 0) {
  1695.             return 0;
  1696.         }
  1697.         final int actualLen = Math.min(Math.min(size, length), target.length - targetIndex);
  1698.         getChars(startIndex, actualLen, target, targetIndex);
  1699.         delete(startIndex, actualLen);
  1700.         return actualLen;
  1701.     }

  1702.     /**
  1703.      * Checks whether this builder ends with the specified string.
  1704.      * <p>
  1705.      * Note that this method handles null input quietly, unlike String.
  1706.      * </p>
  1707.      *
  1708.      * @param str the string to search for, null returns false
  1709.      * @return true if the builder ends with the string
  1710.      */
  1711.     public boolean endsWith(final String str) {
  1712.         if (str == null) {
  1713.             return false;
  1714.         }
  1715.         final int len = str.length();
  1716.         if (len == 0) {
  1717.             return true;
  1718.         }
  1719.         if (len > size) {
  1720.             return false;
  1721.         }
  1722.         int pos = size - len;
  1723.         for (int i = 0; i < len; i++, pos++) {
  1724.             if (buffer[pos] != str.charAt(i)) {
  1725.                 return false;
  1726.             }
  1727.         }
  1728.         return true;
  1729.     }

  1730.     /**
  1731.      * Tests the capacity and ensures that it is at least the size specified.
  1732.      *
  1733.      * <p>
  1734.      * Note: This method can be used to minimise memory reallocations during
  1735.      * repeated addition of values by pre-allocating the character buffer.
  1736.      * The method ignores a negative {@code capacity} argument.
  1737.      * </p>
  1738.      *
  1739.      * @param capacity the capacity to ensure
  1740.      * @return this, to enable chaining
  1741.      * @throws OutOfMemoryError if the capacity cannot be allocated
  1742.      */
  1743.     public TextStringBuilder ensureCapacity(final int capacity) {
  1744.         if (capacity > 0) {
  1745.             ensureCapacityInternal(capacity);
  1746.         }
  1747.         return this;
  1748.     }

  1749.     /**
  1750.      * Ensures that the buffer is at least the size specified. The {@code capacity} argument
  1751.      * is treated as an unsigned integer.
  1752.      *
  1753.      * <p>
  1754.      * This method will raise an {@link OutOfMemoryError} if the capacity is too large
  1755.      * for an array, or cannot be allocated.
  1756.      * </p>
  1757.      *
  1758.      * @param capacity the capacity to ensure
  1759.      * @throws OutOfMemoryError if the capacity cannot be allocated
  1760.      */
  1761.     private void ensureCapacityInternal(final int capacity) {
  1762.         // Check for overflow of the current buffer.
  1763.         // Assumes capacity is an unsigned integer up to Integer.MAX_VALUE * 2
  1764.         // (the largest possible addition of two maximum length arrays).
  1765.         if (capacity - buffer.length > 0) {
  1766.             resizeBuffer(capacity);
  1767.         }
  1768.     }

  1769.     /**
  1770.      * Tests the contents of this builder against another to see if they contain the same character content.
  1771.      *
  1772.      * @param obj the object to check, null returns false
  1773.      * @return true if the builders contain the same characters in the same order
  1774.      */
  1775.     @Override
  1776.     public boolean equals(final Object obj) {
  1777.         return obj instanceof TextStringBuilder && equals((TextStringBuilder) obj);
  1778.     }

  1779.     /**
  1780.      * Tests the contents of this builder against another to see if they contain the same character content.
  1781.      *
  1782.      * @param other the object to check, null returns false
  1783.      * @return true if the builders contain the same characters in the same order
  1784.      */
  1785.     public boolean equals(final TextStringBuilder other) {
  1786.         if (this == other) {
  1787.             return true;
  1788.         }
  1789.         if (other == null) {
  1790.             return false;
  1791.         }
  1792.         if (this.size != other.size) {
  1793.             return false;
  1794.         }
  1795.         // Be aware not to use Arrays.equals(buffer, other.buffer) for equals() method
  1796.         // as length of the buffers may be different (TEXT-211)
  1797.         final char[] thisBuf = this.buffer;
  1798.         final char[] otherBuf = other.buffer;
  1799.         for (int i = size - 1; i >= 0; i--) {
  1800.             if (thisBuf[i] != otherBuf[i]) {
  1801.                 return false;
  1802.             }
  1803.         }
  1804.         return true;
  1805.     }

  1806.     /**
  1807.      * Tests the contents of this builder against another to see if they contain the same character content ignoring
  1808.      * case.
  1809.      *
  1810.      * @param other the object to check, null returns false
  1811.      * @return true if the builders contain the same characters in the same order
  1812.      */
  1813.     public boolean equalsIgnoreCase(final TextStringBuilder other) {
  1814.         if (this == other) {
  1815.             return true;
  1816.         }
  1817.         if (this.size != other.size) {
  1818.             return false;
  1819.         }
  1820.         final char[] thisBuf = this.buffer;
  1821.         final char[] otherBuf = other.buffer;
  1822.         for (int i = size - 1; i >= 0; i--) {
  1823.             final char c1 = thisBuf[i];
  1824.             final char c2 = otherBuf[i];
  1825.             if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) {
  1826.                 return false;
  1827.             }
  1828.         }
  1829.         return true;
  1830.     }

  1831.     /**
  1832.      * Converts this instance to a String.
  1833.      *
  1834.      * @return This instance as a String
  1835.      * @see #toString()
  1836.      * @since 1.12.0
  1837.      */
  1838.     @Override
  1839.     public String get() {
  1840.         return toString();
  1841.     }

  1842.     /**
  1843.      * Gets a direct reference to internal storage, not for public consumption.
  1844.      */
  1845.     char[] getBuffer() {
  1846.         return buffer;
  1847.     }

  1848.     /**
  1849.      * Copies this character array into the specified array.
  1850.      *
  1851.      * @param target the target array, null will cause an array to be created
  1852.      * @return The input array, unless that was null or too small
  1853.      */
  1854.     public char[] getChars(char[] target) {
  1855.         final int len = length();
  1856.         if (target == null || target.length < len) {
  1857.             target = new char[len];
  1858.         }
  1859.         System.arraycopy(buffer, 0, target, 0, len);
  1860.         return target;
  1861.     }

  1862.     /**
  1863.      * Copies this character array into the specified array.
  1864.      *
  1865.      * @param startIndex first index to copy, inclusive, must be valid.
  1866.      * @param endIndex last index to copy, exclusive, must be valid.
  1867.      * @param target the target array, must not be null or too small.
  1868.      * @param targetIndex the index to start copying in target.
  1869.      * @throws NullPointerException if the array is null.
  1870.      * @throws IndexOutOfBoundsException if any index is invalid.
  1871.      */
  1872.     public void getChars(final int startIndex, final int endIndex, final char[] target, final int targetIndex) {
  1873.         if (startIndex < 0) {
  1874.             throw new StringIndexOutOfBoundsException(startIndex);
  1875.         }
  1876.         if (endIndex < 0 || endIndex > length()) {
  1877.             throw new StringIndexOutOfBoundsException(endIndex);
  1878.         }
  1879.         if (startIndex > endIndex) {
  1880.             throw new StringIndexOutOfBoundsException("end < start");
  1881.         }
  1882.         System.arraycopy(buffer, startIndex, target, targetIndex, endIndex - startIndex);
  1883.     }

  1884.     /**
  1885.      * Gets the text to be appended when a {@link #appendNewLine() new line} is added.
  1886.      *
  1887.      * @return The new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
  1888.      */
  1889.     public String getNewLineText() {
  1890.         return newLine;
  1891.     }

  1892.     /**
  1893.      * Gets the text to be appended when null is added.
  1894.      *
  1895.      * @return The null text, null means no append
  1896.      */
  1897.     public String getNullText() {
  1898.         return nullText;
  1899.     }

  1900.     /**
  1901.      * Gets a suitable hash code for this builder.
  1902.      *
  1903.      * @return a hash code
  1904.      */
  1905.     @Override
  1906.     public int hashCode() {
  1907.         // no allocation
  1908.         final char[] buf = buffer;
  1909.         int result = 0;
  1910.         for (int i = 0; i < size; i++) {
  1911.             result = 31 * result + buf[i];
  1912.         }
  1913.         return result;
  1914.     }

  1915.     /**
  1916.      * Searches the string builder to find the first reference to the specified char.
  1917.      *
  1918.      * @param ch the character to find
  1919.      * @return The first index of the character, or -1 if not found
  1920.      */
  1921.     public int indexOf(final char ch) {
  1922.         return indexOf(ch, 0);
  1923.     }

  1924.     /**
  1925.      * Searches the string builder to find the first reference to the specified char.
  1926.      *
  1927.      * @param ch the character to find
  1928.      * @param startIndex the index to start at, invalid index rounded to edge
  1929.      * @return The first index of the character, or -1 if not found
  1930.      */
  1931.     public int indexOf(final char ch, int startIndex) {
  1932.         startIndex = Math.max(0, startIndex);
  1933.         if (startIndex >= size) {
  1934.             return StringUtils.INDEX_NOT_FOUND;
  1935.         }
  1936.         final char[] thisBuf = buffer;
  1937.         for (int i = startIndex; i < size; i++) {
  1938.             if (thisBuf[i] == ch) {
  1939.                 return i;
  1940.             }
  1941.         }
  1942.         return StringUtils.INDEX_NOT_FOUND;
  1943.     }

  1944.     /**
  1945.      * Searches the string builder to find the first reference to the specified string.
  1946.      * <p>
  1947.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  1948.      * </p>
  1949.      *
  1950.      * @param str the string to find, null returns -1
  1951.      * @return The first index of the string, or -1 if not found
  1952.      */
  1953.     public int indexOf(final String str) {
  1954.         return indexOf(str, 0);
  1955.     }

  1956.     /**
  1957.      * Searches the string builder to find the first reference to the specified string starting searching from the given
  1958.      * index.
  1959.      * <p>
  1960.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  1961.      * </p>
  1962.      *
  1963.      * @param str the string to find, null returns -1
  1964.      * @param startIndex the index to start at, invalid index rounded to edge
  1965.      * @return The first index of the string, or -1 if not found
  1966.      */
  1967.     public int indexOf(final String str, int startIndex) {
  1968.         startIndex = Math.max(0, startIndex);
  1969.         if (str == null || startIndex >= size) {
  1970.             return StringUtils.INDEX_NOT_FOUND;
  1971.         }
  1972.         final int strLen = str.length();
  1973.         if (strLen == 1) {
  1974.             return indexOf(str.charAt(0), startIndex);
  1975.         }
  1976.         if (strLen == 0) {
  1977.             return startIndex;
  1978.         }
  1979.         if (strLen > size) {
  1980.             return StringUtils.INDEX_NOT_FOUND;
  1981.         }
  1982.         final char[] thisBuf = buffer;
  1983.         final int len = size - strLen + 1;
  1984.         outer: for (int i = startIndex; i < len; i++) {
  1985.             for (int j = 0; j < strLen; j++) {
  1986.                 if (str.charAt(j) != thisBuf[i + j]) {
  1987.                     continue outer;
  1988.                 }
  1989.             }
  1990.             return i;
  1991.         }
  1992.         return StringUtils.INDEX_NOT_FOUND;
  1993.     }

  1994.     /**
  1995.      * Searches the string builder using the matcher to find the first match.
  1996.      * <p>
  1997.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
  1998.      * character 'a' followed by a number.
  1999.      * </p>
  2000.      *
  2001.      * @param matcher the matcher to use, null returns -1
  2002.      * @return The first index matched, or -1 if not found
  2003.      */
  2004.     public int indexOf(final StringMatcher matcher) {
  2005.         return indexOf(matcher, 0);
  2006.     }

  2007.     /**
  2008.      * Searches the string builder using the matcher to find the first match searching from the given index.
  2009.      * <p>
  2010.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
  2011.      * character 'a' followed by a number.
  2012.      * </p>
  2013.      *
  2014.      * @param matcher the matcher to use, null returns -1
  2015.      * @param startIndex the index to start at, invalid index rounded to edge
  2016.      * @return The first index matched, or -1 if not found
  2017.      */
  2018.     public int indexOf(final StringMatcher matcher, int startIndex) {
  2019.         startIndex = Math.max(0, startIndex);
  2020.         if (matcher == null || startIndex >= size) {
  2021.             return StringUtils.INDEX_NOT_FOUND;
  2022.         }
  2023.         final int len = size;
  2024.         final char[] buf = buffer;
  2025.         for (int i = startIndex; i < len; i++) {
  2026.             if (matcher.isMatch(buf, i, startIndex, len) > 0) {
  2027.                 return i;
  2028.             }
  2029.         }
  2030.         return StringUtils.INDEX_NOT_FOUND;
  2031.     }

  2032.     /**
  2033.      * Inserts the value into this builder.
  2034.      *
  2035.      * @param index the index to add at, must be valid
  2036.      * @param value the value to insert
  2037.      * @return this, to enable chaining
  2038.      * @throws IndexOutOfBoundsException if the index is invalid
  2039.      */
  2040.     public TextStringBuilder insert(final int index, final boolean value) {
  2041.         validateIndex(index);
  2042.         if (value) {
  2043.             ensureCapacityInternal(size + TRUE_STRING_SIZE);
  2044.             System.arraycopy(buffer, index, buffer, index + TRUE_STRING_SIZE, size - index);
  2045.             appendTrue(index);
  2046.         } else {
  2047.             ensureCapacityInternal(size + FALSE_STRING_SIZE);
  2048.             System.arraycopy(buffer, index, buffer, index + FALSE_STRING_SIZE, size - index);
  2049.             appendFalse(index);
  2050.         }
  2051.         return this;
  2052.     }

  2053.     /**
  2054.      * Inserts the value into this builder.
  2055.      *
  2056.      * @param index the index to add at, must be valid
  2057.      * @param value the value to insert
  2058.      * @return this, to enable chaining
  2059.      * @throws IndexOutOfBoundsException if the index is invalid
  2060.      */
  2061.     public TextStringBuilder insert(final int index, final char value) {
  2062.         validateIndex(index);
  2063.         ensureCapacityInternal(size + 1);
  2064.         System.arraycopy(buffer, index, buffer, index + 1, size - index);
  2065.         buffer[index] = value;
  2066.         size++;
  2067.         return this;
  2068.     }

  2069.     /**
  2070.      * Inserts the character array into this builder. Inserting null will use the stored null text value.
  2071.      *
  2072.      * @param index the index to add at, must be valid
  2073.      * @param chars the char array to insert
  2074.      * @return this, to enable chaining
  2075.      * @throws IndexOutOfBoundsException if the index is invalid
  2076.      */
  2077.     public TextStringBuilder insert(final int index, final char[] chars) {
  2078.         validateIndex(index);
  2079.         if (chars == null) {
  2080.             return insert(index, nullText);
  2081.         }
  2082.         final int len = chars.length;
  2083.         if (len > 0) {
  2084.             ensureCapacityInternal(size + len);
  2085.             System.arraycopy(buffer, index, buffer, index + len, size - index);
  2086.             System.arraycopy(chars, 0, buffer, index, len);
  2087.             size += len;
  2088.         }
  2089.         return this;
  2090.     }

  2091.     /**
  2092.      * Inserts part of the character array into this builder. Inserting null will use the stored null text value.
  2093.      *
  2094.      * @param index the index to add at, must be valid
  2095.      * @param chars the char array to insert
  2096.      * @param offset the offset into the character array to start at, must be valid
  2097.      * @param length the length of the character array part to copy, must be positive
  2098.      * @return this, to enable chaining
  2099.      * @throws IndexOutOfBoundsException if any index is invalid
  2100.      */
  2101.     public TextStringBuilder insert(final int index, final char[] chars, final int offset, final int length) {
  2102.         validateIndex(index);
  2103.         if (chars == null) {
  2104.             return insert(index, nullText);
  2105.         }
  2106.         if (offset < 0 || offset > chars.length) {
  2107.             throw new StringIndexOutOfBoundsException("Invalid offset: " + offset);
  2108.         }
  2109.         if (length < 0 || offset + length > chars.length) {
  2110.             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
  2111.         }
  2112.         if (length > 0) {
  2113.             ensureCapacityInternal(size + length);
  2114.             System.arraycopy(buffer, index, buffer, index + length, size - index);
  2115.             System.arraycopy(chars, offset, buffer, index, length);
  2116.             size += length;
  2117.         }
  2118.         return this;
  2119.     }

  2120.     /**
  2121.      * Inserts the value into this builder.
  2122.      *
  2123.      * @param index the index to add at, must be valid
  2124.      * @param value the value to insert
  2125.      * @return this, to enable chaining
  2126.      * @throws IndexOutOfBoundsException if the index is invalid
  2127.      */
  2128.     public TextStringBuilder insert(final int index, final double value) {
  2129.         return insert(index, String.valueOf(value));
  2130.     }

  2131.     /**
  2132.      * Inserts the value into this builder.
  2133.      *
  2134.      * @param index the index to add at, must be valid
  2135.      * @param value the value to insert
  2136.      * @return this, to enable chaining
  2137.      * @throws IndexOutOfBoundsException if the index is invalid
  2138.      */
  2139.     public TextStringBuilder insert(final int index, final float value) {
  2140.         return insert(index, String.valueOf(value));
  2141.     }

  2142.     /**
  2143.      * Inserts the value into this builder.
  2144.      *
  2145.      * @param index the index to add at, must be valid
  2146.      * @param value the value to insert
  2147.      * @return this, to enable chaining
  2148.      * @throws IndexOutOfBoundsException if the index is invalid
  2149.      */
  2150.     public TextStringBuilder insert(final int index, final int value) {
  2151.         return insert(index, String.valueOf(value));
  2152.     }

  2153.     /**
  2154.      * Inserts the value into this builder.
  2155.      *
  2156.      * @param index the index to add at, must be valid
  2157.      * @param value the value to insert
  2158.      * @return this, to enable chaining
  2159.      * @throws IndexOutOfBoundsException if the index is invalid
  2160.      */
  2161.     public TextStringBuilder insert(final int index, final long value) {
  2162.         return insert(index, String.valueOf(value));
  2163.     }

  2164.     /**
  2165.      * Inserts the string representation of an object into this builder. Inserting null will use the stored null text
  2166.      * value.
  2167.      *
  2168.      * @param index the index to add at, must be valid
  2169.      * @param obj the object to insert
  2170.      * @return this, to enable chaining
  2171.      * @throws IndexOutOfBoundsException if the index is invalid
  2172.      */
  2173.     public TextStringBuilder insert(final int index, final Object obj) {
  2174.         if (obj == null) {
  2175.             return insert(index, nullText);
  2176.         }
  2177.         return insert(index, obj.toString());
  2178.     }

  2179.     /**
  2180.      * Inserts the string into this builder. Inserting null will use the stored null text value.
  2181.      *
  2182.      * @param index the index to add at, must be valid
  2183.      * @param str the string to insert
  2184.      * @return this, to enable chaining
  2185.      * @throws IndexOutOfBoundsException if the index is invalid
  2186.      */
  2187.     public TextStringBuilder insert(final int index, String str) {
  2188.         validateIndex(index);
  2189.         if (str == null) {
  2190.             str = nullText;
  2191.         }
  2192.         if (str != null) {
  2193.             final int strLen = str.length();
  2194.             if (strLen > 0) {
  2195.                 final int newSize = size + strLen;
  2196.                 ensureCapacityInternal(newSize);
  2197.                 System.arraycopy(buffer, index, buffer, index + strLen, size - index);
  2198.                 size = newSize;
  2199.                 str.getChars(0, strLen, buffer, index);
  2200.             }
  2201.         }
  2202.         return this;
  2203.     }

  2204.     /**
  2205.      * Checks is the string builder is empty (convenience Collections API style method).
  2206.      * <p>
  2207.      * This method is the same as checking {@link #length()} and is provided to match the API of Collections.
  2208.      * </p>
  2209.      *
  2210.      * @return {@code true} if the size is {@code 0}.
  2211.      */
  2212.     public boolean isEmpty() {
  2213.         return size == 0;
  2214.     }

  2215.     /**
  2216.      * Checks is the string builder is not empty.
  2217.      * <p>
  2218.      * This method is the same as checking {@link #length()}.
  2219.      * </p>
  2220.      *
  2221.      * @return {@code true} if the size is not {@code 0}.
  2222.      * @since 1.9
  2223.      */
  2224.     public boolean isNotEmpty() {
  2225.         return size != 0;
  2226.     }

  2227.     /**
  2228.      * Gets whether the internal buffer has been reallocated.
  2229.      *
  2230.      * @return Whether the internal buffer has been reallocated.
  2231.      * @since 1.9
  2232.      */
  2233.     public boolean isReallocated() {
  2234.         return reallocations > 0;
  2235.     }

  2236.     /**
  2237.      * Searches the string builder to find the last reference to the specified char.
  2238.      *
  2239.      * @param ch the character to find
  2240.      * @return The last index of the character, or -1 if not found
  2241.      */
  2242.     public int lastIndexOf(final char ch) {
  2243.         return lastIndexOf(ch, size - 1);
  2244.     }

  2245.     /**
  2246.      * Searches the string builder to find the last reference to the specified char.
  2247.      *
  2248.      * @param ch the character to find
  2249.      * @param startIndex the index to start at, invalid index rounded to edge
  2250.      * @return The last index of the character, or -1 if not found
  2251.      */
  2252.     public int lastIndexOf(final char ch, int startIndex) {
  2253.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2254.         if (startIndex < 0) {
  2255.             return StringUtils.INDEX_NOT_FOUND;
  2256.         }
  2257.         for (int i = startIndex; i >= 0; i--) {
  2258.             if (buffer[i] == ch) {
  2259.                 return i;
  2260.             }
  2261.         }
  2262.         return StringUtils.INDEX_NOT_FOUND;
  2263.     }

  2264.     /**
  2265.      * Searches the string builder to find the last reference to the specified string.
  2266.      * <p>
  2267.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  2268.      * </p>
  2269.      *
  2270.      * @param str the string to find, null returns -1
  2271.      * @return The last index of the string, or -1 if not found
  2272.      */
  2273.     public int lastIndexOf(final String str) {
  2274.         return lastIndexOf(str, size - 1);
  2275.     }

  2276.     /**
  2277.      * Searches the string builder to find the last reference to the specified string starting searching from the given
  2278.      * index.
  2279.      * <p>
  2280.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  2281.      * </p>
  2282.      *
  2283.      * @param str the string to find, null returns -1
  2284.      * @param startIndex the index to start at, invalid index rounded to edge
  2285.      * @return The last index of the string, or -1 if not found
  2286.      */
  2287.     public int lastIndexOf(final String str, int startIndex) {
  2288.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2289.         if (str == null || startIndex < 0) {
  2290.             return StringUtils.INDEX_NOT_FOUND;
  2291.         }
  2292.         final int strLen = str.length();
  2293.         if (strLen > 0 && strLen <= size) {
  2294.             if (strLen == 1) {
  2295.                 return lastIndexOf(str.charAt(0), startIndex);
  2296.             }

  2297.             outer: for (int i = startIndex - strLen + 1; i >= 0; i--) {
  2298.                 for (int j = 0; j < strLen; j++) {
  2299.                     if (str.charAt(j) != buffer[i + j]) {
  2300.                         continue outer;
  2301.                     }
  2302.                 }
  2303.                 return i;
  2304.             }

  2305.         } else if (strLen == 0) {
  2306.             return startIndex;
  2307.         }
  2308.         return StringUtils.INDEX_NOT_FOUND;
  2309.     }

  2310.     /**
  2311.      * Searches the string builder using the matcher to find the last match.
  2312.      * <p>
  2313.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
  2314.      * character 'a' followed by a number.
  2315.      * </p>
  2316.      *
  2317.      * @param matcher the matcher to use, null returns -1
  2318.      * @return The last index matched, or -1 if not found
  2319.      */
  2320.     public int lastIndexOf(final StringMatcher matcher) {
  2321.         return lastIndexOf(matcher, size);
  2322.     }

  2323.     /**
  2324.      * Searches the string builder using the matcher to find the last match searching from the given index.
  2325.      * <p>
  2326.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
  2327.      * character 'a' followed by a number.
  2328.      * </p>
  2329.      *
  2330.      * @param matcher the matcher to use, null returns -1
  2331.      * @param startIndex the index to start at, invalid index rounded to edge
  2332.      * @return The last index matched, or -1 if not found
  2333.      */
  2334.     public int lastIndexOf(final StringMatcher matcher, int startIndex) {
  2335.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2336.         if (matcher == null || startIndex < 0) {
  2337.             return StringUtils.INDEX_NOT_FOUND;
  2338.         }
  2339.         final char[] buf = buffer;
  2340.         final int endIndex = startIndex + 1;
  2341.         for (int i = startIndex; i >= 0; i--) {
  2342.             if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
  2343.                 return i;
  2344.             }
  2345.         }
  2346.         return StringUtils.INDEX_NOT_FOUND;
  2347.     }

  2348.     /**
  2349.      * Extracts the leftmost characters from the string builder without throwing an exception.
  2350.      * <p>
  2351.      * This method extracts the left {@code length} characters from the builder. If this many characters are not
  2352.      * available, the whole builder is returned. Thus the returned string may be shorter than the length requested.
  2353.      * </p>
  2354.      *
  2355.      * @param length the number of characters to extract, negative returns empty string
  2356.      * @return The new string
  2357.      */
  2358.     public String leftString(final int length) {
  2359.         if (length <= 0) {
  2360.             return StringUtils.EMPTY;
  2361.         }
  2362.         if (length >= size) {
  2363.             return new String(buffer, 0, size);
  2364.         }
  2365.         return new String(buffer, 0, length);
  2366.     }

  2367.     /**
  2368.      * Gets the length of the string builder.
  2369.      *
  2370.      * @return The length
  2371.      */
  2372.     @Override
  2373.     public int length() {
  2374.         return size;
  2375.     }

  2376.     /**
  2377.      * Extracts some characters from the middle of the string builder without throwing an exception.
  2378.      * <p>
  2379.      * This method extracts {@code length} characters from the builder at the specified index. If the index is negative
  2380.      * it is treated as zero. If the index is greater than the builder size, it is treated as the builder size. If the
  2381.      * length is negative, the empty string is returned. If insufficient characters are available in the builder, as
  2382.      * much as possible is returned. Thus the returned string may be shorter than the length requested.
  2383.      * </p>
  2384.      *
  2385.      * @param index the index to start at, negative means zero
  2386.      * @param length the number of characters to extract, negative returns empty string
  2387.      * @return The new string
  2388.      */
  2389.     public String midString(int index, final int length) {
  2390.         if (index < 0) {
  2391.             index = 0;
  2392.         }
  2393.         if (length <= 0 || index >= size) {
  2394.             return StringUtils.EMPTY;
  2395.         }
  2396.         if (size <= index + length) {
  2397.             return new String(buffer, index, size - index);
  2398.         }
  2399.         return new String(buffer, index, length);
  2400.     }

  2401.     /**
  2402.      * Minimizes the capacity to the actual length of the string.
  2403.      *
  2404.      * @return this, to enable chaining
  2405.      */
  2406.     public TextStringBuilder minimizeCapacity() {
  2407.         if (buffer.length > size) {
  2408.             reallocate(size);
  2409.         }
  2410.         return this;
  2411.     }

  2412.     /**
  2413.      * If possible, reads chars from the provided {@link CharBuffer} directly into underlying character buffer without
  2414.      * making extra copies.
  2415.      *
  2416.      * @param charBuffer CharBuffer to read.
  2417.      * @return The number of characters read.
  2418.      * @see #appendTo(Appendable)
  2419.      * @since 1.9
  2420.      */
  2421.     public int readFrom(final CharBuffer charBuffer) {
  2422.         final int oldSize = size;
  2423.         final int remaining = charBuffer.remaining();
  2424.         ensureCapacityInternal(size + remaining);
  2425.         charBuffer.get(buffer, size, remaining);
  2426.         size += remaining;
  2427.         return size - oldSize;
  2428.     }

  2429.     /**
  2430.      * If possible, reads all chars from the provided {@link Readable} directly into underlying character buffer without
  2431.      * making extra copies.
  2432.      *
  2433.      * @param readable object to read from
  2434.      * @return The number of characters read
  2435.      * @throws IOException if an I/O error occurs.
  2436.      * @see #appendTo(Appendable)
  2437.      */
  2438.     public int readFrom(final Readable readable) throws IOException {
  2439.         if (readable instanceof Reader) {
  2440.             return readFrom((Reader) readable);
  2441.         }
  2442.         if (readable instanceof CharBuffer) {
  2443.             return readFrom((CharBuffer) readable);
  2444.         }
  2445.         final int oldSize = size;
  2446.         while (true) {
  2447.             ensureCapacityInternal(size + 1);
  2448.             final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size);
  2449.             final int read = readable.read(buf);
  2450.             if (read == EOS) {
  2451.                 break;
  2452.             }
  2453.             size += read;
  2454.         }
  2455.         return size - oldSize;
  2456.     }

  2457.     /**
  2458.      * If possible, reads all chars from the provided {@link Reader} directly into underlying character buffer without
  2459.      * making extra copies.
  2460.      *
  2461.      * @param reader Reader to read.
  2462.      * @return The number of characters read or -1 if we reached the end of stream.
  2463.      * @throws IOException if an I/O error occurs.
  2464.      * @see #appendTo(Appendable)
  2465.      * @since 1.9
  2466.      */
  2467.     public int readFrom(final Reader reader) throws IOException {
  2468.         final int oldSize = size;
  2469.         ensureCapacityInternal(size + 1);
  2470.         int readCount = reader.read(buffer, size, buffer.length - size);
  2471.         if (readCount == EOS) {
  2472.             return EOS;
  2473.         }
  2474.         do {
  2475.             size += readCount;
  2476.             ensureCapacityInternal(size + 1);
  2477.             readCount = reader.read(buffer, size, buffer.length - size);
  2478.         } while (readCount != EOS);
  2479.         return size - oldSize;
  2480.     }

  2481.     /**
  2482.      * If possible, reads {@code count} chars from the provided {@link Reader} directly into underlying character buffer
  2483.      * without making extra copies.
  2484.      *
  2485.      * @param reader Reader to read.
  2486.      * @param count The maximum characters to read, a value &lt;= 0 returns 0.
  2487.      * @return The number of characters read. If less than {@code count}, then we've reached the end-of-stream, or -1 if
  2488.      *         we reached the end of stream.
  2489.      * @throws IOException if an I/O error occurs.
  2490.      * @see #appendTo(Appendable)
  2491.      * @since 1.9
  2492.      */
  2493.     public int readFrom(final Reader reader, final int count) throws IOException {
  2494.         if (count <= 0) {
  2495.             return 0;
  2496.         }
  2497.         final int oldSize = size;
  2498.         ensureCapacityInternal(size + count);
  2499.         int target = count;
  2500.         int readCount = reader.read(buffer, size, target);
  2501.         if (readCount == EOS) {
  2502.             return EOS;
  2503.         }
  2504.         do {
  2505.             target -= readCount;
  2506.             size += readCount;
  2507.             readCount = reader.read(buffer, size, target);
  2508.         } while (target > 0 && readCount != EOS);
  2509.         return size - oldSize;
  2510.     }

  2511.     /**
  2512.      * Reallocates the buffer to the new length.
  2513.      *
  2514.      * @param newLength the length of the copy to be returned
  2515.      */
  2516.     private void reallocate(final int newLength) {
  2517.         this.buffer = Arrays.copyOf(buffer, newLength);
  2518.         this.reallocations++;
  2519.     }

  2520.     /**
  2521.      * Replaces a portion of the string builder with another string. The length of the inserted string does not have to
  2522.      * match the removed length.
  2523.      *
  2524.      * @param startIndex the start index, inclusive, must be valid
  2525.      * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string
  2526.      * @param replaceStr the string to replace with, null means delete range
  2527.      * @return this, to enable chaining
  2528.      * @throws IndexOutOfBoundsException if the index is invalid
  2529.      */
  2530.     public TextStringBuilder replace(final int startIndex, int endIndex, final String replaceStr) {
  2531.         endIndex = validateRange(startIndex, endIndex);
  2532.         final int insertLen = replaceStr == null ? 0 : replaceStr.length();
  2533.         replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen);
  2534.         return this;
  2535.     }

  2536.     /**
  2537.      * Advanced search and replaces within the builder using a matcher.
  2538.      * <p>
  2539.      * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all
  2540.      * occurrences where the character 'a' is followed by a number.
  2541.      * </p>
  2542.      *
  2543.      * @param matcher the matcher to use to find the deletion, null causes no action
  2544.      * @param replaceStr the string to replace the match with, null is a delete
  2545.      * @param startIndex the start index, inclusive, must be valid
  2546.      * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string
  2547.      * @param replaceCount the number of times to replace, -1 for replace all
  2548.      * @return this, to enable chaining
  2549.      * @throws IndexOutOfBoundsException if start index is invalid
  2550.      */
  2551.     public TextStringBuilder replace(final StringMatcher matcher, final String replaceStr, final int startIndex,
  2552.         int endIndex, final int replaceCount) {
  2553.         endIndex = validateRange(startIndex, endIndex);
  2554.         return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount);
  2555.     }

  2556.     /**
  2557.      * Replaces the search character with the replace character throughout the builder.
  2558.      *
  2559.      * @param search the search character
  2560.      * @param replace the replace character
  2561.      * @return this, to enable chaining
  2562.      */
  2563.     public TextStringBuilder replaceAll(final char search, final char replace) {
  2564.         if (search != replace) {
  2565.             for (int i = 0; i < size; i++) {
  2566.                 if (buffer[i] == search) {
  2567.                     buffer[i] = replace;
  2568.                 }
  2569.             }
  2570.         }
  2571.         return this;
  2572.     }

  2573.     /**
  2574.      * Replaces the search string with the replace string throughout the builder.
  2575.      *
  2576.      * @param searchStr the search string, null causes no action to occur
  2577.      * @param replaceStr the replace string, null is equivalent to an empty string
  2578.      * @return this, to enable chaining
  2579.      */
  2580.     public TextStringBuilder replaceAll(final String searchStr, final String replaceStr) {
  2581.         final int searchLen = searchStr == null ? 0 : searchStr.length();
  2582.         if (searchLen > 0) {
  2583.             final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
  2584.             int index = indexOf(searchStr, 0);
  2585.             while (index >= 0) {
  2586.                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
  2587.                 index = indexOf(searchStr, index + replaceLen);
  2588.             }
  2589.         }
  2590.         return this;
  2591.     }

  2592.     /**
  2593.      * Replaces all matches within the builder with the replace string.
  2594.      * <p>
  2595.      * Matchers can be used to perform advanced replace behavior. For example you could write a matcher to replace all
  2596.      * occurrences where the character 'a' is followed by a number.
  2597.      * </p>
  2598.      *
  2599.      * @param matcher the matcher to use to find the deletion, null causes no action
  2600.      * @param replaceStr the replace string, null is equivalent to an empty string
  2601.      * @return this, to enable chaining
  2602.      */
  2603.     public TextStringBuilder replaceAll(final StringMatcher matcher, final String replaceStr) {
  2604.         return replace(matcher, replaceStr, 0, size, -1);
  2605.     }

  2606.     /**
  2607.      * Replaces the first instance of the search character with the replace character in the builder.
  2608.      *
  2609.      * @param search the search character
  2610.      * @param replace the replace character
  2611.      * @return this, to enable chaining
  2612.      */
  2613.     public TextStringBuilder replaceFirst(final char search, final char replace) {
  2614.         if (search != replace) {
  2615.             for (int i = 0; i < size; i++) {
  2616.                 if (buffer[i] == search) {
  2617.                     buffer[i] = replace;
  2618.                     break;
  2619.                 }
  2620.             }
  2621.         }
  2622.         return this;
  2623.     }

  2624.     /**
  2625.      * Replaces the first instance of the search string with the replace string.
  2626.      *
  2627.      * @param searchStr the search string, null causes no action to occur
  2628.      * @param replaceStr the replace string, null is equivalent to an empty string
  2629.      * @return this, to enable chaining
  2630.      */
  2631.     public TextStringBuilder replaceFirst(final String searchStr, final String replaceStr) {
  2632.         final int searchLen = searchStr == null ? 0 : searchStr.length();
  2633.         if (searchLen > 0) {
  2634.             final int index = indexOf(searchStr, 0);
  2635.             if (index >= 0) {
  2636.                 final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
  2637.                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
  2638.             }
  2639.         }
  2640.         return this;
  2641.     }

  2642.     /**
  2643.      * Replaces the first match within the builder with the replace string.
  2644.      * <p>
  2645.      * Matchers can be used to perform advanced replace behavior. For example you could write a matcher to replace where
  2646.      * the character 'a' is followed by a number.
  2647.      * </p>
  2648.      *
  2649.      * @param matcher the matcher to use to find the deletion, null causes no action
  2650.      * @param replaceStr the replace string, null is equivalent to an empty string
  2651.      * @return this, to enable chaining
  2652.      */
  2653.     public TextStringBuilder replaceFirst(final StringMatcher matcher, final String replaceStr) {
  2654.         return replace(matcher, replaceStr, 0, size, 1);
  2655.     }

  2656.     /**
  2657.      * Internal method to delete a range without validation.
  2658.      *
  2659.      * @param startIndex the start index, must be valid
  2660.      * @param endIndex the end index (exclusive), must be valid
  2661.      * @param removeLen the length to remove (endIndex - startIndex), must be valid
  2662.      * @param insertStr the string to replace with, null means delete range
  2663.      * @param insertLen the length of the insert string, must be valid
  2664.      * @throws IndexOutOfBoundsException if any index is invalid
  2665.      */
  2666.     private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr,
  2667.         final int insertLen) {
  2668.         final int newSize = size - removeLen + insertLen;
  2669.         if (insertLen != removeLen) {
  2670.             ensureCapacityInternal(newSize);
  2671.             System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex);
  2672.             size = newSize;
  2673.         }
  2674.         if (insertLen > 0) {
  2675.             insertStr.getChars(0, insertLen, buffer, startIndex);
  2676.         }
  2677.     }

  2678.     /**
  2679.      * Replaces within the builder using a matcher.
  2680.      * <p>
  2681.      * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all
  2682.      * occurrences where the character 'a' is followed by a number.
  2683.      * </p>
  2684.      *
  2685.      * @param matcher the matcher to use to find the deletion, null causes no action
  2686.      * @param replaceStr the string to replace the match with, null is a delete
  2687.      * @param from the start index, must be valid
  2688.      * @param to the end index (exclusive), must be valid
  2689.      * @param replaceCount the number of times to replace, -1 for replace all
  2690.      * @return this, to enable chaining
  2691.      * @throws IndexOutOfBoundsException if any index is invalid
  2692.      */
  2693.     private TextStringBuilder replaceImpl(final StringMatcher matcher, final String replaceStr, final int from, int to,
  2694.         int replaceCount) {
  2695.         if (matcher == null || size == 0) {
  2696.             return this;
  2697.         }
  2698.         final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
  2699.         for (int i = from; i < to && replaceCount != 0; i++) {
  2700.             final char[] buf = buffer;
  2701.             final int removeLen = matcher.isMatch(buf, i, from, to);
  2702.             if (removeLen > 0) {
  2703.                 replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen);
  2704.                 to = to - removeLen + replaceLen;
  2705.                 i = i + replaceLen - 1;
  2706.                 if (replaceCount > 0) {
  2707.                     replaceCount--;
  2708.                 }
  2709.             }
  2710.         }
  2711.         return this;
  2712.     }

  2713.     /**
  2714.      * Resizes the buffer to at least the size specified.
  2715.      *
  2716.      * @param minCapacity the minimum required capacity
  2717.      * @throws OutOfMemoryError if the {@code minCapacity} is negative
  2718.      */
  2719.     private void resizeBuffer(final int minCapacity) {
  2720.         // Overflow-conscious code treats the min and new capacity as unsigned.
  2721.         final int oldCapacity = buffer.length;
  2722.         int newCapacity = oldCapacity * 2;
  2723.         if (Integer.compareUnsigned(newCapacity, minCapacity) < 0) {
  2724.             newCapacity = minCapacity;
  2725.         }
  2726.         if (Integer.compareUnsigned(newCapacity, MAX_BUFFER_SIZE) > 0) {
  2727.             newCapacity = createPositiveCapacity(minCapacity);
  2728.         }
  2729.         reallocate(newCapacity);
  2730.     }

  2731.     /**
  2732.      * Reverses the string builder placing each character in the opposite index.
  2733.      *
  2734.      * @return this, to enable chaining
  2735.      */
  2736.     public TextStringBuilder reverse() {
  2737.         if (size == 0) {
  2738.             return this;
  2739.         }

  2740.         final int half = size / 2;
  2741.         final char[] buf = buffer;
  2742.         for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) {
  2743.             final char swap = buf[leftIdx];
  2744.             buf[leftIdx] = buf[rightIdx];
  2745.             buf[rightIdx] = swap;
  2746.         }
  2747.         return this;
  2748.     }

  2749.     /**
  2750.      * Extracts the rightmost characters from the string builder without throwing an exception.
  2751.      * <p>
  2752.      * This method extracts the right {@code length} characters from the builder. If this many characters are not
  2753.      * available, the whole builder is returned. Thus the returned string may be shorter than the length requested.
  2754.      * </p>
  2755.      *
  2756.      * @param length the number of characters to extract, negative returns empty string
  2757.      * @return The new string
  2758.      */
  2759.     public String rightString(final int length) {
  2760.         if (length <= 0) {
  2761.             return StringUtils.EMPTY;
  2762.         }
  2763.         if (length >= size) {
  2764.             return new String(buffer, 0, size);
  2765.         }
  2766.         return new String(buffer, size - length, length);
  2767.     }

  2768.     /**
  2769.      * Clears and sets this builder to the given value.
  2770.      *
  2771.      * @see #charAt(int)
  2772.      * @see #deleteCharAt(int)
  2773.      * @param str the new value.
  2774.      * @return this, to enable chaining
  2775.      * @since 1.9
  2776.      */
  2777.     public TextStringBuilder set(final CharSequence str) {
  2778.         clear();
  2779.         append(str);
  2780.         return this;
  2781.     }

  2782.     /**
  2783.      * Sets the character at the specified index.
  2784.      *
  2785.      * @see #charAt(int)
  2786.      * @see #deleteCharAt(int)
  2787.      * @param index the index to set
  2788.      * @param ch the new character
  2789.      * @return this, to enable chaining
  2790.      * @throws IndexOutOfBoundsException if the index is invalid
  2791.      */
  2792.     public TextStringBuilder setCharAt(final int index, final char ch) {
  2793.         validateIndex(index);
  2794.         buffer[index] = ch;
  2795.         return this;
  2796.     }

  2797.     /**
  2798.      * Updates the length of the builder by either dropping the last characters or adding filler of Unicode zero.
  2799.      *
  2800.      * @param length the length to set to, must be zero or positive
  2801.      * @return this, to enable chaining
  2802.      * @throws IndexOutOfBoundsException if the length is negative
  2803.      */
  2804.     public TextStringBuilder setLength(final int length) {
  2805.         if (length < 0) {
  2806.             throw new StringIndexOutOfBoundsException(length);
  2807.         }
  2808.         if (length < size) {
  2809.             size = length;
  2810.         } else if (length > size) {
  2811.             ensureCapacityInternal(length);
  2812.             final int oldEnd = size;
  2813.             size = length;
  2814.             Arrays.fill(buffer, oldEnd, length, '\0');
  2815.         }
  2816.         return this;
  2817.     }

  2818.     /**
  2819.      * Sets the text to be appended when {@link #appendNewLine() new line} is called.
  2820.      *
  2821.      * @param newLine the new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
  2822.      * @return this instance.
  2823.      */
  2824.     public TextStringBuilder setNewLineText(final String newLine) {
  2825.         this.newLine = newLine;
  2826.         return this;
  2827.     }

  2828.     /**
  2829.      * Sets the text to be appended when null is added.
  2830.      *
  2831.      * @param nullText the null text, null means no append
  2832.      * @return this, to enable chaining
  2833.      */
  2834.     public TextStringBuilder setNullText(String nullText) {
  2835.         if (nullText != null && nullText.isEmpty()) {
  2836.             nullText = null;
  2837.         }
  2838.         this.nullText = nullText;
  2839.         return this;
  2840.     }

  2841.     /**
  2842.      * Gets the length of the string builder.
  2843.      * <p>
  2844.      * This method is the same as {@link #length()} and is provided to match the API of Collections.
  2845.      * </p>
  2846.      *
  2847.      * @return The length
  2848.      */
  2849.     public int size() {
  2850.         return size;
  2851.     }

  2852.     /**
  2853.      * Checks whether this builder starts with the specified string.
  2854.      * <p>
  2855.      * Note that this method handles null input quietly, unlike String.
  2856.      * </p>
  2857.      *
  2858.      * @param str the string to search for, null returns false
  2859.      * @return true if the builder starts with the string
  2860.      */
  2861.     public boolean startsWith(final String str) {
  2862.         if (str == null) {
  2863.             return false;
  2864.         }
  2865.         final int len = str.length();
  2866.         if (len == 0) {
  2867.             return true;
  2868.         }
  2869.         if (len > size) {
  2870.             return false;
  2871.         }
  2872.         for (int i = 0; i < len; i++) {
  2873.             if (buffer[i] != str.charAt(i)) {
  2874.                 return false;
  2875.             }
  2876.         }
  2877.         return true;
  2878.     }

  2879.     /**
  2880.      * {@inheritDoc}
  2881.      */
  2882.     @Override
  2883.     public CharSequence subSequence(final int startIndex, final int endIndex) {
  2884.         if (startIndex < 0) {
  2885.             throw new StringIndexOutOfBoundsException(startIndex);
  2886.         }
  2887.         if (endIndex > size) {
  2888.             throw new StringIndexOutOfBoundsException(endIndex);
  2889.         }
  2890.         if (startIndex > endIndex) {
  2891.             throw new StringIndexOutOfBoundsException(endIndex - startIndex);
  2892.         }
  2893.         return substring(startIndex, endIndex);
  2894.     }

  2895.     /**
  2896.      * Extracts a portion of this string builder as a string.
  2897.      *
  2898.      * @param start the start index, inclusive, must be valid
  2899.      * @return The new string
  2900.      * @throws IndexOutOfBoundsException if the index is invalid
  2901.      */
  2902.     public String substring(final int start) {
  2903.         return substring(start, size);
  2904.     }

  2905.     /**
  2906.      * Extracts a portion of this string builder as a string.
  2907.      * <p>
  2908.      * Note: This method treats an endIndex greater than the length of the builder as equal to the length of the
  2909.      * builder, and continues without error, unlike StringBuffer or String.
  2910.      * </p>
  2911.      *
  2912.      * @param startIndex the start index, inclusive, must be valid
  2913.      * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string
  2914.      * @return The new string
  2915.      * @throws IndexOutOfBoundsException if the index is invalid
  2916.      */
  2917.     public String substring(final int startIndex, int endIndex) {
  2918.         endIndex = validateRange(startIndex, endIndex);
  2919.         return new String(buffer, startIndex, endIndex - startIndex);
  2920.     }

  2921.     /**
  2922.      * Copies the builder's character array into a new character array.
  2923.      *
  2924.      * @return a new array that represents the contents of the builder
  2925.      */
  2926.     public char[] toCharArray() {
  2927.         return size == 0 ? ArrayUtils.EMPTY_CHAR_ARRAY : Arrays.copyOf(buffer, size);
  2928.     }

  2929.     /**
  2930.      * Copies part of the builder's character array into a new character array.
  2931.      *
  2932.      * @param startIndex the start index, inclusive, must be valid
  2933.      * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string
  2934.      * @return a new array that holds part of the contents of the builder
  2935.      * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is invalid (but endIndex greater than
  2936.      *         size is valid)
  2937.      */
  2938.     public char[] toCharArray(final int startIndex, int endIndex) {
  2939.         endIndex = validateRange(startIndex, endIndex);
  2940.         final int len = endIndex - startIndex;
  2941.         return len == 0 ? ArrayUtils.EMPTY_CHAR_ARRAY : Arrays.copyOfRange(buffer, startIndex, endIndex);
  2942.     }

  2943.     /**
  2944.      * Gets a String version of the string builder, creating a new instance each time the method is called.
  2945.      * <p>
  2946.      * Note that unlike StringBuffer, the string version returned is independent of the string builder.
  2947.      * </p>
  2948.      *
  2949.      * @return The builder as a String
  2950.      */
  2951.     @Override
  2952.     public String toString() {
  2953.         return new String(buffer, 0, size);
  2954.     }

  2955.     /**
  2956.      * Gets a StringBuffer version of the string builder, creating a new instance each time the method is called.
  2957.      *
  2958.      * @return The builder as a StringBuffer
  2959.      */
  2960.     public StringBuffer toStringBuffer() {
  2961.         return new StringBuffer(size).append(buffer, 0, size);
  2962.     }

  2963.     /**
  2964.      * Gets a StringBuilder version of the string builder, creating a new instance each time the method is called.
  2965.      *
  2966.      * @return The builder as a StringBuilder
  2967.      */
  2968.     public StringBuilder toStringBuilder() {
  2969.         return new StringBuilder(size).append(buffer, 0, size);
  2970.     }

  2971.     /**
  2972.      * Trims the builder by removing characters less than or equal to a space from the beginning and end.
  2973.      *
  2974.      * @return this, to enable chaining
  2975.      */
  2976.     public TextStringBuilder trim() {
  2977.         if (size == 0) {
  2978.             return this;
  2979.         }
  2980.         int len = size;
  2981.         final char[] buf = buffer;
  2982.         int pos = 0;
  2983.         while (pos < len && buf[pos] <= SPACE) {
  2984.             pos++;
  2985.         }
  2986.         while (pos < len && buf[len - 1] <= SPACE) {
  2987.             len--;
  2988.         }
  2989.         if (len < size) {
  2990.             delete(len, size);
  2991.         }
  2992.         if (pos > 0) {
  2993.             delete(0, pos);
  2994.         }
  2995.         return this;
  2996.     }

  2997.     /**
  2998.      * Validates that an index is in the range {@code 0 <= index <= size}.
  2999.      *
  3000.      * @param index the index to test.
  3001.      * @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index <= size}.
  3002.      */
  3003.     protected void validateIndex(final int index) {
  3004.         if (index < 0 || index >= size) {
  3005.             throw new StringIndexOutOfBoundsException(index);
  3006.         }
  3007.     }

  3008.     /**
  3009.      * Validates parameters defining a range of the builder.
  3010.      *
  3011.      * @param startIndex the start index, inclusive, must be valid
  3012.      * @param endIndex the end index, exclusive, must be valid except that if too large it is treated as end of string
  3013.      * @return A valid end index.
  3014.      * @throws StringIndexOutOfBoundsException if the index is invalid
  3015.      */
  3016.     protected int validateRange(final int startIndex, int endIndex) {
  3017.         if (startIndex < 0) {
  3018.             throw new StringIndexOutOfBoundsException(startIndex);
  3019.         }
  3020.         if (endIndex > size) {
  3021.             endIndex = size;
  3022.         }
  3023.         if (startIndex > endIndex) {
  3024.             throw new StringIndexOutOfBoundsException("end < start");
  3025.         }
  3026.         return endIndex;
  3027.     }

  3028. }