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