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