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 }