View Javadoc

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.lang.text;
18  
19  import java.io.Reader;
20  import java.io.Writer;
21  import java.util.Collection;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import org.apache.commons.lang.ArrayUtils;
26  import org.apache.commons.lang.SystemUtils;
27  
28  /**
29   * Builds a string from constituent parts providing a more flexible and powerful API
30   * than StringBuffer.
31   * <p>
32   * The main differences from StringBuffer/StringBuilder are:
33   * <ul>
34   * <li>Not synchronized</li>
35   * <li>Not final</li>
36   * <li>Subclasses have direct access to character array</li>
37   * <li>Additional methods
38   *  <ul>
39   *   <li>appendWithSeparators - adds an array of values, with a separator</li>
40   *   <li>appendPadding - adds a length padding characters</li>
41   *   <li>appendFixedLength - adds a fixed width field to the builder</li>
42   *   <li>toCharArray/getChars - simpler ways to get a range of the character array</li>
43   *   <li>delete - delete char or string</li>
44   *   <li>replace - search and replace for a char or string</li>
45   *   <li>leftString/rightString/midString - substring without exceptions</li>
46   *   <li>contains - whether the builder contains a char or string</li>
47   *   <li>size/clear/isEmpty - collections style API methods</li>
48   *  </ul>
49   * </li>
50   * </ul>
51   * <li>Views
52   *  <ul>
53   *   <li>asTokenizer - uses the internal buffer as the source of a StrTokenizer</li>
54   *   <li>asReader - uses the internal buffer as the source of a Reader</li>
55   *   <li>asWriter - allows a Writer to write directly to the internal buffer</li>
56   *  </ul>
57   * </li>
58   * </ul>
59   * <p>
60   * The aim has been to provide an API that mimics very closely what StringBuffer
61   * provides, but with additional methods. It should be noted that some edge cases,
62   * with invalid indices or null input, have been altered - see individual methods.
63   * The biggest of these changes is that by default, null will not output the text
64   * 'null'. This can be controlled by a property, {@link #setNullText(String)}.
65   *
66   * @author Stephen Colebourne
67   * @since 2.2
68   * @version $Id: StrBuilder.java 627248 2008-02-13 05:44:46Z bayard $
69   */
70  public class StrBuilder implements Cloneable {
71  
72      /**
73       * The extra capacity for new builders.
74       */
75      static final int CAPACITY = 32;
76  
77      /**
78       * Required for serialization support.
79       * 
80       * @see java.io.Serializable
81       */
82      private static final long serialVersionUID = 7628716375283629643L;
83  
84      /** Internal data storage. */
85      protected char[] buffer;
86      /** Current size of the buffer. */
87      protected int size;
88      /** The new line. */
89      private String newLine;
90      /** The null text. */
91      private String nullText;
92  
93      //-----------------------------------------------------------------------
94      /**
95       * Constructor that creates an empty builder initial capacity 32 characters.
96       */
97      public StrBuilder() {
98          this(CAPACITY);
99      }
100 
101     /**
102      * Constructor that creates an empty builder the specified initial capacity.
103      *
104      * @param initialCapacity  the initial capacity, zero or less will be converted to 32
105      */
106     public StrBuilder(int initialCapacity) {
107         super();
108         if (initialCapacity <= 0) {
109             initialCapacity = CAPACITY;
110         }
111         buffer = new char[initialCapacity];
112     }
113 
114     /**
115      * Constructor that creates a builder from the string, allocating
116      * 32 extra characters for growth.
117      *
118      * @param str  the string to copy, null treated as blank string
119      */
120     public StrBuilder(String str) {
121         super();
122         if (str == null) {
123             buffer = new char[CAPACITY];
124         } else {
125             buffer = new char[str.length() + CAPACITY];
126             append(str);
127         }
128     }
129 
130     //-----------------------------------------------------------------------
131     /**
132      * Gets the text to be appended when a new line is added.
133      *
134      * @return the new line text, null means use system default
135      */
136     public String getNewLineText() {
137         return newLine;
138     }
139 
140     /**
141      * Sets the text to be appended when a new line is added.
142      *
143      * @param newLine  the new line text, null means use system default
144      * @return this, to enable chaining
145      */
146     public StrBuilder setNewLineText(String newLine) {
147         this.newLine = newLine;
148         return this;
149     }
150 
151     //-----------------------------------------------------------------------
152     /**
153      * Gets the text to be appended when null is added.
154      *
155      * @return the null text, null means no append
156      */
157     public String getNullText() {
158         return nullText;
159     }
160 
161     /**
162      * Sets the text to be appended when null is added.
163      *
164      * @param nullText  the null text, null means no append
165      * @return this, to enable chaining
166      */
167     public StrBuilder setNullText(String nullText) {
168         if (nullText != null && nullText.length() == 0) {
169             nullText = null;
170         }
171         this.nullText = nullText;
172         return this;
173     }
174 
175     //-----------------------------------------------------------------------
176     /**
177      * Gets the length of the string builder.
178      *
179      * @return the length
180      */
181     public int length() {
182         return size;
183     }
184 
185     /**
186      * Updates the length of the builder by either dropping the last characters
187      * or adding filler of unicode zero.
188      *
189      * @param length  the length to set to, must be zero or positive
190      * @return this, to enable chaining
191      * @throws IndexOutOfBoundsException if the length is negative
192      */
193     public StrBuilder setLength(int length) {
194         if (length < 0) {
195             throw new StringIndexOutOfBoundsException(length);
196         }
197         if (length < size) {
198             size = length;
199         } else if (length > size) {
200             ensureCapacity(length);
201             int oldEnd = size;
202             int newEnd = length;
203             size = length;
204             for (int i = oldEnd; i < newEnd; i++) {
205                 buffer[i] = '\0';
206             }
207         }
208         return this;
209     }
210 
211     //-----------------------------------------------------------------------
212     /**
213      * Gets the current size of the internal character array buffer.
214      *
215      * @return the capacity
216      */
217     public int capacity() {
218         return buffer.length;
219     }
220 
221     /**
222      * Checks the capacity and ensures that it is at least the size specified.
223      *
224      * @param capacity  the capacity to ensure
225      * @return this, to enable chaining
226      */
227     public StrBuilder ensureCapacity(int capacity) {
228         if (capacity > buffer.length) {
229             char[] old = buffer;
230             buffer = new char[capacity];
231             System.arraycopy(old, 0, buffer, 0, size);
232         }
233         return this;
234     }
235 
236     /**
237      * Minimizes the capacity to the actual length of the string.
238      *
239      * @return this, to enable chaining
240      */
241     public StrBuilder minimizeCapacity() {
242         if (buffer.length > length()) {
243             char[] old = buffer;
244             buffer = new char[length()];
245             System.arraycopy(old, 0, buffer, 0, size);
246         }
247         return this;
248     }
249 
250     //-----------------------------------------------------------------------
251     /**
252      * Gets the length of the string builder.
253      * <p>
254      * This method is the same as {@link #length()} and is provided to match the
255      * API of Collections.
256      *
257      * @return the length
258      */
259     public int size() {
260         return size;
261     }
262 
263     /**
264      * Checks is the string builder is empty (convenience Collections API style method).
265      * <p>
266      * This method is the same as checking {@link #length()} and is provided to match the
267      * API of Collections.
268      *
269      * @return <code>true</code> if the size is <code>0</code>.
270      */
271     public boolean isEmpty() {
272         return size == 0;
273     }
274 
275     /**
276      * Clears the string builder (convenience Collections API style method).
277      * <p>
278      * This method does not reduce the size of the internal character buffer.
279      * To do that, call <code>clear()</code> followed by {@link #minimizeCapacity()}.
280      * <p>
281      * This method is the same as {@link #setLength(int)} called with zero
282      * and is provided to match the API of Collections.
283      *
284      * @return this, to enable chaining
285      */
286     public StrBuilder clear() {
287         size = 0;
288         return this;
289     }
290 
291     //-----------------------------------------------------------------------
292     /**
293      * Gets the character at the specified index.
294      *
295      * @see #setCharAt(int, char)
296      * @see #deleteCharAt(int)
297      * @param index  the index to retrieve, must be valid
298      * @return the character at the index
299      * @throws IndexOutOfBoundsException if the index is invalid
300      */
301     public char charAt(int index) {
302         if (index < 0 || index >= length()) {
303             throw new StringIndexOutOfBoundsException(index);
304         }
305         return buffer[index];
306     }
307 
308     /**
309      * Sets the character at the specified index.
310      *
311      * @see #charAt(int)
312      * @see #deleteCharAt(int)
313      * @param index  the index to set
314      * @param ch  the new character
315      * @return this, to enable chaining
316      * @throws IndexOutOfBoundsException if the index is invalid
317      */
318     public StrBuilder setCharAt(int index, char ch) {
319         if (index < 0 || index >= length()) {
320             throw new StringIndexOutOfBoundsException(index);
321         }
322         buffer[index] = ch;
323         return this;
324     }
325 
326     /**
327      * Deletes the character at the specified index.
328      *
329      * @see #charAt(int)
330      * @see #setCharAt(int, char)
331      * @param index  the index to delete
332      * @return this, to enable chaining
333      * @throws IndexOutOfBoundsException if the index is invalid
334      */
335     public StrBuilder deleteCharAt(int index) {
336         if (index < 0 || index >= size) {
337             throw new StringIndexOutOfBoundsException(index);
338         }
339         deleteImpl(index, index + 1, 1);
340         return this;
341     }
342 
343     //-----------------------------------------------------------------------
344     /**
345      * Copies the builder's character array into a new character array.
346      * 
347      * @return a new array that represents the contents of the builder
348      */
349     public char[] toCharArray() {
350         if (size == 0) {
351             return ArrayUtils.EMPTY_CHAR_ARRAY;
352         }
353         char chars[] = new char[size];
354         System.arraycopy(buffer, 0, chars, 0, size);
355         return chars;
356     }
357 
358     /**
359      * Copies part of the builder's character array into a new character array.
360      * 
361      * @param startIndex  the start index, inclusive, must be valid
362      * @param endIndex  the end index, exclusive, must be valid except that
363      *  if too large it is treated as end of string
364      * @return a new array that holds part of the contents of the builder
365      * @throws IndexOutOfBoundsException if startIndex is invalid,
366      *  or if endIndex is invalid (but endIndex greater than size is valid)
367      */
368     public char[] toCharArray(int startIndex, int endIndex) {
369         endIndex = validateRange(startIndex, endIndex);
370         int len = endIndex - startIndex;
371         if (len == 0) {
372             return ArrayUtils.EMPTY_CHAR_ARRAY;
373         }
374         char chars[] = new char[len];
375         System.arraycopy(buffer, startIndex, chars, 0, len);
376         return chars;
377     }
378 
379     /**
380      * Copies the character array into the specified array.
381      * 
382      * @param destination  the destination array, null will cause an array to be created
383      * @return the input array, unless that was null or too small
384      */
385     public char[] getChars(char[] destination) {
386         int len = length();
387         if (destination == null || destination.length < len) {
388             destination = new char[len];
389         }
390         System.arraycopy(buffer, 0, destination, 0, len);
391         return destination;
392     }
393 
394     /**
395      * Copies the character array into the specified array.
396      *
397      * @param startIndex  first index to copy, inclusive, must be valid
398      * @param endIndex  last index, exclusive, must be valid
399      * @param destination  the destination array, must not be null or too small
400      * @param destinationIndex  the index to start copying in destination
401      * @throws NullPointerException if the array is null
402      * @throws IndexOutOfBoundsException if any index is invalid
403      */
404     public void getChars(int startIndex, int endIndex, char destination[], int destinationIndex) {
405         if (startIndex < 0) {
406             throw new StringIndexOutOfBoundsException(startIndex);
407         }
408         if (endIndex < 0 || endIndex > length()) {
409             throw new StringIndexOutOfBoundsException(endIndex);
410         }
411         if (startIndex > endIndex) {
412             throw new StringIndexOutOfBoundsException("end < start");
413         }
414         System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex);
415     }
416 
417     //-----------------------------------------------------------------------
418     /**
419      * Appends the new line string to this string builder.
420      * <p>
421      * The new line string can be altered using {@link #setNewLineText(String)}.
422      * This might be used to force the output to always use Unix line endings
423      * even when on Windows.
424      *
425      * @return this, to enable chaining
426      */
427     public StrBuilder appendNewLine() {
428         if (newLine == null)  {
429             append(SystemUtils.LINE_SEPARATOR);
430             return this;
431         }
432         return append(newLine);
433     }
434 
435     /**
436      * Appends the text representing <code>null</code> to this string builder.
437      *
438      * @return this, to enable chaining
439      */
440     public StrBuilder appendNull() {
441         if (nullText == null)  {
442             return this;
443         }
444         return append(nullText);
445     }
446 
447     /**
448      * Appends an object to this string builder.
449      * Appending null will call {@link #appendNull()}.
450      *
451      * @param obj  the object to append
452      * @return this, to enable chaining
453      */
454     public StrBuilder append(Object obj) {
455         if (obj == null) {
456             return appendNull();
457         } 
458         return append(obj.toString());        
459     }
460 
461     /**
462      * Appends a string to this string builder.
463      * Appending null will call {@link #appendNull()}.
464      *
465      * @param str  the string to append
466      * @return this, to enable chaining
467      */
468     public StrBuilder append(String str) {
469         if (str == null) {
470             return appendNull();
471         }
472         int strLen = str.length();
473         if (strLen > 0) {
474             int len = length();
475             ensureCapacity(len + strLen);
476             str.getChars(0, strLen, buffer, len);
477             size += strLen;
478         }
479         return this;
480     }
481 
482     /**
483      * Appends part of a string to this string builder.
484      * Appending null will call {@link #appendNull()}.
485      *
486      * @param str  the string to append
487      * @param startIndex  the start index, inclusive, must be valid
488      * @param length  the length to append, must be valid
489      * @return this, to enable chaining
490      */
491     public StrBuilder append(String str, int startIndex, int length) {
492         if (str == null) {
493             return appendNull();
494         }
495         if (startIndex < 0 || startIndex > str.length()) {
496             throw new StringIndexOutOfBoundsException("startIndex must be valid");
497         }
498         if (length < 0 || (startIndex + length) > str.length()) {
499             throw new StringIndexOutOfBoundsException("length must be valid");
500         }
501         if (length > 0) {
502             int len = length();
503             ensureCapacity(len + length);
504             str.getChars(startIndex, startIndex + length, buffer, len);
505             size += length;
506         }
507         return this;
508     }
509 
510     /**
511      * Appends a string buffer to this string builder.
512      * Appending null will call {@link #appendNull()}.
513      *
514      * @param str  the string buffer to append
515      * @return this, to enable chaining
516      */
517     public StrBuilder append(StringBuffer str) {
518         if (str == null) {
519             return appendNull();
520         }
521         int strLen = str.length();
522         if (strLen > 0) {
523             int len = length();
524             ensureCapacity(len + strLen);
525             str.getChars(0, strLen, buffer, len);
526             size += strLen;
527         }
528         return this;
529     }
530 
531     /**
532      * Appends part of a string buffer to this string builder.
533      * Appending null will call {@link #appendNull()}.
534      *
535      * @param str  the string to append
536      * @param startIndex  the start index, inclusive, must be valid
537      * @param length  the length to append, must be valid
538      * @return this, to enable chaining
539      */
540     public StrBuilder append(StringBuffer str, int startIndex, int length) {
541         if (str == null) {
542             return appendNull();
543         }
544         if (startIndex < 0 || startIndex > str.length()) {
545             throw new StringIndexOutOfBoundsException("startIndex must be valid");
546         }
547         if (length < 0 || (startIndex + length) > str.length()) {
548             throw new StringIndexOutOfBoundsException("length must be valid");
549         }
550         if (length > 0) {
551             int len = length();
552             ensureCapacity(len + length);
553             str.getChars(startIndex, startIndex + length, buffer, len);
554             size += length;
555         }
556         return this;
557     }
558 
559     /**
560      * Appends another string builder to this string builder.
561      * Appending null will call {@link #appendNull()}.
562      *
563      * @param str  the string builder to append
564      * @return this, to enable chaining
565      */
566     public StrBuilder append(StrBuilder str) {
567         if (str == null) {
568             return appendNull();
569         }
570         int strLen = str.length();
571         if (strLen > 0) {
572             int len = length();
573             ensureCapacity(len + strLen);
574             System.arraycopy(str.buffer, 0, buffer, len, strLen);
575             size += strLen;
576         }
577         return this;
578     }
579 
580     /**
581      * Appends part of a string builder to this string builder.
582      * Appending null will call {@link #appendNull()}.
583      *
584      * @param str  the string to append
585      * @param startIndex  the start index, inclusive, must be valid
586      * @param length  the length to append, must be valid
587      * @return this, to enable chaining
588      */
589     public StrBuilder append(StrBuilder str, int startIndex, int length) {
590         if (str == null) {
591             return appendNull();
592         }
593         if (startIndex < 0 || startIndex > str.length()) {
594             throw new StringIndexOutOfBoundsException("startIndex must be valid");
595         }
596         if (length < 0 || (startIndex + length) > str.length()) {
597             throw new StringIndexOutOfBoundsException("length must be valid");
598         }
599         if (length > 0) {
600             int len = length();
601             ensureCapacity(len + length);
602             str.getChars(startIndex, startIndex + length, buffer, len);
603             size += length;
604         }
605         return this;
606     }
607 
608     /**
609      * Appends a char array to the string builder.
610      * Appending null will call {@link #appendNull()}.
611      *
612      * @param chars  the char array to append
613      * @return this, to enable chaining
614      */
615     public StrBuilder append(char[] chars) {
616         if (chars == null) {
617             return appendNull();
618         }
619         int strLen = chars.length;
620         if (strLen > 0) {
621             int len = length();
622             ensureCapacity(len + strLen);
623             System.arraycopy(chars, 0, buffer, len, strLen);
624             size += strLen;
625         }
626         return this;
627     }
628 
629     /**
630      * Appends a char array to the string builder.
631      * Appending null will call {@link #appendNull()}.
632      *
633      * @param chars  the char array to append
634      * @param startIndex  the start index, inclusive, must be valid
635      * @param length  the length to append, must be valid
636      * @return this, to enable chaining
637      */
638     public StrBuilder append(char[] chars, int startIndex, int length) {
639         if (chars == null) {
640             return appendNull();
641         }
642         if (startIndex < 0 || startIndex > chars.length) {
643             throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length);
644         }
645         if (length < 0 || (startIndex + length) > chars.length) {
646             throw new StringIndexOutOfBoundsException("Invalid length: " + length);
647         }
648         if (length > 0) {
649             int len = length();
650             ensureCapacity(len + length);
651             System.arraycopy(chars, startIndex, buffer, len, length);
652             size += length;
653         }
654         return this;
655     }
656 
657     /**
658      * Appends a boolean value to the string builder.
659      *
660      * @param value  the value to append
661      * @return this, to enable chaining
662      */
663     public StrBuilder append(boolean value) {
664         if (value) {
665             ensureCapacity(size + 4);
666             buffer[size++] = 't';
667             buffer[size++] = 'r';
668             buffer[size++] = 'u';
669             buffer[size++] = 'e';
670         } else {
671             ensureCapacity(size + 5);
672             buffer[size++] = 'f';
673             buffer[size++] = 'a';
674             buffer[size++] = 'l';
675             buffer[size++] = 's';
676             buffer[size++] = 'e';
677         }
678         return this;
679     }
680 
681     /**
682      * Appends a char value to the string builder.
683      *
684      * @param ch  the value to append
685      * @return this, to enable chaining
686      */
687     public StrBuilder append(char ch) {
688         int len = length();
689         ensureCapacity(len + 1);
690         buffer[size++] = ch;
691         return this;
692     }
693 
694     /**
695      * Appends an int value to the string builder using <code>String.valueOf</code>.
696      *
697      * @param value  the value to append
698      * @return this, to enable chaining
699      */
700     public StrBuilder append(int value) {
701         return append(String.valueOf(value));
702     }
703 
704     /**
705      * Appends a long value to the string builder using <code>String.valueOf</code>.
706      *
707      * @param value  the value to append
708      * @return this, to enable chaining
709      */
710     public StrBuilder append(long value) {
711         return append(String.valueOf(value));
712     }
713 
714     /**
715      * Appends a float value to the string builder using <code>String.valueOf</code>.
716      *
717      * @param value  the value to append
718      * @return this, to enable chaining
719      */
720     public StrBuilder append(float value) {
721         return append(String.valueOf(value));
722     }
723 
724     /**
725      * Appends a double value to the string builder using <code>String.valueOf</code>.
726      *
727      * @param value  the value to append
728      * @return this, to enable chaining
729      */
730     public StrBuilder append(double value) {
731         return append(String.valueOf(value));
732     }
733 
734     //-----------------------------------------------------------------------
735     /**
736      * Appends an object followed by a new line to this string builder.
737      * Appending null will call {@link #appendNull()}.
738      *
739      * @param obj  the object to append
740      * @return this, to enable chaining
741      * @since 2.3
742      */
743     public StrBuilder appendln(Object obj) {
744         return append(obj).appendNewLine();
745     }
746 
747     /**
748      * Appends a string followed by a new line to this string builder.
749      * Appending null will call {@link #appendNull()}.
750      *
751      * @param str  the string to append
752      * @return this, to enable chaining
753      * @since 2.3
754      */
755     public StrBuilder appendln(String str) {
756         return append(str).appendNewLine();
757     }
758 
759     /**
760      * Appends part of a string followed by a new line to this string builder.
761      * Appending null will call {@link #appendNull()}.
762      *
763      * @param str  the string to append
764      * @param startIndex  the start index, inclusive, must be valid
765      * @param length  the length to append, must be valid
766      * @return this, to enable chaining
767      * @since 2.3
768      */
769     public StrBuilder appendln(String str, int startIndex, int length) {
770         return append(str, startIndex, length).appendNewLine();
771     }
772 
773     /**
774      * Appends a string buffer followed by a new line to this string builder.
775      * Appending null will call {@link #appendNull()}.
776      *
777      * @param str  the string buffer to append
778      * @return this, to enable chaining
779      * @since 2.3
780      */
781     public StrBuilder appendln(StringBuffer str) {
782         return append(str).appendNewLine();
783     }
784 
785     /**
786      * Appends part of a string buffer followed by a new line to this string builder.
787      * Appending null will call {@link #appendNull()}.
788      *
789      * @param str  the string to append
790      * @param startIndex  the start index, inclusive, must be valid
791      * @param length  the length to append, must be valid
792      * @return this, to enable chaining
793      * @since 2.3
794      */
795     public StrBuilder appendln(StringBuffer str, int startIndex, int length) {
796         return append(str, startIndex, length).appendNewLine();
797     }
798 
799     /**
800      * Appends another string builder followed by a new line to this string builder.
801      * Appending null will call {@link #appendNull()}.
802      *
803      * @param str  the string builder to append
804      * @return this, to enable chaining
805      * @since 2.3
806      */
807     public StrBuilder appendln(StrBuilder str) {
808         return append(str).appendNewLine();
809     }
810 
811     /**
812      * Appends part of a string builder followed by a new line to this string builder.
813      * Appending null will call {@link #appendNull()}.
814      *
815      * @param str  the string to append
816      * @param startIndex  the start index, inclusive, must be valid
817      * @param length  the length to append, must be valid
818      * @return this, to enable chaining
819      * @since 2.3
820      */
821     public StrBuilder appendln(StrBuilder str, int startIndex, int length) {
822         return append(str, startIndex, length).appendNewLine();
823     }
824 
825     /**
826      * Appends a char array followed by a new line to the string builder.
827      * Appending null will call {@link #appendNull()}.
828      *
829      * @param chars  the char array to append
830      * @return this, to enable chaining
831      * @since 2.3
832      */
833     public StrBuilder appendln(char[] chars) {
834         return append(chars).appendNewLine();
835     }
836 
837     /**
838      * Appends a char array followed by a new line to the string builder.
839      * Appending null will call {@link #appendNull()}.
840      *
841      * @param chars  the char array to append
842      * @param startIndex  the start index, inclusive, must be valid
843      * @param length  the length to append, must be valid
844      * @return this, to enable chaining
845      * @since 2.3
846      */
847     public StrBuilder appendln(char[] chars, int startIndex, int length) {
848         return append(chars, startIndex, length).appendNewLine();
849     }
850 
851     /**
852      * Appends a boolean value followed by a new line to the string builder.
853      *
854      * @param value  the value to append
855      * @return this, to enable chaining
856      * @since 2.3
857      */
858     public StrBuilder appendln(boolean value) {
859         return append(value).appendNewLine();
860     }
861 
862     /**
863      * Appends a char value followed by a new line to the string builder.
864      *
865      * @param ch  the value to append
866      * @return this, to enable chaining
867      * @since 2.3
868      */
869     public StrBuilder appendln(char ch) {
870         return append(ch).appendNewLine();
871     }
872 
873     /**
874      * Appends an int value followed by a new line to the string builder using <code>String.valueOf</code>.
875      *
876      * @param value  the value to append
877      * @return this, to enable chaining
878      * @since 2.3
879      */
880     public StrBuilder appendln(int value) {
881         return append(value).appendNewLine();
882     }
883 
884     /**
885      * Appends a long value followed by a new line to the string builder using <code>String.valueOf</code>.
886      *
887      * @param value  the value to append
888      * @return this, to enable chaining
889      * @since 2.3
890      */
891     public StrBuilder appendln(long value) {
892         return append(value).appendNewLine();
893     }
894 
895     /**
896      * Appends a float value followed by a new line to the string builder using <code>String.valueOf</code>.
897      *
898      * @param value  the value to append
899      * @return this, to enable chaining
900      * @since 2.3
901      */
902     public StrBuilder appendln(float value) {
903         return append(value).appendNewLine();
904     }
905 
906     /**
907      * Appends a double value followed by a new line to the string builder using <code>String.valueOf</code>.
908      *
909      * @param value  the value to append
910      * @return this, to enable chaining
911      * @since 2.3
912      */
913     public StrBuilder appendln(double value) {
914         return append(value).appendNewLine();
915     }
916 
917     //-----------------------------------------------------------------------
918     /**
919      * Appends each item in an array to the builder without any separators.
920      * Appending a null array will have no effect.
921      * Each object is appended using {@link #append(Object)}.
922      *
923      * @param array  the array to append
924      * @return this, to enable chaining
925      * @since 2.3
926      */
927     public StrBuilder appendAll(Object[] array) {
928         if (array != null && array.length > 0) {
929             for (int i = 0; i < array.length; i++) {
930                 append(array[i]);
931             }
932         }
933         return this;
934     }
935 
936     /**
937      * Appends each item in a collection to the builder without any separators.
938      * Appending a null collection will have no effect.
939      * Each object is appended using {@link #append(Object)}.
940      *
941      * @param coll  the collection to append
942      * @return this, to enable chaining
943      * @since 2.3
944      */
945     public StrBuilder appendAll(Collection coll) {
946         if (coll != null && coll.size() > 0) {
947             Iterator it = coll.iterator();
948             while (it.hasNext()) {
949                 append(it.next());
950             }
951         }
952         return this;
953     }
954 
955     /**
956      * Appends each item in an iterator to the builder without any separators.
957      * Appending a null iterator will have no effect.
958      * Each object is appended using {@link #append(Object)}.
959      *
960      * @param it  the iterator to append
961      * @return this, to enable chaining
962      * @since 2.3
963      */
964     public StrBuilder appendAll(Iterator it) {
965         if (it != null) {
966             while (it.hasNext()) {
967                 append(it.next());
968             }
969         }
970         return this;
971     }
972 
973     //-----------------------------------------------------------------------
974     /**
975      * Appends an array placing separators between each value, but
976      * not before the first or after the last.
977      * Appending a null array will have no effect.
978      * Each object is appended using {@link #append(Object)}.
979      *
980      * @param array  the array to append
981      * @param separator  the separator to use, null means no separator
982      * @return this, to enable chaining
983      */
984     public StrBuilder appendWithSeparators(Object[] array, String separator) {
985         if (array != null && array.length > 0) {
986             separator = (separator == null ? "" : separator);
987             append(array[0]);
988             for (int i = 1; i < array.length; i++) {
989                 append(separator);
990                 append(array[i]);
991             }
992         }
993         return this;
994     }
995 
996     /**
997      * Appends a collection placing separators between each value, but
998      * not before the first or after the last.
999      * Appending a null collection will have no effect.
1000      * Each object is appended using {@link #append(Object)}.
1001      *
1002      * @param coll  the collection to append
1003      * @param separator  the separator to use, null means no separator
1004      * @return this, to enable chaining
1005      */
1006     public StrBuilder appendWithSeparators(Collection coll, String separator) {
1007         if (coll != null && coll.size() > 0) {
1008             separator = (separator == null ? "" : separator);
1009             Iterator it = coll.iterator();
1010             while (it.hasNext()) {
1011                 append(it.next());
1012                 if (it.hasNext()) {
1013                     append(separator);
1014                 }
1015             }
1016         }
1017         return this;
1018     }
1019 
1020     /**
1021      * Appends an iterator placing separators between each value, but
1022      * not before the first or after the last.
1023      * Appending a null iterator will have no effect.
1024      * Each object is appended using {@link #append(Object)}.
1025      *
1026      * @param it  the iterator to append
1027      * @param separator  the separator to use, null means no separator
1028      * @return this, to enable chaining
1029      */
1030     public StrBuilder appendWithSeparators(Iterator it, String separator) {
1031         if (it != null) {
1032             separator = (separator == null ? "" : separator);
1033             while (it.hasNext()) {
1034                 append(it.next());
1035                 if (it.hasNext()) {
1036                     append(separator);
1037                 }
1038             }
1039         }
1040         return this;
1041     }
1042 
1043     //-----------------------------------------------------------------------
1044     /**
1045      * Appends a separator if the builder is currently non-empty.
1046      * Appending a null separator will have no effect.
1047      * The separator is appended using {@link #append(String)}.
1048      * <p>
1049      * This method is useful for adding a separator each time around the
1050      * loop except the first.
1051      * <pre>
1052      * for (Iterator it = list.iterator(); it.hasNext(); ) {
1053      *   appendSeparator(",");
1054      *   append(it.next());
1055      * }
1056      * </pre>
1057      * Note that for this simple example, you should use
1058      * {@link #appendWithSeparators(Collection, String)}.
1059      * 
1060      * @param separator  the separator to use, null means no separator
1061      * @return this, to enable chaining
1062      * @since 2.3
1063      */
1064     public StrBuilder appendSeparator(String separator) {
1065         if (separator != null && size() > 0) {
1066             append(separator);
1067         }
1068         return this;
1069     }
1070 
1071     /**
1072      * Appends a separator if the builder is currently non-empty.
1073      * The separator is appended using {@link #append(char)}.
1074      * <p>
1075      * This method is useful for adding a separator each time around the
1076      * loop except the first.
1077      * <pre>
1078      * for (Iterator it = list.iterator(); it.hasNext(); ) {
1079      *   appendSeparator(',');
1080      *   append(it.next());
1081      * }
1082      * </pre>
1083      * Note that for this simple example, you should use
1084      * {@link #appendWithSeparators(Collection, String)}.
1085      * 
1086      * @param separator  the separator to use
1087      * @return this, to enable chaining
1088      * @since 2.3
1089      */
1090     public StrBuilder appendSeparator(char separator) {
1091         if (size() > 0) {
1092             append(separator);
1093         }
1094         return this;
1095     }
1096 
1097     /**
1098      * Appends a separator to the builder if the loop index is greater than zero.
1099      * Appending a null separator will have no effect.
1100      * The separator is appended using {@link #append(String)}.
1101      * <p>
1102      * This method is useful for adding a separator each time around the
1103      * loop except the first.
1104      * <pre>
1105      * for (int i = 0; i < list.size(); i++) {
1106      *   appendSeparator(",", i);
1107      *   append(list.get(i));
1108      * }
1109      * </pre>
1110      * Note that for this simple example, you should use
1111      * {@link #appendWithSeparators(Collection, String)}.
1112      * 
1113      * @param separator  the separator to use, null means no separator
1114      * @param loopIndex  the loop index
1115      * @return this, to enable chaining
1116      * @since 2.3
1117      */
1118     public StrBuilder appendSeparator(String separator, int loopIndex) {
1119         if (separator != null && loopIndex > 0) {
1120             append(separator);
1121         }
1122         return this;
1123     }
1124 
1125     /**
1126      * Appends a separator to the builder if the loop index is greater than zero.
1127      * The separator is appended using {@link #append(char)}.
1128      * <p>
1129      * This method is useful for adding a separator each time around the
1130      * loop except the first.
1131      * <pre>
1132      * for (int i = 0; i < list.size(); i++) {
1133      *   appendSeparator(",", i);
1134      *   append(list.get(i));
1135      * }
1136      * </pre>
1137      * Note that for this simple example, you should use
1138      * {@link #appendWithSeparators(Collection, String)}.
1139      * 
1140      * @param separator  the separator to use
1141      * @param loopIndex  the loop index
1142      * @return this, to enable chaining
1143      * @since 2.3
1144      */
1145     public StrBuilder appendSeparator(char separator, int loopIndex) {
1146         if (loopIndex > 0) {
1147             append(separator);
1148         }
1149         return this;
1150     }
1151 
1152     //-----------------------------------------------------------------------
1153     /**
1154      * Appends the pad character to the builder the specified number of times.
1155      * 
1156      * @param length  the length to append, negative means no append
1157      * @param padChar  the character to append
1158      * @return this, to enable chaining
1159      */
1160     public StrBuilder appendPadding(int length, char padChar) {
1161         if (length >= 0) {
1162             ensureCapacity(size + length);
1163             for (int i = 0; i < length; i++) {
1164                 buffer[size++] = padChar;
1165             }
1166         }
1167         return this;
1168     }
1169 
1170     //-----------------------------------------------------------------------
1171     /**
1172      * Appends an object to the builder padding on the left to a fixed width.
1173      * The <code>toString</code> of the object is used.
1174      * If the object is larger than the length, the left hand side is lost.
1175      * If the object is null, the null text value is used.
1176      * 
1177      * @param obj  the object to append, null uses null text
1178      * @param width  the fixed field width, zero or negative has no effect
1179      * @param padChar  the pad character to use
1180      * @return this, to enable chaining
1181      */
1182     public StrBuilder appendFixedWidthPadLeft(Object obj, int width, char padChar) {
1183         if (width > 0) {
1184             ensureCapacity(size + width);
1185             String str = (obj == null ? getNullText() : obj.toString());
1186             if (str == null) {
1187                 str = "";
1188             }
1189             int strLen = str.length();
1190             if (strLen >= width) {
1191                 str.getChars(strLen - width, strLen, buffer, size);
1192             } else {
1193                 int padLen = width - strLen;
1194                 for (int i = 0; i < padLen; i++) {
1195                     buffer[size + i] = padChar;
1196                 }
1197                 str.getChars(0, strLen, buffer, size + padLen);
1198             }
1199             size += width;
1200         }
1201         return this;
1202     }
1203 
1204     /**
1205      * Appends an object to the builder padding on the left to a fixed width.
1206      * The <code>String.valueOf</code> of the <code>int</code> value is used.
1207      * If the formatted value is larger than the length, the left hand side is lost.
1208      * 
1209      * @param value  the value to append
1210      * @param width  the fixed field width, zero or negative has no effect
1211      * @param padChar  the pad character to use
1212      * @return this, to enable chaining
1213      */
1214     public StrBuilder appendFixedWidthPadLeft(int value, int width, char padChar) {
1215         return appendFixedWidthPadLeft(String.valueOf(value), width, padChar);
1216     }
1217 
1218     /**
1219      * Appends an object to the builder padding on the right to a fixed length.
1220      * The <code>toString</code> of the object is used.
1221      * If the object is larger than the length, the right hand side is lost.
1222      * If the object is null, null text value is used.
1223      * 
1224      * @param obj  the object to append, null uses null text
1225      * @param width  the fixed field width, zero or negative has no effect
1226      * @param padChar  the pad character to use
1227      * @return this, to enable chaining
1228      */
1229     public StrBuilder appendFixedWidthPadRight(Object obj, int width, char padChar) {
1230         if (width > 0) {
1231             ensureCapacity(size + width);
1232             String str = (obj == null ? getNullText() : obj.toString());
1233             if (str == null) {
1234                 str = "";
1235             }
1236             int strLen = str.length();
1237             if (strLen >= width) {
1238                 str.getChars(0, width, buffer, size);
1239             } else {
1240                 int padLen = width - strLen;
1241                 str.getChars(0, strLen, buffer, size);
1242                 for (int i = 0; i < padLen; i++) {
1243                     buffer[size + strLen + i] = padChar;
1244                 }
1245             }
1246             size += width;
1247         }
1248         return