KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensymphony > module > sitemesh > html > util > CharArray


1 package com.opensymphony.module.sitemesh.html.util;
2
3 /**
4  * A leaner, meaner version of StringBuffer.
5  * <p/>
6  * It provides basic functionality to handle dynamically-growing
7  * char arrays as quickly as possible. This class is not threadsafe.
8  *
9  * @author Chris Miller
10  */

11 public class CharArray
12 {
13    int size = 0;
14    char[] buffer;
15
16    // These properties allow us to specify a substring within the character array
17
// that we can perform comparisons against. This is here purely for performance -
18
// the comparisons are at the heart of the FastPageParser loop and any speed increase
19
// we can get at this level has a huge impact on performance.
20
int subStrStart = 0;
21    int subStrLen = 0;
22
23    /**
24     * Constructs a CharArray that is initialized to the specified size.
25     *
26     * Do not pass in a negative value because there is no bounds checking!
27     */

28    public CharArray(int size)
29    {
30       buffer = new char[size];
31    }
32
33    /**
34     * Returns a String represenation of the character array.
35     */

36    public String JavaDoc toString()
37    {
38       return new String JavaDoc(buffer, 0, size);
39    }
40
41    /**
42     * Returns the character that is at the specified position in the array.
43     *
44     * There is no bounds checking on this method so be sure to pass in a
45     * sensible value.
46     */

47    public char charAt(int pos)
48    {
49       return buffer[pos];
50    }
51
52    /**
53     * Changes the size of the character array to the value specified.
54     *
55     * If the new size is less than the current size, the data in the
56     * internal array will be truncated. If the new size is &lt;= 0,
57     * the array will be reset to empty (but, unlike StringBuffer, the
58     * internal array will NOT be shrunk). If the new size is &gt the
59     * current size, the array will be padded out with null characters
60     * (<tt>'&#92;u0000'</tt>).
61     *
62     * @param newSize the new size of the character array
63     */

64    public void setLength(int newSize)
65    {
66       if (newSize < 0)
67       {
68          newSize = 0;
69       }
70
71       if (newSize <= size)
72       {
73          size = newSize;
74       }
75       else
76       {
77          if (newSize >= buffer.length)
78             grow(newSize);
79          // Pad the array
80
for (; size < newSize; size++)
81                 buffer[size] = '\0';
82       }
83    }
84
85    /**
86     * Returns the current length of the character array.
87     */

88    public int length()
89    {
90       return size;
91    }
92
93    /**
94     * Appends an existing CharArray on to this one.
95     *
96     * Passing in a <tt>null</tt> CharArray will result in a <tt>NullPointerException</tt>.
97     */

98    public CharArray append(CharArray chars)
99    {
100       return append(chars.buffer, 0, chars.size);
101    }
102
103    /**
104     * Appends the supplied characters to the end of the array.
105     */

106    public CharArray append(char[] chars)
107    {
108       return append(chars, 0, chars.length);
109    }
110
111    public CharArray append(char[] chars, int position, int length)
112    {
113        int requiredSize = length + size;
114        if (requiredSize >= buffer.length)
115           grow(requiredSize);
116        System.arraycopy(chars, position, buffer, size, length);
117        size = requiredSize;
118        return this;
119    }
120
121    /**
122     * Appends a single character to the end of the character array.
123     */

124    public CharArray append(char c)
125    {
126       if (buffer.length == size)
127          grow(0);
128       buffer[size++] = c;
129       return this;
130    }
131
132    /**
133     * Appends the supplied string to the end of this character array.
134     *
135     * Passing in a <tt>null</tt> string will result in a <tt>NullPointerException</tt>.
136     */

137    public CharArray append(String JavaDoc str)
138    {
139       int requiredSize = str.length() + size;
140       if (requiredSize >= buffer.length)
141          grow(requiredSize);
142
143       for (int i = 0; i < str.length(); i++)
144          buffer[size + i] = str.charAt(i);
145
146       size = requiredSize;
147       return this;
148    }
149
150    /**
151     * Returns a substring from within this character array.
152     *
153     * Note that NO range checking is performed!
154     */

155    public String JavaDoc substring(int begin, int end)
156    {
157       return new String JavaDoc(buffer, begin, end - begin);
158    }
159
160    /**
161     * Allows an arbitrary substring of this character array to be specified.
162     * This method should be called prior to calling {@link #compareLowerSubstr(String)}
163     * to set the range of the substring comparison.
164     *
165     * @param begin the starting offset into the character array.
166     * @param end the ending offset into the character array.
167     */

168    public void setSubstr(int begin, int end)
169    {
170       subStrStart = begin;
171       subStrLen = end - begin;
172    }
173
174    /**
175     * Returns the substring that was specified by the {@link #setSubstr(int, int)} call.
176     */

177    public String JavaDoc getLowerSubstr()
178    {
179       for (int i = subStrStart; i < subStrStart + subStrLen; i++)
180          buffer[i] |= 32;
181       return new String JavaDoc(buffer, subStrStart, subStrLen);
182    }
183
184    /**
185     * This compares a substring of this character array (as specified
186     * by the {@link #setSubstr(int, int)} method call) with the supplied
187     * string. The supplied string <em>must</em> be lowercase, otherwise
188     * the comparison will fail.
189     */

190    public boolean compareLowerSubstr(String JavaDoc lowerStr)
191    {
192       // Range check
193
if (lowerStr.length() != subStrLen || subStrLen <= 0)
194          return false;
195
196       for (int i = 0; i < lowerStr.length(); i++) {
197          // | 32 converts from ASCII uppercase to ASCII lowercase
198
if ((buffer[subStrStart + i] | 32) != lowerStr.charAt(i))
199             return false;
200       }
201       return true;
202    }
203
204    /**
205     * Returns the hashcode for a <em>lowercase</em> version of the array's substring
206     * (as set by the {@link #setSubstr(int, int)} method).
207     *
208     * This uses the same calculation as the <tt>String.hashCode()</tt> method
209     * so that it remains compatible with the hashcodes of normal strings.
210     */

211    public int substrHashCode()
212    {
213       int hash = 0;
214       int offset = subStrStart;
215       for (int i = 0; i < subStrLen; i++) {
216          hash = 31 * hash + (buffer[offset++] | 32);
217       }
218       return hash;
219    }
220
221    /**
222     * Compares the supplied uppercase string with the contents of
223     * the character array, starting at the offset specified.
224     *
225     * This is a specialized method to help speed up the FastPageParser
226     * slightly.
227     * <p/>
228     * The supplied string is assumed to contain only uppercase ASCII
229     * characters. The offset indicates the offset into the character
230     * array that the comparison should start from.
231     * <p/>
232     * If (and only if) the supplied string and the relevant portion of the
233     * character array are considered equal, this method will return <tt>true</tt>.
234     */

235    public boolean compareLower(String JavaDoc lowerStr, int offset)
236    {
237       // Range check
238
if (offset < 0 || offset + lowerStr.length() > size)
239          return false;
240
241       for (int i = 0; i < lowerStr.length(); i++)
242       {
243          // | 32 converts from ASCII uppercase to ASCII lowercase
244
if ((buffer[offset + i] | 32) != lowerStr.charAt(i))
245             return false;
246       }
247       return true;
248    }
249
250    /**
251     * Grows the internal array by either ~100% or minSize (whichever is larger),
252     * up to a maximum size of Integer.MAX_VALUE.
253     */

254    private final void grow(int minSize)
255    {
256       int newCapacity = (buffer.length + 1) * 2;
257       if (newCapacity < 0)
258       {
259          newCapacity = Integer.MAX_VALUE;
260       }
261       else if (minSize > newCapacity)
262       {
263          newCapacity = minSize;
264       }
265       char newBuffer[] = new char[newCapacity];
266       System.arraycopy(buffer, 0, newBuffer, 0, size);
267       buffer = newBuffer;
268    }
269
270     /**
271      * Clear the contents.
272      */

273     public final void clear()
274     {
275         size = 0;
276     }
277
278 }
279
Popular Tags