1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2000,2008 Oracle.  All rights reserved.
5 *
6 * $Id: FastInputStream.java,v 12.8 2008/01/08 20:58:39 bostic Exp $
7 */
8
9package com.sleepycat.util;
10
11import java.io.IOException;
12import java.io.InputStream;
13
14/**
15 * A replacement for ByteArrayInputStream that does not synchronize every
16 * byte read.
17 *
18 * <p>This class extends {@link InputStream} and its <code>read()</code>
19 * methods allow it to be used as a standard input stream.  In addition, it
20 * provides <code>readFast()</code> methods that are not declared to throw
21 * <code>IOException</code>.  <code>IOException</code> is never thrown by this
22 * class.</p>
23 *
24 * @author Mark Hayes
25 */
26public class FastInputStream extends InputStream {
27
28    protected int len;
29    protected int off;
30    protected int mark;
31    protected byte[] buf;
32
33    /**
34     * Creates an input stream.
35     *
36     * @param buffer the data to read.
37     */
38    public FastInputStream(byte[] buffer) {
39
40        buf = buffer;
41        len = buffer.length;
42    }
43
44    /**
45     * Creates an input stream.
46     *
47     * @param buffer the data to read.
48     *
49     * @param offset the byte offset at which to begin reading.
50     *
51     * @param length the number of bytes to read.
52     */
53    public FastInputStream(byte[] buffer, int offset, int length) {
54
55        buf = buffer;
56        off = offset;
57        len = offset + length;
58    }
59
60    // --- begin ByteArrayInputStream compatible methods ---
61
62    public int available() {
63
64        return len - off;
65    }
66
67    public boolean markSupported() {
68
69        return true;
70    }
71
72    public void mark(int readLimit) {
73
74        mark = off;
75    }
76
77    public void reset() {
78
79        off = mark;
80    }
81
82    public long skip(long count) {
83
84        int myCount = (int) count;
85        if (myCount + off > len) {
86            myCount = len - off;
87        }
88        skipFast(myCount);
89        return myCount;
90    }
91
92    public int read() throws IOException {
93
94        return readFast();
95    }
96
97    public int read(byte[] toBuf) throws IOException {
98
99        return readFast(toBuf, 0, toBuf.length);
100    }
101
102    public int read(byte[] toBuf, int offset, int length) throws IOException {
103
104        return readFast(toBuf, offset, length);
105    }
106
107    // --- end ByteArrayInputStream compatible methods ---
108
109    /**
110     * Equivalent to <code>skip()<code> but takes an int parameter instead of a
111     * long, and does not check whether the count given is larger than the
112     * number of remaining bytes.
113     * @see #skip(long)
114     */
115    public final void skipFast(int count) {
116        off += count;
117    }
118
119    /**
120     * Equivalent to <code>read()<code> but does not throw
121     * <code>IOException</code>.
122     * @see #read()
123     */
124    public final int readFast() {
125
126        return (off < len) ? (buf[off++] & 0xff) : (-1);
127    }
128
129    /**
130     * Equivalent to <code>read(byte[])<code> but does not throw
131     * <code>IOException</code>.
132     * @see #read(byte[])
133     */
134    public final int readFast(byte[] toBuf) {
135
136        return readFast(toBuf, 0, toBuf.length);
137    }
138
139    /**
140     * Equivalent to <code>read(byte[],int,int)<code> but does not throw
141     * <code>IOException</code>.
142     * @see #read(byte[],int,int)
143     */
144    public final int readFast(byte[] toBuf, int offset, int length) {
145
146        int avail = len - off;
147        if (avail <= 0) {
148            return -1;
149        }
150        if (length > avail) {
151            length = avail;
152        }
153        System.arraycopy(buf, off, toBuf, offset, length);
154        off += length;
155        return length;
156    }
157
158    /**
159     * Returns the underlying data being read.
160     *
161     * @return the underlying data.
162     */
163    public final byte[] getBufferBytes() {
164
165        return buf;
166    }
167
168    /**
169     * Returns the offset at which data is being read from the buffer.
170     *
171     * @return the offset at which data is being read.
172     */
173    public final int getBufferOffset() {
174
175        return off;
176    }
177
178    /**
179     * Returns the end of the buffer being read.
180     *
181     * @return the end of the buffer.
182     */
183    public final int getBufferLength() {
184
185        return len;
186    }
187}
188