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