1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.IO
  9 {
 10     public class BinaryWriter
 11     {
 12         public nothrow BinaryWriter(const SharedPtr<ByteStream>& stream_) : stream(stream_)
 13         {
 14         }
 15         public void Write(bool x)
 16         {
 17             Write(cast<byte>(x));
 18         }
 19         public void Write(char x)
 20         {
 21             Write(cast<byte>(x));
 22         }
 23         public void Write(wchar x)
 24         {
 25             Write(cast<ushort>(x));
 26         }
 27         public void Write(uchar x)
 28         {
 29             Write(cast<uint>(x));
 30         }
 31         public void Write(sbyte x)
 32         {
 33             Write(cast<byte>(x));
 34         }
 35         public void Write(byte x)
 36         {
 37             stream->Write(x);
 38         }
 39         public void Write(short x)
 40         {
 41             Write(cast<ushort>(x));
 42         }
 43         public void Write(ushort x)
 44         {
 45             byte x0 = cast<byte>(x >> 8u);
 46             byte x1 = cast<byte>(x);
 47             Write(x0);
 48             Write(x1);
 49         }
 50         public void Write(int x)
 51         {
 52             Write(cast<uint>(x));
 53         }
 54         public void Write(uint x)
 55         {
 56             byte x0 = cast<byte>(x >> 24u);
 57             byte x1 = cast<byte>(x >> 16u);
 58             byte x2 = cast<byte>(x >> 8u);
 59             byte x3 = cast<byte>(x);
 60             Write(x0);
 61             Write(x1);
 62             Write(x2);
 63             Write(x3);
 64         }
 65         public void Write(long x)
 66         {
 67             Write(cast<ulong>(x));
 68         }
 69         public void Write(ulong x)
 70         {
 71             byte x0 = cast<byte>(x >> 56u);
 72             byte x1 = cast<byte>(x >> 48u);
 73             byte x2 = cast<byte>(x >> 40u);
 74             byte x3 = cast<byte>(x >> 32u);
 75             byte x4 = cast<byte>(x >> 24u);
 76             byte x5 = cast<byte>(x >> 16u);
 77             byte x6 = cast<byte>(x >> 8u);
 78             byte x7 = cast<byte>(x);
 79             Write(x0);
 80             Write(x1);
 81             Write(x2);
 82             Write(x3);
 83             Write(x4);
 84             Write(x5);
 85             Write(x6);
 86             Write(x7);
 87         }
 88         public void Write(float x)
 89         {
 90             void* v = &x;
 91             uint* u = cast<uint*>(v);
 92             Write(*u);
 93         }
 94         public void Write(double x)
 95         {
 96             void* v = &x;
 97             ulong* u = cast<ulong*>(v);
 98             Write(*u);
 99         }
100         public void Write(const string& x)
101         {
102             for (char c : x)
103             {
104                 Write(c);
105             }
106             Write('\0');
107         }
108         public void Write(const wstring& x)
109         {
110             Write(ToUtf8(x));
111         }
112         public void Write(const ustring& x)
113         {
114             Write(ToUtf8(x));
115         }
116         public void WriteULEB128UInt(uint x)
117         {
118             do
119             {
120                 byte b = cast<byte>(x & 0x7Fu);
121                 x = x >> 7u;
122                 if (x != 0u)
123                 {
124                     b = b | 0x80u;
125                 }
126                 Write(b);
127             }
128             while (x != 0u);
129         }
130         public void WriteULEB128ULong(ulong x)
131         {
132             do
133             {
134                 byte b = cast<byte>(x & 0x7Fu);
135                 x = x >> 7u;
136                 if (x != 0u)
137                 {
138                     b = b | 0x80u;
139                 }
140                 Write(b);
141             }
142             while (x != 0u);
143         }
144         public void WriteSLEB128Int(int x)
145         {
146             bool more = true;
147             bool negative = x < 0;
148             while (more)
149             {
150                 byte b = cast<byte>(x & 0x7F);
151                 x = x >> 7;
152                 if (negative)
153                 {
154                     x = x | (~int(0) << (32 - 7));
155                 }
156                 if (x == 0 && (b & 0x40u) == 0u || x == -1 && (b & 0x40u) != 0u)
157                 {
158                     more = false;
159                 }
160                 else
161                 {
162                     b = b | 0x80u;
163                 }
164                 Write(b);
165             }
166         }
167         public void WriteSLEB128Long(long x)
168         {
169             bool more = true;
170             bool negative = x < 0;
171             while (more)
172             {
173                 byte b = cast<byte>(x & 0x7F);
174                 x = x >> 7;
175                 if (negative)
176                 {
177                     x = x | (~long(0) << (64 - 7));
178                 }
179                 if (x == 0 && (b & 0x40u) == 0u || x == -1 && (b & 0x40u) != 0u)
180                 {
181                     more = false;
182                 }
183                 else
184                 {
185                     b = b | 0x80u;
186                 }
187                 Write(b);
188             }
189         }
190         public void Write(const Uuid& uuid)
191         {
192             for (byte b : uuid)
193             {
194                 Write(b);
195             }
196         }
197         public void Write(byte* bufferint size)
198         {
199             for (int i = 0; i < size; ++i;)
200             {
201                 Write(buffer[i]);
202             }
203         }
204         public void Seek(long posOrigin origin)
205         {
206             stream->Seek(posorigin);
207         }
208         public long Tell()
209         {
210             return stream->Tell();
211         }
212         public nothrow const SharedPtr<ByteStream>& ContainedStream()
213         {
214             return stream;
215         }
216         private SharedPtr<ByteStream> stream;
217     }
218 }