/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2001-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.internal.io; import java.io.Reader; import java.io.IOException; import java.io.LineNumberReader; /** * A buffered character-input stream that keeps track of line numbers * and stream position. This class can't be public for now, because I * can't figure out how to implement reliably {@link #readLine}. * * @author Martin Desruisseaux (IRD) * @version 3.00 * * @since 1.2 * @module */ public final class LineReader extends LineNumberReader { /** * The current stream position. */ private long position; /** * The position of the mark, if any. */ private long markedPosition; /** * Creates a new line reader, using the default input-buffer size. * * @param in a Reader object to provide the underlying stream. */ public LineReader(final Reader in) { super(in); } /** * Creates a new line reader, reading characters into a buffer of the given size. * * @param in a Reader object to provide the underlying stream. * @param size an int specifying the size of the buffer. */ public LineReader(final Reader in, final int size) { super(in, size); } /** * Gets the current stream position. * * @return The current stream position. */ public long getPosition() { return position; } /** * Reads a single character. * * @return The character read, or -1 if the end of the stream has been reached. * @throws IOException If an I/O error occurs. */ @Override public int read() throws IOException { synchronized (lock) { final int c = super.read(); if (c >= 0) { position++; } return c; } } /** * Reads characters into a portion of an array. * * @param cbuf Destination buffer * @param off Offset at which to start storing characters * @param len Maximum number of characters to read * @return The number of bytes read, or -1 if the end of the stream has already been reached. * @throws IOException If an I/O error occurs. */ @Override public int read(final char[] cbuf, final int off, final int len) throws IOException { synchronized (lock) { final int n = super.read(cbuf, off, len); if (n >= 0) { position += n; } return n; } } /** * Reads a line of text. A line is considered to be terminated by any one * of a line feed ('\n'), a carriage return ('\r'), or a carriage return * followed immediately by a linefeed. * * @return A String containing the contents of the line, not including * any line-termination characters, or null if the end of the * stream has been reached * @throws IOException If an I/O error occurs. */ @Override public String readLine() throws IOException { synchronized (lock) { // TODO: Position update is **approximative**. There is no way to // know if 'super.readLine()' found "\r", "\n" or "\r\n". final String line = super.readLine(); if (line != null) { position += line.length() + 1; } return line; } } /** * Marks the present position in the stream. Subsequent calls to {@link #reset} * will attempt to reposition the stream to this point, and will also reset * the stream position appropriately. * * @param readAheadLimit Limit on the number of characters that may be read while still * preserving the mark. After reading this many characters, attempting to reset * the stream may fail. * @throws IOException If an I/O error occurs. */ @Override public void mark(final int readAheadLimit) throws IOException { synchronized (lock) { super.mark(readAheadLimit); markedPosition = position; } } /** * Resets the stream to the most recent mark. * * @throws IOException If the stream has not been marked, or if the mark has been invalidated. */ @Override public void reset() throws IOException { synchronized (lock) { super.reset(); position = markedPosition; } } }