KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > text > CharArray


1 /*
2  * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
3  * Copyright (C) 2005 - Javolution (http://javolution.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package javolution.text;
10
11 import j2me.lang.CharSequence;
12 import j2me.lang.Comparable;
13 import javolution.util.FastComparator;
14
15 /**
16  * <p> This class represents a character sequence backed up by a
17  * <code>char</code> array. Instances of this class are mutable and
18  * are typically used/reused to hold temporary text (unlike
19  * <code>String</code> they do not forces object creation).</p>
20  *
21  * <p> Instances of this classes have the following properties:<ul>
22  *
23  * <li> They support equality or lexical comparison with any
24  * <code>CharSequence</code> (e.g. <code>String</code>).</li>
25  *
26  * <li> They have the same hashcode than <code>String</code> and can be
27  * used to retrieve data from maps for which the keys are
28  * <code>String</code> instances.</li>
29  *
30  * <li> They support fast conversions to primitive types
31  * (e.g. {@link #toBoolean() Boolean}, {@link #toInt int}).</li>
32  *
33  * </ul></p>
34  *
35  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
36  * @version 4.0, June 16, 2006
37  */

38 public final class CharArray implements CharSequence JavaDoc, Comparable JavaDoc {
39
40     /**
41      * Holds the character array.
42      */

43     private char[] _array;
44
45     /**
46      * Holds the index of the first character.
47      */

48     private int _offset;
49
50     /**
51      * Holds the length of char sequence.
52      */

53     private int _length;
54
55     /**
56      * Holds the string representation of this CharArray (if known).
57      */

58     private String JavaDoc _asString;
59
60     /**
61      * Default constructor.
62      */

63     public CharArray() {
64     }
65
66     /**
67      * Creates a character array from the specified String.
68      *
69      * @param string the string source.
70      */

71     public CharArray(String JavaDoc string) {
72         _array = string.toCharArray();
73         _length = string.length();
74         _asString = string;
75     }
76
77     /**
78      * Creates a character array from the specified character sequence.
79      *
80      * @param csq the character sequence source.
81      */

82     public CharArray(CharSequence JavaDoc csq) {
83         _length = csq.length();
84         _array = new char[_length];
85         for (int i=0; i < _length;) {
86             _array[i] = csq.charAt(i++);
87         }
88     }
89
90     /**
91      * Returns the underlying array (read-only).
92      * The array returned should not be modified (unfortunately there is
93      * no way to make an array immutable in Java).
94      *
95      * @return the underlying array.
96      */

97     public char[] array() {
98         return _array;
99     }
100
101     /**
102      * Returns the length of this character sequence.
103      *
104      * @return the number of characters (16-bits Unicode) composing this
105      * character sequence.
106      */

107     public int length() {
108         return _length;
109     }
110
111     /**
112      * Returns the offset of the first character in the underlying array.
113      *
114      * @return the offset of the first character.
115      */

116     public int offset() {
117         return _offset;
118     }
119
120     /**
121      * Sets the underlying array of this CharArray.
122      *
123      * @param offset the new offset.
124      * @param array the new underlying array.
125      * @param length the new length.
126      * @return <code>this</code>
127      */

128     public CharArray setArray(char[] array, int offset, int length) {
129         _array = array;
130         _offset = offset;
131         _length = length;
132         _asString = null;
133         return this;
134     }
135
136     /**
137      * Returns the character at the specified index.
138      *
139      * @param index the index of the character starting at <code>0</code>.
140      * @return the character at the specified index of this character sequence.
141      * @throws IndexOutOfBoundsException if <code>((index < 0) ||
142      * (index >= length))</code>
143      */

144     public char charAt(int index) {
145         if ((index < 0) || (index >= _length))
146             throw new IndexOutOfBoundsException JavaDoc("index: " + index);
147         return _array[_offset + index];
148     }
149
150     /**
151      * Returns a new character sequence that is a subsequence of this sequence.
152      *
153      * @param start the index of the first character inclusive.
154      * @param end the index of the last character exclusive.
155      * @return the character sequence starting at the specified
156      * <code>start</code> position and ending just before the specified
157      * <code>end</code> position.
158      * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
159      * (start > end) || (end > this.length())</code>
160      */

161     public CharSequence JavaDoc subSequence(int start, int end) {
162         if ((start < 0) || (end < 0) || (start > end) || (end > this.length()))
163             throw new IndexOutOfBoundsException JavaDoc();
164         CharArray chars = new CharArray();
165         chars._array = _array;
166         chars._offset = _offset + start;
167         chars._length = end - start;
168         return chars;
169     }
170
171     /**
172      * Returns the offset within this character array of the first occurrence
173      * of the specified characters sequence searching forward from this
174      * character array {@link #offset()} to <code>offset() + length()</code>.
175      *
176      * @param csq a character sequence searched for.
177      * @return the offset of the specified character sequence in the range
178      * <code>[offset(), offset() + length()[</code>
179      * or <code>-1</code> if the character sequence is not found.
180      */

181     public final int offsetOf(CharSequence JavaDoc csq) {
182         final char c = csq.charAt(0);
183         final int csqLength = csq.length();
184         for (int i=_offset, end = _offset + _length - csqLength + 1; i < end; i++) {
185             if (_array[i] == c) { // Potential match.
186
boolean match = true;
187                 for (int j = 1; j < csqLength; j++) {
188                     if (_array[i + j] != csq.charAt(j)) {
189                         match = false;
190                         break;
191                     }
192                 }
193                 if (match) {
194                     return i;
195                 }
196             }
197         }
198         return -1;
199     }
200
201     /**
202      * Returns the offset within this character array of the first occurrence
203      * of the specified character searching forward from this
204      * character array {@link #offset()} to <code>offset() + length()</code>.
205      *
206      * @param c the character to search for.
207      * @return the offset of the specified character in the range
208      * <code>[offset(), offset() + length()[</code>
209      * or <code>-1</code> if the character is not found.
210      */

211     public final int offsetOf(char c) {
212         for (int i=_offset, end = _offset + _length; i < end; i++) {
213             if (_array[i] == c) return i;
214         }
215         return -1;
216     }
217     
218     /**
219      * Returns the <code>String<code> corresponding to this character
220      * sequence. The <code>String</code> returned is always allocated on the
221      * heap and can safely be referenced elsewhere.
222      *
223      * @return the <code>java.lang.String</code> for this character sequence.
224      */

225     public String JavaDoc toString() {
226         if (_asString == null) {
227             _asString = new String JavaDoc(_array, _offset, _length);
228         }
229         return _asString;
230     }
231
232     /**
233      * Returns the hash code for this {@link CharArray}.
234      *
235      * <p> Note: Returns the same hashCode as <code>java.lang.String</code>
236      * (consistent with {@link #equals})</p>
237      * @return the hash code value.
238      */

239     public int hashCode() {
240         if (_asString != null) return _asString.hashCode();
241         int h = 0;
242         for (int i = 0, j = _offset; i < _length; i++) {
243             h = 31 * h + _array[j++];
244         }
245         return h;
246     }
247
248     /**
249      * Compares this character sequence against the specified object
250      * (<code>String</code> or <code>CharSequence</code>).
251      *
252      * @param that the object to compare with.
253      * @return <code>true</code> if both objects represent the same sequence;
254      * <code>false</code> otherwise.
255      */

256     public boolean equals(Object JavaDoc that) {
257         if (that instanceof String JavaDoc) {
258             return equals((String JavaDoc) that);
259         } else if (that instanceof CharArray) {
260             return equals((CharArray) that);
261         } else if (that instanceof CharSequence JavaDoc) {
262             return equals((CharSequence JavaDoc) that);
263         } else {
264             return false;
265         }
266     }
267
268     // Do not make public or String instances may not use equals(String)
269
private boolean equals(CharSequence JavaDoc chars) {
270         if (chars == null)
271             return false;
272         if (this._length != chars.length())
273             return false;
274         for (int i = _length, j = _offset + _length; --i >= 0;) {
275             if (_array[--j] != chars.charAt(i))
276                 return false;
277         }
278         return true;
279     }
280
281     /**
282      * Compares this character array against the specified {@link CharArray}.
283      *
284      * @param that the character array to compare with.
285      * @return <code>true</code> if both objects represent the same sequence;
286      * <code>false</code> otherwise.
287      */

288     public boolean equals(CharArray that) {
289         if (this == that)
290             return true;
291         if (that == null)
292             return false;
293         if (this._length != that._length)
294             return false;
295         final char[] thatData = that._array;
296         for (int i = that._offset + _length, j = _offset + _length; --j >= _offset;) {
297             if (_array[j] != thatData[--i])
298                 return false;
299         }
300         return true;
301     }
302
303     /**
304      * Compares this character array against the specified String.
305      * In case of equality, the CharArray keeps a reference to the
306      * String for future comparisons.
307      *
308      * @param str the string to compare with.
309      * @return <code>true</code> if both objects represent the same sequence;
310      * <code>false</code> otherwise.
311      */

312     public boolean equals(String JavaDoc str) {
313         if (_asString != null)
314             return (_asString == str) ? true : _asString.equals(str) ?
315                     (_asString = str) == str : false;
316         if (str == null)
317             return false;
318         if (_length != str.length())
319             return false;
320         for (int i = _length, j = _offset + _length; --i >= 0;) {
321             if (_array[--j] != str.charAt(i))
322                 return false;
323         }
324         _asString = str;
325         return true;
326     }
327
328
329     /**
330      * Compares this character array with the specified character
331      * sequence lexicographically.
332      *
333      * @param seq the character sequence to be compared.
334      * @return <code>{@link FastComparator#LEXICAL}.compare(this, seq)</code>
335      * @throws ClassCastException if the specifed object is not a
336      * <code>CharSequence</code>.
337      */

338     public int compareTo(Object JavaDoc seq) {
339         return ((FastComparator)FastComparator.LEXICAL).compare(this, seq);
340     }
341
342     /**
343      * Returns the <code>boolean</code> represented by this character array.
344      *
345      * @return the corresponding <code>boolean</code> value.
346      * @throws NumberFormatException if this character sequence
347      * does not contain a parsable <code>boolean</code>.
348      */

349     public boolean toBoolean() {
350         int i = _offset;
351         if ((_length == 4) && (_array[i] == 't' || _array[i] == 'T')
352                 && (_array[++i] == 'r' || _array[i] == 'R')
353                 && (_array[++i] == 'u' || _array[i] == 'U')
354                 && (_array[++i] == 'e' || _array[i] == 'E'))
355             return true;
356         if ((_length == 5) && (_array[i] == 'f' || _array[i] == 'F')
357                 && (_array[++i] == 'a' || _array[i] == 'A')
358                 && (_array[++i] == 'l' || _array[i] == 'L')
359                 && (_array[++i] == 's' || _array[i] == 'S')
360                 && (_array[++i] == 'e' || _array[i] == 'E'))
361             return false;
362         throw new IllegalArgumentException JavaDoc("Cannot parse " + this
363                 + " as boolean");
364     }
365
366     /**
367      * Returns the decimal <code>int</code> represented by this character array.
368      *
369      * @return <code>toInt(10)</code>
370      * @throws NumberFormatException if this character sequence
371      * does not contain a parsable <code>int</code>.
372      */

373     public int toInt() {
374         return TypeFormat.parseInt(this);
375     }
376
377     /**
378      * Returns the <code>int</code> represented by this character array
379      * in the specified radix.
380      *
381      * @param radix the radix (e.g. <code>16</code> for hexadecimal).
382      * @return the corresponding <code>int</code> value.
383      * @throws NumberFormatException if this character sequence
384      * does not contain a parsable <code>int</code>.
385      */

386     public int toInt(int radix) {
387         return TypeFormat.parseInt(this, radix);
388     }
389
390     /**
391      * Returns the decimal <code>long</code> represented by this character
392      * array.
393      *
394      * @return the corresponding <code>long</code> value.
395      * @throws NumberFormatException if this character sequence
396      * does not contain a parsable <code>long</code>.
397      */

398     public long toLong() {
399         return TypeFormat.parseLong(this);
400     }
401
402     /**
403      * Returns the decimal <code>long</code> represented by this character
404      * array in the specified radix.
405      *
406      * @param radix the radix (e.g. <code>16</code> for hexadecimal).
407      * @return the corresponding <code>long</code> value.
408      * @throws NumberFormatException if this character sequence
409      * does not contain a parsable <code>long</code>.
410      */

411     public long toLong(int radix) {
412         return TypeFormat.parseLong(this, radix);
413     }
414
415     /**
416      * Returns the <code>float</code> represented by this character array.
417      *
418      * @return the corresponding <code>float</code> value.
419      * @return <code>TypeFormat.parseFloat(this)</code>
420      * @throws NumberFormatException if this character sequence
421      * does not contain a parsable <code>float</code>.
422      /*@JVM-1.1+@
423      public float toFloat() {
424      return TypeFormat.parseFloat(this);
425      }
426      /**/

427
428     /**
429      * Returns the <code>double</code> represented by this character array.
430      *
431      * @return the corresponding <code>double</code> value.
432      * @throws NumberFormatException if this character sequence
433      * does not contain a parsable <code>double</code>.
434      /*@JVM-1.1+@
435      public double toDouble() {
436      return TypeFormat.parseDouble(this);
437      }
438      /**/

439
440 }
Popular Tags