Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package java.io;
     27 
     28 /**
     29  * This class implements a character buffer that can be used as a
     30  * character-input stream.
     31  *
     32  * @author      Herb Jellinek
     33  * @since       JDK1.1
     34  */
     35 public class CharArrayReader extends Reader {
     36     /** The character buffer. */
     37     protected char buf[];
     38 
     39     /** The current buffer position. */
     40     protected int pos;
     41 
     42     /** The position of mark in buffer. */
     43     protected int markedPos = 0;
     44 
     45     /**
     46      *  The index of the end of this buffer.  There is not valid
     47      *  data at or beyond this index.
     48      */
     49     protected int count;
     50 
     51     /**
     52      * Creates a CharArrayReader from the specified array of chars.
     53      * @param buf       Input buffer (not copied)
     54      */
     55     public CharArrayReader(char buf[]) {
     56         this.buf = buf;
     57         this.pos = 0;
     58         this.count = buf.length;
     59     }
     60 
     61     /**
     62      * Creates a CharArrayReader from the specified array of chars.
     63      *
     64      * <p> The resulting reader will start reading at the given
     65      * <tt>offset</tt>.  The total number of <tt>char</tt> values that can be
     66      * read from this reader will be either <tt>length</tt> or
     67      * <tt>buf.length-offset</tt>, whichever is smaller.
     68      *
     69      * @throws IllegalArgumentException
     70      *         If <tt>offset</tt> is negative or greater than
     71      *         <tt>buf.length</tt>, or if <tt>length</tt> is negative, or if
     72      *         the sum of these two values is negative.
     73      *
     74      * @param buf       Input buffer (not copied)
     75      * @param offset    Offset of the first char to read
     76      * @param length    Number of chars to read
     77      */
     78     public CharArrayReader(char buf[], int offset, int length) {
     79         if ((offset < 0) || (offset > buf.length) || (length < 0) ||
     80             ((offset + length) < 0)) {
     81             throw new IllegalArgumentException();
     82         }
     83         this.buf = buf;
     84         this.pos = offset;
     85         this.count = Math.min(offset + length, buf.length);
     86         this.markedPos = offset;
     87     }
     88 
     89     /** Checks to make sure that the stream has not been closed */
     90     private void ensureOpen() throws IOException {
     91         if (buf == null)
     92             throw new IOException("Stream closed");
     93     }
     94 
     95     /**
     96      * Reads a single character.
     97      *
     98      * @exception   IOException  If an I/O error occurs
     99      */
    100     public int read() throws IOException {
    101         synchronized (lock) {
    102             ensureOpen();
    103             if (pos >= count)
    104                 return -1;
    105             else
    106                 return buf[pos++];
    107         }
    108     }
    109 
    110     /**
    111      * Reads characters into a portion of an array.
    112      * @param b  Destination buffer
    113      * @param off  Offset at which to start storing characters
    114      * @param len   Maximum number of characters to read
    115      * @return  The actual number of characters read, or -1 if
    116      *          the end of the stream has been reached
    117      *
    118      * @exception   IOException  If an I/O error occurs
    119      */
    120     public int read(char b[], int off, int len) throws IOException {
    121         synchronized (lock) {
    122             ensureOpen();
    123             if ((off < 0) || (off > b.length) || (len < 0) ||
    124                 ((off + len) > b.length) || ((off + len) < 0)) {
    125                 throw new IndexOutOfBoundsException();
    126             } else if (len == 0) {
    127                 return 0;
    128             }
    129 
    130             if (pos >= count) {
    131                 return -1;
    132             }
    133             if (pos + len > count) {
    134                 len = count - pos;
    135             }
    136             if (len <= 0) {
    137                 return 0;
    138             }
    139             System.arraycopy(buf, pos, b, off, len);
    140             pos += len;
    141             return len;
    142         }
    143     }
    144 
    145     /**
    146      * Skips characters.  Returns the number of characters that were skipped.
    147      *
    148      * <p>The <code>n</code> parameter may be negative, even though the
    149      * <code>skip</code> method of the {@link Reader} superclass throws
    150      * an exception in this case. If <code>n</code> is negative, then
    151      * this method does nothing and returns <code>0</code>.
    152      *
    153      * @param n The number of characters to skip
    154      * @return       The number of characters actually skipped
    155      * @exception  IOException If the stream is closed, or an I/O error occurs
    156      */
    157     public long skip(long n) throws IOException {
    158         synchronized (lock) {
    159             ensureOpen();
    160             if (pos + n > count) {
    161                 n = count - pos;
    162             }
    163             if (n < 0) {
    164                 return 0;
    165             }
    166             pos += n;
    167             return n;
    168         }
    169     }
    170 
    171     /**
    172      * Tells whether this stream is ready to be read.  Character-array readers
    173      * are always ready to be read.
    174      *
    175      * @exception  IOException  If an I/O error occurs
    176      */
    177     public boolean ready() throws IOException {
    178         synchronized (lock) {
    179             ensureOpen();
    180             return (count - pos) > 0;
    181         }
    182     }
    183 
    184     /**
    185      * Tells whether this stream supports the mark() operation, which it does.
    186      */
    187     public boolean markSupported() {
    188         return true;
    189     }
    190 
    191     /**
    192      * Marks the present position in the stream.  Subsequent calls to reset()
    193      * will reposition the stream to this point.
    194      *
    195      * @param  readAheadLimit  Limit on the number of characters that may be
    196      *                         read while still preserving the mark.  Because
    197      *                         the stream's input comes from a character array,
    198      *                         there is no actual limit; hence this argument is
    199      *                         ignored.
    200      *
    201      * @exception  IOException  If an I/O error occurs
    202      */
    203     public void mark(int readAheadLimit) throws IOException {
    204         synchronized (lock) {
    205             ensureOpen();
    206             markedPos = pos;
    207         }
    208     }
    209 
    210     /**
    211      * Resets the stream to the most recent mark, or to the beginning if it has
    212      * never been marked.
    213      *
    214      * @exception  IOException  If an I/O error occurs
    215      */
    216     public void reset() throws IOException {
    217         synchronized (lock) {
    218             ensureOpen();
    219             pos = markedPos;
    220         }
    221     }
    222 
    223     /**
    224      * Closes the stream and releases any system resources associated with
    225      * it.  Once the stream has been closed, further read(), ready(),
    226      * mark(), reset(), or skip() invocations will throw an IOException.
    227      * Closing a previously closed stream has no effect.
    228      */
    229     public void close() {
    230         buf = null;
    231     }
    232 }
    233