1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.IO
 10 {
 11     public class BinaryWriter : IOBase
 12     {
 13         public BinaryWriter() : base()stream(null)
 14         {
 15         }
 16         public BinaryWriter(Stream* stream_) : base()stream(stream_)
 17         {
 18         }
 19         public override ~BinaryWriter()
 20         {
 21             if (stream != null)
 22             {
 23                 stream->Flush();
 24             }
 25             long n = streams.Count();
 26             for (long i = n - 1; i >= 0; --i;)
 27             {
 28                 streams[i].Reset();
 29             }
 30         }
 31         suppress BinaryWriter(const BinaryWriter&);
 32         suppress void operator=(const BinaryWriter&);
 33         public BinaryWriter(BinaryWriter&& that) : stream(that.stream)streams(Rvalue(that.streams))
 34         {
 35             that.stream = null;
 36         }
 37         public default void operator=(BinaryWriter&&);
 38         public Stream* GetStream()
 39         {
 40             return stream;
 41         }
 42         public void SetStream(Stream* stream_)
 43         {
 44             stream = stream_;
 45         }
 46         public void Own(Stream* strm)
 47         {
 48             streams.Add(UniquePtr<Stream>(strm));
 49         }
 50         [nodiscard]
 51         public Result<bool> Write(bool x)
 52         {
 53             if (Error())
 54             {
 55                 return Result<bool>(ErrorId(GetErrorId()));
 56             }
 57             return Write(cast<byte>(x));
 58         }
 59         [nodiscard]
 60         public Result<bool> Write(char x)
 61         {
 62             if (Error())
 63             {
 64                 return Result<bool>(ErrorId(GetErrorId()));
 65             }
 66             return Write(cast<byte>(x));
 67         }
 68         [nodiscard]
 69         public Result<bool> Write(wchar x)
 70         {
 71             if (Error())
 72             {
 73                 return Result<bool>(ErrorId(GetErrorId()));
 74             }
 75             return Write(cast<ushort>(x));
 76         }
 77         [nodiscard]
 78         public Result<bool> Write(uchar x)
 79         {
 80             if (Error())
 81             {
 82                 return Result<bool>(ErrorId(GetErrorId()));
 83             }
 84             return Write(cast<uint>(x));
 85         }
 86         [nodiscard]
 87         public Result<bool> Write(sbyte x)
 88         {
 89             if (Error())
 90             {
 91                 return Result<bool>(ErrorId(GetErrorId()));
 92             }
 93             return Write(cast<byte>(x));
 94         }
 95         [nodiscard]
 96         public Result<bool> Write(byte x)
 97         {
 98             if (Error())
 99             {
100                 return Result<bool>(ErrorId(GetErrorId()));
101             }
102             if (stream == null)
103             {
104                 int errorId = RtmAllocateError("BinaryWriter.Write(byte): stream is null");
105                 SetErrorId(errorId);
106                 return Result<bool>(ErrorId(errorId));
107             }
108             auto result = stream->Write(x);
109             if (result.Error())
110             {
111                 SetErrorId(result.GetErrorId());
112             }
113             return result;
114         }
115         [nodiscard]
116         public Result<bool> Write(short x)
117         {
118             if (Error())
119             {
120                 return Result<bool>(ErrorId(GetErrorId()));
121             }
122             return Write(cast<ushort>(x));
123         }
124         [nodiscard]
125         public Result<bool> Write(ushort x)
126         {
127             if (Error())
128             {
129                 return Result<bool>(ErrorId(GetErrorId()));
130             }
131             byte x0 = cast<byte>(x >> 8u);
132             byte x1 = cast<byte>(x);
133             auto r0 = Write(x0);
134             if (r0.Error())
135             {
136                 return r0;
137             }
138             auto r1 = Write(x1);
139             if (r1.Error())
140             {
141                 return r1;
142             }
143             return Result<bool>(true);
144         }
145         [nodiscard]
146         public Result<bool> Write(int x)
147         {
148             if (Error())
149             {
150                 return Result<bool>(ErrorId(GetErrorId()));
151             }
152             return Write(cast<uint>(x));
153         }
154         [nodiscard]
155         public Result<bool> Write(uint x)
156         {
157             if (Error())
158             {
159                 return Result<bool>(ErrorId(GetErrorId()));
160             }
161             byte x0 = cast<byte>(x >> 24u);
162             byte x1 = cast<byte>(x >> 16u);
163             byte x2 = cast<byte>(x >> 8u);
164             byte x3 = cast<byte>(x);
165             auto r0 = Write(x0);
166             if (r0.Error())
167             {
168                 return r0;
169             }
170             auto r1 = Write(x1);
171             if (r1.Error())
172             {
173                 return r1;
174             }
175             auto r2 = Write(x2);
176             if (r2.Error())
177             {
178                 return r2;
179             }
180             auto r3 = Write(x3);
181             if (r3.Error())
182             {
183                 return r3;
184             }
185             return Result<bool>(true);
186         }
187         [nodiscard]
188         public Result<bool> Write(long x)
189         {
190             if (Error())
191             {
192                 return Result<bool>(ErrorId(GetErrorId()));
193             }
194             return Write(cast<ulong>(x));
195         }
196         [nodiscard]
197         public Result<bool> Write(ulong x)
198         {
199             if (Error())
200             {
201                 return Result<bool>(ErrorId(GetErrorId()));
202             }
203             byte x0 = cast<byte>(x >> 56u);
204             byte x1 = cast<byte>(x >> 48u);
205             byte x2 = cast<byte>(x >> 40u);
206             byte x3 = cast<byte>(x >> 32u);
207             byte x4 = cast<byte>(x >> 24u);
208             byte x5 = cast<byte>(x >> 16u);
209             byte x6 = cast<byte>(x >> 8u);
210             byte x7 = cast<byte>(x);
211             auto r0 = Write(x0);
212             if (r0.Error())
213             {
214                 return r0;
215             }
216             auto r1 = Write(x1);
217             if (r1.Error())
218             {
219                 return r1;
220             }
221             auto r2 = Write(x2);
222             if (r2.Error())
223             {
224                 return r2;
225             }
226             auto r3 = Write(x3);
227             if (r3.Error())
228             {
229                 return r3;
230             }
231             auto r4 = Write(x4);
232             if (r4.Error())
233             {
234                 return r4;
235             }
236             auto r5 = Write(x5);
237             if (r5.Error())
238             {
239                 return r5;
240             }
241             auto r6 = Write(x6);
242             if (r6.Error())
243             {
244                 return r6;
245             }
246             auto r7 = Write(x7);
247             if (r7.Error())
248             {
249                 return r7;
250             }
251             return Result<bool>(true);
252         }
253         [nodiscard]
254         public Result<bool> Write(float x)
255         {
256             if (Error())
257             {
258                 return Result<bool>(ErrorId(GetErrorId()));
259             }
260             void* v = &x;
261             uint* u = cast<uint*>(v);
262             return Write(*u);
263         }
264         [nodiscard]
265         public Result<bool> Write(double x)
266         {
267             if (Error())
268             {
269                 return Result<bool>(ErrorId(GetErrorId()));
270             }
271             void* v = &x;
272             ulong* u = cast<ulong*>(v);
273             return Write(*u);
274         }
275         [nodiscard]
276         public Result<bool> Write(const string& x)
277         {
278             if (Error())
279             {
280                 return Result<bool>(ErrorId(GetErrorId()));
281             }
282             for (char c : x)
283             {
284                 auto result = Write(c);
285                 if (result.Error())
286                 {
287                     return result;
288                 }
289             }
290             auto result = Write('\0');
291             if (result.Error())
292             {
293                 return result;
294             }
295             return Result<bool>(true);
296         }
297         [nodiscard]
298         public Result<bool> Write(const wstring& x)
299         {
300             if (Error())
301             {
302                 return Result<bool>(ErrorId(GetErrorId()));
303             }
304             auto result = ToUtf8(x);
305             if (result.Error())
306             {
307                 return Result<bool>(ErrorId(result.GetErrorId()));
308             }
309             return Write(result.Value());
310         }
311         [nodiscard]
312         public Result<bool> Write(const ustring& x)
313         {
314             if (Error())
315             {
316                 return Result<bool>(ErrorId(GetErrorId()));
317             }
318             auto result = ToUtf8(x);
319             if (result.Error())
320             {
321                 return Result<bool>(ErrorId(result.GetErrorId()));
322             }
323             return Write(result.Value());
324         }
325         [nodiscard]
326         public Result<bool> Write(const Uuid& uuid)
327         {
328             if (Error())
329             {
330                 return Result<bool>(ErrorId(GetErrorId()));
331             }
332             for (byte b : uuid)
333             {
334                 auto result = Write(b);
335                 if (result.Error())
336                 {
337                     return result;
338                 }
339             }
340             return Result<bool>(true);
341         }
342         [nodiscard]
343         public Result<bool> Write(byte* bufferint size)
344         {
345             if (Error())
346             {
347                 return Result<bool>(ErrorId(GetErrorId()));
348             }
349             for (int i = 0; i < size; ++i;)
350             {
351                 auto result = Write(buffer[i]);
352                 if (result.Error())
353                 {
354                     return result;
355                 }
356             }
357             return Result<bool>(true);
358         }
359         [nodiscard]
360         public Result<bool> Seek(long posOrigin origin)
361         {
362             if (Error())
363             {
364                 return Result<bool>(ErrorId(GetErrorId()));
365             }
366             if (stream == null)
367             {
368                 int errorId = RtmAllocateError("BinaryWriter.Seek: stream is null");
369                 SetErrorId(errorId);
370                 return Result<bool>(ErrorId(errorId));
371             }
372             auto result = stream->Seek(posorigin);
373             if (result.Error())
374             {
375                 SetErrorId(result.GetErrorId());
376             }
377             return result;
378         }
379         [nodiscard]
380         public Result<long> Tell()
381         {
382             if (Error())
383             {
384                 return Result<long>(ErrorId(GetErrorId()));
385             }
386             if (stream == null)
387             {
388                 int errorId = RtmAllocateError("BinaryWriter.Tell: stream is null");
389                 SetErrorId(errorId);
390                 return Result<long>(ErrorId(errorId));
391             }
392             auto result = stream->Tell();
393             if (result.Error())
394             {
395                 SetErrorId(result.GetErrorId());
396             }
397             return result;
398         }
399         private Stream* stream;
400         private List<UniquePtr<Stream>> streams;
401     }