Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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(),&nbsp;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>'&#92;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,&nbsp;end)</pre></blockquote>
737      *
738      * behaves in exactly the same way as the invocation
739      *
740      * <blockquote><pre>
741      * sb.substring(begin,&nbsp;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}