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.ByteArrayInputStream; 13 14 import hunt.io.Common; 15 16 import hunt.Exceptions; 17 import std.algorithm; 18 19 20 /** 21 * A <code>ByteArrayInputStream</code> contains 22 * an internal buffer that contains bytes that 23 * may be read from the stream. An internal 24 * counter keeps track of the next byte to 25 * be supplied by the <code>read</code> method. 26 * <p> 27 * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in 28 * this class can be called after the stream has been closed without 29 * generating an <tt>IOException</tt>. 30 * 31 */ 32 class ByteArrayInputStream : InputStream { 33 34 /** 35 * An array of bytes that was provided 36 * by the creator of the stream. Elements <code>buf[0]</code> 37 * through <code>buf[count-1]</code> are the 38 * only bytes that can ever be read from the 39 * stream; element <code>buf[pos]</code> is 40 * the next byte to be read. 41 */ 42 protected byte[] buf; 43 44 /** 45 * The index of the next character to read from the input stream buffer. 46 * This value should always be nonnegative 47 * and not larger than the value of <code>count</code>. 48 * The next byte to be read from the input stream buffer 49 * will be <code>buf[pos]</code>. 50 */ 51 protected int pos; 52 53 /** 54 * The currently marked position in the stream. 55 * ByteArrayInputStream objects are marked at position zero by 56 * default when constructed. They may be marked at another 57 * position within the buffer by the <code>mark()</code> method. 58 * The current buffer position is set to this point by the 59 * <code>reset()</code> method. 60 * <p> 61 * If no mark has been set, then the value of mark is the offset 62 * passed to the constructor (or 0 if the offset was not supplied). 63 * 64 * @since JDK1.1 65 */ 66 protected int _mark = 0; 67 68 /** 69 * The index one greater than the last valid character in the input 70 * stream buffer. 71 * This value should always be nonnegative 72 * and not larger than the length of <code>buf</code>. 73 * It is one greater than the position of 74 * the last byte within <code>buf</code> that 75 * can ever be read from the input stream buffer. 76 */ 77 protected int count; 78 79 alias read = InputStream.read; 80 81 /** 82 * Creates a <code>ByteArrayInputStream</code> 83 * so that it uses <code>buf</code> as its 84 * buffer array. 85 * The buffer array is not copied. 86 * The initial value of <code>pos</code> 87 * is <code>0</code> and the initial value 88 * of <code>count</code> is the length of 89 * <code>buf</code>. 90 * 91 * @param buf the input buffer. 92 */ 93 this(byte[] buf) { 94 this.buf = buf; 95 this.pos = 0; 96 this.count = cast(int)buf.length; 97 } 98 99 /** 100 * Creates <code>ByteArrayInputStream</code> 101 * that uses <code>buf</code> as its 102 * buffer array. The initial value of <code>pos</code> 103 * is <code>offset</code> and the initial value 104 * of <code>count</code> is the minimum of <code>offset+length</code> 105 * and <code>buf.length</code>. 106 * The buffer array is not copied. The buffer's mark is 107 * set to the specified offset. 108 * 109 * @param buf the input buffer. 110 * @param offset the offset in the buffer of the first byte to read. 111 * @param length the maximum number of bytes to read from the buffer. 112 */ 113 this(byte[] buf, int offset, size_t length) { 114 this.buf = buf; 115 this.pos = offset; 116 this.count = cast(int) min(offset + length, buf.length); 117 this._mark = offset; 118 } 119 120 byte[] getRawBuffer() 121 { 122 return buf; 123 } 124 125 /** 126 * Reads the next byte of data from this input stream. The value 127 * byte is returned as an <code>int</code> in the range 128 * <code>0</code> to <code>255</code>. If no byte is available 129 * because the end of the stream has been reached, the value 130 * <code>-1</code> is returned. 131 * <p> 132 * This <code>read</code> method 133 * cannot block. 134 * 135 * @return the next byte of data, or <code>-1</code> if the end of the 136 * stream has been reached. 137 */ 138 override int read() { 139 return (pos < count) ? (buf[pos++] & 0xff) : -1; 140 } 141 142 /** 143 * Reads up to <code>len</code> bytes of data into an array of bytes 144 * from this input stream. 145 * If <code>pos</code> equals <code>count</code>, 146 * then <code>-1</code> is returned to indicate 147 * end of file. Otherwise, the number <code>k</code> 148 * of bytes read is equal to the smaller of 149 * <code>len</code> and <code>count-pos</code>. 150 * If <code>k</code> is positive, then bytes 151 * <code>buf[pos]</code> through <code>buf[pos+k-1]</code> 152 * are copied into <code>b[off]</code> through 153 * <code>b[off+k-1]</code> in the manner performed 154 * by <code>System.arraycopy</code>. The 155 * value <code>k</code> is added into <code>pos</code> 156 * and <code>k</code> is returned. 157 * <p> 158 * This <code>read</code> method cannot block. 159 * 160 * @param b the buffer into which the data is read. 161 * @param off the start offset in the destination array <code>b</code> 162 * @param len the maximum number of bytes read. 163 * @return the total number of bytes read into the buffer, or 164 * <code>-1</code> if there is no more data because the end of 165 * the stream has been reached. 166 * @exception NullPointerException If <code>b</code> is <code>null</code>. 167 * @exception IndexOutOfBoundsException If <code>off</code> is negative, 168 * <code>len</code> is negative, or <code>len</code> is greater than 169 * <code>b.length - off</code> 170 */ 171 override int read(byte[] b, int off, int len) { 172 if (b is null) { 173 throw new NullPointerException(""); 174 } else if (off < 0 || len < 0 || len > b.length - off) { 175 throw new IndexOutOfBoundsException(""); 176 } 177 178 if (pos >= count) { 179 return -1; 180 } 181 182 int avail = count - pos; 183 if (len > avail) { 184 len = avail; 185 } 186 if (len <= 0) { 187 return 0; 188 } 189 // System.arraycopy(buf, pos, b, off, len); 190 b[off .. off+len] = buf[pos .. pos+len]; 191 pos += len; 192 return len; 193 } 194 195 /** 196 * Skips <code>n</code> bytes of input from this input stream. Fewer 197 * bytes might be skipped if the end of the input stream is reached. 198 * The actual number <code>k</code> 199 * of bytes to be skipped is equal to the smaller 200 * of <code>n</code> and <code>count-pos</code>. 201 * The value <code>k</code> is added into <code>pos</code> 202 * and <code>k</code> is returned. 203 * 204 * @param n the number of bytes to be skipped. 205 * @return the actual number of bytes skipped. 206 */ 207 override long skip(long n) { 208 long k = count - pos; 209 if (n < k) { 210 k = n < 0 ? 0 : n; 211 } 212 213 pos += k; 214 return k; 215 } 216 217 /** 218 * Returns the number of remaining bytes that can be read (or skipped over) 219 * from this input stream. 220 * <p> 221 * The value returned is <code>count - pos</code>, 222 * which is the number of bytes remaining to be read from the input buffer. 223 * 224 * @return the number of remaining bytes that can be read (or skipped 225 * over) from this input stream without blocking. 226 */ 227 override int available() @trusted nothrow { 228 return count - pos; 229 } 230 231 /** 232 * Tests if this <code>InputStream</code> supports mark/reset. The 233 * <code>markSupported</code> method of <code>ByteArrayInputStream</code> 234 * always returns <code>true</code>. 235 * 236 * @since JDK1.1 237 */ 238 override bool markSupported() { 239 return true; 240 } 241 242 /** 243 * Set the current marked position in the stream. 244 * ByteArrayInputStream objects are marked at position zero by 245 * default when constructed. They may be marked at another 246 * position within the buffer by this method. 247 * <p> 248 * If no mark has been set, then the value of the mark is the 249 * offset passed to the constructor (or 0 if the offset was not 250 * supplied). 251 * 252 * <p> Note: The <code>readAheadLimit</code> for this class 253 * has no meaning. 254 * 255 * @since JDK1.1 256 */ 257 override void mark(int readAheadLimit) { 258 _mark = pos; 259 } 260 261 /** 262 * Resets the buffer to the marked position. The marked position 263 * is 0 unless another position was marked or an offset was specified 264 * in the constructor. 265 */ 266 override void reset() { 267 pos = _mark; 268 } 269 270 /** 271 * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in 272 * this class can be called after the stream has been closed without 273 * generating an <tt>IOException</tt>. 274 */ 275 // void close(){ 276 // } 277 278 }