StrBuilder.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.CharUtils;
  29. import org.apache.commons.lang3.StringUtils;

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

  71.     /**
  72.      * Inner class to allow StrBuilder to operate as a reader.
  73.      */
  74.     final class StrBuilderReader extends Reader {

  75.         /** The current stream position. */
  76.         private int pos;

  77.         /** The last mark position. */
  78.         private int mark;

  79.         /**
  80.          * Default constructor.
  81.          */
  82.         StrBuilderReader() {
  83.         }

  84.         /** {@inheritDoc} */
  85.         @Override
  86.         public void close() {
  87.             // do nothing
  88.         }

  89.         /** {@inheritDoc} */
  90.         @Override
  91.         public void mark(final int readAheadLimit) {
  92.             mark = pos;
  93.         }

  94.         /** {@inheritDoc} */
  95.         @Override
  96.         public boolean markSupported() {
  97.             return true;
  98.         }

  99.         /** {@inheritDoc} */
  100.         @Override
  101.         public int read() {
  102.             if (!ready()) {
  103.                 return -1;
  104.             }
  105.             return charAt(pos++);
  106.         }

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

  126.         /** {@inheritDoc} */
  127.         @Override
  128.         public boolean ready() {
  129.             return pos < size();
  130.         }

  131.         /** {@inheritDoc} */
  132.         @Override
  133.         public void reset() {
  134.             pos = mark;
  135.         }

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

  149.     /**
  150.      * Inner class to allow StrBuilder to operate as a tokenizer.
  151.      */
  152.     final class StrBuilderTokenizer extends StrTokenizer {

  153.         /**
  154.          * Default constructor.
  155.          */
  156.         StrBuilderTokenizer() {
  157.         }

  158.         /** {@inheritDoc} */
  159.         @Override
  160.         public String getContent() {
  161.             final String str = super.getContent();
  162.             if (str == null) {
  163.                 return StrBuilder.this.toString();
  164.             }
  165.             return str;
  166.         }

  167.         /** {@inheritDoc} */
  168.         @Override
  169.         protected List<String> tokenize(final char[] chars, final int offset, final int count) {
  170.             if (chars == null) {
  171.                 return super.tokenize(StrBuilder.this.buffer, 0, StrBuilder.this.size());
  172.             }
  173.             return super.tokenize(chars, offset, count);
  174.         }
  175.     }

  176.     /**
  177.      * Inner class to allow StrBuilder to operate as a writer.
  178.      */
  179.     final class StrBuilderWriter extends Writer {

  180.         /**
  181.          * Default constructor.
  182.          */
  183.         StrBuilderWriter() {
  184.         }

  185.         /** {@inheritDoc} */
  186.         @Override
  187.         public void close() {
  188.             // do nothing
  189.         }

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

  195.         /** {@inheritDoc} */
  196.         @Override
  197.         public void write(final char[] cbuf) {
  198.             StrBuilder.this.append(cbuf);
  199.         }

  200.         /** {@inheritDoc} */
  201.         @Override
  202.         public void write(final char[] cbuf, final int off, final int len) {
  203.             StrBuilder.this.append(cbuf, off, len);
  204.         }

  205.         /** {@inheritDoc} */
  206.         @Override
  207.         public void write(final int c) {
  208.             StrBuilder.this.append((char) c);
  209.         }

  210.         /** {@inheritDoc} */
  211.         @Override
  212.         public void write(final String str) {
  213.             StrBuilder.this.append(str);
  214.         }

  215.         /** {@inheritDoc} */
  216.         @Override
  217.         public void write(final String str, final int off, final int len) {
  218.             StrBuilder.this.append(str, off, len);
  219.         }
  220.     }

  221.     /**
  222.      * The extra capacity for new builders.
  223.      */
  224.     static final int CAPACITY = 32;

  225.     /**
  226.      * Required for serialization support.
  227.      *
  228.      * @see java.io.Serializable
  229.      */
  230.     private static final long serialVersionUID = 7628716375283629643L;

  231.     /** Internal data storage. */
  232.     char[] buffer; // package-protected for test code use only

  233.     /** Current size of the buffer. */
  234.     private int size;

  235.     /**
  236.      * The new line, {@code null} means use the system default from {@link System#lineSeparator()}.
  237.      */
  238.     private String newLine;

  239.     /** The null text. */
  240.     private String nullText;

  241.     /**
  242.      * Constructs an empty builder initial capacity 32 characters.
  243.      */
  244.     public StrBuilder() {
  245.         this(CAPACITY);
  246.     }

  247.     /**
  248.      * Constructs an empty builder the specified initial capacity.
  249.      *
  250.      * @param initialCapacity the initial capacity, zero or less will be converted to 32
  251.      */
  252.     public StrBuilder(int initialCapacity) {
  253.         if (initialCapacity <= 0) {
  254.             initialCapacity = CAPACITY;
  255.         }
  256.         buffer = new char[initialCapacity];
  257.     }

  258.     /**
  259.      * Constructs a builder from the string, allocating 32 extra characters for growth.
  260.      *
  261.      * @param str the string to copy, null treated as blank string
  262.      */
  263.     public StrBuilder(final String str) {
  264.         if (str == null) {
  265.             buffer = new char[CAPACITY];
  266.         } else {
  267.             buffer = new char[str.length() + CAPACITY];
  268.             append(str);
  269.         }
  270.     }

  271.     /**
  272.      * Appends a boolean value to the string builder.
  273.      *
  274.      * @param value the value to append
  275.      * @return {@code this} instance.
  276.      */
  277.     public StrBuilder append(final boolean value) {
  278.         if (value) {
  279.             ensureCapacity(size + 4);
  280.             buffer[size++] = 't';
  281.             buffer[size++] = 'r';
  282.             buffer[size++] = 'u';
  283.         } else {
  284.             ensureCapacity(size + 5);
  285.             buffer[size++] = 'f';
  286.             buffer[size++] = 'a';
  287.             buffer[size++] = 'l';
  288.             buffer[size++] = 's';
  289.         }
  290.         buffer[size++] = 'e';
  291.         return this;
  292.     }

  293.     /**
  294.      * Appends a char value to the string builder.
  295.      *
  296.      * @param ch the value to append
  297.      * @return {@code this} instance.
  298.      */
  299.     @Override
  300.     public StrBuilder append(final char ch) {
  301.         final int len = length();
  302.         ensureCapacity(len + 1);
  303.         buffer[size++] = ch;
  304.         return this;
  305.     }

  306.     /**
  307.      * Appends a char array to the string builder. Appending null will call {@link #appendNull()}.
  308.      *
  309.      * @param chars the char array to append
  310.      * @return {@code this} instance.
  311.      */
  312.     public StrBuilder append(final char[] chars) {
  313.         if (chars == null) {
  314.             return appendNull();
  315.         }
  316.         final int strLen = chars.length;
  317.         if (strLen > 0) {
  318.             final int len = length();
  319.             ensureCapacity(len + strLen);
  320.             System.arraycopy(chars, 0, buffer, len, strLen);
  321.             size += strLen;
  322.         }
  323.         return this;
  324.     }

  325.     /**
  326.      * Appends a char array to the string builder. Appending null will call {@link #appendNull()}.
  327.      *
  328.      * @param chars      the char array to append
  329.      * @param startIndex the start index, inclusive, must be valid
  330.      * @param length     the length to append, must be valid
  331.      * @return {@code this} instance.
  332.      */
  333.     public StrBuilder append(final char[] chars, final int startIndex, final int length) {
  334.         if (chars == null) {
  335.             return appendNull();
  336.         }
  337.         if (startIndex < 0 || startIndex > chars.length) {
  338.             throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length);
  339.         }
  340.         if (length < 0 || startIndex + length > chars.length) {
  341.             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
  342.         }
  343.         if (length > 0) {
  344.             final int len = length();
  345.             ensureCapacity(len + length);
  346.             System.arraycopy(chars, startIndex, buffer, len, length);
  347.             size += length;
  348.         }
  349.         return this;
  350.     }

  351.     /**
  352.      * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}.
  353.      *
  354.      * @param buf the char buffer to append
  355.      * @return {@code this} instance.
  356.      */
  357.     public StrBuilder append(final CharBuffer buf) {
  358.         if (buf == null) {
  359.             return appendNull();
  360.         }
  361.         if (buf.hasArray()) {
  362.             final int length = buf.remaining();
  363.             final int len = length();
  364.             ensureCapacity(len + length);
  365.             System.arraycopy(buf.array(), buf.arrayOffset() + buf.position(), buffer, len, length);
  366.             size += length;
  367.         } else {
  368.             append(buf.toString());
  369.         }
  370.         return this;
  371.     }

  372.     /**
  373.      * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}.
  374.      *
  375.      * @param buf        the char buffer to append
  376.      * @param startIndex the start index, inclusive, must be valid
  377.      * @param length     the length to append, must be valid
  378.      * @return {@code this} instance.
  379.      */
  380.     public StrBuilder append(final CharBuffer buf, final int startIndex, final int length) {
  381.         if (buf == null) {
  382.             return appendNull();
  383.         }
  384.         if (buf.hasArray()) {
  385.             final int totalLength = buf.remaining();
  386.             if (startIndex < 0 || startIndex > totalLength) {
  387.                 throw new StringIndexOutOfBoundsException("startIndex must be valid");
  388.             }
  389.             if (length < 0 || startIndex + length > totalLength) {
  390.                 throw new StringIndexOutOfBoundsException("length must be valid");
  391.             }
  392.             final int len = length();
  393.             ensureCapacity(len + length);
  394.             System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length);
  395.             size += length;
  396.         } else {
  397.             append(buf.toString(), startIndex, length);
  398.         }
  399.         return this;
  400.     }

  401.     /**
  402.      * Appends a CharSequence to this string builder. Appending null will call {@link #appendNull()}.
  403.      *
  404.      * @param seq the CharSequence to append
  405.      * @return {@code this} instance.
  406.      */
  407.     @Override
  408.     public StrBuilder append(final CharSequence seq) {
  409.         if (seq == null) {
  410.             return appendNull();
  411.         }
  412.         if (seq instanceof StrBuilder) {
  413.             return append((StrBuilder) seq);
  414.         }
  415.         if (seq instanceof StringBuilder) {
  416.             return append((StringBuilder) seq);
  417.         }
  418.         if (seq instanceof StringBuffer) {
  419.             return append((StringBuffer) seq);
  420.         }
  421.         if (seq instanceof CharBuffer) {
  422.             return append((CharBuffer) seq);
  423.         }
  424.         return append(seq.toString());
  425.     }

  426.     /**
  427.      * Appends part of a CharSequence to this string builder. Appending null will call {@link #appendNull()}.
  428.      *
  429.      * @param seq        the CharSequence to append
  430.      * @param startIndex the start index, inclusive, must be valid
  431.      * @param length     the length to append, must be valid
  432.      * @return {@code this} instance.
  433.      */
  434.     @Override
  435.     public StrBuilder append(final CharSequence seq, final int startIndex, final int length) {
  436.         if (seq == null) {
  437.             return appendNull();
  438.         }
  439.         return append(seq.toString(), startIndex, length);
  440.     }

  441.     /**
  442.      * Appends a double value to the string builder using {@code String.valueOf}.
  443.      *
  444.      * @param value the value to append
  445.      * @return {@code this} instance.
  446.      */
  447.     public StrBuilder append(final double value) {
  448.         return append(String.valueOf(value));
  449.     }

  450.     /**
  451.      * Appends a float value to the string builder using {@code String.valueOf}.
  452.      *
  453.      * @param value the value to append
  454.      * @return {@code this} instance.
  455.      */
  456.     public StrBuilder append(final float value) {
  457.         return append(String.valueOf(value));
  458.     }

  459.     /**
  460.      * Appends an int value to the string builder using {@code String.valueOf}.
  461.      *
  462.      * @param value the value to append
  463.      * @return {@code this} instance.
  464.      */
  465.     public StrBuilder append(final int value) {
  466.         return append(String.valueOf(value));
  467.     }

  468.     /**
  469.      * Appends a long value to the string builder using {@code String.valueOf}.
  470.      *
  471.      * @param value the value to append
  472.      * @return {@code this} instance.
  473.      */
  474.     public StrBuilder append(final long value) {
  475.         return append(String.valueOf(value));
  476.     }

  477.     /**
  478.      * Appends an object to this string builder. Appending null will call {@link #appendNull()}.
  479.      *
  480.      * @param obj the object to append
  481.      * @return {@code this} instance.
  482.      */
  483.     public StrBuilder append(final Object obj) {
  484.         if (obj == null) {
  485.             return appendNull();
  486.         }
  487.         if (obj instanceof CharSequence) {
  488.             return append((CharSequence) obj);
  489.         }
  490.         return append(obj.toString());
  491.     }

  492.     /**
  493.      * Appends another string builder to this string builder. Appending null will call {@link #appendNull()}.
  494.      *
  495.      * @param str the string builder to append
  496.      * @return {@code this} instance.
  497.      */
  498.     public StrBuilder append(final StrBuilder str) {
  499.         if (str == null) {
  500.             return appendNull();
  501.         }
  502.         final int strLen = str.length();
  503.         if (strLen > 0) {
  504.             final int len = length();
  505.             ensureCapacity(len + strLen);
  506.             System.arraycopy(str.buffer, 0, buffer, len, strLen);
  507.             size += strLen;
  508.         }
  509.         return this;
  510.     }

  511.     /**
  512.      * Appends part of a string builder to this string builder. Appending null will call {@link #appendNull()}.
  513.      *
  514.      * @param str        the string to append
  515.      * @param startIndex the start index, inclusive, must be valid
  516.      * @param length     the length to append, must be valid
  517.      * @return {@code this} instance.
  518.      */
  519.     public StrBuilder append(final StrBuilder str, final int startIndex, final int length) {
  520.         if (str == null) {
  521.             return appendNull();
  522.         }
  523.         if (startIndex < 0 || startIndex > str.length()) {
  524.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  525.         }
  526.         if (length < 0 || startIndex + length > str.length()) {
  527.             throw new StringIndexOutOfBoundsException("length must be valid");
  528.         }
  529.         if (length > 0) {
  530.             final int len = length();
  531.             ensureCapacity(len + length);
  532.             str.getChars(startIndex, startIndex + length, buffer, len);
  533.             size += length;
  534.         }
  535.         return this;
  536.     }

  537.     /**
  538.      * Appends a string to this string builder. Appending null will call {@link #appendNull()}.
  539.      *
  540.      * @param str the string to append
  541.      * @return {@code this} instance.
  542.      */
  543.     public StrBuilder append(final String str) {
  544.         if (str == null) {
  545.             return appendNull();
  546.         }
  547.         final int strLen = str.length();
  548.         if (strLen > 0) {
  549.             final int len = length();
  550.             ensureCapacity(len + strLen);
  551.             str.getChars(0, strLen, buffer, len);
  552.             size += strLen;
  553.         }
  554.         return this;
  555.     }

  556.     /**
  557.      * Appends part of a string to this string builder. Appending null will call {@link #appendNull()}.
  558.      *
  559.      * @param str        the string to append
  560.      * @param startIndex the start index, inclusive, must be valid
  561.      * @param length     the length to append, must be valid
  562.      * @return {@code this} instance.
  563.      */
  564.     public StrBuilder append(final String str, final int startIndex, final int length) {
  565.         if (str == null) {
  566.             return appendNull();
  567.         }
  568.         if (startIndex < 0 || startIndex > str.length()) {
  569.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  570.         }
  571.         if (length < 0 || startIndex + length > str.length()) {
  572.             throw new StringIndexOutOfBoundsException("length must be valid");
  573.         }
  574.         if (length > 0) {
  575.             final int len = length();
  576.             ensureCapacity(len + length);
  577.             str.getChars(startIndex, startIndex + length, buffer, len);
  578.             size += length;
  579.         }
  580.         return this;
  581.     }

  582.     /**
  583.      * Calls {@link String#format(String, Object...)} and appends the result.
  584.      *
  585.      * @param format the format string
  586.      * @param objs   the objects to use in the format string
  587.      * @return {@code this} to enable chaining
  588.      * @see String#format(String, Object...)
  589.      */
  590.     public StrBuilder append(final String format, final Object... objs) {
  591.         return append(String.format(format, objs));
  592.     }

  593.     /**
  594.      * Appends a string buffer to this string builder. Appending null will call {@link #appendNull()}.
  595.      *
  596.      * @param str the string buffer to append
  597.      * @return {@code this} instance.
  598.      */
  599.     public StrBuilder append(final StringBuffer str) {
  600.         if (str == null) {
  601.             return appendNull();
  602.         }
  603.         final int strLen = str.length();
  604.         if (strLen > 0) {
  605.             final int len = length();
  606.             ensureCapacity(len + strLen);
  607.             str.getChars(0, strLen, buffer, len);
  608.             size += strLen;
  609.         }
  610.         return this;
  611.     }

  612.     /**
  613.      * Appends part of a string buffer to this string builder. Appending null will call {@link #appendNull()}.
  614.      *
  615.      * @param str        the string to append
  616.      * @param startIndex the start index, inclusive, must be valid
  617.      * @param length     the length to append, must be valid
  618.      * @return {@code this} instance.
  619.      */
  620.     public StrBuilder append(final StringBuffer str, final int startIndex, final int length) {
  621.         if (str == null) {
  622.             return appendNull();
  623.         }
  624.         if (startIndex < 0 || startIndex > str.length()) {
  625.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  626.         }
  627.         if (length < 0 || startIndex + length > str.length()) {
  628.             throw new StringIndexOutOfBoundsException("length must be valid");
  629.         }
  630.         if (length > 0) {
  631.             final int len = length();
  632.             ensureCapacity(len + length);
  633.             str.getChars(startIndex, startIndex + length, buffer, len);
  634.             size += length;
  635.         }
  636.         return this;
  637.     }

  638.     /**
  639.      * Appends a StringBuilder to this string builder. Appending null will call {@link #appendNull()}.
  640.      *
  641.      * @param str the StringBuilder to append
  642.      * @return {@code this} instance.
  643.      */
  644.     public StrBuilder append(final StringBuilder str) {
  645.         if (str == null) {
  646.             return appendNull();
  647.         }
  648.         final int strLen = str.length();
  649.         if (strLen > 0) {
  650.             final int len = length();
  651.             ensureCapacity(len + strLen);
  652.             str.getChars(0, strLen, buffer, len);
  653.             size += strLen;
  654.         }
  655.         return this;
  656.     }

  657.     /**
  658.      * Appends part of a StringBuilder to this string builder. Appending null will call {@link #appendNull()}.
  659.      *
  660.      * @param str        the StringBuilder to append
  661.      * @param startIndex the start index, inclusive, must be valid
  662.      * @param length     the length to append, must be valid
  663.      * @return {@code this} instance.
  664.      */
  665.     public StrBuilder append(final StringBuilder str, final int startIndex, final int length) {
  666.         if (str == null) {
  667.             return appendNull();
  668.         }
  669.         if (startIndex < 0 || startIndex > str.length()) {
  670.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  671.         }
  672.         if (length < 0 || startIndex + length > str.length()) {
  673.             throw new StringIndexOutOfBoundsException("length must be valid");
  674.         }
  675.         if (length > 0) {
  676.             final int len = length();
  677.             ensureCapacity(len + length);
  678.             str.getChars(startIndex, startIndex + length, buffer, len);
  679.             size += length;
  680.         }
  681.         return this;
  682.     }

  683.     /**
  684.      * Appends each item in an iterable to the builder without any separators. Appending a null iterable will have no effect. Each object is appended using
  685.      * {@link #append(Object)}.
  686.      *
  687.      * @param iterable the iterable to append
  688.      * @return {@code this} instance.
  689.      */
  690.     public StrBuilder appendAll(final Iterable<?> iterable) {
  691.         if (iterable != null) {
  692.             iterable.forEach(this::append);
  693.         }
  694.         return this;
  695.     }

  696.     /**
  697.      * Appends each item in an iterator to the builder without any separators. Appending a null iterator will have no effect. Each object is appended using
  698.      * {@link #append(Object)}.
  699.      *
  700.      * @param it the iterator to append
  701.      * @return {@code this} instance.
  702.      */
  703.     public StrBuilder appendAll(final Iterator<?> it) {
  704.         if (it != null) {
  705.             while (it.hasNext()) {
  706.                 append(it.next());
  707.             }
  708.         }
  709.         return this;
  710.     }

  711.     /**
  712.      * Appends each item in an array to the builder without any separators. Appending a null array will have no effect. Each object is appended using
  713.      * {@link #append(Object)}.
  714.      *
  715.      * @param <T>   the element type
  716.      * @param array the array to append
  717.      * @return {@code this} instance.
  718.      */
  719.     public <T> StrBuilder appendAll(@SuppressWarnings("unchecked") final T... array) {
  720.         /*
  721.          * @SuppressWarnings used to hide warning about vararg usage. We cannot use @SafeVarargs, since this method is not final. Using @SuppressWarnings is
  722.          * fine, because it isn't inherited by subclasses, so each subclass must vouch for itself whether its use of 'array' is safe.
  723.          */
  724.         if (array != null && array.length > 0) {
  725.             for (final Object element : array) {
  726.                 append(element);
  727.             }
  728.         }
  729.         return this;
  730.     }

  731.     /**
  732.      * Appends an object to the builder padding on the left to a fixed width. The {@code String.valueOf} of the {@code int} value is used. If the formatted
  733.      * value is larger than the length, the left hand side is lost.
  734.      *
  735.      * @param value   the value to append
  736.      * @param width   the fixed field width, zero or negative has no effect
  737.      * @param padChar the pad character to use
  738.      * @return {@code this} instance.
  739.      */
  740.     public StrBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) {
  741.         return appendFixedWidthPadLeft(String.valueOf(value), width, padChar);
  742.     }

  743.     /**
  744.      * Appends an object to the builder padding on the left to a fixed width. The {@code toString} of the object is used. If the object is larger than the
  745.      * length, the left hand side is lost. If the object is null, the null text value is used.
  746.      *
  747.      * @param obj     the object to append, null uses null text
  748.      * @param width   the fixed field width, zero or negative has no effect
  749.      * @param padChar the pad character to use
  750.      * @return {@code this} instance.
  751.      */
  752.     public StrBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) {
  753.         if (width > 0) {
  754.             ensureCapacity(size + width);
  755.             String str = Objects.toString(obj, getNullText());
  756.             if (str == null) {
  757.                 str = StringUtils.EMPTY;
  758.             }
  759.             final int strLen = str.length();
  760.             if (strLen >= width) {
  761.                 str.getChars(strLen - width, strLen, buffer, size);
  762.             } else {
  763.                 final int padLen = width - strLen;
  764.                 final int toIndex = size + padLen;
  765.                 Arrays.fill(buffer, size, toIndex, padChar);
  766.                 str.getChars(0, strLen, buffer, toIndex);
  767.             }
  768.             size += width;
  769.         }
  770.         return this;
  771.     }

  772.     /**
  773.      * Appends an object to the builder padding on the right to a fixed length. The {@code String.valueOf} of the {@code int} value is used. If the object is
  774.      * larger than the length, the right hand side is lost.
  775.      *
  776.      * @param value   the value to append
  777.      * @param width   the fixed field width, zero or negative has no effect
  778.      * @param padChar the pad character to use
  779.      * @return {@code this} instance.
  780.      */
  781.     public StrBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) {
  782.         return appendFixedWidthPadRight(String.valueOf(value), width, padChar);
  783.     }

  784.     /**
  785.      * Appends an object to the builder padding on the right to a fixed length. The {@code toString} of the object is used. If the object is larger than the
  786.      * length, the right hand side is lost. If the object is null, null text value is used.
  787.      *
  788.      * @param obj     the object to append, null uses null text
  789.      * @param width   the fixed field width, zero or negative has no effect
  790.      * @param padChar the pad character to use
  791.      * @return {@code this} instance.
  792.      */
  793.     public StrBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) {
  794.         if (width > 0) {
  795.             ensureCapacity(size + width);
  796.             String str = Objects.toString(obj, getNullText());
  797.             if (str == null) {
  798.                 str = StringUtils.EMPTY;
  799.             }
  800.             final int strLen = str.length();
  801.             if (strLen >= width) {
  802.                 str.getChars(0, width, buffer, size);
  803.             } else {
  804.                 str.getChars(0, strLen, buffer, size);
  805.                 final int fromIndex = size + strLen;
  806.                 Arrays.fill(buffer, fromIndex, fromIndex + width - strLen, padChar);
  807.             }
  808.             size += width;
  809.         }
  810.         return this;
  811.     }

  812.     /**
  813.      * Appends a boolean value followed by a {@link #appendNewLine() new line} to the string builder.
  814.      *
  815.      * @param value the value to append
  816.      * @return {@code this} instance.
  817.      * @see #appendNewLine()
  818.      */
  819.     public StrBuilder appendln(final boolean value) {
  820.         return append(value).appendNewLine();
  821.     }

  822.     /**
  823.      * Appends a char value followed by a {@link #appendNewLine() new line} to the string builder.
  824.      *
  825.      * @param ch the value to append
  826.      * @return {@code this} instance.
  827.      * @see #appendNewLine()
  828.      */
  829.     public StrBuilder appendln(final char ch) {
  830.         return append(ch).appendNewLine();
  831.     }

  832.     /**
  833.      * Appends a char array followed by a {@link #appendNewLine() new line} to the string builder. Appending null will call {@link #appendNull()}.
  834.      *
  835.      * @param chars the char array to append
  836.      * @return {@code this} instance.
  837.      * @see #appendNewLine()
  838.      */
  839.     public StrBuilder appendln(final char[] chars) {
  840.         return append(chars).appendNewLine();
  841.     }

  842.     /**
  843.      * Appends a char array followed by a {@link #appendNewLine() new line} to the string builder. Appending null will call {@link #appendNull()}.
  844.      *
  845.      * @param chars      the char array to append
  846.      * @param startIndex the start index, inclusive, must be valid
  847.      * @param length     the length to append, must be valid
  848.      * @return {@code this} instance.
  849.      * @see #appendNewLine()
  850.      */
  851.     public StrBuilder appendln(final char[] chars, final int startIndex, final int length) {
  852.         return append(chars, startIndex, length).appendNewLine();
  853.     }

  854.     /**
  855.      * Appends a double value followed by a {@link #appendNewLine() new line} to the string builder using {@code String.valueOf}.
  856.      *
  857.      * @param value the value to append
  858.      * @return {@code this} instance.
  859.      * @see #appendNewLine()
  860.      */
  861.     public StrBuilder appendln(final double value) {
  862.         return append(value).appendNewLine();
  863.     }

  864.     /**
  865.      * Appends a float value followed by a {@link #appendNewLine() new line} to the string builder using {@code String.valueOf}.
  866.      *
  867.      * @param value the value to append
  868.      * @return {@code this} instance.
  869.      * @see #appendNewLine()
  870.      */
  871.     public StrBuilder appendln(final float value) {
  872.         return append(value).appendNewLine();
  873.     }

  874.     /**
  875.      * Appends an int value followed by a {@link #appendNewLine() new line} to the string builder using {@code String.valueOf}.
  876.      *
  877.      * @param value the value to append
  878.      * @return {@code this} instance.
  879.      * @see #appendNewLine()
  880.      */
  881.     public StrBuilder appendln(final int value) {
  882.         return append(value).appendNewLine();
  883.     }

  884.     /**
  885.      * Appends a long value followed by a {@link #appendNewLine() new line} to the string builder using {@code String.valueOf}.
  886.      *
  887.      * @param value the value to append
  888.      * @return {@code this} instance.
  889.      * @see #appendNewLine()
  890.      */
  891.     public StrBuilder appendln(final long value) {
  892.         return append(value).appendNewLine();
  893.     }

  894.     /**
  895.      * Appends an object followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  896.      *
  897.      * @param obj the object to append
  898.      * @return {@code this} instance.
  899.      * @see #appendNewLine()
  900.      */
  901.     public StrBuilder appendln(final Object obj) {
  902.         return append(obj).appendNewLine();
  903.     }

  904.     /**
  905.      * Appends another string builder followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  906.      *
  907.      * @param str the string builder to append
  908.      * @return {@code this} instance.
  909.      * @see #appendNewLine()
  910.      */
  911.     public StrBuilder appendln(final StrBuilder str) {
  912.         return append(str).appendNewLine();
  913.     }

  914.     /**
  915.      * Appends part of a string builder followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  916.      *
  917.      * @param str        the string to append
  918.      * @param startIndex the start index, inclusive, must be valid
  919.      * @param length     the length to append, must be valid
  920.      * @return {@code this} instance.
  921.      * @see #appendNewLine()
  922.      */
  923.     public StrBuilder appendln(final StrBuilder str, final int startIndex, final int length) {
  924.         return append(str, startIndex, length).appendNewLine();
  925.     }

  926.     /**
  927.      * Appends a string followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  928.      *
  929.      * @param str the string to append
  930.      * @return {@code this} instance.
  931.      * @see #appendNewLine()
  932.      */
  933.     public StrBuilder appendln(final String str) {
  934.         return append(str).appendNewLine();
  935.     }

  936.     /**
  937.      * Appends part of a string followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  938.      *
  939.      * @param str        the string to append
  940.      * @param startIndex the start index, inclusive, must be valid
  941.      * @param length     the length to append, must be valid
  942.      * @return {@code this} instance.
  943.      * @see #appendNewLine()
  944.      */
  945.     public StrBuilder appendln(final String str, final int startIndex, final int length) {
  946.         return append(str, startIndex, length).appendNewLine();
  947.     }

  948.     /**
  949.      * Calls {@link String#format(String, Object...)} and appends the result.
  950.      *
  951.      * @param format the format string
  952.      * @param objs   the objects to use in the format string
  953.      * @return {@code this} to enable chaining
  954.      * @see String#format(String, Object...)
  955.      * @see #appendNewLine()
  956.      */
  957.     public StrBuilder appendln(final String format, final Object... objs) {
  958.         return append(format, objs).appendNewLine();
  959.     }

  960.     /**
  961.      * Appends a string buffer followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  962.      *
  963.      * @param str the string buffer to append
  964.      * @return {@code this} instance.
  965.      * @see #appendNewLine()
  966.      */
  967.     public StrBuilder appendln(final StringBuffer str) {
  968.         return append(str).appendNewLine();
  969.     }

  970.     /**
  971.      * Appends part of a string buffer followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  972.      *
  973.      * @param str        the string to append
  974.      * @param startIndex the start index, inclusive, must be valid
  975.      * @param length     the length to append, must be valid
  976.      * @return {@code this} instance.
  977.      * @see #appendNewLine()
  978.      */
  979.     public StrBuilder appendln(final StringBuffer str, final int startIndex, final int length) {
  980.         return append(str, startIndex, length).appendNewLine();
  981.     }

  982.     /**
  983.      * Appends a string builder followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  984.      *
  985.      * @param str the string builder to append
  986.      * @return {@code this} instance.
  987.      * @see #appendNewLine()
  988.      */
  989.     public StrBuilder appendln(final StringBuilder str) {
  990.         return append(str).appendNewLine();
  991.     }

  992.     /**
  993.      * Appends part of a string builder followed by a {@link #appendNewLine() new line} to this string builder. Appending null will call {@link #appendNull()}.
  994.      *
  995.      * @param str        the string builder to append
  996.      * @param startIndex the start index, inclusive, must be valid
  997.      * @param length     the length to append, must be valid
  998.      * @return {@code this} instance.
  999.      * @see #appendNewLine()
  1000.      */
  1001.     public StrBuilder appendln(final StringBuilder str, final int startIndex, final int length) {
  1002.         return append(str, startIndex, length).appendNewLine();
  1003.     }

  1004.     /**
  1005.      * Appends this builder's new line string to this builder.
  1006.      * <p>
  1007.      * By default, the new line is the system default from {@link System#lineSeparator()}.
  1008.      * </p>
  1009.      * <p>
  1010.      * 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
  1011.      * endings even when on Windows.
  1012.      * </p>
  1013.      *
  1014.      * @return {@code this} instance.
  1015.      * @see #getNewLineText()
  1016.      * @see #setNewLineText(String)
  1017.      */
  1018.     public StrBuilder appendNewLine() {
  1019.         if (newLine == null) {
  1020.             append(System.lineSeparator());
  1021.             return this;
  1022.         }
  1023.         return append(newLine);
  1024.     }

  1025.     /**
  1026.      * Appends this builder's null text to this builder.
  1027.      *
  1028.      * @return {@code this} instance.
  1029.      */
  1030.     public StrBuilder appendNull() {
  1031.         if (nullText == null) {
  1032.             return this;
  1033.         }
  1034.         return append(nullText);
  1035.     }

  1036.     /**
  1037.      * Appends the pad character to the builder the specified number of times.
  1038.      *
  1039.      * @param length  the length to append, negative means no append
  1040.      * @param padChar the character to append
  1041.      * @return {@code this} instance.
  1042.      */
  1043.     public StrBuilder appendPadding(final int length, final char padChar) {
  1044.         if (length >= 0) {
  1045.             ensureCapacity(size + length);
  1046.             for (int i = 0; i < length; i++) {
  1047.                 buffer[size++] = padChar;
  1048.             }
  1049.         }
  1050.         return this;
  1051.     }

  1052.     /**
  1053.      * Appends a separator if the builder is currently non-empty. The separator is appended using {@link #append(char)}.
  1054.      * <p>
  1055.      * This method is useful for adding a separator each time around the loop except the first.
  1056.      * </p>
  1057.      *
  1058.      * <pre>
  1059.      * for (Iterator it = list.iterator(); it.hasNext();) {
  1060.      *     appendSeparator(',');
  1061.      *     append(it.next());
  1062.      * }
  1063.      * </pre>
  1064.      * <p>
  1065.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1066.      * </p>
  1067.      *
  1068.      * @param separator the separator to use
  1069.      * @return {@code this} instance.
  1070.      */
  1071.     public StrBuilder appendSeparator(final char separator) {
  1072.         if (isNotEmpty()) {
  1073.             append(separator);
  1074.         }
  1075.         return this;
  1076.     }

  1077.     /**
  1078.      * Appends one of both separators to the builder If the builder is currently empty it will append the defaultIfEmpty-separator Otherwise it will append the
  1079.      * standard-separator
  1080.      *
  1081.      * The separator is appended using {@link #append(char)}.
  1082.      *
  1083.      * @param standard       the separator if builder is not empty
  1084.      * @param defaultIfEmpty the separator if builder is empty
  1085.      * @return {@code this} instance.
  1086.      */
  1087.     public StrBuilder appendSeparator(final char standard, final char defaultIfEmpty) {
  1088.         if (isNotEmpty()) {
  1089.             append(standard);
  1090.         } else {
  1091.             append(defaultIfEmpty);
  1092.         }
  1093.         return this;
  1094.     }

  1095.     /**
  1096.      * Appends a separator to the builder if the loop index is greater than zero. The separator is appended using {@link #append(char)}.
  1097.      * <p>
  1098.      * This method is useful for adding a separator each time around the loop except the first.
  1099.      * </p>
  1100.      *
  1101.      * <pre>
  1102.      * for (int i = 0; i &lt; list.size(); i++) {
  1103.      *     appendSeparator(",", i);
  1104.      *     append(list.get(i));
  1105.      * }
  1106.      * </pre>
  1107.      * <p>
  1108.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1109.      * </p>
  1110.      *
  1111.      * @param separator the separator to use
  1112.      * @param loopIndex the loop index
  1113.      * @return {@code this} instance.
  1114.      */
  1115.     public StrBuilder appendSeparator(final char separator, final int loopIndex) {
  1116.         if (loopIndex > 0) {
  1117.             append(separator);
  1118.         }
  1119.         return this;
  1120.     }

  1121.     /**
  1122.      * Appends a separator if the builder is currently non-empty. Appending a null separator will have no effect. The separator is appended using
  1123.      * {@link #append(String)}.
  1124.      * <p>
  1125.      * This method is useful for adding a separator each time around the loop except the first.
  1126.      * </p>
  1127.      *
  1128.      * <pre>
  1129.      * for (Iterator it = list.iterator(); it.hasNext();) {
  1130.      *     appendSeparator(",");
  1131.      *     append(it.next());
  1132.      * }
  1133.      * </pre>
  1134.      * <p>
  1135.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1136.      * </p>
  1137.      *
  1138.      * @param separator the separator to use, null means no separator
  1139.      * @return {@code this} instance.
  1140.      */
  1141.     public StrBuilder appendSeparator(final String separator) {
  1142.         return appendSeparator(separator, null);
  1143.     }

  1144.     /**
  1145.      * Appends a separator to the builder if the loop index is greater than zero. Appending a null separator will have no effect. The separator is appended
  1146.      * using {@link #append(String)}.
  1147.      * <p>
  1148.      * This method is useful for adding a separator each time around the loop except the first.
  1149.      * </p>
  1150.      *
  1151.      * <pre>
  1152.      * for (int i = 0; i &lt; list.size(); i++) {
  1153.      *     appendSeparator(",", i);
  1154.      *     append(list.get(i));
  1155.      * }
  1156.      * </pre>
  1157.      * <p>
  1158.      * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
  1159.      * </p>
  1160.      *
  1161.      * @param separator the separator to use, null means no separator
  1162.      * @param loopIndex the loop index
  1163.      * @return {@code this} instance.
  1164.      */
  1165.     public StrBuilder appendSeparator(final String separator, final int loopIndex) {
  1166.         if (separator != null && loopIndex > 0) {
  1167.             append(separator);
  1168.         }
  1169.         return this;
  1170.     }

  1171.     /**
  1172.      * Appends one of both separators to the StrBuilder. If the builder is currently empty it will append the defaultIfEmpty-separator Otherwise it will append
  1173.      * the standard-separator
  1174.      * <p>
  1175.      * Appending a null separator will have no effect. The separator is appended using {@link #append(String)}.
  1176.      * </p>
  1177.      * <p>
  1178.      * This method is for example useful for constructing queries
  1179.      * </p>
  1180.      *
  1181.      * <pre>
  1182.      * StrBuilder whereClause = new StrBuilder();
  1183.      * if (searchCommand.getPriority() != null) {
  1184.      *   whereClause.appendSeparator(" and", " where");
  1185.      *   whereClause.append(" priority = ?")
  1186.      * }
  1187.      * if (searchCommand.getComponent() != null) {
  1188.      *   whereClause.appendSeparator(" and", " where");
  1189.      *   whereClause.append(" component = ?")
  1190.      * }
  1191.      * selectClause.append(whereClause)
  1192.      * </pre>
  1193.      *
  1194.      * @param standard       the separator if builder is not empty, null means no separator
  1195.      * @param defaultIfEmpty the separator if builder is empty, null means no separator
  1196.      * @return {@code this} instance.
  1197.      */
  1198.     public StrBuilder appendSeparator(final String standard, final String defaultIfEmpty) {
  1199.         final String str = isEmpty() ? defaultIfEmpty : standard;
  1200.         if (str != null) {
  1201.             append(str);
  1202.         }
  1203.         return this;
  1204.     }

  1205.     /**
  1206.      * Appends current contents of this {@code StrBuilder} to the provided {@link Appendable}.
  1207.      * <p>
  1208.      * This method tries to avoid doing any extra copies of contents.
  1209.      * </p>
  1210.      *
  1211.      * @param appendable the appendable to append data to
  1212.      * @throws IOException if an I/O error occurs
  1213.      * @see #readFrom(Readable)
  1214.      */
  1215.     public void appendTo(final Appendable appendable) throws IOException {
  1216.         if (appendable instanceof Writer) {
  1217.             ((Writer) appendable).write(buffer, 0, size);
  1218.         } else if (appendable instanceof StringBuilder) {
  1219.             ((StringBuilder) appendable).append(buffer, 0, size);
  1220.         } else if (appendable instanceof StringBuffer) {
  1221.             ((StringBuffer) appendable).append(buffer, 0, size);
  1222.         } else if (appendable instanceof CharBuffer) {
  1223.             ((CharBuffer) appendable).put(buffer, 0, size);
  1224.         } else {
  1225.             appendable.append(this);
  1226.         }
  1227.     }

  1228.     /**
  1229.      * Appends an iterable placing separators between each value, but not before the first or after the last. Appending a null iterable will have no effect.
  1230.      * Each object is appended using {@link #append(Object)}.
  1231.      *
  1232.      * @param iterable  the iterable to append
  1233.      * @param separator the separator to use, null means no separator
  1234.      * @return {@code this} instance.
  1235.      */
  1236.     public StrBuilder appendWithSeparators(final Iterable<?> iterable, final String separator) {
  1237.         if (iterable != null) {
  1238.             appendWithSeparators(iterable.iterator(), separator);
  1239.         }
  1240.         return this;
  1241.     }

  1242.     /**
  1243.      * Appends an iterator placing separators between each value, but not before the first or after the last. Appending a null iterator will have no effect.
  1244.      * Each object is appended using {@link #append(Object)}.
  1245.      *
  1246.      * @param iterator  the iterator to append
  1247.      * @param separator the separator to use, null means no separator
  1248.      * @return {@code this} instance.
  1249.      */
  1250.     public StrBuilder appendWithSeparators(final Iterator<?> iterator, final String separator) {
  1251.         if (iterator != null) {
  1252.             final String sep = Objects.toString(separator, StringUtils.EMPTY);
  1253.             while (iterator.hasNext()) {
  1254.                 append(iterator.next());
  1255.                 if (iterator.hasNext()) {
  1256.                     append(sep);
  1257.                 }
  1258.             }
  1259.         }
  1260.         return this;
  1261.     }

  1262.     /**
  1263.      * Appends an array placing separators between each value, but not before the first or after the last. Appending a null array will have no effect. Each
  1264.      * object is appended using {@link #append(Object)}.
  1265.      *
  1266.      * @param array     the array to append
  1267.      * @param separator the separator to use, null means no separator
  1268.      * @return {@code this} instance.
  1269.      */
  1270.     public StrBuilder appendWithSeparators(final Object[] array, final String separator) {
  1271.         if (array != null && array.length > 0) {
  1272.             final String sep = Objects.toString(separator, StringUtils.EMPTY);
  1273.             append(array[0]);
  1274.             for (int i = 1; i < array.length; i++) {
  1275.                 append(sep);
  1276.                 append(array[i]);
  1277.             }
  1278.         }
  1279.         return this;
  1280.     }

  1281.     /**
  1282.      * Gets the contents of this builder as a Reader.
  1283.      * <p>
  1284.      * This method allows the contents of the builder to be read using any standard method that expects a Reader.
  1285.      * </p>
  1286.      * <p>
  1287.      * To use, simply create a {@code StrBuilder}, populate it with data, call {@code asReader}, and then read away.
  1288.      * </p>
  1289.      * <p>
  1290.      * The internal character array is shared between the builder and the reader. This allows you to append to the builder after creating the reader, and the
  1291.      * changes will be picked up. Note however, that no synchronization occurs, so you must perform all operations with the builder and the reader in one
  1292.      * thread.
  1293.      * </p>
  1294.      * <p>
  1295.      * The returned reader supports marking, and ignores the flush method.
  1296.      * </p>
  1297.      *
  1298.      * @return a reader that reads from this builder
  1299.      */
  1300.     public Reader asReader() {
  1301.         return new StrBuilderReader();
  1302.     }

  1303.     /**
  1304.      * Creates a tokenizer that can tokenize the contents of this builder.
  1305.      * <p>
  1306.      * This method allows the contents of this builder to be tokenized. The tokenizer will be setup by default to tokenize on space, tab, newline and form feed
  1307.      * (as per StringTokenizer). These values can be changed on the tokenizer class, before retrieving the tokens.
  1308.      * </p>
  1309.      * <p>
  1310.      * The returned tokenizer is linked to this builder. You may intermix calls to the builder and tokenizer within certain limits, however there is no
  1311.      * synchronization. Once the tokenizer has been used once, it must be {@link StrTokenizer#reset() reset} to pickup the latest changes in the builder. For
  1312.      * example:
  1313.      * </p>
  1314.      *
  1315.      * <pre>
  1316.      * StrBuilder b = new StrBuilder();
  1317.      * b.append("a b ");
  1318.      * StrTokenizer t = b.asTokenizer();
  1319.      * String[] tokens1 = t.getTokenArray(); // returns a,b
  1320.      * b.append("c d ");
  1321.      * String[] tokens2 = t.getTokenArray(); // returns a,b (c and d ignored)
  1322.      * t.reset(); // reset causes builder changes to be picked up
  1323.      * String[] tokens3 = t.getTokenArray(); // returns a,b,c,d
  1324.      * </pre>
  1325.      * <p>
  1326.      * In addition to simply intermixing appends and tokenization, you can also call the set methods on the tokenizer to alter how it tokenizes. Just remember
  1327.      * to call reset when you want to pickup builder changes.
  1328.      * </p>
  1329.      * <p>
  1330.      * Calling {@link StrTokenizer#reset(String)} or {@link StrTokenizer#reset(char[])} with a non-null value will break the link with the builder.
  1331.      * </p>
  1332.      *
  1333.      * @return a tokenizer that is linked to this builder
  1334.      */
  1335.     public StrTokenizer asTokenizer() {
  1336.         return new StrBuilderTokenizer();
  1337.     }

  1338.     /**
  1339.      * Gets this builder as a Writer that can be written to.
  1340.      * <p>
  1341.      * This method allows you to populate the contents of the builder using any standard method that takes a Writer.
  1342.      * </p>
  1343.      * <p>
  1344.      * To use, simply create a {@code StrBuilder}, call {@code asWriter}, and populate away. The data is available at any time using the methods of the
  1345.      * {@code StrBuilder}.
  1346.      * </p>
  1347.      * <p>
  1348.      * The internal character array is shared between the builder and the writer. This allows you to intermix calls that append to the builder and write using
  1349.      * the writer and the changes will be occur correctly. Note however, that no synchronization occurs, so you must perform all operations with the builder and
  1350.      * the writer in one thread.
  1351.      * </p>
  1352.      * <p>
  1353.      * The returned writer ignores the close and flush methods.
  1354.      * </p>
  1355.      *
  1356.      * @return a writer that populates this builder
  1357.      */
  1358.     public Writer asWriter() {
  1359.         return new StrBuilderWriter();
  1360.     }

  1361.     /**
  1362.      * Converts this instance to a String.
  1363.      *
  1364.      * @return This instance as a String
  1365.      * @see #toString()
  1366.      * @deprecated Use {@link #get()}.
  1367.      */
  1368.     @Deprecated
  1369.     @Override
  1370.     public String build() {
  1371.         return toString();
  1372.     }

  1373.     /**
  1374.      * Gets the current size of the internal character array buffer.
  1375.      *
  1376.      * @return The capacity
  1377.      */
  1378.     public int capacity() {
  1379.         return buffer.length;
  1380.     }

  1381.     /**
  1382.      * Gets the character at the specified index.
  1383.      *
  1384.      * @see #setCharAt(int, char)
  1385.      * @see #deleteCharAt(int)
  1386.      * @param index the index to retrieve, must be valid
  1387.      * @return The character at the index
  1388.      * @throws IndexOutOfBoundsException if the index is invalid
  1389.      */
  1390.     @Override
  1391.     public char charAt(final int index) {
  1392.         if (index < 0 || index >= length()) {
  1393.             throw new StringIndexOutOfBoundsException(index);
  1394.         }
  1395.         return buffer[index];
  1396.     }

  1397.     /**
  1398.      * Clears the string builder (convenience Collections API style method).
  1399.      * <p>
  1400.      * This method does not reduce the size of the internal character buffer. To do that, call {@code clear()} followed by {@link #minimizeCapacity()}.
  1401.      * </p>
  1402.      * <p>
  1403.      * This method is the same as {@link #setLength(int)} called with zero and is provided to match the API of Collections.
  1404.      * </p>
  1405.      *
  1406.      * @return {@code this} instance.
  1407.      */
  1408.     public StrBuilder clear() {
  1409.         size = 0;
  1410.         return this;
  1411.     }

  1412.     /**
  1413.      * Checks if the string builder contains the specified char.
  1414.      *
  1415.      * @param ch the character to find
  1416.      * @return true if the builder contains the character
  1417.      */
  1418.     public boolean contains(final char ch) {
  1419.         final char[] thisBuf = buffer;
  1420.         for (int i = 0; i < this.size; i++) {
  1421.             if (thisBuf[i] == ch) {
  1422.                 return true;
  1423.             }
  1424.         }
  1425.         return false;
  1426.     }

  1427.     /**
  1428.      * Tests if the string builder contains the specified string.
  1429.      *
  1430.      * @param str the string to find
  1431.      * @return true if the builder contains the string
  1432.      */
  1433.     public boolean contains(final String str) {
  1434.         return indexOf(str, 0) >= 0;
  1435.     }

  1436.     /**
  1437.      * Tests if the string builder contains a string matched using the specified matcher.
  1438.      * <p>
  1439.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to search for the character 'a' followed by a number.
  1440.      * </p>
  1441.      *
  1442.      * @param matcher the matcher to use, null returns -1
  1443.      * @return true if the matcher finds a match in the builder
  1444.      */
  1445.     public boolean contains(final StrMatcher matcher) {
  1446.         return indexOf(matcher, 0) >= 0;
  1447.     }

  1448.     /**
  1449.      * Deletes the characters between the two specified indices.
  1450.      *
  1451.      * @param startIndex the start index, inclusive, must be valid
  1452.      * @param endIndex   the end index, exclusive, must be valid except that if too large it is treated as end of string
  1453.      * @return {@code this} instance.
  1454.      * @throws IndexOutOfBoundsException if the index is invalid
  1455.      */
  1456.     public StrBuilder delete(final int startIndex, int endIndex) {
  1457.         endIndex = validateRange(startIndex, endIndex);
  1458.         final int len = endIndex - startIndex;
  1459.         if (len > 0) {
  1460.             deleteImpl(startIndex, endIndex, len);
  1461.         }
  1462.         return this;
  1463.     }

  1464.     /**
  1465.      * Deletes the character wherever it occurs in the builder.
  1466.      *
  1467.      * @param ch the character to delete
  1468.      * @return {@code this} instance.
  1469.      */
  1470.     public StrBuilder deleteAll(final char ch) {
  1471.         for (int i = 0; i < size; i++) {
  1472.             if (buffer[i] == ch) {
  1473.                 final int start = i;
  1474.                 while (++i < size) {
  1475.                     if (buffer[i] != ch) {
  1476.                         break;
  1477.                     }
  1478.                 }
  1479.                 final int len = i - start;
  1480.                 deleteImpl(start, i, len);
  1481.                 i -= len;
  1482.             }
  1483.         }
  1484.         return this;
  1485.     }

  1486.     /**
  1487.      * Deletes the string wherever it occurs in the builder.
  1488.      *
  1489.      * @param str the string to delete, null causes no action
  1490.      * @return {@code this} instance.
  1491.      */
  1492.     public StrBuilder deleteAll(final String str) {
  1493.         final int len = str == null ? 0 : str.length();
  1494.         if (len > 0) {
  1495.             int index = indexOf(str, 0);
  1496.             while (index >= 0) {
  1497.                 deleteImpl(index, index + len, len);
  1498.                 index = indexOf(str, index);
  1499.             }
  1500.         }
  1501.         return this;
  1502.     }

  1503.     /**
  1504.      * Deletes all parts of the builder that the matcher matches.
  1505.      * <p>
  1506.      * Matchers can be used to perform advanced deletion behavior. For example you could write a matcher to delete all occurrences where the character 'a' is
  1507.      * followed by a number.
  1508.      * </p>
  1509.      *
  1510.      * @param matcher the matcher to use to find the deletion, null causes no action
  1511.      * @return {@code this} instance.
  1512.      */
  1513.     public StrBuilder deleteAll(final StrMatcher matcher) {
  1514.         return replace(matcher, null, 0, size, -1);
  1515.     }

  1516.     /**
  1517.      * Deletes the character at the specified index.
  1518.      *
  1519.      * @see #charAt(int)
  1520.      * @see #setCharAt(int, char)
  1521.      * @param index the index to delete
  1522.      * @return {@code this} instance.
  1523.      * @throws IndexOutOfBoundsException if the index is invalid
  1524.      */
  1525.     public StrBuilder deleteCharAt(final int index) {
  1526.         if (index < 0 || index >= size) {
  1527.             throw new StringIndexOutOfBoundsException(index);
  1528.         }
  1529.         deleteImpl(index, index + 1, 1);
  1530.         return this;
  1531.     }

  1532.     /**
  1533.      * Deletes the character wherever it occurs in the builder.
  1534.      *
  1535.      * @param ch the character to delete
  1536.      * @return {@code this} instance.
  1537.      */
  1538.     public StrBuilder deleteFirst(final char ch) {
  1539.         for (int i = 0; i < size; i++) {
  1540.             if (buffer[i] == ch) {
  1541.                 deleteImpl(i, i + 1, 1);
  1542.                 break;
  1543.             }
  1544.         }
  1545.         return this;
  1546.     }

  1547.     /**
  1548.      * Deletes the string wherever it occurs in the builder.
  1549.      *
  1550.      * @param str the string to delete, null causes no action
  1551.      * @return {@code this} instance.
  1552.      */
  1553.     public StrBuilder deleteFirst(final String str) {
  1554.         final int len = str == null ? 0 : str.length();
  1555.         if (len > 0) {
  1556.             final int index = indexOf(str, 0);
  1557.             if (index >= 0) {
  1558.                 deleteImpl(index, index + len, len);
  1559.             }
  1560.         }
  1561.         return this;
  1562.     }

  1563.     /**
  1564.      * Deletes the first match within the builder using the specified matcher.
  1565.      * <p>
  1566.      * Matchers can be used to perform advanced deletion behavior. For example you could write a matcher to delete where the character 'a' is followed by a
  1567.      * number.
  1568.      * </p>
  1569.      *
  1570.      * @param matcher the matcher to use to find the deletion, null causes no action
  1571.      * @return {@code this} instance.
  1572.      */
  1573.     public StrBuilder deleteFirst(final StrMatcher matcher) {
  1574.         return replace(matcher, null, 0, size, 1);
  1575.     }

  1576.     /**
  1577.      * Internal method to delete a range without validation.
  1578.      *
  1579.      * @param startIndex the start index, must be valid
  1580.      * @param endIndex   the end index (exclusive), must be valid
  1581.      * @param len        the length, must be valid
  1582.      * @throws IndexOutOfBoundsException if any index is invalid
  1583.      */
  1584.     private void deleteImpl(final int startIndex, final int endIndex, final int len) {
  1585.         System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex);
  1586.         size -= len;
  1587.     }

  1588.     /**
  1589.      * Tests whether this builder ends with the specified string.
  1590.      * <p>
  1591.      * Note that this method handles null input quietly, unlike String.
  1592.      * </p>
  1593.      *
  1594.      * @param str the string to search for, null returns false
  1595.      * @return true if the builder ends with the string
  1596.      */
  1597.     public boolean endsWith(final String str) {
  1598.         if (str == null) {
  1599.             return false;
  1600.         }
  1601.         final int len = str.length();
  1602.         if (len == 0) {
  1603.             return true;
  1604.         }
  1605.         if (len > size) {
  1606.             return false;
  1607.         }
  1608.         int pos = size - len;
  1609.         for (int i = 0; i < len; i++, pos++) {
  1610.             if (buffer[pos] != str.charAt(i)) {
  1611.                 return false;
  1612.             }
  1613.         }
  1614.         return true;
  1615.     }

  1616.     /**
  1617.      * Tests the capacity and ensures that it is at least the size specified.
  1618.      *
  1619.      * @param capacity the capacity to ensure
  1620.      * @return {@code this} instance.
  1621.      */
  1622.     public StrBuilder ensureCapacity(final int capacity) {
  1623.         if (capacity > buffer.length) {
  1624.             final char[] old = buffer;
  1625.             buffer = new char[capacity * 2];
  1626.             System.arraycopy(old, 0, buffer, 0, size);
  1627.         }
  1628.         return this;
  1629.     }

  1630.     /**
  1631.      * Tests the contents of this builder against another to see if they contain the same character content.
  1632.      *
  1633.      * @param obj the object to check, null returns false
  1634.      * @return true if the builders contain the same characters in the same order
  1635.      */
  1636.     @Override
  1637.     public boolean equals(final Object obj) {
  1638.         return obj instanceof StrBuilder && equals((StrBuilder) obj);
  1639.     }

  1640.     /**
  1641.      * Tests the contents of this builder against another to see if they contain the same character content.
  1642.      *
  1643.      * @param other the object to check, null returns false
  1644.      * @return true if the builders contain the same characters in the same order
  1645.      */
  1646.     public boolean equals(final StrBuilder other) {
  1647.         if (this == other) {
  1648.             return true;
  1649.         }
  1650.         if (other == null) {
  1651.             return false;
  1652.         }
  1653.         if (this.size != other.size) {
  1654.             return false;
  1655.         }
  1656.         final char[] thisBuf = this.buffer;
  1657.         final char[] otherBuf = other.buffer;
  1658.         for (int i = size - 1; i >= 0; i--) {
  1659.             if (thisBuf[i] != otherBuf[i]) {
  1660.                 return false;
  1661.             }
  1662.         }
  1663.         return true;
  1664.     }

  1665.     /**
  1666.      * Tests the contents of this builder against another to see if they contain the same character content ignoring case.
  1667.      *
  1668.      * @param other the object to check, null returns false
  1669.      * @return true if the builders contain the same characters in the same order
  1670.      */
  1671.     public boolean equalsIgnoreCase(final StrBuilder other) {
  1672.         if (this == other) {
  1673.             return true;
  1674.         }
  1675.         if (this.size != other.size) {
  1676.             return false;
  1677.         }
  1678.         final char[] thisBuf = this.buffer;
  1679.         final char[] otherBuf = other.buffer;
  1680.         for (int i = size - 1; i >= 0; i--) {
  1681.             final char c1 = thisBuf[i];
  1682.             final char c2 = otherBuf[i];
  1683.             if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) {
  1684.                 return false;
  1685.             }
  1686.         }
  1687.         return true;
  1688.     }

  1689.     /**
  1690.      * Converts this instance to a String.
  1691.      *
  1692.      * @return This instance as a String
  1693.      * @see #toString()
  1694.      * @since 1.12.0
  1695.      */
  1696.     @Override
  1697.     public String get() {
  1698.         return toString();
  1699.     }

  1700.     /**
  1701.      * Copies the character array into the specified array.
  1702.      *
  1703.      * @param destination the destination array, null will cause an array to be created
  1704.      * @return The input array, unless that was null or too small
  1705.      */
  1706.     public char[] getChars(char[] destination) {
  1707.         final int len = length();
  1708.         if (destination == null || destination.length < len) {
  1709.             destination = new char[len];
  1710.         }
  1711.         System.arraycopy(buffer, 0, destination, 0, len);
  1712.         return destination;
  1713.     }

  1714.     /**
  1715.      * Copies the character array into the specified array.
  1716.      *
  1717.      * @param startIndex       first index to copy, inclusive, must be valid
  1718.      * @param endIndex         last index, exclusive, must be valid
  1719.      * @param destination      the destination array, must not be null or too small
  1720.      * @param destinationIndex the index to start copying in destination
  1721.      * @throws NullPointerException      if the array is null
  1722.      * @throws IndexOutOfBoundsException if any index is invalid
  1723.      */
  1724.     public void getChars(final int startIndex, final int endIndex, final char[] destination, final int destinationIndex) {
  1725.         if (startIndex < 0) {
  1726.             throw new StringIndexOutOfBoundsException(startIndex);
  1727.         }
  1728.         if (endIndex < 0 || endIndex > length()) {
  1729.             throw new StringIndexOutOfBoundsException(endIndex);
  1730.         }
  1731.         if (startIndex > endIndex) {
  1732.             throw new StringIndexOutOfBoundsException("end < start");
  1733.         }
  1734.         System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex);
  1735.     }

  1736.     /**
  1737.      * Gets the text to be appended when a {@link #appendNewLine() new line} is added.
  1738.      *
  1739.      * @return The new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
  1740.      */
  1741.     public String getNewLineText() {
  1742.         return newLine;
  1743.     }

  1744.     /**
  1745.      * Gets the text to be appended when null is added.
  1746.      *
  1747.      * @return The null text, null means no append
  1748.      */
  1749.     public String getNullText() {
  1750.         return nullText;
  1751.     }

  1752.     /**
  1753.      * Gets a suitable hash code for this builder.
  1754.      *
  1755.      * @return a hash code
  1756.      */
  1757.     @Override
  1758.     public int hashCode() {
  1759.         final char[] buf = buffer;
  1760.         int hash = 0;
  1761.         for (int i = size - 1; i >= 0; i--) {
  1762.             hash = 31 * hash + buf[i];
  1763.         }
  1764.         return hash;
  1765.     }

  1766.     /**
  1767.      * Searches the string builder to find the first reference to the specified char.
  1768.      *
  1769.      * @param ch the character to find
  1770.      * @return The first index of the character, or -1 if not found
  1771.      */
  1772.     public int indexOf(final char ch) {
  1773.         return indexOf(ch, 0);
  1774.     }

  1775.     /**
  1776.      * Searches the string builder to find the first reference to the specified char.
  1777.      *
  1778.      * @param ch         the character to find
  1779.      * @param startIndex the index to start at, invalid index rounded to edge
  1780.      * @return The first index of the character, or -1 if not found
  1781.      */
  1782.     public int indexOf(final char ch, int startIndex) {
  1783.         startIndex = Math.max(startIndex, 0);
  1784.         if (startIndex >= size) {
  1785.             return -1;
  1786.         }
  1787.         final char[] thisBuf = buffer;
  1788.         for (int i = startIndex; i < size; i++) {
  1789.             if (thisBuf[i] == ch) {
  1790.                 return i;
  1791.             }
  1792.         }
  1793.         return -1;
  1794.     }

  1795.     /**
  1796.      * Searches the string builder to find the first reference to the specified string.
  1797.      * <p>
  1798.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  1799.      * </p>
  1800.      *
  1801.      * @param str the string to find, null returns -1
  1802.      * @return The first index of the string, or -1 if not found
  1803.      */
  1804.     public int indexOf(final String str) {
  1805.         return indexOf(str, 0);
  1806.     }

  1807.     /**
  1808.      * Searches the string builder to find the first reference to the specified string starting searching from the given index.
  1809.      * <p>
  1810.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  1811.      * </p>
  1812.      *
  1813.      * @param str        the string to find, null returns -1
  1814.      * @param startIndex the index to start at, invalid index rounded to edge
  1815.      * @return The first index of the string, or -1 if not found
  1816.      */
  1817.     public int indexOf(final String str, int startIndex) {
  1818.         startIndex = Math.max(startIndex, 0);
  1819.         if (str == null || startIndex >= size) {
  1820.             return -1;
  1821.         }
  1822.         final int strLen = str.length();
  1823.         if (strLen == 1) {
  1824.             return indexOf(str.charAt(0), startIndex);
  1825.         }
  1826.         if (strLen == 0) {
  1827.             return startIndex;
  1828.         }
  1829.         if (strLen > size) {
  1830.             return -1;
  1831.         }
  1832.         final char[] thisBuf = buffer;
  1833.         final int len = size - strLen + 1;
  1834.         outer: for (int i = startIndex; i < len; i++) {
  1835.             for (int j = 0; j < strLen; j++) {
  1836.                 if (str.charAt(j) != thisBuf[i + j]) {
  1837.                     continue outer;
  1838.                 }
  1839.             }
  1840.             return i;
  1841.         }
  1842.         return -1;
  1843.     }

  1844.     /**
  1845.      * Searches the string builder using the matcher to find the first match.
  1846.      * <p>
  1847.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number.
  1848.      * </p>
  1849.      *
  1850.      * @param matcher the matcher to use, null returns -1
  1851.      * @return The first index matched, or -1 if not found
  1852.      */
  1853.     public int indexOf(final StrMatcher matcher) {
  1854.         return indexOf(matcher, 0);
  1855.     }

  1856.     /**
  1857.      * Searches the string builder using the matcher to find the first match searching from the given index.
  1858.      * <p>
  1859.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number.
  1860.      * </p>
  1861.      *
  1862.      * @param matcher    the matcher to use, null returns -1
  1863.      * @param startIndex the index to start at, invalid index rounded to edge
  1864.      * @return The first index matched, or -1 if not found
  1865.      */
  1866.     public int indexOf(final StrMatcher matcher, int startIndex) {
  1867.         startIndex = Math.max(startIndex, 0);
  1868.         if (matcher == null || startIndex >= size) {
  1869.             return -1;
  1870.         }
  1871.         final int len = size;
  1872.         final char[] buf = buffer;
  1873.         for (int i = startIndex; i < len; i++) {
  1874.             if (matcher.isMatch(buf, i, startIndex, len) > 0) {
  1875.                 return i;
  1876.             }
  1877.         }
  1878.         return -1;
  1879.     }

  1880.     /**
  1881.      * Inserts the value into this builder.
  1882.      *
  1883.      * @param index the index to add at, must be valid
  1884.      * @param value the value to insert
  1885.      * @return {@code this} instance.
  1886.      * @throws IndexOutOfBoundsException if the index is invalid
  1887.      */
  1888.     public StrBuilder insert(int index, final boolean value) {
  1889.         validateIndex(index);
  1890.         if (value) {
  1891.             ensureCapacity(size + 4);
  1892.             System.arraycopy(buffer, index, buffer, index + 4, size - index);
  1893.             buffer[index++] = 't';
  1894.             buffer[index++] = 'r';
  1895.             buffer[index++] = 'u';
  1896.             buffer[index] = 'e';
  1897.             size += 4;
  1898.         } else {
  1899.             ensureCapacity(size + 5);
  1900.             System.arraycopy(buffer, index, buffer, index + 5, size - index);
  1901.             buffer[index++] = 'f';
  1902.             buffer[index++] = 'a';
  1903.             buffer[index++] = 'l';
  1904.             buffer[index++] = 's';
  1905.             buffer[index] = 'e';
  1906.             size += 5;
  1907.         }
  1908.         return this;
  1909.     }

  1910.     /**
  1911.      * Inserts the value into this builder.
  1912.      *
  1913.      * @param index the index to add at, must be valid
  1914.      * @param value the value to insert
  1915.      * @return {@code this} instance.
  1916.      * @throws IndexOutOfBoundsException if the index is invalid
  1917.      */
  1918.     public StrBuilder insert(final int index, final char value) {
  1919.         validateIndex(index);
  1920.         ensureCapacity(size + 1);
  1921.         System.arraycopy(buffer, index, buffer, index + 1, size - index);
  1922.         buffer[index] = value;
  1923.         size++;
  1924.         return this;
  1925.     }

  1926.     /**
  1927.      * Inserts the character array into this builder. Inserting null will use the stored null text value.
  1928.      *
  1929.      * @param index the index to add at, must be valid
  1930.      * @param chars the char array to insert
  1931.      * @return {@code this} instance.
  1932.      * @throws IndexOutOfBoundsException if the index is invalid
  1933.      */
  1934.     public StrBuilder insert(final int index, final char[] chars) {
  1935.         validateIndex(index);
  1936.         if (chars == null) {
  1937.             return insert(index, nullText);
  1938.         }
  1939.         final int len = chars.length;
  1940.         if (len > 0) {
  1941.             ensureCapacity(size + len);
  1942.             System.arraycopy(buffer, index, buffer, index + len, size - index);
  1943.             System.arraycopy(chars, 0, buffer, index, len);
  1944.             size += len;
  1945.         }
  1946.         return this;
  1947.     }

  1948.     /**
  1949.      * Inserts part of the character array into this builder. Inserting null will use the stored null text value.
  1950.      *
  1951.      * @param index  the index to add at, must be valid
  1952.      * @param chars  the char array to insert
  1953.      * @param offset the offset into the character array to start at, must be valid
  1954.      * @param length the length of the character array part to copy, must be positive
  1955.      * @return {@code this} instance.
  1956.      * @throws IndexOutOfBoundsException if any index is invalid
  1957.      */
  1958.     public StrBuilder insert(final int index, final char[] chars, final int offset, final int length) {
  1959.         validateIndex(index);
  1960.         if (chars == null) {
  1961.             return insert(index, nullText);
  1962.         }
  1963.         if (offset < 0 || offset > chars.length) {
  1964.             throw new StringIndexOutOfBoundsException("Invalid offset: " + offset);
  1965.         }
  1966.         if (length < 0 || offset + length > chars.length) {
  1967.             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
  1968.         }
  1969.         if (length > 0) {
  1970.             ensureCapacity(size + length);
  1971.             System.arraycopy(buffer, index, buffer, index + length, size - index);
  1972.             System.arraycopy(chars, offset, buffer, index, length);
  1973.             size += length;
  1974.         }
  1975.         return this;
  1976.     }

  1977.     /**
  1978.      * Inserts the value into this builder.
  1979.      *
  1980.      * @param index the index to add at, must be valid
  1981.      * @param value the value to insert
  1982.      * @return {@code this} instance.
  1983.      * @throws IndexOutOfBoundsException if the index is invalid
  1984.      */
  1985.     public StrBuilder insert(final int index, final double value) {
  1986.         return insert(index, String.valueOf(value));
  1987.     }

  1988.     /**
  1989.      * Inserts the value into this builder.
  1990.      *
  1991.      * @param index the index to add at, must be valid
  1992.      * @param value the value to insert
  1993.      * @return {@code this} instance.
  1994.      * @throws IndexOutOfBoundsException if the index is invalid
  1995.      */
  1996.     public StrBuilder insert(final int index, final float value) {
  1997.         return insert(index, String.valueOf(value));
  1998.     }

  1999.     /**
  2000.      * Inserts the value into this builder.
  2001.      *
  2002.      * @param index the index to add at, must be valid
  2003.      * @param value the value to insert
  2004.      * @return {@code this} instance.
  2005.      * @throws IndexOutOfBoundsException if the index is invalid
  2006.      */
  2007.     public StrBuilder insert(final int index, final int value) {
  2008.         return insert(index, String.valueOf(value));
  2009.     }

  2010.     /**
  2011.      * Inserts the value into this builder.
  2012.      *
  2013.      * @param index the index to add at, must be valid
  2014.      * @param value the value to insert
  2015.      * @return {@code this} instance.
  2016.      * @throws IndexOutOfBoundsException if the index is invalid
  2017.      */
  2018.     public StrBuilder insert(final int index, final long value) {
  2019.         return insert(index, String.valueOf(value));
  2020.     }

  2021.     /**
  2022.      * Inserts the string representation of an object into this builder. Inserting null will use the stored null text value.
  2023.      *
  2024.      * @param index the index to add at, must be valid
  2025.      * @param obj   the object to insert
  2026.      * @return {@code this} instance.
  2027.      * @throws IndexOutOfBoundsException if the index is invalid
  2028.      */
  2029.     public StrBuilder insert(final int index, final Object obj) {
  2030.         if (obj == null) {
  2031.             return insert(index, nullText);
  2032.         }
  2033.         return insert(index, obj.toString());
  2034.     }

  2035.     /**
  2036.      * Inserts the string into this builder. Inserting null will use the stored null text value.
  2037.      *
  2038.      * @param index the index to add at, must be valid
  2039.      * @param str   the string to insert
  2040.      * @return {@code this} instance.
  2041.      * @throws IndexOutOfBoundsException if the index is invalid
  2042.      */
  2043.     public StrBuilder insert(final int index, String str) {
  2044.         validateIndex(index);
  2045.         if (str == null) {
  2046.             str = nullText;
  2047.         }
  2048.         if (str != null) {
  2049.             final int strLen = str.length();
  2050.             if (strLen > 0) {
  2051.                 final int newSize = size + strLen;
  2052.                 ensureCapacity(newSize);
  2053.                 System.arraycopy(buffer, index, buffer, index + strLen, size - index);
  2054.                 size = newSize;
  2055.                 str.getChars(0, strLen, buffer, index);
  2056.             }
  2057.         }
  2058.         return this;
  2059.     }

  2060.     /**
  2061.      * Tests if the string builder is empty (convenience Collections API style method).
  2062.      * <p>
  2063.      * This method is the same as checking {@link #length()} and is provided to match the API of Collections.
  2064.      * </p>
  2065.      *
  2066.      * @return {@code true} if the size is {@code 0}.
  2067.      */
  2068.     public boolean isEmpty() {
  2069.         return size == 0;
  2070.     }

  2071.     /**
  2072.      * Tests if the string builder is not empty (convenience Collections API style method).
  2073.      * <p>
  2074.      * This method is the same as checking {@link #length()} and is provided to match the API of Collections.
  2075.      * </p>
  2076.      *
  2077.      * @return {@code true} if the size is greater than {@code 0}.
  2078.      * @since 1.10.0
  2079.      */
  2080.     public boolean isNotEmpty() {
  2081.         return size > 0;
  2082.     }

  2083.     /**
  2084.      * Searches the string builder to find the last reference to the specified char.
  2085.      *
  2086.      * @param ch the character to find
  2087.      * @return The last index of the character, or -1 if not found
  2088.      */
  2089.     public int lastIndexOf(final char ch) {
  2090.         return lastIndexOf(ch, size - 1);
  2091.     }

  2092.     /**
  2093.      * Searches the string builder to find the last reference to the specified char.
  2094.      *
  2095.      * @param ch         the character to find
  2096.      * @param startIndex the index to start at, invalid index rounded to edge
  2097.      * @return The last index of the character, or -1 if not found
  2098.      */
  2099.     public int lastIndexOf(final char ch, int startIndex) {
  2100.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2101.         if (startIndex < 0) {
  2102.             return -1;
  2103.         }
  2104.         for (int i = startIndex; i >= 0; i--) {
  2105.             if (buffer[i] == ch) {
  2106.                 return i;
  2107.             }
  2108.         }
  2109.         return -1;
  2110.     }

  2111.     /**
  2112.      * Searches the string builder to find the last reference to the specified string.
  2113.      * <p>
  2114.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  2115.      * </p>
  2116.      *
  2117.      * @param str the string to find, null returns -1
  2118.      * @return The last index of the string, or -1 if not found
  2119.      */
  2120.     public int lastIndexOf(final String str) {
  2121.         return lastIndexOf(str, size - 1);
  2122.     }

  2123.     /**
  2124.      * Searches the string builder to find the last reference to the specified string starting searching from the given index.
  2125.      * <p>
  2126.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  2127.      * </p>
  2128.      *
  2129.      * @param str        the string to find, null returns -1
  2130.      * @param startIndex the index to start at, invalid index rounded to edge
  2131.      * @return The last index of the string, or -1 if not found
  2132.      */
  2133.     public int lastIndexOf(final String str, int startIndex) {
  2134.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2135.         if (str == null || startIndex < 0) {
  2136.             return -1;
  2137.         }
  2138.         final int strLen = str.length();
  2139.         if (strLen > 0 && strLen <= size) {
  2140.             if (strLen == 1) {
  2141.                 return lastIndexOf(str.charAt(0), startIndex);
  2142.             }

  2143.             outer: for (int i = startIndex - strLen + 1; i >= 0; i--) {
  2144.                 for (int j = 0; j < strLen; j++) {
  2145.                     if (str.charAt(j) != buffer[i + j]) {
  2146.                         continue outer;
  2147.                     }
  2148.                 }
  2149.                 return i;
  2150.             }

  2151.         } else if (strLen == 0) {
  2152.             return startIndex;
  2153.         }
  2154.         return -1;
  2155.     }

  2156.     /**
  2157.      * Searches the string builder using the matcher to find the last match.
  2158.      * <p>
  2159.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number.
  2160.      * </p>
  2161.      *
  2162.      * @param matcher the matcher to use, null returns -1
  2163.      * @return The last index matched, or -1 if not found
  2164.      */
  2165.     public int lastIndexOf(final StrMatcher matcher) {
  2166.         return lastIndexOf(matcher, size);
  2167.     }

  2168.     /**
  2169.      * Searches the string builder using the matcher to find the last match searching from the given index.
  2170.      * <p>
  2171.      * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the character 'a' followed by a number.
  2172.      * </p>
  2173.      *
  2174.      * @param matcher    the matcher to use, null returns -1
  2175.      * @param startIndex the index to start at, invalid index rounded to edge
  2176.      * @return The last index matched, or -1 if not found
  2177.      */
  2178.     public int lastIndexOf(final StrMatcher matcher, int startIndex) {
  2179.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2180.         if (matcher == null || startIndex < 0) {
  2181.             return -1;
  2182.         }
  2183.         final char[] buf = buffer;
  2184.         final int endIndex = startIndex + 1;
  2185.         for (int i = startIndex; i >= 0; i--) {
  2186.             if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
  2187.                 return i;
  2188.             }
  2189.         }
  2190.         return -1;
  2191.     }

  2192.     /**
  2193.      * Extracts the leftmost characters from the string builder without throwing an exception.
  2194.      * <p>
  2195.      * This method extracts the left {@code length} characters from the builder. If this many characters are not available, the whole builder is returned. Thus
  2196.      * the returned string may be shorter than the length requested.
  2197.      * </p>
  2198.      *
  2199.      * @param length the number of characters to extract, negative returns empty string
  2200.      * @return The new string
  2201.      */
  2202.     public String leftString(final int length) {
  2203.         if (length <= 0) {
  2204.             return StringUtils.EMPTY;
  2205.         }
  2206.         if (length >= size) {
  2207.             return new String(buffer, 0, size);
  2208.         }
  2209.         return new String(buffer, 0, length);
  2210.     }

  2211.     /**
  2212.      * Gets the length of the string builder.
  2213.      *
  2214.      * @return The length
  2215.      */
  2216.     @Override
  2217.     public int length() {
  2218.         return size;
  2219.     }

  2220.     /**
  2221.      * Extracts some characters from the middle of the string builder without throwing an exception.
  2222.      * <p>
  2223.      * This method extracts {@code length} characters from the builder at the specified index. If the index is negative it is treated as zero. If the index is
  2224.      * greater than the builder size, it is treated as the builder size. If the length is negative, the empty string is returned. If insufficient characters are
  2225.      * available in the builder, as much as possible is returned. Thus the returned string may be shorter than the length requested.
  2226.      * </p>
  2227.      *
  2228.      * @param index  the index to start at, negative means zero
  2229.      * @param length the number of characters to extract, negative returns empty string
  2230.      * @return The new string
  2231.      */
  2232.     public String midString(int index, final int length) {
  2233.         if (index < 0) {
  2234.             index = 0;
  2235.         }
  2236.         if (length <= 0 || index >= size) {
  2237.             return StringUtils.EMPTY;
  2238.         }
  2239.         if (size <= index + length) {
  2240.             return new String(buffer, index, size - index);
  2241.         }
  2242.         return new String(buffer, index, length);
  2243.     }

  2244.     /**
  2245.      * Minimizes the capacity to the actual length of the string.
  2246.      *
  2247.      * @return {@code this} instance.
  2248.      */
  2249.     public StrBuilder minimizeCapacity() {
  2250.         if (buffer.length > length()) {
  2251.             final char[] old = buffer;
  2252.             buffer = new char[length()];
  2253.             System.arraycopy(old, 0, buffer, 0, size);
  2254.         }
  2255.         return this;
  2256.     }

  2257.     /**
  2258.      * If possible, reads chars from the provided {@link Readable} directly into underlying character buffer without making extra copies.
  2259.      *
  2260.      * @param readable object to read from
  2261.      * @return The number of characters read
  2262.      * @throws IOException if an I/O error occurs.
  2263.      * @see #appendTo(Appendable)
  2264.      */
  2265.     public int readFrom(final Readable readable) throws IOException {
  2266.         final int oldSize = size;
  2267.         if (readable instanceof Reader) {
  2268.             final Reader r = (Reader) readable;
  2269.             ensureCapacity(size + 1);
  2270.             int read;
  2271.             while ((read = r.read(buffer, size, buffer.length - size)) != -1) {
  2272.                 size += read;
  2273.                 ensureCapacity(size + 1);
  2274.             }
  2275.         } else if (readable instanceof CharBuffer) {
  2276.             final CharBuffer cb = (CharBuffer) readable;
  2277.             final int remaining = cb.remaining();
  2278.             ensureCapacity(size + remaining);
  2279.             cb.get(buffer, size, remaining);
  2280.             size += remaining;
  2281.         } else {
  2282.             while (true) {
  2283.                 ensureCapacity(size + 1);
  2284.                 final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size);
  2285.                 final int read = readable.read(buf);
  2286.                 if (read == -1) {
  2287.                     break;
  2288.                 }
  2289.                 size += read;
  2290.             }
  2291.         }
  2292.         return size - oldSize;
  2293.     }

  2294.     /**
  2295.      * Replaces a portion of the string builder with another string. The length of the inserted string does not have to match the removed length.
  2296.      *
  2297.      * @param startIndex the start index, inclusive, must be valid
  2298.      * @param endIndex   the end index, exclusive, must be valid except that if too large it is treated as end of string
  2299.      * @param replaceStr the string to replace with, null means delete range
  2300.      * @return {@code this} instance.
  2301.      * @throws IndexOutOfBoundsException if the index is invalid
  2302.      */
  2303.     public StrBuilder replace(final int startIndex, int endIndex, final String replaceStr) {
  2304.         endIndex = validateRange(startIndex, endIndex);
  2305.         final int insertLen = replaceStr == null ? 0 : replaceStr.length();
  2306.         replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen);
  2307.         return this;
  2308.     }

  2309.     /**
  2310.      * Advanced search and replaces within the builder using a matcher.
  2311.      * <p>
  2312.      * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all occurrences where the character 'a' is followed by
  2313.      * a number.
  2314.      * </p>
  2315.      *
  2316.      * @param matcher      the matcher to use to find the deletion, null causes no action
  2317.      * @param replaceStr   the string to replace the match with, null is a delete
  2318.      * @param startIndex   the start index, inclusive, must be valid
  2319.      * @param endIndex     the end index, exclusive, must be valid except that if too large it is treated as end of string
  2320.      * @param replaceCount the number of times to replace, -1 for replace all
  2321.      * @return {@code this} instance.
  2322.      * @throws IndexOutOfBoundsException if start index is invalid
  2323.      */
  2324.     public StrBuilder replace(final StrMatcher matcher, final String replaceStr, final int startIndex, int endIndex, final int replaceCount) {
  2325.         endIndex = validateRange(startIndex, endIndex);
  2326.         return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount);
  2327.     }

  2328.     /**
  2329.      * Replaces the search character with the replace character throughout the builder.
  2330.      *
  2331.      * @param search  the search character
  2332.      * @param replace the replace character
  2333.      * @return {@code this} instance.
  2334.      */
  2335.     public StrBuilder replaceAll(final char search, final char replace) {
  2336.         if (search != replace) {
  2337.             for (int i = 0; i < size; i++) {
  2338.                 if (buffer[i] == search) {
  2339.                     buffer[i] = replace;
  2340.                 }
  2341.             }
  2342.         }
  2343.         return this;
  2344.     }

  2345.     /**
  2346.      * Replaces the search string with the replace string throughout the builder.
  2347.      *
  2348.      * @param searchStr  the search string, null causes no action to occur
  2349.      * @param replaceStr the replace string, null is equivalent to an empty string
  2350.      * @return {@code this} instance.
  2351.      */
  2352.     public StrBuilder replaceAll(final String searchStr, final String replaceStr) {
  2353.         final int searchLen = searchStr == null ? 0 : searchStr.length();
  2354.         if (searchLen > 0) {
  2355.             final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
  2356.             int index = indexOf(searchStr, 0);
  2357.             while (index >= 0) {
  2358.                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
  2359.                 index = indexOf(searchStr, index + replaceLen);
  2360.             }
  2361.         }
  2362.         return this;
  2363.     }

  2364.     /**
  2365.      * Replaces all matches within the builder with the replace string.
  2366.      * <p>
  2367.      * Matchers can be used to perform advanced replace behavior. For example you could write a matcher to replace all occurrences where the character 'a' is
  2368.      * followed by a number.
  2369.      * </p>
  2370.      *
  2371.      * @param matcher    the matcher to use to find the deletion, null causes no action
  2372.      * @param replaceStr the replace string, null is equivalent to an empty string
  2373.      * @return {@code this} instance.
  2374.      */
  2375.     public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) {
  2376.         return replace(matcher, replaceStr, 0, size, -1);
  2377.     }

  2378.     /**
  2379.      * Replaces the first instance of the search character with the replace character in the builder.
  2380.      *
  2381.      * @param search  the search character
  2382.      * @param replace the replace character
  2383.      * @return {@code this} instance.
  2384.      */
  2385.     public StrBuilder replaceFirst(final char search, final char replace) {
  2386.         if (search != replace) {
  2387.             for (int i = 0; i < size; i++) {
  2388.                 if (buffer[i] == search) {
  2389.                     buffer[i] = replace;
  2390.                     break;
  2391.                 }
  2392.             }
  2393.         }
  2394.         return this;
  2395.     }

  2396.     /**
  2397.      * Replaces the first instance of the search string with the replace string.
  2398.      *
  2399.      * @param searchStr  the search string, null causes no action to occur
  2400.      * @param replaceStr the replace string, null is equivalent to an empty string
  2401.      * @return {@code this} instance.
  2402.      */
  2403.     public StrBuilder replaceFirst(final String searchStr, final String replaceStr) {
  2404.         final int searchLen = searchStr == null ? 0 : searchStr.length();
  2405.         if (searchLen > 0) {
  2406.             final int index = indexOf(searchStr, 0);
  2407.             if (index >= 0) {
  2408.                 final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
  2409.                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
  2410.             }
  2411.         }
  2412.         return this;
  2413.     }

  2414.     /**
  2415.      * Replaces the first match within the builder with the replace string.
  2416.      * <p>
  2417.      * Matchers can be used to perform advanced replace behavior. For example you could write a matcher to replace where the character 'a' is followed by a
  2418.      * number.
  2419.      * </p>
  2420.      *
  2421.      * @param matcher    the matcher to use to find the deletion, null causes no action
  2422.      * @param replaceStr the replace string, null is equivalent to an empty string
  2423.      * @return {@code this} instance.
  2424.      */
  2425.     public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr) {
  2426.         return replace(matcher, replaceStr, 0, size, 1);
  2427.     }

  2428.     /**
  2429.      * Internal method to delete a range without validation.
  2430.      *
  2431.      * @param startIndex the start index, must be valid
  2432.      * @param endIndex   the end index (exclusive), must be valid
  2433.      * @param removeLen  the length to remove (endIndex - startIndex), must be valid
  2434.      * @param insertStr  the string to replace with, null means delete range
  2435.      * @param insertLen  the length of the insert string, must be valid
  2436.      * @throws IndexOutOfBoundsException if any index is invalid
  2437.      */
  2438.     private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, final int insertLen) {
  2439.         final int newSize = size - removeLen + insertLen;
  2440.         if (insertLen != removeLen) {
  2441.             ensureCapacity(newSize);
  2442.             System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex);
  2443.             size = newSize;
  2444.         }
  2445.         if (insertLen > 0) {
  2446.             insertStr.getChars(0, insertLen, buffer, startIndex);
  2447.         }
  2448.     }

  2449.     /**
  2450.      * Replaces within the builder using a matcher.
  2451.      * <p>
  2452.      * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all occurrences where the character 'a' is followed by
  2453.      * a number.
  2454.      * </p>
  2455.      *
  2456.      * @param matcher      the matcher to use to find the deletion, null causes no action
  2457.      * @param replaceStr   the string to replace the match with, null is a delete
  2458.      * @param from         the start index, must be valid
  2459.      * @param to           the end index (exclusive), must be valid
  2460.      * @param replaceCount the number of times to replace, -1 for replace all
  2461.      * @return {@code this} instance.
  2462.      * @throws IndexOutOfBoundsException if any index is invalid
  2463.      */
  2464.     private StrBuilder replaceImpl(final StrMatcher matcher, final String replaceStr, final int from, int to, int replaceCount) {
  2465.         if (matcher == null || size == 0) {
  2466.             return this;
  2467.         }
  2468.         final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
  2469.         for (int i = from; i < to && replaceCount != 0; i++) {
  2470.             final char[] buf = buffer;
  2471.             final int removeLen = matcher.isMatch(buf, i, from, to);
  2472.             if (removeLen > 0) {
  2473.                 replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen);
  2474.                 to = to - removeLen + replaceLen;
  2475.                 i = i + replaceLen - 1;
  2476.                 if (replaceCount > 0) {
  2477.                     replaceCount--;
  2478.                 }
  2479.             }
  2480.         }
  2481.         return this;
  2482.     }

  2483.     /**
  2484.      * Reverses the string builder placing each character in the opposite index.
  2485.      *
  2486.      * @return {@code this} instance.
  2487.      */
  2488.     public StrBuilder reverse() {
  2489.         if (size == 0) {
  2490.             return this;
  2491.         }

  2492.         final int half = size / 2;
  2493.         final char[] buf = buffer;
  2494.         for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) {
  2495.             final char swap = buf[leftIdx];
  2496.             buf[leftIdx] = buf[rightIdx];
  2497.             buf[rightIdx] = swap;
  2498.         }
  2499.         return this;
  2500.     }

  2501.     /**
  2502.      * Extracts the rightmost characters from the string builder without throwing an exception.
  2503.      * <p>
  2504.      * This method extracts the right {@code length} characters from the builder. If this many characters are not available, the whole builder is returned. Thus
  2505.      * the returned string may be shorter than the length requested.
  2506.      * </p>
  2507.      *
  2508.      * @param length the number of characters to extract, negative returns empty string
  2509.      * @return The new string
  2510.      */
  2511.     public String rightString(final int length) {
  2512.         if (length <= 0) {
  2513.             return StringUtils.EMPTY;
  2514.         }
  2515.         if (length >= size) {
  2516.             return new String(buffer, 0, size);
  2517.         }
  2518.         return new String(buffer, size - length, length);
  2519.     }

  2520.     /**
  2521.      * Sets the character at the specified index.
  2522.      *
  2523.      * @see #charAt(int)
  2524.      * @see #deleteCharAt(int)
  2525.      * @param index the index to set
  2526.      * @param ch    the new character
  2527.      * @return {@code this} instance.
  2528.      * @throws IndexOutOfBoundsException if the index is invalid
  2529.      */
  2530.     public StrBuilder setCharAt(final int index, final char ch) {
  2531.         if (index < 0 || index >= length()) {
  2532.             throw new StringIndexOutOfBoundsException(index);
  2533.         }
  2534.         buffer[index] = ch;
  2535.         return this;
  2536.     }

  2537.     /**
  2538.      * Updates the length of the builder by either dropping the last characters or adding filler of Unicode zero.
  2539.      *
  2540.      * @param length the length to set to, must be zero or positive
  2541.      * @return {@code this} instance.
  2542.      * @throws IndexOutOfBoundsException if the length is negative
  2543.      */
  2544.     public StrBuilder setLength(final int length) {
  2545.         if (length < 0) {
  2546.             throw new StringIndexOutOfBoundsException(length);
  2547.         }
  2548.         if (length < size) {
  2549.             size = length;
  2550.         } else if (length > size) {
  2551.             ensureCapacity(length);
  2552.             Arrays.fill(buffer, size, length, CharUtils.NUL);
  2553.             size = length;
  2554.         }
  2555.         return this;
  2556.     }

  2557.     /**
  2558.      * Sets the text to be appended when {@link #appendNewLine() new line} is called.
  2559.      *
  2560.      * @param newLine the new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
  2561.      * @return {@code this} instance.
  2562.      */
  2563.     public StrBuilder setNewLineText(final String newLine) {
  2564.         this.newLine = newLine;
  2565.         return this;
  2566.     }

  2567.     /**
  2568.      * Sets the text to be appended when null is added.
  2569.      *
  2570.      * @param nullText the null text, null means no append
  2571.      * @return {@code this} instance.
  2572.      */
  2573.     public StrBuilder setNullText(String nullText) {
  2574.         if (nullText != null && nullText.isEmpty()) {
  2575.             nullText = null;
  2576.         }
  2577.         this.nullText = nullText;
  2578.         return this;
  2579.     }

  2580.     /**
  2581.      * Gets the length of the string builder.
  2582.      * <p>
  2583.      * This method is the same as {@link #length()} and is provided to match the API of Collections.
  2584.      * </p>
  2585.      *
  2586.      * @return The length
  2587.      */
  2588.     public int size() {
  2589.         return size;
  2590.     }

  2591.     /**
  2592.      * Checks whether this builder starts with the specified string.
  2593.      * <p>
  2594.      * Note that this method handles null input quietly, unlike String.
  2595.      * </p>
  2596.      *
  2597.      * @param str the string to search for, null returns false
  2598.      * @return true if the builder starts with the string
  2599.      */
  2600.     public boolean startsWith(final String str) {
  2601.         if (str == null) {
  2602.             return false;
  2603.         }
  2604.         final int len = str.length();
  2605.         if (len == 0) {
  2606.             return true;
  2607.         }
  2608.         if (len > size) {
  2609.             return false;
  2610.         }
  2611.         for (int i = 0; i < len; i++) {
  2612.             if (buffer[i] != str.charAt(i)) {
  2613.                 return false;
  2614.             }
  2615.         }
  2616.         return true;
  2617.     }

  2618.     /**
  2619.      * {@inheritDoc}
  2620.      */
  2621.     @Override
  2622.     public CharSequence subSequence(final int startIndex, final int endIndex) {
  2623.         if (startIndex < 0) {
  2624.             throw new StringIndexOutOfBoundsException(startIndex);
  2625.         }
  2626.         if (endIndex > size) {
  2627.             throw new StringIndexOutOfBoundsException(endIndex);
  2628.         }
  2629.         if (startIndex > endIndex) {
  2630.             throw new StringIndexOutOfBoundsException(endIndex - startIndex);
  2631.         }
  2632.         return substring(startIndex, endIndex);
  2633.     }

  2634.     /**
  2635.      * Extracts a portion of this string builder as a string.
  2636.      *
  2637.      * @param start the start index, inclusive, must be valid
  2638.      * @return The new string
  2639.      * @throws IndexOutOfBoundsException if the index is invalid
  2640.      */
  2641.     public String substring(final int start) {
  2642.         return substring(start, size);
  2643.     }

  2644.     /**
  2645.      * Extracts a portion of this string builder as a string.
  2646.      * <p>
  2647.      * Note: This method treats an endIndex greater than the length of the builder as equal to the length of the builder, and continues without error, unlike
  2648.      * StringBuffer or String.
  2649.      *
  2650.      * @param startIndex the start index, inclusive, must be valid
  2651.      * @param endIndex   the end index, exclusive, must be valid except that if too large it is treated as end of string
  2652.      * @return The new string
  2653.      * @throws IndexOutOfBoundsException if the index is invalid
  2654.      */
  2655.     public String substring(final int startIndex, int endIndex) {
  2656.         endIndex = validateRange(startIndex, endIndex);
  2657.         return new String(buffer, startIndex, endIndex - startIndex);
  2658.     }

  2659.     /**
  2660.      * Copies the builder's character array into a new character array.
  2661.      *
  2662.      * @return a new array that represents the contents of the builder
  2663.      */
  2664.     public char[] toCharArray() {
  2665.         return size == 0 ? ArrayUtils.EMPTY_CHAR_ARRAY : Arrays.copyOf(buffer, size);
  2666.     }

  2667.     /**
  2668.      * Copies part of the builder's character array into a new character array.
  2669.      *
  2670.      * @param startIndex the start index, inclusive, must be valid
  2671.      * @param endIndex   the end index, exclusive, must be valid except that if too large it is treated as end of string
  2672.      * @return a new array that holds part of the contents of the builder
  2673.      * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is invalid (but endIndex greater than size is valid)
  2674.      */
  2675.     public char[] toCharArray(final int startIndex, int endIndex) {
  2676.         endIndex = validateRange(startIndex, endIndex);
  2677.         final int len = endIndex - startIndex;
  2678.         if (len == 0) {
  2679.             return ArrayUtils.EMPTY_CHAR_ARRAY;
  2680.         }
  2681.         final char[] chars = new char[len];
  2682.         System.arraycopy(buffer, startIndex, chars, 0, len);
  2683.         return chars;
  2684.     }

  2685.     /**
  2686.      * Gets a String version of the string builder, creating a new instance each time the method is called.
  2687.      * <p>
  2688.      * Note that unlike StringBuffer, the string version returned is independent of the string builder.
  2689.      * </p>
  2690.      *
  2691.      * @return The builder as a String
  2692.      */
  2693.     @Override
  2694.     public String toString() {
  2695.         return new String(buffer, 0, size);
  2696.     }

  2697.     /**
  2698.      * Gets a StringBuffer version of the string builder, creating a new instance each time the method is called.
  2699.      *
  2700.      * @return The builder as a StringBuffer
  2701.      */
  2702.     public StringBuffer toStringBuffer() {
  2703.         return new StringBuffer(size).append(buffer, 0, size);
  2704.     }

  2705.     /**
  2706.      * Gets a StringBuilder version of the string builder, creating a new instance each time the method is called.
  2707.      *
  2708.      * @return The builder as a StringBuilder
  2709.      */
  2710.     public StringBuilder toStringBuilder() {
  2711.         return new StringBuilder(size).append(buffer, 0, size);
  2712.     }

  2713.     /**
  2714.      * Trims the builder by removing characters less than or equal to a space from the beginning and end.
  2715.      *
  2716.      * @return {@code this} instance.
  2717.      */
  2718.     public StrBuilder trim() {
  2719.         if (size == 0) {
  2720.             return this;
  2721.         }
  2722.         int len = size;
  2723.         final char[] buf = buffer;
  2724.         int pos = 0;
  2725.         while (pos < len && buf[pos] <= ' ') {
  2726.             pos++;
  2727.         }
  2728.         while (pos < len && buf[len - 1] <= ' ') {
  2729.             len--;
  2730.         }
  2731.         if (len < size) {
  2732.             delete(len, size);
  2733.         }
  2734.         if (pos > 0) {
  2735.             delete(0, pos);
  2736.         }
  2737.         return this;
  2738.     }

  2739.     /**
  2740.      * Validates parameters defining a single index in the builder.
  2741.      *
  2742.      * @param index the index, must be valid
  2743.      * @throws IndexOutOfBoundsException if the index is invalid
  2744.      */
  2745.     protected void validateIndex(final int index) {
  2746.         if (index < 0 || index > size) {
  2747.             throw new StringIndexOutOfBoundsException(index);
  2748.         }
  2749.     }

  2750.     /**
  2751.      * Validates parameters defining a range of the builder.
  2752.      *
  2753.      * @param startIndex the start index, inclusive, must be valid
  2754.      * @param endIndex   the end index, exclusive, must be valid except that if too large it is treated as end of string
  2755.      * @return The new string
  2756.      * @throws IndexOutOfBoundsException if the index is invalid
  2757.      */
  2758.     protected int validateRange(final int startIndex, int endIndex) {
  2759.         if (startIndex < 0) {
  2760.             throw new StringIndexOutOfBoundsException(startIndex);
  2761.         }
  2762.         if (endIndex > size) {
  2763.             endIndex = size;
  2764.         }
  2765.         if (startIndex > endIndex) {
  2766.             throw new StringIndexOutOfBoundsException("end < start");
  2767.         }
  2768.         return endIndex;
  2769.     }

  2770. }