Path: blob/master/src/java.base/share/classes/java/io/CharArrayReader.java
41152 views
/*1* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.io;2627import java.nio.CharBuffer;28import java.util.Objects;2930/**31* This class implements a character buffer that can be used as a32* character-input stream.33*34* @author Herb Jellinek35* @since 1.136*/37public class CharArrayReader extends Reader {38/** The character buffer. */39protected char[] buf;4041/** The current buffer position. */42protected int pos;4344/** The position of mark in buffer. */45protected int markedPos = 0;4647/**48* The index of the end of this buffer. There is not valid49* data at or beyond this index.50*/51protected int count;5253/**54* Creates a CharArrayReader from the specified array of chars.55* @param buf Input buffer (not copied)56*/57public CharArrayReader(char[] buf) {58this.buf = buf;59this.pos = 0;60this.count = buf.length;61}6263/**64* Creates a CharArrayReader from the specified array of chars.65*66* <p> The resulting reader will start reading at the given67* {@code offset}. The total number of {@code char} values that can be68* read from this reader will be either {@code length} or69* {@code buf.length-offset}, whichever is smaller.70*71* @throws IllegalArgumentException72* If {@code offset} is negative or greater than73* {@code buf.length}, or if {@code length} is negative, or if74* the sum of these two values is negative.75*76* @param buf Input buffer (not copied)77* @param offset Offset of the first char to read78* @param length Number of chars to read79*/80public CharArrayReader(char[] buf, int offset, int length) {81if ((offset < 0) || (offset > buf.length) || (length < 0) ||82((offset + length) < 0)) {83throw new IllegalArgumentException();84}85this.buf = buf;86this.pos = offset;87this.count = Math.min(offset + length, buf.length);88this.markedPos = offset;89}9091/** Checks to make sure that the stream has not been closed */92private void ensureOpen() throws IOException {93if (buf == null)94throw new IOException("Stream closed");95}9697/**98* Reads a single character.99*100* @throws IOException If an I/O error occurs101*/102public int read() throws IOException {103synchronized (lock) {104ensureOpen();105if (pos >= count)106return -1;107else108return buf[pos++];109}110}111112/**113* Reads characters into a portion of an array.114*115* <p> If {@code len} is zero, then no characters are read and {@code 0} is116* returned; otherwise, there is an attempt to read at least one character.117* If no character is available because the stream is at its end, the value118* {@code -1} is returned; otherwise, at least one character is read and119* stored into {@code cbuf}.120*121* @param cbuf {@inheritDoc}122* @param off {@inheritDoc}123* @param len {@inheritDoc}124*125* @return {@inheritDoc}126*127* @throws IndexOutOfBoundsException {@inheritDoc}128* @throws IOException {@inheritDoc}129*/130public int read(char[] cbuf, int off, int len) throws IOException {131synchronized (lock) {132ensureOpen();133Objects.checkFromIndexSize(off, len, cbuf.length);134if (len == 0) {135return 0;136}137138if (pos >= count) {139return -1;140}141142int avail = count - pos;143if (len > avail) {144len = avail;145}146if (len <= 0) {147return 0;148}149System.arraycopy(buf, pos, cbuf, off, len);150pos += len;151return len;152}153}154155@Override156public int read(CharBuffer target) throws IOException {157synchronized (lock) {158ensureOpen();159160if (pos >= count) {161return -1;162}163164int avail = count - pos;165int len = Math.min(avail, target.remaining());166target.put(buf, pos, len);167pos += len;168return len;169}170}171172/**173* Skips characters. If the stream is already at its end before this method174* is invoked, then no characters are skipped and zero is returned.175*176* <p>The {@code n} parameter may be negative, even though the177* {@code skip} method of the {@link Reader} superclass throws178* an exception in this case. If {@code n} is negative, then179* this method does nothing and returns {@code 0}.180*181* @param n {@inheritDoc}182*183* @return {@inheritDoc}184*185* @throws IOException {@inheritDoc}186*/187public long skip(long n) throws IOException {188synchronized (lock) {189ensureOpen();190191long avail = count - pos;192if (n > avail) {193n = avail;194}195if (n < 0) {196return 0;197}198pos += n;199return n;200}201}202203/**204* Tells whether this stream is ready to be read. Character-array readers205* are always ready to be read.206*207* @throws IOException If an I/O error occurs208*/209public boolean ready() throws IOException {210synchronized (lock) {211ensureOpen();212return (count - pos) > 0;213}214}215216/**217* Tells whether this stream supports the mark() operation, which it does.218*/219public boolean markSupported() {220return true;221}222223/**224* Marks the present position in the stream. Subsequent calls to reset()225* will reposition the stream to this point.226*227* @param readAheadLimit Limit on the number of characters that may be228* read while still preserving the mark. Because229* the stream's input comes from a character array,230* there is no actual limit; hence this argument is231* ignored.232*233* @throws IOException If an I/O error occurs234*/235public void mark(int readAheadLimit) throws IOException {236synchronized (lock) {237ensureOpen();238markedPos = pos;239}240}241242/**243* Resets the stream to the most recent mark, or to the beginning if it has244* never been marked.245*246* @throws IOException If an I/O error occurs247*/248public void reset() throws IOException {249synchronized (lock) {250ensureOpen();251pos = markedPos;252}253}254255/**256* Closes the stream and releases any system resources associated with257* it. Once the stream has been closed, further read(), ready(),258* mark(), reset(), or skip() invocations will throw an IOException.259* Closing a previously closed stream has no effect. This method will block260* while there is another thread blocking on the reader.261*/262public void close() {263synchronized (lock) {264buf = null;265}266}267}268269270