0N/A/*
2362N/A * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.io;
0N/A
0N/A
0N/A/**
0N/A * A character stream whose source is a string.
0N/A *
0N/A * @author Mark Reinhold
0N/A * @since JDK1.1
0N/A */
0N/A
0N/Apublic class StringReader extends Reader {
0N/A
0N/A private String str;
0N/A private int length;
0N/A private int next = 0;
0N/A private int mark = 0;
0N/A
0N/A /**
0N/A * Creates a new string reader.
0N/A *
0N/A * @param s String providing the character stream.
0N/A */
0N/A public StringReader(String s) {
0N/A this.str = s;
0N/A this.length = s.length();
0N/A }
0N/A
0N/A /** Check to make sure that the stream has not been closed */
0N/A private void ensureOpen() throws IOException {
0N/A if (str == null)
0N/A throw new IOException("Stream closed");
0N/A }
0N/A
0N/A /**
0N/A * Reads a single character.
0N/A *
0N/A * @return The character read, or -1 if the end of the stream has been
0N/A * reached
0N/A *
0N/A * @exception IOException If an I/O error occurs
0N/A */
0N/A public int read() throws IOException {
0N/A synchronized (lock) {
0N/A ensureOpen();
0N/A if (next >= length)
0N/A return -1;
0N/A return str.charAt(next++);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Reads characters into a portion of an array.
0N/A *
0N/A * @param cbuf Destination buffer
0N/A * @param off Offset at which to start writing characters
0N/A * @param len Maximum number of characters to read
0N/A *
0N/A * @return The number of characters read, or -1 if the end of the
0N/A * stream has been reached
0N/A *
0N/A * @exception IOException If an I/O error occurs
0N/A */
0N/A public int read(char cbuf[], int off, int len) throws IOException {
0N/A synchronized (lock) {
0N/A ensureOpen();
0N/A if ((off < 0) || (off > cbuf.length) || (len < 0) ||
0N/A ((off + len) > cbuf.length) || ((off + len) < 0)) {
0N/A throw new IndexOutOfBoundsException();
0N/A } else if (len == 0) {
0N/A return 0;
0N/A }
0N/A if (next >= length)
0N/A return -1;
0N/A int n = Math.min(length - next, len);
0N/A str.getChars(next, next + n, cbuf, off);
0N/A next += n;
0N/A return n;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Skips the specified number of characters in the stream. Returns
0N/A * the number of characters that were skipped.
0N/A *
0N/A * <p>The <code>ns</code> parameter may be negative, even though the
0N/A * <code>skip</code> method of the {@link Reader} superclass throws
0N/A * an exception in this case. Negative values of <code>ns</code> cause the
0N/A * stream to skip backwards. Negative return values indicate a skip
0N/A * backwards. It is not possible to skip backwards past the beginning of
0N/A * the string.
0N/A *
0N/A * <p>If the entire string has been read or skipped, then this method has
0N/A * no effect and always returns 0.
0N/A *
0N/A * @exception IOException If an I/O error occurs
0N/A */
0N/A public long skip(long ns) throws IOException {
0N/A synchronized (lock) {
0N/A ensureOpen();
0N/A if (next >= length)
0N/A return 0;
0N/A // Bound skip by beginning and end of the source
0N/A long n = Math.min(length - next, ns);
0N/A n = Math.max(-next, n);
0N/A next += n;
0N/A return n;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Tells whether this stream is ready to be read.
0N/A *
0N/A * @return True if the next read() is guaranteed not to block for input
0N/A *
0N/A * @exception IOException If the stream is closed
0N/A */
0N/A public boolean ready() throws IOException {
0N/A synchronized (lock) {
0N/A ensureOpen();
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Tells whether this stream supports the mark() operation, which it does.
0N/A */
0N/A public boolean markSupported() {
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * Marks the present position in the stream. Subsequent calls to reset()
0N/A * will reposition the stream to this point.
0N/A *
0N/A * @param readAheadLimit Limit on the number of characters that may be
0N/A * read while still preserving the mark. Because
0N/A * the stream's input comes from a string, there
0N/A * is no actual limit, so this argument must not
0N/A * be negative, but is otherwise ignored.
0N/A *
0N/A * @exception IllegalArgumentException If readAheadLimit is < 0
0N/A * @exception IOException If an I/O error occurs
0N/A */
0N/A public void mark(int readAheadLimit) throws IOException {
0N/A if (readAheadLimit < 0){
0N/A throw new IllegalArgumentException("Read-ahead limit < 0");
0N/A }
0N/A synchronized (lock) {
0N/A ensureOpen();
0N/A mark = next;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Resets the stream to the most recent mark, or to the beginning of the
0N/A * string if it has never been marked.
0N/A *
0N/A * @exception IOException If an I/O error occurs
0N/A */
0N/A public void reset() throws IOException {
0N/A synchronized (lock) {
0N/A ensureOpen();
0N/A next = mark;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Closes the stream and releases any system resources associated with
0N/A * it. Once the stream has been closed, further read(),
0N/A * ready(), mark(), or reset() invocations will throw an IOException.
0N/A * Closing a previously closed stream has no effect.
0N/A */
0N/A public void close() {
0N/A str = null;
0N/A }
0N/A}