KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > util > StringObject


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 /*
11  * @(#)StringBuffer.java 1.28 96/02/14
12  *
13  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
14  *
15  * Permission to use, copy, modify, and distribute this software
16  * and its documentation for NON-COMMERCIAL purposes and without
17  * fee is hereby granted provided that this copyright notice
18  * appears in all copies. Please refer to the file "copyright.html"
19  * for further important copyright and licensing information.
20  *
21  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
22  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
23  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
24  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
25  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
27  */

28
29 package org.mmbase.util;
30
31 /**
32  * This Class is a growable buffer for characters.
33  * It is mainly used to create Strings. The compiler uses it to implement the "+" operator.
34  * For example:
35  * <pre>
36  * "a" + 4 + "c"
37  * </pre>
38  * is compiled to:
39  * <pre>
40  * new StringBuffer().append("a").append(4).append("c").toString()
41  * </pre>
42  *
43  * Note that the method toString() does not create a copy of the internal buffer. Instead
44  * the buffer is marked as shared. Any further changes to the buffer will
45  * cause a copy to be made. <p>
46  *
47  * this is based on StringBuffer code, we have a seperate class since sun doesn't
48  * allow us to extend StringBuffer for some reason and we want methods like replace
49  * over the whole buffer.
50  *
51  * @license Sun license
52  * @see String
53  * @author Daniel Ockeloen
54  * @author Johannes Verelst (bugfix)
55  * @author Arthur van Hoff
56  * @version $Id: StringObject.java,v 1.11 2006/06/26 18:16:01 johannes Exp $
57  */

58
59 public final class StringObject {
60     /** The value is used for character storage. */
61     private char value[];
62
63     /** The count is the number of characters in the buffer. */
64     private int count;
65
66     /** A flag indicating whether the buffer is shared */
67     private boolean shared;
68
69     /**
70      * Constructs an empty String buffer.
71      */

72     public StringObject() {
73         this(16);
74     }
75
76     /**
77      * Constructs an empty String buffer with the specified initial length.
78      * @param length the initial length
79      */

80     public StringObject(int length) {
81         value = new char[length];
82         shared = false;
83     }
84
85     /**
86      * Constructs a String buffer with the specified initial value.
87      * @param str the initial value of the buffer
88      */

89     public StringObject(String JavaDoc str) {
90         this(str.length() + 16);
91         append(str);
92     }
93
94     /**
95      * Returns the length (character count) of the buffer.
96      */

97     public int length() {
98         return count;
99     }
100
101     /**
102      * Returns the current capacity of the String buffer. The capacity
103      * is the amount of storage available for newly inserted
104      * characters; beyond which an allocation will occur.
105      */

106     public int capacity() {
107         return value.length;
108     }
109
110     /**
111      * Copies the buffer value if it is shared.
112      */

113     private final void copyWhenShared() {
114         if (shared) {
115             char newValue[] = new char[value.length];
116             System.arraycopy(value, 0, newValue, 0, count);
117             value = newValue;
118             shared = false;
119         }
120     }
121
122     /**
123      * Ensures that the capacity of the buffer is at least equal to the
124      * specified minimum.
125      * @param minimumCapacity the minimum desired capacity
126      */

127     public synchronized void ensureCapacity(int minimumCapacity) {
128         int maxCapacity = value.length;
129
130         if (minimumCapacity > maxCapacity) {
131             int newCapacity = (maxCapacity + 1) * 2;
132             if (minimumCapacity > newCapacity) {
133                 newCapacity = minimumCapacity;
134             }
135
136             char newValue[] = new char[newCapacity];
137             System.arraycopy(value, 0, newValue, 0, count);
138             value = newValue;
139             shared = false;
140         }
141     }
142
143     /**
144      * Sets the length of the String. If the length is reduced, characters
145      * are lost. If the length is extended, the values of the new characters
146      * are set to 0.
147      * @param newLength the new length of the buffer
148      * @exception StringIndexOutOfBoundsException If the length is invalid.
149      */

150     public synchronized void setLength(int newLength) {
151         if (newLength < 0) {
152             throw new StringIndexOutOfBoundsException JavaDoc(newLength);
153         }
154         ensureCapacity(newLength);
155
156         if (count < newLength) {
157             copyWhenShared();
158             for (; count < newLength; count++) {
159                 value[count] = '\0';
160             }
161         }
162         count = newLength;
163     }
164
165     /**
166      * Returns the character at the specified index. An index ranges
167      * from 0..length()-1.
168      * @param index the index of the desired character
169      * @exception StringIndexOutOfBoundsException If the index is invalid.
170      */

171     public synchronized char charAt(int index) {
172         if ((index < 0) || (index >= count)) {
173             throw new StringIndexOutOfBoundsException JavaDoc(index);
174         }
175         return value[index];
176     }
177
178     /**
179      * Copies the characters of the specified substring (determined by
180      * srcBegin and srcEnd) into the character array, starting at the
181      * array's dstBegin location. Both srcBegin and srcEnd must be legal
182      * indexes into the buffer.
183      * @param srcBegin begin copy at this offset in the String
184      * @param srcEnd stop copying at this offset in the String
185      * @param dst the array to copy the data into
186      * @param dstBegin offset into dst
187      * @exception StringIndexOutOfBoundsException If there is an invalid index into the buffer.
188      */

189     public synchronized void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
190         if ((srcBegin < 0) || (srcBegin >= count)) {
191             throw new StringIndexOutOfBoundsException JavaDoc(srcBegin);
192         }
193         if ((srcEnd < 0) || (srcEnd > count)) {
194             throw new StringIndexOutOfBoundsException JavaDoc(srcEnd);
195         }
196         if (srcBegin < srcEnd) {
197             System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
198         }
199     }
200
201     /**
202      * Changes the character at the specified index to be ch.
203      * @param index the index of the character
204      * @param ch the new character
205      * @exception StringIndexOutOfBoundsException If the index is invalid.
206      */

207     public synchronized void setCharAt(int index, char ch) {
208         if ((index < 0) || (index >= count)) {
209             throw new StringIndexOutOfBoundsException JavaDoc(index);
210         }
211         copyWhenShared();
212         value[index] = ch;
213     }
214
215     /**
216      * Appends an object to the end of this buffer.
217      * @param obj the object to be appended
218      * @return the StringBuffer itself, NOT a new one.
219      */

220     public synchronized StringObject append(Object JavaDoc obj) {
221         return append(String.valueOf(obj));
222     }
223
224     /**
225      * Appends a String to the end of this buffer.
226      * @param str the String to be appended
227      * @return the StringBuffer itself, NOT a new one.
228      */

229     public synchronized StringObject append(String JavaDoc str) {
230         if (str == null) {
231             str = String.valueOf(str);
232         }
233
234         int len = str.length();
235         ensureCapacity(count + len);
236         copyWhenShared();
237         str.getChars(0, len, value, count);
238         count += len;
239         return this;
240     }
241
242     /**
243      * Appends an array of characters to the end of this buffer.
244      * @param str the characters to be appended
245      * @return the StringBuffer itself, NOT a new one.
246      */

247     public synchronized StringObject append(char str[]) {
248         int len = str.length;
249         ensureCapacity(count + len);
250         copyWhenShared();
251         System.arraycopy(str, 0, value, count, len);
252         count += len;
253         return this;
254     }
255
256     /**
257      * Appends a part of an array of characters to the end of this buffer.
258      * @param str the characters to be appended
259      * @param offset where to start
260      * @param len the number of characters to add
261      * @return the StringBuffer itself, NOT a new one.
262      */

263     public synchronized StringObject append(char str[], int offset, int len) {
264         ensureCapacity(count + len);
265         copyWhenShared();
266         System.arraycopy(str, offset, value, count, len);
267         count += len;
268         return this;
269     }
270
271     /**
272      * Appends a boolean to the end of this buffer.
273      * @param b the boolean to be appended
274      * @return the StringBuffer itself, NOT a new one.
275      */

276     public StringObject append(boolean b) {
277         return append(String.valueOf(b));
278     }
279
280     /**
281      * Appends a character to the end of this buffer.
282      * @param c the character to be appended
283      * @return the StringBuffer itself, NOT a new one.
284      */

285     public synchronized StringObject append(char c) {
286         ensureCapacity(count + 1);
287         copyWhenShared();
288         value[count++] = c;
289         return this;
290     }
291
292     /**
293      * Appends an integer to the end of this buffer.
294      * @param i the integer to be appended
295      * @return the StringBuffer itself, NOT a new one.
296      */

297     public StringObject append(int i) {
298         return append(String.valueOf(i));
299     }
300
301     /**
302      * Appends a long to the end of this buffer.
303      * @param l the long to be appended
304      * @return the StringBuffer itself, NOT a new one.
305      */

306     public StringObject append(long l) {
307         return append(String.valueOf(l));
308     }
309
310     /**
311      * Appends a float to the end of this buffer.
312      * @param f the float to be appended
313      * @return the StringBuffer itself, NOT a new one.
314      */

315     public StringObject append(float f) {
316         return append(String.valueOf(f));
317     }
318
319     /**
320      * Appends a double to the end of this buffer.
321      * @param d the double to be appended
322      * @return the StringBuffer itself, NOT a new one.
323      */

324     public StringObject append(double d) {
325         return append(String.valueOf(d));
326     }
327
328     /**
329      * Inserts an object into the String buffer.
330      * @param offset the offset at which to insert
331      * @param obj the object to insert
332      * @return the StringBuffer itself, NOT a new one.
333      * @exception StringIndexOutOfBoundsException If the offset is invalid.
334      */

335     public synchronized StringObject insert(int offset, Object JavaDoc obj) {
336         return insert(offset, String.valueOf(obj));
337     }
338
339     /**
340      * Inserts a String into the String buffer.
341      * @param offset the offset at which to insert
342      * @param str the String to insert
343      * @return the StringBuffer itself, NOT a new one.
344      * @exception StringIndexOutOfBoundsException If the offset is invalid.
345      */

346     public synchronized StringObject insert(int offset, String JavaDoc str) {
347         if ((offset < 0) || (offset > count)) {
348             throw new StringIndexOutOfBoundsException JavaDoc();
349         }
350         int len = str.length();
351         ensureCapacity(count + len);
352         copyWhenShared();
353         System.arraycopy(value, offset, value, offset + len, count - offset);
354         str.getChars(0, len, value, offset);
355         count += len;
356         return this;
357     }
358
359     /**
360      * Inserts an array of characters into the String buffer.
361      * @param offset the offset at which to insert
362      * @param str the characters to insert
363      * @return the StringBuffer itself, NOT a new one.
364      * @exception StringIndexOutOfBoundsException If the offset is invalid.
365      */

366     public synchronized StringObject insert(int offset, char str[]) {
367         if ((offset < 0) || (offset > count)) {
368             throw new StringIndexOutOfBoundsException JavaDoc();
369         }
370         int len = str.length;
371         ensureCapacity(count + len);
372         copyWhenShared();
373         System.arraycopy(value, offset, value, offset + len, count - offset);
374         System.arraycopy(str, 0, value, offset, len);
375         count += len;
376         return this;
377     }
378
379     /**
380      * Inserts a boolean into the String buffer.
381      * @param offset the offset at which to insert
382      * @param b the boolean to insert
383      * @return the StringBuffer itself, NOT a new one.
384      * @exception StringIndexOutOfBoundsException If the offset is invalid.
385      */

386     public StringObject insert(int offset, boolean b) {
387         return insert(offset, String.valueOf(b));
388     }
389
390     /**
391      * Inserts a character into the String buffer.
392      * @param offset the offset at which to insert
393      * @param c the character to insert
394      * @return the StringBuffer itself, NOT a new one.
395      * @exception StringIndexOutOfBoundsException If the offset invalid.
396      */

397     public synchronized StringObject insert(int offset, char c) {
398         ensureCapacity(count + 1);
399         copyWhenShared();
400         System.arraycopy(value, offset, value, offset + 1, count - offset);
401         value[offset] = c;
402         count += 1;
403         return this;
404     }
405
406     /**
407      * Inserts an integer into the String buffer.
408      * @param offset the offset at which to insert
409      * @param i the integer to insert
410      * @return the StringBuffer itself, NOT a new one.
411      * @exception StringIndexOutOfBoundsException If the offset is invalid.
412      */

413     public StringObject insert(int offset, int i) {
414         return insert(offset, String.valueOf(i));
415     }
416
417     /**
418      * Inserts a long into the String buffer.
419      * @param offset the offset at which to insert
420      * @param l the long to insert
421      * @return the StringBuffer itself, NOT a new one.
422      * @exception StringIndexOutOfBoundsException If the offset is invalid.
423      */

424     public StringObject insert(int offset, long l) {
425         return insert(offset, String.valueOf(l));
426     }
427
428     /**
429      * Inserts a float into the String buffer.
430      * @param offset the offset at which to insert
431      * @param f the float to insert
432      * @return the StringBuffer itself, NOT a new one.
433      * @exception StringIndexOutOfBoundsException If the offset is invalid.
434      */

435     public StringObject insert(int offset, float f) {
436         return insert(offset, String.valueOf(f));
437     }
438
439     /**
440      * Inserts a double into the String buffer.
441      * @param offset the offset at which to insert
442      * @param d the double to insert
443      * @return the StringBuffer itself, NOT a new one.
444      * @exception StringIndexOutOfBoundsException If the offset is invalid.
445      */

446     public StringObject insert(int offset, double d) {
447         return insert(offset, String.valueOf(d));
448     }
449
450     /**
451      * Reverse the order of the characters in the String buffer.
452      */

453     public synchronized StringObject reverse() {
454         copyWhenShared();
455         int n = count - 1;
456         for (int j = (n-1) >> 1; j >= 0; --j) {
457             char temp = value[j];
458             value[j] = value[n - j];
459             value[n - j] = temp;
460         }
461         return this;
462     }
463
464
465     /**
466      * Converts to a String representing the data in the buffer.
467      */

468     public String JavaDoc toString() {
469         return new String JavaDoc(value,0,count);
470     }
471
472     // The following two methods are needed by String to efficiently
473
// convert a StringBuffer into a String. They are not public.
474
// They shouldn't be called by anyone but String.
475
// XXX doesn't make sense... if this is package scope how can String call it?
476

477     final void setShared() {
478         shared = true;
479     }
480
481     final char[] getValue() {
482         return value;
483     }
484
485     /**
486      * delete part of the buffer
487      */

488     public synchronized StringObject delete(int offset,int len) {
489
490         if ((offset < 0) || (offset > count)) {
491             throw new StringIndexOutOfBoundsException JavaDoc();
492         }
493         copyWhenShared();
494         System.arraycopy(value, offset+len, value, offset, count-(offset+len));
495         count -= len;
496         return this;
497         }
498
499
500     /**
501      * replace
502      */

503     public synchronized StringObject replace(int offset,int len,String JavaDoc str) {
504         delete(offset,len);
505         insert(offset,str);
506         return this;
507     }
508
509
510     /**
511      * replace
512      */

513     public synchronized StringObject replaceFirst(String JavaDoc oldstr,String JavaDoc newstr) {
514         int pos=indexOf(oldstr,0);
515         if (pos!=-1) {
516             delete(pos,oldstr.length());
517             insert(pos,newstr);
518         }
519         return this;
520     }
521
522
523     /**
524      * replace
525      */

526     public synchronized StringObject replace(String JavaDoc oldstr,String JavaDoc newstr) {
527         int strlen = oldstr.length();
528         int pos=indexOf(oldstr,0,strlen);
529         while (pos!=-1) {
530             delete(pos,strlen);
531             insert(pos,newstr);
532             pos=indexOf(oldstr,pos+newstr.length(),strlen);
533         }
534         return this;
535     }
536
537
538     /**
539      * Does a replace/insert.
540      * Like make bold:bla into &lt:b&gt:bla&lt:/b&gt:
541      */

542     public synchronized StringObject replace(String JavaDoc oldstart,String JavaDoc oldend,String JavaDoc newstart, String JavaDoc newend) {
543         int pos2;
544         int pos=indexOf(oldstart,0);
545
546         while (pos!=-1) {
547             delete(pos,oldstart.length());
548             insert(pos,newstart);
549             pos2=indexOf(oldend,pos+newstart.length());
550             if (pos2!=-1) {
551                 delete(pos2,oldend.length());
552                 insert(pos2,newend);
553             }
554             pos=indexOf(oldstart,pos2+newend.length());
555         }
556         return this;
557     }
558
559         /**
560         * inserts links
561         */

562     public synchronized StringObject insertLinks(String JavaDoc oldstart,String JavaDoc oldend,String JavaDoc newstart,String JavaDoc newend, String JavaDoc startend) {
563         int pos2;
564         int pos=indexOf(oldstart,0);
565         String JavaDoc link="";
566         while (pos!=-1) {
567             delete(pos,oldstart.length());
568             insert(pos,newstart);
569             pos2=indexOf(oldend,pos+newstart.length());
570             if (pos2!=-1) {
571                 link=new String JavaDoc(value,pos+newstart.length(),pos2-(pos+newstart.length()));
572                 delete(pos2,oldend.length());
573                 insert(pos2,newend+link+startend);
574             }
575             pos=indexOf(oldstart,pos2+newend.length());
576         }
577         return this;
578     }
579
580     public int indexOf(String JavaDoc str) {
581         return indexOf(str,0);
582     }
583
584     public int indexOf(String JavaDoc str, int fromIndex) {
585        return indexOf(str, fromIndex, str.length());
586     }
587
588     private int indexOf(String JavaDoc str, int fromIndex, int strlen) {
589         char v1[] = value;
590         char v2[] = str.toCharArray();
591         int max = (count - strlen);
592       test:
593         for (int i = ((fromIndex < 0) ? 0 : fromIndex); i <= max ; i++) {
594             int n = strlen;
595             int j = i;
596             int k = 0;
597             while (n-- != 0) {
598                 if (v1[j++] != v2[k++]) {
599                     continue test;
600                 }
601             }
602             return i;
603         }
604         return -1;
605     }
606     
607
608     /**
609      */

610     public byte[] getBytes() {
611         return toString().getBytes();
612     }
613 }
614
Popular Tags