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 }