KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sosnoski > util > CharBuffer


1 /*
2  * Copyright (c) 2000-2001 Sosnoski Software Solutions, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */

22
23 package com.sosnoski.util;
24
25 import com.sosnoski.util.array.CharArray;
26
27 /**
28  * Growable <code>char</code> array with added <code>StringBuffer</code>-like
29  * functionality. This implementation differs from <code>StringBuffer</code> in
30  * that it is unsynchronized so as to provide the best possible performance for
31  * typical usage scenarios. Explicit synchronization must be implemented by a
32  * wrapper class or directly by the application in cases where instances are
33  * modified in a multithreaded environment. See the base classes for other
34  * details of the implementation.<p>
35  *
36  * This class defines a number of convenience methods for working with
37  * character data (including simple arrays and <code>String</code>s). Besides
38  * allowing character data to be appended/inserted/replaced in the growable
39  * array, other methods support comparisons between the several forms of
40  * character sequences and calculations of hash codes independent of the form
41  * of the sequence.
42  *
43  * @author Dennis M. Sosnoski
44  * @version 1.0
45  */

46
47 public class CharBuffer extends CharArray
48 {
49     /** Hash value multiplier to scramble bits in accumulation. */
50     protected static final int KEY_MULTIPLIER = 517;
51
52     /**
53      * Constructor with full specification.
54      *
55      * @param size number of <code>char</code> values initially allowed in array
56      * @param growth maximum size increment for growing array
57      */

58     
59     public CharBuffer(int size, int growth) {
60         super(size, growth);
61     }
62
63     /**
64      * Constructor with initial size specified.
65      *
66      * @param size number of <code>char</code> values initially allowed in array
67      */

68     
69     public CharBuffer(int size) {
70         super(size);
71     }
72
73     /**
74      * Default constructor.
75      */

76     
77     public CharBuffer() {
78         this(DEFAULT_SIZE);
79     }
80
81     /**
82      * Constructor from <code>String</code>.
83      */

84     
85     public CharBuffer(String JavaDoc base) {
86         this(base.length());
87         append(base);
88     }
89
90     /**
91      * Constructor from <code>char[]</code>.
92      */

93     
94     public CharBuffer(char[] base) {
95         this(base.length);
96         append(base);
97     }
98
99     /**
100      * Copy (clone) constructor.
101      *
102      * @param base instance being copied
103      */

104     
105     public CharBuffer(CharArray base) {
106         super(base);
107     }
108
109     /**
110      * Appends the characters from a <code>String</code> to the current contents
111      * of the array.
112      *
113      * @param text <code>String</code> of characters to be appended
114      * @return index number of first character appended
115      */

116     
117     public int append(String JavaDoc text) {
118         
119         // grow array if necessary
120
int length = text.length();
121         ensureCapacity(m_countPresent + length);
122         
123         // append text after existing content
124
int start = m_countPresent;
125         for (int i = 0; i < length; i++) {
126             m_baseArray[m_countPresent++] = text.charAt(i);
127         }
128         return start;
129     }
130
131     /**
132      * Appends the characters from an array range to the current contents
133      * of the array.
134      *
135      * @param text array containing characters to be appended
136      * @param offset starting offset in array
137      * @param length length of character range in array
138      * @return index number of first character appended
139      */

140     
141     public int append(char[] text, int offset, int length) {
142         
143         // grow array if necessary
144
ensureCapacity(m_countPresent + length);
145         
146         // append text after existing content
147
int start = m_countPresent;
148         System.arraycopy(text, offset, m_baseArray, m_countPresent, length);
149         m_countPresent += length;
150         return start;
151     }
152
153     /**
154      * Appends all the characters from an array to the current contents
155      * of the array.
156      *
157      * @param text array containing characters to be appended
158      * @return index number of first character appended
159      */

160     
161     public int append(char[] text) {
162         return append(text, 0, text.length);
163     }
164
165     /**
166      * Appends all the characters from another growable array to the current
167      * contents of the array.
168      *
169      * @param text growable array containing characters to be appended
170      * @return index number of first character appended
171      */

172     
173     public int append(CharArray text) {
174         return append((char[])getArray(text), 0, text.size());
175     }
176
177     /**
178      * Adjust the characters in the array to make room for an insertion or
179      * replacement. Depending on the relative sizes of the range being
180      * replaced and the range being inserted, this may move characters past
181      * the start of the replacement range up or down in the array.
182      *
183      * @param from index number of first character to be replaced
184      * @param to index number past last character to be replaced
185      * @param length length of character range being inserted
186      */

187     
188     protected void adjust(int from, int to, int length) {
189         if (from >= 0 && to < m_countPresent && from <= to) {
190             int change = from + length - to;
191             if (change > 0) {
192                 ensureCapacity(m_countPresent+change);
193             }
194             if (to < m_countPresent){
195                 System.arraycopy(m_baseArray, to, m_baseArray, to + change,
196                     m_countPresent - to);
197                 m_countPresent += change;
198             }
199         } else {
200             throw new ArrayIndexOutOfBoundsException JavaDoc("Invalid remove range");
201         }
202     }
203
204     /**
205      * Replace a character range in the array with the characters from a
206      * <code>String</code>.
207      *
208      * @param from index number of first character to be replaced
209      * @param to index number past last character to be replaced
210      * @param text replacement text
211      */

212     
213     public void replace(int from, int to, String JavaDoc text) {
214         adjust(from, to, text.length());
215         text.getChars(0, text.length(), m_baseArray, from);
216     }
217
218     /**
219      * Replace a character range in the array with the characters from a
220      * <code>char[]</code>.
221      *
222      * @param from index number of first character to be replaced
223      * @param to index number past last character to be replaced
224      * @param text replacement text
225      */

226     
227     public void replace(int from, int to, char[] text) {
228         adjust(from, to, text.length);
229         System.arraycopy(text, 0, m_baseArray, from, text.length);
230     }
231
232     /**
233      * Insert the characters from a <code>String</code> into the array.
234      *
235      * @param offset insert position offset in array
236      * @param text insertion text
237      */

238     
239     public void insert(int offset, String JavaDoc text) {
240         adjust(offset, offset, text.length());
241         text.getChars(0, text.length(), m_baseArray, offset);
242     }
243
244     /**
245      * Insert the characters from a <code>char[]</code> into the array.
246      *
247      * @param offset insert position offset in array
248      * @param text insertion text
249      */

250     
251     public void insert(int offset, char[] text) {
252         adjust(offset, offset, text.length);
253         System.arraycopy(text, 0, m_baseArray, offset, text.length);
254     }
255
256     /**
257      * Compare the character sequence in the array with a <code>String</code>.
258      *
259      * @param comp <code>String</code> value to be compared
260      * @return <code>true</code> if the character sequences are identical,
261      * <code>false</code> if they're different
262      */

263     
264     public boolean equals(String JavaDoc comp) {
265         
266         // first check for lengths the same
267
if (comp != null && m_countPresent == comp.length()) {
268                 
269             // match character by character for full compare
270
for (int index = 0; index < m_countPresent; index++) {
271                 if (m_baseArray[index] != comp.charAt(index)) {
272                     return false;
273                 }
274             }
275             
276             // return with all characters matched
277
return true;
278         }
279         
280         // fail if matching not done
281
return false;
282     }
283
284     /**
285      * Compare the character sequence in the array with the characters in a
286      * simple array range.
287      *
288      * @param comp array of characters to be compared
289      * @param offset starting offset in array
290      * @param length length of character range in array
291      * @return <code>true</code> if the character sequences are identical,
292      * <code>false</code> if they're different
293      */

294     
295     public boolean equals(char[] comp, int offset, int length) {
296         
297         // first check for lengths the same
298
if (comp != null && m_countPresent == length) {
299                 
300             // match character by character for full compare
301
for (int index = 0; index < m_countPresent; index++) {
302                 if (m_baseArray[index] != comp[index+offset]) {
303                     return false;
304                 }
305             }
306             
307             // return with all characters matched
308
return true;
309         }
310         
311         // fail if matching not done
312
return false;
313     }
314
315     /**
316      * Compare the character sequence in the array with that in a simple
317      * array.
318      *
319      * @param comp array of characters to be compared
320      * @return <code>true</code> if the character sequences are identical,
321      * <code>false</code> if they're different
322      */

323     
324     public boolean equals(char[] comp) {
325         return equals(comp, 0, comp.length);
326     }
327
328     /**
329      * Compare the character sequence in the array with the sequence in
330      * another growable array.
331      *
332      * @param comp array of characters to be compared
333      * @return <code>true</code> if the character sequences are identical,
334      * <code>false</code> if they're different
335      */

336     
337     public boolean equals(CharArray comp) {
338         return equals((char[])getArray(comp), 0, comp.size());
339     }
340     
341     /**
342      * Compare the character sequences in a pair of arrays.
343      *
344      * @param a first character sequence array (non-<code>null</code>)
345      * @param b second character sequence array (may be <code>null</code>)
346      * @return <code>true</code> if the character sequences are identical,
347      * <code>false</code> if they're different
348      */

349     
350     public static boolean equals(char[] a, char[] b) {
351         
352         // make sure the lengths are the same
353
if (b != null && a.length == b.length) {
354                 
355             // match character by character for full compare
356
for (int i = 0; i < a.length; i++) {
357                 if (a[i] != b[i]) {
358                     return false;
359                 }
360             }
361             return true;
362             
363         } else {
364             return false;
365         }
366     }
367     
368     /**
369      * Compare the character sequences in a simple array and a
370      * <code>String</code>.
371      *
372      * @param a simple array character sequence (non-<code>null</code>)
373      * @param b <code>String</code> character sequence (may be
374      * <code>null</code>)
375      * @return <code>true</code> if the character sequences are identical,
376      * <code>false</code> if they're different
377      */

378     
379     public static boolean equals(char[] a, String JavaDoc b) {
380         
381         // make sure the lengths are the same
382
if (b != null && a.length == b.length()) {
383                 
384             // match character by character for full compare
385
for (int i = 0; i < a.length; i++) {
386                 if (a[i] != b.charAt(i)) {
387                     return false;
388                 }
389             }
390             return true;
391             
392         } else {
393             return false;
394         }
395     }
396
397     /**
398      * Compare the character sequence in the array with a <code>String</code>
399      * without regard to case.
400      *
401      * @param comp <code>String</code> value to be compared
402      * @return <code>true</code> if the character sequences are identical
403      * except perhaps for case, <code>false</code> if they're different
404      */

405     
406     public boolean equalsNoCase(String JavaDoc comp) {
407         
408         // first check for lengths the same
409
if (comp != null && m_countPresent == comp.length()) {
410             
411             // match character by character for full compare
412
int index = 0;
413             for (; index < m_countPresent; index++) {
414                 if (Character.toLowerCase(m_baseArray[index]) !=
415                     Character.toLowerCase(comp.charAt(index))) {
416                     return false;
417                 }
418             }
419             
420             // return with all characters matched
421
return true;
422         }
423         
424         // fail if matching not done
425
return false;
426     }
427
428     /**
429      * Compare the character sequence in the array with the characters in a
430      * simple array range without regard to case.
431      *
432      * @param comp array of characters to be compared
433      * @param offset starting offset in array
434      * @param length length of character range in array
435      * @return <code>true</code> if the character sequences are identical
436      * except perhaps for case, <code>false</code> if they're different
437      */

438     
439     public boolean equalsNoCase(char[] comp, int offset, int length) {
440         
441         // first check for lengths the same
442
if (comp != null && m_countPresent == length) {
443                 
444             // match character by character for full compare
445
for (int index = 0; index < m_countPresent; index++) {
446                 if (Character.toLowerCase(m_baseArray[index]) !=
447                     Character.toLowerCase(comp[index+offset])) {
448                     return false;
449                 }
450             }
451             
452             // return with all characters matched
453
return true;
454         }
455         
456         // fail if matching not done
457
return false;
458     }
459
460     /**
461      * Compare the character sequence in the array with that in a simple
462      * array without regard to case.
463      *
464      * @param comp array of characters to be compared
465      * @return <code>true</code> if the character sequences are identical
466      * except perhaps for case, <code>false</code> if they're different
467      */

468     
469     public boolean equalsNoCase(char[] comp) {
470         return equalsNoCase(comp, 0, comp.length);
471     }
472
473     /**
474      * Compare the character sequence in the array with the sequence in
475      * another growable array without regard to case.
476      *
477      * @param comp array of characters to be compared
478      * @return <code>true</code> if the character sequences are identical
479      * except perhaps for case, <code>false</code> if they're different
480      */

481     
482     public boolean equalsNoCase(CharArray comp) {
483         return equalsNoCase((char[])getArray(comp), 0, comp.size());
484     }
485     
486     /**
487      * Compare the character sequences in a pair of arrays without regard to
488      * case.
489      *
490      * @param a first character sequence array (non-<code>null</code>)
491      * @param b second character sequence array (may be <code>null</code>)
492      * @return <code>true</code> if the character sequences are identical
493      * except perhaps for case, <code>false</code> if they're different
494      */

495     
496     public static boolean equalsNoCase(char[] a, char[] b) {
497         
498         // make sure the lengths are the same
499
if (b != null && a.length == b.length) {
500                 
501             // match character by character for full compare
502
for (int i = 0; i < a.length; i++) {
503                 if (Character.toUpperCase(a[i]) !=
504                     Character.toUpperCase(b[i])) {
505                     return false;
506                 }
507             }
508             return true;
509             
510         } else {
511             return false;
512         }
513     }
514     
515     /**
516      * Compare the character sequences in a simple array and a
517      * <code>String</code> without regard to case.
518      *
519      * @param a simple array character sequence (non-<code>null</code>)
520      * @param b <code>String</code> character sequence (may be
521      * <code>null</code>)
522      * @return <code>true</code> if the character sequences are identical
523      * except perhaps for case, <code>false</code> if they're different
524      */

525     
526     public static boolean equalsNoCase(char[] a, String JavaDoc b) {
527         
528         // make sure the lengths are the same
529
if (b != null && a.length == b.length()) {
530                 
531             // match character by character for full compare
532
for (int i = 0; i < a.length; i++) {
533                 if (Character.toLowerCase(a[i]) !=
534                     Character.toLowerCase(b.charAt(i))) {
535                     return false;
536                 }
537             }
538             return true;
539             
540         } else {
541             return false;
542         }
543     }
544     
545     /**
546      * Compute the compatible hash code value for character sequence in a simple
547      * array.
548      *
549      * @param text text to be hashed
550      * @return compatible hash code value
551      */

552     
553     public static int hashCode(char[] text) {
554         int hash = 0;
555         for (int i = 0; i < text.length; i++) {
556             hash = (hash * KEY_MULTIPLIER) + text[i];
557         }
558         return hash;
559     }
560
561     /**
562      * Compute the compatible hash code value for character sequence in a
563      * <code>String</code>.
564      *
565      * @param text text to be hashed
566      * @return compatible hash code value
567      */

568     
569     public static int hashCode(String JavaDoc text) {
570         int hash = 0;
571         for (int i = 0; i < text.length(); i++) {
572             hash = (hash * KEY_MULTIPLIER) + text.charAt(i);
573         }
574         return hash;
575     }
576
577     /**
578      * Compute a compatible hash code value for this character sequence.
579      *
580      * @return compatible hash code value
581      */

582     
583     public int hashCode() {
584         int hash = 0;
585         for (int i = 0; i < size(); i++) {
586             hash = (hash * KEY_MULTIPLIER) + m_baseArray[i];
587         }
588         return hash;
589     }
590
591     /**
592      * Duplicates the object with the generic call.
593      *
594      * @return a copy of the object
595      */

596     
597     public Object JavaDoc clone() {
598         return new CharBuffer(this);
599     }
600
601     /**
602      * Construct a <code>String</code> from the character sequence present.
603      *
604      * @return copy of data as <code>String</code>
605      */

606     
607     public String JavaDoc toString() {
608         return new String JavaDoc(m_baseArray, 0, m_countPresent);
609     }
610
611     /**
612      * Construct a <code>String</code> from a portion of the character sequence
613      * present.
614      *
615      * @param offset start offset in array
616      * @param length number of characters to use
617      * @return copy of data as <code>String</code>
618      */

619     
620     public String JavaDoc toString(int offset, int length) {
621         if (offset + length <= m_countPresent) {
622             return new String JavaDoc(m_baseArray, offset, length);
623         } else {
624             throw new ArrayIndexOutOfBoundsException JavaDoc();
625         }
626     }
627 }
628
Popular Tags