1 /* -------------------------------------------------------------------
2 * Java source file for the class StringReader
3 *
4 * Copyright (c), 2002, Masahiro Takatsuka.
5 * All Rights Researved.
6 *
7 * Original Author: Masahiro Takatsuka (masa@jbeans.net)
8 * $Author: takatsukam $
9 *
10 * $Date: 2003/07/25 04:51:46 $
11 *
12 * $Id: StringReader.java,v 1.1.1.1 2003/07/25 04:51:46 takatsukam Exp $
13 *
14 * Reference: Document no:
15 * ___ ___
16 *
17 * To Do:
18 * ___
19 *
20 ------------------------------------------------------------------- */
21
22 /* --------------------------- Package ---------------------------- */
23 package net.jbeans.io;
24
25 /* ------------------ Import classes (packages) ------------------- *//package-summary/html">color="#329900"> ------------------ Import classes (packages) ------------------- *//package-summary.html">color="#329900">/* ------------------ Import classes (packages) ------------------- *//package-summary.html">color="#329900"> ------------------ Import classes (packages) ------------------- */
26 import java.io.*;
27 import java.util.*;
28
29 /*====================================================================
30 Implementation of class StringReader
31 ====================================================================*/
32 /***
33 * The -string reader class allows an application to read tokens
34 * as well as single characters from a string. The tokenization method
35 * is the same one used by <code>StringTokenizer</code>.
36 * The <code>MtStringReader</code> does not recognize identifiers, numbers,
37 * quoted strings and skip comments.
38 * <p>
39 * Delimiters can be set at creation time as well as on a per-token basis.
40 * <p>
41 * The <code>MtStringReader</code> behaves in one of two ways
42 * (same as java.util.StringTokenizer), depending
43 * on whether it was created with the <code>returnTokens</code> flag
44 * having the value <code>true</code> or <code>false</code>: see more detail
45 * in <code>java.util.StringTokenizer</code>.
46 * <p>
47 * The following is one example of the use of the string reader. The code:
48 * <blockquote><pre>
49 * MtStringReader sr = new MtStringReader("this is a test 1 2 3.4");
50 * while (sr.hasMoreTokens()) {
51 * println(sr.nextToken());
52 * }
53 * </pre></blockquote>
54 * <p>
55 * prints the following output:
56 * <blockquote><pre>
57 * this
58 * is
59 * a
60 * test
61 * 1
62 * 2
63 * 3.4
64 * </pre></blockquote>
65 * or
66 * <blockquote><pre>
67 * MtStringReader sr = new MtStringReader("this is a test 1 2 3.4");
68 * println(sr.nextToken());
69 * println(sr.nextToken());
70 * println(sr.nextToken());
71 * println(sr.nextToken());
72 * println(sr.readInt());
73 * println(sr.readInt());
74 * println(sr.readFloat());
75 * </pre></blockquote>
76 * <p>
77 * prints the following output:
78 * <blockquote><pre>
79 * this
80 * is
81 * a
82 * test
83 * 1
84 * 2
85 * 3.4
86 * </pre></blockquote>
87 *
88 * @version $Revision: 1.1.1.1 $
89 * @author Masahiro Takatsuka (masa@jbeans.net)
90 * @see Reader
91 * @see Enumeration
92 */
93
94 public final class StringReader extends Reader implements Enumeration {
95 private int currentPosition;
96 private int maxPosition;
97 private String str;
98 private String delimiters;
99 private boolean retTokens;
100 private int mark;
101 private String quotes; // 1999-Oct-18
102
103 /***
104 * Constructs a M-string reader for the specified string. The set of
105 * delimiters is specified in the <code>delim</code> argument.
106 * <p>
107 * If the <code>returnTokens</code> flag is <code>true</code>, then
108 * the delimiter characters are also returned as tokens.
109 *
110 * @param str a string to be parsed.
111 * @param delim the delimiters.
112 * @param quotes quotation characters.// 1999-Oct-18
113 * @param returnTokens flag indicating whether to return the delimiters
114 * as tokens.
115 */
116 public StringReader(String str, String delim, String quotes, boolean returnTokens) {
117 super();
118 this.currentPosition = 0;
119 this.str = str;
120 this.maxPosition = (this.str !=null)?this.str.length():0;
121 this.delimiters = (delim == null) ? " \t\n\r\f" : delim;
122 this.quotes = quotes; // 1999-Oct-18
123 this.retTokens = returnTokens;
124 this.mark = 0;
125 }
126
127 /***
128 * Constructs a M-string reader for the specified string. The set of
129 * delimiters is specified in the <code>delim</code> argument.
130 * <p>
131 * If the <code>returnTokens</code> flag is <code>true</code>, then
132 * the delimiter characters are also returned as tokens.
133 *
134 * @param str a string to be parsed.
135 * @param delim the delimiters.
136 * @param returnTokens flag indicating whether to return the delimiters
137 * as tokens.
138 */
139 public StringReader(String str, String delim, boolean returnTokens) {
140 this(str, delim, "\"\'", returnTokens);
141 }
142
143 /***
144 * Constructs a M-string reader for the specified string. The set of
145 * delimiters is specified in the <code>delim</code> argument.
146 *
147 * @param str a string to be parsed.
148 * @param delim the delimiters.
149 */
150 public StringReader(String str, String delim) {
151 this(str, delim, false);
152 }
153
154 /***
155 * Constructs a M-string reader for the specified string. The following
156 * characters are used as the default delimiter set:
157 * <code>"\t\n\r\f"</code>: the space character, the tab
158 * character, the newline character, the carriage-return character,
159 * and the form-feed character.
160 *
161 * @param str a string to be parsed.
162 */
163 public StringReader(String str) {
164 this(str, " \t\n\r\f", false);
165 }
166
167 /***
168 * Skips delimiters.
169 */
170 private void skipDelimiters() {
171 if (!this.retTokens) {
172 while ((this.currentPosition < this.maxPosition) &&
173 (this.delimiters.indexOf(this.str.charAt(this.currentPosition)) >= 0)) {
174 this.currentPosition++;
175 }
176 }
177 }
178
179 /***
180 * Returns <tt>true</tt> if there are more tokens available.
181 * If this method returns <tt>true</tt>, then a subsequent call to
182 * <tt>nextToken</tt> or <tt>readToken</tt> with no argument will
183 * successfully return a token.
184 *
185 * @return <code>true</code> if and only if there is at least one token
186 * in the string after the current position; <code>false</code>
187 * otherwise.
188 */
189 public final boolean hasMoreTokens() {
190 skipDelimiters();
191 return (this.currentPosition < this.maxPosition);
192 }
193
194 /***
195 * Returns the rest of tokens in the string.
196 *
197 * @return the rest of tokens in the string.
198 * @exception NoSuchElementException if there are no more tokens.
199 */
200 public final String restOfTokens() {
201 skipDelimiters();
202 if (this.currentPosition >= this.maxPosition) {
203 throw new NoSuchElementException();
204 }
205 return this.str.substring(this.currentPosition);
206 }
207
208 /***
209 * Returns the next token.
210 *
211 * @return the next token.
212 * @exception NoSuchElementException if there are no more tokens.
213 */
214 public final String nextToken() {
215 skipDelimiters();
216
217 if (this.currentPosition >= this.maxPosition) {
218 throw new NoSuchElementException();
219 }
220
221 int start = this.currentPosition;
222 while ((this.currentPosition < this.maxPosition) &&
223 (this.delimiters.indexOf(this.str.charAt(this.currentPosition)) < 0)) {
224 this.currentPosition++;
225 }
226 if (this.retTokens && (start == this.currentPosition) &&
227 (this.delimiters.indexOf(this.str.charAt(this.currentPosition)) >= 0)) {
228 this.currentPosition++;
229 }
230 return this.str.substring(start, this.currentPosition);
231 }
232
233 /***
234 * Returns the next token. First, delimiters specified by
235 * <tt>delim</tt> is set as the new delimiters. Then the next token
236 * in the string after the current position is returned.
237 * The new delimiter set remains the default after this call.
238 *
239 * @param delim the new delimiters.
240 * @return the next token, after switching to the new delimiter set.
241 * @exception NoSuchElementException if there are no more tokens.
242 */
243 public final String nextToken(String delim) {
244 this.delimiters = delim;
245 return nextToken();
246 }
247
248 /***
249 * Returns the same value as the <code>hasMoreTokens</code>
250 * method. It exists so that this class can implement the
251 * <code>Enumeration</code> interface.
252 *
253 * @return <code>true</code> if there are more tokens;
254 * <code>false</code> otherwise.
255 * @see #hasMoreTokens()
256 */
257 public final boolean hasMoreElements() {
258 return hasMoreTokens();
259 }
260
261 /***
262 * Returns the same value as the <code>nextToken</code> method,
263 * except that its declared return value is <code>Object</code> rather than
264 * <code>String</code>. It exists so that this class can implement the
265 * <code>Enumeration</code> interface.
266 *
267 * @return the next token in the string.
268 * @exception NoSuchElementException if there are no more tokens in this
269 * tokenizer's string.
270 * @see #nextToken()
271 */
272 public final Object nextElement() {
273 return nextToken();
274 }
275
276 /***
277 * Calculates the number of tokens in the string.
278 * The current position is not advanced.
279 *
280 * @return the number of tokens remaining in the string using the current
281 * delimiter set.
282 */
283 public final int countTokens() {
284 int count = 0;
285 int currpos = this.currentPosition;
286
287 while (currpos < this.maxPosition) {
288 if (!this.retTokens) { // skip delimiters.
289 while ((currpos < this.maxPosition) &&
290 (this.delimiters.indexOf(this.str.charAt(currpos)) >= 0)) {
291 currpos++;
292 }
293 }
294
295 if (currpos >= this.maxPosition) {
296 break;
297 }
298
299 int start = currpos;
300 while ((currpos < this.maxPosition) &&
301 (this.delimiters.indexOf(this.str.charAt(currpos)) < 0)) {
302 currpos++;
303 }
304 if (this.retTokens && (start == currpos) &&
305 (this.delimiters.indexOf(this.str.charAt(currpos)) >= 0)) {
306 currpos++;
307 }
308 count++;
309
310 }
311 return count;
312 }
313
314 /***
315 * Resets a M-string reader for the specified string. The set of
316 * delimiters is specified in the <code>delim</code> argument.
317 * <p>
318 * If the <code>returnTokens</code> flag is <code>true</code>, then
319 * the delimiter characters are also returned as tokens.
320 *
321 * @param str a string to be parsed.
322 * @param delim the delimiters.
323 * @param returnTokens flag indicating whether to return the delimiters
324 * as tokens.
325 */
326 public final void reset(String str, String delim, boolean returnTokens) {
327 this.currentPosition = 0;
328 this.str = str;
329 this.maxPosition = (this.str !=null)?this.str.length():0;
330 this.delimiters = delim;
331 this.retTokens = returnTokens;
332 }
333
334 /***
335 * Constructs a M-string reader for the specified string. The set of
336 * delimiters is specified in the <code>delim</code> argument.
337 *
338 * @param str a string to be parsed.
339 * @param delim the delimiters.
340 */
341 public final void reset(String str, String delim) {
342 reset(str, delim, false);
343 }
344
345 /***
346 * Constructs a M-string reader for the specified string. The following
347 * characters are used as the default delimiter set:
348 * <code>"\t\n\r\f"</code>: the space character, the tab
349 * character, the newline character, the carriage-return character,
350 * and the form-feed character.
351 *
352 * @param str a string to be parsed.
353 */
354 public final void reset(String str) {
355 reset(str, " \t\n\r\f", false);
356 }
357
358 /***
359 * Read characters into a portion of an array.
360 *
361 * @param cbuf Destination buffer
362 * @param off Offset at which to start writing characters
363 * @param len Maximum number of characters to read
364 * @return The number of characters read, or -1 if the end of the
365 * stream has been reached
366 *
367 * @exception IOException If an I/O error occurs
368 */
369 public final int read(char cbuf[], int off, int len) {
370 skipDelimiters();
371
372 if (this.currentPosition >= this.maxPosition) {
373 return -1; // the end of the stream has been reached.
374 // throw new NoSuchElementException();
375 }
376
377 int n = Math.min(this.maxPosition - this.currentPosition, len);
378 this.str.getChars(this.currentPosition, this.currentPosition + n, cbuf, off);
379 this.currentPosition += n;
380 return n;
381 }
382
383 /***
384 * Read a single character. This method will block until a character is
385 * available, an I/O error occurs, or the end of the stream is reached.
386 *
387 * <p> Subclasses that intend to support efficient single-character input
388 * should override this method.
389 *
390 * @return The character read, as an integer in the range 0 to 16383
391 * (<tt>0x00-0xffff</tt>), or -1 if the end of the stream has
392 * been reached
393 */
394 public final int read() {
395 char cb[] = new char[1];
396 if (read(cb, 0, 1) == -1)
397 return -1;
398 else
399 return cb[0];
400 }
401
402 /***
403 * Read characters into an array. This method will block until some input
404 * is available, an I/O error occurs, or the end of the stream is reached.
405 *
406 * @param cbuf Destination buffer
407 *
408 * @return The number of bytes read, or -1 if the end of the stream
409 * has been reached
410 */
411 public final int read(char cbuf[]) {
412 return read(cbuf, 0, cbuf.length);
413 }
414
415 /***
416 * Tell whether this stream is ready to be read. String readers are
417 * always ready to be read.
418 */
419 public final boolean ready() {
420 return (this.str != null)?true:false;
421 }
422
423 /***
424 * Tell whether this stream supports the mark() operation, which it does.
425 */
426 public final boolean markSupported() {
427 return true;
428 }
429
430 /***
431 * Mark the present position in the stream. Subsequent calls to reset()
432 * will reposition the stream to this point.
433 *
434 * @param readAheadLimit Limit on the number of characters that may be
435 * read while still preserving the mark. Because
436 * the stream's input comes from a string, there
437 * is no actual limit, so this argument is ignored.
438 *
439 * @exception IOException If an I/O error occurs
440 */
441 public final void mark(int readAheadLimit) throws IOException {
442 this.mark = this.currentPosition;
443 }
444
445 /***
446 * Reset the stream to the most recent mark, or to the beginning of the
447 * string if it has never been marked.
448 *
449 * @exception IOException If an I/O error occurs
450 */
451 public final void reset() throws IOException {
452 this.currentPosition = this.mark;
453 }
454
455 /***
456 * Close the stream.
457 */
458 public final void close() {
459 this.str = null;
460 }
461
462 /***
463 * Read one token as a string.
464 *
465 * @return A String containing the string, or null if the end of the
466 * stream has been reached.
467 */
468 public final String readToken() {
469 return nextToken();
470 }
471
472 /***
473 * Returns the next token in this string tokenizer's string. First,
474 * the set of characters considered to be delimiters by this
475 * <tt>StringTokenizer</tt> object is changed to be the characters in
476 * the string <tt>delim</tt>. Then the next token in the string
477 * after the current position is returned. The current position is
478 * advanced beyond the recognized token. The new delimiter set
479 * remains the default after this call.
480 *
481 * @param delim the new delimiters.
482 * @return the next token, after switching to the new delimiter set.
483 * @exception NoSuchElementException if there are no more tokens in this
484 * tokenizer's string.
485 */
486 public final String readToken(String delim) {
487 return nextToken(delim);
488 }
489
490 /***
491 * Reads a <code>boolean</code> from this data input stream. This
492 * method reads a single byte from the underlying input stream. A
493 * value of <code>0</code> represents <code>false</code>. Any other
494 * value represents <code>true</code>. This method blocks until
495 * either the byte is read, the end of the stream is detected, or an
496 * exception is thrown.
497 *
498 * @return the <code>boolean</code> value read.
499 */
500 public final boolean readBoolean() {
501 return (Boolean.valueOf(nextToken())).booleanValue();
502 }
503
504 /***
505 * Reads a signed 8-bit value from this data input stream. This
506 * method reads a byte from the underlying input stream. If the byte
507 * read is <code>b</code>, where
508 * 0 <= <code>b</code> <= 255, then the
509 * result is:
510 * <ul><code>
511 * (byte)(b)
512 * </code></ul>
513 * <p>
514 * This method blocks until either the byte is read, the end of the
515 * stream is detected, or an exception is thrown.
516 *
517 * @return the next byte of this input stream as a signed 8-bit
518 * <code>byte</code>.
519 */
520 public final byte readByte() {
521 return Byte.parseByte(nextToken());
522 }
523
524 /***
525 * Reads a signed 16-bit number from this data input stream. The
526 * method reads two bytes from the underlying input stream. If the two
527 * bytes read, in order, are <code>b1</code> and <code>b2</code>,
528 * where each of the two values is between <code>0</code> and
529 * <code>255</code>, inclusive, then the result is equal to:
530 * <ul><code>
531 * (short)((b1 << 8) | b2)
532 * </code></ul>
533 * <p>
534 * This method blocks until the two bytes are read, the end of the
535 * stream is detected, or an exception is thrown.
536 *
537 * @return the next two bytes of this input stream, interpreted as a
538 * signed 16-bit number.
539 */
540 public final short readShort() {
541 return Short.parseShort(nextToken());
542 }
543
544 /***
545 * Reads a Unicode character from this data input stream. This
546 * method reads two bytes from the underlying input stream. If the
547 * bytes read, in order, are <code>b1</code> and <code>b2</code>,
548 * where 0 <= <code>b1</code>,
549 * <code>b1</code> <= 255, then the result is equal to:
550 * <ul><code>
551 * (char)((b1 << 8) | b2)
552 * </code></ul>
553 * <p>
554 * This method blocks until either the two bytes are read, the end of
555 * the stream is detected, or an exception is thrown.
556 *
557 * @return the next two bytes of this input stream as a Unicode
558 * character.
559 */
560 public final char readChar() {
561 int ch1 = read();
562 int ch2 = read();
563 if ((ch1 | ch2) < 0)
564 throw new NoSuchElementException();
565 return (char)((ch1 << 8) + (ch2 << 0));
566 }
567
568 /***
569 * Reads a signed 32-bit integer from this data input stream. This
570 * method reads four bytes from the underlying input stream. If the
571 * bytes read, in order, are <code>b1</code>, <code>b2</code>,
572 * <code>b3</code>, and <code>b4</code>, where
573 * 0 <= <code>b1</code>, <code>b2</code>,
574 * <code>b3</code>, <code>b4</code> <= 255, then the
575 * result is equal to:
576 * <ul><code>
577 * (b1 << 24) | (b2 << 16) + (b3 << 8) +b4
578 * </code></ul>
579 * <p>
580 * This method blocks until the four bytes are read, the end of the
581 * stream is detected, or an exception is thrown.
582 *
583 * @return the next four bytes of this input stream, interpreted as an
584 * <code>int</code>.
585 */
586 public final int readInt() {
587 return Integer.parseInt(nextToken());
588 }
589
590 /***
591 * Reads a signed 64-bit integer from this data input stream. This
592 * method reads eight bytes from the underlying input stream. If the
593 * bytes read, in order, are <code>b1</code>, <code>b2</code>,
594 * <code>b3</code>, <code>b4</code>, <code>b5</code>,
595 * <code>b6</code>, <code>b7</code>, and <code>b8</code>, where
596 * <ul><code>
597 * 0 <= b1, b2, b3, b4, b5, b6, b7, b8 <= 255,
598 * </code></ul>
599 * <p>
600 * then the result is equal to:
601 * <p><blockquote><pre>
602 * ((long)b1 << 56) + ((long)b2 << 48) +
603 * ((long)b3 << 40) + ((long)b4 << 32) +
604 * ((long)b5 << 24) + (b6 << 16) +
605 * (b7 << 8) + b8
606 * </pre></blockquote>
607 * <p>
608 * This method blocks until the eight bytes are read, the end of the
609 * stream is detected, or an exception is thrown.
610 *
611 * @return the next eight bytes of this input stream, interpreted as a
612 * <code>long</code>.
613 */
614 public final long readLong() throws IOException {
615 return Long.parseLong(nextToken());
616 }
617
618 /***
619 * Reads a <code>float</code> from this data input stream. This
620 * method reads an <code>int</code> value as if by the
621 * <code>readInt</code> method and then converts that
622 * <code>int</code> to a <code>float</code> using the
623 * <code>intBitsToFloat</code> method in class <code>Float</code>.
624 * This method blocks until the four bytes are read, the end of the
625 * stream is detected, or an exception is thrown.
626 *
627 * @return the next four bytes of this input stream, interpreted as a
628 * <code>float</code>.
629 */
630 public final float readFloat() {
631 return Float.parseFloat(nextToken());
632 }
633
634 /***
635 * Reads a <code>double</code> from this data input stream. This
636 * method reads a <code>long</code> value as if by the
637 * <code>readLong</code> method and then converts that
638 * <code>long</code> to a <code>double</code> using the
639 * <code>longBitsToDouble</code> method in class <code>Double</code>.
640 * <p>
641 * This method blocks until the eight bytes are read, the end of the
642 * stream is detected, or an exception is thrown.
643 *
644 * @return the next eight bytes of this input stream, interpreted as a
645 * <code>double</code>.
646 */
647 public final double readDouble() {
648 return Double.parseDouble(nextToken());
649 }
650 }
This page was automatically generated by Maven