Source code: jflight/tools/JfStringBuffer.java
1 /*
2 * This class is used whenever some special StringBuffer functions
3 * are used in JFlight that are hard to code using just jdk1.1
4 * functions
5 */
6
7 /*
8 * @(#)JfStringBuffer.java 1.70 01/12/03
9 *
10 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
11 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
12 */
13
14 package jflight.tools;
15
16 /**
17 * A string buffer implements a mutable sequence of characters.
18 * A string buffer is like a {@link String}, but can be modified. At any
19 * point in time it contains some particular sequence of characters, but
20 * the length and content of the sequence can be changed through certain
21 * method calls.
22 * <p>
23 * String buffers are safe for use by multiple threads. The methods
24 * are synchronized where necessary so that all the operations on any
25 * particular instance behave as if they occur in some serial order
26 * that is consistent with the order of the method calls made by each of
27 * the individual threads involved.
28 * <p>
29 * String buffers are used by the compiler to implement the binary
30 * string concatenation operator <code>+</code>. For example, the code:
31 * <p><blockquote><pre>
32 * x = "a" + 4 + "c"
33 * </pre></blockquote><p>
34 * is compiled to the equivalent of:
35 * <p><blockquote><pre>
36 * x = new JfStringBuffer().append("a").append(4).append("c")
37 * .toString()
38 * </pre></blockquote>
39 * which creates a new string buffer (initially empty), appends the string
40 * representation of each operand to the string buffer in turn, and then
41 * converts the contents of the string buffer to a string. Overall, this avoids
42 * creating many temporary strings.
43 * <p>
44 * The principal operations on a <code>JfStringBuffer</code> are the
45 * <code>append</code> and <code>insert</code> methods, which are
46 * overloaded so as to accept data of any type. Each effectively
47 * converts a given datum to a string and then appends or inserts the
48 * characters of that string to the string buffer. The
49 * <code>append</code> method always adds these characters at the end
50 * of the buffer; the <code>insert</code> method adds the characters at
51 * a specified point.
52 * <p>
53 * For example, if <code>z</code> refers to a string buffer object
54 * whose current contents are "<code>start</code>", then
55 * the method call <code>z.append("le")</code> would cause the string
56 * buffer to contain "<code>startle</code>", whereas
57 * <code>z.insert(4, "le")</code> would alter the string buffer to
58 * contain "<code>starlet</code>".
59 * <p>
60 * In general, if sb refers to an instance of a <code>JfStringBuffer</code>,
61 * then <code>sb.append(x)</code> has the same effect as
62 * <code>sb.insert(sb.length(), x)</code>.
63 * <p>
64 * Every string buffer has a capacity. As long as the length of the
65 * character sequence contained in the string buffer does not exceed
66 * the capacity, it is not necessary to allocate a new internal
67 * buffer array. If the internal buffer overflows, it is
68 * automatically made larger.
69 *
70 * @author Arthur van Hoff
71 * @version 1.70, 12/03/01
72 * @see java.io.ByteArrayOutputStream
73 * @see java.lang.String
74 * @since JDK1.0
75 */
76
77 public final class JfStringBuffer
78 // implements java.io.Serializable, java.lang.CharSequence
79 {
80 /**
81 * The value is used for character storage.
82 *
83 * @serial
84 */
85 private char value[];
86
87 /**
88 * The count is the number of characters in the buffer.
89 *
90 * @serial
91 */
92 private int count;
93
94 /**
95 * A flag indicating whether the buffer is shared
96 *
97 * @serial
98 */
99 private boolean shared;
100
101 /** use serialVersionUID from JDK 1.0.2 for interoperability */
102 static final long serialVersionUID = 3388685877147921107L;
103
104 /**
105 * Constructs a string buffer with no characters in it and an
106 * initial capacity of 16 characters.
107 */
108 public JfStringBuffer() {
109 this(16);
110 }
111
112 /**
113 * Constructs a string buffer with no characters in it and an
114 * initial capacity specified by the <code>length</code> argument.
115 *
116 * @param length the initial capacity.
117 * @exception NegativeArraySizeException if the <code>length</code>
118 * argument is less than <code>0</code>.
119 */
120 public JfStringBuffer(int length) {
121 value = new char[length];
122 shared = false;
123 }
124
125 /**
126 * Constructs a string buffer so that it represents the same
127 * sequence of characters as the string argument; in other
128 * words, the initial contents of the string buffer is a copy of the
129 * argument string. The initial capacity of the string buffer is
130 * <code>16</code> plus the length of the string argument.
131 *
132 * @param str the initial contents of the buffer.
133 */
134 public JfStringBuffer(String str) {
135 this(str.length() + 16);
136 append(str);
137 }
138
139 /**
140 * Returns the length (character count) of this string buffer.
141 *
142 * @return the length of the sequence of characters currently
143 * represented by this string buffer.
144 */
145 public synchronized int length() {
146 return count;
147 }
148
149 /**
150 * Returns the current capacity of the String buffer. The capacity
151 * is the amount of storage available for newly inserted
152 * characters; beyond which an allocation will occur.
153 *
154 * @return the current capacity of this string buffer.
155 */
156 public synchronized int capacity() {
157 return value.length;
158 }
159
160 /**
161 * Copies the buffer value. This is normally only called when shared
162 * is true. It should only be called from a synchronized method.
163 */
164 private final void copy() {
165 char newValue[] = new char[value.length];
166 System.arraycopy(value, 0, newValue, 0, count);
167 value = newValue;
168 shared = false;
169 }
170
171 /**
172 * Ensures that the capacity of the buffer is at least equal to the
173 * specified minimum.
174 * If the current capacity of this string buffer is less than the
175 * argument, then a new internal buffer is allocated with greater
176 * capacity. The new capacity is the larger of:
177 * <ul>
178 * <li>The <code>minimumCapacity</code> argument.
179 * <li>Twice the old capacity, plus <code>2</code>.
180 * </ul>
181 * If the <code>minimumCapacity</code> argument is nonpositive, this
182 * method takes no action and simply returns.
183 *
184 * @param minimumCapacity the minimum desired capacity.
185 */
186 public synchronized void ensureCapacity(int minimumCapacity) {
187 if (minimumCapacity > value.length) {
188 expandCapacity(minimumCapacity);
189 }
190 }
191
192 /**
193 * This implements the expansion semantics of ensureCapacity but is
194 * unsynchronized for use internally by methods which are already
195 * synchronized.
196 *
197 * @see java.lang.JfStringBuffer#ensureCapacity(int)
198 */
199 private void expandCapacity(int minimumCapacity) {
200 int newCapacity = (value.length + 1) * 2;
201 if (newCapacity < 0) {
202 newCapacity = Integer.MAX_VALUE;
203 } else if (minimumCapacity > newCapacity) {
204 newCapacity = minimumCapacity;
205 }
206
207 char newValue[] = new char[newCapacity];
208 System.arraycopy(value, 0, newValue, 0, count);
209 value = newValue;
210 shared = false;
211 }
212
213 /**
214 * Sets the length of this String buffer.
215 * This string buffer is altered to represent a new character sequence
216 * whose length is specified by the argument. For every nonnegative
217 * index <i>k</i> less than <code>newLength</code>, the character at
218 * index <i>k</i> in the new character sequence is the same as the
219 * character at index <i>k</i> in the old sequence if <i>k</i> is less
220 * than the length of the old character sequence; otherwise, it is the
221 * null character <code>'\u0000'</code>.
222 *
223 * In other words, if the <code>newLength</code> argument is less than
224 * the current length of the string buffer, the string buffer is
225 * truncated to contain exactly the number of characters given by the
226 * <code>newLength</code> argument.
227 * <p>
228 * If the <code>newLength</code> argument is greater than or equal
229 * to the current length, sufficient null characters
230 * (<code>'\u0000'</code>) are appended to the string buffer so that
231 * length becomes the <code>newLength</code> argument.
232 * <p>
233 * The <code>newLength</code> argument must be greater than or equal
234 * to <code>0</code>.
235 *
236 * @param newLength the new length of the buffer.
237 * @exception IndexOutOfBoundsException if the
238 * <code>newLength</code> argument is negative.
239 * @see java.lang.JfStringBuffer#length()
240 */
241 public synchronized void setLength(int newLength) {
242 if (newLength < 0) {
243 throw new StringIndexOutOfBoundsException(newLength);
244 }
245
246 if (newLength > value.length) {
247 expandCapacity(newLength);
248 }
249
250 if (count < newLength) {
251 if (shared) copy();
252 for (; count < newLength; count++) {
253 value[count] = '\0';
254 }
255 } else {
256 count = newLength;
257 if (shared) {
258 if (newLength > 0) {
259 copy();
260 } else {
261 // If newLength is zero, assume the JfStringBuffer is being
262 // stripped for reuse; Make new buffer of default size
263 value = new char[16];
264 shared = false;
265 }
266 }
267 }
268 }
269
270 /**
271 * The specified character of the sequence currently represented by
272 * the string buffer, as indicated by the <code>index</code> argument,
273 * is returned. The first character of a string buffer is at index
274 * <code>0</code>, the next at index <code>1</code>, and so on, for
275 * array indexing.
276 * <p>
277 * The index argument must be greater than or equal to
278 * <code>0</code>, and less than the length of this string buffer.
279 *
280 * @param index the index of the desired character.
281 * @return the character at the specified index of this string buffer.
282 * @exception IndexOutOfBoundsException if <code>index</code> is
283 * negative or greater than or equal to <code>length()</code>.
284 * @see java.lang.JfStringBuffer#length()
285 */
286 public synchronized char charAt(int index) {
287 if ((index < 0) || (index >= count)) {
288 throw new StringIndexOutOfBoundsException(index);
289 }
290 return value[index];
291 }
292
293 /**
294 * Characters are copied from this string buffer into the
295 * destination character array <code>dst</code>. The first character to
296 * be copied is at index <code>srcBegin</code>; the last character to
297 * be copied is at index <code>srcEnd-1</code>. The total number of
298 * characters to be copied is <code>srcEnd-srcBegin</code>. The
299 * characters are copied into the subarray of <code>dst</code> starting
300 * at index <code>dstBegin</code> and ending at index:
301 * <p><blockquote><pre>
302 * dstbegin + (srcEnd-srcBegin) - 1
303 * </pre></blockquote>
304 *
305 * @param srcBegin start copying at this offset in the string buffer.
306 * @param srcEnd stop copying at this offset in the string buffer.
307 * @param dst the array to copy the data into.
308 * @param dstBegin offset into <code>dst</code>.
309 * @exception NullPointerException if <code>dst</code> is
310 * <code>null</code>.
311 * @exception IndexOutOfBoundsException if any of the following is true:
312 * <ul>
313 * <li><code>srcBegin</code> is negative
314 * <li><code>dstBegin</code> is negative
315 * <li>the <code>srcBegin</code> argument is greater than
316 * the <code>srcEnd</code> argument.
317 * <li><code>srcEnd</code> is greater than
318 * <code>this.length()</code>, the current length of this
319 * string buffer.
320 * <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
321 * <code>dst.length</code>
322 * </ul>
323 */
324 public synchronized void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
325 if (srcBegin < 0) {
326 throw new StringIndexOutOfBoundsException(srcBegin);
327 }
328 if ((srcEnd < 0) || (srcEnd > count)) {
329 throw new StringIndexOutOfBoundsException(srcEnd);
330 }
331 if (srcBegin > srcEnd) {
332 throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
333 }
334 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
335 }
336
337 /**
338 * The character at the specified index of this string buffer is set
339 * to <code>ch</code>. The string buffer is altered to represent a new
340 * character sequence that is identical to the old character sequence,
341 * except that it contains the character <code>ch</code> at position
342 * <code>index</code>.
343 * <p>
344 * The offset argument must be greater than or equal to
345 * <code>0</code>, and less than the length of this string buffer.
346 *
347 * @param index the index of the character to modify.
348 * @param ch the new character.
349 * @exception IndexOutOfBoundsException if <code>index</code> is
350 * negative or greater than or equal to <code>length()</code>.
351 * @see java.lang.JfStringBuffer#length()
352 */
353 public synchronized void setCharAt(int index, char ch) {
354 if ((index < 0) || (index >= count)) {
355 throw new StringIndexOutOfBoundsException(index);
356 }
357 if (shared) copy();
358 value[index] = ch;
359 }
360
361 /**
362 * Appends the string representation of the <code>Object</code>
363 * argument to this string buffer.
364 * <p>
365 * The argument is converted to a string as if by the method
366 * <code>String.valueOf</code>, and the characters of that
367 * string are then appended to this string buffer.
368 *
369 * @param obj an <code>Object</code>.
370 * @return a reference to this <code>JfStringBuffer</code> object.
371 * @see java.lang.String#valueOf(java.lang.Object)
372 * @see java.lang.JfStringBuffer#append(java.lang.String)
373 */
374 public synchronized JfStringBuffer append(Object obj) {
375 return append(String.valueOf(obj));
376 }
377
378 /**
379 * Appends the string to this string buffer.
380 * <p>
381 * The characters of the <code>String</code> argument are appended, in
382 * order, to the contents of this string buffer, increasing the
383 * length of this string buffer by the length of the argument.
384 * If <code>str</code> is <code>null</code>, then the four characters
385 * <code>"null"</code> are appended to this string buffer.
386 * <p>
387 * Let <i>n</i> be the length of the old character sequence, the one
388 * contained in the string buffer just prior to execution of the
389 * <code>append</code> method. Then the character at index <i>k</i> in
390 * the new character sequence is equal to the character at index <i>k</i>
391 * in the old character sequence, if <i>k</i> is less than <i>n</i>;
392 * otherwise, it is equal to the character at index <i>k-n</i> in the
393 * argument <code>str</code>.
394 *
395 * @param str a string.
396 * @return a reference to this <code>JfStringBuffer</code>.
397 */
398 public synchronized JfStringBuffer append(String str) {
399 if (str == null) {
400 str = String.valueOf(str);
401 }
402
403 int len = str.length();
404 int newcount = count + len;
405 if (newcount > value.length)
406 expandCapacity(newcount);
407 str.getChars(0, len, value, count);
408 count = newcount;
409 return this;
410 }
411
412 /**
413 * Appends the specified <tt>JfStringBuffer</tt> to this
414 * <tt>JfStringBuffer</tt>.
415 * <p>
416 * The characters of the <tt>JfStringBuffer</tt> argument are appended,
417 * in order, to the contents of this <tt>JfStringBuffer</tt>, increasing the
418 * length of this <tt>JfStringBuffer</tt> by the length of the argument.
419 * If <tt>sb</tt> is <tt>null</tt>, then the four characters
420 * <tt>"null"</tt> are appended to this <tt>JfStringBuffer</tt>.
421 * <p>
422 * Let <i>n</i> be the length of the old character sequence, the one
423 * contained in the <tt>JfStringBuffer</tt> just prior to execution of the
424 * <tt>append</tt> method. Then the character at index <i>k</i> in
425 * the new character sequence is equal to the character at index <i>k</i>
426 * in the old character sequence, if <i>k</i> is less than <i>n</i>;
427 * otherwise, it is equal to the character at index <i>k-n</i> in the
428 * argument <code>sb</code>.
429 * <p>
430 * The method <tt>ensureCapacity</tt> is first called on this
431 * <tt>JfStringBuffer</tt> with the new buffer length as its argument.
432 * (This ensures that the storage of this <tt>JfStringBuffer</tt> is
433 * adequate to contain the additional characters being appended.)
434 *
435 * @param sb the <tt>JfStringBuffer</tt> to append.
436 * @return a reference to this <tt>JfStringBuffer</tt>.
437 * @since 1.4
438 */
439 public synchronized JfStringBuffer append(JfStringBuffer sb) {
440 if (sb == null) {
441 sb = NULL;
442 }
443
444 int len = sb.length();
445 int newcount = count + len;
446 if (newcount > value.length)
447 expandCapacity(newcount);
448 sb.getChars(0, len, value, count);
449 count = newcount;
450 return this;
451 }
452
453 private static final JfStringBuffer NULL = new JfStringBuffer("null");
454
455 /**
456 * Appends the string representation of the <code>char</code> array
457 * argument to this string buffer.
458 * <p>
459 * The characters of the array argument are appended, in order, to
460 * the contents of this string buffer. The length of this string
461 * buffer increases by the length of the argument.
462 * <p>
463 * The overall effect is exactly as if the argument were converted to
464 * a string by the method {@link String#valueOf(char[])} and the
465 * characters of that string were then {@link #append(String) appended}
466 * to this <code>JfStringBuffer</code> object.
467 *
468 * @param str the characters to be appended.
469 * @return a reference to this <code>JfStringBuffer</code> object.
470 */
471 public synchronized JfStringBuffer append(char str[]) {
472 int len = str.length;
473 int newcount = count + len;
474 if (newcount > value.length)
475 expandCapacity(newcount);
476 System.arraycopy(str, 0, value, count, len);
477 count = newcount;
478 return this;
479 }
480
481 /**
482 * Appends the string representation of a subarray of the
483 * <code>char</code> array argument to this string buffer.
484 * <p>
485 * Characters of the character array <code>str</code>, starting at
486 * index <code>offset</code>, are appended, in order, to the contents
487 * of this string buffer. The length of this string buffer increases
488 * by the value of <code>len</code>.
489 * <p>
490 * The overall effect is exactly as if the arguments were converted to
491 * a string by the method {@link String#valueOf(char[],int,int)} and the
492 * characters of that string were then {@link #append(String) appended}
493 * to this <code>JfStringBuffer</code> object.
494 *
495 * @param str the characters to be appended.
496 * @param offset the index of the first character to append.
497 * @param len the number of characters to append.
498 * @return a reference to this <code>JfStringBuffer</code> object.
499 */
500 public synchronized JfStringBuffer append(char str[], int offset, int len) {
501 int newcount = count + len;
502 if (newcount > value.length)
503 expandCapacity(newcount);
504 System.arraycopy(str, offset, value, count, len);
505 count = newcount;
506 return this;
507 }
508
509 /**
510 * Appends the string representation of the <code>boolean</code>
511 * argument to the string buffer.
512 * <p>
513 * The argument is converted to a string as if by the method
514 * <code>String.valueOf</code>, and the characters of that
515 * string are then appended to this string buffer.
516 *
517 * @param b a <code>boolean</code>.
518 * @return a reference to this <code>JfStringBuffer</code>.
519 * @see java.lang.String#valueOf(boolean)
520 * @see java.lang.JfStringBuffer#append(java.lang.String)
521 */
522 public JfStringBuffer append(boolean b) {
523 return append(String.valueOf(b));
524 }
525
526 /**
527 * Appends the string representation of the <code>char</code>
528 * argument to this string buffer.
529 * <p>
530 * The argument is appended to the contents of this string buffer.
531 * The length of this string buffer increases by <code>1</code>.
532 * <p>
533 * The overall effect is exactly as if the argument were converted to
534 * a string by the method {@link String#valueOf(char)} and the character
535 * in that string were then {@link #append(String) appended} to this
536 * <code>JfStringBuffer</code> object.
537 *
538 * @param c a <code>char</code>.
539 * @return a reference to this <code>JfStringBuffer</code> object.
540 */
541 public synchronized JfStringBuffer append(char c) {
542 int newcount = count + 1;
543 if (newcount > value.length)
544 expandCapacity(newcount);
545 value[count++] = c;
546 return this;
547 }
548
549 /**
550 * Appends the string representation of the <code>int</code>
551 * argument to this string buffer.
552 * <p>
553 * The argument is converted to a string as if by the method
554 * <code>String.valueOf</code>, and the characters of that
555 * string are then appended to this string buffer.
556 *
557 * @param i an <code>int</code>.
558 * @return a reference to this <code>JfStringBuffer</code> object.
559 * @see java.lang.String#valueOf(int)
560 * @see java.lang.JfStringBuffer#append(java.lang.String)
561 */
562 public JfStringBuffer append(int i) {
563 return append(String.valueOf(i));
564 }
565
566 /**
567 * Appends the string representation of the <code>long</code>
568 * argument to this string buffer.
569 * <p>
570 * The argument is converted to a string as if by the method
571 * <code>String.valueOf</code>, and the characters of that
572 * string are then appended to this string buffer.
573 *
574 * @param l a <code>long</code>.
575 * @return a reference to this <code>JfStringBuffer</code> object.
576 * @see java.lang.String#valueOf(long)
577 * @see java.lang.JfStringBuffer#append(java.lang.String)
578 */
579 public JfStringBuffer append(long l) {
580 return append(String.valueOf(l));
581 }
582
583 /**
584 * Appends the string representation of the <code>float</code>
585 * argument to this string buffer.
586 * <p>
587 * The argument is converted to a string as if by the method
588 * <code>String.valueOf</code>, and the characters of that
589 * string are then appended to this string buffer.
590 *
591 * @param f a <code>float</code>.
592 * @return a reference to this <code>JfStringBuffer</code> object.
593 * @see java.lang.String#valueOf(float)
594 * @see java.lang.JfStringBuffer#append(java.lang.String)
595 */
596 public JfStringBuffer append(float f) {
597 return append(String.valueOf(f));
598 }
599
600 /**
601 * Appends the string representation of the <code>double</code>
602 * argument to this string buffer.
603 * <p>
604 * The argument is converted to a string as if by the method
605 * <code>String.valueOf</code>, and the characters of that
606 * string are then appended to this string buffer.
607 *
608 * @param d a <code>double</code>.
609 * @return a reference to this <code>JfStringBuffer</code> object.
610 * @see java.lang.String#valueOf(double)
611 * @see java.lang.JfStringBuffer#append(java.lang.String)
612 */
613 public JfStringBuffer append(double d) {
614 return append(String.valueOf(d));
615 }
616
617 /**
618 * Removes the characters in a substring of this <code>JfStringBuffer</code>.
619 * The substring begins at the specified <code>start</code> and extends to
620 * the character at index <code>end - 1</code> or to the end of the
621 * <code>JfStringBuffer</code> if no such character exists. If
622 * <code>start</code> is equal to <code>end</code>, no changes are made.
623 *
624 * @param start The beginning index, inclusive.
625 * @param end The ending index, exclusive.
626 * @return This string buffer.
627 * @exception StringIndexOutOfBoundsException if <code>start</code>
628 * is negative, greater than <code>length()</code>, or
629 * greater than <code>end</code>.
630 * @since 1.2
631 */
632 public synchronized JfStringBuffer delete(int start, int end) {
633 if (start < 0)
634 throw new StringIndexOutOfBoundsException(start);
635 if (end > count)
636 end = count;
637 if (start > end)
638 throw new StringIndexOutOfBoundsException();
639
640 int len = end - start;
641 if (len > 0) {
642 if (shared)
643 copy();
644 System.arraycopy(value, start+len, value, start, count-end);
645 count -= len;
646 }
647 return this;
648 }
649
650 /**
651 * Removes the character at the specified position in this
652 * <code>JfStringBuffer</code> (shortening the <code>JfStringBuffer</code>
653 * by one character).
654 *
655 * @param index Index of character to remove
656 * @return This string buffer.
657 * @exception StringIndexOutOfBoundsException if the <code>index</code>
658 * is negative or greater than or equal to
659 * <code>length()</code>.
660 * @since 1.2
661 */
662 public synchronized JfStringBuffer deleteCharAt(int index) {
663 if ((index < 0) || (index >= count))
664 throw new StringIndexOutOfBoundsException();
665 if (shared)
666 copy();
667 System.arraycopy(value, index+1, value, index, count-index-1);
668 count--;
669 return this;
670 }
671
672 /**
673 * Replaces the characters in a substring of this <code>JfStringBuffer</code>
674 * with characters in the specified <code>String</code>. The substring
675 * begins at the specified <code>start</code> and extends to the character
676 * at index <code>end - 1</code> or to the end of the
677 * <code>JfStringBuffer</code> if no such character exists. First the
678 * characters in the substring are removed and then the specified
679 * <code>String</code> is inserted at <code>start</code>. (The
680 * <code>JfStringBuffer</code> will be lengthened to accommodate the
681 * specified String if necessary.)
682 *
683 * @param start The beginning index, inclusive.
684 * @param end The ending index, exclusive.
685 * @param str String that will replace previous contents.
686 * @return This string buffer.
687 * @exception StringIndexOutOfBoundsException if <code>start</code>
688 * is negative, greater than <code>length()</code>, or
689 * greater than <code>end</code>.
690 * @since 1.2
691 */
692 public synchronized JfStringBuffer replace(int start, int end, String str) {
693 if (start < 0)
694 throw new StringIndexOutOfBoundsException(start);
695 if (end > count)
696 end = count;
697 if (start > end)
698 throw new StringIndexOutOfBoundsException();
699
700 int len = str.length();
701 int newCount = count + len - (end - start);
702 if (newCount > value.length)
703 expandCapacity(newCount);
704 else if (shared)
705 copy();
706
707 System.arraycopy(value, end, value, start + len, count - end);
708 str.getChars(0, len, value, start);
709 count = newCount;
710 return this;
711 }
712
713 /**
714 * Returns a new <code>String</code> that contains a subsequence of
715 * characters currently contained in this <code>JfStringBuffer</code>.The
716 * substring begins at the specified index and extends to the end of the
717 * <code>JfStringBuffer</code>.
718 *
719 * @param start The beginning index, inclusive.
720 * @return The new string.
721 * @exception StringIndexOutOfBoundsException if <code>start</code> is
722 * less than zero, or greater than the length of this
723 * <code>JfStringBuffer</code>.
724 * @since 1.2
725 */
726 public synchronized String substring(int start) {
727 return substring(start, count);
728 }
729
730 /**
731 * Returns a new character sequence that is a subsequence of this sequence.
732 *
733 * <p> An invocation of this method of the form
734 *
735 * <blockquote><pre>
736 * sb.subSequence(begin, end)</pre></blockquote>
737 *
738 * behaves in exactly the same way as the invocation
739 *
740 * <blockquote><pre>
741 * sb.substring(begin, end)</pre></blockquote>
742 *
743 * This method is provided so that the <tt>JfStringBuffer</tt> class can
744 * implement the {@link CharSequence} interface. </p>
745 *
746 * @param start the start index, inclusive.
747 * @param end the end index, exclusive.
748 * @return the specified subsequence.
749 *
750 * @throws IndexOutOfBoundsException
751 * if <tt>start</tt> or <tt>end</tt> are negative,
752 * if <tt>end</tt> is greater than <tt>length()</tt>,
753 * or if <tt>start</tt> is greater than <tt>end</tt>
754 *
755 * @since 1.4
756 * @spec JSR-51
757 */
758 /* public CharSequence subSequence(int start, int end) {
759 return this.substring(start, end);
760 }
761 */
762 /**
763 * Returns a new <code>String</code> that contains a subsequence of
764 * characters currently contained in this <code>JfStringBuffer</code>. The
765 * substring begins at the specified <code>start</code> and
766 * extends to the character at index <code>end - 1</code>. An
767 * exception is thrown if
768 *
769 * @param start The beginning index, inclusive.
770 * @param end The ending index, exclusive.
771 * @return The new string.
772 * @exception StringIndexOutOfBoundsException if <code>start</code>
773 * or <code>end</code> are negative or greater than
774 * <code>length()</code>, or <code>start</code> is
775 * greater than <code>end</code>.
776 * @since 1.2
777 */
778 public synchronized String substring(int start, int end) {
779 if (start < 0)
780 throw new StringIndexOutOfBoundsException(start);
781 if (end > count)
782 throw new StringIndexOutOfBoundsException(end);
783 if (start > end)
784 throw new StringIndexOutOfBoundsException(end - start);
785 return new String(value, start, end - start);
786 }
787
788 /**
789 * Inserts the string representation of a subarray of the <code>str</code>
790 * array argument into this string buffer. The subarray begins at the
791 * specified <code>offset</code> and extends <code>len</code> characters.
792 * The characters of the subarray are inserted into this string buffer at
793 * the position indicated by <code>index</code>. The length of this
794 * <code>JfStringBuffer</code> increases by <code>len</code> characters.
795 *
796 * @param index position at which to insert subarray.
797 * @param str A character array.
798 * @param offset the index of the first character in subarray to
799 * to be inserted.
800 * @param len the number of characters in the subarray to
801 * to be inserted.
802 * @return This string buffer.
803 * @exception StringIndexOutOfBoundsException if <code>index</code>
804 * is negative or greater than <code>length()</code>, or
805 * <code>offset</code> or <code>len</code> are negative, or
806 * <code>(offset+len)</code> is greater than
807 * <code>str.length</code>.
808 * @since 1.2
809 */
810 public synchronized JfStringBuffer insert(int index, char str[], int offset,
811 int len) {
812 if ((index < 0) || (index > count))
813 throw new StringIndexOutOfBoundsException();
814 if ((offset < 0) || (offset + len < 0) || (offset + len > str.length))
815 throw new StringIndexOutOfBoundsException(offset);
816 if (len < 0)
817 throw new StringIndexOutOfBoundsException(len);
818 int newCount = count + len;
819 if (newCount > value.length)
820 expandCapacity(newCount);
821 else if (shared)
822 copy();
823 System.arraycopy(value, index, value, index + len, count - index);
824 System.arraycopy(str, offset, value, index, len);
825 count = newCount;
826 return this;
827 }
828
829 /**
830 * Inserts the string representation of the <code>Object</code>
831 * argument into this string buffer.
832 * <p>
833 * The second argument is converted to a string as if by the method
834 * <code>String.valueOf</code>, and the characters of that
835 * string are then inserted into this string buffer at the indicated
836 * offset.
837 * <p>
838 * The offset argument must be greater than or equal to
839 * <code>0</code>, and less than or equal to the length of this
840 * string buffer.
841 *
842 * @param offset the offset.
843 * @param obj an <code>Object</code>.
844 * @return a reference to this <code>JfStringBuffer</code> object.
845 * @exception StringIndexOutOfBoundsException if the offset is invalid.
846 * @see java.lang.String#valueOf(java.lang.Object)
847 * @see java.lang.JfStringBuffer#insert(int, java.lang.String)
848 * @see java.lang.JfStringBuffer#length()
849 */
850 public synchronized JfStringBuffer insert(int offset, Object obj) {
851 return insert(offset, String.valueOf(obj));
852 }
853
854 /**
855 * Inserts the string into this string buffer.
856 * <p>
857 * The characters of the <code>String</code> argument are inserted, in
858 * order, into this string buffer at the indicated offset, moving up any
859 * characters originally above that position and increasing the length
860 * of this string buffer by the length of the argument. If
861 * <code>str</code> is <code>null</code>, then the four characters
862 * <code>"null"</code> are inserted into this string buffer.
863 * <p>
864 * The character at index <i>k</i> in the new character sequence is
865 * equal to:
866 * <ul>
867 * <li>the character at index <i>k</i> in the old character sequence, if
868 * <i>k</i> is less than <code>offset</code>
869 * <li>the character at index <i>k</i><code>-offset</code> in the
870 * argument <code>str</code>, if <i>k</i> is not less than
871 * <code>offset</code> but is less than <code>offset+str.length()</code>
872 * <li>the character at index <i>k</i><code>-str.length()</code> in the
873 * old character sequence, if <i>k</i> is not less than
874 * <code>offset+str.length()</code>
875 * </ul><p>
876 * The offset argument must be greater than or equal to
877 * <code>0</code>, and less than or equal to the length of this
878 * string buffer.
879 *
880 * @param offset the offset.
881 * @param str a string.
882 * @return a reference to this <code>JfStringBuffer</code> object.
883 * @exception StringIndexOutOfBoundsException if the offset is invalid.
884 * @see java.lang.JfStringBuffer#length()
885 */
886 public synchronized JfStringBuffer insert(int offset, String str) {
887 if ((offset < 0) || (offset > count)) {
888 throw new StringIndexOutOfBoundsException();
889 }
890
891 if (str == null) {
892 str = String.valueOf(str);
893 }
894 int len = str.length();
895 int newcount = count + len;
896 if (newcount > value.length)
897 expandCapacity(newcount);
898 else if (shared)
899 copy();
900 System.arraycopy(value, offset, value, offset + len, count - offset);
901 str.getChars(0, len, value, offset);
902 count = newcount;
903 return this;
904 }
905
906 /**
907 * Inserts the string representation of the <code>char</code> array
908 * argument into this string buffer.
909 * <p>
910 * The characters of the array argument are inserted into the
911 * contents of this string buffer at the position indicated by
912 * <code>offset</code>. The length of this string buffer increases by
913 * the length of the argument.
914 * <p>
915 * The overall effect is exactly as if the argument were converted to
916 * a string by the method {@link String#valueOf(char[])} and the
917 * characters of that string were then
918 * {@link #insert(int,String) inserted} into this
919 * <code>JfStringBuffer</code> object at the position indicated by
920 * <code>offset</code>.
921 *
922 * @param offset the offset.
923 * @param str a character array.
924 * @return a reference to this <code>JfStringBuffer</code> object.
925 * @exception StringIndexOutOfBoundsException if the offset is invalid.
926 */
927 public synchronized JfStringBuffer insert(int offset, char str[]) {
928 if ((offset < 0) || (offset > count)) {
929 throw new StringIndexOutOfBoundsException();
930 }
931 int len = str.length;
932 int newcount = count + len;
933 if (newcount > value.length)
934 expandCapacity(newcount);
935 else if (shared)
936 copy();
937 System.arraycopy(value, offset, value, offset + len, count - offset);
938 System.arraycopy(str, 0, value, offset, len);
939 count = newcount;
940 return this;
941 }
942
943 /**
944 * Inserts the string representation of the <code>boolean</code>
945 * argument into this string buffer.
946 * <p>
947 * The second argument is converted to a string as if by the method
948 * <code>String.valueOf</code>, and the characters of that
949 * string are then inserted into this string buffer at the indicated
950 * offset.
951 * <p>
952 * The offset argument must be greater than or equal to
953 * <code>0</code>, and less than or equal to the length of this
954 * string buffer.
955 *
956 * @param offset the offset.
957 * @param b a <code>boolean</code>.
958 * @return a reference to this <code>JfStringBuffer</code> object.
959 * @exception StringIndexOutOfBoundsException if the offset is invalid.
960 * @see java.lang.String#valueOf(boolean)
961 * @see java.lang.JfStringBuffer#insert(int, java.lang.String)
962 * @see java.lang.JfStringBuffer#length()
963 */
964 public JfStringBuffer insert(int offset, boolean b) {
965 return insert(offset, String.valueOf(b));
966 }
967
968 /**
969 * Inserts the string representation of the <code>char</code>
970 * argument into this string buffer.
971 * <p>
972 * The second argument is inserted into the contents of this string
973 * buffer at the position indicated by <code>offset</code>. The length
974 * of this string buffer increases by one.
975 * <p>
976 * The overall effect is exactly as if the argument were converted to
977 * a string by the method {@link String#valueOf(char)} and the character
978 * in that string were then {@link #insert(int, String) inserted} into
979 * this <code>JfStringBuffer</code> object at the position indicated by
980 * <code>offset</code>.
981 * <p>
982 * The offset argument must be greater than or equal to
983 * <code>0</code>, and less than or equal to the length of this
984 * string buffer.
985 *
986 * @param offset the offset.
987 * @param c a <code>char</code>.
988 * @return a reference to this <code>JfStringBuffer</code> object.
989 * @exception IndexOutOfBoundsException if the offset is invalid.
990 * @see java.lang.JfStringBuffer#length()
991 */
992 public synchronized JfStringBuffer insert(int offset, char c) {
993 int newcount = count + 1;
994 if (newcount > value.length)
995 expandCapacity(newcount);
996 else if (shared)
997 copy();
998 System.arraycopy(value, offset, value, offset + 1, count - offset);
999 value[offset] = c;
1000 count = newcount;
1001 return this;
1002 }
1003
1004 /**
1005 * Inserts the string representation of the second <code>int</code>
1006 * argument into this string buffer.
1007 * <p>
1008 * The second argument is converted to a string as if by the method
1009 * <code>String.valueOf</code>, and the characters of that
1010 * string are then inserted into this string buffer at the indicated
1011 * offset.
1012 * <p>
1013 * The offset argument must be greater than or equal to
1014 * <code>0</code>, and less than or equal to the length of this
1015 * string buffer.
1016 *
1017 * @param offset the offset.
1018 * @param i an <code>int</code>.
1019 * @return a reference to this <code>JfStringBuffer</code> object.
1020 * @exception StringIndexOutOfBoundsException if the offset is invalid.
1021 * @see java.lang.String#valueOf(int)
1022 * @see java.lang.JfStringBuffer#insert(int, java.lang.String)
1023 * @see java.lang.JfStringBuffer#length()
1024 */
1025 public JfStringBuffer insert(int offset, int i) {
1026 return insert(offset, String.valueOf(i));
1027 }
1028
1029 /**
1030 * Inserts the string representation of the <code>long</code>
1031 * argument into this string buffer.
1032 * <p>
1033 * The second argument is converted to a string as if by the method
1034 * <code>String.valueOf</code>, and the characters of that
1035 * string are then inserted into this string buffer at the position
1036 * indicated by <code>offset</code>.
1037 * <p>
1038 * The offset argument must be greater than or equal to
1039 * <code>0</code>, and less than or equal to the length of this
1040 * string buffer.
1041 *
1042 * @param offset the offset.
1043 * @param l a <code>long</code>.
1044 * @return a reference to this <code>JfStringBuffer</code> object.
1045 * @exception StringIndexOutOfBoundsException if the offset is invalid.
1046 * @see java.lang.String#valueOf(long)
1047 * @see java.lang.JfStringBuffer#insert(int, java.lang.String)
1048 * @see java.lang.JfStringBuffer#length()
1049 */
1050 public JfStringBuffer insert(int offset, long l) {
1051 return insert(offset, String.valueOf(l));
1052 }
1053
1054 /**
1055 * Inserts the string representation of the <code>float</code>
1056 * argument into this string buffer.
1057 * <p>
1058 * The second argument is converted to a string as if by the method
1059 * <code>String.valueOf</code>, and the characters of that
1060 * string are then inserted into this string buffer at the indicated
1061 * offset.
1062 * <p>
1063 * The offset argument must be greater than or equal to
1064 * <code>0</code>, and less than or equal to the length of this
1065 * string buffer.
1066 *
1067 * @param offset the offset.
1068 * @param f a <code>float</code>.
1069 * @return a reference to this <code>JfStringBuffer</code> object.
1070 * @exception StringIndexOutOfBoundsException if the offset is invalid.
1071 * @see java.lang.String#valueOf(float)
1072 * @see java.lang.JfStringBuffer#insert(int, java.lang.String)
1073 * @see java.lang.JfStringBuffer#length()
1074 */
1075 public JfStringBuffer insert(int offset, float f) {
1076 return insert(offset, String.valueOf(f));
1077 }
1078
1079 /**
1080 * Inserts the string representation of the <code>double</code>
1081 * argument into this string buffer.
1082 * <p>
1083 * The second argument is converted to a string as if by the method
1084 * <code>String.valueOf</code>, and the characters of that
1085 * string are then inserted into this string buffer at the indicated
1086 * offset.
1087 * <p>
1088 * The offset argument must be greater than or equal to
1089 * <code>0</code>, and less than or equal to the length of this
1090 * string buffer.
1091 *
1092 * @param offset the offset.
1093 * @param d a <code>double</code>.
1094 * @return a reference to this <code>JfStringBuffer</code> object.
1095 * @exception StringIndexOutOfBoundsException if the offset is invalid.
1096 * @see java.lang.String#valueOf(double)
1097 * @see java.lang.JfStringBuffer#insert(int, java.lang.String)
1098 * @see java.lang.JfStringBuffer#length()
1099 */
1100 public JfStringBuffer insert(int offset, double d) {
1101 return insert(offset, String.valueOf(d));
1102 }
1103
1104 /**
1105 * Returns the index within this string of the first occurrence of the
1106 * specified substring. The integer returned is the smallest value
1107 * <i>k</i> such that:
1108 * <blockquote><pre>
1109 * this.toString().startsWith(str, <i>k</i>)
1110 * </pre></blockquote>
1111 * is <code>true</code>.
1112 *
1113 * @param str any string.
1114 * @return if the string argument occurs as a substring within this
1115 * object, then the index of the first character of the first
1116 * such substring is returned; if it does not occur as a
1117 * substring, <code>-1</code> is returned.
1118 * @exception java.lang.NullPointerException if <code>str</code> is
1119 * <code>null</code>.
1120 * @since 1.4
1121 */
1122 public int indexOf(String str) {
1123 return indexOf(str, 0);
1124 }
1125
1126 /**
1127 * Returns the index within this string of the first occurrence of the
1128 * specified substring, starting at the specified index. The integer
1129 * returned is the smallest value <tt>k</tt> for which:
1130 * <blockquote><pre>
1131 * k >= Math.min(fromIndex, str.length()) &&
1132 * this.toString().startsWith(str, k)
1133 * </pre></blockquote>
1134 * If no such value of <i>k</i> exists, then -1 is returned.
1135 *
1136 * @param str the substring for which to search.
1137 * @param fromIndex the index from which to start the search.
1138 * @return the index within this string of the first occurrence of the
1139 * specified substring, starting at the specified index.
1140 * @exception java.lang.NullPointerException if <code>str</code> is
1141 * <code>null</code>.
1142 * @since 1.4
1143 */
1144 public synchronized int indexOf(String str, int fromIndex) {
1145/* not used currently
1146 return String.indexOf(value, 0, count,
1147 str.toCharArray(), 0, str.length(), fromIndex);
1148*/
1149 return -1;
1150 }
1151
1152 /**
1153 * Returns the index within this string of the rightmost occurrence
1154 * of the specified substring. The rightmost empty string "" is
1155 * considered to occur at the index value <code>this.length()</code>.
1156 * The returned index is the largest value <i>k</i> such that
1157 * <blockquote><pre>
1158 * this.toString().startsWith(str, k)
1159 * </pre></blockquote>
1160 * is true.
1161 *
1162 * @param str the substring to search for.
1163 * @return if the string argument occurs one or more times as a substring
1164 * within this object, then the index of the first character of
1165 * the last such substring is returned. If it does not occur as
1166 * a substring, <code>-1</code> is returned.
1167 * @exception java.lang.NullPointerException if <code>str</code> is
1168 * <code>null</code>.
1169 * @since 1.4
1170 */
1171 public synchronized int lastIndexOf(String str) {
1172 return lastIndexOf(str, count);
1173 }
1174
1175 /**
1176 * Returns the index within this string of the last occurrence of the
1177 * specified substring. The integer returned is the largest value <i>k</i>
1178 * such that:
1179 * <blockquote><pre>
1180 * k <= Math.min(fromIndex, str.length()) &&
1181 * this.toString().startsWith(str, k)
1182 * </pre></blockquote>
1183 * If no such value of <i>k</i> exists, then -1 is returned.
1184 *
1185 * @param str the substring to search for.
1186 * @param fromIndex the index to start the search from.
1187 * @return the index within this string of the last occurrence of the
1188 * specified substring.
1189 * @exception java.lang.NullPointerException if <code>str</code> is
1190 * <code>null</code>.
1191 * @since 1.4
1192 */
1193 public synchronized int lastIndexOf(String str, int fromIndex) {
1194/* not used currently
1195 return String.lastIndexOf(value, 0, count,
1196 str.toCharArray(), 0, str.length(), fromIndex);
1197*/
1198 return -1;
1199 }
1200
1201 /**
1202 * The character sequence contained in this string buffer is
1203 * replaced by the reverse of the sequence.
1204 * <p>
1205 * Let <i>n</i> be the length of the old character sequence, the one
1206 * contained in the string buffer just prior to execution of the
1207 * <code>reverse</code> method. Then the character at index <i>k</i> in
1208 * the new character sequence is equal to the character at index
1209 * <i>n-k-1</i> in the old character sequence.
1210 *
1211 * @return a reference to this <code>JfStringBuffer</code> object.
1212 * @since JDK1.0.2
1213 */
1214 public synchronized JfStringBuffer reverse() {
1215 if (shared) copy();
1216 int n = count - 1;
1217 for (int j = (n-1) >> 1; j >= 0; --j) {
1218 char temp = value[j];
1219 value[j] = value[n - j];
1220 value[n - j] = temp;
1221 }
1222 return this;
1223 }
1224
1225 /**
1226 * Converts to a string representing the data in this string buffer.
1227 * A new <code>String</code> object is allocated and initialized to
1228 * contain the character sequence currently represented by this
1229 * string buffer. This <code>String</code> is then returned. Subsequent
1230 * changes to the string buffer do not affect the contents of the
1231 * <code>String</code>.
1232 * <p>
1233 * Implementation advice: This method can be coded so as to create a new
1234 * <code>String</code> object without allocating new memory to hold a
1235 * copy of the character sequence. Instead, the string can share the
1236 * memory used by the string buffer. Any subsequent operation that alters
1237 * the content or capacity of the string buffer must then make a copy of
1238 * the internal buffer at that time. This strategy is effective for
1239 * reducing the amount of memory allocated by a string concatenation
1240 * operation when it is implemented using a string buffer.
1241 *
1242 * @return a string representation of the string buffer.
1243 */
1244 public String toString() {
1245 return new String(value);
1246 }
1247
1248 //
1249 // The following two methods are needed by String to efficiently
1250 // convert a JfStringBuffer into a String. They are not public.
1251 // They shouldn't be called by anyone but String.
1252 final void setShared() { shared = true; }
1253 final char[] getValue() { return value; }
1254
1255 /**
1256 * readObject is called to restore the state of the JfStringBuffer from
1257 * a stream.
1258 */
1259 private synchronized void readObject(java.io.ObjectInputStream s)
1260 throws java.io.IOException, ClassNotFoundException {
1261 s.defaultReadObject();
1262 value = (char[]) value.clone();
1263 shared = false;
1264 }
1265}