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.lang3.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.Iterator;
  24. import java.util.List;
  25. import java.util.Objects;

  26. import org.apache.commons.lang3.ArrayUtils;
  27. import org.apache.commons.lang3.CharUtils;
  28. import org.apache.commons.lang3.ObjectUtils;
  29. import org.apache.commons.lang3.StringUtils;
  30. import org.apache.commons.lang3.builder.Builder;

  31. /**
  32.  * Builds a string from constituent parts providing a more flexible and powerful API
  33.  * than StringBuffer.
  34.  * <p>
  35.  * The main differences from StringBuffer/StringBuilder are:
  36.  * </p>
  37.  * <ul>
  38.  * <li>Not synchronized</li>
  39.  * <li>Not final</li>
  40.  * <li>Subclasses have direct access to character array</li>
  41.  * <li>Additional methods
  42.  *  <ul>
  43.  *   <li>appendWithSeparators - adds an array of values, with a separator</li>
  44.  *   <li>appendPadding - adds a length padding characters</li>
  45.  *   <li>appendFixedLength - adds a fixed width field to the builder</li>
  46.  *   <li>toCharArray/getChars - simpler ways to get a range of the character array</li>
  47.  *   <li>delete - delete char or string</li>
  48.  *   <li>replace - search and replace for a char or string</li>
  49.  *   <li>leftString/rightString/midString - substring without exceptions</li>
  50.  *   <li>contains - whether the builder contains a char or string</li>
  51.  *   <li>size/clear/isEmpty - collections style API methods</li>
  52.  *  </ul>
  53.  * </li>
  54.  * <li>Views
  55.  *  <ul>
  56.  *   <li>asTokenizer - uses the internal buffer as the source of a StrTokenizer</li>
  57.  *   <li>asReader - uses the internal buffer as the source of a Reader</li>
  58.  *   <li>asWriter - allows a Writer to write directly to the internal buffer</li>
  59.  *  </ul>
  60.  * </li>
  61.  * </ul>
  62.  * <p>
  63.  * The aim has been to provide an API that mimics very closely what StringBuffer
  64.  * provides, but with additional methods. It should be noted that some edge cases,
  65.  * with invalid indices or null input, have been altered - see individual methods.
  66.  * The biggest of these changes is that by default, null will not output the text
  67.  * 'null'. This can be controlled by a property, {@link #setNullText(String)}.
  68.  * </p>
  69.  * <p>
  70.  * Prior to 3.0, this class implemented Cloneable but did not implement the
  71.  * clone method so could not be used. From 3.0 onwards it no longer implements
  72.  * the interface.
  73.  * </p>
  74.  *
  75.  * @since 2.2
  76.  * @deprecated As of 3.6, use Apache Commons Text
  77.  * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/TextStringBuilder.html">
  78.  * TextStringBuilder</a> instead
  79.  */
  80. @Deprecated
  81. public class StrBuilder implements CharSequence, Appendable, Serializable, Builder<String> {

  82.     /**
  83.      * Inner class to allow StrBuilder to operate as a reader.
  84.      */
  85.     final class StrBuilderReader extends Reader {
  86.         /** The current stream position. */
  87.         private int pos;
  88.         /** The last mark position. */
  89.         private int mark;

  90.         /**
  91.          * Default constructor.
  92.          */
  93.         StrBuilderReader() {
  94.         }

  95.         /** {@inheritDoc} */
  96.         @Override
  97.         public void close() {
  98.             // do nothing
  99.         }

  100.         /** {@inheritDoc} */
  101.         @Override
  102.         public void mark(final int readAheadLimit) {
  103.             mark = pos;
  104.         }

  105.         /** {@inheritDoc} */
  106.         @Override
  107.         public boolean markSupported() {
  108.             return true;
  109.         }

  110.         /** {@inheritDoc} */
  111.         @Override
  112.         public int read() {
  113.             if (!ready()) {
  114.                 return -1;
  115.             }
  116.             return StrBuilder.this.charAt(pos++);
  117.         }

  118.         /** {@inheritDoc} */
  119.         @Override
  120.         public int read(final char[] b, final int off, int len) {
  121.             if (off < 0 || len < 0 || off > b.length ||
  122.                     off + len > b.length || off + len < 0) {
  123.                 throw new IndexOutOfBoundsException();
  124.             }
  125.             if (len == 0) {
  126.                 return 0;
  127.             }
  128.             if (pos >= StrBuilder.this.size()) {
  129.                 return -1;
  130.             }
  131.             if (pos + len > size()) {
  132.                 len = StrBuilder.this.size() - pos;
  133.             }
  134.             StrBuilder.this.getChars(pos, pos + len, b, off);
  135.             pos += len;
  136.             return len;
  137.         }

  138.         /** {@inheritDoc} */
  139.         @Override
  140.         public boolean ready() {
  141.             return pos < StrBuilder.this.size();
  142.         }

  143.         /** {@inheritDoc} */
  144.         @Override
  145.         public void reset() {
  146.             pos = mark;
  147.         }

  148.         /** {@inheritDoc} */
  149.         @Override
  150.         public long skip(long n) {
  151.             if (pos + n > StrBuilder.this.size()) {
  152.                 n = StrBuilder.this.size() - pos;
  153.             }
  154.             if (n < 0) {
  155.                 return 0;
  156.             }
  157.             pos = Math.addExact(pos, Math.toIntExact(n));
  158.             return n;
  159.         }
  160.     }

  161.     /**
  162.      * Inner class to allow StrBuilder to operate as a tokenizer.
  163.      */
  164.     final class StrBuilderTokenizer extends StrTokenizer {

  165.         /**
  166.          * Default constructor.
  167.          */
  168.         StrBuilderTokenizer() {
  169.         }

  170.         /** {@inheritDoc} */
  171.         @Override
  172.         public String getContent() {
  173.             final String str = super.getContent();
  174.             if (str == null) {
  175.                 return StrBuilder.this.toString();
  176.             }
  177.             return str;
  178.         }

  179.         /** {@inheritDoc} */
  180.         @Override
  181.         protected List<String> tokenize(final char[] chars, final int offset, final int count) {
  182.             if (chars == null) {
  183.                 return super.tokenize(StrBuilder.this.buffer, 0, StrBuilder.this.size());
  184.             }
  185.             return super.tokenize(chars, offset, count);
  186.         }
  187.     }

  188.     /**
  189.      * Inner class to allow StrBuilder to operate as a writer.
  190.      */
  191.     final class StrBuilderWriter extends Writer {

  192.         /**
  193.          * Default constructor.
  194.          */
  195.         StrBuilderWriter() {
  196.         }

  197.         /** {@inheritDoc} */
  198.         @Override
  199.         public void close() {
  200.             // do nothing
  201.         }

  202.         /** {@inheritDoc} */
  203.         @Override
  204.         public void flush() {
  205.             // do nothing
  206.         }

  207.         /** {@inheritDoc} */
  208.         @Override
  209.         public void write(final char[] cbuf) {
  210.             StrBuilder.this.append(cbuf);
  211.         }

  212.         /** {@inheritDoc} */
  213.         @Override
  214.         public void write(final char[] cbuf, final int off, final int len) {
  215.             StrBuilder.this.append(cbuf, off, len);
  216.         }

  217.         /** {@inheritDoc} */
  218.         @Override
  219.         public void write(final int c) {
  220.             StrBuilder.this.append((char) c);
  221.         }

  222.         /** {@inheritDoc} */
  223.         @Override
  224.         public void write(final String str) {
  225.             StrBuilder.this.append(str);
  226.         }

  227.         /** {@inheritDoc} */
  228.         @Override
  229.         public void write(final String str, final int off, final int len) {
  230.             StrBuilder.this.append(str, off, len);
  231.         }
  232.     }
  233.     /**
  234.      * The extra capacity for new builders.
  235.      */
  236.     static final int CAPACITY = 32;
  237.     /**
  238.      * Required for serialization support.
  239.      *
  240.      * @see java.io.Serializable
  241.      */
  242.     private static final long serialVersionUID = 7628716375283629643L;
  243.     /** Internal data storage. */
  244.     protected char[] buffer; // TODO make private?

  245.     /** Current size of the buffer. */
  246.     protected int size; // TODO make private?

  247.     /**
  248.      * The new line, {@code null} means use the system default from {@link System#lineSeparator()}.
  249.      */
  250.     private String newLine;

  251.     /** The null text. */
  252.     private String nullText;

  253.     /**
  254.      * Constructor that creates an empty builder initial capacity 32 characters.
  255.      */
  256.     public StrBuilder() {
  257.         this(CAPACITY);
  258.     }

  259.     /**
  260.      * Constructor that creates an empty builder the specified initial capacity.
  261.      *
  262.      * @param initialCapacity  the initial capacity, zero or less will be converted to 32
  263.      */
  264.     public StrBuilder(int initialCapacity) {
  265.         if (initialCapacity <= 0) {
  266.             initialCapacity = CAPACITY;
  267.         }
  268.         buffer = new char[initialCapacity];
  269.     }

  270.     /**
  271.      * Constructor that creates a builder from the string, allocating
  272.      * 32 extra characters for growth.
  273.      *
  274.      * @param str  the string to copy, null treated as blank string
  275.      */
  276.     public StrBuilder(final String str) {
  277.         if (str == null) {
  278.             buffer = new char[CAPACITY];
  279.         } else {
  280.             buffer = new char[str.length() + CAPACITY];
  281.             append(str);
  282.         }
  283.     }

  284.     /**
  285.      * Appends a boolean value to the string builder.
  286.      *
  287.      * @param value  the value to append
  288.      * @return this, to enable chaining
  289.      */
  290.     public StrBuilder append(final boolean value) {
  291.         if (value) {
  292.             ensureCapacity(size + 4);
  293.             buffer[size++] = 't';
  294.             buffer[size++] = 'r';
  295.             buffer[size++] = 'u';
  296.         } else {
  297.             ensureCapacity(size + 5);
  298.             buffer[size++] = 'f';
  299.             buffer[size++] = 'a';
  300.             buffer[size++] = 'l';
  301.             buffer[size++] = 's';
  302.         }
  303.         buffer[size++] = 'e';
  304.         return this;
  305.     }

  306.     /**
  307.      * Appends a char value to the string builder.
  308.      *
  309.      * @param ch  the value to append
  310.      * @return this, to enable chaining
  311.      * @since 3.0
  312.      */
  313.     @Override
  314.     public StrBuilder append(final char ch) {
  315.         final int len = length();
  316.         ensureCapacity(len + 1);
  317.         buffer[size++] = ch;
  318.         return this;
  319.     }

  320.     /**
  321.      * Appends a char array to the string builder.
  322.      * Appending null will call {@link #appendNull()}.
  323.      *
  324.      * @param chars  the char array to append
  325.      * @return this, to enable chaining
  326.      */
  327.     public StrBuilder append(final char[] chars) {
  328.         if (chars == null) {
  329.             return appendNull();
  330.         }
  331.         final int strLen = chars.length;
  332.         if (strLen > 0) {
  333.             final int len = length();
  334.             ensureCapacity(len + strLen);
  335.             System.arraycopy(chars, 0, buffer, len, strLen);
  336.             size += strLen;
  337.         }
  338.         return this;
  339.     }

  340.     /**
  341.      * Appends a char array to the string builder.
  342.      * Appending null will call {@link #appendNull()}.
  343.      *
  344.      * @param chars  the char array to append
  345.      * @param startIndex  the start index, inclusive, must be valid
  346.      * @param length  the length to append, must be valid
  347.      * @return this, to enable chaining
  348.      */
  349.     public StrBuilder append(final char[] chars, final int startIndex, final int length) {
  350.         if (chars == null) {
  351.             return appendNull();
  352.         }
  353.         if (startIndex < 0 || startIndex > chars.length) {
  354.             throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length);
  355.         }
  356.         if (length < 0 || startIndex + length > chars.length) {
  357.             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
  358.         }
  359.         if (length > 0) {
  360.             final int len = length();
  361.             ensureCapacity(len + length);
  362.             System.arraycopy(chars, startIndex, buffer, len, length);
  363.             size += length;
  364.         }
  365.         return this;
  366.     }

  367.     /**
  368.      * Appends the contents of a char buffer to this string builder.
  369.      * Appending null will call {@link #appendNull()}.
  370.      *
  371.      * @param buf  the char buffer to append
  372.      * @return this, to enable chaining
  373.      * @since 3.4
  374.      */
  375.     public StrBuilder append(final CharBuffer buf) {
  376.         if (buf == null) {
  377.             return appendNull();
  378.         }
  379.         if (buf.hasArray()) {
  380.             final int length = buf.remaining();
  381.             final int len = length();
  382.             ensureCapacity(len + length);
  383.             System.arraycopy(buf.array(), buf.arrayOffset() + buf.position(), buffer, len, length);
  384.             size += length;
  385.         } else {
  386.             append(buf.toString());
  387.         }
  388.         return this;
  389.     }

  390.     /**
  391.      * Appends the contents of a char buffer to this string builder.
  392.      * Appending null will call {@link #appendNull()}.
  393.      *
  394.      * @param buf  the char buffer to append
  395.      * @param startIndex  the start index, inclusive, must be valid
  396.      * @param length  the length to append, must be valid
  397.      * @return this, to enable chaining
  398.      * @since 3.4
  399.      */
  400.     public StrBuilder append(final CharBuffer buf, final int startIndex, final int length) {
  401.         if (buf == null) {
  402.             return appendNull();
  403.         }
  404.         if (buf.hasArray()) {
  405.             final int totalLength = buf.remaining();
  406.             if (startIndex < 0 || startIndex > totalLength) {
  407.                 throw new StringIndexOutOfBoundsException("startIndex must be valid");
  408.             }
  409.             if (length < 0 || startIndex + length > totalLength) {
  410.                 throw new StringIndexOutOfBoundsException("length must be valid");
  411.             }
  412.             final int len = length();
  413.             ensureCapacity(len + length);
  414.             System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length);
  415.             size += length;
  416.         } else {
  417.             append(buf.toString(), startIndex, length);
  418.         }
  419.         return this;
  420.     }

  421.     /**
  422.      * Appends a CharSequence to this string builder.
  423.      * Appending null will call {@link #appendNull()}.
  424.      *
  425.      * @param seq  the CharSequence to append
  426.      * @return this, to enable chaining
  427.      * @since 3.0
  428.      */
  429.     @Override
  430.     public StrBuilder append(final CharSequence seq) {
  431.         if (seq == null) {
  432.             return appendNull();
  433.         }
  434.         if (seq instanceof StrBuilder) {
  435.             return append((StrBuilder) seq);
  436.         }
  437.         if (seq instanceof StringBuilder) {
  438.             return append((StringBuilder) seq);
  439.         }
  440.         if (seq instanceof StringBuffer) {
  441.             return append((StringBuffer) seq);
  442.         }
  443.         if (seq instanceof CharBuffer) {
  444.             return append((CharBuffer) seq);
  445.         }
  446.         return append(seq.toString());
  447.     }

  448.     /**
  449.      * Appends part of a CharSequence to this string builder.
  450.      * Appending null will call {@link #appendNull()}.
  451.      *
  452.      * @param seq  the CharSequence to append
  453.      * @param startIndex  the start index, inclusive, must be valid
  454.      * @param length  the length to append, must be valid
  455.      * @return this, to enable chaining
  456.      * @since 3.0
  457.      */
  458.     @Override
  459.     public StrBuilder append(final CharSequence seq, final int startIndex, final int length) {
  460.         if (seq == null) {
  461.             return appendNull();
  462.         }
  463.         return append(seq.toString(), startIndex, length);
  464.     }

  465.     /**
  466.      * Appends a double value to the string builder using {@code String.valueOf}.
  467.      *
  468.      * @param value  the value to append
  469.      * @return this, to enable chaining
  470.      */
  471.     public StrBuilder append(final double value) {
  472.         return append(String.valueOf(value));
  473.     }

  474.     /**
  475.      * Appends a float value to the string builder using {@code String.valueOf}.
  476.      *
  477.      * @param value  the value to append
  478.      * @return this, to enable chaining
  479.      */
  480.     public StrBuilder append(final float value) {
  481.         return append(String.valueOf(value));
  482.     }

  483.     /**
  484.      * Appends an int value to the string builder using {@code String.valueOf}.
  485.      *
  486.      * @param value  the value to append
  487.      * @return this, to enable chaining
  488.      */
  489.     public StrBuilder append(final int value) {
  490.         return append(String.valueOf(value));
  491.     }

  492.     /**
  493.      * Appends a long value to the string builder using {@code String.valueOf}.
  494.      *
  495.      * @param value  the value to append
  496.      * @return this, to enable chaining
  497.      */
  498.     public StrBuilder append(final long value) {
  499.         return append(String.valueOf(value));
  500.     }

  501.     /**
  502.      * Appends an object to this string builder.
  503.      * Appending null will call {@link #appendNull()}.
  504.      *
  505.      * @param obj  the object to append
  506.      * @return this, to enable chaining
  507.      */
  508.     public StrBuilder append(final Object obj) {
  509.         if (obj == null) {
  510.             return appendNull();
  511.         }
  512.         if (obj instanceof CharSequence) {
  513.             return append((CharSequence) obj);
  514.         }
  515.         return append(obj.toString());
  516.     }

  517.     /**
  518.      * Appends another string builder to this string builder.
  519.      * Appending null will call {@link #appendNull()}.
  520.      *
  521.      * @param str  the string builder to append
  522.      * @return this, to enable chaining
  523.      */
  524.     public StrBuilder append(final StrBuilder str) {
  525.         if (str == null) {
  526.             return appendNull();
  527.         }
  528.         final int strLen = str.length();
  529.         if (strLen > 0) {
  530.             final int len = length();
  531.             ensureCapacity(len + strLen);
  532.             System.arraycopy(str.buffer, 0, buffer, len, strLen);
  533.             size += strLen;
  534.         }
  535.         return this;
  536.     }

  537.     /**
  538.      * Appends part of a string builder to this string builder.
  539.      * Appending null will call {@link #appendNull()}.
  540.      *
  541.      * @param str  the string to append
  542.      * @param startIndex  the start index, inclusive, must be valid
  543.      * @param length  the length to append, must be valid
  544.      * @return this, to enable chaining
  545.      */
  546.     public StrBuilder append(final StrBuilder str, final int startIndex, final int length) {
  547.         if (str == null) {
  548.             return appendNull();
  549.         }
  550.         if (startIndex < 0 || startIndex > str.length()) {
  551.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  552.         }
  553.         if (length < 0 || startIndex + length > str.length()) {
  554.             throw new StringIndexOutOfBoundsException("length must be valid");
  555.         }
  556.         if (length > 0) {
  557.             final int len = length();
  558.             ensureCapacity(len + length);
  559.             str.getChars(startIndex, startIndex + length, buffer, len);
  560.             size += length;
  561.         }
  562.         return this;
  563.     }

  564.     /**
  565.      * Appends a string to this string builder.
  566.      * Appending null will call {@link #appendNull()}.
  567.      *
  568.      * @param str  the string to append
  569.      * @return this, to enable chaining
  570.      */
  571.     public StrBuilder append(final String str) {
  572.         if (str == null) {
  573.             return appendNull();
  574.         }
  575.         final int strLen = str.length();
  576.         if (strLen > 0) {
  577.             final int len = length();
  578.             ensureCapacity(len + strLen);
  579.             str.getChars(0, strLen, buffer, len);
  580.             size += strLen;
  581.         }
  582.         return this;
  583.     }

  584.     /**
  585.      * Appends part of a string to this string builder.
  586.      * Appending null will call {@link #appendNull()}.
  587.      *
  588.      * @param str  the string to append
  589.      * @param startIndex  the start index, inclusive, must be valid
  590.      * @param length  the length to append, must be valid
  591.      * @return this, to enable chaining
  592.      */
  593.     public StrBuilder append(final String str, final int startIndex, final int length) {
  594.         if (str == null) {
  595.             return appendNull();
  596.         }
  597.         if (startIndex < 0 || startIndex > str.length()) {
  598.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  599.         }
  600.         if (length < 0 || startIndex + length > str.length()) {
  601.             throw new StringIndexOutOfBoundsException("length must be valid");
  602.         }
  603.         if (length > 0) {
  604.             final int len = length();
  605.             ensureCapacity(len + length);
  606.             str.getChars(startIndex, startIndex + length, buffer, len);
  607.             size += length;
  608.         }
  609.         return this;
  610.     }

  611.     /**
  612.      * Calls {@link String#format(String, Object...)} and appends the result.
  613.      *
  614.      * @param format the format string
  615.      * @param objs the objects to use in the format string
  616.      * @return {@code this} to enable chaining
  617.      * @see String#format(String, Object...)
  618.      * @since 3.2
  619.      */
  620.     public StrBuilder append(final String format, final Object... objs) {
  621.         return append(String.format(format, objs));
  622.     }

  623.     /**
  624.      * Appends a string buffer to this string builder.
  625.      * Appending null will call {@link #appendNull()}.
  626.      *
  627.      * @param str  the string buffer to append
  628.      * @return this, to enable chaining
  629.      */
  630.     public StrBuilder append(final StringBuffer str) {
  631.         if (str == null) {
  632.             return appendNull();
  633.         }
  634.         final int strLen = str.length();
  635.         if (strLen > 0) {
  636.             final int len = length();
  637.             ensureCapacity(len + strLen);
  638.             str.getChars(0, strLen, buffer, len);
  639.             size += strLen;
  640.         }
  641.         return this;
  642.     }

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

  670.     /**
  671.      * Appends a StringBuilder to this string builder.
  672.      * Appending null will call {@link #appendNull()}.
  673.      *
  674.      * @param str the StringBuilder to append
  675.      * @return this, to enable chaining
  676.      * @since 3.2
  677.      */
  678.     public StrBuilder append(final StringBuilder str) {
  679.         if (str == null) {
  680.             return appendNull();
  681.         }
  682.         final int strLen = str.length();
  683.         if (strLen > 0) {
  684.             final int len = length();
  685.             ensureCapacity(len + strLen);
  686.             str.getChars(0, strLen, buffer, len);
  687.             size += strLen;
  688.         }
  689.         return this;
  690.     }

  691.     /**
  692.      * Appends part of a StringBuilder to this string builder.
  693.      * Appending null will call {@link #appendNull()}.
  694.      *
  695.      * @param str the StringBuilder to append
  696.      * @param startIndex the start index, inclusive, must be valid
  697.      * @param length the length to append, must be valid
  698.      * @return this, to enable chaining
  699.      * @since 3.2
  700.      */
  701.     public StrBuilder append(final StringBuilder str, final int startIndex, final int length) {
  702.         if (str == null) {
  703.             return appendNull();
  704.         }
  705.         if (startIndex < 0 || startIndex > str.length()) {
  706.             throw new StringIndexOutOfBoundsException("startIndex must be valid");
  707.         }
  708.         if (length < 0 || startIndex + length > str.length()) {
  709.             throw new StringIndexOutOfBoundsException("length must be valid");
  710.         }
  711.         if (length > 0) {
  712.             final int len = length();
  713.             ensureCapacity(len + length);
  714.             str.getChars(startIndex, startIndex + length, buffer, len);
  715.             size += length;
  716.         }
  717.         return this;
  718.     }

  719.     /**
  720.      * Appends each item in an iterable to the builder without any separators.
  721.      * Appending a null iterable will have no effect.
  722.      * Each object is appended using {@link #append(Object)}.
  723.      *
  724.      * @param iterable  the iterable to append
  725.      * @return this, to enable chaining
  726.      * @since 2.3
  727.      */
  728.     public StrBuilder appendAll(final Iterable<?> iterable) {
  729.         if (iterable != null) {
  730.             iterable.forEach(this::append);
  731.         }
  732.         return this;
  733.     }

  734.     /**
  735.      * Appends each item in an iterator to the builder without any separators.
  736.      * Appending a null iterator will have no effect.
  737.      * Each object is appended using {@link #append(Object)}.
  738.      *
  739.      * @param it  the iterator to append
  740.      * @return this, to enable chaining
  741.      * @since 2.3
  742.      */
  743.     public StrBuilder appendAll(final Iterator<?> it) {
  744.         if (it != null) {
  745.             it.forEachRemaining(this::append);
  746.         }
  747.         return this;
  748.     }

  749.     /**
  750.      * Appends each item in an array to the builder without any separators.
  751.      * Appending a null array will have no effect.
  752.      * Each object is appended using {@link #append(Object)}.
  753.      *
  754.      * @param <T>  the element type
  755.      * @param array  the array to append
  756.      * @return this, to enable chaining
  757.      * @since 2.3
  758.      */
  759.     public <T> StrBuilder appendAll(@SuppressWarnings("unchecked") final T... array) {
  760.         /*
  761.          * @SuppressWarnings used to hide warning about vararg usage. We cannot
  762.          * use @SafeVarargs, since this method is not final. Using @SuppressWarnings
  763.          * is fine, because it isn't inherited by subclasses, so each subclass must
  764.          * vouch for itself whether its use of 'array' is safe.
  765.          */
  766.         if (ArrayUtils.isNotEmpty(array)) {
  767.             for (final Object element : array) {
  768.                 append(element);
  769.             }
  770.         }
  771.         return this;
  772.     }

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

  786.     /**
  787.      * Appends an object to the builder padding on the left to a fixed width.
  788.      * The {@code toString} of the object is used.
  789.      * If the object is larger than the length, the left-hand side side is lost.
  790.      * If the object is null, the null text value is used.
  791.      *
  792.      * @param obj  the object to append, null uses null text
  793.      * @param width  the fixed field width, zero or negative has no effect
  794.      * @param padChar  the pad character to use
  795.      * @return this, to enable chaining
  796.      */
  797.     public StrBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) {
  798.         if (width > 0) {
  799.             ensureCapacity(size + width);
  800.             String str = ObjectUtils.toString(obj, this::getNullText);
  801.             if (str == null) {
  802.                 str = StringUtils.EMPTY;
  803.             }
  804.             final int strLen = str.length();
  805.             if (strLen >= width) {
  806.                 str.getChars(strLen - width, strLen, buffer, size);
  807.             } else {
  808.                 final int padLen = width - strLen;
  809.                 for (int i = 0; i < padLen; i++) {
  810.                     buffer[size + i] = padChar;
  811.                 }
  812.                 str.getChars(0, strLen, buffer, size + padLen);
  813.             }
  814.             size += width;
  815.         }
  816.         return this;
  817.     }

  818.     /**
  819.      * Appends an object to the builder padding on the right to a fixed length.
  820.      * The {@code String.valueOf} of the {@code int} value is used.
  821.      * If the object is larger than the length, the right-hand side side is lost.
  822.      *
  823.      * @param value  the value to append
  824.      * @param width  the fixed field width, zero or negative has no effect
  825.      * @param padChar  the pad character to use
  826.      * @return this, to enable chaining
  827.      */
  828.     public StrBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) {
  829.         return appendFixedWidthPadRight(String.valueOf(value), width, padChar);
  830.     }

  831.     /**
  832.      * Appends an object to the builder padding on the right to a fixed length.
  833.      * The {@code toString} of the object is used.
  834.      * If the object is larger than the length, the right-hand side side is lost.
  835.      * If the object is null, null text value is used.
  836.      *
  837.      * @param obj  the object to append, null uses null text
  838.      * @param width  the fixed field width, zero or negative has no effect
  839.      * @param padChar  the pad character to use
  840.      * @return this, to enable chaining
  841.      */
  842.     public StrBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) {
  843.         if (width > 0) {
  844.             ensureCapacity(size + width);
  845.             String str = ObjectUtils.toString(obj, this::getNullText);
  846.             if (str == null) {
  847.                 str = StringUtils.EMPTY;
  848.             }
  849.             final int strLen = str.length();
  850.             if (strLen >= width) {
  851.                 str.getChars(0, width, buffer, size);
  852.             } else {
  853.                 final int padLen = width - strLen;
  854.                 str.getChars(0, strLen, buffer, size);
  855.                 for (int i = 0; i < padLen; i++) {
  856.                     buffer[size + strLen + i] = padChar;
  857.                 }
  858.             }
  859.             size += width;
  860.         }
  861.         return this;
  862.     }

  863.     /**
  864.      * Appends a boolean value followed by a new line to the string builder.
  865.      *
  866.      * @param value  the value to append
  867.      * @return this, to enable chaining
  868.      * @since 2.3
  869.      */
  870.     public StrBuilder appendln(final boolean value) {
  871.         return append(value).appendNewLine();
  872.     }

  873.     /**
  874.      * Appends a char value followed by a new line to the string builder.
  875.      *
  876.      * @param ch  the value to append
  877.      * @return this, to enable chaining
  878.      * @since 2.3
  879.      */
  880.     public StrBuilder appendln(final char ch) {
  881.         return append(ch).appendNewLine();
  882.     }

  883.     /**
  884.      * Appends a char array followed by a new line to the string builder.
  885.      * Appending null will call {@link #appendNull()}.
  886.      *
  887.      * @param chars  the char array to append
  888.      * @return this, to enable chaining
  889.      * @since 2.3
  890.      */
  891.     public StrBuilder appendln(final char[] chars) {
  892.         return append(chars).appendNewLine();
  893.     }

  894.     /**
  895.      * Appends a char array followed by a new line to the string builder.
  896.      * Appending null will call {@link #appendNull()}.
  897.      *
  898.      * @param chars  the char array to append
  899.      * @param startIndex  the start index, inclusive, must be valid
  900.      * @param length  the length to append, must be valid
  901.      * @return this, to enable chaining
  902.      * @since 2.3
  903.      */
  904.     public StrBuilder appendln(final char[] chars, final int startIndex, final int length) {
  905.         return append(chars, startIndex, length).appendNewLine();
  906.     }

  907.     /**
  908.      * Appends a double value followed by a new line to the string builder using {@code String.valueOf}.
  909.      *
  910.      * @param value  the value to append
  911.      * @return this, to enable chaining
  912.      * @since 2.3
  913.      */
  914.     public StrBuilder appendln(final double value) {
  915.         return append(value).appendNewLine();
  916.     }

  917.     /**
  918.      * Appends a float value followed by a new line to the string builder using {@code String.valueOf}.
  919.      *
  920.      * @param value  the value to append
  921.      * @return this, to enable chaining
  922.      * @since 2.3
  923.      */
  924.     public StrBuilder appendln(final float value) {
  925.         return append(value).appendNewLine();
  926.     }

  927.     /**
  928.      * Appends an int value followed by a new line to the string builder using {@code String.valueOf}.
  929.      *
  930.      * @param value  the value to append
  931.      * @return this, to enable chaining
  932.      * @since 2.3
  933.      */
  934.     public StrBuilder appendln(final int value) {
  935.         return append(value).appendNewLine();
  936.     }

  937.     /**
  938.      * Appends a long value followed by a new line to the string builder using {@code String.valueOf}.
  939.      *
  940.      * @param value  the value to append
  941.      * @return this, to enable chaining
  942.      * @since 2.3
  943.      */
  944.     public StrBuilder appendln(final long value) {
  945.         return append(value).appendNewLine();
  946.     }

  947.     /**
  948.      * Appends an object followed by a new line to this string builder.
  949.      * Appending null will call {@link #appendNull()}.
  950.      *
  951.      * @param obj  the object to append
  952.      * @return this, to enable chaining
  953.      * @since 2.3
  954.      */
  955.     public StrBuilder appendln(final Object obj) {
  956.         return append(obj).appendNewLine();
  957.     }

  958.     /**
  959.      * Appends another string builder followed by a new line to this string builder.
  960.      * Appending null will call {@link #appendNull()}.
  961.      *
  962.      * @param str  the string builder to append
  963.      * @return this, to enable chaining
  964.      * @since 2.3
  965.      */
  966.     public StrBuilder appendln(final StrBuilder str) {
  967.         return append(str).appendNewLine();
  968.     }

  969.     /**
  970.      * Appends part of a string builder followed by a new line to this string builder.
  971.      * 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 this, to enable chaining
  977.      * @since 2.3
  978.      */
  979.     public StrBuilder appendln(final StrBuilder str, final int startIndex, final int length) {
  980.         return append(str, startIndex, length).appendNewLine();
  981.     }

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

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

  1006.     /**
  1007.      * Calls {@link String#format(String, Object...)} and appends the result.
  1008.      *
  1009.      * @param format the format string
  1010.      * @param objs the objects to use in the format string
  1011.      * @return {@code this} to enable chaining
  1012.      * @see String#format(String, Object...)
  1013.      * @since 3.2
  1014.      */
  1015.     public StrBuilder appendln(final String format, final Object... objs) {
  1016.         return append(format, objs).appendNewLine();
  1017.     }

  1018.     /**
  1019.      * Appends a string buffer followed by a new line to this string builder.
  1020.      * Appending null will call {@link #appendNull()}.
  1021.      *
  1022.      * @param str  the string buffer to append
  1023.      * @return this, to enable chaining
  1024.      * @since 2.3
  1025.      */
  1026.     public StrBuilder appendln(final StringBuffer str) {
  1027.         return append(str).appendNewLine();
  1028.     }

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

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

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

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

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

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

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

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

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

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

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

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

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

  1302.     /**
  1303.      * Appends an iterable placing separators between each value, but
  1304.      * not before the first or after the last.
  1305.      * Appending a null iterable will have no effect.
  1306.      * Each object is appended using {@link #append(Object)}.
  1307.      *
  1308.      * @param iterable  the iterable to append
  1309.      * @param separator  the separator to use, null means no separator
  1310.      * @return this, to enable chaining
  1311.      */
  1312.     public StrBuilder appendWithSeparators(final Iterable<?> iterable, final String separator) {
  1313.         if (iterable != null) {
  1314.             final String sep = Objects.toString(separator, "");
  1315.             final Iterator<?> it = iterable.iterator();
  1316.             while (it.hasNext()) {
  1317.                 append(it.next());
  1318.                 if (it.hasNext()) {
  1319.                     append(sep);
  1320.                 }
  1321.             }
  1322.         }
  1323.         return this;
  1324.     }

  1325.     /**
  1326.      * Appends an iterator placing separators between each value, but
  1327.      * not before the first or after the last.
  1328.      * Appending a null iterator will have no effect.
  1329.      * Each object is appended using {@link #append(Object)}.
  1330.      *
  1331.      * @param it  the iterator to append
  1332.      * @param separator  the separator to use, null means no separator
  1333.      * @return this, to enable chaining
  1334.      */
  1335.     public StrBuilder appendWithSeparators(final Iterator<?> it, final String separator) {
  1336.         if (it != null) {
  1337.             final String sep = Objects.toString(separator, "");
  1338.             while (it.hasNext()) {
  1339.                 append(it.next());
  1340.                 if (it.hasNext()) {
  1341.                     append(sep);
  1342.                 }
  1343.             }
  1344.         }
  1345.         return this;
  1346.     }

  1347.     /**
  1348.      * Appends an array placing separators between each value, but
  1349.      * not before the first or after the last.
  1350.      * Appending a null array will have no effect.
  1351.      * Each object is appended using {@link #append(Object)}.
  1352.      *
  1353.      * @param array  the array to append
  1354.      * @param separator  the separator to use, null means no separator
  1355.      * @return this, to enable chaining
  1356.      */
  1357.     public StrBuilder appendWithSeparators(final Object[] array, final String separator) {
  1358.         if (array != null && array.length > 0) {
  1359.             final String sep = Objects.toString(separator, "");
  1360.             append(array[0]);
  1361.             for (int i = 1; i < array.length; i++) {
  1362.                 append(sep);
  1363.                 append(array[i]);
  1364.             }
  1365.         }
  1366.         return this;
  1367.     }

  1368.     /**
  1369.      * Gets the contents of this builder as a Reader.
  1370.      * <p>
  1371.      * This method allows the contents of the builder to be read
  1372.      * using any standard method that expects a Reader.
  1373.      * </p>
  1374.      * <p>
  1375.      * To use, simply create a {@link StrBuilder}, populate it with
  1376.      * data, call {@code asReader}, and then read away.
  1377.      * </p>
  1378.      * <p>
  1379.      * The internal character array is shared between the builder and the reader.
  1380.      * This allows you to append to the builder after creating the reader,
  1381.      * and the changes will be picked up.
  1382.      * Note however, that no synchronization occurs, so you must perform
  1383.      * all operations with the builder and the reader in one thread.
  1384.      * </p>
  1385.      * <p>
  1386.      * The returned reader supports marking, and ignores the flush method.
  1387.      * </p>
  1388.      *
  1389.      * @return a reader that reads from this builder
  1390.      */
  1391.     public Reader asReader() {
  1392.         return new StrBuilderReader();
  1393.     }

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

  1434.     /**
  1435.      * Gets this builder as a Writer that can be written to.
  1436.      * <p>
  1437.      * This method allows you to populate the contents of the builder
  1438.      * using any standard method that takes a Writer.
  1439.      * </p>
  1440.      * <p>
  1441.      * To use, simply create a {@link StrBuilder},
  1442.      * call {@code asWriter}, and populate away. The data is available
  1443.      * at any time using the methods of the {@link StrBuilder}.
  1444.      * </p>
  1445.      * <p>
  1446.      * The internal character array is shared between the builder and the writer.
  1447.      * This allows you to intermix calls that append to the builder and
  1448.      * write using the writer and the changes will be occur correctly.
  1449.      * Note however, that no synchronization occurs, so you must perform
  1450.      * all operations with the builder and the writer in one thread.
  1451.      * </p>
  1452.      * <p>
  1453.      * The returned writer ignores the close and flush methods.
  1454.      * </p>
  1455.      *
  1456.      * @return a writer that populates this builder
  1457.      */
  1458.     public Writer asWriter() {
  1459.         return new StrBuilderWriter();
  1460.     }

  1461.     /**
  1462.      * Implement the {@link Builder} interface.
  1463.      * @return the builder as a String
  1464.      * @since 3.2
  1465.      * @see #toString()
  1466.      */
  1467.     @Override
  1468.     public String build() {
  1469.         return toString();
  1470.     }

  1471.     /**
  1472.      * Gets the current size of the internal character array buffer.
  1473.      *
  1474.      * @return the capacity
  1475.      */
  1476.     public int capacity() {
  1477.         return buffer.length;
  1478.     }

  1479.     /**
  1480.      * Gets the character at the specified index.
  1481.      *
  1482.      * @see #setCharAt(int, char)
  1483.      * @see #deleteCharAt(int)
  1484.      * @param index  the index to retrieve, must be valid
  1485.      * @return the character at the index
  1486.      * @throws IndexOutOfBoundsException if the index is invalid
  1487.      */
  1488.     @Override
  1489.     public char charAt(final int index) {
  1490.         if (index < 0 || index >= length()) {
  1491.             throw new StringIndexOutOfBoundsException(index);
  1492.         }
  1493.         return buffer[index];
  1494.     }

  1495.     /**
  1496.      * Clears the string builder (convenience Collections API style method).
  1497.      * <p>
  1498.      * This method does not reduce the size of the internal character buffer.
  1499.      * To do that, call {@code clear()} followed by {@link #minimizeCapacity()}.
  1500.      * </p>
  1501.      * <p>
  1502.      * This method is the same as {@link #setLength(int)} called with zero
  1503.      * and is provided to match the API of Collections.
  1504.      * </p>
  1505.      *
  1506.      * @return this, to enable chaining
  1507.      */
  1508.     public StrBuilder clear() {
  1509.         size = 0;
  1510.         return this;
  1511.     }

  1512.     /**
  1513.      * Checks if the string builder contains the specified char.
  1514.      *
  1515.      * @param ch  the character to find
  1516.      * @return true if the builder contains the character
  1517.      */
  1518.     public boolean contains(final char ch) {
  1519.         final char[] thisBuf = buffer;
  1520.         for (int i = 0; i < this.size; i++) {
  1521.             if (thisBuf[i] == ch) {
  1522.                 return true;
  1523.             }
  1524.         }
  1525.         return false;
  1526.     }

  1527.     /**
  1528.      * Checks if the string builder contains the specified string.
  1529.      *
  1530.      * @param str  the string to find
  1531.      * @return true if the builder contains the string
  1532.      */
  1533.     public boolean contains(final String str) {
  1534.         return indexOf(str, 0) >= 0;
  1535.     }

  1536.     /**
  1537.      * Checks if the string builder contains a string matched using the
  1538.      * specified matcher.
  1539.      * <p>
  1540.      * Matchers can be used to perform advanced searching behavior.
  1541.      * For example you could write a matcher to search for the character
  1542.      * 'a' followed by a number.
  1543.      * </p>
  1544.      *
  1545.      * @param matcher  the matcher to use, null returns -1
  1546.      * @return true if the matcher finds a match in the builder
  1547.      */
  1548.     public boolean contains(final StrMatcher matcher) {
  1549.         return indexOf(matcher, 0) >= 0;
  1550.     }
  1551.     /**
  1552.      * Deletes the characters between the two specified indices.
  1553.      *
  1554.      * @param startIndex  the start index, inclusive, must be valid
  1555.      * @param endIndex  the end index, exclusive, must be valid except
  1556.      *  that if too large it is treated as end of string
  1557.      * @return this, to enable chaining
  1558.      * @throws IndexOutOfBoundsException if the index is invalid
  1559.      */
  1560.     public StrBuilder delete(final int startIndex, int endIndex) {
  1561.         endIndex = validateRange(startIndex, endIndex);
  1562.         final int len = endIndex - startIndex;
  1563.         if (len > 0) {
  1564.             deleteImpl(startIndex, endIndex, len);
  1565.         }
  1566.         return this;
  1567.     }

  1568.     /**
  1569.      * Deletes the character wherever it occurs in the builder.
  1570.      *
  1571.      * @param ch  the character to delete
  1572.      * @return this, to enable chaining
  1573.      */
  1574.     public StrBuilder deleteAll(final char ch) {
  1575.         for (int i = 0; i < size; i++) {
  1576.             if (buffer[i] == ch) {
  1577.                 final int start = i;
  1578.                 while (++i < size) {
  1579.                     if (buffer[i] != ch) {
  1580.                         break;
  1581.                     }
  1582.                 }
  1583.                 final int len = i - start;
  1584.                 deleteImpl(start, i, len);
  1585.                 i -= len;
  1586.             }
  1587.         }
  1588.         return this;
  1589.     }

  1590.     /**
  1591.      * Deletes the string wherever it occurs in the builder.
  1592.      *
  1593.      * @param str  the string to delete, null causes no action
  1594.      * @return this, to enable chaining
  1595.      */
  1596.     public StrBuilder deleteAll(final String str) {
  1597.         final int len = StringUtils.length(str);
  1598.         if (len > 0) {
  1599.             int index = indexOf(str, 0);
  1600.             while (index >= 0) {
  1601.                 deleteImpl(index, index + len, len);
  1602.                 index = indexOf(str, index);
  1603.             }
  1604.         }
  1605.         return this;
  1606.     }

  1607.     /**
  1608.      * Deletes all parts of the builder that the matcher matches.
  1609.      * <p>
  1610.      * Matchers can be used to perform advanced deletion behavior.
  1611.      * For example you could write a matcher to delete all occurrences
  1612.      * where the character 'a' is followed by a number.
  1613.      * </p>
  1614.      *
  1615.      * @param matcher  the matcher to use to find the deletion, null causes no action
  1616.      * @return this, to enable chaining
  1617.      */
  1618.     public StrBuilder deleteAll(final StrMatcher matcher) {
  1619.         return replace(matcher, null, 0, size, -1);
  1620.     }

  1621.     /**
  1622.      * Deletes the character at the specified index.
  1623.      *
  1624.      * @see #charAt(int)
  1625.      * @see #setCharAt(int, char)
  1626.      * @param index  the index to delete
  1627.      * @return this, to enable chaining
  1628.      * @throws IndexOutOfBoundsException if the index is invalid
  1629.      */
  1630.     public StrBuilder deleteCharAt(final int index) {
  1631.         if (index < 0 || index >= size) {
  1632.             throw new StringIndexOutOfBoundsException(index);
  1633.         }
  1634.         deleteImpl(index, index + 1, 1);
  1635.         return this;
  1636.     }

  1637.     /**
  1638.      * Deletes the character wherever it occurs in the builder.
  1639.      *
  1640.      * @param ch  the character to delete
  1641.      * @return this, to enable chaining
  1642.      */
  1643.     public StrBuilder deleteFirst(final char ch) {
  1644.         for (int i = 0; i < size; i++) {
  1645.             if (buffer[i] == ch) {
  1646.                 deleteImpl(i, i + 1, 1);
  1647.                 break;
  1648.             }
  1649.         }
  1650.         return this;
  1651.     }

  1652.     /**
  1653.      * Deletes the string wherever it occurs in the builder.
  1654.      *
  1655.      * @param str  the string to delete, null causes no action
  1656.      * @return this, to enable chaining
  1657.      */
  1658.     public StrBuilder deleteFirst(final String str) {
  1659.         final int len = StringUtils.length(str);
  1660.         if (len > 0) {
  1661.             final int index = indexOf(str, 0);
  1662.             if (index >= 0) {
  1663.                 deleteImpl(index, index + len, len);
  1664.             }
  1665.         }
  1666.         return this;
  1667.     }

  1668.     /**
  1669.      * Deletes the first match within the builder using the specified matcher.
  1670.      * <p>
  1671.      * Matchers can be used to perform advanced deletion behavior.
  1672.      * For example you could write a matcher to delete
  1673.      * where the character 'a' is followed by a number.
  1674.      * </p>
  1675.      *
  1676.      * @param matcher  the matcher to use to find the deletion, null causes no action
  1677.      * @return this, to enable chaining
  1678.      */
  1679.     public StrBuilder deleteFirst(final StrMatcher matcher) {
  1680.         return replace(matcher, null, 0, size, 1);
  1681.     }

  1682.     /**
  1683.      * Internal method to delete a range without validation.
  1684.      *
  1685.      * @param startIndex  the start index, must be valid
  1686.      * @param endIndex  the end index (exclusive), must be valid
  1687.      * @param len  the length, must be valid
  1688.      * @throws IndexOutOfBoundsException if any index is invalid
  1689.      */
  1690.     private void deleteImpl(final int startIndex, final int endIndex, final int len) {
  1691.         System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex);
  1692.         size -= len;
  1693.     }

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

  1722.     /**
  1723.      * Checks the capacity and ensures that it is at least the size specified.
  1724.      *
  1725.      * @param capacity  the capacity to ensure
  1726.      * @return this, to enable chaining
  1727.      */
  1728.     public StrBuilder ensureCapacity(final int capacity) {
  1729.         if (capacity > buffer.length) {
  1730.             buffer = ArrayUtils.arraycopy(buffer, 0, 0, size, () -> new char[capacity * 2]);
  1731.         }
  1732.         return this;
  1733.     }

  1734.     /**
  1735.      * Checks the contents of this builder against another to see if they
  1736.      * contain the same character content.
  1737.      *
  1738.      * @param obj  the object to check, null returns false
  1739.      * @return true if the builders contain the same characters in the same order
  1740.      */
  1741.     @Override
  1742.     public boolean equals(final Object obj) {
  1743.         return obj instanceof StrBuilder && equals((StrBuilder) obj);
  1744.     }

  1745.     /**
  1746.      * Checks the contents of this builder against another to see if they
  1747.      * contain the same character content.
  1748.      *
  1749.      * @param other  the object to check, null returns false
  1750.      * @return true if the builders contain the same characters in the same order
  1751.      */
  1752.     public boolean equals(final StrBuilder other) {
  1753.         if (this == other) {
  1754.             return true;
  1755.         }
  1756.         if (other == null) {
  1757.             return false;
  1758.         }
  1759.         if (this.size != other.size) {
  1760.             return false;
  1761.         }
  1762.         final char[] thisBuf = this.buffer;
  1763.         final char[] otherBuf = other.buffer;
  1764.         for (int i = size - 1; i >= 0; i--) {
  1765.             if (thisBuf[i] != otherBuf[i]) {
  1766.                 return false;
  1767.             }
  1768.         }
  1769.         return true;
  1770.     }

  1771.     /**
  1772.      * Checks the contents of this builder against another to see if they
  1773.      * contain the same character content ignoring case.
  1774.      *
  1775.      * @param other  the object to check, null returns false
  1776.      * @return true if the builders contain the same characters in the same order
  1777.      */
  1778.     public boolean equalsIgnoreCase(final StrBuilder other) {
  1779.         if (this == other) {
  1780.             return true;
  1781.         }
  1782.         if (this.size != other.size) {
  1783.             return false;
  1784.         }
  1785.         final char[] thisBuf = this.buffer;
  1786.         final char[] otherBuf = other.buffer;
  1787.         for (int i = size - 1; i >= 0; i--) {
  1788.             final char c1 = thisBuf[i];
  1789.             final char c2 = otherBuf[i];
  1790.             if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) {
  1791.                 return false;
  1792.             }
  1793.         }
  1794.         return true;
  1795.     }

  1796.     /**
  1797.      * Copies the character array into the specified array.
  1798.      *
  1799.      * @param destination  the destination array, null will cause an array to be created
  1800.      * @return the input array, unless that was null or too small
  1801.      */
  1802.     public char[] getChars(char[] destination) {
  1803.         final int len = length();
  1804.         if (destination == null || destination.length < len) {
  1805.             destination = new char[len];
  1806.         }
  1807.         return ArrayUtils.arraycopy(buffer, 0, destination, 0, len);
  1808.     }

  1809.     /**
  1810.      * Copies the character array into the specified array.
  1811.      *
  1812.      * @param startIndex  first index to copy, inclusive, must be valid
  1813.      * @param endIndex  last index, exclusive, must be valid
  1814.      * @param destination  the destination array, must not be null or too small
  1815.      * @param destinationIndex  the index to start copying in destination
  1816.      * @throws NullPointerException if the array is null
  1817.      * @throws IndexOutOfBoundsException if any index is invalid
  1818.      */
  1819.     public void getChars(final int startIndex, final int endIndex, final char[] destination, final int destinationIndex) {
  1820.         if (startIndex < 0) {
  1821.             throw new StringIndexOutOfBoundsException(startIndex);
  1822.         }
  1823.         if (endIndex < 0 || endIndex > length()) {
  1824.             throw new StringIndexOutOfBoundsException(endIndex);
  1825.         }
  1826.         if (startIndex > endIndex) {
  1827.             throw new StringIndexOutOfBoundsException("end < start");
  1828.         }
  1829.         System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex);
  1830.     }

  1831.     /**
  1832.      * Gets the text to be appended when a {@link #appendNewLine() new line} is added.
  1833.      *
  1834.      * @return The new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
  1835.      */
  1836.     public String getNewLineText() {
  1837.         return newLine;
  1838.     }

  1839.     /**
  1840.      * Gets the text to be appended when null is added.
  1841.      *
  1842.      * @return the null text, null means no append
  1843.      */
  1844.     public String getNullText() {
  1845.         return nullText;
  1846.     }

  1847.     /**
  1848.      * Gets a suitable hash code for this builder.
  1849.      *
  1850.      * @return a hash code
  1851.      */
  1852.     @Override
  1853.     public int hashCode() {
  1854.         final char[] buf = buffer;
  1855.         int hash = 0;
  1856.         for (int i = size - 1; i >= 0; i--) {
  1857.             hash = 31 * hash + buf[i];
  1858.         }
  1859.         return hash;
  1860.     }

  1861.     /**
  1862.      * Searches the string builder to find the first reference to the specified char.
  1863.      *
  1864.      * @param ch  the character to find
  1865.      * @return the first index of the character, or -1 if not found
  1866.      */
  1867.     public int indexOf(final char ch) {
  1868.         return indexOf(ch, 0);
  1869.     }

  1870.     /**
  1871.      * Searches the string builder to find the first reference to the specified char.
  1872.      *
  1873.      * @param ch  the character to find
  1874.      * @param startIndex  the index to start at, invalid index rounded to edge
  1875.      * @return the first index of the character, or -1 if not found
  1876.      */
  1877.     public int indexOf(final char ch, int startIndex) {
  1878.         startIndex = Math.max(startIndex, 0);
  1879.         if (startIndex >= size) {
  1880.             return -1;
  1881.         }
  1882.         final char[] thisBuf = buffer;
  1883.         for (int i = startIndex; i < size; i++) {
  1884.             if (thisBuf[i] == ch) {
  1885.                 return i;
  1886.             }
  1887.         }
  1888.         return -1;
  1889.     }

  1890.     /**
  1891.      * Searches the string builder to find the first reference to the specified string.
  1892.      * <p>
  1893.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  1894.      * </p>
  1895.      *
  1896.      * @param str  the string to find, null returns -1
  1897.      * @return the first index of the string, or -1 if not found
  1898.      */
  1899.     public int indexOf(final String str) {
  1900.         return indexOf(str, 0);
  1901.     }

  1902.     /**
  1903.      * Searches the string builder to find the first reference to the specified
  1904.      * string starting searching from the given index.
  1905.      * <p>
  1906.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  1907.      * </p>
  1908.      *
  1909.      * @param str  the string to find, null returns -1
  1910.      * @param startIndex  the index to start at, invalid index rounded to edge
  1911.      * @return the first index of the string, or -1 if not found
  1912.      */
  1913.     public int indexOf(final String str, final int startIndex) {
  1914.         return StringUtils.indexOf(this, str, startIndex);
  1915.     }

  1916.     /**
  1917.      * Searches the string builder using the matcher to find the first match.
  1918.      * <p>
  1919.      * Matchers can be used to perform advanced searching behavior.
  1920.      * For example you could write a matcher to find the character 'a'
  1921.      * followed by a number.
  1922.      * </p>
  1923.      *
  1924.      * @param matcher  the matcher to use, null returns -1
  1925.      * @return the first index matched, or -1 if not found
  1926.      */
  1927.     public int indexOf(final StrMatcher matcher) {
  1928.         return indexOf(matcher, 0);
  1929.     }

  1930.     /**
  1931.      * Searches the string builder using the matcher to find the first
  1932.      * match searching from the given index.
  1933.      * <p>
  1934.      * Matchers can be used to perform advanced searching behavior.
  1935.      * For example you could write a matcher to find the character 'a'
  1936.      * followed by a number.
  1937.      * </p>
  1938.      *
  1939.      * @param matcher  the matcher to use, null returns -1
  1940.      * @param startIndex  the index to start at, invalid index rounded to edge
  1941.      * @return the first index matched, or -1 if not found
  1942.      */
  1943.     public int indexOf(final StrMatcher matcher, int startIndex) {
  1944.         startIndex = Math.max(startIndex, 0);
  1945.         if (matcher == null || startIndex >= size) {
  1946.             return -1;
  1947.         }
  1948.         final int len = size;
  1949.         final char[] buf = buffer;
  1950.         for (int i = startIndex; i < len; i++) {
  1951.             if (matcher.isMatch(buf, i, startIndex, len) > 0) {
  1952.                 return i;
  1953.             }
  1954.         }
  1955.         return -1;
  1956.     }

  1957.     /**
  1958.      * Inserts the value into this builder.
  1959.      *
  1960.      * @param index  the index to add at, must be valid
  1961.      * @param value  the value to insert
  1962.      * @return this, to enable chaining
  1963.      * @throws IndexOutOfBoundsException if the index is invalid
  1964.      */
  1965.     public StrBuilder insert(int index, final boolean value) {
  1966.         validateIndex(index);
  1967.         if (value) {
  1968.             ensureCapacity(size + 4);
  1969.             System.arraycopy(buffer, index, buffer, index + 4, size - index);
  1970.             buffer[index++] = 't';
  1971.             buffer[index++] = 'r';
  1972.             buffer[index++] = 'u';
  1973.             buffer[index] = 'e';
  1974.             size += 4;
  1975.         } else {
  1976.             ensureCapacity(size + 5);
  1977.             System.arraycopy(buffer, index, buffer, index + 5, size - index);
  1978.             buffer[index++] = 'f';
  1979.             buffer[index++] = 'a';
  1980.             buffer[index++] = 'l';
  1981.             buffer[index++] = 's';
  1982.             buffer[index] = 'e';
  1983.             size += 5;
  1984.         }
  1985.         return this;
  1986.     }

  1987.     /**
  1988.      * Inserts the value into this builder.
  1989.      *
  1990.      * @param index  the index to add at, must be valid
  1991.      * @param value  the value to insert
  1992.      * @return this, to enable chaining
  1993.      * @throws IndexOutOfBoundsException if the index is invalid
  1994.      */
  1995.     public StrBuilder insert(final int index, final char value) {
  1996.         validateIndex(index);
  1997.         ensureCapacity(size + 1);
  1998.         System.arraycopy(buffer, index, buffer, index + 1, size - index);
  1999.         buffer[index] = value;
  2000.         size++;
  2001.         return this;
  2002.     }

  2003.     /**
  2004.      * Inserts the character array into this builder.
  2005.      * Inserting null will use the stored null text value.
  2006.      *
  2007.      * @param index  the index to add at, must be valid
  2008.      * @param chars  the char array to insert
  2009.      * @return this, to enable chaining
  2010.      * @throws IndexOutOfBoundsException if the index is invalid
  2011.      */
  2012.     public StrBuilder insert(final int index, final char[] chars) {
  2013.         validateIndex(index);
  2014.         if (chars == null) {
  2015.             return insert(index, nullText);
  2016.         }
  2017.         final int len = chars.length;
  2018.         if (len > 0) {
  2019.             ensureCapacity(size + len);
  2020.             System.arraycopy(buffer, index, buffer, index + len, size - index);
  2021.             System.arraycopy(chars, 0, buffer, index, len);
  2022.             size += len;
  2023.         }
  2024.         return this;
  2025.     }

  2026.     /**
  2027.      * Inserts part of the character array into this builder.
  2028.      * Inserting null will use the stored null text value.
  2029.      *
  2030.      * @param index  the index to add at, must be valid
  2031.      * @param chars  the char array to insert
  2032.      * @param offset  the offset into the character array to start at, must be valid
  2033.      * @param length  the length of the character array part to copy, must be positive
  2034.      * @return this, to enable chaining
  2035.      * @throws IndexOutOfBoundsException if any index is invalid
  2036.      */
  2037.     public StrBuilder insert(final int index, final char[] chars, final int offset, final int length) {
  2038.         validateIndex(index);
  2039.         if (chars == null) {
  2040.             return insert(index, nullText);
  2041.         }
  2042.         if (offset < 0 || offset > chars.length) {
  2043.             throw new StringIndexOutOfBoundsException("Invalid offset: " + offset);
  2044.         }
  2045.         if (length < 0 || offset + length > chars.length) {
  2046.             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
  2047.         }
  2048.         if (length > 0) {
  2049.             ensureCapacity(size + length);
  2050.             System.arraycopy(buffer, index, buffer, index + length, size - index);
  2051.             System.arraycopy(chars, offset, buffer, index, length);
  2052.             size += length;
  2053.         }
  2054.         return this;
  2055.     }

  2056.     /**
  2057.      * Inserts the value into this builder.
  2058.      *
  2059.      * @param index  the index to add at, must be valid
  2060.      * @param value  the value to insert
  2061.      * @return this, to enable chaining
  2062.      * @throws IndexOutOfBoundsException if the index is invalid
  2063.      */
  2064.     public StrBuilder insert(final int index, final double value) {
  2065.         return insert(index, String.valueOf(value));
  2066.     }

  2067.     /**
  2068.      * Inserts the value into this builder.
  2069.      *
  2070.      * @param index  the index to add at, must be valid
  2071.      * @param value  the value to insert
  2072.      * @return this, to enable chaining
  2073.      * @throws IndexOutOfBoundsException if the index is invalid
  2074.      */
  2075.     public StrBuilder insert(final int index, final float value) {
  2076.         return insert(index, String.valueOf(value));
  2077.     }

  2078.     /**
  2079.      * Inserts the value into this builder.
  2080.      *
  2081.      * @param index  the index to add at, must be valid
  2082.      * @param value  the value to insert
  2083.      * @return this, to enable chaining
  2084.      * @throws IndexOutOfBoundsException if the index is invalid
  2085.      */
  2086.     public StrBuilder insert(final int index, final int value) {
  2087.         return insert(index, String.valueOf(value));
  2088.     }

  2089.     /**
  2090.      * Inserts the value into this builder.
  2091.      *
  2092.      * @param index  the index to add at, must be valid
  2093.      * @param value  the value to insert
  2094.      * @return this, to enable chaining
  2095.      * @throws IndexOutOfBoundsException if the index is invalid
  2096.      */
  2097.     public StrBuilder insert(final int index, final long value) {
  2098.         return insert(index, String.valueOf(value));
  2099.     }

  2100.     /**
  2101.      * Inserts the string representation of an object into this builder.
  2102.      * Inserting null will use the stored null text value.
  2103.      *
  2104.      * @param index  the index to add at, must be valid
  2105.      * @param obj  the object to insert
  2106.      * @return this, to enable chaining
  2107.      * @throws IndexOutOfBoundsException if the index is invalid
  2108.      */
  2109.     public StrBuilder insert(final int index, final Object obj) {
  2110.         if (obj == null) {
  2111.             return insert(index, nullText);
  2112.         }
  2113.         return insert(index, obj.toString());
  2114.     }

  2115.     /**
  2116.      * Inserts the string into this builder.
  2117.      * Inserting null will use the stored null text value.
  2118.      *
  2119.      * @param index  the index to add at, must be valid
  2120.      * @param str  the string to insert
  2121.      * @return this, to enable chaining
  2122.      * @throws IndexOutOfBoundsException if the index is invalid
  2123.      */
  2124.     public StrBuilder insert(final int index, String str) {
  2125.         validateIndex(index);
  2126.         if (str == null) {
  2127.             str = nullText;
  2128.         }
  2129.         if (str != null) {
  2130.             final int strLen = str.length();
  2131.             if (strLen > 0) {
  2132.                 final int newSize = size + strLen;
  2133.                 ensureCapacity(newSize);
  2134.                 System.arraycopy(buffer, index, buffer, index + strLen, size - index);
  2135.                 size = newSize;
  2136.                 str.getChars(0, strLen, buffer, index);
  2137.             }
  2138.         }
  2139.         return this;
  2140.     }

  2141.     /**
  2142.      * Checks is the string builder is empty (convenience Collections API style method).
  2143.      * <p>
  2144.      * This method is the same as checking {@link #length()} and is provided to match the
  2145.      * API of Collections.
  2146.      * </p>
  2147.      *
  2148.      * @return {@code true} if the size is {@code 0}.
  2149.      */
  2150.     public boolean isEmpty() {
  2151.         return size == 0;
  2152.     }

  2153.     /**
  2154.      * Checks is the string builder is not empty (convenience Collections API style method).
  2155.      * <p>
  2156.      * This method is the same as checking {@link #length()} and is provided to match the
  2157.      * API of Collections.
  2158.      * </p>
  2159.      *
  2160.      * @return {@code true} if the size is greater than {@code 0}.
  2161.      * @since 3.12.0
  2162.      */
  2163.     public boolean isNotEmpty() {
  2164.         return size > 0;
  2165.     }

  2166.     /**
  2167.      * Searches the string builder to find the last reference to the specified char.
  2168.      *
  2169.      * @param ch  the character to find
  2170.      * @return the last index of the character, or -1 if not found
  2171.      */
  2172.     public int lastIndexOf(final char ch) {
  2173.         return lastIndexOf(ch, size - 1);
  2174.     }

  2175.     /**
  2176.      * Searches the string builder to find the last reference to the specified char.
  2177.      *
  2178.      * @param ch  the character to find
  2179.      * @param startIndex  the index to start at, invalid index rounded to edge
  2180.      * @return the last index of the character, or -1 if not found
  2181.      */
  2182.     public int lastIndexOf(final char ch, int startIndex) {
  2183.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2184.         if (startIndex < 0) {
  2185.             return -1;
  2186.         }
  2187.         for (int i = startIndex; i >= 0; i--) {
  2188.             if (buffer[i] == ch) {
  2189.                 return i;
  2190.             }
  2191.         }
  2192.         return -1;
  2193.     }

  2194.     /**
  2195.      * Searches the string builder to find the last reference to the specified string.
  2196.      * <p>
  2197.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  2198.      * </p>
  2199.      *
  2200.      * @param str  the string to find, null returns -1
  2201.      * @return the last index of the string, or -1 if not found
  2202.      */
  2203.     public int lastIndexOf(final String str) {
  2204.         return lastIndexOf(str, size - 1);
  2205.     }

  2206.     /**
  2207.      * Searches the string builder to find the last reference to the specified
  2208.      * string starting searching from the given index.
  2209.      * <p>
  2210.      * Note that a null input string will return -1, whereas the JDK throws an exception.
  2211.      * </p>
  2212.      *
  2213.      * @param str  the string to find, null returns -1
  2214.      * @param startIndex  the index to start at, invalid index rounded to edge
  2215.      * @return the last index of the string, or -1 if not found
  2216.      */
  2217.     public int lastIndexOf(final String str, final int startIndex) {
  2218.         return StringUtils.lastIndexOf(this, str, startIndex);
  2219.     }

  2220.     /**
  2221.      * Searches the string builder using the matcher to find the last match.
  2222.      * <p>
  2223.      * Matchers can be used to perform advanced searching behavior.
  2224.      * For example you could write a matcher to find the character 'a'
  2225.      * followed by a number.
  2226.      * </p>
  2227.      *
  2228.      * @param matcher  the matcher to use, null returns -1
  2229.      * @return the last index matched, or -1 if not found
  2230.      */
  2231.     public int lastIndexOf(final StrMatcher matcher) {
  2232.         return lastIndexOf(matcher, size);
  2233.     }

  2234.     /**
  2235.      * Searches the string builder using the matcher to find the last
  2236.      * match searching from the given index.
  2237.      * <p>
  2238.      * Matchers can be used to perform advanced searching behavior.
  2239.      * For example you could write a matcher to find the character 'a'
  2240.      * followed by a number.
  2241.      * </p>
  2242.      *
  2243.      * @param matcher  the matcher to use, null returns -1
  2244.      * @param startIndex  the index to start at, invalid index rounded to edge
  2245.      * @return the last index matched, or -1 if not found
  2246.      */
  2247.     public int lastIndexOf(final StrMatcher matcher, int startIndex) {
  2248.         startIndex = startIndex >= size ? size - 1 : startIndex;
  2249.         if (matcher == null || startIndex < 0) {
  2250.             return -1;
  2251.         }
  2252.         final char[] buf = buffer;
  2253.         final int endIndex = startIndex + 1;
  2254.         for (int i = startIndex; i >= 0; i--) {
  2255.             if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
  2256.                 return i;
  2257.             }
  2258.         }
  2259.         return -1;
  2260.     }

  2261.     /**
  2262.      * Extracts the leftmost characters from the string builder without
  2263.      * throwing an exception.
  2264.      * <p>
  2265.      * This method extracts the left {@code length} characters from
  2266.      * the builder. If this many characters are not available, the whole
  2267.      * builder is returned. Thus the returned string may be shorter than the
  2268.      * length requested.
  2269.      * </p>
  2270.      *
  2271.      * @param length  the number of characters to extract, negative returns empty string
  2272.      * @return the new string
  2273.      */
  2274.     public String leftString(final int length) {
  2275.         if (length <= 0) {
  2276.             return StringUtils.EMPTY;
  2277.         }
  2278.         if (length >= size) {
  2279.             return new String(buffer, 0, size);
  2280.         }
  2281.         return new String(buffer, 0, length);
  2282.     }

  2283.     /**
  2284.      * Gets the length of the string builder.
  2285.      *
  2286.      * @return the length
  2287.      */
  2288.     @Override
  2289.     public int length() {
  2290.         return size;
  2291.     }

  2292.     /**
  2293.      * Extracts some characters from the middle of the string builder without
  2294.      * throwing an exception.
  2295.      * <p>
  2296.      * This method extracts {@code length} characters from the builder
  2297.      * at the specified index.
  2298.      * If the index is negative it is treated as zero.
  2299.      * If the index is greater than the builder size, it is treated as the builder size.
  2300.      * If the length is negative, the empty string is returned.
  2301.      * If insufficient characters are available in the builder, as much as possible is returned.
  2302.      * Thus the returned string may be shorter than the length requested.
  2303.      * </p>
  2304.      *
  2305.      * @param index  the index to start at, negative means zero
  2306.      * @param length  the number of characters to extract, negative returns empty string
  2307.      * @return the new string
  2308.      */
  2309.     public String midString(int index, final int length) {
  2310.         if (index < 0) {
  2311.             index = 0;
  2312.         }
  2313.         if (length <= 0 || index >= size) {
  2314.             return StringUtils.EMPTY;
  2315.         }
  2316.         if (size <= index + length) {
  2317.             return new String(buffer, index, size - index);
  2318.         }
  2319.         return new String(buffer, index, length);
  2320.     }

  2321.     /**
  2322.      * Minimizes the capacity to the actual length of the string.
  2323.      *
  2324.      * @return this, to enable chaining
  2325.      */
  2326.     public StrBuilder minimizeCapacity() {
  2327.         if (buffer.length > length()) {
  2328.             buffer = ArrayUtils.arraycopy(buffer, 0, 0, size, () -> new char[length()]);
  2329.         }
  2330.         return this;
  2331.     }

  2332.     /**
  2333.      * If possible, reads chars from the provided {@link Readable} directly into underlying
  2334.      * character buffer without making extra copies.
  2335.      *
  2336.      * @param readable  object to read from
  2337.      * @return the number of characters read
  2338.      * @throws IOException if an I/O error occurs.
  2339.      *
  2340.      * @since 3.4
  2341.      * @see #appendTo(Appendable)
  2342.      */
  2343.     public int readFrom(final Readable readable) throws IOException {
  2344.         final int oldSize = size;
  2345.         if (readable instanceof Reader) {
  2346.             final Reader r = (Reader) readable;
  2347.             ensureCapacity(size + 1);
  2348.             int read;
  2349.             while ((read = r.read(buffer, size, buffer.length - size)) != -1) {
  2350.                 size += read;
  2351.                 ensureCapacity(size + 1);
  2352.             }
  2353.         } else if (readable instanceof CharBuffer) {
  2354.             final CharBuffer cb = (CharBuffer) readable;
  2355.             final int remaining = cb.remaining();
  2356.             ensureCapacity(size + remaining);
  2357.             cb.get(buffer, size, remaining);
  2358.             size += remaining;
  2359.         } else {
  2360.             while (true) {
  2361.                 ensureCapacity(size + 1);
  2362.                 final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size);
  2363.                 final int read = readable.read(buf);
  2364.                 if (read == -1) {
  2365.                     break;
  2366.                 }
  2367.                 size += read;
  2368.             }
  2369.         }
  2370.         return size - oldSize;
  2371.     }

  2372.     /**
  2373.      * Replaces a portion of the string builder with another string.
  2374.      * The length of the inserted string does not have to match the removed length.
  2375.      *
  2376.      * @param startIndex  the start index, inclusive, must be valid
  2377.      * @param endIndex  the end index, exclusive, must be valid except
  2378.      *  that if too large it is treated as end of string
  2379.      * @param replaceStr  the string to replace with, null means delete range
  2380.      * @return this, to enable chaining
  2381.      * @throws IndexOutOfBoundsException if the index is invalid
  2382.      */
  2383.     public StrBuilder replace(final int startIndex, int endIndex, final String replaceStr) {
  2384.         endIndex = validateRange(startIndex, endIndex);
  2385.         final int insertLen = StringUtils.length(replaceStr);
  2386.         replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen);
  2387.         return this;
  2388.     }

  2389.     /**
  2390.      * Advanced search and replaces within the builder using a matcher.
  2391.      * <p>
  2392.      * Matchers can be used to perform advanced behavior.
  2393.      * For example you could write a matcher to delete all occurrences
  2394.      * where the character 'a' is followed by a number.
  2395.      * </p>
  2396.      *
  2397.      * @param matcher  the matcher to use to find the deletion, null causes no action
  2398.      * @param replaceStr  the string to replace the match with, null is a delete
  2399.      * @param startIndex  the start index, inclusive, must be valid
  2400.      * @param endIndex  the end index, exclusive, must be valid except
  2401.      *  that if too large it is treated as end of string
  2402.      * @param replaceCount  the number of times to replace, -1 for replace all
  2403.      * @return this, to enable chaining
  2404.      * @throws IndexOutOfBoundsException if start index is invalid
  2405.      */
  2406.     public StrBuilder replace(
  2407.             final StrMatcher matcher, final String replaceStr,
  2408.             final int startIndex, int endIndex, final int replaceCount) {
  2409.         endIndex = validateRange(startIndex, endIndex);
  2410.         return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount);
  2411.     }

  2412.     /**
  2413.      * Replaces the search character with the replace character
  2414.      * throughout the builder.
  2415.      *
  2416.      * @param search  the search character
  2417.      * @param replace  the replace character
  2418.      * @return this, to enable chaining
  2419.      */
  2420.     public StrBuilder replaceAll(final char search, final char replace) {
  2421.         if (search != replace) {
  2422.             for (int i = 0; i < size; i++) {
  2423.                 if (buffer[i] == search) {
  2424.                     buffer[i] = replace;
  2425.                 }
  2426.             }
  2427.         }
  2428.         return this;
  2429.     }

  2430.     /**
  2431.      * Replaces the search string with the replace string throughout the builder.
  2432.      *
  2433.      * @param searchStr  the search string, null causes no action to occur
  2434.      * @param replaceStr  the replace string, null is equivalent to an empty string
  2435.      * @return this, to enable chaining
  2436.      */
  2437.     public StrBuilder replaceAll(final String searchStr, final String replaceStr) {
  2438.         final int searchLen = StringUtils.length(searchStr);
  2439.         if (searchLen > 0) {
  2440.             final int replaceLen = StringUtils.length(replaceStr);
  2441.             int index = indexOf(searchStr, 0);
  2442.             while (index >= 0) {
  2443.                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
  2444.                 index = indexOf(searchStr, index + replaceLen);
  2445.             }
  2446.         }
  2447.         return this;
  2448.     }

  2449.     /**
  2450.      * Replaces all matches within the builder with the replace string.
  2451.      * <p>
  2452.      * Matchers can be used to perform advanced replace behavior.
  2453.      * For example you could write a matcher to replace all occurrences
  2454.      * where the character 'a' is followed by a number.
  2455.      * </p>
  2456.      *
  2457.      * @param matcher  the matcher to use to find the deletion, null causes no action
  2458.      * @param replaceStr  the replace string, null is equivalent to an empty string
  2459.      * @return this, to enable chaining
  2460.      */
  2461.     public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) {
  2462.         return replace(matcher, replaceStr, 0, size, -1);
  2463.     }

  2464.     /**
  2465.      * Replaces the first instance of the search character with the
  2466.      * replace character in the builder.
  2467.      *
  2468.      * @param search  the search character
  2469.      * @param replace  the replace character
  2470.      * @return this, to enable chaining
  2471.      */
  2472.     public StrBuilder replaceFirst(final char search, final char replace) {
  2473.         if (search != replace) {
  2474.             for (int i = 0; i < size; i++) {
  2475.                 if (buffer[i] == search) {
  2476.                     buffer[i] = replace;
  2477.                     break;
  2478.                 }
  2479.             }
  2480.         }
  2481.         return this;
  2482.     }

  2483.     /**
  2484.      * Replaces the first instance of the search string with the replace string.
  2485.      *
  2486.      * @param searchStr  the search string, null causes no action to occur
  2487.      * @param replaceStr  the replace string, null is equivalent to an empty string
  2488.      * @return this, to enable chaining
  2489.      */
  2490.     public StrBuilder replaceFirst(final String searchStr, final String replaceStr) {
  2491.         final int searchLen = StringUtils.length(searchStr);
  2492.         if (searchLen > 0) {
  2493.             final int index = indexOf(searchStr, 0);
  2494.             if (index >= 0) {
  2495.                 final int replaceLen = StringUtils.length(replaceStr);
  2496.                 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
  2497.             }
  2498.         }
  2499.         return this;
  2500.     }

  2501.     /**
  2502.      * Replaces the first match within the builder with the replace string.
  2503.      * <p>
  2504.      * Matchers can be used to perform advanced replace behavior.
  2505.      * For example you could write a matcher to replace
  2506.      * where the character 'a' is followed by a number.
  2507.      * </p>
  2508.      *
  2509.      * @param matcher  the matcher to use to find the deletion, null causes no action
  2510.      * @param replaceStr  the replace string, null is equivalent to an empty string
  2511.      * @return this, to enable chaining
  2512.      */
  2513.     public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr) {
  2514.         return replace(matcher, replaceStr, 0, size, 1);
  2515.     }

  2516.     /**
  2517.      * Internal method to delete a range without validation.
  2518.      *
  2519.      * @param startIndex  the start index, must be valid
  2520.      * @param endIndex  the end index (exclusive), must be valid
  2521.      * @param removeLen  the length to remove (endIndex - startIndex), must be valid
  2522.      * @param insertStr  the string to replace with, null means delete range
  2523.      * @param insertLen  the length of the insert string, must be valid
  2524.      * @throws IndexOutOfBoundsException if any index is invalid
  2525.      */
  2526.     private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, final int insertLen) {
  2527.         final int newSize = size - removeLen + insertLen;
  2528.         if (insertLen != removeLen) {
  2529.             ensureCapacity(newSize);
  2530.             System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex);
  2531.             size = newSize;
  2532.         }
  2533.         if (insertLen > 0) {
  2534.             insertStr.getChars(0, insertLen, buffer, startIndex);
  2535.         }
  2536.     }

  2537.     /**
  2538.      * Replaces within the builder using a matcher.
  2539.      * <p>
  2540.      * Matchers can be used to perform advanced behavior.
  2541.      * For example you could write a matcher to delete all occurrences
  2542.      * where the character 'a' is followed by a number.
  2543.      * </p>
  2544.      *
  2545.      * @param matcher  the matcher to use to find the deletion, null causes no action
  2546.      * @param replaceStr  the string to replace the match with, null is a delete
  2547.      * @param from  the start index, must be valid
  2548.      * @param to  the end index (exclusive), must be valid
  2549.      * @param replaceCount  the number of times to replace, -1 for replace all
  2550.      * @return this, to enable chaining
  2551.      * @throws IndexOutOfBoundsException if any index is invalid
  2552.      */
  2553.     private StrBuilder replaceImpl(
  2554.             final StrMatcher matcher, final String replaceStr,
  2555.             final int from, int to, int replaceCount) {
  2556.         if (matcher == null || size == 0) {
  2557.             return this;
  2558.         }
  2559.         final int replaceLen = StringUtils.length(replaceStr);
  2560.         for (int i = from; i < to && replaceCount != 0; i++) {
  2561.             final char[] buf = buffer;
  2562.             final int removeLen = matcher.isMatch(buf, i, from, to);
  2563.             if (removeLen > 0) {
  2564.                 replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen);
  2565.                 to = to - removeLen + replaceLen;
  2566.                 i = i + replaceLen - 1;
  2567.                 if (replaceCount > 0) {
  2568.                     replaceCount--;
  2569.                 }
  2570.             }
  2571.         }
  2572.         return this;
  2573.     }

  2574.     /**
  2575.      * Reverses the string builder placing each character in the opposite index.
  2576.      *
  2577.      * @return this, to enable chaining
  2578.      */
  2579.     public StrBuilder reverse() {
  2580.         if (size == 0) {
  2581.             return this;
  2582.         }

  2583.         final int half = size / 2;
  2584.         final char[] buf = buffer;
  2585.         for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) {
  2586.             final char swap = buf[leftIdx];
  2587.             buf[leftIdx] = buf[rightIdx];
  2588.             buf[rightIdx] = swap;
  2589.         }
  2590.         return this;
  2591.     }

  2592.     /**
  2593.      * Extracts the rightmost characters from the string builder without
  2594.      * throwing an exception.
  2595.      * <p>
  2596.      * This method extracts the right {@code length} characters from
  2597.      * the builder. If this many characters are not available, the whole
  2598.      * builder is returned. Thus the returned string may be shorter than the
  2599.      * length requested.
  2600.      * </p>
  2601.      *
  2602.      * @param length  the number of characters to extract, negative returns empty string
  2603.      * @return the new string
  2604.      */
  2605.     public String rightString(final int length) {
  2606.         if (length <= 0) {
  2607.             return StringUtils.EMPTY;
  2608.         }
  2609.         if (length >= size) {
  2610.             return new String(buffer, 0, size);
  2611.         }
  2612.         return new String(buffer, size - length, length);
  2613.     }

  2614.     /**
  2615.      * Sets the character at the specified index.
  2616.      *
  2617.      * @see #charAt(int)
  2618.      * @see #deleteCharAt(int)
  2619.      * @param index  the index to set
  2620.      * @param ch  the new character
  2621.      * @return this, to enable chaining
  2622.      * @throws IndexOutOfBoundsException if the index is invalid
  2623.      */
  2624.     public StrBuilder setCharAt(final int index, final char ch) {
  2625.         if (index < 0 || index >= length()) {
  2626.             throw new StringIndexOutOfBoundsException(index);
  2627.         }
  2628.         buffer[index] = ch;
  2629.         return this;
  2630.     }

  2631.     /**
  2632.      * Updates the length of the builder by either dropping the last characters
  2633.      * or adding filler of Unicode zero.
  2634.      *
  2635.      * @param length  the length to set to, must be zero or positive
  2636.      * @return this, to enable chaining
  2637.      * @throws IndexOutOfBoundsException if the length is negative
  2638.      */
  2639.     public StrBuilder setLength(final int length) {
  2640.         if (length < 0) {
  2641.             throw new StringIndexOutOfBoundsException(length);
  2642.         }
  2643.         if (length < size) {
  2644.             size = length;
  2645.         } else if (length > size) {
  2646.             ensureCapacity(length);
  2647.             final int oldEnd = size;
  2648.             size = length;
  2649.             for (int i = oldEnd; i < length; i++) {
  2650.                 buffer[i] = CharUtils.NUL;
  2651.             }
  2652.         }
  2653.         return this;
  2654.     }

  2655.     /**
  2656.      * Sets the text to be appended when {@link #appendNewLine() new line} is called.
  2657.      *
  2658.      * @param newLine the new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
  2659.      * @return {@code this} instance.
  2660.      */
  2661.     public StrBuilder setNewLineText(final String newLine) {
  2662.         this.newLine = newLine;
  2663.         return this;
  2664.     }

  2665.     /**
  2666.      * Sets the text to be appended when null is added.
  2667.      *
  2668.      * @param nullText  the null text, null means no append
  2669.      * @return this, to enable chaining
  2670.      */
  2671.     public StrBuilder setNullText(String nullText) {
  2672.         if (StringUtils.isEmpty(nullText)) {
  2673.             nullText = null;
  2674.         }
  2675.         this.nullText = nullText;
  2676.         return this;
  2677.     }

  2678.     /**
  2679.      * Gets the length of the string builder.
  2680.      * <p>
  2681.      * This method is the same as {@link #length()} and is provided to match the
  2682.      * API of Collections.
  2683.      * </p>
  2684.      *
  2685.      * @return the length
  2686.      */
  2687.     public int size() {
  2688.         return size;
  2689.     }

  2690.     /**
  2691.      * Checks whether this builder starts with the specified string.
  2692.      * <p>
  2693.      * Note that this method handles null input quietly, unlike String.
  2694.      * </p>
  2695.      *
  2696.      * @param str  the string to search for, null returns false
  2697.      * @return true if the builder starts with the string
  2698.      */
  2699.     public boolean startsWith(final String str) {
  2700.         if (str == null) {
  2701.             return false;
  2702.         }
  2703.         final int len = str.length();
  2704.         if (len == 0) {
  2705.             return true;
  2706.         }
  2707.         if (len > size) {
  2708.             return false;
  2709.         }
  2710.         for (int i = 0; i < len; i++) {
  2711.             if (buffer[i] != str.charAt(i)) {
  2712.                 return false;
  2713.             }
  2714.         }
  2715.         return true;
  2716.     }

  2717.     /**
  2718.      * {@inheritDoc}
  2719.      * @since 3.0
  2720.      */
  2721.     @Override
  2722.     public CharSequence subSequence(final int startIndex, final int endIndex) {
  2723.       if (startIndex < 0) {
  2724.           throw new StringIndexOutOfBoundsException(startIndex);
  2725.       }
  2726.       if (endIndex > size) {
  2727.           throw new StringIndexOutOfBoundsException(endIndex);
  2728.       }
  2729.       if (startIndex > endIndex) {
  2730.           throw new StringIndexOutOfBoundsException(endIndex - startIndex);
  2731.       }
  2732.       return substring(startIndex, endIndex);
  2733.     }

  2734.     /**
  2735.      * Extracts a portion of this string builder as a string.
  2736.      *
  2737.      * @param start  the start index, inclusive, must be valid
  2738.      * @return the new string
  2739.      * @throws IndexOutOfBoundsException if the index is invalid
  2740.      */
  2741.     public String substring(final int start) {
  2742.         return substring(start, size);
  2743.     }

  2744.     /**
  2745.      * Extracts a portion of this string builder as a string.
  2746.      * <p>
  2747.      * Note: This method treats an endIndex greater than the length of the
  2748.      * builder as equal to the length of the builder, and continues
  2749.      * without error, unlike StringBuffer or String.
  2750.      * </p>
  2751.      *
  2752.      * @param startIndex  the start index, inclusive, must be valid
  2753.      * @param endIndex  the end index, exclusive, must be valid except
  2754.      *  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.     public String substring(final int startIndex, int endIndex) {
  2759.         endIndex = validateRange(startIndex, endIndex);
  2760.         return new String(buffer, startIndex, endIndex - startIndex);
  2761.     }

  2762.     /**
  2763.      * Copies the builder's character array into a new character array.
  2764.      *
  2765.      * @return a new array that represents the contents of the builder
  2766.      */
  2767.     public char[] toCharArray() {
  2768.         if (size == 0) {
  2769.             return ArrayUtils.EMPTY_CHAR_ARRAY;
  2770.         }
  2771.         return ArrayUtils.arraycopy(buffer, 0, 0, size, char[]::new);
  2772.     }

  2773.     /**
  2774.      * Copies part of the builder's character array into a new character array.
  2775.      *
  2776.      * @param startIndex  the start index, inclusive, must be valid
  2777.      * @param endIndex  the end index, exclusive, must be valid except that
  2778.      *  if too large it is treated as end of string
  2779.      * @return a new array that holds part of the contents of the builder
  2780.      * @throws IndexOutOfBoundsException if startIndex is invalid,
  2781.      *  or if endIndex is invalid (but endIndex greater than size is valid)
  2782.      */
  2783.     public char[] toCharArray(final int startIndex, int endIndex) {
  2784.         endIndex = validateRange(startIndex, endIndex);
  2785.         final int len = endIndex - startIndex;
  2786.         if (len == 0) {
  2787.             return ArrayUtils.EMPTY_CHAR_ARRAY;
  2788.         }
  2789.         return ArrayUtils.arraycopy(buffer, startIndex, 0, len, char[]::new);
  2790.     }

  2791.     /**
  2792.      * Gets a String version of the string builder, creating a new instance
  2793.      * each time the method is called.
  2794.      * <p>
  2795.      * Note that unlike StringBuffer, the string version returned is
  2796.      * independent of the string builder.
  2797.      * </p>
  2798.      *
  2799.      * @return the builder as a String
  2800.      */
  2801.     @Override
  2802.     public String toString() {
  2803.         return new String(buffer, 0, size);
  2804.     }

  2805.     /**
  2806.      * Gets a StringBuffer version of the string builder, creating a
  2807.      * new instance each time the method is called.
  2808.      *
  2809.      * @return the builder as a StringBuffer
  2810.      */
  2811.     public StringBuffer toStringBuffer() {
  2812.         return new StringBuffer(size).append(buffer, 0, size);
  2813.     }

  2814.     /**
  2815.      * Gets a StringBuilder version of the string builder, creating a
  2816.      * new instance each time the method is called.
  2817.      *
  2818.      * @return the builder as a StringBuilder
  2819.      * @since 3.2
  2820.      */
  2821.     public StringBuilder toStringBuilder() {
  2822.         return new StringBuilder(size).append(buffer, 0, size);
  2823.     }

  2824.     /**
  2825.      * Trims the builder by removing characters less than or equal to a space
  2826.      * from the beginning and end.
  2827.      *
  2828.      * @return this, to enable chaining
  2829.      */
  2830.     public StrBuilder trim() {
  2831.         if (size == 0) {
  2832.             return this;
  2833.         }
  2834.         int len = size;
  2835.         final char[] buf = buffer;
  2836.         int pos = 0;
  2837.         while (pos < len && buf[pos] <= ' ') {
  2838.             pos++;
  2839.         }
  2840.         while (pos < len && buf[len - 1] <= ' ') {
  2841.             len--;
  2842.         }
  2843.         if (len < size) {
  2844.             delete(len, size);
  2845.         }
  2846.         if (pos > 0) {
  2847.             delete(0, pos);
  2848.         }
  2849.         return this;
  2850.     }

  2851.     /**
  2852.      * Validates parameters defining a single index in the builder.
  2853.      *
  2854.      * @param index  the index, must be valid
  2855.      * @throws IndexOutOfBoundsException if the index is invalid
  2856.      */
  2857.     protected void validateIndex(final int index) {
  2858.         if (index < 0 || index > size) {
  2859.             throw new StringIndexOutOfBoundsException(index);
  2860.         }
  2861.     }

  2862.     /**
  2863.      * Validates parameters defining a range of the builder.
  2864.      *
  2865.      * @param startIndex  the start index, inclusive, must be valid
  2866.      * @param endIndex  the end index, exclusive, must be valid except
  2867.      *  that if too large it is treated as end of string
  2868.      * @return the new string
  2869.      * @throws IndexOutOfBoundsException if the index is invalid
  2870.      */
  2871.     protected int validateRange(final int startIndex, int endIndex) {
  2872.         if (startIndex < 0) {
  2873.             throw new StringIndexOutOfBoundsException(startIndex);
  2874.         }
  2875.         if (endIndex > size) {
  2876.             endIndex = size;
  2877.         }
  2878.         if (startIndex > endIndex) {
  2879.             throw new StringIndexOutOfBoundsException("end < start");
  2880.         }
  2881.         return endIndex;
  2882.     }

  2883. }