67 */
68 protected int pos;
69
70 /**
71 * Check to make sure that this stream has not been closed
72 */
73 private void ensureOpen() throws IOException {
74 if (in == null)
75 throw new IOException("Stream closed");
76 }
77
78 /**
79 * Creates a <code>PushbackInputStream</code>
80 * with a pushback buffer of the specified <code>size</code>,
81 * and saves its argument, the input stream
82 * <code>in</code>, for later use. Initially,
83 * the pushback buffer is empty.
84 *
85 * @param in the input stream from which bytes will be read.
86 * @param size the size of the pushback buffer.
87 * @exception IllegalArgumentException if {@code size <= 0}
88 * @since 1.1
89 */
90 public PushbackInputStream(InputStream in, int size) {
91 super(in);
92 if (size <= 0) {
93 throw new IllegalArgumentException("size <= 0");
94 }
95 this.buf = new byte[size];
96 this.pos = size;
97 }
98
99 /**
100 * Creates a <code>PushbackInputStream</code>
101 * with a 1-byte pushback buffer, and saves its argument, the input stream
102 * <code>in</code>, for later use. Initially,
103 * the pushback buffer is empty.
104 *
105 * @param in the input stream from which bytes will be read.
106 */
107 public PushbackInputStream(InputStream in) {
108 this(in, 1);
109 }
110
111 /**
112 * Reads the next byte of data from this input stream. The value
113 * byte is returned as an <code>int</code> in the range
114 * <code>0</code> to <code>255</code>. If no byte is available
115 * because the end of the stream has been reached, the value
116 * <code>-1</code> is returned. This method blocks until input data
117 * is available, the end of the stream is detected, or an exception
118 * is thrown.
119 *
120 * <p> This method returns the most recently pushed-back byte, if there is
121 * one, and otherwise calls the <code>read</code> method of its underlying
122 * input stream and returns whatever value that method returns.
123 *
124 * @return the next byte of data, or <code>-1</code> if the end of the
125 * stream has been reached.
126 * @exception IOException if this input stream has been closed by
127 * invoking its {@link #close()} method,
128 * or an I/O error occurs.
129 * @see java.io.InputStream#read()
130 */
131 public int read() throws IOException {
132 ensureOpen();
133 if (pos < buf.length) {
134 return buf[pos++] & 0xff;
135 }
136 return super.read();
137 }
138
139 /**
140 * Reads up to <code>len</code> bytes of data from this input stream into
141 * an array of bytes. This method first reads any pushed-back bytes; after
142 * that, if fewer than <code>len</code> bytes have been read then it
143 * reads from the underlying input stream. If <code>len</code> is not zero, the method
144 * blocks until at least 1 byte of input is available; otherwise, no
145 * bytes are read and <code>0</code> is returned.
146 *
147 * @param b the buffer into which the data is read.
148 * @param off the start offset in the destination array <code>b</code>
149 * @param len the maximum number of bytes read.
150 * @return the total number of bytes read into the buffer, or
151 * <code>-1</code> if there is no more data because the end of
152 * the stream has been reached.
153 * @exception NullPointerException If <code>b</code> is <code>null</code>.
154 * @exception IndexOutOfBoundsException If <code>off</code> is negative,
155 * <code>len</code> is negative, or <code>len</code> is greater than
156 * <code>b.length - off</code>
157 * @exception IOException if this input stream has been closed by
158 * invoking its {@link #close()} method,
159 * or an I/O error occurs.
160 * @see java.io.InputStream#read(byte[], int, int)
161 */
162 public int read(byte[] b, int off, int len) throws IOException {
163 ensureOpen();
164 if (b == null) {
165 throw new NullPointerException();
166 } else if (off < 0 || len < 0 || len > b.length - off) {
167 throw new IndexOutOfBoundsException();
168 } else if (len == 0) {
169 return 0;
170 }
171
172 int avail = buf.length - pos;
173 if (avail > 0) {
174 if (len < avail) {
175 avail = len;
176 }
177 System.arraycopy(buf, pos, b, off, avail);
179 off += avail;
180 len -= avail;
181 }
182 if (len > 0) {
183 len = super.read(b, off, len);
184 if (len == -1) {
185 return avail == 0 ? -1 : avail;
186 }
187 return avail + len;
188 }
189 return avail;
190 }
191
192 /**
193 * Pushes back a byte by copying it to the front of the pushback buffer.
194 * After this method returns, the next byte to be read will have the value
195 * <code>(byte)b</code>.
196 *
197 * @param b the <code>int</code> value whose low-order
198 * byte is to be pushed back.
199 * @exception IOException If there is not enough room in the pushback
200 * buffer for the byte, or this input stream has been closed by
201 * invoking its {@link #close()} method.
202 */
203 public void unread(int b) throws IOException {
204 ensureOpen();
205 if (pos == 0) {
206 throw new IOException("Push back buffer is full");
207 }
208 buf[--pos] = (byte)b;
209 }
210
211 /**
212 * Pushes back a portion of an array of bytes by copying it to the front
213 * of the pushback buffer. After this method returns, the next byte to be
214 * read will have the value <code>b[off]</code>, the byte after that will
215 * have the value <code>b[off+1]</code>, and so forth.
216 *
217 * @param b the byte array to push back.
218 * @param off the start offset of the data.
219 * @param len the number of bytes to push back.
220 * @exception NullPointerException If <code>b</code> is <code>null</code>.
221 * @exception IOException If there is not enough room in the pushback
222 * buffer for the specified number of bytes,
223 * or this input stream has been closed by
224 * invoking its {@link #close()} method.
225 * @since 1.1
226 */
227 public void unread(byte[] b, int off, int len) throws IOException {
228 ensureOpen();
229 if (len > pos) {
230 throw new IOException("Push back buffer is full");
231 }
232 pos -= len;
233 System.arraycopy(b, off, buf, pos, len);
234 }
235
236 /**
237 * Pushes back an array of bytes by copying it to the front of the
238 * pushback buffer. After this method returns, the next byte to be read
239 * will have the value <code>b[0]</code>, the byte after that will have the
240 * value <code>b[1]</code>, and so forth.
241 *
242 * @param b the byte array to push back
243 * @exception NullPointerException If <code>b</code> is <code>null</code>.
244 * @exception IOException If there is not enough room in the pushback
245 * buffer for the specified number of bytes,
246 * or this input stream has been closed by
247 * invoking its {@link #close()} method.
248 * @since 1.1
249 */
250 public void unread(byte[] b) throws IOException {
251 unread(b, 0, b.length);
252 }
253
254 /**
255 * Returns an estimate of the number of bytes that can be read (or
256 * skipped over) from this input stream without blocking by the next
257 * invocation of a method for this input stream. The next invocation might be
258 * the same thread or another thread. A single read or skip of this
259 * many bytes will not block, but may read or skip fewer bytes.
260 *
261 * <p> The method returns the sum of the number of bytes that have been
262 * pushed back and the value returned by {@link
263 * java.io.FilterInputStream#available available}.
264 *
265 * @return the number of bytes that can be read (or skipped over) from
266 * the input stream without blocking.
267 * @exception IOException if this input stream has been closed by
268 * invoking its {@link #close()} method,
269 * or an I/O error occurs.
270 * @see java.io.FilterInputStream#in
271 * @see java.io.InputStream#available()
272 */
273 public int available() throws IOException {
274 ensureOpen();
275 int n = buf.length - pos;
276 int avail = super.available();
277 return n > (Integer.MAX_VALUE - avail)
278 ? Integer.MAX_VALUE
279 : n + avail;
280 }
281
282 /**
283 * Skips over and discards <code>n</code> bytes of data from this
284 * input stream. The <code>skip</code> method may, for a variety of
285 * reasons, end up skipping over some smaller number of bytes,
286 * possibly zero. If <code>n</code> is negative, no bytes are skipped.
287 *
338 * Marks the current position in this input stream.
339 *
340 * <p> The <code>mark</code> method of <code>PushbackInputStream</code>
341 * does nothing.
342 *
343 * @param readlimit the maximum limit of bytes that can be read before
344 * the mark position becomes invalid.
345 * @see java.io.InputStream#reset()
346 */
347 public synchronized void mark(int readlimit) {
348 }
349
350 /**
351 * Repositions this stream to the position at the time the
352 * <code>mark</code> method was last called on this input stream.
353 *
354 * <p> The method <code>reset</code> for class
355 * <code>PushbackInputStream</code> does nothing except throw an
356 * <code>IOException</code>.
357 *
358 * @exception IOException if this method is invoked.
359 * @see java.io.InputStream#mark(int)
360 * @see java.io.IOException
361 */
362 public synchronized void reset() throws IOException {
363 throw new IOException("mark/reset not supported");
364 }
365
366 /**
367 * Closes this input stream and releases any system resources
368 * associated with the stream.
369 * Once the stream has been closed, further read(), unread(),
370 * available(), reset(), or skip() invocations will throw an IOException.
371 * Closing a previously closed stream has no effect.
372 *
373 * @exception IOException if an I/O error occurs.
374 */
375 public synchronized void close() throws IOException {
376 if (in == null)
377 return;
378 in.close();
379 in = null;
380 buf = null;
381 }
382 }
|
67 */
68 protected int pos;
69
70 /**
71 * Check to make sure that this stream has not been closed
72 */
73 private void ensureOpen() throws IOException {
74 if (in == null)
75 throw new IOException("Stream closed");
76 }
77
78 /**
79 * Creates a <code>PushbackInputStream</code>
80 * with a pushback buffer of the specified <code>size</code>,
81 * and saves its argument, the input stream
82 * <code>in</code>, for later use. Initially,
83 * the pushback buffer is empty.
84 *
85 * @param in the input stream from which bytes will be read.
86 * @param size the size of the pushback buffer.
87 * @throws IllegalArgumentException if {@code size <= 0}
88 * @since 1.1
89 */
90 public PushbackInputStream(InputStream in, int size) {
91 super(in);
92 if (size <= 0) {
93 throw new IllegalArgumentException("size <= 0");
94 }
95 this.buf = new byte[size];
96 this.pos = size;
97 }
98
99 /**
100 * Creates a <code>PushbackInputStream</code>
101 * with a 1-byte pushback buffer, and saves its argument, the input stream
102 * <code>in</code>, for later use. Initially,
103 * the pushback buffer is empty.
104 *
105 * @param in the input stream from which bytes will be read.
106 */
107 public PushbackInputStream(InputStream in) {
108 this(in, 1);
109 }
110
111 /**
112 * Reads the next byte of data from this input stream. The value
113 * byte is returned as an <code>int</code> in the range
114 * <code>0</code> to <code>255</code>. If no byte is available
115 * because the end of the stream has been reached, the value
116 * <code>-1</code> is returned. This method blocks until input data
117 * is available, the end of the stream is detected, or an exception
118 * is thrown.
119 *
120 * <p> This method returns the most recently pushed-back byte, if there is
121 * one, and otherwise calls the <code>read</code> method of its underlying
122 * input stream and returns whatever value that method returns.
123 *
124 * @return the next byte of data, or <code>-1</code> if the end of the
125 * stream has been reached.
126 * @throws IOException if this input stream has been closed by
127 * invoking its {@link #close()} method,
128 * or an I/O error occurs.
129 * @see java.io.InputStream#read()
130 */
131 public int read() throws IOException {
132 ensureOpen();
133 if (pos < buf.length) {
134 return buf[pos++] & 0xff;
135 }
136 return super.read();
137 }
138
139 /**
140 * Reads up to <code>len</code> bytes of data from this input stream into
141 * an array of bytes. This method first reads any pushed-back bytes; after
142 * that, if fewer than <code>len</code> bytes have been read then it
143 * reads from the underlying input stream. If <code>len</code> is not zero, the method
144 * blocks until at least 1 byte of input is available; otherwise, no
145 * bytes are read and <code>0</code> is returned.
146 *
147 * @param b the buffer into which the data is read.
148 * @param off the start offset in the destination array <code>b</code>
149 * @param len the maximum number of bytes read.
150 * @return the total number of bytes read into the buffer, or
151 * <code>-1</code> if there is no more data because the end of
152 * the stream has been reached.
153 * @throws NullPointerException If <code>b</code> is <code>null</code>.
154 * @throws IndexOutOfBoundsException If <code>off</code> is negative,
155 * <code>len</code> is negative, or <code>len</code> is greater than
156 * <code>b.length - off</code>
157 * @throws IOException if this input stream has been closed by
158 * invoking its {@link #close()} method,
159 * or an I/O error occurs.
160 * @see java.io.InputStream#read(byte[], int, int)
161 */
162 public int read(byte[] b, int off, int len) throws IOException {
163 ensureOpen();
164 if (b == null) {
165 throw new NullPointerException();
166 } else if (off < 0 || len < 0 || len > b.length - off) {
167 throw new IndexOutOfBoundsException();
168 } else if (len == 0) {
169 return 0;
170 }
171
172 int avail = buf.length - pos;
173 if (avail > 0) {
174 if (len < avail) {
175 avail = len;
176 }
177 System.arraycopy(buf, pos, b, off, avail);
179 off += avail;
180 len -= avail;
181 }
182 if (len > 0) {
183 len = super.read(b, off, len);
184 if (len == -1) {
185 return avail == 0 ? -1 : avail;
186 }
187 return avail + len;
188 }
189 return avail;
190 }
191
192 /**
193 * Pushes back a byte by copying it to the front of the pushback buffer.
194 * After this method returns, the next byte to be read will have the value
195 * <code>(byte)b</code>.
196 *
197 * @param b the <code>int</code> value whose low-order
198 * byte is to be pushed back.
199 * @throws IOException If there is not enough room in the pushback
200 * buffer for the byte, or this input stream has been closed by
201 * invoking its {@link #close()} method.
202 */
203 public void unread(int b) throws IOException {
204 ensureOpen();
205 if (pos == 0) {
206 throw new IOException("Push back buffer is full");
207 }
208 buf[--pos] = (byte)b;
209 }
210
211 /**
212 * Pushes back a portion of an array of bytes by copying it to the front
213 * of the pushback buffer. After this method returns, the next byte to be
214 * read will have the value <code>b[off]</code>, the byte after that will
215 * have the value <code>b[off+1]</code>, and so forth.
216 *
217 * @param b the byte array to push back.
218 * @param off the start offset of the data.
219 * @param len the number of bytes to push back.
220 * @throws NullPointerException If <code>b</code> is <code>null</code>.
221 * @throws IOException If there is not enough room in the pushback
222 * buffer for the specified number of bytes,
223 * or this input stream has been closed by
224 * invoking its {@link #close()} method.
225 * @since 1.1
226 */
227 public void unread(byte[] b, int off, int len) throws IOException {
228 ensureOpen();
229 if (len > pos) {
230 throw new IOException("Push back buffer is full");
231 }
232 pos -= len;
233 System.arraycopy(b, off, buf, pos, len);
234 }
235
236 /**
237 * Pushes back an array of bytes by copying it to the front of the
238 * pushback buffer. After this method returns, the next byte to be read
239 * will have the value <code>b[0]</code>, the byte after that will have the
240 * value <code>b[1]</code>, and so forth.
241 *
242 * @param b the byte array to push back
243 * @throws NullPointerException If <code>b</code> is <code>null</code>.
244 * @throws IOException If there is not enough room in the pushback
245 * buffer for the specified number of bytes,
246 * or this input stream has been closed by
247 * invoking its {@link #close()} method.
248 * @since 1.1
249 */
250 public void unread(byte[] b) throws IOException {
251 unread(b, 0, b.length);
252 }
253
254 /**
255 * Returns an estimate of the number of bytes that can be read (or
256 * skipped over) from this input stream without blocking by the next
257 * invocation of a method for this input stream. The next invocation might be
258 * the same thread or another thread. A single read or skip of this
259 * many bytes will not block, but may read or skip fewer bytes.
260 *
261 * <p> The method returns the sum of the number of bytes that have been
262 * pushed back and the value returned by {@link
263 * java.io.FilterInputStream#available available}.
264 *
265 * @return the number of bytes that can be read (or skipped over) from
266 * the input stream without blocking.
267 * @throws IOException if this input stream has been closed by
268 * invoking its {@link #close()} method,
269 * or an I/O error occurs.
270 * @see java.io.FilterInputStream#in
271 * @see java.io.InputStream#available()
272 */
273 public int available() throws IOException {
274 ensureOpen();
275 int n = buf.length - pos;
276 int avail = super.available();
277 return n > (Integer.MAX_VALUE - avail)
278 ? Integer.MAX_VALUE
279 : n + avail;
280 }
281
282 /**
283 * Skips over and discards <code>n</code> bytes of data from this
284 * input stream. The <code>skip</code> method may, for a variety of
285 * reasons, end up skipping over some smaller number of bytes,
286 * possibly zero. If <code>n</code> is negative, no bytes are skipped.
287 *
338 * Marks the current position in this input stream.
339 *
340 * <p> The <code>mark</code> method of <code>PushbackInputStream</code>
341 * does nothing.
342 *
343 * @param readlimit the maximum limit of bytes that can be read before
344 * the mark position becomes invalid.
345 * @see java.io.InputStream#reset()
346 */
347 public synchronized void mark(int readlimit) {
348 }
349
350 /**
351 * Repositions this stream to the position at the time the
352 * <code>mark</code> method was last called on this input stream.
353 *
354 * <p> The method <code>reset</code> for class
355 * <code>PushbackInputStream</code> does nothing except throw an
356 * <code>IOException</code>.
357 *
358 * @throws IOException if this method is invoked.
359 * @see java.io.InputStream#mark(int)
360 * @see java.io.IOException
361 */
362 public synchronized void reset() throws IOException {
363 throw new IOException("mark/reset not supported");
364 }
365
366 /**
367 * Closes this input stream and releases any system resources
368 * associated with the stream.
369 * Once the stream has been closed, further read(), unread(),
370 * available(), reset(), or skip() invocations will throw an IOException.
371 * Closing a previously closed stream has no effect.
372 *
373 * @throws IOException if an I/O error occurs.
374 */
375 public synchronized void close() throws IOException {
376 if (in == null)
377 return;
378 in.close();
379 in = null;
380 buf = null;
381 }
382 }
|