1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <soulng/util/BinaryReader.hpp>
  7 #include <soulng/util/Unicode.hpp>
  8 #include <soulng/util/Error.hpp>
  9 #include <cstring>
 10 
 11 namespace soulng { namespace util {
 12 
 13 using namespace soulng::unicode;
 14 
 15 BinaryReader::BinaryReader(const std::string& fileName_) :
 16     fileName(fileName_)file(fileName)begin(reinterpret_cast<const uint8_t*>(file.Begin()))end(reinterpret_cast<const uint8_t*>(file.End()))pos(0)
 17 {
 18 }
 19 
 20 BinaryReader::~BinaryReader()
 21 {
 22 }
 23 
 24 bool BinaryReader::ReadBool()
 25 {
 26     uint8_t x = ReadByte();
 27     return static_cast<bool>(x);
 28 }
 29 
 30 uint8_t BinaryReader::ReadByte()
 31 {
 32     CheckEof();
 33     uint8_t x = *begin++;
 34     ++pos;
 35     return x;
 36 }
 37 
 38 int8_t BinaryReader::ReadSByte()
 39 {
 40     uint8_t x = ReadByte();
 41     return static_cast<int8_t>(x);
 42 }
 43 
 44 uint16_t BinaryReader::ReadUShort()
 45 {
 46     uint8_t h = ReadByte();
 47     uint8_t l = ReadByte();
 48     return (static_cast<uint16_t>(h) << 8) | static_cast<uint16_t>(l);
 49 }
 50 
 51 int16_t BinaryReader::ReadShort()
 52 {
 53     uint16_t x = ReadUShort();
 54     return static_cast<int16_t>(x);
 55 }
 56 
 57 uint32_t BinaryReader::ReadUInt()
 58 {
 59     uint8_t b0 = ReadByte();
 60     uint8_t b1 = ReadByte();
 61     uint8_t b2 = ReadByte();
 62     uint8_t b3 = ReadByte();
 63     return (static_cast<uint32_t>(b0) << 24) | (static_cast<uint32_t>(b1) << 16) | (static_cast<uint32_t>(b2) << 8) | static_cast<uint32_t>(b3);
 64 }
 65 
 66 int32_t BinaryReader::ReadInt()
 67 {
 68     uint32_t x = ReadUInt();
 69     return static_cast<int32_t>(x);
 70 }
 71 
 72 uint64_t BinaryReader::ReadULong()
 73 {
 74     uint8_t b0 = ReadByte();
 75     uint8_t b1 = ReadByte();
 76     uint8_t b2 = ReadByte();
 77     uint8_t b3 = ReadByte();
 78     uint8_t b4 = ReadByte();
 79     uint8_t b5 = ReadByte();
 80     uint8_t b6 = ReadByte();
 81     uint8_t b7 = ReadByte();
 82     return (static_cast<uint64_t>(b0) << 56) | (static_cast<uint64_t>(b1) << 48) | (static_cast<uint64_t>(b2) << 40) | (static_cast<uint64_t>(b3) << 32) | (static_cast<uint64_t>(b4) << 24) | 
 83         (static_cast<uint64_t>(b5) << 16) | (static_cast<uint64_t>(b6) << 8) | static_cast<uint64_t>(b7);
 84 }
 85 
 86 int64_t BinaryReader::ReadLong()
 87 {
 88     uint64_t x = ReadULong();
 89     return static_cast<int64_t>(x);
 90 }
 91 
 92 float BinaryReader::ReadFloat()
 93 {
 94     uint32_t x = ReadUInt();
 95     return *reinterpret_cast<float*>(&x);
 96 }
 97 
 98 double BinaryReader::ReadDouble()
 99 {
100     uint64_t x = ReadULong();
101     return *reinterpret_cast<double*>(&x);
102 }
103 
104 char BinaryReader::ReadChar()
105 {
106     uint8_t x = ReadByte();
107     return static_cast<char>(x);
108 }
109 
110 char16_t BinaryReader::ReadWChar()
111 {
112     uint16_t x = ReadUShort();
113     return static_cast<char16_t>(x);
114 }
115 
116 char32_t BinaryReader::ReadUChar()
117 {
118     uint32_t x = ReadUInt();
119     return static_cast<char32_t>(x);
120 }
121 
122 std::string BinaryReader::ReadUtf8String()
123 {
124     std::string s;
125     uint8_t x = ReadByte();
126     while (x != 0)
127     {
128         s.append(1static_cast<char>(x));
129         x = ReadByte();
130     }
131     return s;
132 }
133 
134 std::u16string BinaryReader::ReadUtf16String()
135 {
136     std::string s = ReadUtf8String();
137     return ToUtf16(s);
138 }
139 
140 std::u32string BinaryReader::ReadUtf32String()
141 {
142     std::string s = ReadUtf8String();
143     return ToUtf32(s);
144 }
145 
146 uint32_t BinaryReader::ReadULEB128UInt()
147 {
148     uint32_t result = 0;
149     uint32_t shift = 0;
150     while (true)
151     {
152         uint8_t b = ReadByte();
153         result |= ((b & 0x7F) << shift);
154         if ((b & 0x80) == 0) break;
155         shift += 7;
156     }
157     return result;
158 }
159 
160 uint64_t BinaryReader::ReadULEB128ULong()
161 {
162     uint64_t result = 0;
163     uint64_t shift = 0;
164     while (true)
165     {
166         uint8_t b = ReadByte();
167         result |= ((b & 0x7F) << shift);
168         if ((b & 0x80) == 0) break;
169         shift += 7;
170     }
171     return result;
172 }
173 
174 int32_t BinaryReader::ReadSLEB128Int()
175 {
176     int32_t result = 0;
177     int32_t shift = 0;
178     uint8_t b = 0;
179     do
180     {
181         b = ReadByte();
182         result |= (b & 0x7F) << shift;
183         shift += 7;
184     }
185     while ((b & 0x80) != 0);
186     if ((shift < 32) && (b & 0x40) != 0)
187     {
188         result |= ~int32_t(0) << shift;
189     }
190     return result;
191 }
192 
193 int64_t BinaryReader::ReadSLEB128Long()
194 {
195     int64_t result = 0;
196     int64_t shift = 0;
197     uint8_t b = 0;
198     do
199     {
200         b = ReadByte();
201         result |= (b & 0x7F) << shift;
202         shift += 7;
203     }
204     while ((b & 0x80) != 0);
205     if ((shift < 64) && (b & 0x40) != 0)
206     {
207         result |= ~int64_t(0) << shift;
208     }
209     return result;
210 }
211 
212 void BinaryReader::ReadUuid(boost::uuids::uuid& uuid)
213 {
214     for (boost::uuids::uuid::value_type& x : uuid)
215     {
216         x = ReadByte();
217     }
218 }
219 
220 void BinaryReader::Skip(uint32_t size)
221 {
222     begin += size;
223     pos += size;
224 }
225 
226 void BinaryReader::CheckEof()
227 {
228     if (begin == end)
229     {
230         throw std::runtime_error("unexpected end of file '" + fileName + "'");
231     }
232 }
233 
234 } } // namespace soulng::util