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.wicket.util.string; 018 019import java.io.IOException; 020 021/** 022 * This is a copy or combination of <code>java.lang.StringBuffer</code> and 023 * <code>java.lang.String</code> It has a special method getValue() which returns the internal char 024 * array. 025 * 026 * Hashcode and equals methods are also implemented. 027 * 028 * This AppendingStringBuffer is not synchronized. 029 * 030 * @author Johan Compagner 031 * @see java.lang.StringBuffer 032 */ 033public final class AppendingStringBuffer implements java.io.Serializable, CharSequence 034{ 035 /** use serialVersionUID from JDK 1.0.2 for interoperability */ 036 private static final long serialVersionUID = 1L; 037 038 private static final AppendingStringBuffer NULL = new AppendingStringBuffer("null"); 039 private static final StringBuilder SB_NULL = new StringBuilder("null"); 040 private static final StringBuffer SBF_NULL = new StringBuffer("null"); 041 042 /** 043 * The value is used for character storage. 044 * 045 * @serial 046 */ 047 private char value[]; 048 049 /** 050 * The count is the number of characters in the buffer. 051 * 052 * @serial 053 */ 054 private int count; 055 056 /** 057 * Constructs a string buffer with no characters in it and an initial capacity of 16 characters. 058 */ 059 public AppendingStringBuffer() 060 { 061 this(16); 062 } 063 064 /** 065 * Constructs a string buffer with no characters in it and an initial capacity specified by the 066 * <code>length</code> argument. 067 * 068 * @param length 069 * the initial capacity. 070 * @exception NegativeArraySizeException 071 * if the <code>length</code> argument is less than <code>0</code>. 072 */ 073 public AppendingStringBuffer(final int length) 074 { 075 value = new char[length]; 076 } 077 078 /** 079 * Constructs a string buffer so that it represents the same sequence of characters as the 080 * string argument; in other words, the initial contents of the string buffer is a copy of the 081 * argument string. The initial capacity of the string buffer is <code>16</code> plus the length 082 * of the string argument. 083 * 084 * @param str 085 * the initial contents of the buffer. 086 * @exception NullPointerException 087 * if <code>str</code> is <code>null</code> 088 */ 089 public AppendingStringBuffer(final CharSequence str) 090 { 091 this(str.length() + 16); 092 append(str); 093 } 094 095 /** 096 * Returns the length (character count) of this string buffer. 097 * 098 * @return the length of the sequence of characters currently represented by this string buffer. 099 */ 100 @Override 101 public int length() 102 { 103 return count; 104 } 105 106 /** 107 * Returns the current capacity of the String buffer. The capacity is the amount of storage 108 * available for newly inserted characters; beyond which an allocation will occur. 109 * 110 * @return the current capacity of this string buffer. 111 */ 112 public int capacity() 113 { 114 return value.length; 115 } 116 117 /** 118 * Ensures that the capacity of the buffer is at least equal to the specified minimum. If the 119 * current capacity of this string buffer is less than the argument, then a new internal buffer 120 * is allocated with greater capacity. The new capacity is the larger of: 121 * <ul> 122 * <li>The <code>minimumCapacity</code> argument. 123 * <li>Twice the old capacity, plus <code>2</code>. 124 * </ul> 125 * If the <code>minimumCapacity</code> argument is nonpositive, this method takes no action and 126 * simply returns. 127 * 128 * @param minimumCapacity 129 * the minimum desired capacity. 130 */ 131 public void ensureCapacity(final int minimumCapacity) 132 { 133 if (minimumCapacity > value.length) 134 { 135 expandCapacity(minimumCapacity); 136 } 137 } 138 139 /** 140 * This implements the expansion semantics of ensureCapacity but is unsynchronized for use 141 * internally by methods which are already synchronized. 142 * 143 * @param minimumCapacity 144 * 145 * @see java.lang.StringBuffer#ensureCapacity(int) 146 */ 147 private void expandCapacity(final int minimumCapacity) 148 { 149 int newCapacity = (value.length + 1) * 2; 150 if (newCapacity < 0) 151 { 152 newCapacity = Integer.MAX_VALUE; 153 } 154 else if (minimumCapacity > newCapacity) 155 { 156 newCapacity = minimumCapacity; 157 } 158 159 char newValue[] = new char[newCapacity]; 160 System.arraycopy(value, 0, newValue, 0, count); 161 value = newValue; 162 } 163 164 /** 165 * Sets the length of this String buffer. This string buffer is altered to represent a new 166 * character sequence whose length is specified by the argument. For every nonnegative index 167 * <i>k</i> less than <code>newLength</code>, the character at index <i>k</i> in the new 168 * character sequence is the same as the character at index <i>k</i> in the old sequence if 169 * <i>k</i> is less than the length of the old character sequence; otherwise, it is the null 170 * character <code>'\u0000'</code>. 171 * 172 * In other words, if the <code>newLength</code> argument is less than the current length of the 173 * string buffer, the string buffer is truncated to contain exactly the number of characters 174 * given by the <code>newLength</code> argument. 175 * <p> 176 * If the <code>newLength</code> argument is greater than or equal to the current length, 177 * sufficient null characters (<code>'\u0000'</code>) are appended to the string buffer so 178 * that length becomes the <code>newLength</code> argument. 179 * <p> 180 * The <code>newLength</code> argument must be greater than or equal to <code>0</code>. 181 * 182 * @param newLength 183 * the new length of the buffer. 184 * @exception IndexOutOfBoundsException 185 * if the <code>newLength</code> argument is negative. 186 * @see java.lang.StringBuffer#length() 187 */ 188 public void setLength(final int newLength) 189 { 190 if (newLength < 0) 191 { 192 throw new StringIndexOutOfBoundsException(newLength); 193 } 194 195 if (newLength > value.length) 196 { 197 expandCapacity(newLength); 198 } 199 200 if (count < newLength) 201 { 202 for (; count < newLength; count++) 203 { 204 value[count] = '\0'; 205 } 206 } 207 else 208 { 209 count = newLength; 210 } 211 } 212 213 /** 214 * The specified character of the sequence currently represented by the string buffer, as 215 * indicated by the <code>index</code> argument, is returned. The first character of a string 216 * buffer is at index <code>0</code>, the next at index <code>1</code>, and so on, for array 217 * indexing. 218 * <p> 219 * The index argument must be greater than or equal to <code>0</code>, and less than the length 220 * of this string buffer. 221 * 222 * @param index 223 * the index of the desired character. 224 * @return the character at the specified index of this string buffer. 225 * @exception IndexOutOfBoundsException 226 * if <code>index</code> is negative or greater than or equal to 227 * <code>length()</code>. 228 * @see java.lang.StringBuffer#length() 229 */ 230 @Override 231 public char charAt(final int index) 232 { 233 if ((index < 0) || (index >= count)) 234 { 235 throw new StringIndexOutOfBoundsException(index); 236 } 237 return value[index]; 238 } 239 240 /** 241 * Characters are copied from this string buffer into the destination character array 242 * <code>dst</code>. The first character to be copied is at index <code>srcBegin</code>; the 243 * last character to be copied is at index <code>srcEnd-1</code>. The total number of characters 244 * to be copied is <code>srcEnd-srcBegin</code>. The characters are copied into the subarray of 245 * <code>dst</code> starting at index <code>dstBegin</code> and ending at index: 246 * <p> 247 * <blockquote> 248 * 249 * <pre> 250 * dstbegin + (srcEnd - srcBegin) - 1 251 * </pre> 252 * 253 * </blockquote> 254 * 255 * @param srcBegin 256 * start copying at this offset in the string buffer. 257 * @param srcEnd 258 * stop copying at this offset in the string buffer. 259 * @param dst 260 * the array to copy the data into. 261 * @param dstBegin 262 * offset into <code>dst</code>. 263 * @exception NullPointerException 264 * if <code>dst</code> is <code>null</code>. 265 * @exception IndexOutOfBoundsException 266 * if any of the following is true: 267 * <ul> 268 * <li><code>srcBegin</code> is negative <li><code>dstBegin</code> is negative 269 * <li>the <code>srcBegin</code> argument is greater than the <code>srcEnd</code> 270 * argument. <li><code>srcEnd</code> is greater than <code>this.length()</code>, 271 * the current length of this string buffer. <li><code>dstBegin+srcEnd-srcBegin 272 * </code> is greater than <code>dst.length</code> 273 * </ul> 274 */ 275 public void getChars(final int srcBegin, final int srcEnd, final char dst[], final int dstBegin) 276 { 277 if (srcBegin < 0) 278 { 279 throw new StringIndexOutOfBoundsException(srcBegin); 280 } 281 if ((srcEnd < 0) || (srcEnd > count)) 282 { 283 throw new StringIndexOutOfBoundsException(srcEnd); 284 } 285 if (srcBegin > srcEnd) 286 { 287 throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); 288 } 289 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); 290 } 291 292 /** 293 * The character at the specified index of this string buffer is set to <code>ch</code>. The 294 * string buffer is altered to represent a new character sequence that is identical to the old 295 * character sequence, except that it contains the character <code>ch</code> at position 296 * <code>index</code>. 297 * <p> 298 * The index argument must be greater than or equal to <code>0</code>, and less than the length 299 * of this string buffer. 300 * 301 * @param index 302 * the index of the character to modify. 303 * @param ch 304 * the new character. 305 * @exception IndexOutOfBoundsException 306 * if <code>index</code> is negative or greater than or equal to 307 * <code>length()</code>. 308 * @see java.lang.StringBuffer#length() 309 */ 310 public void setCharAt(final int index, final char ch) 311 { 312 if ((index < 0) || (index >= count)) 313 { 314 throw new StringIndexOutOfBoundsException(index); 315 } 316 value[index] = ch; 317 } 318 319 /** 320 * Appends the string representation of the <code>Object</code> argument to this string buffer. 321 * <p> 322 * The argument is converted to a string as if by the method <code>String.valueOf</code>, and 323 * the characters of that string are then appended to this string buffer. 324 * 325 * @param obj 326 * an <code>Object</code>. 327 * @return a reference to this <code>AppendingStringBuffer</code> object. 328 * @see java.lang.String#valueOf(java.lang.Object) 329 * @see java.lang.StringBuffer#append(java.lang.String) 330 */ 331 public AppendingStringBuffer append(final Object obj) 332 { 333 if (obj instanceof AppendingStringBuffer) 334 { 335 return append((AppendingStringBuffer)obj); 336 } 337 else if (obj instanceof StringBuilder) 338 { 339 return append((StringBuilder)obj); 340 } 341 else if (obj instanceof StringBuffer) 342 { 343 return append(obj.toString()); 344 } 345 return append(String.valueOf(obj)); 346 } 347 348 /** 349 * Appends the string to this string buffer. 350 * <p> 351 * The characters of the <code>String</code> argument are appended, in order, to the contents of 352 * this string buffer, increasing the length of this string buffer by the length of the 353 * argument. If <code>str</code> is <code>null</code>, then the four characters 354 * <code>"null"</code> are appended to this string buffer. 355 * <p> 356 * Let <i>n</i> be the length of the old character sequence, the one contained in the string 357 * buffer just prior to execution of the <code>append</code> method. Then the character at index 358 * <i>k</i> in the new character sequence is equal to the character at index <i>k</i> in the old 359 * character sequence, if <i>k</i> is less than <i>n</i>; otherwise, it is equal to the 360 * character at index <i>k-n</i> in the argument <code>str</code>. 361 * 362 * @param str 363 * a string. 364 * @return a reference to this <code>AppendingStringBuffer</code>. 365 */ 366 public AppendingStringBuffer append(String str) 367 { 368 if (str == null) 369 { 370 str = String.valueOf(str); 371 } 372 373 int len = str.length(); 374 int newcount = count + len; 375 if (newcount > value.length) 376 { 377 expandCapacity(newcount); 378 } 379 str.getChars(0, len, value, count); 380 count = newcount; 381 return this; 382 } 383 384 /** 385 * Appends the specified <tt>AppendingStringBuffer</tt> to this <tt>AppendingStringBuffer</tt>. 386 * <p> 387 * The characters of the <tt>AppendingStringBuffer</tt> argument are appended, in order, to the 388 * contents of this <tt>AppendingStringBuffer</tt>, increasing the length of this 389 * <tt>AppendingStringBuffer</tt> by the length of the argument. If <tt>sb</tt> is <tt>null</tt> 390 * , then the four characters <tt>"null"</tt> are appended to this 391 * <tt>AppendingStringBuffer</tt>. 392 * <p> 393 * Let <i>n</i> be the length of the old character sequence, the one contained in the 394 * <tt>AppendingStringBuffer</tt> just prior to execution of the <tt>append</tt> method. Then 395 * the character at index <i>k</i> in the new character sequence is equal to the character at 396 * index <i>k</i> in the old character sequence, if <i>k</i> is less than <i>n</i>; otherwise, 397 * it is equal to the character at index <i>k-n</i> in the argument <code>sb</code>. 398 * <p> 399 * The method <tt>ensureCapacity</tt> is first called on this <tt>AppendingStringBuffer</tt> 400 * with the new buffer length as its argument. (This ensures that the storage of this 401 * <tt>AppendingStringBuffer</tt> is adequate to contain the additional characters being 402 * appended.) 403 * 404 * @param sb 405 * the <tt>AppendingStringBuffer</tt> to append. 406 * @return a reference to this <tt>AppendingStringBuffer</tt>. 407 * @since 1.4 408 */ 409 public AppendingStringBuffer append(AppendingStringBuffer sb) 410 { 411 if (sb == null) 412 { 413 sb = NULL; 414 } 415 416 int len = sb.length(); 417 int newcount = count + len; 418 if (newcount > value.length) 419 { 420 expandCapacity(newcount); 421 } 422 sb.getChars(0, len, value, count); 423 count = newcount; 424 return this; 425 } 426 427 /** 428 * Appends the specified <tt>AppendingStringBuffer</tt> to this <tt>AppendingStringBuffer</tt>. 429 * <p> 430 * The characters of the <tt>AppendingStringBuffer</tt> argument are appended, in order, to the 431 * contents of this <tt>AppendingStringBuffer</tt>, increasing the length of this 432 * <tt>AppendingStringBuffer</tt> by the length of the argument. If <tt>sb</tt> is <tt>null</tt> 433 * , then the four characters <tt>"null"</tt> are appended to this 434 * <tt>AppendingStringBuffer</tt>. 435 * <p> 436 * Let <i>n</i> be the length of the old character sequence, the one contained in the 437 * <tt>AppendingStringBuffer</tt> just prior to execution of the <tt>append</tt> method. Then 438 * the character at index <i>k</i> in the new character sequence is equal to the character at 439 * index <i>k</i> in the old character sequence, if <i>k</i> is less than <i>n</i>; otherwise, 440 * it is equal to the character at index <i>k-n</i> in the argument <code>sb</code>. 441 * <p> 442 * The method <tt>ensureCapacity</tt> is first called on this <tt>AppendingStringBuffer</tt> 443 * with the new buffer length as its argument. (This ensures that the storage of this 444 * <tt>AppendingStringBuffer</tt> is adequate to contain the additional characters being 445 * appended.) 446 * 447 * @param sb 448 * the <tt>AppendingStringBuffer</tt> to append. 449 * @return a reference to this <tt>AppendingStringBuffer</tt>. 450 * @since 1.4 451 */ 452 public AppendingStringBuffer append(StringBuilder sb) 453 { 454 if (sb == null) 455 { 456 sb = SB_NULL; 457 } 458 459 int len = sb.length(); 460 int newcount = count + len; 461 if (newcount > value.length) 462 { 463 expandCapacity(newcount); 464 } 465 sb.getChars(0, len, value, count); 466 count = newcount; 467 return this; 468 } 469 470 /** 471 * Appends the string representation of the <code>char</code> array argument to this string 472 * buffer. 473 * <p> 474 * The characters of the array argument are appended, in order, to the contents of this string 475 * buffer. The length of this string buffer increases by the length of the argument. 476 * <p> 477 * The overall effect is exactly as if the argument were converted to a string by the method 478 * {@link String#valueOf(char[])} and the characters of that string were then 479 * {@link #append(String) appended} to this <code>AppendingStringBuffer</code> object. 480 * 481 * @param str 482 * the characters to be appended. 483 * @return a reference to this <code>AppendingStringBuffer</code> object. 484 */ 485 public AppendingStringBuffer append(final char str[]) 486 { 487 int len = str.length; 488 int newcount = count + len; 489 if (newcount > value.length) 490 { 491 expandCapacity(newcount); 492 } 493 System.arraycopy(str, 0, value, count, len); 494 count = newcount; 495 return this; 496 } 497 498 /** 499 * Appends the string representation of a subarray of the <code>char</code> array argument to 500 * this string buffer. 501 * <p> 502 * Characters of the character array <code>str</code>, starting at index <code>offset</code>, 503 * are appended, in order, to the contents of this string buffer. The length of this string 504 * buffer increases by the value of <code>len</code>. 505 * <p> 506 * The overall effect is exactly as if the arguments were converted to a string by the method 507 * {@link String#valueOf(char[],int,int)} and the characters of that string were then 508 * {@link #append(String) appended} to this <code>AppendingStringBuffer</code> object. 509 * 510 * @param str 511 * the characters to be appended. 512 * @param offset 513 * the index of the first character to append. 514 * @param len 515 * the number of characters to append. 516 * @return a reference to this <code>AppendingStringBuffer</code> object. 517 */ 518 public AppendingStringBuffer append(final char str[], final int offset, final int len) 519 { 520 int newcount = count + len; 521 if (newcount > value.length) 522 { 523 expandCapacity(newcount); 524 } 525 System.arraycopy(str, offset, value, count, len); 526 count = newcount; 527 return this; 528 } 529 530 /** 531 * Appends the string representation of the <code>boolean</code> argument to the string buffer. 532 * <p> 533 * The argument is converted to a string as if by the method <code>String.valueOf</code>, and 534 * the characters of that string are then appended to this string buffer. 535 * 536 * @param b 537 * a <code>boolean</code>. 538 * @return a reference to this <code>AppendingStringBuffer</code>. 539 * @see java.lang.String#valueOf(boolean) 540 * @see java.lang.StringBuffer#append(java.lang.String) 541 */ 542 public AppendingStringBuffer append(final boolean b) 543 { 544 if (b) 545 { 546 int newcount = count + 4; 547 if (newcount > value.length) 548 { 549 expandCapacity(newcount); 550 } 551 value[count++] = 't'; 552 value[count++] = 'r'; 553 value[count++] = 'u'; 554 value[count++] = 'e'; 555 } 556 else 557 { 558 int newcount = count + 5; 559 if (newcount > value.length) 560 { 561 expandCapacity(newcount); 562 } 563 value[count++] = 'f'; 564 value[count++] = 'a'; 565 value[count++] = 'l'; 566 value[count++] = 's'; 567 value[count++] = 'e'; 568 } 569 return this; 570 } 571 572 /** 573 * Appends the string representation of the <code>char</code> argument to this string buffer. 574 * <p> 575 * The argument is appended to the contents of this string buffer. The length of this string 576 * buffer increases by <code>1</code>. 577 * <p> 578 * The overall effect is exactly as if the argument were converted to a string by the method 579 * {@link String#valueOf(char)} and the character in that string were then 580 * {@link #append(String) appended} to this <code>AppendingStringBuffer</code> object. 581 * 582 * @param c 583 * a <code>char</code>. 584 * @return a reference to this <code>AppendingStringBuffer</code> object. 585 */ 586 public AppendingStringBuffer append(final char c) 587 { 588 int newcount = count + 1; 589 if (newcount > value.length) 590 { 591 expandCapacity(newcount); 592 } 593 value[count++] = c; 594 return this; 595 } 596 597 /** 598 * Appends the string representation of the <code>int</code> argument to this string buffer. 599 * <p> 600 * The argument is converted to a string as if by the method <code>String.valueOf</code>, and 601 * the characters of that string are then appended to this string buffer. 602 * 603 * @param i 604 * an <code>int</code>. 605 * @return a reference to this <code>AppendingStringBuffer</code> object. 606 * @see java.lang.String#valueOf(int) 607 * @see java.lang.StringBuffer#append(java.lang.String) 608 */ 609 public AppendingStringBuffer append(final int i) 610 { 611 return append(String.valueOf(i)); 612 } 613 614 /** 615 * Appends the string representation of the <code>long</code> argument to this string buffer. 616 * <p> 617 * The argument is converted to a string as if by the method <code>String.valueOf</code>, and 618 * the characters of that string are then appended to this string buffer. 619 * 620 * @param l 621 * a <code>long</code>. 622 * @return a reference to this <code>AppendingStringBuffer</code> object. 623 * @see java.lang.String#valueOf(long) 624 * @see java.lang.StringBuffer#append(java.lang.String) 625 */ 626 public AppendingStringBuffer append(final long l) 627 { 628 return append(String.valueOf(l)); 629 } 630 631 /** 632 * Appends the string representation of the <code>float</code> argument to this string buffer. 633 * <p> 634 * The argument is converted to a string as if by the method <code>String.valueOf</code>, and 635 * the characters of that string are then appended to this string buffer. 636 * 637 * @param f 638 * a <code>float</code>. 639 * @return a reference to this <code>AppendingStringBuffer</code> object. 640 * @see java.lang.String#valueOf(float) 641 * @see java.lang.StringBuffer#append(java.lang.String) 642 */ 643 public AppendingStringBuffer append(final float f) 644 { 645 return append(String.valueOf(f)); 646 } 647 648 /** 649 * Appends the string representation of the <code>double</code> argument to this string buffer. 650 * <p> 651 * The argument is converted to a string as if by the method <code>String.valueOf</code>, and 652 * the characters of that string are then appended to this string buffer. 653 * 654 * @param d 655 * a <code>double</code>. 656 * @return a reference to this <code>AppendingStringBuffer</code> object. 657 * @see java.lang.String#valueOf(double) 658 * @see java.lang.StringBuffer#append(java.lang.String) 659 */ 660 public AppendingStringBuffer append(final double d) 661 { 662 return append(String.valueOf(d)); 663 } 664 665 /** 666 * Removes the characters in a substring of this <code>AppendingStringBuffer</code>. The 667 * substring begins at the specified <code>start</code> and extends to the character at index 668 * <code>end - 1</code> or to the end of the <code>AppendingStringBuffer</code> if no such 669 * character exists. If <code>start</code> is equal to <code>end</code>, no changes are made. 670 * 671 * @param start 672 * The beginning index, inclusive. 673 * @param end 674 * The ending index, exclusive. 675 * @return This string buffer. 676 * @exception StringIndexOutOfBoundsException 677 * if <code>start</code> is negative, greater than <code>length()</code>, or 678 * greater than <code>end</code>. 679 * @since 1.2 680 */ 681 public AppendingStringBuffer delete(final int start, int end) 682 { 683 if (start < 0) 684 { 685 throw new StringIndexOutOfBoundsException(start); 686 } 687 if (end > count) 688 { 689 end = count; 690 } 691 if (start > end) 692 { 693 throw new StringIndexOutOfBoundsException(); 694 } 695 696 int len = end - start; 697 if (len > 0) 698 { 699 System.arraycopy(value, start + len, value, start, count - end); 700 count -= len; 701 } 702 return this; 703 } 704 705 /** 706 * Removes the character at the specified position in this <code>AppendingStringBuffer</code> 707 * (shortening the <code>AppendingStringBuffer</code> by one character). 708 * 709 * @param index 710 * Index of character to remove 711 * @return This string buffer. 712 * @exception StringIndexOutOfBoundsException 713 * if the <code>index</code> is negative or greater than or equal to 714 * <code>length()</code>. 715 * @since 1.2 716 */ 717 public AppendingStringBuffer deleteCharAt(final int index) 718 { 719 if ((index < 0) || (index >= count)) 720 { 721 throw new StringIndexOutOfBoundsException(); 722 } 723 System.arraycopy(value, index + 1, value, index, count - index - 1); 724 count--; 725 return this; 726 } 727 728 /** 729 * Replaces the characters in a substring of this <code>AppendingStringBuffer</code> with 730 * characters in the specified <code>String</code>. The substring begins at the specified 731 * <code>start</code> and extends to the character at index <code>end - 1</code> or to the end 732 * of the <code>AppendingStringBuffer</code> if no such character exists. First the characters 733 * in the substring are removed and then the specified <code>String</code> is inserted at 734 * <code>start</code>. (The <code>AppendingStringBuffer</code> will be lengthened to accommodate 735 * the specified String if necessary.) 736 * 737 * @param start 738 * The beginning index, inclusive. 739 * @param end 740 * The ending index, exclusive. 741 * @param str 742 * String that will replace previous contents. 743 * @return This string buffer. 744 * @exception StringIndexOutOfBoundsException 745 * if <code>start</code> is negative, greater than <code>length()</code>, or 746 * greater than <code>end</code>. 747 * @since 1.2 748 */ 749 public AppendingStringBuffer replace(final int start, int end, final String str) 750 { 751 if (start < 0) 752 { 753 throw new StringIndexOutOfBoundsException(start); 754 } 755 if (end > count) 756 { 757 end = count; 758 } 759 if (start > end) 760 { 761 throw new StringIndexOutOfBoundsException(); 762 } 763 764 int len = str.length(); 765 int newCount = count + len - (end - start); 766 if (newCount > value.length) 767 { 768 expandCapacity(newCount); 769 } 770 771 System.arraycopy(value, end, value, start + len, count - end); 772 str.getChars(0, len, value, start); 773 count = newCount; 774 return this; 775 } 776 777 /** 778 * Returns a new <code>String</code> that contains a subsequence of characters currently 779 * contained in this <code>AppendingStringBuffer</code>.The substring begins at the specified 780 * index and extends to the end of the <code>AppendingStringBuffer</code>. 781 * 782 * @param start 783 * The beginning index, inclusive. 784 * @return The new string. 785 * @exception StringIndexOutOfBoundsException 786 * if <code>start</code> is less than zero, or greater than the length of this 787 * <code>AppendingStringBuffer</code>. 788 * @since 1.2 789 */ 790 public String substring(final int start) 791 { 792 return substring(start, count); 793 } 794 795 /** 796 * Returns a new character sequence that is a subsequence of this sequence. 797 * 798 * <p> 799 * An invocation of this method of the form 800 * 801 * <blockquote> 802 * 803 * <pre> 804 * sb.subSequence(begin, end) 805 * </pre> 806 * 807 * </blockquote> 808 * 809 * behaves in exactly the same way as the invocation 810 * 811 * <blockquote> 812 * 813 * <pre> 814 * sb.substring(begin, end) 815 * </pre> 816 * 817 * </blockquote> 818 * 819 * This method is provided so that the <tt>AppendingStringBuffer</tt> class can implement the 820 * {@link CharSequence} interface. 821 * </p> 822 * 823 * @param start 824 * the start index, inclusive. 825 * @param end 826 * the end index, exclusive. 827 * @return the specified subsequence. 828 * 829 * @throws IndexOutOfBoundsException 830 * if <tt>start</tt> or <tt>end</tt> are negative, if <tt>end</tt> is greater than 831 * <tt>length()</tt>, or if <tt>start</tt> is greater than <tt>end</tt> 832 * 833 * @since 1.4 834 * Specification: JSR-51 835 */ 836 @Override 837 public CharSequence subSequence(final int start, final int end) 838 { 839 return this.substring(start, end); 840 } 841 842 /** 843 * Returns a new <code>String</code> that contains a subsequence of characters currently 844 * contained in this <code>AppendingStringBuffer</code>. The substring begins at the specified 845 * <code>start</code> and extends to the character at index <code>end - 1</code>. An exception 846 * is thrown if 847 * 848 * @param start 849 * The beginning index, inclusive. 850 * @param end 851 * The ending index, exclusive. 852 * @return The new string. 853 * @exception StringIndexOutOfBoundsException 854 * if <code>start</code> or <code>end</code> are negative or greater than 855 * <code>length()</code>, or <code>start</code> is greater than <code>end</code>. 856 * @since 1.2 857 */ 858 public String substring(final int start, final int end) 859 { 860 if (start < 0) 861 { 862 throw new StringIndexOutOfBoundsException(start); 863 } 864 if (end > count) 865 { 866 throw new StringIndexOutOfBoundsException(end); 867 } 868 if (start > end) 869 { 870 throw new StringIndexOutOfBoundsException(end - start); 871 } 872 return new String(value, start, end - start); 873 } 874 875 /** 876 * Inserts the string representation of a subarray of the <code>str</code> array argument into 877 * this string buffer. The subarray begins at the specified <code>offset</code> and extends 878 * <code>len</code> characters. The characters of the subarray are inserted into this string 879 * buffer at the position indicated by <code>index</code>. The length of this 880 * <code>AppendingStringBuffer</code> increases by <code>len</code> characters. 881 * 882 * @param index 883 * position at which to insert subarray. 884 * @param str 885 * A character array. 886 * @param offset 887 * the index of the first character in subarray to to be inserted. 888 * @param len 889 * the number of characters in the subarray to to be inserted. 890 * @return This string buffer. 891 * @exception StringIndexOutOfBoundsException 892 * if <code>index</code> is negative or greater than <code>length()</code>, or 893 * <code>offset</code> or <code>len</code> are negative, or 894 * <code>(offset+len)</code> is greater than <code>str.length</code>. 895 * @since 1.2 896 */ 897 public AppendingStringBuffer insert(final int index, final char str[], final int offset, 898 final int len) 899 { 900 if ((index < 0) || (index > count)) 901 { 902 throw new StringIndexOutOfBoundsException(); 903 } 904 if ((offset < 0) || (offset + len < 0) || (offset + len > str.length)) 905 { 906 throw new StringIndexOutOfBoundsException(offset); 907 } 908 if (len < 0) 909 { 910 throw new StringIndexOutOfBoundsException(len); 911 } 912 int newCount = count + len; 913 if (newCount > value.length) 914 { 915 expandCapacity(newCount); 916 } 917 System.arraycopy(value, index, value, index + len, count - index); 918 System.arraycopy(str, offset, value, index, len); 919 count = newCount; 920 return this; 921 } 922 923 /** 924 * Inserts the string representation of the <code>Object</code> argument into this string 925 * buffer. 926 * <p> 927 * The second argument is converted to a string as if by the method <code>String.valueOf</code>, 928 * and the characters of that string are then inserted into this string buffer at the indicated 929 * offset. 930 * <p> 931 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 932 * to the length of this string buffer. 933 * 934 * @param offset 935 * the offset. 936 * @param obj 937 * an <code>Object</code>. 938 * @return a reference to this <code>AppendingStringBuffer</code> object. 939 * @exception StringIndexOutOfBoundsException 940 * if the offset is invalid. 941 * @see java.lang.String#valueOf(java.lang.Object) 942 * @see AppendingStringBuffer#insert(int, java.lang.String) 943 * @see AppendingStringBuffer#length() 944 */ 945 public AppendingStringBuffer insert(final int offset, final Object obj) 946 { 947 if (obj instanceof AppendingStringBuffer) 948 { 949 AppendingStringBuffer asb = (AppendingStringBuffer)obj; 950 return insert(offset, asb.value, 0, asb.count); 951 } 952 else if (obj instanceof StringBuffer) 953 { 954 return insert(offset, (StringBuffer)obj); 955 } 956 else if (obj instanceof StringBuilder) 957 { 958 return insert(offset, (StringBuilder)obj); 959 } 960 return insert(offset, String.valueOf(obj)); 961 } 962 963 /** 964 * Inserts the string into this string buffer. 965 * <p> 966 * The characters of the <code>String</code> argument are inserted, in order, into this string 967 * buffer at the indicated offset, moving up any characters originally above that position and 968 * increasing the length of this string buffer by the length of the argument. If 969 * <code>str</code> is <code>null</code>, then the four characters <code>"null"</code> are 970 * inserted into this string buffer. 971 * <p> 972 * The character at index <i>k</i> in the new character sequence is equal to: 973 * <ul> 974 * <li>the character at index <i>k</i> in the old character sequence, if <i>k</i> is less than 975 * <code>offset</code> 976 * <li>the character at index <i>k</i><code>-offset</code> in the argument <code>str</code>, if 977 * <i>k</i> is not less than <code>offset</code> but is less than 978 * <code>offset+str.length()</code> 979 * <li>the character at index <i>k</i><code>-str.length()</code> in the old character sequence, 980 * if <i>k</i> is not less than <code>offset+str.length()</code> 981 * </ul> 982 * <p> 983 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 984 * to the length of this string buffer. 985 * 986 * @param offset 987 * the offset. 988 * @param str 989 * a string. 990 * @return a reference to this <code>AppendingStringBuffer</code> object. 991 * @exception StringIndexOutOfBoundsException 992 * if the offset is invalid. 993 * @see java.lang.StringBuffer#length() 994 */ 995 public AppendingStringBuffer insert(final int offset, String str) 996 { 997 if ((offset < 0) || (offset > count)) 998 { 999 throw new StringIndexOutOfBoundsException(); 1000 } 1001 1002 if (str == null) 1003 { 1004 str = String.valueOf(str); 1005 } 1006 int len = str.length(); 1007 int newcount = count + len; 1008 if (newcount > value.length) 1009 { 1010 expandCapacity(newcount); 1011 } 1012 System.arraycopy(value, offset, value, offset + len, count - offset); 1013 str.getChars(0, len, value, offset); 1014 count = newcount; 1015 return this; 1016 } 1017 1018 /** 1019 * Inserts the string into this string buffer. 1020 * <p> 1021 * The characters of the <code>StringBuilder</code> argument are inserted, in order, into this 1022 * string buffer at the indicated offset, moving up any characters originally above that 1023 * position and increasing the length of this string buffer by the length of the argument. If 1024 * <code>str</code> is <code>null</code>, then the four characters <code>"null"</code> are 1025 * inserted into this string buffer. 1026 * <p> 1027 * The character at index <i>k</i> in the new character sequence is equal to: 1028 * <ul> 1029 * <li>the character at index <i>k</i> in the old character sequence, if <i>k</i> is less than 1030 * <code>offset</code> 1031 * <li>the character at index <i>k</i><code>-offset</code> in the argument <code>str</code>, if 1032 * <i>k</i> is not less than <code>offset</code> but is less than 1033 * <code>offset+str.length()</code> 1034 * <li>the character at index <i>k</i><code>-str.length()</code> in the old character sequence, 1035 * if <i>k</i> is not less than <code>offset+str.length()</code> 1036 * </ul> 1037 * <p> 1038 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1039 * to the length of this string buffer. 1040 * 1041 * @param offset 1042 * the offset. 1043 * @param str 1044 * a string. 1045 * @return a reference to this <code>AppendingStringBuffer</code> object. 1046 * @exception StringIndexOutOfBoundsException 1047 * if the offset is invalid. 1048 * @see java.lang.StringBuffer#length() 1049 */ 1050 public AppendingStringBuffer insert(final int offset, StringBuilder str) 1051 { 1052 if ((offset < 0) || (offset > count)) 1053 { 1054 throw new StringIndexOutOfBoundsException(); 1055 } 1056 1057 if (str == null) 1058 { 1059 str = SB_NULL; 1060 } 1061 int len = str.length(); 1062 int newcount = count + len; 1063 if (newcount > value.length) 1064 { 1065 expandCapacity(newcount); 1066 } 1067 System.arraycopy(value, offset, value, offset + len, count - offset); 1068 str.getChars(0, len, value, offset); 1069 count = newcount; 1070 return this; 1071 } 1072 1073 /** 1074 * Inserts the string into this string buffer. 1075 * <p> 1076 * The characters of the <code>StringBuffer</code> argument are inserted, in order, into this 1077 * string buffer at the indicated offset, moving up any characters originally above that 1078 * position and increasing the length of this string buffer by the length of the argument. If 1079 * <code>str</code> is <code>null</code>, then the four characters <code>"null"</code> are 1080 * inserted into this string buffer. 1081 * <p> 1082 * The character at index <i>k</i> in the new character sequence is equal to: 1083 * <ul> 1084 * <li>the character at index <i>k</i> in the old character sequence, if <i>k</i> is less than 1085 * <code>offset</code> 1086 * <li>the character at index <i>k</i><code>-offset</code> in the argument <code>str</code>, if 1087 * <i>k</i> is not less than <code>offset</code> but is less than 1088 * <code>offset+str.length()</code> 1089 * <li>the character at index <i>k</i><code>-str.length()</code> in the old character sequence, 1090 * if <i>k</i> is not less than <code>offset+str.length()</code> 1091 * </ul> 1092 * <p> 1093 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1094 * to the length of this string buffer. 1095 * 1096 * @param offset 1097 * the offset. 1098 * @param str 1099 * a string. 1100 * @return a reference to this <code>AppendingStringBuffer</code> object. 1101 * @exception StringIndexOutOfBoundsException 1102 * if the offset is invalid. 1103 * @see java.lang.StringBuffer#length() 1104 */ 1105 public AppendingStringBuffer insert(final int offset, StringBuffer str) 1106 { 1107 if ((offset < 0) || (offset > count)) 1108 { 1109 throw new StringIndexOutOfBoundsException(); 1110 } 1111 1112 if (str == null) 1113 { 1114 str = SBF_NULL; 1115 } 1116 int len = str.length(); 1117 int newcount = count + len; 1118 if (newcount > value.length) 1119 { 1120 expandCapacity(newcount); 1121 } 1122 System.arraycopy(value, offset, value, offset + len, count - offset); 1123 str.getChars(0, len, value, offset); 1124 count = newcount; 1125 return this; 1126 } 1127 1128 /** 1129 * Inserts the string representation of the <code>char</code> array argument into this string 1130 * buffer. 1131 * <p> 1132 * The characters of the array argument are inserted into the contents of this string buffer at 1133 * the position indicated by <code>offset</code>. The length of this string buffer increases by 1134 * the length of the argument. 1135 * <p> 1136 * The overall effect is exactly as if the argument were converted to a string by the method 1137 * {@link String#valueOf(char[])} and the characters of that string were then 1138 * {@link #insert(int,String) inserted} into this <code>AppendingStringBuffer</code> object at 1139 * the position indicated by <code>offset</code>. 1140 * 1141 * @param offset 1142 * the offset. 1143 * @param str 1144 * a character array. 1145 * @return a reference to this <code>AppendingStringBuffer</code> object. 1146 * @exception StringIndexOutOfBoundsException 1147 * if the offset is invalid. 1148 */ 1149 public AppendingStringBuffer insert(final int offset, final char str[]) 1150 { 1151 if ((offset < 0) || (offset > count)) 1152 { 1153 throw new StringIndexOutOfBoundsException(); 1154 } 1155 int len = str.length; 1156 int newcount = count + len; 1157 if (newcount > value.length) 1158 { 1159 expandCapacity(newcount); 1160 } 1161 System.arraycopy(value, offset, value, offset + len, count - offset); 1162 System.arraycopy(str, 0, value, offset, len); 1163 count = newcount; 1164 return this; 1165 } 1166 1167 /** 1168 * Inserts the string representation of the <code>boolean</code> argument into this string 1169 * buffer. 1170 * <p> 1171 * The second argument is converted to a string as if by the method <code>String.valueOf</code>, 1172 * and the characters of that string are then inserted into this string buffer at the indicated 1173 * offset. 1174 * <p> 1175 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1176 * to the length of this string buffer. 1177 * 1178 * @param offset 1179 * the offset. 1180 * @param b 1181 * a <code>boolean</code>. 1182 * @return a reference to this <code>AppendingStringBuffer</code> object. 1183 * @exception StringIndexOutOfBoundsException 1184 * if the offset is invalid. 1185 * @see java.lang.String#valueOf(boolean) 1186 * @see java.lang.StringBuffer#insert(int, java.lang.String) 1187 * @see java.lang.StringBuffer#length() 1188 */ 1189 public AppendingStringBuffer insert(final int offset, final boolean b) 1190 { 1191 return insert(offset, String.valueOf(b)); 1192 } 1193 1194 /** 1195 * Inserts the string representation of the <code>char</code> argument into this string buffer. 1196 * <p> 1197 * The second argument is inserted into the contents of this string buffer at the position 1198 * indicated by <code>offset</code>. The length of this string buffer increases by one. 1199 * <p> 1200 * The overall effect is exactly as if the argument were converted to a string by the method 1201 * {@link String#valueOf(char)} and the character in that string were then 1202 * {@link #insert(int, String) inserted} into this <code>AppendingStringBuffer</code> object at 1203 * the position indicated by <code>offset</code>. 1204 * <p> 1205 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1206 * to the length of this string buffer. 1207 * 1208 * @param offset 1209 * the offset. 1210 * @param c 1211 * a <code>char</code>. 1212 * @return a reference to this <code>AppendingStringBuffer</code> object. 1213 * @exception IndexOutOfBoundsException 1214 * if the offset is invalid. 1215 * @see java.lang.StringBuffer#length() 1216 */ 1217 public AppendingStringBuffer insert(final int offset, final char c) 1218 { 1219 int newcount = count + 1; 1220 if (newcount > value.length) 1221 { 1222 expandCapacity(newcount); 1223 } 1224 System.arraycopy(value, offset, value, offset + 1, count - offset); 1225 value[offset] = c; 1226 count = newcount; 1227 return this; 1228 } 1229 1230 /** 1231 * Inserts the string representation of the second <code>int</code> argument into this string 1232 * buffer. 1233 * <p> 1234 * The second argument is converted to a string as if by the method <code>String.valueOf</code>, 1235 * and the characters of that string are then inserted into this string buffer at the indicated 1236 * offset. 1237 * <p> 1238 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1239 * to the length of this string buffer. 1240 * 1241 * @param offset 1242 * the offset. 1243 * @param i 1244 * an <code>int</code>. 1245 * @return a reference to this <code>AppendingStringBuffer</code> object. 1246 * @exception StringIndexOutOfBoundsException 1247 * if the offset is invalid. 1248 * @see java.lang.String#valueOf(int) 1249 * @see java.lang.StringBuffer#insert(int, java.lang.String) 1250 * @see java.lang.StringBuffer#length() 1251 */ 1252 public AppendingStringBuffer insert(final int offset, final int i) 1253 { 1254 return insert(offset, String.valueOf(i)); 1255 } 1256 1257 /** 1258 * Inserts the string representation of the <code>long</code> argument into this string buffer. 1259 * <p> 1260 * The second argument is converted to a string as if by the method <code>String.valueOf</code>, 1261 * and the characters of that string are then inserted into this string buffer at the position 1262 * indicated by <code>offset</code>. 1263 * <p> 1264 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1265 * to the length of this string buffer. 1266 * 1267 * @param offset 1268 * the offset. 1269 * @param l 1270 * a <code>long</code>. 1271 * @return a reference to this <code>AppendingStringBuffer</code> object. 1272 * @exception StringIndexOutOfBoundsException 1273 * if the offset is invalid. 1274 * @see java.lang.String#valueOf(long) 1275 * @see java.lang.StringBuffer#insert(int, java.lang.String) 1276 * @see java.lang.StringBuffer#length() 1277 */ 1278 public AppendingStringBuffer insert(final int offset, final long l) 1279 { 1280 return insert(offset, String.valueOf(l)); 1281 } 1282 1283 /** 1284 * Inserts the string representation of the <code>float</code> argument into this string buffer. 1285 * <p> 1286 * The second argument is converted to a string as if by the method <code>String.valueOf</code>, 1287 * and the characters of that string are then inserted into this string buffer at the indicated 1288 * offset. 1289 * <p> 1290 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1291 * to the length of this string buffer. 1292 * 1293 * @param offset 1294 * the offset. 1295 * @param f 1296 * a <code>float</code>. 1297 * @return a reference to this <code>AppendingStringBuffer</code> object. 1298 * @exception StringIndexOutOfBoundsException 1299 * if the offset is invalid. 1300 * @see java.lang.String#valueOf(float) 1301 * @see java.lang.StringBuffer#insert(int, java.lang.String) 1302 * @see java.lang.StringBuffer#length() 1303 */ 1304 public AppendingStringBuffer insert(final int offset, final float f) 1305 { 1306 return insert(offset, String.valueOf(f)); 1307 } 1308 1309 /** 1310 * Inserts the string representation of the <code>double</code> argument into this string 1311 * buffer. 1312 * <p> 1313 * The second argument is converted to a string as if by the method <code>String.valueOf</code>, 1314 * and the characters of that string are then inserted into this string buffer at the indicated 1315 * offset. 1316 * <p> 1317 * The offset argument must be greater than or equal to <code>0</code>, and less than or equal 1318 * to the length of this string buffer. 1319 * 1320 * @param offset 1321 * the offset. 1322 * @param d 1323 * a <code>double</code>. 1324 * @return a reference to this <code>AppendingStringBuffer</code> object. 1325 * @exception StringIndexOutOfBoundsException 1326 * if the offset is invalid. 1327 * @see java.lang.String#valueOf(double) 1328 * @see java.lang.StringBuffer#insert(int, java.lang.String) 1329 * @see java.lang.StringBuffer#length() 1330 */ 1331 public AppendingStringBuffer insert(final int offset, final double d) 1332 { 1333 return insert(offset, String.valueOf(d)); 1334 } 1335 1336 /** 1337 * Returns the index within this string of the first occurrence of the specified substring. The 1338 * integer returned is the smallest value <i>k</i> such that: <blockquote> 1339 * 1340 * <pre> 1341 * this.toString().startsWith(str, <i>k</i>) 1342 * </pre> 1343 * 1344 * </blockquote> is <code>true</code>. 1345 * 1346 * @param str 1347 * any string. 1348 * @return if the string argument occurs as a substring within this object, then the index of 1349 * the first character of the first such substring is returned; if it does not occur as 1350 * a substring, <code>-1</code> is returned. 1351 * @exception java.lang.NullPointerException 1352 * if <code>str</code> is <code>null</code>. 1353 * @since 1.4 1354 */ 1355 public int indexOf(final String str) 1356 { 1357 return indexOf(str, 0); 1358 } 1359 1360 /** 1361 * Returns the index within this string of the first occurrence of the specified substring, 1362 * starting at the specified index. The integer returned is the smallest value <tt>k</tt> for 1363 * which: <blockquote> 1364 * 1365 * <pre> 1366 * k >= Math.min(fromIndex, str.length()) && this.toString().startsWith(str, k) 1367 * </pre> 1368 * 1369 * </blockquote> If no such value of <i>k</i> exists, then -1 is returned. 1370 * 1371 * @param str 1372 * the substring for which to search. 1373 * @param fromIndex 1374 * the index from which to start the search. 1375 * @return the index within this string of the first occurrence of the specified substring, 1376 * starting at the specified index. 1377 * @exception java.lang.NullPointerException 1378 * if <code>str</code> is <code>null</code>. 1379 * @since 1.4 1380 */ 1381 public int indexOf(final String str, final int fromIndex) 1382 { 1383 return indexOf(value, 0, count, str.toCharArray(), 0, str.length(), fromIndex); 1384 } 1385 1386 static int indexOf(final char[] source, final int sourceOffset, final int sourceCount, 1387 final char[] target, final int targetOffset, final int targetCount, int fromIndex) 1388 { 1389 if (fromIndex >= sourceCount) 1390 { 1391 return (targetCount == 0 ? sourceCount : -1); 1392 } 1393 if (fromIndex < 0) 1394 { 1395 fromIndex = 0; 1396 } 1397 if (targetCount == 0) 1398 { 1399 return fromIndex; 1400 } 1401 1402 char first = target[targetOffset]; 1403 int i = sourceOffset + fromIndex; 1404 int max = sourceOffset + (sourceCount - targetCount); 1405 1406 startSearchForFirstChar : while (true) 1407 { 1408 /* Look for first character. */ 1409 while ((i <= max) && (source[i] != first)) 1410 { 1411 i++; 1412 } 1413 if (i > max) 1414 { 1415 return -1; 1416 } 1417 1418 /* Found first character, now look at the rest of v2 */ 1419 int j = i + 1; 1420 int end = j + targetCount - 1; 1421 int k = targetOffset + 1; 1422 while (j < end) 1423 { 1424 if (source[j++] != target[k++]) 1425 { 1426 i++; 1427 /* Look for str's first char again. */ 1428 continue startSearchForFirstChar; 1429 } 1430 } 1431 return i - sourceOffset; /* Found whole string. */ 1432 } 1433 } 1434 1435 /** 1436 * Returns the index within this string of the rightmost occurrence of the specified substring. 1437 * The rightmost empty string "" is considered to occur at the index value 1438 * <code>this.length()</code>. The returned index is the largest value <i>k</i> such that 1439 * <blockquote> 1440 * 1441 * <pre> 1442 * this.toString().startsWith(str, k) 1443 * </pre> 1444 * 1445 * </blockquote> is true. 1446 * 1447 * @param str 1448 * the substring to search for. 1449 * @return if the string argument occurs one or more times as a substring within this object, 1450 * then the index of the first character of the last such substring is returned. If it 1451 * does not occur as a substring, <code>-1</code> is returned. 1452 * @exception java.lang.NullPointerException 1453 * if <code>str</code> is <code>null</code>. 1454 * @since 1.4 1455 */ 1456 public int lastIndexOf(final String str) 1457 { 1458 return lastIndexOf(str, count); 1459 } 1460 1461 /** 1462 * Returns the index within this string of the last occurrence of the specified substring. The 1463 * integer returned is the largest value <i>k</i> such that: <blockquote> 1464 * 1465 * <pre> 1466 * k <= Math.min(fromIndex, str.length()) && this.toString().startsWith(str, k) 1467 * </pre> 1468 * 1469 * </blockquote> If no such value of <i>k</i> exists, then -1 is returned. 1470 * 1471 * @param str 1472 * the substring to search for. 1473 * @param fromIndex 1474 * the index to start the search from. 1475 * @return the index within this string of the last occurrence of the specified substring. 1476 * @exception java.lang.NullPointerException 1477 * if <code>str</code> is <code>null</code>. 1478 * @since 1.4 1479 */ 1480 public int lastIndexOf(final String str, final int fromIndex) 1481 { 1482 return lastIndexOf(value, 0, count, str.toCharArray(), 0, str.length(), fromIndex); 1483 } 1484 1485 static int lastIndexOf(final char[] source, final int sourceOffset, final int sourceCount, 1486 final char[] target, final int targetOffset, final int targetCount, int fromIndex) 1487 { 1488 /* 1489 * Check arguments; return immediately where possible. For consistency, don't check for null 1490 * str. 1491 */ 1492 int rightIndex = sourceCount - targetCount; 1493 if (fromIndex < 0) 1494 { 1495 return -1; 1496 } 1497 if (fromIndex > rightIndex) 1498 { 1499 fromIndex = rightIndex; 1500 } 1501 /* Empty string always matches. */ 1502 if (targetCount == 0) 1503 { 1504 return fromIndex; 1505 } 1506 1507 int strLastIndex = targetOffset + targetCount - 1; 1508 char strLastChar = target[strLastIndex]; 1509 int min = sourceOffset + targetCount - 1; 1510 int i = min + fromIndex; 1511 1512 startSearchForLastChar : while (true) 1513 { 1514 while ((i >= min) && (source[i] != strLastChar)) 1515 { 1516 i--; 1517 } 1518 if (i < min) 1519 { 1520 return -1; 1521 } 1522 int j = i - 1; 1523 int start = j - (targetCount - 1); 1524 int k = strLastIndex - 1; 1525 1526 while (j > start) 1527 { 1528 if (source[j--] != target[k--]) 1529 { 1530 i--; 1531 continue startSearchForLastChar; 1532 } 1533 } 1534 return start - sourceOffset + 1; 1535 } 1536 } 1537 1538 /** 1539 * Tests if this AppendingStringBuffer starts with the specified prefix beginning a specified 1540 * index. 1541 * 1542 * @param prefix 1543 * the prefix. 1544 * @param toffset 1545 * where to begin looking in the string. 1546 * @return <code>true</code> if the character sequence represented by the argument is a prefix 1547 * of the substring of this object starting at index <code>toffset</code>; 1548 * <code>false</code> otherwise. The result is <code>false</code> if 1549 * <code>toffset</code> is negative or greater than the length of this 1550 * <code>String</code> object; otherwise the result is the same as the result of the 1551 * expression 1552 * 1553 * <pre> 1554 * this.subString(toffset).startsWith(prefix) 1555 * </pre> 1556 */ 1557 public boolean startsWith(final CharSequence prefix, final int toffset) 1558 { 1559 char ta[] = value; 1560 int to = toffset; 1561 int po = 0; 1562 int pc = prefix.length(); 1563 // Note: toffset might be near -1>>>1. 1564 if ((toffset < 0) || (toffset > count - pc)) 1565 { 1566 return false; 1567 } 1568 while (--pc >= 0) 1569 { 1570 if (ta[to++] != prefix.charAt(po++)) 1571 { 1572 return false; 1573 } 1574 } 1575 return true; 1576 } 1577 1578 /** 1579 * Tests if this AppendingStringBuffer starts with the specified prefix. 1580 * 1581 * @param prefix 1582 * the prefix. 1583 * @return <code>true</code> if the character sequence represented by the argument is a prefix 1584 * of the character sequence represented by this AppendingStringBuffer; 1585 * <code>false</code> otherwise. Note also that <code>true</code> will be returned if 1586 * the argument is an empty string or is equal to this 1587 * <code>AppendingStringBuffer</code> object as determined by the 1588 * {@link #equals(Object)} method. 1589 * @since 1. 0 1590 */ 1591 public boolean startsWith(final CharSequence prefix) 1592 { 1593 return startsWith(prefix, 0); 1594 } 1595 1596 /** 1597 * Tests if this AppendingStringBuffer ends with the specified suffix. 1598 * 1599 * @param suffix 1600 * the suffix. 1601 * @return <code>true</code> if the character sequence represented by the argument is a suffix 1602 * of the character sequence represented by this AppendingStringBuffer; 1603 * <code>false</code> otherwise. Note that the result will be <code>true</code> if the 1604 * argument is the empty string or is equal to this <code>AppendingStringBuffer</code> 1605 * object as determined by the {@link #equals(Object)} method. 1606 */ 1607 public boolean endsWith(final CharSequence suffix) 1608 { 1609 return startsWith(suffix, count - suffix.length()); 1610 } 1611 1612 /** 1613 * Converts to a string representing the data in this AppendingStringBuffer. A new 1614 * <code>String</code> object is allocated and initialized to contain the character sequence 1615 * currently represented by this string buffer. This <code>String</code> is then returned. 1616 * Subsequent changes to the string buffer do not affect the contents of the <code>String</code> 1617 * . 1618 * <p> 1619 * Implementation advice: This method can be coded so as to create a new <code>String</code> 1620 * object without allocating new memory to hold a copy of the character sequence. Instead, the 1621 * string can share the memory used by the string buffer. Any subsequent operation that alters 1622 * the content or capacity of the string buffer must then make a copy of the internal buffer at 1623 * that time. This strategy is effective for reducing the amount of memory allocated by a string 1624 * concatenation operation when it is implemented using a string buffer. 1625 * 1626 * @return a string representation of the string buffer. 1627 */ 1628 @Override 1629 public String toString() 1630 { 1631 return new String(value, 0, count); 1632 } 1633 1634 /** 1635 * This method returns the internal char array. So it is not 1636 * 1637 * @return The internal char array 1638 */ 1639 public final char[] getValue() 1640 { 1641 return value; 1642 } 1643 1644 1645 /** 1646 * readObject is called to restore the state of the AppendingStringBuffer from a stream. 1647 * 1648 * @param s 1649 * @throws ClassNotFoundException 1650 * @throws IOException 1651 */ 1652 private void readObject(final java.io.ObjectInputStream s) throws IOException, 1653 ClassNotFoundException 1654 { 1655 s.defaultReadObject(); 1656 value = value.clone(); 1657 } 1658 1659 /** 1660 * Compares this AppendingStringBuffer to the specified object. The result is <code>true</code> 1661 * if and only if the argument is not <code>null</code> and is a 1662 * <code>AppendingStringBuffer</code> object or another charsequence object! that represents the 1663 * same sequence of characters as this object. 1664 * 1665 * @param anObject 1666 * the object to compare this <code>AppendingStringBuffer</code> against. 1667 * @return <code>true</code> if the <code>AppendingStringBuffer</code>are equal; 1668 * <code>false</code> otherwise. 1669 */ 1670 @Override 1671 public boolean equals(final Object anObject) 1672 { 1673 if (this == anObject) 1674 { 1675 return true; 1676 } 1677 if (anObject instanceof AppendingStringBuffer) 1678 { 1679 AppendingStringBuffer anotherString = (AppendingStringBuffer)anObject; 1680 int n = count; 1681 if (n == anotherString.count) 1682 { 1683 char v1[] = value; 1684 char v2[] = anotherString.value; 1685 int i = 0; 1686 while (n-- != 0) 1687 { 1688 if (v1[i] != v2[i++]) 1689 { 1690 return false; 1691 } 1692 } 1693 return true; 1694 } 1695 } 1696 else if (anObject instanceof CharSequence) 1697 { 1698 CharSequence sequence = (CharSequence)anObject; 1699 int n = count; 1700 if (sequence.length() == count) 1701 { 1702 char v1[] = value; 1703 int i = 0; 1704 while (n-- != 0) 1705 { 1706 if (v1[i] != sequence.charAt(i++)) 1707 { 1708 return false; 1709 } 1710 } 1711 return true; 1712 } 1713 } 1714 return false; 1715 } 1716 1717 /** 1718 * Returns a hash code for this AppendingStringBuffer. The hash code for a 1719 * <code>AppendingStringBuffer</code> object is computed as <blockquote> 1720 * 1721 * <pre> 1722 * s[0]*31ˆ(n-1) + s[1]*31ˆ(n-2) + ... + s[n-1] 1723 * </pre> 1724 * 1725 * </blockquote> using <code>int</code> arithmetic, where <code>s[i]</code> is the <i>i</i>th 1726 * character of the AppendingStringBuffer, <code>n</code> is the length of the 1727 * AppendingStringBuffer, and <code>^</code> indicates exponentiation. (The hash value of the 1728 * empty AppendingStringBuffer is zero.) 1729 * 1730 * @return a hash code value for this object. 1731 */ 1732 @Override 1733 public int hashCode() 1734 { 1735 int h = 0; 1736 if (h == 0) 1737 { 1738 int off = 0; 1739 char val[] = value; 1740 int len = count; 1741 1742 for (int i = 0; i < len; i++) 1743 { 1744 h = 31 * h + val[off++]; 1745 } 1746 } 1747 return h; 1748 } 1749 1750 /** 1751 * Clears the buffer contents, but leaves the allocated size intact 1752 */ 1753 public void clear() 1754 { 1755 count = 0; 1756 } 1757}