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.Common; 13 14 import hunt.io.ByteBuffer; 15 import hunt.concurrency.CountingCallback; 16 import hunt.Exceptions; 17 import hunt.logging; 18 import hunt.util.Common; 19 20 import std.algorithm; 21 22 23 /** 24 * This abstract class is the superclass of all classes representing 25 * an input stream of bytes. 26 * 27 * <p> Applications that need to define a subclass of <code>InputStream</code> 28 * must always provide a method that returns the next byte of input. 29 * 30 * @author Arthur van Hoff 31 */ 32 abstract class InputStream : Closeable { 33 34 // MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to 35 // use when skipping. 36 private enum int MAX_SKIP_BUFFER_SIZE = 2048; 37 38 /** 39 * Reads the next byte of data from the input stream. The value byte is 40 * returned as an <code>int</code> in the range <code>0</code> to 41 * <code>255</code>. If no byte is available because the end of the stream 42 * has been reached, the value <code>-1</code> is returned. This method 43 * blocks until input data is available, the end of the stream is detected, 44 * or an exception is thrown. 45 * 46 * <p> A subclass must provide an implementation of this method. 47 * 48 * @return the next byte of data, or <code>-1</code> if the end of the 49 * stream is reached. 50 * @exception IOException if an I/O error occurs. 51 */ 52 abstract int read(); 53 54 /** 55 * Reads some number of bytes from the input stream and stores them into 56 * the buffer array <code>b</code>. The number of bytes actually read is 57 * returned as an integer. This method blocks until input data is 58 * available, end of file is detected, or an exception is thrown. 59 * 60 * <p> If the length of <code>b</code> is zero, then no bytes are read and 61 * <code>0</code> is returned; otherwise, there is an attempt to read at 62 * least one byte. If no byte is available because the stream is at the 63 * end of the file, the value <code>-1</code> is returned; otherwise, at 64 * least one byte is read and stored into <code>b</code>. 65 * 66 * <p> The first byte read is stored into element <code>b[0]</code>, the 67 * next one into <code>b[1]</code>, and so on. The number of bytes read is, 68 * at most, equal to the length of <code>b</code>. Let <i>k</i> be the 69 * number of bytes actually read; these bytes will be stored in elements 70 * <code>b[0]</code> through <code>b[</code><i>k</i><code>-1]</code>, 71 * leaving elements <code>b[</code><i>k</i><code>]</code> through 72 * <code>b[b.length-1]</code> unaffected. 73 * 74 * <p> The <code>read(b)</code> method for class <code>InputStream</code> 75 * has the same effect as: <pre><code> read(b, 0, b.length) </code></pre> 76 * 77 * @param b the buffer into which the data is read. 78 * @return the total number of bytes read into the buffer, or 79 * <code>-1</code> if there is no more data because the end of 80 * the stream has been reached. 81 * @exception IOException If the first byte cannot be read for any reason 82 * other than the end of the file, if the input stream has been closed, or 83 * if some other I/O error occurs. 84 * @exception NullPointerException if <code>b</code> is <code>null</code>. 85 * @see java.io.InputStream#read(byte[], int, int) 86 */ 87 int read(byte[] b) { 88 return read(b, 0, cast(int)b.length); 89 } 90 91 /** 92 * Reads up to <code>len</code> bytes of data from the input stream into 93 * an array of bytes. An attempt is made to read as many as 94 * <code>len</code> bytes, but a smaller number may be read. 95 * The number of bytes actually read is returned as an integer. 96 * 97 * <p> This method blocks until input data is available, end of file is 98 * detected, or an exception is thrown. 99 * 100 * <p> If <code>len</code> is zero, then no bytes are read and 101 * <code>0</code> is returned; otherwise, there is an attempt to read at 102 * least one byte. If no byte is available because the stream is at end of 103 * file, the value <code>-1</code> is returned; otherwise, at least one 104 * byte is read and stored into <code>b</code>. 105 * 106 * <p> The first byte read is stored into element <code>b[off]</code>, the 107 * next one into <code>b[off+1]</code>, and so on. The number of bytes read 108 * is, at most, equal to <code>len</code>. Let <i>k</i> be the number of 109 * bytes actually read; these bytes will be stored in elements 110 * <code>b[off]</code> through <code>b[off+</code><i>k</i><code>-1]</code>, 111 * leaving elements <code>b[off+</code><i>k</i><code>]</code> through 112 * <code>b[off+len-1]</code> unaffected. 113 * 114 * <p> In every case, elements <code>b[0]</code> through 115 * <code>b[off]</code> and elements <code>b[off+len]</code> through 116 * <code>b[b.length-1]</code> are unaffected. 117 * 118 * <p> The <code>read(b,</code> <code>off,</code> <code>len)</code> method 119 * for class <code>InputStream</code> simply calls the method 120 * <code>read()</code> repeatedly. If the first such call results in an 121 * <code>IOException</code>, that exception is returned from the call to 122 * the <code>read(b,</code> <code>off,</code> <code>len)</code> method. If 123 * any subsequent call to <code>read()</code> results in a 124 * <code>IOException</code>, the exception is caught and treated as if it 125 * were end of file; the bytes read up to that point are stored into 126 * <code>b</code> and the number of bytes read before the exception 127 * occurred is returned. The default implementation of this method blocks 128 * until the requested amount of input data <code>len</code> has been read, 129 * end of file is detected, or an exception is thrown. Subclasses are encouraged 130 * to provide a more efficient implementation of this method. 131 * 132 * @param b the buffer into which the data is read. 133 * @param off the start offset in array <code>b</code> 134 * at which the data is written. 135 * @param len the maximum number of bytes to read. 136 * @return the total number of bytes read into the buffer, or 137 * <code>-1</code> if there is no more data because the end of 138 * the stream has been reached. 139 * @exception IOException If the first byte cannot be read for any reason 140 * other than end of file, or if the input stream has been closed, or if 141 * some other I/O error occurs. 142 * @exception NullPointerException If <code>b</code> is <code>null</code>. 143 * @exception IndexOutOfBoundsException If <code>off</code> is negative, 144 * <code>len</code> is negative, or <code>len</code> is greater than 145 * <code>b.length - off</code> 146 * @see java.io.InputStream#read() 147 */ 148 int read(byte[] b, int off, int len) { 149 if (b is null) { 150 throw new NullPointerException(""); 151 } else if (off < 0 || len < 0 || len > b.length - off) { 152 throw new IndexOutOfBoundsException(""); 153 } else if (len == 0) { 154 return 0; 155 } 156 157 int c = read(); 158 if (c == -1) { 159 return -1; 160 } 161 b[off] = cast(byte)c; 162 163 int i = 1; 164 try { 165 for (; i < len ; i++) { 166 c = read(); 167 if (c == -1) { 168 break; 169 } 170 b[off + i] = cast(byte)c; 171 } 172 } catch (IOException ee) { 173 } 174 return i; 175 } 176 177 /** 178 * Skips over and discards <code>n</code> bytes of data from this input 179 * stream. The <code>skip</code> method may, for a variety of reasons, end 180 * up skipping over some smaller number of bytes, possibly <code>0</code>. 181 * This may result from any of a number of conditions; reaching end of file 182 * before <code>n</code> bytes have been skipped is only one possibility. 183 * The actual number of bytes skipped is returned. If {@code n} is 184 * negative, the {@code skip} method for class {@code InputStream} always 185 * returns 0, and no bytes are skipped. Subclasses may handle the negative 186 * value differently. 187 * 188 * <p> The <code>skip</code> method of this class creates a 189 * byte array and then repeatedly reads into it until <code>n</code> bytes 190 * have been read or the end of the stream has been reached. Subclasses are 191 * encouraged to provide a more efficient implementation of this method. 192 * For instance, the implementation may depend on the ability to seek. 193 * 194 * @param n the number of bytes to be skipped. 195 * @return the actual number of bytes skipped. 196 * @exception IOException if the stream does not support seek, 197 * or if some other I/O error occurs. 198 */ 199 long skip(long n) { 200 long remaining = n; 201 int nr; 202 203 if (n <= 0) { 204 return 0; 205 } 206 207 int size = cast(int)min(MAX_SKIP_BUFFER_SIZE, remaining); 208 byte[] skipBuffer = new byte[size]; 209 while (remaining > 0) { 210 nr = read(skipBuffer, 0, cast(int)min(size, remaining)); 211 if (nr < 0) { 212 break; 213 } 214 remaining -= nr; 215 } 216 217 return n - remaining; 218 } 219 220 /** 221 * Returns an estimate of the number of bytes that can be read (or 222 * skipped over) from this input stream without blocking by the next 223 * invocation of a method for this input stream. The next invocation 224 * might be the same thread or another thread. A single read or skip of this 225 * many bytes will not block, but may read or skip fewer bytes. 226 * 227 * <p> Note that while some implementations of {@code InputStream} will return 228 * the total number of bytes in the stream, many will not. It is 229 * never correct to use the return value of this method to allocate 230 * a buffer intended to hold all data in this stream. 231 * 232 * <p> A subclass' implementation of this method may choose to throw an 233 * {@link IOException} if this input stream has been closed by 234 * invoking the {@link #close()} method. 235 * 236 * <p> The {@code available} method for class {@code InputStream} always 237 * returns {@code 0}. 238 * 239 * <p> This method should be overridden by subclasses. 240 * 241 * @return an estimate of the number of bytes that can be read (or skipped 242 * over) from this input stream without blocking or {@code 0} when 243 * it reaches the end of the input stream. 244 * @exception IOException if an I/O error occurs. 245 */ 246 int available() { // @trusted nothrow 247 return 0; 248 } 249 250 /** 251 * Closes this input stream and releases any system resources associated 252 * with the stream. 253 * 254 * <p> The <code>close</code> method of <code>InputStream</code> does 255 * nothing. 256 * 257 * @exception IOException if an I/O error occurs. 258 */ 259 void close() {} 260 261 /** 262 * Marks the current position in this input stream. A subsequent call to 263 * the <code>reset</code> method repositions this stream at the last marked 264 * position so that subsequent reads re-read the same bytes. 265 * 266 * <p> The <code>readlimit</code> arguments tells this input stream to 267 * allow that many bytes to be read before the mark position gets 268 * invalidated. 269 * 270 * <p> The general contract of <code>mark</code> is that, if the method 271 * <code>markSupported</code> returns <code>true</code>, the stream somehow 272 * remembers all the bytes read after the call to <code>mark</code> and 273 * stands ready to supply those same bytes again if and whenever the method 274 * <code>reset</code> is called. However, the stream is not required to 275 * remember any data at all if more than <code>readlimit</code> bytes are 276 * read from the stream before <code>reset</code> is called. 277 * 278 * <p> Marking a closed stream should not have any effect on the stream. 279 * 280 * <p> The <code>mark</code> method of <code>InputStream</code> does 281 * nothing. 282 * 283 * @param readlimit the maximum limit of bytes that can be read before 284 * the mark position becomes invalid. 285 * @see java.io.InputStream#reset() 286 */ 287 void mark(int readlimit) {} 288 289 /** 290 * Repositions this stream to the position at the time the 291 * <code>mark</code> method was last called on this input stream. 292 * 293 * <p> The general contract of <code>reset</code> is: 294 * 295 * <ul> 296 * <li> If the method <code>markSupported</code> returns 297 * <code>true</code>, then: 298 * 299 * <ul><li> If the method <code>mark</code> has not been called since 300 * the stream was created, or the number of bytes read from the stream 301 * since <code>mark</code> was last called is larger than the argument 302 * to <code>mark</code> at that last call, then an 303 * <code>IOException</code> might be thrown. 304 * 305 * <li> If such an <code>IOException</code> is not thrown, then the 306 * stream is reset to a state such that all the bytes read since the 307 * most recent call to <code>mark</code> (or since the start of the 308 * file, if <code>mark</code> has not been called) will be resupplied 309 * to subsequent callers of the <code>read</code> method, followed by 310 * any bytes that otherwise would have been the next input data as of 311 * the time of the call to <code>reset</code>. </ul> 312 * 313 * <li> If the method <code>markSupported</code> returns 314 * <code>false</code>, then: 315 * 316 * <ul><li> The call to <code>reset</code> may throw an 317 * <code>IOException</code>. 318 * 319 * <li> If an <code>IOException</code> is not thrown, then the stream 320 * is reset to a fixed state that depends on the particular type of the 321 * input stream and how it was created. The bytes that will be supplied 322 * to subsequent callers of the <code>read</code> method depend on the 323 * particular type of the input stream. </ul></ul> 324 * 325 * <p>The method <code>reset</code> for class <code>InputStream</code> 326 * does nothing except throw an <code>IOException</code>. 327 * 328 * @exception IOException if this stream has not been marked or if the 329 * mark has been invalidated. 330 * @see java.io.InputStream#mark(int) 331 * @see java.io.IOException 332 */ 333 void reset() { 334 throw new IOException("mark/reset not supported"); 335 } 336 337 /** 338 * set a new position 339 */ 340 void position(int index) { 341 throw new IOException("reset not supported"); 342 } 343 344 /** 345 * Tests if this input stream supports the <code>mark</code> and 346 * <code>reset</code> methods. Whether or not <code>mark</code> and 347 * <code>reset</code> are supported is an invariant property of a 348 * particular input stream instance. The <code>markSupported</code> method 349 * of <code>InputStream</code> returns <code>false</code>. 350 * 351 * @return <code>true</code> if this stream instance supports the mark 352 * and reset methods; <code>false</code> otherwise. 353 * @see java.io.InputStream#mark(int) 354 * @see java.io.InputStream#reset() 355 */ 356 bool markSupported() { 357 return false; 358 } 359 } 360 361 362 /** 363 * This abstract class is the superclass of all classes representing 364 * an output stream of bytes. An output stream accepts output bytes 365 * and sends them to some sink. 366 * <p> 367 * Applications that need to define a subclass of 368 * <code>OutputStream</code> must always provide at least a method 369 * that writes one byte of output. 370 * 371 * @author Arthur van Hoff 372 */ 373 abstract class OutputStream : Closeable, Flushable { 374 /** 375 * Writes the specified byte to this output stream. The general 376 * contract for <code>write</code> is that one byte is written 377 * to the output stream. The byte to be written is the eight 378 * low-order bits of the argument <code>b</code>. The 24 379 * high-order bits of <code>b</code> are ignored. 380 * <p> 381 * Subclasses of <code>OutputStream</code> must provide an 382 * implementation for this method. 383 * 384 * @param b the <code>byte</code>. 385 * @exception IOException if an I/O error occurs. In particular, 386 * an <code>IOException</code> may be thrown if the 387 * output stream has been closed. 388 */ 389 abstract void write(int b) ; 390 391 void write(string b) { 392 write(cast(byte[])b, 0, cast(int)b.length); 393 } 394 395 /** 396 * Writes <code>b.length</code> bytes from the specified byte array 397 * to this output stream. The general contract for <code>write(b)</code> 398 * is that it should have exactly the same effect as the call 399 * <code>write(b, 0, b.length)</code>. 400 * 401 * @param b the data. 402 * @exception IOException if an I/O error occurs. 403 * @see java.io.OutputStream#write(byte[], int, int) 404 */ 405 void write(byte[] b) { 406 write(b, 0, cast(int)b.length); 407 } 408 409 /** 410 * Writes <code>len</code> bytes from the specified byte array 411 * starting at offset <code>off</code> to this output stream. 412 * The general contract for <code>write(b, off, len)</code> is that 413 * some of the bytes in the array <code>b</code> are written to the 414 * output stream in order; element <code>b[off]</code> is the first 415 * byte written and <code>b[off+len-1]</code> is the last byte written 416 * by this operation. 417 * <p> 418 * The <code>write</code> method of <code>OutputStream</code> calls 419 * the write method of one argument on each of the bytes to be 420 * written out. Subclasses are encouraged to override this method and 421 * provide a more efficient implementation. 422 * <p> 423 * If <code>b</code> is <code>null</code>, a 424 * <code>NullPointerException</code> is thrown. 425 * <p> 426 * If <code>off</code> is negative, or <code>len</code> is negative, or 427 * <code>off+len</code> is greater than the length of the array 428 * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown. 429 * 430 * @param b the data. 431 * @param off the start offset in the data. 432 * @param len the number of bytes to write. 433 * @exception IOException if an I/O error occurs. In particular, 434 * an <code>IOException</code> is thrown if the output 435 * stream is closed. 436 */ 437 void write(byte[] b, int off, int len) { 438 int bufferSize = cast(int)b.length; 439 if (b is null) { 440 throw new NullPointerException(""); 441 } else if ((off < 0) || (off > bufferSize) || (len < 0) || 442 ((off + len) > bufferSize) || ((off + len) < 0)) { 443 import std.format; 444 string msg = format("buffer error, size: %d, offset: %d, length: %d", 445 bufferSize, off, len); 446 throw new IndexOutOfBoundsException(msg); 447 } else if (len == 0) { 448 return; 449 } 450 for (int i = 0 ; i < len ; i++) { 451 write(b[off + i]); 452 } 453 } 454 455 /** 456 * Flushes this output stream and forces any buffered output bytes 457 * to be written out. The general contract of <code>flush</code> is 458 * that calling it is an indication that, if any bytes previously 459 * written have been buffered by the implementation of the output 460 * stream, such bytes should immediately be written to their 461 * intended destination. 462 * <p> 463 * If the intended destination of this stream is an abstraction provided by 464 * the underlying operating system, for example a file, then flushing the 465 * stream guarantees only that bytes previously written to the stream are 466 * passed to the operating system for writing; it does not guarantee that 467 * they are actually written to a physical device such as a disk drive. 468 * <p> 469 * The <code>flush</code> method of <code>OutputStream</code> does nothing. 470 * 471 * @exception IOException if an I/O error occurs. 472 */ 473 void flush() { 474 } 475 476 /** 477 * Closes this output stream and releases any system resources 478 * associated with this stream. The general contract of <code>close</code> 479 * is that it closes the output stream. A closed stream cannot perform 480 * output operations and cannot be reopened. 481 * <p> 482 * The <code>close</code> method of <code>OutputStream</code> does nothing. 483 * 484 * @exception IOException if an I/O error occurs. 485 */ 486 void close() { 487 } 488 489 } 490 491 /** 492 * IO Utilities. Provides stream handling utilities in singleton Threadpool 493 * implementation accessed by static members. 494 */ 495 // class IO { 496 497 // enum string CRLF = "\015\012"; 498 499 // enum byte[] CRLF_BYTES = [ '\015', '\012' ]; 500 501 // enum int bufferSize = 64 * 1024; 502 503 // /** 504 // * Closes an arbitrary closable, and logs exceptions at ignore level 505 // * 506 // * @param closeable 507 // * the closeable to close 508 // */ 509 // static void close(Closeable closeable) { 510 // try { 511 // if (closeable !is null) 512 // closeable.close(); 513 // } catch (IOException ignore) { 514 // } 515 // } 516 // } 517 518 519 // interface BufferReaderHandler { 520 // void readBuffer(ByteBuffer buf, CountingCallback countingCallback, long count); 521 // }