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 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.text;
18
19 import java.io.IOException;
20 import java.io.Reader;
21 import java.io.Serializable;
22 import java.io.Writer;
23 import java.nio.CharBuffer;
24 import java.util.Arrays;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Objects;
28
29 import org.apache.commons.lang3.ArrayUtils;
30 import org.apache.commons.lang3.CharUtils;
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.commons.text.matcher.StringMatcher;
33
34 /**
35 * Builds a string from constituent parts providing a more flexible and powerful API than {@link StringBuffer} and
36 * {@link StringBuilder}.
37 * <p>
38 * The main differences from StringBuffer/StringBuilder are:
39 * </p>
40 * <ul>
41 * <li>Not synchronized</li>
42 * <li>Not final</li>
43 * <li>Subclasses have direct access to character array</li>
44 * <li>Additional methods
45 * <ul>
46 * <li>appendWithSeparators - adds an array of values, with a separator</li>
47 * <li>appendPadding - adds a length padding characters</li>
48 * <li>appendFixedLength - adds a fixed width field to the builder</li>
49 * <li>toCharArray/getChars - simpler ways to get a range of the character array</li>
50 * <li>delete - delete char or string</li>
51 * <li>replace - search and replace for a char or string</li>
52 * <li>leftString/rightString/midString - substring without exceptions</li>
53 * <li>contains - whether the builder contains a char or string</li>
54 * <li>size/clear/isEmpty - collections style API methods</li>
55 * </ul>
56 * </li>
57 * <li>Views
58 * <ul>
59 * <li>asTokenizer - uses the internal buffer as the source of a StrTokenizer</li>
60 * <li>asReader - uses the internal buffer as the source of a Reader</li>
61 * <li>asWriter - allows a Writer to write directly to the internal buffer</li>
62 * </ul>
63 * </li>
64 * </ul>
65 * <p>
66 * The aim has been to provide an API that mimics very closely what StringBuffer provides, but with additional methods.
67 * It should be noted that some edge cases, with invalid indices or null input, have been altered - see individual
68 * methods. The biggest of these changes is that by default, null will not output the text 'null'. This can be
69 * controlled by a property, {@link #setNullText(String)}.
70 * </p>
71 * <p>
72 * This class is called {@code TextStringBuilder} instead of {@code StringBuilder} to avoid clashing with
73 * {@link StringBuilder}.
74 * </p>
75 *
76 * @since 1.3
77 */
78 public class TextStringBuilder implements CharSequence, Appendable, Serializable, Builder<String> {
79
80 /**
81 * Inner class to allow StrBuilder to operate as a reader.
82 */
83 final class TextStringBuilderReader extends Reader {
84
85 /** The last mark position. */
86 private int mark;
87
88 /** The current stream position. */
89 private int pos;
90
91 /**
92 * Default constructor.
93 */
94 TextStringBuilderReader() {
95 }
96
97 /** {@inheritDoc} */
98 @Override
99 public void close() {
100 // do nothing
101 }
102
103 /** {@inheritDoc} */
104 @Override
105 public void mark(final int readAheadLimit) {
106 mark = pos;
107 }
108
109 /** {@inheritDoc} */
110 @Override
111 public boolean markSupported() {
112 return true;
113 }
114
115 /** {@inheritDoc} */
116 @Override
117 public int read() {
118 return ready() ? charAt(pos++) : -1;
119 }
120
121 /** {@inheritDoc} */
122 @Override
123 public int read(final char[] b, final int off, int len) {
124 if (off < 0 || len < 0 || off > b.length || off + len > b.length || off + len < 0) {
125 throw new IndexOutOfBoundsException();
126 }
127 if (len == 0) {
128 return 0;
129 }
130 if (pos >= size()) {
131 return -1;
132 }
133 if (pos + len > size()) {
134 len = size() - pos;
135 }
136 TextStringBuilder.this.getChars(pos, pos + len, b, off);
137 pos += len;
138 return len;
139 }
140
141 /** {@inheritDoc} */
142 @Override
143 public boolean ready() {
144 return pos < size();
145 }
146
147 /** {@inheritDoc} */
148 @Override
149 public void reset() {
150 pos = mark;
151 }
152
153 /** {@inheritDoc} */
154 @Override
155 public long skip(long n) {
156 if (pos + n > size()) {
157 n = size() - pos;
158 }
159 if (n < 0) {
160 return 0;
161 }
162 pos = Math.addExact(pos, Math.toIntExact(n));
163 return n;
164 }
165 }
166
167 /**
168 * Inner class to allow StrBuilder to operate as a tokenizer.
169 */
170 final class TextStringBuilderTokenizer extends StringTokenizer {
171
172 /**
173 * Default constructor.
174 */
175 TextStringBuilderTokenizer() {
176 }
177
178 /** {@inheritDoc} */
179 @Override
180 public String getContent() {
181 final String str = super.getContent();
182 return str != null ? str : TextStringBuilder.this.toString();
183 }
184
185 /** {@inheritDoc} */
186 @Override
187 protected List<String> tokenize(final char[] chars, final int offset, final int count) {
188 if (chars == null) {
189 return super.tokenize(getBuffer(), 0, TextStringBuilder.this.size());
190 }
191 return super.tokenize(chars, offset, count);
192 }
193 }
194
195 /**
196 * Inner class to allow StrBuilder to operate as a writer.
197 */
198 final class TextStringBuilderWriter extends Writer {
199
200 /**
201 * Default constructor.
202 */
203 TextStringBuilderWriter() {
204 }
205
206 /** {@inheritDoc} */
207 @Override
208 public void close() {
209 // do nothing
210 }
211
212 /** {@inheritDoc} */
213 @Override
214 public void flush() {
215 // do nothing
216 }
217
218 /** {@inheritDoc} */
219 @Override
220 public void write(final char[] cbuf) {
221 TextStringBuilder.this.append(cbuf);
222 }
223
224 /** {@inheritDoc} */
225 @Override
226 public void write(final char[] cbuf, final int off, final int len) {
227 TextStringBuilder.this.append(cbuf, off, len);
228 }
229
230 /** {@inheritDoc} */
231 @Override
232 public void write(final int c) {
233 TextStringBuilder.this.append((char) c);
234 }
235
236 /** {@inheritDoc} */
237 @Override
238 public void write(final String str) {
239 TextStringBuilder.this.append(str);
240 }
241
242 /** {@inheritDoc} */
243 @Override
244 public void write(final String str, final int off, final int len) {
245 TextStringBuilder.this.append(str, off, len);
246 }
247 }
248
249 /** The space character. */
250 private static final char SPACE = ' ';
251
252 /**
253 * The extra capacity for new builders.
254 */
255 static final int CAPACITY = 32;
256
257 /**
258 * End-Of-Stream.
259 */
260 private static final int EOS = -1;
261
262 /**
263 * The size of the string {@code "false"}.
264 */
265 private static final int FALSE_STRING_SIZE = Boolean.FALSE.toString().length();
266
267 /**
268 * Required for serialization support.
269 *
270 * @see java.io.Serializable
271 */
272 private static final long serialVersionUID = 1L;
273
274 /**
275 * The size of the string {@code "true"}.
276 */
277 private static final int TRUE_STRING_SIZE = Boolean.TRUE.toString().length();
278
279 /**
280 * The maximum size buffer to allocate.
281 *
282 * <p>This is set to the same size used in the JDK {@link java.util.ArrayList}:</p>
283 * <blockquote>
284 * Some VMs reserve some header words in an array.
285 * Attempts to allocate larger arrays may result in
286 * OutOfMemoryError: Requested array size exceeds VM limit.
287 * </blockquote>
288 */
289 private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
290
291 /**
292 * Creates a positive capacity at least as large the minimum required capacity.
293 * If the minimum capacity is negative then this throws an OutOfMemoryError as no array
294 * can be allocated.
295 *
296 * @param minCapacity The minimum capacity
297 * @return The capacity
298 * @throws OutOfMemoryError if the {@code minCapacity} is negative
299 */
300 private static int createPositiveCapacity(final int minCapacity) {
301 if (minCapacity < 0) {
302 // overflow
303 throw new OutOfMemoryError("Unable to allocate array size: " + Integer.toUnsignedString(minCapacity));
304 }
305 // This is called when we require buffer expansion to a very big array.
306 // Use the conservative maximum buffer size if possible, otherwise the biggest required.
307 //
308 // Note: In this situation JDK 1.8 java.util.ArrayList returns Integer.MAX_VALUE.
309 // This excludes some VMs that can exceed MAX_BUFFER_SIZE but not allocate a full
310 // Integer.MAX_VALUE length array.
311 // The result is that we may have to allocate an array of this size more than once if
312 // the capacity must be expanded again.
313 return Math.max(minCapacity, MAX_BUFFER_SIZE);
314 }
315
316 /**
317 * Constructs an instance from a reference to a character array. Changes to the input chars are reflected in this
318 * instance until the internal buffer needs to be reallocated. Using a reference to an array allows the instance to
319 * be initialized without copying the input array.
320 *
321 * @param initialBuffer The initial array that will back the new builder.
322 * @return A new instance.
323 * @since 1.9
324 */
325 public static TextStringBuilder wrap(final char[] initialBuffer) {
326 Objects.requireNonNull(initialBuffer, "initialBuffer");
327 return new TextStringBuilder(initialBuffer, initialBuffer.length);
328 }
329
330 /**
331 * Constructs an instance from a reference to a character array. Changes to the input chars are reflected in this
332 * instance until the internal buffer needs to be reallocated. Using a reference to an array allows the instance to
333 * be initialized without copying the input array.
334 *
335 * @param initialBuffer The initial array that will back the new builder.
336 * @param length The length of the subarray to be used; must be non-negative and no larger than
337 * {@code initialBuffer.length}. The new builder's size will be set to {@code length}.
338 * @return A new instance.
339 * @since 1.9
340 */
341 public static TextStringBuilder wrap(final char[] initialBuffer, final int length) {
342 return new TextStringBuilder(initialBuffer, length);
343 }
344
345 /** Internal data storage. */
346 private char[] buffer;
347
348 /**
349 * The new line, {@code null} means use the system default from {@link System#lineSeparator()}.
350 */
351 private String newLine;
352
353 /** The null text. */
354 private String nullText;
355
356 /** Incremented when the buffer is reallocated. */
357 private int reallocations;
358
359 /** Current size of the buffer. */
360 private int size;
361
362 /**
363 * Constructs an empty builder with an initial capacity of 32 characters.
364 */
365 public TextStringBuilder() {
366 this(CAPACITY);
367 }
368
369 /**
370 * Constructs an instance from a reference to a character array.
371 *
372 * @param initialBuffer A reference to a character array, must not be null.
373 * @param length The length of the subarray to be used; must be non-negative and no larger than {@code initialBuffer.length}. The new builder's size
374 * will be set to {@code length}.
375 * @throws NullPointerException If {@code initialBuffer} is null.
376 * @throws IllegalArgumentException if {@code length} is bad.
377 */
378 private TextStringBuilder(final char[] initialBuffer, final int length) {
379 this.buffer = Objects.requireNonNull(initialBuffer, "initialBuffer");
380 if (length < 0 || length > initialBuffer.length) {
381 throw new IllegalArgumentException("initialBuffer.length=" + initialBuffer.length + ", length=" + length);
382 }
383 this.size = length;
384 }
385
386 /**
387 * Constructs an instance from a character sequence, allocating 32 extra characters for growth.
388 *
389 * @param seq The string to copy, null treated as blank string.
390 * @since 1.9
391 */
392 public TextStringBuilder(final CharSequence seq) {
393 this(StringUtils.length(seq) + CAPACITY);
394 if (seq != null) {
395 append(seq);
396 }
397 }
398
399 /**
400 * Constructs an instance with the specified initial capacity.
401 *
402 * @param initialCapacity The initial capacity, zero or less will be converted to 32.
403 */
404 public TextStringBuilder(final int initialCapacity) {
405 buffer = new char[initialCapacity <= 0 ? CAPACITY : initialCapacity];
406 }
407
408 /**
409 * Constructs an instance from a string, allocating 32 extra characters for growth.
410 *
411 * @param str The string to copy, null treated as blank string.
412 */
413 public TextStringBuilder(final String str) {
414 this(StringUtils.length(str) + CAPACITY);
415 if (str != null) {
416 append(str);
417 }
418 }
419
420 /**
421 * Appends a boolean value to the string builder.
422 *
423 * @param value The value to append.
424 * @return {@code this} instance.
425 */
426 public TextStringBuilder append(final boolean value) {
427 if (value) {
428 ensureCapacityInternal(size + TRUE_STRING_SIZE);
429 appendTrue(size);
430 } else {
431 ensureCapacityInternal(size + FALSE_STRING_SIZE);
432 appendFalse(size);
433 }
434 return this;
435 }
436
437 /**
438 * Appends a char value to the string builder.
439 *
440 * @param ch The value to append.
441 * @return {@code this} instance.
442 */
443 @Override
444 public TextStringBuilder append(final char ch) {
445 final int len = length();
446 ensureCapacityInternal(len + 1);
447 buffer[size++] = ch;
448 return this;
449 }
450
451 /**
452 * Appends a char array to the string builder. Appending null will call {@link #appendNull()}.
453 *
454 * @param chars The char array to append.
455 * @return {@code this} instance.
456 */
457 public TextStringBuilder append(final char[] chars) {
458 if (chars == null) {
459 return appendNull();
460 }
461 final int strLen = chars.length;
462 if (strLen > 0) {
463 final int len = length();
464 ensureCapacityInternal(len + strLen);
465 System.arraycopy(chars, 0, buffer, len, strLen);
466 size += strLen;
467 }
468 return this;
469 }
470
471 /**
472 * Appends a char array to the string builder. Appending null will call {@link #appendNull()}.
473 *
474 * @param chars The char array to append.
475 * @param startIndex The start index, inclusive, must be valid.
476 * @param length The length to append, must be valid.
477 * @return {@code this} instance.
478 * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the range {@code 0 <= startIndex <= chars.length}.
479 * @throws StringIndexOutOfBoundsException if {@code length < 0}.
480 * @throws StringIndexOutOfBoundsException if {@code startIndex + length > chars.length}.
481 */
482 public TextStringBuilder append(final char[] chars, final int startIndex, final int length) {
483 if (chars == null) {
484 return appendNull();
485 }
486 if (startIndex < 0 || startIndex > chars.length) {
487 throw new StringIndexOutOfBoundsException("Invalid startIndex: " + startIndex);
488 }
489 if (length < 0 || startIndex + length > chars.length) {
490 throw new StringIndexOutOfBoundsException("Invalid length: " + length);
491 }
492 if (length > 0) {
493 final int len = length();
494 ensureCapacityInternal(len + length);
495 System.arraycopy(chars, startIndex, buffer, len, length);
496 size += length;
497 }
498 return this;
499 }
500
501 /**
502 * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}.
503 *
504 * @param str The char buffer to append.
505 * @return {@code this} instance.
506 */
507 public TextStringBuilder append(final CharBuffer str) {
508 return append(str, 0, StringUtils.length(str));
509 }
510
511 /**
512 * Appends the contents of a char buffer to this string builder. Appending null will call {@link #appendNull()}.
513 *
514 * @param buf The char buffer to append.
515 * @param startIndex The start index, inclusive, must be valid.
516 * @param length The length to append, must be valid.
517 * @return {@code this} instance.
518 */
519 public TextStringBuilder append(final CharBuffer buf, final int startIndex, final int length) {
520 if (buf == null) {
521 return appendNull();
522 }
523 if (buf.hasArray()) {
524 final int totalLength = buf.remaining();
525 if (startIndex < 0 || startIndex > totalLength) {
526 throw new StringIndexOutOfBoundsException("startIndex must be valid");
527 }
528 if (length < 0 || startIndex + length > totalLength) {
529 throw new StringIndexOutOfBoundsException("length must be valid");
530 }
531 final int len = length();
532 ensureCapacityInternal(len + length);
533 System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length);
534 size += length;
535 } else {
536 append(buf.toString(), startIndex, length);
537 }
538 return this;
539 }
540
541 /**
542 * Appends a CharSequence to this string builder. Appending null will call {@link #appendNull()}.
543 *
544 * @param seq The CharSequence to append.
545 * @return {@code this} instance.
546 */
547 @Override
548 public TextStringBuilder append(final CharSequence seq) {
549 if (seq == null) {
550 return appendNull();
551 }
552 if (seq instanceof TextStringBuilder) {
553 return append((TextStringBuilder) seq);
554 }
555 if (seq instanceof StringBuilder) {
556 return append((StringBuilder) seq);
557 }
558 if (seq instanceof StringBuffer) {
559 return append((StringBuffer) seq);
560 }
561 if (seq instanceof CharBuffer) {
562 return append((CharBuffer) seq);
563 }
564 return append(seq.toString());
565 }
566
567 /**
568 * Appends part of a CharSequence to this string builder. Appending null will call {@link #appendNull()}.
569 *
570 * @param seq The CharSequence to append.
571 * @param startIndex The start index, inclusive, must be valid.
572 * @param endIndex The end index, exclusive, must be valid.
573 * @return {@code this} instance.
574 */
575 @Override
576 public TextStringBuilder append(final CharSequence seq, final int startIndex, final int endIndex) {
577 if (seq == null) {
578 return appendNull();
579 }
580 if (endIndex <= 0) {
581 throw new StringIndexOutOfBoundsException("endIndex must be valid");
582 }
583 if (startIndex >= endIndex) {
584 throw new StringIndexOutOfBoundsException("endIndex must be greater than startIndex");
585 }
586 return append(seq.toString(), startIndex, endIndex - startIndex);
587 }
588
589 /**
590 * Appends a double value to the string builder using {@code String.valueOf}.
591 *
592 * @param value The value to append.
593 * @return {@code this} instance.
594 */
595 public TextStringBuilder append(final double value) {
596 return append(String.valueOf(value));
597 }
598
599 /**
600 * Appends a float value to the string builder using {@code String.valueOf}.
601 *
602 * @param value The value to append.
603 * @return {@code this} instance.
604 */
605 public TextStringBuilder append(final float value) {
606 return append(String.valueOf(value));
607 }
608
609 /**
610 * Appends an int value to the string builder using {@code String.valueOf}.
611 *
612 * @param value The value to append.
613 * @return {@code this} instance.
614 */
615 public TextStringBuilder append(final int value) {
616 return append(String.valueOf(value));
617 }
618
619 /**
620 * Appends a long value to the string builder using {@code String.valueOf}.
621 *
622 * @param value The value to append.
623 * @return {@code this} instance.
624 */
625 public TextStringBuilder append(final long value) {
626 return append(String.valueOf(value));
627 }
628
629 /**
630 * Appends an object to this string builder. Appending null will call {@link #appendNull()}.
631 *
632 * @param obj The object to append.
633 * @return {@code this} instance.
634 */
635 public TextStringBuilder append(final Object obj) {
636 if (obj == null) {
637 return appendNull();
638 }
639 if (obj instanceof CharSequence) {
640 return append((CharSequence) obj);
641 }
642 return append(obj.toString());
643 }
644
645 /**
646 * Appends a string to this string builder. Appending null will call {@link #appendNull()}.
647 *
648 * @param str The string to append.
649 * @return {@code this} instance.
650 */
651 public TextStringBuilder append(final String str) {
652 return append(str, 0, StringUtils.length(str));
653 }
654
655 /**
656 * Appends part of a string to this string builder. Appending null will call {@link #appendNull()}.
657 *
658 * @param str The string to append.
659 * @param startIndex The start index, inclusive, must be valid.
660 * @param length The length to append, must be valid.
661 * @return {@code this} instance.
662 * @throws StringIndexOutOfBoundsException if {@code startIndex} is not in the range {@code 0 <= startIndex <= str.length()}.
663 * @throws StringIndexOutOfBoundsException if {@code length < 0}.
664 * @throws StringIndexOutOfBoundsException if {@code startIndex + length > str.length()}.
665 */
666 public TextStringBuilder append(final String str, final int startIndex, final int length) {
667 if (str == null) {
668 return appendNull();
669 }
670 validateRange(startIndex, length, str.length());
671 if (length > 0) {
672 final int len = length();
673 ensureCapacityInternal(len + length);
674 str.getChars(startIndex, startIndex + length, buffer, len);
675 size += length;
676 }
677 return this;
678 }
679
680 /**
681 * Calls {@link String#format(String, Object...)} and appends the result.
682 *
683 * @param format The format string.
684 * @param objs The objects to use in the format string.
685 * @return {@code this} to enable chaining.
686 * @see String#format(String, Object...)
687 */
688 public TextStringBuilder append(final String format, final Object... objs) {
689 return append(String.format(format, objs));
690 }
691
692 /**
693 * Appends a string buffer to this string builder. Appending null will call {@link #appendNull()}.
694 *
695 * @param str The string buffer to append.
696 * @return {@code this} instance.
697 */
698 public TextStringBuilder append(final StringBuffer str) {
699 return append(str, 0, StringUtils.length(str));
700 }
701
702 /**
703 * Appends part of a string buffer to this string builder. Appending null will call {@link #appendNull()}.
704 *
705 * @param str The string to append.
706 * @param startIndex The start index, inclusive, must be valid.
707 * @param length The length to append, must be valid.
708 * @return {@code this} instance.
709 */
710 public TextStringBuilder append(final StringBuffer str, final int startIndex, final int length) {
711 if (str == null) {
712 return appendNull();
713 }
714 validateRange(startIndex, length, str.length());
715 if (length > 0) {
716 final int len = length();
717 ensureCapacityInternal(len + length);
718 str.getChars(startIndex, startIndex + length, buffer, len);
719 size += length;
720 }
721 return this;
722 }
723
724 /**
725 * Appends a StringBuilder to this string builder. Appending null will call {@link #appendNull()}.
726 *
727 * @param str The StringBuilder to append.
728 * @return {@code this} instance.
729 */
730 public TextStringBuilder append(final StringBuilder str) {
731 return append(str, 0, StringUtils.length(str));
732 }
733
734 /**
735 * Appends part of a StringBuilder to this string builder. Appending null will call {@link #appendNull()}.
736 *
737 * @param str The StringBuilder to append.
738 * @param startIndex The start index, inclusive, must be valid.
739 * @param length The length to append, must be valid.
740 * @return {@code this} instance.
741 */
742 public TextStringBuilder append(final StringBuilder str, final int startIndex, final int length) {
743 if (str == null) {
744 return appendNull();
745 }
746 validateRange(startIndex, length, str.length());
747 if (length > 0) {
748 final int len = length();
749 ensureCapacityInternal(len + length);
750 str.getChars(startIndex, startIndex + length, buffer, len);
751 size += length;
752 }
753 return this;
754 }
755
756 /**
757 * Appends another string builder to this string builder. Appending null will call {@link #appendNull()}.
758 *
759 * @param str The string builder to append.
760 * @return {@code this} instance.
761 */
762 public TextStringBuilder append(final TextStringBuilder str) {
763 return append(str, 0, StringUtils.length(str));
764 }
765
766 /**
767 * Appends part of a string builder to this string builder. Appending null will call {@link #appendNull()}.
768 *
769 * @param str The string to append.
770 * @param startIndex The start index, inclusive, must be valid.
771 * @param length The length to append, must be valid.
772 * @return {@code this} instance.
773 */
774 public TextStringBuilder append(final TextStringBuilder str, final int startIndex, final int length) {
775 if (str == null) {
776 return appendNull();
777 }
778 validateRange(startIndex, length, str.length());
779 if (length > 0) {
780 final int len = length();
781 ensureCapacityInternal(len + length);
782 str.getChars(startIndex, startIndex + length, buffer, len);
783 size += length;
784 }
785 return this;
786 }
787
788 /**
789 * Appends each item in an iterable to the builder without any separators. Appending a null iterable will have no effect. Each object is appended using
790 * {@link #append(Object)}.
791 *
792 * @param iterable The iterable to append.
793 * @return {@code this} instance.
794 */
795 public TextStringBuilder appendAll(final Iterable<?> iterable) {
796 if (iterable != null) {
797 iterable.forEach(this::append);
798 }
799 return this;
800 }
801
802 /**
803 * Appends each item in an iterator to the builder without any separators. Appending a null iterator will have no effect. Each object is appended using
804 * {@link #append(Object)}.
805 *
806 * @param it The iterator to append.
807 * @return {@code this} instance.
808 */
809 public TextStringBuilder appendAll(final Iterator<?> it) {
810 if (it != null) {
811 it.forEachRemaining(this::append);
812 }
813 return this;
814 }
815
816 /**
817 * Appends each item in an array to the builder without any separators. Appending a null array will have no effect. Each object is appended using
818 * {@link #append(Object)}.
819 *
820 * @param <T> the element type.
821 * @param array The array to append.
822 * @return {@code this} instance.
823 */
824 public <T> TextStringBuilder appendAll(@SuppressWarnings("unchecked") final T... array) {
825 /*
826 * @SuppressWarnings used to hide warning about vararg usage. We cannot use @SafeVarargs, since this method is
827 * not final. Using @SuppressWarnings is fine, because it isn't inherited by subclasses, so each subclass must
828 * vouch for itself whether its use of 'array' is safe.
829 */
830 if (array != null && array.length > 0) {
831 for (final Object element : array) {
832 append(element);
833 }
834 }
835 return this;
836 }
837
838 /** Appends {@code "false"}. */
839 private void appendFalse(int index) {
840 buffer[index++] = 'f';
841 buffer[index++] = 'a';
842 buffer[index++] = 'l';
843 buffer[index++] = 's';
844 buffer[index] = 'e';
845 size += FALSE_STRING_SIZE;
846 }
847
848 /**
849 * Appends an object to the builder padding on the left to a fixed width. The {@code String.valueOf} of the {@code int} value is used. If the formatted
850 * value is larger than the length, the left hand side is lost.
851 *
852 * @param value The value to append.
853 * @param width The fixed field width, zero or negative has no effect.
854 * @param padChar The pad character to use.
855 * @return {@code this} instance.
856 */
857 public TextStringBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) {
858 return appendFixedWidthPadLeft(String.valueOf(value), width, padChar);
859 }
860
861 /**
862 * Appends an object to the builder padding on the left to a fixed width. The {@code toString} of the object is used. If the object is larger than the
863 * length, the left hand side is lost. If the object is null, the null text value is used.
864 *
865 * @param obj The object to append, null uses null text.
866 * @param width The fixed field width, zero or negative has no effect.
867 * @param padChar The pad character to use.
868 * @return {@code this} instance.
869 */
870 public TextStringBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) {
871 if (width > 0) {
872 ensureCapacityInternal(size + width);
873 String str = Objects.toString(obj, getNullText());
874 if (str == null) {
875 str = StringUtils.EMPTY;
876 }
877 final int strLen = str.length();
878 if (strLen >= width) {
879 str.getChars(strLen - width, strLen, buffer, size);
880 } else {
881 final int padLen = width - strLen;
882 final int toIndex = size + padLen;
883 Arrays.fill(buffer, size, toIndex, padChar);
884 str.getChars(0, strLen, buffer, toIndex);
885 }
886 size += width;
887 }
888 return this;
889 }
890
891 /**
892 * Appends an object to the builder padding on the right to a fixed length. The {@code String.valueOf} of the {@code int} value is used. If the object is
893 * larger than the length, the right hand side is lost.
894 *
895 * @param value The value to append.
896 * @param width The fixed field width, zero or negative has no effect.
897 * @param padChar The pad character to use.
898 * @return {@code this} instance.
899 */
900 public TextStringBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) {
901 return appendFixedWidthPadRight(String.valueOf(value), width, padChar);
902 }
903
904 /**
905 * Appends an object to the builder padding on the right to a fixed length. The {@code toString} of the object is used. If the object is larger than the
906 * length, the right hand side is lost. If the object is null, null text value is used.
907 *
908 * @param obj The object to append, null uses null text.
909 * @param width The fixed field width, zero or negative has no effect.
910 * @param padChar The pad character to use.
911 * @return {@code this} instance.
912 */
913 public TextStringBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) {
914 if (width > 0) {
915 ensureCapacityInternal(size + width);
916 String str = Objects.toString(obj, getNullText());
917 if (str == null) {
918 str = StringUtils.EMPTY;
919 }
920 final int strLen = str.length();
921 if (strLen >= width) {
922 str.getChars(0, width, buffer, size);
923 } else {
924 str.getChars(0, strLen, buffer, size);
925 final int fromIndex = size + strLen;
926 Arrays.fill(buffer, fromIndex, fromIndex + width - strLen, padChar);
927 }
928 size += width;
929 }
930 return this;
931 }
932
933 /**
934 * Appends a boolean value followed by a new line to the string builder.
935 *
936 * @param value The value to append.
937 * @return {@code this} instance.
938 */
939 public TextStringBuilder appendln(final boolean value) {
940 return append(value).appendNewLine();
941 }
942
943 /**
944 * Appends a char value followed by a new line to the string builder.
945 *
946 * @param ch The value to append.
947 * @return {@code this} instance.
948 */
949 public TextStringBuilder appendln(final char ch) {
950 return append(ch).appendNewLine();
951 }
952
953 /**
954 * Appends a char array followed by a new line to the string builder. Appending null will call
955 * {@link #appendNull()}.
956 *
957 * @param chars The char array to append.
958 * @return {@code this} instance.
959 */
960 public TextStringBuilder appendln(final char[] chars) {
961 return append(chars).appendNewLine();
962 }
963
964 /**
965 * Appends a char array followed by a new line to the string builder. Appending null will call
966 * {@link #appendNull()}.
967 *
968 * @param chars The char array to append.
969 * @param startIndex The start index, inclusive, must be valid.
970 * @param length The length to append, must be valid.
971 * @return {@code this} instance.
972 */
973 public TextStringBuilder appendln(final char[] chars, final int startIndex, final int length) {
974 return append(chars, startIndex, length).appendNewLine();
975 }
976
977 /**
978 * Appends a double value followed by a new line to the string builder using {@code String.valueOf}.
979 *
980 * @param value The value to append.
981 * @return {@code this} instance.
982 */
983 public TextStringBuilder appendln(final double value) {
984 return append(value).appendNewLine();
985 }
986
987 /**
988 * Appends a float value followed by a new line to the string builder using {@code String.valueOf}.
989 *
990 * @param value The value to append.
991 * @return {@code this} instance.
992 */
993 public TextStringBuilder appendln(final float value) {
994 return append(value).appendNewLine();
995 }
996
997 /**
998 * Appends an int value followed by a new line to the string builder using {@code String.valueOf}.
999 *
1000 * @param value The value to append.
1001 * @return {@code this} instance.
1002 */
1003 public TextStringBuilder appendln(final int value) {
1004 return append(value).appendNewLine();
1005 }
1006
1007 /**
1008 * Appends a long value followed by a new line to the string builder using {@code String.valueOf}.
1009 *
1010 * @param value The value to append.
1011 * @return {@code this} instance.
1012 */
1013 public TextStringBuilder appendln(final long value) {
1014 return append(value).appendNewLine();
1015 }
1016
1017 /**
1018 * Appends an object followed by a new line to this string builder. Appending null will call {@link #appendNull()}.
1019 *
1020 * @param obj The object to append.
1021 * @return {@code this} instance.
1022 */
1023 public TextStringBuilder appendln(final Object obj) {
1024 return append(obj).appendNewLine();
1025 }
1026
1027 /**
1028 * Appends a string followed by a new line to this string builder. Appending null will call {@link #appendNull()}.
1029 *
1030 * @param str The string to append.
1031 * @return {@code this} instance.
1032 */
1033 public TextStringBuilder appendln(final String str) {
1034 return append(str).appendNewLine();
1035 }
1036
1037 /**
1038 * Appends part of a string followed by a new line to this string builder. Appending null will call
1039 * {@link #appendNull()}.
1040 *
1041 * @param str The string to append.
1042 * @param startIndex The start index, inclusive, must be valid.
1043 * @param length The length to append, must be valid.
1044 * @return {@code this} instance.
1045 */
1046 public TextStringBuilder appendln(final String str, final int startIndex, final int length) {
1047 return append(str, startIndex, length).appendNewLine();
1048 }
1049
1050 /**
1051 * Calls {@link String#format(String, Object...)} and appends the result.
1052 *
1053 * @param format The format string.
1054 * @param objs The objects to use in the format string.
1055 * @return {@code this} to enable chaining.
1056 * @see String#format(String, Object...)
1057 */
1058 public TextStringBuilder appendln(final String format, final Object... objs) {
1059 return append(format, objs).appendNewLine();
1060 }
1061
1062 /**
1063 * Appends a string buffer followed by a new line to this string builder. Appending null will call
1064 * {@link #appendNull()}.
1065 *
1066 * @param str The string buffer to append.
1067 * @return {@code this} instance.
1068 */
1069 public TextStringBuilder appendln(final StringBuffer str) {
1070 return append(str).appendNewLine();
1071 }
1072
1073 /**
1074 * Appends part of a string buffer followed by a new line to this string builder. Appending null will call
1075 * {@link #appendNull()}.
1076 *
1077 * @param str The string to append.
1078 * @param startIndex The start index, inclusive, must be valid.
1079 * @param length The length to append, must be valid.
1080 * @return {@code this} instance.
1081 */
1082 public TextStringBuilder appendln(final StringBuffer str, final int startIndex, final int length) {
1083 return append(str, startIndex, length).appendNewLine();
1084 }
1085
1086 /**
1087 * Appends a string builder followed by a new line to this string builder. Appending null will call
1088 * {@link #appendNull()}.
1089 *
1090 * @param str The string builder to append.
1091 * @return {@code this} instance.
1092 */
1093 public TextStringBuilder appendln(final StringBuilder str) {
1094 return append(str).appendNewLine();
1095 }
1096
1097 /**
1098 * Appends part of a string builder followed by a new line to this string builder. Appending null will call
1099 * {@link #appendNull()}.
1100 *
1101 * @param str The string builder to append.
1102 * @param startIndex The start index, inclusive, must be valid.
1103 * @param length The length to append, must be valid.
1104 * @return {@code this} instance.
1105 */
1106 public TextStringBuilder appendln(final StringBuilder str, final int startIndex, final int length) {
1107 return append(str, startIndex, length).appendNewLine();
1108 }
1109
1110 /**
1111 * Appends another string builder followed by a new line to this string builder. Appending null will call
1112 * {@link #appendNull()}.
1113 *
1114 * @param str The string builder to append.
1115 * @return {@code this} instance.
1116 */
1117 public TextStringBuilder appendln(final TextStringBuilder str) {
1118 return append(str).appendNewLine();
1119 }
1120
1121 /**
1122 * Appends part of a string builder followed by a new line to this string builder. Appending null will call
1123 * {@link #appendNull()}.
1124 *
1125 * @param str The string to append.
1126 * @param startIndex The start index, inclusive, must be valid.
1127 * @param length The length to append, must be valid.
1128 * @return {@code this} instance.
1129 */
1130 public TextStringBuilder appendln(final TextStringBuilder str, final int startIndex, final int length) {
1131 return append(str, startIndex, length).appendNewLine();
1132 }
1133
1134 /**
1135 * Appends this builder's new line string to this builder.
1136 * <p>
1137 * By default, the new line is the system default from {@link System#lineSeparator()}.
1138 * </p>
1139 * <p>
1140 * 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
1141 * endings even when on Windows.
1142 * </p>
1143 *
1144 * @return {@code this} instance.
1145 * @see #getNewLineText()
1146 * @see #setNewLineText(String)
1147 */
1148 public TextStringBuilder appendNewLine() {
1149 return append(newLine == null ? System.lineSeparator() : newLine);
1150 }
1151
1152 /**
1153 * Appends the text representing {@code null} to this string builder.
1154 *
1155 * @return {@code this} instance.
1156 */
1157 public TextStringBuilder appendNull() {
1158 return nullText != null ? append(nullText) : this;
1159 }
1160
1161 /**
1162 * Appends the pad character to the builder the specified number of times.
1163 *
1164 * @param length The length to append, negative means no append.
1165 * @param padChar The character to append.
1166 * @return {@code this} instance.
1167 */
1168 public TextStringBuilder appendPadding(final int length, final char padChar) {
1169 if (length >= 0) {
1170 ensureCapacityInternal(size + length);
1171 for (int i = 0; i < length; i++) {
1172 buffer[size++] = padChar;
1173 }
1174 }
1175 return this;
1176 }
1177
1178 /**
1179 * Appends a separator if the builder is currently non-empty. The separator is appended using {@link #append(char)}.
1180 * <p>
1181 * This method is useful for adding a separator each time around the loop except the first.
1182 * </p>
1183 *
1184 * <pre>
1185 * for (Iterator it = list.iterator(); it.hasNext();) {
1186 * appendSeparator(',');
1187 * append(it.next());
1188 * }
1189 * </pre>
1190 *
1191 * <p>
1192 * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
1193 * </p>
1194 *
1195 * @param separator The separator to use.
1196 * @return {@code this} instance.
1197 */
1198 public TextStringBuilder appendSeparator(final char separator) {
1199 return isEmpty() ? this : append(separator);
1200 }
1201
1202 /**
1203 * Appends one of both separators to the builder If the builder is currently empty it will append the defaultIfEmpty-separator Otherwise it will append the
1204 * standard-separator
1205 * <p>
1206 * The separator is appended using {@link #append(char)}.
1207 * </p>
1208 *
1209 * @param standard The separator if builder is not empty.
1210 * @param defaultIfEmpty The separator if builder is empty.
1211 * @return {@code this} instance.
1212 */
1213 public TextStringBuilder appendSeparator(final char standard, final char defaultIfEmpty) {
1214 return append(isEmpty() ? defaultIfEmpty : standard);
1215 }
1216
1217 /**
1218 * Appends a separator to the builder if the loop index is greater than zero. The separator is appended using
1219 * {@link #append(char)}.
1220 * <p>
1221 * This method is useful for adding a separator each time around the loop except the first.
1222 * </p>
1223 *
1224 * <pre>
1225 * for (int i = 0; i < list.size(); i++) {
1226 * appendSeparator(",", i);
1227 * append(list.get(i));
1228 * }
1229 * </pre>
1230 *
1231 * <p>
1232 * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
1233 * </p>
1234 *
1235 * @param separator The separator to use.
1236 * @param loopIndex The loop index.
1237 * @return {@code this} instance.
1238 */
1239 public TextStringBuilder appendSeparator(final char separator, final int loopIndex) {
1240 return loopIndex > 0 ? append(separator) : this;
1241 }
1242
1243 /**
1244 * Appends a separator if the builder is currently non-empty. Appending a null separator will have no effect. The
1245 * separator is appended using {@link #append(String)}.
1246 * <p>
1247 * This method is useful for adding a separator each time around the loop except the first.
1248 * </p>
1249 *
1250 * <pre>
1251 * for (Iterator it = list.iterator(); it.hasNext();) {
1252 * appendSeparator(",");
1253 * append(it.next());
1254 * }
1255 * </pre>
1256 *
1257 * <p>
1258 * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
1259 * </p>
1260 *
1261 * @param separator The separator to use, null means no separator.
1262 * @return {@code this} instance.
1263 */
1264 public TextStringBuilder appendSeparator(final String separator) {
1265 return appendSeparator(separator, null);
1266 }
1267
1268 /**
1269 * Appends a separator to the builder if the loop index is greater than zero. Appending a null separator will have
1270 * no effect. The separator is appended using {@link #append(String)}.
1271 * <p>
1272 * This method is useful for adding a separator each time around the loop except the first.
1273 * </p>
1274 *
1275 * <pre>
1276 * for (int i = 0; i < list.size(); i++) {
1277 * appendSeparator(",", i);
1278 * append(list.get(i));
1279 * }
1280 * </pre>
1281 *
1282 * <p>
1283 * Note that for this simple example, you should use {@link #appendWithSeparators(Iterable, String)}.
1284 * </p>
1285 *
1286 * @param separator The separator to use, null means no separator.
1287 * @param loopIndex The loop index.
1288 * @return {@code this} instance.
1289 */
1290 public TextStringBuilder appendSeparator(final String separator, final int loopIndex) {
1291 return separator != null && loopIndex > 0 ? append(separator) : this;
1292 }
1293
1294 /**
1295 * Appends one of both separators to the StrBuilder. If the builder is currently empty, it will append the
1296 * defaultIfEmpty-separator, otherwise it will append the standard-separator.
1297 * <p>
1298 * Appending a null separator will have no effect. The separator is appended using {@link #append(String)}.
1299 * </p>
1300 * <p>
1301 * This method is for example useful for constructing queries
1302 * </p>
1303 *
1304 * <pre>
1305 * StrBuilder whereClause = new StrBuilder();
1306 * if (searchCommand.getPriority() != null) {
1307 * whereClause.appendSeparator(" and", " where");
1308 * whereClause.append(" priority = ?")
1309 * }
1310 * if (searchCommand.getComponent() != null) {
1311 * whereClause.appendSeparator(" and", " where");
1312 * whereClause.append(" component = ?")
1313 * }
1314 * selectClause.append(whereClause)
1315 * </pre>
1316 *
1317 * @param standard The separator if builder is not empty, null means no separator.
1318 * @param defaultIfEmpty The separator if builder is empty, null means no separator.
1319 * @return {@code this} instance.
1320 */
1321 public TextStringBuilder appendSeparator(final String standard, final String defaultIfEmpty) {
1322 final String str = isEmpty() ? defaultIfEmpty : standard;
1323 return str != null ? append(str) : this;
1324 }
1325
1326 /**
1327 * Appends current contents of this {@code StrBuilder} to the provided {@link Appendable}.
1328 * <p>
1329 * This method tries to avoid doing any extra copies of contents.
1330 * </p>
1331 *
1332 * @param appendable The appendable to append data to.
1333 * @throws IOException Thrown if an I/O error occurs.
1334 * @see #readFrom(Readable)
1335 */
1336 public void appendTo(final Appendable appendable) throws IOException {
1337 if (appendable instanceof Writer) {
1338 ((Writer) appendable).write(buffer, 0, size);
1339 } else if (appendable instanceof StringBuilder) {
1340 ((StringBuilder) appendable).append(buffer, 0, size);
1341 } else if (appendable instanceof StringBuffer) {
1342 ((StringBuffer) appendable).append(buffer, 0, size);
1343 } else if (appendable instanceof CharBuffer) {
1344 ((CharBuffer) appendable).put(buffer, 0, size);
1345 } else {
1346 appendable.append(this);
1347 }
1348 }
1349
1350 /** Appends {@code "true"}. */
1351 private void appendTrue(int index) {
1352 buffer[index++] = 't';
1353 buffer[index++] = 'r';
1354 buffer[index++] = 'u';
1355 buffer[index] = 'e';
1356 size += TRUE_STRING_SIZE;
1357 }
1358
1359 /**
1360 * Appends an iterable placing separators between each value, but not before the first or after the last. Appending
1361 * a null iterable will have no effect. Each object is appended using {@link #append(Object)}.
1362 *
1363 * @param iterable The iterable to append.
1364 * @param separator The separator to use, null means no separator.
1365 * @return {@code this} instance.
1366 */
1367 public TextStringBuilder appendWithSeparators(final Iterable<?> iterable, final String separator) {
1368 if (iterable != null) {
1369 appendWithSeparators(iterable.iterator(), separator);
1370 }
1371 return this;
1372 }
1373
1374 /**
1375 * Appends an iterator placing separators between each value, but not before the first or after the last. Appending
1376 * a null iterator will have no effect. Each object is appended using {@link #append(Object)}.
1377 *
1378 * @param it The iterator to append.
1379 * @param separator The separator to use, null means no separator.
1380 * @return {@code this} instance.
1381 */
1382 public TextStringBuilder appendWithSeparators(final Iterator<?> it, final String separator) {
1383 if (it != null) {
1384 final String sep = Objects.toString(separator, StringUtils.EMPTY);
1385 while (it.hasNext()) {
1386 append(it.next());
1387 if (it.hasNext()) {
1388 append(sep);
1389 }
1390 }
1391 }
1392 return this;
1393 }
1394
1395 /**
1396 * Appends an array placing separators between each value, but not before the first or after the last. Appending a
1397 * null array will have no effect. Each object is appended using {@link #append(Object)}.
1398 *
1399 * @param array The array to append.
1400 * @param separator The separator to use, null means no separator.
1401 * @return {@code this} instance.
1402 */
1403 public TextStringBuilder appendWithSeparators(final Object[] array, final String separator) {
1404 if (array != null && array.length > 0) {
1405 final String sep = Objects.toString(separator, StringUtils.EMPTY);
1406 append(array[0]);
1407 for (int i = 1; i < array.length; i++) {
1408 append(sep).append(array[i]);
1409 }
1410 }
1411 return this;
1412 }
1413
1414 /**
1415 * Gets the contents of this builder as a Reader.
1416 * <p>
1417 * This method allows the contents of the builder to be read using any standard method that expects a Reader.
1418 * </p>
1419 * <p>
1420 * To use, simply create a {@code StrBuilder}, populate it with data, call {@code asReader}, and then read away.
1421 * </p>
1422 * <p>
1423 * The internal character array is shared between the builder and the reader. This allows you to append to the
1424 * builder after creating the reader, and the changes will be picked up. Note however, that no synchronization
1425 * occurs, so you must perform all operations with the builder and the reader in one thread.
1426 * </p>
1427 * <p>
1428 * The returned reader supports marking, and ignores the flush method.
1429 * </p>
1430 *
1431 * @return A reader that reads from this builder.
1432 */
1433 public Reader asReader() {
1434 return new TextStringBuilderReader();
1435 }
1436
1437 /**
1438 * Creates a tokenizer that can tokenize the contents of this builder.
1439 * <p>
1440 * This method allows the contents of this builder to be tokenized. The tokenizer will be setup by default to
1441 * tokenize on space, tab, newline and form feed (as per StringTokenizer). These values can be changed on the
1442 * tokenizer class, before retrieving the tokens.
1443 * </p>
1444 * <p>
1445 * The returned tokenizer is linked to this builder. You may intermix calls to the builder and tokenizer within
1446 * certain limits, however there is no synchronization. Once the tokenizer has been used once, it must be
1447 * {@link StringTokenizer#reset() reset} to pickup the latest changes in the builder. For example:
1448 * </p>
1449 *
1450 * <pre>
1451 * StrBuilder b = new StrBuilder();
1452 * b.append("a b ");
1453 * StrTokenizer t = b.asTokenizer();
1454 * String[] tokens1 = t.getTokenArray(); // returns a,b
1455 * b.append("c d ");
1456 * String[] tokens2 = t.getTokenArray(); // returns a,b (c and d ignored)
1457 * t.reset(); // reset causes builder changes to be picked up
1458 * String[] tokens3 = t.getTokenArray(); // returns a,b,c,d
1459 * </pre>
1460 *
1461 * <p>
1462 * In addition to simply intermixing appends and tokenization, you can also call the set methods on the tokenizer to
1463 * alter how it tokenizes. Just remember to call reset when you want to pickup builder changes.
1464 * </p>
1465 * <p>
1466 * Calling {@link StringTokenizer#reset(String)} or {@link StringTokenizer#reset(char[])} with a non-null value will
1467 * break the link with the builder.
1468 * </p>
1469 *
1470 * @return A tokenizer that is linked to this builder.
1471 */
1472 public StringTokenizer asTokenizer() {
1473 return new TextStringBuilderTokenizer();
1474 }
1475
1476 /**
1477 * Gets this builder as a Writer that can be written to.
1478 * <p>
1479 * This method allows you to populate the contents of the builder using any standard method that takes a Writer.
1480 * </p>
1481 * <p>
1482 * To use, simply create a {@code StrBuilder}, call {@code asWriter}, and populate away. The data is available at
1483 * any time using the methods of the {@code StrBuilder}.
1484 * </p>
1485 * <p>
1486 * The internal character array is shared between the builder and the writer. This allows you to intermix calls that
1487 * append to the builder and write using the writer and the changes will be occur correctly. Note however, that no
1488 * synchronization occurs, so you must perform all operations with the builder and the writer in one thread.
1489 * </p>
1490 * <p>
1491 * The returned writer ignores the close and flush methods.
1492 * </p>
1493 *
1494 * @return A writer that populates this builder.
1495 */
1496 public Writer asWriter() {
1497 return new TextStringBuilderWriter();
1498 }
1499
1500 /**
1501 * Converts this instance to a String.
1502 *
1503 * @return This instance as a String.
1504 * @see #toString()
1505 * @deprecated Use {@link #get()}.
1506 */
1507 @Deprecated
1508 @Override
1509 public String build() {
1510 return toString();
1511 }
1512
1513 /**
1514 * Gets the current size of the internal character array buffer.
1515 *
1516 * @return The capacity.
1517 */
1518 public int capacity() {
1519 return buffer.length;
1520 }
1521
1522 /**
1523 * Gets the character at the specified index.
1524 *
1525 * @param index The index to retrieve, must be valid.
1526 * @return The character at the index.
1527 * @throws IndexOutOfBoundsException if the index is invalid.
1528 * @see #setCharAt(int, char)
1529 * @see #deleteCharAt(int)
1530 */
1531 @Override
1532 public char charAt(final int index) {
1533 validateIndex(index);
1534 return buffer[index];
1535 }
1536
1537 /**
1538 * Clears the string builder (convenience Collections API style method).
1539 * <p>
1540 * This method does not reduce the size of the internal character buffer. To do that, call {@code clear()} followed
1541 * by {@link #minimizeCapacity()}.
1542 * </p>
1543 * <p>
1544 * This method is the same as {@link #setLength(int)} called with zero and is provided to match the API of
1545 * Collections.
1546 * </p>
1547 *
1548 * @return {@code this} instance.
1549 */
1550 public TextStringBuilder clear() {
1551 size = 0;
1552 Arrays.fill(buffer, CharUtils.NUL);
1553 return this;
1554 }
1555
1556 /**
1557 * Tests if the string builder contains the specified char.
1558 *
1559 * @param ch The character to find.
1560 * @return true if the builder contains the character.
1561 */
1562 public boolean contains(final char ch) {
1563 final char[] thisBuf = buffer;
1564 for (int i = 0; i < this.size; i++) {
1565 if (thisBuf[i] == ch) {
1566 return true;
1567 }
1568 }
1569 return false;
1570 }
1571
1572 /**
1573 * Tests if the string builder contains the specified string.
1574 *
1575 * @param str The string to find.
1576 * @return true if the builder contains the string.
1577 */
1578 public boolean contains(final String str) {
1579 return indexOf(str, 0) >= 0;
1580 }
1581
1582 /**
1583 * Tests if the string builder contains a string matched using the specified matcher.
1584 * <p>
1585 * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to search for
1586 * the character 'a' followed by a number.
1587 * </p>
1588 *
1589 * @param matcher The matcher to use, null returns -1.
1590 * @return true if the matcher finds a match in the builder.
1591 */
1592 public boolean contains(final StringMatcher matcher) {
1593 return indexOf(matcher, 0) >= 0;
1594 }
1595
1596 /**
1597 * Deletes the characters between the two specified indices.
1598 *
1599 * @param startIndex The start index, inclusive, must be valid.
1600 * @param endIndex The end index, exclusive, must be valid except that if too large it is treated as end of string.
1601 * @return {@code this} instance.
1602 * @throws IndexOutOfBoundsException if the index is invalid.
1603 */
1604 public TextStringBuilder delete(final int startIndex, final int endIndex) {
1605 final int actualEndIndex = validateRange(startIndex, endIndex);
1606 final int len = actualEndIndex - startIndex;
1607 if (len > 0) {
1608 deleteImpl(startIndex, actualEndIndex, len);
1609 }
1610 return this;
1611 }
1612
1613 /**
1614 * Deletes the character wherever it occurs in the builder.
1615 *
1616 * @param ch The character to delete.
1617 * @return {@code this} instance.
1618 */
1619 public TextStringBuilder deleteAll(final char ch) {
1620 for (int i = 0; i < size; i++) {
1621 if (buffer[i] == ch) {
1622 final int start = i;
1623 while (++i < size) {
1624 if (buffer[i] != ch) {
1625 break;
1626 }
1627 }
1628 final int len = i - start;
1629 deleteImpl(start, i, len);
1630 i -= len;
1631 }
1632 }
1633 return this;
1634 }
1635
1636 /**
1637 * Deletes the string wherever it occurs in the builder.
1638 *
1639 * @param str The string to delete, null causes no action.
1640 * @return {@code this} instance.
1641 */
1642 public TextStringBuilder deleteAll(final String str) {
1643 final int len = str == null ? 0 : str.length();
1644 if (len > 0) {
1645 int index = indexOf(str, 0);
1646 while (index >= 0) {
1647 deleteImpl(index, index + len, len);
1648 index = indexOf(str, index);
1649 }
1650 }
1651 return this;
1652 }
1653
1654 /**
1655 * Deletes all parts of the builder that the matcher matches.
1656 * <p>
1657 * Matchers can be used to perform advanced deletion behavior. For example you could write a matcher to delete all
1658 * occurrences where the character 'a' is followed by a number.
1659 * </p>
1660 *
1661 * @param matcher The matcher to use to find the deletion, null causes no action.
1662 * @return {@code this} instance.
1663 */
1664 public TextStringBuilder deleteAll(final StringMatcher matcher) {
1665 return replace(matcher, null, 0, size, -1);
1666 }
1667
1668 /**
1669 * Deletes the character at the specified index.
1670 *
1671 * @param index The index to delete.
1672 * @return {@code this} instance.
1673 * @throws IndexOutOfBoundsException if the index is invalid.
1674 * @see #charAt(int)
1675 * @see #setCharAt(int, char)
1676 */
1677 public TextStringBuilder deleteCharAt(final int index) {
1678 validateIndex(index);
1679 deleteImpl(index, index + 1, 1);
1680 return this;
1681 }
1682
1683 /**
1684 * Deletes the character wherever it occurs in the builder.
1685 *
1686 * @param ch The character to delete.
1687 * @return {@code this} instance.
1688 */
1689 public TextStringBuilder deleteFirst(final char ch) {
1690 for (int i = 0; i < size; i++) {
1691 if (buffer[i] == ch) {
1692 deleteImpl(i, i + 1, 1);
1693 break;
1694 }
1695 }
1696 return this;
1697 }
1698
1699 /**
1700 * Deletes the string wherever it occurs in the builder.
1701 *
1702 * @param str The string to delete, null causes no action.
1703 * @return {@code this} instance.
1704 */
1705 public TextStringBuilder deleteFirst(final String str) {
1706 final int len = str == null ? 0 : str.length();
1707 if (len > 0) {
1708 final int index = indexOf(str, 0);
1709 if (index >= 0) {
1710 deleteImpl(index, index + len, len);
1711 }
1712 }
1713 return this;
1714 }
1715
1716 /**
1717 * Deletes the first match within the builder using the specified matcher.
1718 * <p>
1719 * Matchers can be used to perform advanced deletion behavior. For example you could write a matcher to delete where
1720 * the character 'a' is followed by a number.
1721 * </p>
1722 *
1723 * @param matcher The matcher to use to find the deletion, null causes no action.
1724 * @return {@code this} instance.
1725 */
1726 public TextStringBuilder deleteFirst(final StringMatcher matcher) {
1727 return replace(matcher, null, 0, size, 1);
1728 }
1729
1730 /**
1731 * Internal method to delete a range without validation.
1732 *
1733 * @param startIndex The start index, must be valid.
1734 * @param endIndex The end index (exclusive), must be valid.
1735 * @param len The length, must be valid.
1736 * @throws IndexOutOfBoundsException if any index is invalid.
1737 */
1738 private void deleteImpl(final int startIndex, final int endIndex, final int len) {
1739 System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex);
1740 size -= len;
1741 Arrays.fill(buffer, size, size + len, CharUtils.NUL);
1742 }
1743
1744 /**
1745 * Gets the character at the specified index before deleting it.
1746 *
1747 * @param index The index to retrieve, must be valid
1748 * @return The character at the index
1749 * @throws IndexOutOfBoundsException if the index is invalid
1750 * @since 1.9
1751 * @see #charAt(int)
1752 * @see #deleteCharAt(int)
1753 */
1754 public char drainChar(final int index) {
1755 validateIndex(index);
1756 final char c = buffer[index];
1757 deleteCharAt(index);
1758 return c;
1759 }
1760
1761 /**
1762 * Drains (copies, then deletes) this character sequence into the specified array. This is equivalent to copying the
1763 * characters from this sequence into the target and then deleting those character from this sequence.
1764 *
1765 * @param startIndex first index to copy, inclusive.
1766 * @param endIndex last index to copy, exclusive.
1767 * @param target The target array, must not be {@code null}.
1768 * @param targetIndex The index to start copying in the target.
1769 * @return How many characters where copied (then deleted). If this builder is empty, return {@code 0}.
1770 * @since 1.9
1771 */
1772 public int drainChars(final int startIndex, final int endIndex, final char[] target, final int targetIndex) {
1773 final int length = endIndex - startIndex;
1774 if (isEmpty() || length == 0 || target.length == 0) {
1775 return 0;
1776 }
1777 final int actualLen = Math.min(Math.min(size, length), target.length - targetIndex);
1778 getChars(startIndex, actualLen, target, targetIndex);
1779 delete(startIndex, actualLen);
1780 return actualLen;
1781 }
1782
1783 /**
1784 * Checks whether this builder ends with the specified string.
1785 * <p>
1786 * Note that this method handles null input quietly, unlike String.
1787 * </p>
1788 *
1789 * @param str The string to search for, null returns false.
1790 * @return true if the builder ends with the string.
1791 */
1792 public boolean endsWith(final String str) {
1793 if (str == null) {
1794 return false;
1795 }
1796 final int len = str.length();
1797 if (len == 0) {
1798 return true;
1799 }
1800 if (len > size) {
1801 return false;
1802 }
1803 int pos = size - len;
1804 for (int i = 0; i < len; i++, pos++) {
1805 if (buffer[pos] != str.charAt(i)) {
1806 return false;
1807 }
1808 }
1809 return true;
1810 }
1811
1812 /**
1813 * Tests the capacity and ensures that it is at least the size specified.
1814 *
1815 * <p>
1816 * Note: This method can be used to minimise memory reallocations during
1817 * repeated addition of values by pre-allocating the character buffer.
1818 * The method ignores a negative {@code capacity} argument.
1819 * </p>
1820 *
1821 * @param capacity The capacity to ensure.
1822 * @return {@code this} instance.
1823 * @throws OutOfMemoryError if the capacity cannot be allocated.
1824 */
1825 public TextStringBuilder ensureCapacity(final int capacity) {
1826 if (capacity > 0) {
1827 ensureCapacityInternal(capacity);
1828 }
1829 return this;
1830 }
1831
1832 /**
1833 * Ensures that the buffer is at least the size specified. The {@code capacity} argument
1834 * is treated as an unsigned integer.
1835 *
1836 * <p>
1837 * This method will raise an {@link OutOfMemoryError} if the capacity is too large
1838 * for an array, or cannot be allocated.
1839 * </p>
1840 *
1841 * @param capacity The capacity to ensure.
1842 * @throws OutOfMemoryError if the capacity cannot be allocated.
1843 */
1844 private void ensureCapacityInternal(final int capacity) {
1845 // Check for overflow of the current buffer.
1846 // Assumes capacity is an unsigned integer up to Integer.MAX_VALUE * 2
1847 // (the largest possible addition of two maximum length arrays).
1848 if (capacity - buffer.length > 0) {
1849 resizeBuffer(capacity);
1850 }
1851 }
1852
1853 /**
1854 * Tests the contents of this builder against another to see if they contain the same character content.
1855 *
1856 * @param obj The object to check, null returns false.
1857 * @return true if the builders contain the same characters in the same order.
1858 */
1859 @Override
1860 public boolean equals(final Object obj) {
1861 return obj instanceof TextStringBuilder && equals((TextStringBuilder) obj);
1862 }
1863
1864 /**
1865 * Tests the contents of this builder against another to see if they contain the same character content.
1866 *
1867 * @param other The object to check, null returns false.
1868 * @return true if the builders contain the same characters in the same order.
1869 */
1870 public boolean equals(final TextStringBuilder other) {
1871 if (this == other) {
1872 return true;
1873 }
1874 if (other == null) {
1875 return false;
1876 }
1877 if (this.size != other.size) {
1878 return false;
1879 }
1880 // Be aware not to use Arrays.equals(buffer, other.buffer) for equals() method
1881 // as length of the buffers may be different (TEXT-211)
1882 final char[] thisBuf = this.buffer;
1883 final char[] otherBuf = other.buffer;
1884 for (int i = size - 1; i >= 0; i--) {
1885 if (thisBuf[i] != otherBuf[i]) {
1886 return false;
1887 }
1888 }
1889 return true;
1890 }
1891
1892 /**
1893 * Tests the contents of this builder against another to see if they contain the same character content ignoring
1894 * case.
1895 *
1896 * @param other The object to check, null returns false.
1897 * @return true if the builders contain the same characters in the same order.
1898 */
1899 public boolean equalsIgnoreCase(final TextStringBuilder other) {
1900 if (this == other) {
1901 return true;
1902 }
1903 if (this.size != other.size) {
1904 return false;
1905 }
1906 final char[] thisBuf = this.buffer;
1907 final char[] otherBuf = other.buffer;
1908 for (int i = size - 1; i >= 0; i--) {
1909 final char c1 = thisBuf[i];
1910 final char c2 = otherBuf[i];
1911 if (c1 != c2) {
1912 final char u1 = Character.toUpperCase(c1);
1913 final char u2 = Character.toUpperCase(c2);
1914 if (u1 != u2 && Character.toLowerCase(u1) != Character.toLowerCase(u2)) {
1915 return false;
1916 }
1917 }
1918 }
1919 return true;
1920 }
1921
1922 /**
1923 * Converts this instance to a String.
1924 *
1925 * @return This instance as a String.
1926 * @see #toString()
1927 * @since 1.12.0
1928 */
1929 @Override
1930 public String get() {
1931 return toString();
1932 }
1933
1934 /**
1935 * Gets a direct reference to internal storage, not for public consumption.
1936 */
1937 char[] getBuffer() {
1938 return buffer;
1939 }
1940
1941 /**
1942 * Copies this character array into the specified array.
1943 *
1944 * @param target The target array, null will cause an array to be created.
1945 * @return The input array, unless that was null or too small.
1946 */
1947 public char[] getChars(char[] target) {
1948 final int len = length();
1949 if (target == null || target.length < len) {
1950 target = new char[len];
1951 }
1952 System.arraycopy(buffer, 0, target, 0, len);
1953 return target;
1954 }
1955
1956 /**
1957 * Copies this character array into the specified array.
1958 *
1959 * @param startIndex first index to copy, inclusive, must be valid.
1960 * @param endIndex last index to copy, exclusive, must be valid.
1961 * @param target The target array, must not be null or too small.
1962 * @param targetIndex The index to start copying in target.
1963 * @throws NullPointerException if the array is null.
1964 * @throws IndexOutOfBoundsException if any index is invalid.
1965 */
1966 public void getChars(final int startIndex, final int endIndex, final char[] target, final int targetIndex) {
1967 if (startIndex < 0) {
1968 throw new StringIndexOutOfBoundsException(startIndex);
1969 }
1970 if (endIndex < 0 || endIndex > length()) {
1971 throw new StringIndexOutOfBoundsException(endIndex);
1972 }
1973 if (startIndex > endIndex) {
1974 throw new StringIndexOutOfBoundsException("end < start");
1975 }
1976 System.arraycopy(buffer, startIndex, target, targetIndex, endIndex - startIndex);
1977 }
1978
1979 /**
1980 * Gets the text to be appended when a {@link #appendNewLine() new line} is added.
1981 *
1982 * @return The new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
1983 */
1984 public String getNewLineText() {
1985 return newLine;
1986 }
1987
1988 /**
1989 * Gets the text to be appended when null is added.
1990 *
1991 * @return The null text, null means no append.
1992 */
1993 public String getNullText() {
1994 return nullText;
1995 }
1996
1997 /**
1998 * Gets a suitable hash code for this builder.
1999 *
2000 * @return A hash code.
2001 */
2002 @Override
2003 public int hashCode() {
2004 // no allocation
2005 final char[] buf = buffer;
2006 int result = 0;
2007 for (int i = 0; i < size; i++) {
2008 result = 31 * result + buf[i];
2009 }
2010 return result;
2011 }
2012
2013 /**
2014 * Searches the string builder to find the first reference to the specified char.
2015 *
2016 * @param ch The character to find.
2017 * @return The first index of the character, or -1 if not found.
2018 */
2019 public int indexOf(final char ch) {
2020 return indexOf(ch, 0);
2021 }
2022
2023 /**
2024 * Searches the string builder to find the first reference to the specified char.
2025 *
2026 * @param ch The character to find.
2027 * @param startIndex The index to start at, invalid index rounded to edge.
2028 * @return The first index of the character, or -1 if not found.
2029 */
2030 public int indexOf(final char ch, int startIndex) {
2031 startIndex = Math.max(0, startIndex);
2032 if (startIndex >= size) {
2033 return StringUtils.INDEX_NOT_FOUND;
2034 }
2035 final char[] thisBuf = buffer;
2036 for (int i = startIndex; i < size; i++) {
2037 if (thisBuf[i] == ch) {
2038 return i;
2039 }
2040 }
2041 return StringUtils.INDEX_NOT_FOUND;
2042 }
2043
2044 /**
2045 * Searches the string builder to find the first reference to the specified string.
2046 * <p>
2047 * Note that a null input string will return -1, whereas the JDK throws an exception.
2048 * </p>
2049 *
2050 * @param str The string to find, null returns -1.
2051 * @return The first index of the string, or -1 if not found.
2052 */
2053 public int indexOf(final String str) {
2054 return indexOf(str, 0);
2055 }
2056
2057 /**
2058 * Searches the string builder to find the first reference to the specified string starting searching from the given
2059 * index.
2060 * <p>
2061 * Note that a null input string will return -1, whereas the JDK throws an exception.
2062 * </p>
2063 *
2064 * @param str The string to find, null returns -1.
2065 * @param startIndex The index to start at, invalid index rounded to edge.
2066 * @return The first index of the string, or -1 if not found.
2067 */
2068 public int indexOf(final String str, int startIndex) {
2069 startIndex = Math.max(0, startIndex);
2070 if (str == null || startIndex >= size) {
2071 return StringUtils.INDEX_NOT_FOUND;
2072 }
2073 final int strLen = str.length();
2074 if (strLen == 1) {
2075 return indexOf(str.charAt(0), startIndex);
2076 }
2077 if (strLen == 0) {
2078 return startIndex;
2079 }
2080 if (strLen > size) {
2081 return StringUtils.INDEX_NOT_FOUND;
2082 }
2083 final char[] thisBuf = buffer;
2084 final int searchLen = size - strLen + 1;
2085 for (int i = startIndex; i < searchLen; i++) {
2086 boolean found = true;
2087 for (int j = 0; j < strLen && found; j++) {
2088 found = str.charAt(j) == thisBuf[i + j];
2089 }
2090 if (found) {
2091 return i;
2092 }
2093 }
2094 return StringUtils.INDEX_NOT_FOUND;
2095 }
2096
2097 /**
2098 * Searches the string builder using the matcher to find the first match.
2099 * <p>
2100 * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
2101 * character 'a' followed by a number.
2102 * </p>
2103 *
2104 * @param matcher The matcher to use, null returns -1.
2105 * @return The first index matched, or -1 if not found.
2106 */
2107 public int indexOf(final StringMatcher matcher) {
2108 return indexOf(matcher, 0);
2109 }
2110
2111 /**
2112 * Searches the string builder using the matcher to find the first match searching from the given index.
2113 * <p>
2114 * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
2115 * character 'a' followed by a number.
2116 * </p>
2117 *
2118 * @param matcher The matcher to use, null returns -1.
2119 * @param startIndex The index to start at, invalid index rounded to edge.
2120 * @return The first index matched, or -1 if not found.
2121 */
2122 public int indexOf(final StringMatcher matcher, int startIndex) {
2123 startIndex = Math.max(0, startIndex);
2124 if (matcher == null || startIndex >= size) {
2125 return StringUtils.INDEX_NOT_FOUND;
2126 }
2127 final int len = size;
2128 final char[] buf = buffer;
2129 for (int i = startIndex; i < len; i++) {
2130 if (matcher.isMatch(buf, i, startIndex, len) > 0) {
2131 return i;
2132 }
2133 }
2134 return StringUtils.INDEX_NOT_FOUND;
2135 }
2136
2137 /**
2138 * Inserts the value into this builder.
2139 *
2140 * @param index The index to add at, must be valid.
2141 * @param value The value to insert.
2142 * @return {@code this} instance.
2143 * @throws IndexOutOfBoundsException if the index is invalid.
2144 */
2145 public TextStringBuilder insert(final int index, final boolean value) {
2146 validateRange(index, size);
2147 if (value) {
2148 ensureCapacityInternal(size + TRUE_STRING_SIZE);
2149 System.arraycopy(buffer, index, buffer, index + TRUE_STRING_SIZE, size - index);
2150 appendTrue(index);
2151 } else {
2152 ensureCapacityInternal(size + FALSE_STRING_SIZE);
2153 System.arraycopy(buffer, index, buffer, index + FALSE_STRING_SIZE, size - index);
2154 appendFalse(index);
2155 }
2156 return this;
2157 }
2158
2159 /**
2160 * Inserts the value into this builder.
2161 *
2162 * @param index The index to add at, must be valid.
2163 * @param value The value to insert.
2164 * @return {@code this} instance.
2165 * @throws IndexOutOfBoundsException if the index is invalid.
2166 */
2167 public TextStringBuilder insert(final int index, final char value) {
2168 validateRange(index, size);
2169 ensureCapacityInternal(size + 1);
2170 System.arraycopy(buffer, index, buffer, index + 1, size - index);
2171 buffer[index] = value;
2172 size++;
2173 return this;
2174 }
2175
2176 /**
2177 * Inserts the character array into this builder. Inserting null will use the stored null text value.
2178 *
2179 * @param index The index to add at, must be valid.
2180 * @param chars The char array to insert.
2181 * @return {@code this} instance.
2182 * @throws IndexOutOfBoundsException if the index is invalid.
2183 */
2184 public TextStringBuilder insert(final int index, final char[] chars) {
2185 validateRange(index, size);
2186 if (chars == null) {
2187 return insert(index, nullText);
2188 }
2189 final int len = chars.length;
2190 if (len > 0) {
2191 ensureCapacityInternal(size + len);
2192 System.arraycopy(buffer, index, buffer, index + len, size - index);
2193 System.arraycopy(chars, 0, buffer, index, len);
2194 size += len;
2195 }
2196 return this;
2197 }
2198
2199 /**
2200 * Inserts part of the character array into this builder. Inserting null will use the stored null text value.
2201 *
2202 * @param index The index to add at, must be valid.
2203 * @param chars The char array to insert.
2204 * @param offset The offset into the character array to start at, must be valid.
2205 * @param length The length of the character array part to copy, must be positive.
2206 * @return {@code this} instance.
2207 * @throws IndexOutOfBoundsException if any index is invalid.
2208 */
2209 public TextStringBuilder insert(final int index, final char[] chars, final int offset, final int length) {
2210 validateRange(index, size);
2211 if (chars == null) {
2212 return insert(index, nullText);
2213 }
2214 if (offset < 0 || offset > chars.length) {
2215 throw new StringIndexOutOfBoundsException("Invalid offset: " + offset);
2216 }
2217 if (length < 0 || offset + length > chars.length) {
2218 throw new StringIndexOutOfBoundsException("Invalid length: " + length);
2219 }
2220 if (length > 0) {
2221 ensureCapacityInternal(size + length);
2222 System.arraycopy(buffer, index, buffer, index + length, size - index);
2223 System.arraycopy(chars, offset, buffer, index, length);
2224 size += length;
2225 }
2226 return this;
2227 }
2228
2229 /**
2230 * Inserts the value into this builder.
2231 *
2232 * @param index The index to add at, must be valid.
2233 * @param value The value to insert.
2234 * @return {@code this} instance.
2235 * @throws IndexOutOfBoundsException if the index is invalid.
2236 */
2237 public TextStringBuilder insert(final int index, final double value) {
2238 return insert(index, String.valueOf(value));
2239 }
2240
2241 /**
2242 * Inserts the value into this builder.
2243 *
2244 * @param index The index to add at, must be valid.
2245 * @param value The value to insert.
2246 * @return {@code this} instance.
2247 * @throws IndexOutOfBoundsException if the index is invalid.
2248 */
2249 public TextStringBuilder insert(final int index, final float value) {
2250 return insert(index, String.valueOf(value));
2251 }
2252
2253 /**
2254 * Inserts the value into this builder.
2255 *
2256 * @param index The index to add at, must be valid.
2257 * @param value The value to insert.
2258 * @return {@code this} instance.
2259 * @throws IndexOutOfBoundsException if the index is invalid.
2260 */
2261 public TextStringBuilder insert(final int index, final int value) {
2262 return insert(index, String.valueOf(value));
2263 }
2264
2265 /**
2266 * Inserts the value into this builder.
2267 *
2268 * @param index The index to add at, must be valid.
2269 * @param value The value to insert.
2270 * @return {@code this} instance.
2271 * @throws IndexOutOfBoundsException if the index is invalid.
2272 */
2273 public TextStringBuilder insert(final int index, final long value) {
2274 return insert(index, String.valueOf(value));
2275 }
2276
2277 /**
2278 * Inserts the string representation of an object into this builder. Inserting null will use the stored null text
2279 * value.
2280 *
2281 * @param index The index to add at, must be valid.
2282 * @param obj The object to insert.
2283 * @return {@code this} instance.
2284 * @throws IndexOutOfBoundsException if the index is invalid.
2285 */
2286 public TextStringBuilder insert(final int index, final Object obj) {
2287 return insert(index, Objects.toString(obj, nullText));
2288 }
2289
2290 /**
2291 * Inserts the string into this builder. Inserting null will use the stored null text value.
2292 *
2293 * @param index The index to add at, must be valid.
2294 * @param str The string to insert.
2295 * @return {@code this} instance.
2296 * @throws IndexOutOfBoundsException if the index is invalid.
2297 */
2298 public TextStringBuilder insert(final int index, String str) {
2299 validateRange(index, size);
2300 if (str == null) {
2301 str = nullText;
2302 }
2303 if (str != null) {
2304 final int strLen = str.length();
2305 if (strLen > 0) {
2306 final int newSize = size + strLen;
2307 ensureCapacityInternal(newSize);
2308 System.arraycopy(buffer, index, buffer, index + strLen, size - index);
2309 size = newSize;
2310 str.getChars(0, strLen, buffer, index);
2311 }
2312 }
2313 return this;
2314 }
2315
2316 /**
2317 * Checks is the string builder is empty (convenience Collections API style method).
2318 * <p>
2319 * This method is the same as checking {@link #length()} and is provided to match the API of Collections.
2320 * </p>
2321 *
2322 * @return {@code true} if the size is {@code 0}.
2323 */
2324 public boolean isEmpty() {
2325 return size == 0;
2326 }
2327
2328 /**
2329 * Checks is the string builder is not empty.
2330 * <p>
2331 * This method is the same as checking {@link #length()}.
2332 * </p>
2333 *
2334 * @return {@code true} if the size is not {@code 0}.
2335 * @since 1.9
2336 */
2337 public boolean isNotEmpty() {
2338 return size != 0;
2339 }
2340
2341 /**
2342 * Gets whether the internal buffer has been reallocated.
2343 *
2344 * @return Whether the internal buffer has been reallocated.
2345 * @since 1.9
2346 */
2347 public boolean isReallocated() {
2348 return reallocations > 0;
2349 }
2350
2351 /**
2352 * Searches the string builder to find the last reference to the specified char.
2353 *
2354 * @param ch The character to find.
2355 * @return The last index of the character, or -1 if not found.
2356 */
2357 public int lastIndexOf(final char ch) {
2358 return lastIndexOf(ch, size - 1);
2359 }
2360
2361 /**
2362 * Searches the string builder to find the last reference to the specified char.
2363 *
2364 * @param ch The character to find.
2365 * @param startIndex The index to start at, invalid index rounded to edge.
2366 * @return The last index of the character, or -1 if not found.
2367 */
2368 public int lastIndexOf(final char ch, int startIndex) {
2369 startIndex = startIndex >= size ? size - 1 : startIndex;
2370 if (startIndex < 0) {
2371 return StringUtils.INDEX_NOT_FOUND;
2372 }
2373 for (int i = startIndex; i >= 0; i--) {
2374 if (buffer[i] == ch) {
2375 return i;
2376 }
2377 }
2378 return StringUtils.INDEX_NOT_FOUND;
2379 }
2380
2381 /**
2382 * Searches the string builder to find the last reference to the specified string.
2383 * <p>
2384 * Note that a null input string will return -1, whereas the JDK throws an exception.
2385 * </p>
2386 *
2387 * @param str The string to find, null returns -1.
2388 * @return The last index of the string, or -1 if not found.
2389 */
2390 public int lastIndexOf(final String str) {
2391 return lastIndexOf(str, size);
2392 }
2393
2394 /**
2395 * Searches the string builder to find the last reference to the specified string starting searching from the given
2396 * index.
2397 * <p>
2398 * Note that a null input string will return -1, whereas the JDK throws an exception.
2399 * </p>
2400 *
2401 * @param str The string to find, null returns -1.
2402 * @param startIndex The index to start at, invalid index rounded to edge.
2403 * @return The last index of the string, or -1 if not found.
2404 */
2405 public int lastIndexOf(final String str, int startIndex) {
2406 startIndex = Math.min(startIndex, size);
2407 if (str == null || startIndex < 0) {
2408 return StringUtils.INDEX_NOT_FOUND;
2409 }
2410 final int strLen = str.length();
2411 if (strLen == 0) {
2412 return startIndex;
2413 }
2414 if (startIndex >= size) {
2415 startIndex = size - 1;
2416 }
2417 if (strLen > size) {
2418 return StringUtils.INDEX_NOT_FOUND;
2419 }
2420 if (strLen == 1) {
2421 return lastIndexOf(str.charAt(0), startIndex);
2422 }
2423 for (int i = startIndex - strLen + 1; i >= 0; i--) {
2424 boolean found = true;
2425 for (int j = 0; j < strLen && found; j++) {
2426 found = str.charAt(j) == buffer[i + j];
2427 }
2428 if (found) {
2429 return i;
2430 }
2431 }
2432 return StringUtils.INDEX_NOT_FOUND;
2433 }
2434
2435 /**
2436 * Searches the string builder using the matcher to find the last match.
2437 * <p>
2438 * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
2439 * character 'a' followed by a number.
2440 * </p>
2441 *
2442 * @param matcher The matcher to use, null returns -1.
2443 * @return The last index matched, or -1 if not found.
2444 */
2445 public int lastIndexOf(final StringMatcher matcher) {
2446 return lastIndexOf(matcher, size);
2447 }
2448
2449 /**
2450 * Searches the string builder using the matcher to find the last match searching from the given index.
2451 * <p>
2452 * Matchers can be used to perform advanced searching behavior. For example you could write a matcher to find the
2453 * character 'a' followed by a number.
2454 * </p>
2455 *
2456 * @param matcher The matcher to use, null returns -1.
2457 * @param startIndex The index to start at, invalid index rounded to edge.
2458 * @return The last index matched, or -1 if not found.
2459 */
2460 public int lastIndexOf(final StringMatcher matcher, int startIndex) {
2461 startIndex = startIndex >= size ? size - 1 : startIndex;
2462 if (matcher == null || startIndex < 0) {
2463 return StringUtils.INDEX_NOT_FOUND;
2464 }
2465 final char[] buf = buffer;
2466 final int endIndex = startIndex + 1;
2467 for (int i = startIndex; i >= 0; i--) {
2468 if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
2469 return i;
2470 }
2471 }
2472 return StringUtils.INDEX_NOT_FOUND;
2473 }
2474
2475 /**
2476 * Extracts the leftmost characters from the string builder without throwing an exception.
2477 * <p>
2478 * This method extracts the left {@code length} characters from the builder. If this many characters are not
2479 * available, the whole builder is returned. Thus the returned string may be shorter than the length requested.
2480 * </p>
2481 *
2482 * @param length The number of characters to extract, negative returns empty string.
2483 * @return The new string.
2484 */
2485 public String leftString(final int length) {
2486 if (length <= 0) {
2487 return StringUtils.EMPTY;
2488 }
2489 if (length >= size) {
2490 return new String(buffer, 0, size);
2491 }
2492 return new String(buffer, 0, length);
2493 }
2494
2495 /**
2496 * Gets the length of the string builder.
2497 *
2498 * @return The length
2499 */
2500 @Override
2501 public int length() {
2502 return size;
2503 }
2504
2505 /**
2506 * Extracts some characters from the middle of the string builder without throwing an exception.
2507 * <p>
2508 * This method extracts {@code length} characters from the builder at the specified index. If the index is negative
2509 * it is treated as zero. If the index is greater than the builder size, it is treated as the builder size. If the
2510 * length is negative, the empty string is returned. If insufficient characters are available in the builder, as
2511 * much as possible is returned. Thus the returned string may be shorter than the length requested.
2512 * </p>
2513 *
2514 * @param index The index to start at, negative means zero.
2515 * @param length The number of characters to extract, negative returns empty string.
2516 * @return The new string.
2517 */
2518 public String midString(int index, final int length) {
2519 if (index < 0) {
2520 index = 0;
2521 }
2522 if (length <= 0 || index >= size) {
2523 return StringUtils.EMPTY;
2524 }
2525 if (size <= index + length) {
2526 return new String(buffer, index, size - index);
2527 }
2528 return new String(buffer, index, length);
2529 }
2530
2531 /**
2532 * Minimizes the capacity to the actual length of the string.
2533 *
2534 * @return {@code this} instance.
2535 */
2536 public TextStringBuilder minimizeCapacity() {
2537 if (buffer.length > size) {
2538 reallocate(size);
2539 }
2540 return this;
2541 }
2542
2543 /**
2544 * If possible, reads chars from the provided {@link CharBuffer} directly into underlying character buffer without
2545 * making extra copies.
2546 *
2547 * @param charBuffer CharBuffer to read.
2548 * @return The number of characters read.
2549 * @see #appendTo(Appendable)
2550 * @since 1.9
2551 */
2552 public int readFrom(final CharBuffer charBuffer) {
2553 final int oldSize = size;
2554 final int remaining = charBuffer.remaining();
2555 ensureCapacityInternal(size + remaining);
2556 charBuffer.get(buffer, size, remaining);
2557 size += remaining;
2558 return size - oldSize;
2559 }
2560
2561 /**
2562 * If possible, reads all chars from the provided {@link Readable} directly into underlying character buffer without
2563 * making extra copies.
2564 *
2565 * @param readable object to read from.
2566 * @return The number of characters read.
2567 * @throws IOException Thrown if an I/O error occurs.
2568 * @see #appendTo(Appendable)
2569 */
2570 public int readFrom(final Readable readable) throws IOException {
2571 if (readable instanceof Reader) {
2572 return readFrom((Reader) readable);
2573 }
2574 if (readable instanceof CharBuffer) {
2575 return readFrom((CharBuffer) readable);
2576 }
2577 final int oldSize = size;
2578 while (true) {
2579 ensureCapacityInternal(size + 1);
2580 final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size);
2581 final int read = readable.read(buf);
2582 if (read == EOS) {
2583 break;
2584 }
2585 size += read;
2586 }
2587 return size - oldSize;
2588 }
2589
2590 /**
2591 * If possible, reads all chars from the provided {@link Reader} directly into underlying character buffer without
2592 * making extra copies.
2593 *
2594 * @param reader Reader to read.
2595 * @return The number of characters read or -1 if we reached the end of stream.
2596 * @throws IOException Thrown if an I/O error occurs.
2597 * @see #appendTo(Appendable)
2598 * @since 1.9
2599 */
2600 public int readFrom(final Reader reader) throws IOException {
2601 final int oldSize = size;
2602 ensureCapacityInternal(size + 1);
2603 int readCount = reader.read(buffer, size, buffer.length - size);
2604 if (readCount == EOS) {
2605 return EOS;
2606 }
2607 do {
2608 size += readCount;
2609 ensureCapacityInternal(size + 1);
2610 readCount = reader.read(buffer, size, buffer.length - size);
2611 } while (readCount != EOS);
2612 return size - oldSize;
2613 }
2614
2615 /**
2616 * If possible, reads {@code count} chars from the provided {@link Reader} directly into underlying character buffer without making extra copies.
2617 *
2618 * @param reader Reader to read.
2619 * @param count The maximum characters to read, a value <= 0 returns 0.
2620 * @return The number of characters read. If less than {@code count}, then we've reached the end-of-stream, or -1 if we reached the end of stream.
2621 * @throws IOException Thrown if an I/O error occurs.
2622 * @see #appendTo(Appendable)
2623 * @since 1.9
2624 */
2625 public int readFrom(final Reader reader, final int count) throws IOException {
2626 if (count <= 0) {
2627 return 0;
2628 }
2629 final int oldSize = size;
2630 ensureCapacityInternal(size + count);
2631 int target = count;
2632 int readCount = reader.read(buffer, size, target);
2633 if (readCount == EOS) {
2634 return EOS;
2635 }
2636 do {
2637 target -= readCount;
2638 size += readCount;
2639 readCount = reader.read(buffer, size, target);
2640 } while (target > 0 && readCount != EOS);
2641 return size - oldSize;
2642 }
2643
2644 /**
2645 * Reallocates the buffer to the new length.
2646 *
2647 * @param newLength The length of the copy to be returned.
2648 */
2649 private void reallocate(final int newLength) {
2650 this.buffer = Arrays.copyOf(buffer, newLength);
2651 this.reallocations++;
2652 }
2653
2654 /**
2655 * Replaces a portion of the string builder with another string. The length of the inserted string does not have to match the removed length.
2656 *
2657 * @param startIndex The start index, inclusive, must be valid.
2658 * @param endIndex The end index, exclusive, must be valid except that if too large it is treated as end of string.
2659 * @param replaceStr The string to replace with, null means delete range.
2660 * @return {@code this} instance.
2661 * @throws IndexOutOfBoundsException if the index is invalid.
2662 */
2663 public TextStringBuilder replace(final int startIndex, int endIndex, final String replaceStr) {
2664 endIndex = validateRange(startIndex, endIndex);
2665 final int insertLen = replaceStr == null ? 0 : replaceStr.length();
2666 replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen);
2667 return this;
2668 }
2669
2670 /**
2671 * Advanced search and replaces within the builder using a matcher.
2672 * <p>
2673 * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all occurrences where the character 'a' is followed by
2674 * a number.
2675 * </p>
2676 *
2677 * @param matcher The matcher to use to find the deletion, null causes no action.
2678 * @param replaceStr The string to replace the match with, null is a delete.
2679 * @param startIndex The start index, inclusive, must be valid.
2680 * @param endIndex The end index, exclusive, must be valid except that if too large it is treated as end of string.
2681 * @param replaceCount The number of times to replace, -1 for replace all.
2682 * @return {@code this} instance.
2683 * @throws IndexOutOfBoundsException if start index is invalid.
2684 */
2685 public TextStringBuilder replace(final StringMatcher matcher, final String replaceStr, final int startIndex,
2686 int endIndex, final int replaceCount) {
2687 endIndex = validateRange(startIndex, endIndex);
2688 return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount);
2689 }
2690
2691 /**
2692 * Replaces the search character with the replace character throughout the builder.
2693 *
2694 * @param search The search character.
2695 * @param replace The replace character.
2696 * @return {@code this} instance.
2697 */
2698 public TextStringBuilder replaceAll(final char search, final char replace) {
2699 if (search != replace) {
2700 for (int i = 0; i < size; i++) {
2701 if (buffer[i] == search) {
2702 buffer[i] = replace;
2703 }
2704 }
2705 }
2706 return this;
2707 }
2708
2709 /**
2710 * Replaces the search string with the replace string throughout the builder.
2711 *
2712 * @param searchStr The search string, null causes no action to occur.
2713 * @param replaceStr The replace string, null is equivalent to an empty string.
2714 * @return {@code this} instance.
2715 */
2716 public TextStringBuilder replaceAll(final String searchStr, final String replaceStr) {
2717 final int searchLen = searchStr == null ? 0 : searchStr.length();
2718 if (searchLen > 0) {
2719 final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
2720 int index = indexOf(searchStr, 0);
2721 while (index >= 0) {
2722 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
2723 index = indexOf(searchStr, index + replaceLen);
2724 }
2725 }
2726 return this;
2727 }
2728
2729 /**
2730 * Replaces all matches within the builder with the replace string.
2731 * <p>
2732 * Matchers can be used to perform advanced replace behavior. For example you could write a matcher to replace all
2733 * occurrences where the character 'a' is followed by a number.
2734 * </p>
2735 *
2736 * @param matcher The matcher to use to find the deletion, null causes no action.
2737 * @param replaceStr The replace string, null is equivalent to an empty string.
2738 * @return {@code this} instance.
2739 */
2740 public TextStringBuilder replaceAll(final StringMatcher matcher, final String replaceStr) {
2741 return replace(matcher, replaceStr, 0, size, -1);
2742 }
2743
2744 /**
2745 * Replaces the first instance of the search character with the replace character in the builder.
2746 *
2747 * @param search The search character.
2748 * @param replace The replace character.
2749 * @return {@code this} instance.
2750 */
2751 public TextStringBuilder replaceFirst(final char search, final char replace) {
2752 if (search != replace) {
2753 for (int i = 0; i < size; i++) {
2754 if (buffer[i] == search) {
2755 buffer[i] = replace;
2756 break;
2757 }
2758 }
2759 }
2760 return this;
2761 }
2762
2763 /**
2764 * Replaces the first instance of the search string with the replace string.
2765 *
2766 * @param searchStr The search string, null causes no action to occur.
2767 * @param replaceStr The replace string, null is equivalent to an empty string.
2768 * @return {@code this} instance.
2769 */
2770 public TextStringBuilder replaceFirst(final String searchStr, final String replaceStr) {
2771 final int searchLen = searchStr == null ? 0 : searchStr.length();
2772 if (searchLen > 0) {
2773 final int index = indexOf(searchStr, 0);
2774 if (index >= 0) {
2775 final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
2776 replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
2777 }
2778 }
2779 return this;
2780 }
2781
2782 /**
2783 * Replaces the first match within the builder with the replace string.
2784 * <p>
2785 * Matchers can be used to perform advanced replace behavior. For example you could write a matcher to replace where
2786 * the character 'a' is followed by a number.
2787 * </p>
2788 *
2789 * @param matcher The matcher to use to find the deletion, null causes no action.
2790 * @param replaceStr The replace string, null is equivalent to an empty string.
2791 * @return {@code this} instance.
2792 */
2793 public TextStringBuilder replaceFirst(final StringMatcher matcher, final String replaceStr) {
2794 return replace(matcher, replaceStr, 0, size, 1);
2795 }
2796
2797 /**
2798 * Internal method to delete a range without validation.
2799 *
2800 * @param startIndex The start index, must be valid.
2801 * @param endIndex The end index (exclusive), must be valid.
2802 * @param removeLen The length to remove (endIndex - startIndex), must be valid.
2803 * @param insertStr The string to replace with, null means delete range.
2804 * @param insertLen The length of the insert string, must be valid.
2805 * @throws IndexOutOfBoundsException if any index is invalid.
2806 */
2807 private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr,
2808 final int insertLen) {
2809 final int newSize = size - removeLen + insertLen;
2810 if (insertLen != removeLen) {
2811 ensureCapacityInternal(newSize);
2812 System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex);
2813 if (size > newSize) {
2814 Arrays.fill(buffer, newSize, size, CharUtils.NUL);
2815 }
2816 size = newSize;
2817 }
2818 if (insertLen > 0) {
2819 insertStr.getChars(0, insertLen, buffer, startIndex);
2820 }
2821 }
2822
2823 /**
2824 * Replaces within the builder using a matcher.
2825 * <p>
2826 * Matchers can be used to perform advanced behavior. For example you could write a matcher to delete all
2827 * occurrences where the character 'a' is followed by a number.
2828 * </p>
2829 *
2830 * @param matcher The matcher to use to find the deletion, null causes no action.
2831 * @param replaceStr The string to replace the match with, null is a delete.
2832 * @param from The start index, must be valid.
2833 * @param to The end index (exclusive), must be valid.
2834 * @param replaceCount The number of times to replace, -1 for replace all.
2835 * @return {@code this} instance.
2836 * @throws IndexOutOfBoundsException if any index is invalid.
2837 */
2838 private TextStringBuilder replaceImpl(final StringMatcher matcher, final String replaceStr, final int from, int to,
2839 int replaceCount) {
2840 if (matcher == null || size == 0) {
2841 return this;
2842 }
2843 final int replaceLen = replaceStr == null ? 0 : replaceStr.length();
2844 for (int i = from; i < to && replaceCount != 0; i++) {
2845 final char[] buf = buffer;
2846 final int removeLen = matcher.isMatch(buf, i, from, to);
2847 if (removeLen > 0) {
2848 replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen);
2849 to = to - removeLen + replaceLen;
2850 i = i + replaceLen - 1;
2851 if (replaceCount > 0) {
2852 replaceCount--;
2853 }
2854 }
2855 }
2856 return this;
2857 }
2858
2859 /**
2860 * Resizes the buffer to at least the size specified.
2861 *
2862 * @param minCapacity The minimum required capacity.
2863 * @throws OutOfMemoryError if the {@code minCapacity} is negative.
2864 */
2865 private void resizeBuffer(final int minCapacity) {
2866 // Overflow-conscious code treats the min and new capacity as unsigned.
2867 final int oldCapacity = buffer.length;
2868 int newCapacity = oldCapacity * 2;
2869 if (Integer.compareUnsigned(newCapacity, minCapacity) < 0) {
2870 newCapacity = minCapacity;
2871 }
2872 if (Integer.compareUnsigned(newCapacity, MAX_BUFFER_SIZE) > 0) {
2873 newCapacity = createPositiveCapacity(minCapacity);
2874 }
2875 reallocate(newCapacity);
2876 }
2877
2878 /**
2879 * Reverses the string builder placing each character in the opposite index.
2880 *
2881 * @return {@code this} instance.
2882 */
2883 public TextStringBuilder reverse() {
2884 if (size == 0) {
2885 return this;
2886 }
2887 final int half = size / 2;
2888 final char[] buf = buffer;
2889 boolean hasSurrogates = false;
2890 for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) {
2891 final char left = buf[leftIdx];
2892 final char right = buf[rightIdx];
2893 buf[leftIdx] = right;
2894 buf[rightIdx] = left;
2895 hasSurrogates |= Character.isSurrogate(left) || Character.isSurrogate(right);
2896 }
2897 if (hasSurrogates) {
2898 // The plain swap leaves each surrogate pair in low-high order; restore the high-low order so a
2899 // reversed supplementary code point stays a valid pair, matching StringBuilder#reverse().
2900 for (int i = 0; i < size - 1; i++) {
2901 if (Character.isLowSurrogate(buf[i]) && Character.isHighSurrogate(buf[i + 1])) {
2902 final char low = buf[i];
2903 buf[i] = buf[i + 1];
2904 buf[i + 1] = low;
2905 i++;
2906 }
2907 }
2908 }
2909 return this;
2910 }
2911
2912 /**
2913 * Extracts the rightmost characters from the string builder without throwing an exception.
2914 * <p>
2915 * This method extracts the right {@code length} characters from the builder. If this many characters are not
2916 * available, the whole builder is returned. Thus the returned string may be shorter than the length requested.
2917 * </p>
2918 *
2919 * @param length The number of characters to extract, negative returns empty string.
2920 * @return The new string.
2921 */
2922 public String rightString(final int length) {
2923 if (length <= 0) {
2924 return StringUtils.EMPTY;
2925 }
2926 if (length >= size) {
2927 return new String(buffer, 0, size);
2928 }
2929 return new String(buffer, size - length, length);
2930 }
2931
2932 /**
2933 * Clears and sets this builder to the given value.
2934 *
2935 * @param str The new value.
2936 * @return {@code this} instance.
2937 * @since 1.9
2938 * @see #charAt(int)
2939 * @see #deleteCharAt(int)
2940 */
2941 public TextStringBuilder set(final CharSequence str) {
2942 return clear().append(str);
2943 }
2944
2945 /**
2946 * Sets the character at the specified index.
2947 *
2948 * @param index The index to set
2949 * @param ch The new character
2950 * @return {@code this} instance.
2951 * @throws IndexOutOfBoundsException if the index is invalid
2952 * @see #charAt(int)
2953 * @see #deleteCharAt(int)
2954 */
2955 public TextStringBuilder setCharAt(final int index, final char ch) {
2956 validateIndex(index);
2957 buffer[index] = ch;
2958 return this;
2959 }
2960
2961 /**
2962 * Updates the length of the builder by either dropping the last characters or adding filler of Unicode zero.
2963 *
2964 * @param length The length to set to, must be zero or positive.
2965 * @return {@code this} instance.
2966 * @throws IndexOutOfBoundsException if the length is negative.
2967 */
2968 public TextStringBuilder setLength(final int length) {
2969 if (length < 0) {
2970 throw new StringIndexOutOfBoundsException(length);
2971 }
2972 if (length < size) {
2973 Arrays.fill(buffer, length, size, CharUtils.NUL);
2974 size = length;
2975 } else if (length > size) {
2976 ensureCapacityInternal(length);
2977 final int oldEnd = size;
2978 size = length;
2979 Arrays.fill(buffer, oldEnd, length, CharUtils.NUL);
2980 }
2981 return this;
2982 }
2983
2984 /**
2985 * Sets the text to be appended when {@link #appendNewLine() new line} is called.
2986 *
2987 * @param newLine The new line text, {@code null} means use the system default from {@link System#lineSeparator()}.
2988 * @return {@code this} instance.
2989 */
2990 public TextStringBuilder setNewLineText(final String newLine) {
2991 this.newLine = newLine;
2992 return this;
2993 }
2994
2995 /**
2996 * Sets the text to be appended when null is added.
2997 *
2998 * @param nullText The null text, null means no append.
2999 * @return {@code this} instance.
3000 */
3001 public TextStringBuilder setNullText(String nullText) {
3002 if (nullText != null && nullText.isEmpty()) {
3003 nullText = null;
3004 }
3005 this.nullText = nullText;
3006 return this;
3007 }
3008
3009 /**
3010 * Gets the length of the string builder.
3011 * <p>
3012 * This method is the same as {@link #length()} and is provided to match the API of Collections.
3013 * </p>
3014 *
3015 * @return The length.
3016 */
3017 public int size() {
3018 return size;
3019 }
3020
3021 /**
3022 * Checks whether this builder starts with the specified string.
3023 * <p>
3024 * Note that this method handles null input quietly, unlike String.
3025 * </p>
3026 *
3027 * @param str The string to search for, null returns false.
3028 * @return true if the builder starts with the string.
3029 */
3030 public boolean startsWith(final String str) {
3031 if (str == null) {
3032 return false;
3033 }
3034 final int len = str.length();
3035 if (len == 0) {
3036 return true;
3037 }
3038 if (len > size) {
3039 return false;
3040 }
3041 for (int i = 0; i < len; i++) {
3042 if (buffer[i] != str.charAt(i)) {
3043 return false;
3044 }
3045 }
3046 return true;
3047 }
3048
3049 /**
3050 * {@inheritDoc}
3051 */
3052 @Override
3053 public CharSequence subSequence(final int startIndex, final int endIndex) {
3054 if (startIndex < 0) {
3055 throw new StringIndexOutOfBoundsException(startIndex);
3056 }
3057 if (endIndex > size) {
3058 throw new StringIndexOutOfBoundsException(endIndex);
3059 }
3060 if (startIndex > endIndex) {
3061 throw new StringIndexOutOfBoundsException(endIndex - startIndex);
3062 }
3063 return substring(startIndex, endIndex);
3064 }
3065
3066 /**
3067 * Extracts a portion of this string builder as a string.
3068 *
3069 * @param start The start index, inclusive, must be valid.
3070 * @return The new string.
3071 * @throws IndexOutOfBoundsException if the index is invalid.
3072 */
3073 public String substring(final int start) {
3074 return substring(start, size);
3075 }
3076
3077 /**
3078 * Extracts a portion of this string builder as a string.
3079 * <p>
3080 * Note: This method treats an endIndex greater than the length of the builder as equal to the length of the
3081 * builder, and continues without error, unlike StringBuffer or String.
3082 * </p>
3083 *
3084 * @param startIndex The start index, inclusive, must be valid.
3085 * @param endIndex The end index, exclusive, must be valid except that if too large it is treated as end of string.
3086 * @return The new string.
3087 * @throws IndexOutOfBoundsException if the index is invalid.
3088 */
3089 public String substring(final int startIndex, int endIndex) {
3090 endIndex = validateRange(startIndex, endIndex);
3091 return new String(buffer, startIndex, endIndex - startIndex);
3092 }
3093
3094 /**
3095 * Copies the builder's character array into a new character array.
3096 *
3097 * @return A new array that represents the contents of the builder.
3098 */
3099 public char[] toCharArray() {
3100 return size == 0 ? ArrayUtils.EMPTY_CHAR_ARRAY : Arrays.copyOf(buffer, size);
3101 }
3102
3103 /**
3104 * Copies part of the builder's character array into a new character array.
3105 *
3106 * @param startIndex The start index, inclusive, must be valid.
3107 * @param endIndex The end index, exclusive, must be valid except that if too large it is treated as end of string.
3108 * @return A new array that holds part of the contents of the builder.
3109 * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is invalid (but endIndex greater than size is valid).
3110 */
3111 public char[] toCharArray(final int startIndex, int endIndex) {
3112 endIndex = validateRange(startIndex, endIndex);
3113 final int len = endIndex - startIndex;
3114 return len == 0 ? ArrayUtils.EMPTY_CHAR_ARRAY : Arrays.copyOfRange(buffer, startIndex, endIndex);
3115 }
3116
3117 /**
3118 * Gets a String version of the string builder, creating a new instance each time the method is called.
3119 * <p>
3120 * Note that unlike StringBuffer, the string version returned is independent of the string builder.
3121 * </p>
3122 *
3123 * @return The builder as a String.
3124 */
3125 @Override
3126 public String toString() {
3127 return new String(buffer, 0, size);
3128 }
3129
3130 /**
3131 * Gets a StringBuffer version of the string builder, creating a new instance each time the method is called.
3132 *
3133 * @return The builder as a StringBuffer.
3134 */
3135 public StringBuffer toStringBuffer() {
3136 return new StringBuffer(size).append(buffer, 0, size);
3137 }
3138
3139 /**
3140 * Gets a StringBuilder version of the string builder, creating a new instance each time the method is called.
3141 *
3142 * @return The builder as a StringBuilder.
3143 */
3144 public StringBuilder toStringBuilder() {
3145 return new StringBuilder(size).append(buffer, 0, size);
3146 }
3147
3148 /**
3149 * Trims the builder by removing characters less than or equal to a space from the beginning and end.
3150 *
3151 * @return {@code this} instance.
3152 */
3153 public TextStringBuilder trim() {
3154 if (size == 0) {
3155 return this;
3156 }
3157 int len = size;
3158 final char[] buf = buffer;
3159 int pos = 0;
3160 while (pos < len && buf[pos] <= SPACE) {
3161 pos++;
3162 }
3163 while (pos < len && buf[len - 1] <= SPACE) {
3164 len--;
3165 }
3166 if (len < size) {
3167 delete(len, size);
3168 }
3169 if (pos > 0) {
3170 delete(0, pos);
3171 }
3172 return this;
3173 }
3174
3175 /**
3176 * Validates that an index is in the range {@code 0 <= index < size}.
3177 *
3178 * @param index The index to test.
3179 * @throws IndexOutOfBoundsException Thrown when the index is not the range {@code 0 <= index < size}.
3180 */
3181 protected void validateIndex(final int index) {
3182 if (index < 0 || index >= size) {
3183 throw new StringIndexOutOfBoundsException(index);
3184 }
3185 }
3186
3187 /**
3188 * Validates parameters defining a range of the builder.
3189 *
3190 * @param startIndex The start index, inclusive, must be valid.
3191 * @param endIndex The end index, exclusive, must be valid except that if too large it is treated as end of string.
3192 * @return A valid end index.
3193 * @throws StringIndexOutOfBoundsException if the index is invalid.
3194 */
3195 protected int validateRange(final int startIndex, int endIndex) {
3196 if (startIndex < 0) {
3197 throw new StringIndexOutOfBoundsException(startIndex);
3198 }
3199 if (endIndex > size) {
3200 endIndex = size;
3201 }
3202 if (startIndex > endIndex) {
3203 throw new StringIndexOutOfBoundsException("end < start");
3204 }
3205 return endIndex;
3206 }
3207
3208 private void validateRange(final int startIndex, final int length, final int strLength) {
3209 if (startIndex < 0 || startIndex > strLength) {
3210 throw new StringIndexOutOfBoundsException("startIndex must be valid");
3211 }
3212 if (length < 0 || startIndex + length > strLength) {
3213 throw new StringIndexOutOfBoundsException("length must be valid");
3214 }
3215 }
3216
3217 }