1
2
3
4
5
6 using System;
7
8 namespace System.IO
9 {
10 public class IOBuffer
11 {
12 public IOBuffer(long size_) : size(size_), mem(MemAlloc(size)) {}
13 suppress IOBuffer(const IOBuffer&);
14 suppress void operator=(const IOBuffer&);
15 public IOBuffer(IOBuffer&& that) : size(that.size), mem(that.mem)
16 {
17 that.size = 0;
18 that.mem = null;
19 }
20 public default void operator=(IOBuffer&& that);
21 public ~IOBuffer()
22 {
23 if (mem != null)
24 {
25 RtmMemFree(mem);
26 }
27 }
28 public inline long Size() const
29 {
30 return size;
31 }
32 public inline void* Mem() const
33 {
34 return mem;
35 }
36 public inline byte operator[](long index) const
37 {
38 #assert(index >= 0 && index < size);
39 return cast<byte*>(mem)[index];
40 }
41 public inline byte& operator[](long index)
42 {
43 #assert(index >= 0 && index < size);
44 return cast<byte*>(mem)[index];
45 }
46 private long size;
47 private void* mem;
48 }
49
50 public class BufferedStream : Stream
51 {
52 public BufferedStream() : base(), baseStream(null), buffer(), pos(buffer.Size()), bytesAvailable(0), end(0)
53 {
54 }
55 public explicit BufferedStream(Stream* baseStream_) : this(baseStream_, 4096)
56 {
57 }
58 public BufferedStream(Stream* baseStream_, long bufferSize_) : base(), baseStream(baseStream_), buffer(bufferSize_), pos(buffer.Size()), bytesAvailable(0), end(0)
59 {
60 }
61 public Stream* BaseStream()
62 {
63 return baseStream;
64 }
65 suppress BufferedStream(const BufferedStream&);
66 suppress void operator=(const BufferedStream&);
67 public BufferedStream(BufferedStream&& that) : baseStream(that.baseStream), buffer(Rvalue(that.buffer)), pos(that.pos), bytesAvailable(that.bytesAvailable), end(that.end)
68 {
69 that.baseStream = null;
70 }
71 public default void operator=(BufferedStream&&);
72 public override ~BufferedStream()
73 {
74 if (baseStream != null)
75 {
76 Flush();
77 }
78 }
79 [nodiscard]
80 public override Result<int> ReadByte()
81 {
82 auto flushResult = Flush();
83 if (flushResult.Error())
84 {
85 SetErrorId(flushResult.GetErrorId());
86 return Result<int>(ErrorId(flushResult.GetErrorId()));
87 }
88 if (bytesAvailable == 0)
89 {
90 auto fillResult = FillBuf();
91 if (fillResult.Error())
92 {
93 SetErrorId(fillResult.GetErrorId());
94 return Result<int>(ErrorId(fillResult.GetErrorId()));
95 }
96 if (bytesAvailable == 0)
97 {
98 return Result<int>(-1);
99 }
100 }
101 byte value = buffer[pos++];
102 --bytesAvailable;
103 return Result<int>(value);
104 }
105 [nodiscard]
106 public override Result<long> Read(byte* buf, long count)
107 {
108 if (count < 0)
109 {
110 int errorId = RtmAllocateError("BufferedStream.Read: count less than zero");
111 SetErrorId(errorId);
112 return Result<long>(ErrorId(errorId));
113 }
114 auto flushResult = Flush();
115 if (flushResult.Error())
116 {
117 SetErrorId(flushResult.GetErrorId());
118 return Result<long>(ErrorId(flushResult.GetErrorId()));
119 }
120 if (bytesAvailable == 0)
121 {
122 auto fillResult = FillBuf();
123 if (fillResult.Error())
124 {
125 SetErrorId(fillResult.GetErrorId());
126 return Result<long>(ErrorId(fillResult.GetErrorId()));
127 }
128 }
129 long bytesRead = 0;
130 long n = Min(bytesAvailable, count);
131 for (long i = 0; i < n; ++i;)
132 {
133 buf[i] = buffer[pos++];
134 ++bytesRead;
135 --bytesAvailable;
136 }
137 return Result<long>(bytesRead);
138 }
139 [nodiscard]
140 public override Result<bool> Write(byte x)
141 {
142 if (end >= buffer.Size())
143 {
144 auto flushResult = Flush();
145 if (flushResult.Error())
146 {
147 SetErrorId(flushResult.GetErrorId());
148 return Result<bool>(ErrorId(flushResult.GetErrorId()));
149 }
150 }
151 buffer[end++] = x;
152 return Result<bool>(true);
153 }
154 [nodiscard]
155 public override Result<bool> Write(byte* buf, long count)
156 {
157 if (count < 0)
158 {
159 int errorId = RtmAllocateError("BufferedStream.Write: count less than zero");
160 SetErrorId(errorId);
161 return Result<bool>(ErrorId(errorId));
162 }
163 for (long i = 0; i < count; ++i;)
164 {
165 auto result = Write(buf[i]);
166 if (result.Error())
167 {
168 SetErrorId(result.GetErrorId());
169 return result;
170 }
171 }
172 return Result<bool>(true);
173 }
174 public override Result<bool> Flush()
175 {
176 if (end != 0)
177 {
178 if (baseStream == null)
179 {
180 int errorId = RtmAllocateError("BufferedStream.Flush: base stream is null");
181 SetErrorId(errorId);
182 return Result<bool>(ErrorId(errorId));
183 }
184 auto writeResult = baseStream->Write(cast<byte*>(buffer.Mem()), end);
185 if (writeResult.Error())
186 {
187 SetErrorId(writeResult.GetErrorId());
188 return Result<bool>(ErrorId(writeResult.GetErrorId()));
189 }
190 auto flushResult = baseStream->Flush();
191 if (flushResult.Error())
192 {
193 SetErrorId(flushResult.GetErrorId());
194 return Result<bool>(ErrorId(flushResult.GetErrorId()));
195 }
196 end = 0;
197 }
198 return Result<bool>(true);
199 }
200 [nodiscard]
201 public override Result<bool> Seek(long pos, Origin origin)
202 {
203 auto flushResult = Flush();
204 if (flushResult.Error())
205 {
206 SetErrorId(flushResult.GetErrorId());
207 return Result<bool>(ErrorId(flushResult.GetErrorId()));
208 }
209 bytesAvailable = 0;
210 if (baseStream == null)
211 {
212 int errorId = RtmAllocateError("BufferedStream.Seek: base stream is null");
213 SetErrorId(errorId);
214 return Result<bool>(ErrorId(errorId));
215 }
216 auto seekResult = baseStream->Seek(pos, origin);
217 if (seekResult.Error())
218 {
219 SetErrorId(seekResult.GetErrorId());
220 return seekResult;
221 }
222 return Result<bool>(true);
223 }
224 [nodiscard]
225 public override Result<long> Tell()
226 {
227 auto flushResult = Flush();
228 if (flushResult.Error())
229 {
230 SetErrorId(flushResult.GetErrorId());
231 return Result<long>(ErrorId(flushResult.GetErrorId()));
232 }
233 if (baseStream == null)
234 {
235 int errorId = RtmAllocateError("BufferedStream.Tell: base stream is null");
236 SetErrorId(errorId);
237 return Result<long>(ErrorId(errorId));
238 }
239 Result<long> tellResult = baseStream->Tell();
240 if (tellResult.Error())
241 {
242 SetErrorId(tellResult.GetErrorId());
243 return tellResult;
244 }
245 return Result<long>(tellResult.Value() - bytesAvailable);
246 }
247 [nodiscard]
248 private Result<bool> FillBuf()
249 {
250 if (baseStream == null)
251 {
252 int errorId = RtmAllocateError("BufferedStream.FillBuf: base stream is null");
253 SetErrorId(errorId);
254 return Result<bool>(ErrorId(errorId));
255 }
256 Result<long> readResult = baseStream->Read(cast<byte*>(buffer.Mem()), buffer.Size());
257 if (readResult.Error())
258 {
259 SetErrorId(readResult.GetErrorId());
260 return Result<bool>(ErrorId(readResult.GetErrorId()));
261 }
262 bytesAvailable = readResult.Value();
263 pos = 0;
264 return Result<bool>(true);
265 }
266 private Stream* baseStream;
267 private IOBuffer buffer;
268 private long pos;
269 private long bytesAvailable;
270 private long end;
271 }