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