14ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/*
24ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Licensed to the Apache Software Foundation (ASF) under one or more
34ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * contributor license agreements.  See the NOTICE file distributed with
44ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * this work for additional information regarding copyright ownership.
54ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * The ASF licenses this file to You under the Apache License, Version 2.0
64ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * (the "License"); you may not use this file except in compliance with
74ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * the License.  You may obtain a copy of the License at
84ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
94ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      http://www.apache.org/licenses/LICENSE-2.0
104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Unless required by applicable law or agreed to in writing, software
124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * See the License for the specific language governing permissions and
154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * limitations under the License.
164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapackage org.apache.commons.io.input;
184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.EOFException;
204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.IOException;
214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.InputStream;
224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/**
244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * A functional, light weight {@link InputStream} that emulates
254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * a stream of a specified size.
264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <p>
274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * This implementation provides a light weight
284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * object for testing with an {@link InputStream}
294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * where the contents don't matter.
304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <p>
314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * One use case would be for testing the handling of
324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * large {@link InputStream} as it can emulate that
334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * scenario without the overhead of actually processing
344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * large numbers of bytes - significantly speeding up
354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * test execution times.
364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <p>
374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * This implementation returns zero from the method that
384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * reads a byte and leaves the array unchanged in the read
394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * methods that are passed a byte array.
404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * If alternative data is required the <code>processByte()</code> and
414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <code>processBytes()</code> methods can be implemented to generate
424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * data, for example:
434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <pre>
454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *  public class TestInputStream extends NullInputStream {
464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      public TestInputStream(int size) {
474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *          super(size);
484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      }
494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      protected int processByte() {
504ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *          return ... // return required value here
514ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      }
524ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      protected void processBytes(byte[] bytes, int offset, int length) {
534ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *          for (int i = offset; i < length; i++) {
544ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *              bytes[i] = ... // set array value here
554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *          }
564ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      }
574ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *  }
584ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * </pre>
594ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
604ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @since Commons IO 1.3
614ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @version $Revision: 463529 $
624ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
634ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapublic class NullInputStream extends InputStream {
644ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
654ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private long size;
664ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private long position;
674ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private long mark = -1;
684ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private long readlimit;
694ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private boolean eof;
704ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private boolean throwEofException;
714ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private boolean markSupported;
724ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
734ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
744ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Create an {@link InputStream} that emulates a specified size
754ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * which supports marking and does not throw EOFException.
764ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
774ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param size The size of the input stream to emulate.
784ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
794ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public NullInputStream(long size) {
804ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira       this(size, true, false);
814ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
824ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
834ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
844ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Create an {@link InputStream} that emulates a specified
854ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * size with option settings.
864ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
874ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param size The size of the input stream to emulate.
884ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param markSupported Whether this instance will support
894ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * the <code>mark()</code> functionality.
904ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param throwEofException Whether this implementation
914ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * will throw an {@link EOFException} or return -1 when the
924ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * end of file is reached.
934ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
944ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public NullInputStream(long size, boolean markSupported, boolean throwEofException) {
954ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira       this.size = size;
964ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira       this.markSupported = markSupported;
974ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira       this.throwEofException = throwEofException;
984ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
994ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1004ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1014ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Return the current position.
1024ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1034ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return the current position.
1044ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1054ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public long getPosition() {
1064ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return position;
1074ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1084ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1094ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Return the size this {@link InputStream} emulates.
1114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The size of the input stream to emulate.
1134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public long getSize() {
1154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return size;
1164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Return the number of bytes that can be read.
1204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The number of bytes that can be read.
1224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int available() {
1244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        long avail = size - position;
1254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (avail <= 0) {
1264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return 0;
1274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        } else if (avail > Integer.MAX_VALUE) {
1284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return Integer.MAX_VALUE;
1294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        } else {
1304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return (int)avail;
1314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Close this input stream - resets the internal state to
1364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * the initial values.
1374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException If an error occurs.
1394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public void close() throws IOException {
1414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        eof = false;
1424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        position = 0;
1434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        mark = -1;
1444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Mark the current position.
1484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param readlimit The number of bytes before this marked position
1504ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * is invalid.
1514ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws UnsupportedOperationException if mark is not supported.
1524ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1534ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public synchronized void mark(int readlimit) {
1544ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (!markSupported) {
1554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new UnsupportedOperationException("Mark not supported");
1564ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1574ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        mark = position;
1584ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        this.readlimit = readlimit;
1594ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1604ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1614ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1624ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Indicates whether <i>mark</i> is supported.
1634ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1644ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return Whether <i>mark</i> is supported or not.
1654ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1664ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public boolean markSupported() {
1674ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return markSupported;
1684ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1694ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1704ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1714ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Read a byte.
1724ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1734ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return Either The byte value returned by <code>processByte()</code>
1744ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * or <code>-1</code> if the end of file has been reached and
1754ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>false</code>.
1764ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws EOFException if the end of file is reached and
1774ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>true</code>.
1784ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if trying to read past the end of file.
1794ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1804ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read() throws IOException {
1814ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (eof) {
1824ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IOException("Read after end of file");
1834ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1844ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (position == size) {
1854ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return doEndOfFile();
1864ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1874ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        position++;
1884ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return processByte();
1894ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1904ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1914ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1924ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Read some bytes into the specified array.
1934ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1944ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param bytes The byte array to read into
1954ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The number of bytes read or <code>-1</code>
1964ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * if the end of file has been reached and
1974ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>false</code>.
1984ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws EOFException if the end of file is reached and
1994ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>true</code>.
2004ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if trying to read past the end of file.
2014ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
2024ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read(byte[] bytes) throws IOException {
2034ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return read(bytes, 0, bytes.length);
2044ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
2054ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
2064ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
2074ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Read the specified number bytes into an array.
2084ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
2094ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param bytes The byte array to read into.
2104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param offset The offset to start reading bytes into.
2114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param length The number of bytes to read.
2124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The number of bytes read or <code>-1</code>
2134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * if the end of file has been reached and
2144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>false</code>.
2154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws EOFException if the end of file is reached and
2164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>true</code>.
2174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if trying to read past the end of file.
2184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
2194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read(byte[] bytes, int offset, int length) throws IOException {
2204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (eof) {
2214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IOException("Read after end of file");
2224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (position == size) {
2244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return doEndOfFile();
2254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        position += length;
2274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        int returnLength = length;
2284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (position > size) {
2294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            returnLength = length - (int)(position - size);
2304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            position = size;
2314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        processBytes(bytes, offset, returnLength);
2334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return returnLength;
2344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
2354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
2364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
2374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Reset the stream to the point when mark was last called.
2384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
2394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws UnsupportedOperationException if mark is not supported.
2404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException If no position has been marked
2414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * or the read limit has been exceed since the last position was
2424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * marked.
2434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
2444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public synchronized void reset() throws IOException {
2454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (!markSupported) {
2464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new UnsupportedOperationException("Mark not supported");
2474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (mark < 0) {
2494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IOException("No position has been marked");
2504ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2514ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (position > (mark + readlimit)) {
2524ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IOException("Marked position [" + mark +
2534ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    "] is no longer valid - passed the read limit [" +
2544ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    readlimit + "]");
2554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2564ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        position = mark;
2574ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        eof = false;
2584ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
2594ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
2604ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
2614ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Skip a specified number of bytes.
2624ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
2634ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param numberOfBytes The number of bytes to skip.
2644ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The number of bytes skipped or <code>-1</code>
2654ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * if the end of file has been reached and
2664ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>false</code>.
2674ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws EOFException if the end of file is reached and
2684ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <code>throwEofException</code> is set to <code>true</code>.
2694ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws IOException if trying to read past the end of file.
2704ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
2714ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public long skip(long numberOfBytes) throws IOException {
2724ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (eof) {
2734ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IOException("Skip after end of file");
2744ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2754ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (position == size) {
2764ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return doEndOfFile();
2774ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2784ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        position += numberOfBytes;
2794ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        long returnLength = numberOfBytes;
2804ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (position > size) {
2814ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            returnLength = numberOfBytes - (position - size);
2824ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            position = size;
2834ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
2844ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return returnLength;
2854ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
2864ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
2874ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
2884ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Return a byte value for the  <code>read()</code> method.
2894ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <p>
2904ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * This implementation returns zero.
2914ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
2924ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return This implementation always returns zero.
2934ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
2944ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    protected int processByte() {
2954ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        // do nothing - overridable by subclass
2964ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return 0;
2974ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
2984ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
2994ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
3004ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Process the bytes for the <code>read(byte[], offset, length)</code>
3014ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * method.
3024ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * <p>
3034ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * This implementation leaves the byte array unchanged.
3044ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
3054ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param bytes The byte array
3064ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param offset The offset to start at.
3074ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param length The number of bytes.
3084ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
3094ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    protected void processBytes(byte[] bytes, int offset, int length) {
3104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        // do nothing - overridable by subclass
3114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
3124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
3134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
3144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Handle End of File.
3154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
3164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return <code>-1</code> if <code>throwEofException</code> is
3174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * set to <code>false</code>
3184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @throws EOFException if <code>throwEofException</code> is set
3194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * to <code>true</code>.
3204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
3214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private int doEndOfFile() throws EOFException {
3224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        eof = true;
3234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (throwEofException) {
3244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new EOFException();
3254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
3264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return -1;
3274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
3284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
3294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira}
330