001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2001, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.image.io.text;
018:
019: // Input/Output
020: import java.io.IOException;
021: import java.io.LineNumberReader;
022: import java.io.Reader;
023:
024: /**
025: * A buffered character-input stream that keeps track of line numbers
026: * and stream position. This class can't be public for now, because I
027: * can't figure out how to implement reliably {@link #readLine}.
028: *
029: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/coverageio/src/main/java/org/geotools/image/io/text/LineReader.java $
030: * @version $Id: LineReader.java 25699 2007-05-31 15:55:07Z desruisseaux $
031: * @author Martin Desruisseaux
032: */
033: final class LineReader extends LineNumberReader {
034: /**
035: * The current stream position.
036: */
037: private long position;
038:
039: /**
040: * The position of the mark, if any.
041: */
042: private long markedPosition;
043:
044: /**
045: * Create a new line reader, using the default input-buffer size.
046: *
047: * @param in a Reader object to provide the underlying stream.
048: */
049: public LineReader(final Reader in) {
050: super (in);
051: }
052:
053: /**
054: * Create a new line reader, reading characters
055: * into a buffer of the given size.
056: *
057: * @param in a Reader object to provide the underlying stream.
058: * @param size an int specifying the size of the buffer.
059: */
060: public LineReader(final Reader in, final int size) {
061: super (in, size);
062: }
063:
064: /**
065: * Get the current stream position.
066: *
067: * @return The current stream position.
068: */
069: public long getPosition() {
070: return position;
071: }
072:
073: /**
074: * Read a single character.
075: *
076: * @return The character read, or -1 if the end of the stream has been reached.
077: * @throws IOException If an I/O error occurs.
078: */
079: public int read() throws IOException {
080: synchronized (lock) {
081: final int c = super .read();
082: if (c >= 0) {
083: position++;
084: }
085: return c;
086: }
087: }
088:
089: /**
090: * Read characters into a portion of an array.
091: *
092: * @param cbuf Destination buffer
093: * @param off Offset at which to start storing characters
094: * @param len Maximum number of characters to read
095: * @return The number of bytes read, or -1 if the end of the stream has already been reached.
096: * @throws IOException If an I/O error occurs.
097: */
098: public int read(final char cbuf[], final int off, final int len)
099: throws IOException {
100: synchronized (lock) {
101: final int n = super .read(cbuf, off, len);
102: if (n >= 0) {
103: position += n;
104: }
105: return n;
106: }
107: }
108:
109: /**
110: * Read a line of text. A line is considered to be terminated by any one
111: * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
112: * followed immediately by a linefeed.
113: *
114: * @return A String containing the contents of the line, not including
115: * any line-termination characters, or null if the end of the
116: * stream has been reached
117: * @throws IOException If an I/O error occurs.
118: */
119: public String readLine() throws IOException {
120: synchronized (lock) {
121: // TODO: Position update is **approximative**. There is no way to
122: // know if 'super.readLine()' found "\r", "\n" or "\r\n".
123: final String line = super .readLine();
124: if (line != null) {
125: position += line.length() + 1;
126: }
127: return line;
128: }
129: }
130:
131: /**
132: * Mark the present position in the stream. Subsequent calls to {@link #reset}
133: * will attempt to reposition the stream to this point, and will also reset
134: * the stream position appropriately.
135: *
136: * @param readAheadLimit Limit on the number of characters that may be read while still
137: * preserving the mark. After reading this many characters, attempting to reset
138: * the stream may fail.
139: * @throws IOException If an I/O error occurs.
140: */
141: public void mark(final int readAheadLimit) throws IOException {
142: synchronized (lock) {
143: super .mark(readAheadLimit);
144: markedPosition = position;
145: }
146: }
147:
148: /**
149: * Reset the stream to the most recent mark.
150: *
151: * @throws IOException If the stream has not been marked, or if the mark has been invalidated.
152: */
153: public void reset() throws IOException {
154: synchronized (lock) {
155: super.reset();
156: position = markedPosition;
157: }
158: }
159: }
|