1 2 // Copyright Luna & Cospec 2019. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // https://www.boost.org/LICENSE_1_0.txt) 6 7 module wsf.streams.filestream; 8 import std.stdio; 9 import wsf.streams.stream; 10 11 /** 12 A stream that reads/writes to a file 13 */ 14 class FileStream : Stream { 15 private: 16 File file; 17 size_t _length; 18 bool open = true; 19 20 public: 21 22 override { 23 @property bool canRead() { return true; } 24 @property bool canWrite() { return true; } 25 @property bool canSeek() { return true; } 26 @property bool canTell() { return true; } 27 @property bool knowsLength() { return true; } 28 @property size_t length() { return _length; } 29 @property bool eof() { return file.eof; } 30 } 31 32 this(File file) { 33 this.file = file; 34 35 // Get length of file 36 this.seek(0, StreamOrigin.End); 37 this._length = position; 38 39 // Rewind back 40 this.rewind(); 41 } 42 43 ~this() { 44 if (file.isOpen) { 45 flush(); 46 close(); 47 } 48 } 49 50 override { 51 52 int read(ref ubyte[] buffer) { 53 size_t len = file.rawRead(buffer).length; 54 55 if (file.eof) return -1; 56 return cast(int)len; 57 } 58 59 int read(size_t amount, ref ubyte[] buffer) { 60 size_t len = file.rawRead(buffer[0..amount]).length; 61 62 if (file.eof) return -1; 63 return cast(int)len; 64 } 65 66 int peek(ref ubyte[] data) { 67 68 // Seek back to origin after peek 69 ulong pos = tell(); 70 scope(exit) seek(pos, StreamOrigin.Start); 71 72 // Read and return the peek 73 return this.read(data); 74 } 75 76 void write(ubyte[] buffer) { 77 file.rawWrite(buffer); 78 } 79 80 void write(ubyte[] buffer, size_t start) { 81 file.rawWrite(buffer[start..$]); 82 } 83 84 void write(ubyte[] buffer, size_t start, size_t length) { 85 file.rawWrite(buffer[start..start+length]); 86 } 87 88 void seek(long position, StreamOrigin origin) { 89 file.seek(position, origin); 90 } 91 92 ulong tell() { 93 return file.tell(); 94 } 95 96 void flush() { 97 file.flush(); 98 file.sync(); 99 } 100 101 void rewind() { 102 file.rewind(); 103 } 104 105 void close() { 106 file.close(); 107 } 108 109 } 110 }