1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.stream.FilterInputStream;
13 
14 import hunt.stream.Common;
15 import hunt.Exceptions;
16 
17 version(HUNT_DEBUG) {
18     import hunt.logging;
19 }
20 
21 /**
22  * A <code>FilterInputStream</code> contains
23  * some other input stream, which it uses as
24  * its  basic source of data, possibly transforming
25  * the data along the way or providing  additional
26  * functionality. The class <code>FilterInputStream</code>
27  * itself simply overrides all  methods of
28  * <code>InputStream</code> with versions that
29  * pass all requests to the contained  input
30  * stream. Subclasses of <code>FilterInputStream</code>
31  * may further override some of  these methods
32  * and may also provide additional methods
33  * and fields.
34  *
35  * @author  Jonathan Payne
36  */
37 class FilterInputStream : InputStream {
38     /**
39      * The input stream to be filtered.
40      */
41     protected InputStream inputStream;
42 
43     /**
44      * Creates a <code>FilterInputStream</code>
45      * by assigning the  argument <code>inputStream</code>
46      * to the field <code>this.inputStream</code> so as
47      * to remember it for later use.
48      *
49      * @param   inputStream   the underlying input stream, or <code>null</code> if
50      *          this instance is to be created without an underlying stream.
51      */
52     protected this(InputStream inputStream) {
53         this.inputStream = inputStream;
54     }
55 
56     /**
57      * Reads the next byte of data from this input stream. The value
58      * byte is returned as an <code>int</code> in the range
59      * <code>0</code> to <code>255</code>. If no byte is available
60      * because the end of the stream has been reached, the value
61      * <code>-1</code> is returned. This method blocks until input data
62      * is available, the end of the stream is detected, or an exception
63      * is thrown.
64      * <p>
65      * This method
66      * simply performs <code>inputStream.read()</code> and returns the result.
67      *
68      * @return     the next byte of data, or <code>-1</code> if the end of the
69      *             stream is reached.
70      * @exception  IOException  if an I/O error occurs.
71      * @see        java.io.FilterInputStream#inputStream
72      */
73     override int read() {
74         return inputStream.read();
75     }
76 
77     /**
78      * Reads up to <code>b.length</code> bytes of data from this
79      * input stream into an array of bytes. This method blocks until some
80      * input is available.
81      * <p>
82      * This method simply performs the call
83      * <code>read(b, 0, b.length)</code> and returns
84      * the  result. It is important that it does
85      * <i>not</i> do <code>inputStream.read(b)</code> instead;
86      * certain subclasses of  <code>FilterInputStream</code>
87      * depend on the implementation strategy actually
88      * used.
89      *
90      * @param      b   the buffer into which the data is read.
91      * @return     the total number of bytes read into the buffer, or
92      *             <code>-1</code> if there is no more data because the end of
93      *             the stream has been reached.
94      * @exception  IOException  if an I/O error occurs.
95      * @see        java.io.FilterInputStream#read(byte[], int, int)
96      */
97     override int read(byte[] b) {
98         return read(b, 0, cast(int)b.length);
99     }
100 
101     /**
102      * Reads up to <code>len</code> bytes of data from this input stream
103      * into an array of bytes. If <code>len</code> is not zero, the method
104      * blocks until some input is available; otherwise, no
105      * bytes are read and <code>0</code> is returned.
106      * <p>
107      * This method simply performs <code>inputStream.read(b, off, len)</code>
108      * and returns the result.
109      *
110      * @param      b     the buffer into which the data is read.
111      * @param      off   the start offset inputStream the destination array <code>b</code>
112      * @param      len   the maximum number of bytes read.
113      * @return     the total number of bytes read into the buffer, or
114      *             <code>-1</code> if there is no more data because the end of
115      *             the stream has been reached.
116      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
117      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
118      * <code>len</code> is negative, or <code>len</code> is greater than
119      * <code>b.length - off</code>
120      * @exception  IOException  if an I/O error occurs.
121      * @see        java.io.FilterInputStream#inputStream
122      */
123     override int read(byte[] b, int off, int len) {
124         return inputStream.read(b, off, len);
125     }
126 
127     /**
128      * Skips over and discards <code>n</code> bytes of data from the
129      * input stream. The <code>skip</code> method may, for a variety of
130      * reasons, end up skipping over some smaller number of bytes,
131      * possibly <code>0</code>. The actual number of bytes skipped is
132      * returned.
133      * <p>
134      * This method simply performs <code>inputStream.skip(n)</code>.
135      *
136      * @param      n   the number of bytes to be skipped.
137      * @return     the actual number of bytes skipped.
138      * @throws     IOException  if {@code inputStream.skip(n)} throws an IOException.
139      */
140     override long skip(long n) {
141         return inputStream.skip(n);
142     }
143 
144     /**
145      * Returns an estimate of the number of bytes that can be read (or
146      * skipped over) from this input stream without blocking by the next
147      * caller of a method for this input stream. The next caller might be
148      * the same thread or another thread.  A single read or skip of this
149      * many bytes will not block, but may read or skip fewer bytes.
150      * <p>
151      * This method returns the result of {@link #inputStream inputStream}.available().
152      *
153      * @return     an estimate of the number of bytes that can be read (or skipped
154      *             over) from this input stream without blocking.
155      * @exception  IOException  if an I/O error occurs.
156      */
157     override int available() {
158         return inputStream.available();
159     }
160 
161     /**
162      * Closes this input stream and releases any system resources
163      * associated with the stream.
164      * This
165      * method simply performs <code>inputStream.close()</code>.
166      *
167      * @exception  IOException  if an I/O error occurs.
168      * @see        java.io.FilterInputStream#inputStream
169      */
170     override void close() {
171         inputStream.close();
172     }
173 
174     /**
175      * Marks the current position in this input stream. A subsequent
176      * call to the <code>reset</code> method repositions this stream at
177      * the last marked position so that subsequent reads re-read the same bytes.
178      * <p>
179      * The <code>readlimit</code> argument tells this input stream to
180      * allow that many bytes to be read before the mark position gets
181      * invalidated.
182      * <p>
183      * This method simply performs <code>inputStream.mark(readlimit)</code>.
184      *
185      * @param   readlimit   the maximum limit of bytes that can be read before
186      *                      the mark position becomes invalid.
187      * @see     java.io.FilterInputStream#inputStream
188      * @see     java.io.FilterInputStream#reset()
189      */
190     override void mark(int readlimit) {
191         inputStream.mark(readlimit);
192     }
193 
194     /**
195      * Repositions this stream to the position at the time the
196      * <code>mark</code> method was last called on this input stream.
197      * <p>
198      * This method
199      * simply performs <code>inputStream.reset()</code>.
200      * <p>
201      * Stream marks are intended to be used in
202      * situations where you need to read ahead a little to see what's in
203      * the stream. Often this is most easily done by invoking some
204      * general parser. If the stream is of the type handled by the
205      * parse, it just chugs along happily. If the stream is not of
206      * that type, the parser should toss an exception when it fails.
207      * If this happens within readlimit bytes, it allows the outer
208      * code to reset the stream and try another parser.
209      *
210      * @exception  IOException  if the stream has not been marked or if the
211      *               mark has been invalidated.
212      * @see        java.io.FilterInputStream#inputStream
213      * @see        java.io.FilterInputStream#mark(int)
214      */
215     override void reset() {
216         inputStream.reset();
217     }
218 
219     /**
220      * Tests if this input stream supports the <code>mark</code>
221      * and <code>reset</code> methods.
222      * This method
223      * simply performs <code>inputStream.markSupported()</code>.
224      *
225      * @return  <code>true</code> if this stream type supports the
226      *          <code>mark</code> and <code>reset</code> method;
227      *          <code>false</code> otherwise.
228      * @see     java.io.FilterInputStream#inputStream
229      * @see     java.io.InputStream#mark(int)
230      * @see     java.io.InputStream#reset()
231      */
232     override bool markSupported() {
233         return inputStream.markSupported();
234     }
235 }