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