jtulach@1314: /* jtulach@1314: * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved. jtulach@1314: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jtulach@1314: * jtulach@1314: * This code is free software; you can redistribute it and/or modify it jtulach@1314: * under the terms of the GNU General Public License version 2 only, as jtulach@1314: * published by the Free Software Foundation. Oracle designates this jtulach@1314: * particular file as subject to the "Classpath" exception as provided jtulach@1314: * by Oracle in the LICENSE file that accompanied this code. jtulach@1314: * jtulach@1314: * This code is distributed in the hope that it will be useful, but WITHOUT jtulach@1314: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jtulach@1314: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jtulach@1314: * version 2 for more details (a copy is included in the LICENSE file that jtulach@1314: * accompanied this code). jtulach@1314: * jtulach@1314: * You should have received a copy of the GNU General Public License version jtulach@1314: * 2 along with this work; if not, write to the Free Software Foundation, jtulach@1314: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jtulach@1314: * jtulach@1314: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jtulach@1314: * or visit www.oracle.com if you need additional information or have any jtulach@1314: * questions. jtulach@1314: */ jtulach@1314: jtulach@1314: package java.io; jtulach@1314: jtulach@1314: jtulach@1314: /** jtulach@1314: * A character stream whose source is a string. jtulach@1314: * jtulach@1314: * @author Mark Reinhold jtulach@1314: * @since JDK1.1 jtulach@1314: */ jtulach@1314: jtulach@1314: public class StringReader extends Reader { jtulach@1314: jtulach@1314: private String str; jtulach@1314: private int length; jtulach@1314: private int next = 0; jtulach@1314: private int mark = 0; jtulach@1314: jtulach@1314: /** jtulach@1314: * Creates a new string reader. jtulach@1314: * jtulach@1314: * @param s String providing the character stream. jtulach@1314: */ jtulach@1314: public StringReader(String s) { jtulach@1314: this.str = s; jtulach@1314: this.length = s.length(); jtulach@1314: } jtulach@1314: jtulach@1314: /** Check to make sure that the stream has not been closed */ jtulach@1314: private void ensureOpen() throws IOException { jtulach@1314: if (str == null) jtulach@1314: throw new IOException("Stream closed"); jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Reads a single character. jtulach@1314: * jtulach@1314: * @return The character read, or -1 if the end of the stream has been jtulach@1314: * reached jtulach@1314: * jtulach@1314: * @exception IOException If an I/O error occurs jtulach@1314: */ jtulach@1314: public int read() throws IOException { jtulach@1314: synchronized (lock) { jtulach@1314: ensureOpen(); jtulach@1314: if (next >= length) jtulach@1314: return -1; jtulach@1314: return str.charAt(next++); jtulach@1314: } jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Reads characters into a portion of an array. jtulach@1314: * jtulach@1314: * @param cbuf Destination buffer jtulach@1314: * @param off Offset at which to start writing characters jtulach@1314: * @param len Maximum number of characters to read jtulach@1314: * jtulach@1314: * @return The number of characters read, or -1 if the end of the jtulach@1314: * stream has been reached jtulach@1314: * jtulach@1314: * @exception IOException If an I/O error occurs jtulach@1314: */ jtulach@1314: public int read(char cbuf[], int off, int len) throws IOException { jtulach@1314: synchronized (lock) { jtulach@1314: ensureOpen(); jtulach@1314: if ((off < 0) || (off > cbuf.length) || (len < 0) || jtulach@1314: ((off + len) > cbuf.length) || ((off + len) < 0)) { jtulach@1314: throw new IndexOutOfBoundsException(); jtulach@1314: } else if (len == 0) { jtulach@1314: return 0; jtulach@1314: } jtulach@1314: if (next >= length) jtulach@1314: return -1; jtulach@1314: int n = Math.min(length - next, len); jtulach@1314: str.getChars(next, next + n, cbuf, off); jtulach@1314: next += n; jtulach@1314: return n; jtulach@1314: } jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Skips the specified number of characters in the stream. Returns jtulach@1314: * the number of characters that were skipped. jtulach@1314: * jtulach@1314: *

The ns parameter may be negative, even though the jtulach@1314: * skip method of the {@link Reader} superclass throws jtulach@1314: * an exception in this case. Negative values of ns cause the jtulach@1314: * stream to skip backwards. Negative return values indicate a skip jtulach@1314: * backwards. It is not possible to skip backwards past the beginning of jtulach@1314: * the string. jtulach@1314: * jtulach@1314: *

If the entire string has been read or skipped, then this method has jtulach@1314: * no effect and always returns 0. jtulach@1314: * jtulach@1314: * @exception IOException If an I/O error occurs jtulach@1314: */ jtulach@1314: public long skip(long ns) throws IOException { jtulach@1314: synchronized (lock) { jtulach@1314: ensureOpen(); jtulach@1314: if (next >= length) jtulach@1314: return 0; jtulach@1314: // Bound skip by beginning and end of the source jtulach@1314: long n = Math.min(length - next, ns); jtulach@1314: n = Math.max(-next, n); jtulach@1314: next += n; jtulach@1314: return n; jtulach@1314: } jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Tells whether this stream is ready to be read. jtulach@1314: * jtulach@1314: * @return True if the next read() is guaranteed not to block for input jtulach@1314: * jtulach@1314: * @exception IOException If the stream is closed jtulach@1314: */ jtulach@1314: public boolean ready() throws IOException { jtulach@1314: synchronized (lock) { jtulach@1314: ensureOpen(); jtulach@1314: return true; jtulach@1314: } jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Tells whether this stream supports the mark() operation, which it does. jtulach@1314: */ jtulach@1314: public boolean markSupported() { jtulach@1314: return true; jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Marks the present position in the stream. Subsequent calls to reset() jtulach@1314: * will reposition the stream to this point. jtulach@1314: * jtulach@1314: * @param readAheadLimit Limit on the number of characters that may be jtulach@1314: * read while still preserving the mark. Because jtulach@1314: * the stream's input comes from a string, there jtulach@1314: * is no actual limit, so this argument must not jtulach@1314: * be negative, but is otherwise ignored. jtulach@1314: * jtulach@1314: * @exception IllegalArgumentException If readAheadLimit is < 0 jtulach@1314: * @exception IOException If an I/O error occurs jtulach@1314: */ jtulach@1314: public void mark(int readAheadLimit) throws IOException { jtulach@1314: if (readAheadLimit < 0){ jtulach@1314: throw new IllegalArgumentException("Read-ahead limit < 0"); jtulach@1314: } jtulach@1314: synchronized (lock) { jtulach@1314: ensureOpen(); jtulach@1314: mark = next; jtulach@1314: } jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Resets the stream to the most recent mark, or to the beginning of the jtulach@1314: * string if it has never been marked. jtulach@1314: * jtulach@1314: * @exception IOException If an I/O error occurs jtulach@1314: */ jtulach@1314: public void reset() throws IOException { jtulach@1314: synchronized (lock) { jtulach@1314: ensureOpen(); jtulach@1314: next = mark; jtulach@1314: } jtulach@1314: } jtulach@1314: jtulach@1314: /** jtulach@1314: * Closes the stream and releases any system resources associated with jtulach@1314: * it. Once the stream has been closed, further read(), jtulach@1314: * ready(), mark(), or reset() invocations will throw an IOException. jtulach@1314: * Closing a previously closed stream has no effect. jtulach@1314: */ jtulach@1314: public void close() { jtulach@1314: str = null; jtulach@1314: } jtulach@1314: }