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 }