| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package tests.support; |
| |
| import java.io.IOException; |
| import java.io.Reader; |
| |
| public class Support_StringReader extends Reader { |
| private String str; |
| |
| private int markpos = -1; |
| |
| private int pos = 0; |
| |
| private int count; |
| |
| /** |
| * Construct a StringReader on the String <code>str</code>. The size of |
| * the reader is set to the <code>length()</code> of the String and the |
| * Object to synchronize access through is set to <code>str</code>. |
| * |
| * @param str |
| * the String to filter reads on. |
| */ |
| public Support_StringReader(String str) { |
| super(str); |
| this.str = str; |
| this.count = str.length(); |
| } |
| |
| /** |
| * This method closes this StringReader. Once it is closed, you can no |
| * longer read from it. Only the first invocation of this method has any |
| * effect. |
| * |
| */ |
| @Override |
| public void close() { |
| synchronized (lock) { |
| if (isOpen()) { |
| str = null; |
| } |
| } |
| } |
| |
| /** |
| * Answer a boolean indicating whether or not this StringReader is open. |
| */ |
| private boolean isOpen() { |
| return str != null; |
| } |
| |
| /** |
| * Set a Mark position in this Reader. The parameter <code>readLimit</code> |
| * is ignored for StringReaders. Sending reset() will reposition the reader |
| * back to the marked position provided the mark has not been invalidated. |
| * |
| * @param readlimit |
| * ignored for StringReaders. |
| * |
| * @exception java.io.IOException |
| * If an error occurs attempting mark this StringReader. |
| */ |
| @Override |
| public void mark(int readLimit) throws IOException { |
| if (readLimit >= 0) { |
| synchronized (lock) { |
| if (isOpen()) { |
| markpos = pos; |
| } else { |
| throw new IOException("StringReader is closed"); |
| } |
| } |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| /** |
| * Answers a boolean indicating whether or not this StringReader supports |
| * mark() and reset(). This method always returns true. |
| * |
| * @return <code>true</code> if mark() and reset() are supported, |
| * <code>false</code> otherwise. This implementation always |
| * returns <code>true</code>. |
| */ |
| @Override |
| public boolean markSupported() { |
| return true; |
| } |
| |
| /** |
| * Reads a single character from this StringReader and returns the result as |
| * an int. The 2 higher-order bytes are set to 0. If the end of reader was |
| * encountered then return -1. |
| * |
| * @return the character read or -1 if end of reader. |
| * |
| * @exception java.io.IOException |
| * If the StringReader is already closed. |
| */ |
| @Override |
| public int read() throws IOException { |
| synchronized (lock) { |
| if (isOpen()) { |
| if (pos != count) { |
| return str.charAt(pos++); |
| } |
| return -1; |
| } |
| throw new IOException("StringReader is closed"); |
| } |
| } |
| |
| /** |
| * Reads at most <code>count</code> characters from this StringReader and |
| * stores them at <code>offset</code> in the character array |
| * <code>buf</code>. Returns the number of characters actually read or -1 |
| * if the end of reader was encountered. |
| * |
| * @param buf |
| * character array to store the read characters |
| * @param offset |
| * offset in buf to store the read characters |
| * @param count |
| * maximum number of characters to read |
| * @return the number of characters read or -1 if end of reader. |
| * |
| * @exception java.io.IOException |
| * If the StringReader is closed. |
| */ |
| @Override |
| public int read(char buf[], int offset, int count) throws IOException { |
| // avoid int overflow |
| if (0 <= offset && offset <= buf.length && 0 <= count |
| && count <= buf.length - offset) { |
| synchronized (lock) { |
| if (isOpen()) { |
| if (pos == this.count) { |
| return -1; |
| } |
| int end = pos + count > this.count ? this.count : pos |
| + count; |
| str.getChars(pos, end, buf, offset); |
| int read = end - pos; |
| pos = end; |
| return read; |
| } |
| throw new IOException("StringReader is closed"); |
| } |
| } |
| throw new ArrayIndexOutOfBoundsException(); |
| } |
| |
| /** |
| * Answers a <code>boolean</code> indicating whether or not this |
| * StringReader is ready to be read without blocking. If the result is |
| * <code>true</code>, the next <code>read()</code> will not block. If |
| * the result is <code>false</code> this Reader may or may not block when |
| * <code>read()</code> is sent. The implementation in StringReader always |
| * returns <code>true</code> even when it has been closed. |
| * |
| * @return <code>true</code> if the receiver will not block when |
| * <code>read()</code> is called, <code>false</code> if unknown |
| * or blocking will occur. |
| * |
| * @exception java.io.IOException |
| * If an IO error occurs. |
| */ |
| @Override |
| public boolean ready() throws IOException { |
| synchronized (lock) { |
| if (isOpen()) { |
| return true; |
| } |
| throw new IOException("StringReader is closed"); |
| } |
| } |
| |
| /** |
| * Reset this StringReader's position to the last <code>mark()</code> |
| * location. Invocations of <code>read()/skip()</code> will occur from |
| * this new location. If this Reader was not marked, the StringReader is |
| * reset to the beginning of the String. |
| * |
| * @exception java.io.IOException |
| * If this StringReader has already been closed. |
| */ |
| @Override |
| public void reset() throws IOException { |
| synchronized (lock) { |
| if (isOpen()) { |
| pos = markpos != -1 ? markpos : 0; |
| } else { |
| throw new IOException("StringReader is closed"); |
| } |
| } |
| } |
| |
| /** |
| * Skips <code>count</code> number of characters in this StringReader. |
| * Subsequent <code>read()</code>'s will not return these characters |
| * unless <code>reset()</code> is used. |
| * |
| * @param count |
| * The number of characters to skip. |
| * @return the number of characters actually skipped. |
| * |
| * @exception java.io.IOException |
| * If this StringReader has already been closed. |
| */ |
| @Override |
| public long skip(long count) throws IOException { |
| synchronized (lock) { |
| if (isOpen()) { |
| if (count <= 0) { |
| return 0; |
| } |
| long skipped = 0; |
| if (count < this.count - pos) { |
| pos = pos + (int) count; |
| skipped = count; |
| } else { |
| skipped = this.count - pos; |
| pos = this.count; |
| } |
| return skipped; |
| } |
| throw new IOException("StringReader is closed"); |
| } |
| } |
| } |