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