001: /*
002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/StringParser.java,v 1.2 2001/07/22 20:25:14 pier Exp $
003: * $Revision: 1.2 $
004: * $Date: 2001/07/22 20:25:14 $
005: *
006: * ====================================================================
007: *
008: * The Apache Software License, Version 1.1
009: *
010: * Copyright (c) 1999 The Apache Software Foundation. All rights
011: * reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions
015: * are met:
016: *
017: * 1. Redistributions of source code must retain the above copyright
018: * notice, this list of conditions and the following disclaimer.
019: *
020: * 2. Redistributions in binary form must reproduce the above copyright
021: * notice, this list of conditions and the following disclaimer in
022: * the documentation and/or other materials provided with the
023: * distribution.
024: *
025: * 3. The end-user documentation included with the redistribution, if
026: * any, must include the following acknowlegement:
027: * "This product includes software developed by the
028: * Apache Software Foundation (http://www.apache.org/)."
029: * Alternately, this acknowlegement may appear in the software itself,
030: * if and wherever such third-party acknowlegements normally appear.
031: *
032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
033: * Foundation" must not be used to endorse or promote products derived
034: * from this software without prior written permission. For written
035: * permission, please contact apache@apache.org.
036: *
037: * 5. Products derived from this software may not be called "Apache"
038: * nor may "Apache" appear in their names without prior written
039: * permission of the Apache Group.
040: *
041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
052: * SUCH DAMAGE.
053: * ====================================================================
054: *
055: * This software consists of voluntary contributions made by many
056: * individuals on behalf of the Apache Software Foundation. For more
057: * information on the Apache Software Foundation, please see
058: * <http://www.apache.org/>.
059: *
060: * [Additional notices, if required by prior licensing conditions]
061: *
062: */
063:
064: package org.apache.catalina.util;
065:
066: /**
067: * Utility class for string parsing that is higher performance than
068: * StringParser for simple delimited text cases. Parsing is performed
069: * by setting the string, and then using the <code>findXxxx()</code> and
070: * <code>skipXxxx()</code> families of methods to remember significant
071: * offsets. To retrieve the parsed substrings, call the <code>extract()</code>
072: * method with the appropriate saved offset values.
073: *
074: * @author Craig R. McClanahan
075: * @version $Revision: 1.2 $ $Date: 2001/07/22 20:25:14 $
076: */
077:
078: public final class StringParser {
079:
080: // ----------------------------------------------------------- Constructors
081:
082: /**
083: * Construct a string parser with no preset string to be parsed.
084: */
085: public StringParser() {
086:
087: this (null);
088:
089: }
090:
091: /**
092: * Construct a string parser that is initialized to parse the specified
093: * string.
094: *
095: * @param string The string to be parsed
096: */
097: public StringParser(String string) {
098:
099: super ();
100: setString(string);
101:
102: }
103:
104: // ----------------------------------------------------- Instance Variables
105:
106: /**
107: * The characters of the current string, as a character array. Stored
108: * when the string is first specified to speed up access to characters
109: * being compared during parsing.
110: */
111: private char chars[] = null;
112:
113: /**
114: * The zero-relative index of the current point at which we are
115: * positioned within the string being parsed. <strong>NOTE</strong>:
116: * the value of this index can be one larger than the index of the last
117: * character of the string (i.e. equal to the string length) if you
118: * parse off the end of the string. This value is useful for extracting
119: * substrings that include the end of the string.
120: */
121: private int index = 0;
122:
123: /**
124: * The length of the String we are currently parsing. Stored when the
125: * string is first specified to avoid repeated recalculations.
126: */
127: private int length = 0;
128:
129: /**
130: * The String we are currently parsing.
131: */
132: private String string = null;
133:
134: // ------------------------------------------------------------- Properties
135:
136: /**
137: * Return the zero-relative index of our current parsing position
138: * within the string being parsed.
139: */
140: public int getIndex() {
141:
142: return (this .index);
143:
144: }
145:
146: /**
147: * Return the length of the string we are parsing.
148: */
149: public int getLength() {
150:
151: return (this .length);
152:
153: }
154:
155: /**
156: * Return the String we are currently parsing.
157: */
158: public String getString() {
159:
160: return (this .string);
161:
162: }
163:
164: /**
165: * Set the String we are currently parsing. The parser state is also reset
166: * to begin at the start of this string.
167: *
168: * @param string The string to be parsed.
169: */
170: public void setString(String string) {
171:
172: this .string = string;
173: if (string != null) {
174: this .length = string.length();
175: chars = this .string.toCharArray();
176: } else {
177: this .length = 0;
178: chars = new char[0];
179: }
180: reset();
181:
182: }
183:
184: // --------------------------------------------------------- Public Methods
185:
186: /**
187: * Advance the current parsing position by one, if we are not already
188: * past the end of the string.
189: */
190: public void advance() {
191:
192: if (index < length)
193: index++;
194:
195: }
196:
197: /**
198: * Extract and return a substring that starts at the specified position,
199: * and extends to the end of the string being parsed. If this is not
200: * possible, a zero-length string is returned.
201: *
202: * @param start Starting index, zero relative, inclusive
203: */
204: public String extract(int start) {
205:
206: if ((start < 0) || (start >= length))
207: return ("");
208: else
209: return (string.substring(start));
210:
211: }
212:
213: /**
214: * Extract and return a substring that starts at the specified position,
215: * and ends at the character before the specified position. If this is
216: * not possible, a zero-length string is returned.
217: *
218: * @param start Starting index, zero relative, inclusive
219: * @param end Ending index, zero relative, exclusive
220: */
221: public String extract(int start, int end) {
222:
223: if ((start < 0) || (start >= end) || (end > length))
224: return ("");
225: else
226: return (string.substring(start, end));
227:
228: }
229:
230: /**
231: * Return the index of the next occurrence of the specified character,
232: * or the index of the character after the last position of the string
233: * if no more occurrences of this character are found. The current
234: * parsing position is updated to the returned value.
235: *
236: * @param ch Character to be found
237: */
238: public int findChar(char ch) {
239:
240: while ((index < length) && (ch != chars[index]))
241: index++;
242: return (index);
243:
244: }
245:
246: /**
247: * Return the index of the next occurrence of a non-whitespace character,
248: * or the index of the character after the last position of the string
249: * if no more non-whitespace characters are found. The current
250: * parsing position is updated to the returned value.
251: */
252: public int findText() {
253:
254: while ((index < length) && isWhite(chars[index]))
255: index++;
256: return (index);
257:
258: }
259:
260: /**
261: * Return the index of the next occurrence of a whitespace character,
262: * or the index of the character after the last position of the string
263: * if no more whitespace characters are found. The current parsing
264: * position is updated to the returned value.
265: */
266: public int findWhite() {
267:
268: while ((index < length) && !isWhite(chars[index]))
269: index++;
270: return (index);
271:
272: }
273:
274: /**
275: * Reset the current state of the parser to the beginning of the
276: * current string being parsed.
277: */
278: public void reset() {
279:
280: index = 0;
281:
282: }
283:
284: /**
285: * Advance the current parsing position while it is pointing at the
286: * specified character, or until it moves past the end of the string.
287: * Return the final value.
288: *
289: * @param ch Character to be skipped
290: */
291: public int skipChar(char ch) {
292:
293: while ((index < length) && (ch == chars[index]))
294: index++;
295: return (index);
296:
297: }
298:
299: /**
300: * Advance the current parsing position while it is pointing at a
301: * non-whitespace character, or until it moves past the end of the string.
302: * Return the final value.
303: */
304: public int skipText() {
305:
306: while ((index < length) && !isWhite(chars[index]))
307: index++;
308: return (index);
309:
310: }
311:
312: /**
313: * Advance the current parsing position while it is pointing at a
314: * whitespace character, or until it moves past the end of the string.
315: * Return the final value.
316: */
317: public int skipWhite() {
318:
319: while ((index < length) && isWhite(chars[index]))
320: index++;
321: return (index);
322:
323: }
324:
325: // ------------------------------------------------------ Protected Methods
326:
327: /**
328: * Is the specified character considered to be whitespace?
329: *
330: * @param ch Character to be checked
331: */
332: protected boolean isWhite(char ch) {
333:
334: if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'))
335: return (true);
336: else
337: return (false);
338:
339: }
340:
341: }
|