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