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