source: OniSplit/BinaryReader.cs@ 1174

Last change on this file since 1174 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 11.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Text;
5using Oni.Imaging;
6
7namespace Oni
8{
9 internal sealed class BinaryReader : IDisposable
10 {
11 #region Private data
12 private static readonly byte[] seekBuffer = new byte[512];
13 private static readonly Encoding encoding = Encoding.UTF8;
14 private const float rotationAngleScale = MathHelper.Pi / 32767.5f;
15
16 private FileStream stream;
17 private byte[] buffer;
18 private bool bigEndian;
19 private InstanceFile instanceFile;
20 #endregion
21
22 public BinaryReader(string filePath)
23 {
24 this.buffer = new byte[8];
25 this.stream = File.OpenRead(filePath);
26 }
27
28 public BinaryReader(string filePath, bool bigEndian)
29 : this(filePath)
30 {
31 this.bigEndian = bigEndian;
32 }
33
34 public BinaryReader(string filePath, InstanceFile instanceFile)
35 : this(filePath)
36 {
37 this.instanceFile = instanceFile;
38 }
39
40 public void Dispose()
41 {
42 if (stream != null)
43 stream.Dispose();
44
45 stream = null;
46 buffer = null;
47 }
48
49 public string Name => stream.Name;
50
51 public int Length => (int)stream.Length;
52
53 public int Position
54 {
55 get
56 {
57 return (int)stream.Position;
58 }
59 set
60 {
61 int currentPosition = (int)stream.Position;
62 int delta = value - currentPosition;
63
64 if (delta == 0)
65 return;
66
67 if (delta > 0 && delta <= seekBuffer.Length)
68 stream.Read(seekBuffer, 0, delta);
69 else
70 stream.Position = value;
71 }
72 }
73
74 public void Skip(int length)
75 {
76 Position += length;
77 }
78
79 public void SkipCString()
80 {
81 for (int b = 1; b != 0 && b != -1; b = stream.ReadByte())
82 ;
83 }
84
85 public int Read(byte[] buffer, int offset, int length)
86 {
87 return stream.Read(buffer, offset, length);
88 }
89
90 public byte[] ReadBytes(int length)
91 {
92 var buffer = new byte[length];
93 int offset = 0;
94
95 while (length > 0)
96 {
97 int read = stream.Read(buffer, offset, length);
98
99 if (read == 0)
100 break;
101
102 offset += read;
103 length -= read;
104 }
105
106 if (offset != buffer.Length)
107 {
108 var result = new byte[offset];
109 Buffer.BlockCopy(buffer, 0, result, 0, offset);
110 buffer = result;
111 }
112
113 return buffer;
114 }
115
116 public byte ReadByte()
117 {
118 int value = stream.ReadByte();
119
120 if (value == -1)
121 throw new EndOfStreamException();
122
123 return (byte)value;
124 }
125
126 public bool ReadBoolean()
127 {
128 return (ReadByte() != 0);
129 }
130
131 public ushort ReadUInt16()
132 {
133 FillBuffer(2);
134
135 if (bigEndian)
136 {
137 return (ushort)(buffer[1] | buffer[0] << 8);
138 }
139
140 return (ushort)(buffer[0] | buffer[1] << 8);
141 }
142
143 public ushort[] ReadUInt16Array(int length)
144 {
145 var array = new ushort[length];
146
147 for (int i = 0; i < array.Length; i++)
148 array[i] = ReadUInt16();
149
150 return array;
151 }
152
153 public uint ReadUInt32()
154 {
155 FillBuffer(4);
156
157 if (bigEndian)
158 {
159 return (uint)(buffer[3] | buffer[2] << 8 | buffer[1] << 16 | buffer[0] << 24);
160 }
161
162 return (uint)(buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24);
163 }
164
165 public ulong ReadUInt64()
166 {
167 FillBuffer(8);
168
169 ulong lo, hi;
170
171 if (bigEndian)
172 {
173 hi = (uint)(buffer[3] | buffer[2] << 8 | buffer[1] << 16 | buffer[0] << 24);
174 lo = (uint)(buffer[7] | buffer[6] << 8 | buffer[5] << 16 | buffer[4] << 24);
175 }
176 else
177 {
178 lo = (uint)(buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24);
179 hi = (uint)(buffer[4] | buffer[5] << 8 | buffer[6] << 16 | buffer[7] << 24);
180 }
181
182 return (hi << 32) | lo;
183 }
184
185 public short ReadInt16()
186 {
187 return (short)ReadUInt16();
188 }
189
190 public short[] ReadInt16Array(int length)
191 {
192 var array = new short[length];
193
194 for (int i = 0; i < array.Length; i++)
195 array[i] = ReadInt16();
196
197 return array;
198 }
199
200 public int ReadInt32()
201 {
202 return (int)ReadUInt32();
203 }
204
205 public int[] ReadInt32VarArray()
206 {
207 return ReadInt32Array(ReadInt32());
208 }
209
210 public int[] ReadInt32Array(int length)
211 {
212 var array = new int[length];
213
214 for (int i = 0; i < array.Length; i++)
215 array[i] = ReadInt32();
216
217 return array;
218 }
219
220 public long ReadInt64()
221 {
222 return (long)ReadUInt64();
223 }
224
225 public unsafe float ReadSingle()
226 {
227 uint value = ReadUInt32();
228 return *((float*)&value);
229 }
230
231 public float[] ReadSingleArray(int length)
232 {
233 var data = new float[length];
234
235 for (int i = 0; i < data.Length; i++)
236 data[i] = ReadSingle();
237
238 return data;
239 }
240
241 public unsafe double ReadDouble()
242 {
243 ulong value = ReadUInt64();
244 return *((double*)&value);
245 }
246
247 public Vector2 ReadVector2()
248 {
249 return new Vector2(ReadSingle(), ReadSingle());
250 }
251
252 public Vector2[] ReadVector2VarArray()
253 {
254 return ReadVector2Array(ReadInt32());
255 }
256
257 public Vector2[] ReadVector2Array(int length)
258 {
259 var data = new Vector2[length];
260
261 for (int i = 0; i < data.Length; i++)
262 data[i] = ReadVector2();
263
264 return data;
265 }
266
267 public Vector3 ReadVector3()
268 {
269 return new Vector3(ReadSingle(), ReadSingle(), ReadSingle());
270 }
271
272 public Vector3[] ReadVector3VarArray()
273 {
274 return ReadVector3Array(ReadInt32());
275 }
276
277 public Vector3[] ReadVector3Array(int length)
278 {
279 var data = new Vector3[length];
280
281 for (int i = 0; i < data.Length; i++)
282 data[i] = ReadVector3();
283
284 return data;
285 }
286
287 public Plane ReadPlane()
288 {
289 return new Plane(ReadVector3(), ReadSingle());
290 }
291
292 public Plane[] ReadPlaneVarArray()
293 {
294 return ReadPlaneArray(ReadInt32());
295 }
296
297 public Plane[] ReadPlaneArray(int length)
298 {
299 var data = new Plane[length];
300
301 for (int i = 0; i < data.Length; i++)
302 data[i] = ReadPlane();
303
304 return data;
305 }
306
307 public Quaternion ReadQuaternion()
308 {
309 return new Quaternion(ReadSingle(), ReadSingle(), ReadSingle(), -ReadSingle());
310 }
311
312 public Quaternion ReadCompressedQuaternion()
313 {
314 return Quaternion.CreateFromAxisAngle(Vector3.UnitX, ReadInt16() * rotationAngleScale)
315 * Quaternion.CreateFromAxisAngle(Vector3.UnitY, ReadInt16() * rotationAngleScale)
316 * Quaternion.CreateFromAxisAngle(Vector3.UnitZ, ReadInt16() * rotationAngleScale);
317 }
318
319 public BoundingBox ReadBoundingBox()
320 {
321 return new BoundingBox(ReadVector3(), ReadVector3());
322 }
323
324 public Matrix ReadMatrix4x3()
325 {
326 Matrix m;
327 m.M11 = ReadSingle();
328 m.M12 = ReadSingle();
329 m.M13 = ReadSingle();
330 m.M14 = 0.0f;
331 m.M21 = ReadSingle();
332 m.M22 = ReadSingle();
333 m.M23 = ReadSingle();
334 m.M24 = 0.0f;
335 m.M31 = ReadSingle();
336 m.M32 = ReadSingle();
337 m.M33 = ReadSingle();
338 m.M34 = 0.0f;
339 m.M41 = ReadSingle();
340 m.M42 = ReadSingle();
341 m.M43 = ReadSingle();
342 m.M44 = 1.0f;
343 return m;
344 }
345
346 public Color ReadColor()
347 {
348 uint color = ReadUInt32();
349
350 var r = (byte)((color >> 16) & 0xff);
351 var g = (byte)((color >> 08) & 0xff);
352 var b = (byte)((color >> 00) & 0xff);
353 var a = (byte)((color >> 24) & 0xff);
354
355 return new Color(r, g, b, a);
356 }
357
358 public Color[] ReadColorArray(int length)
359 {
360 var data = new Color[length];
361
362 for (int i = 0; i < data.Length; i++)
363 data[i] = ReadColor();
364
365 return data;
366 }
367
368 public string ReadString(int maxLength)
369 {
370 var bytes = ReadBytes(maxLength);
371
372 for (int i = 0; i < bytes.Length; i++)
373 {
374 if (bytes[i] == 0)
375 return encoding.GetString(bytes, 0, i);
376 }
377
378 return encoding.GetString(bytes);
379 }
380
381 public string ReadCString()
382 {
383 var buffer = new List<byte>(64);
384 byte b;
385
386 while ((b = ReadByte()) != 0)
387 buffer.Add(b);
388
389 return encoding.GetString(buffer.ToArray());
390 }
391
392 public InstanceDescriptor ReadInstance()
393 {
394 return instanceFile.ResolveLink(ReadInt32());
395 }
396
397 public InstanceDescriptor[] ReadInstanceArray(int length)
398 {
399 var data = new InstanceDescriptor[length];
400
401 for (int i = 0; i < data.Length; i++)
402 data[i] = ReadInstance();
403
404 return data;
405 }
406
407 public InstanceDescriptor ReadLink()
408 {
409 return instanceFile.GetDescriptor(ReadInt32());
410 }
411
412 public InstanceDescriptor[] ReadLinkArray(int length)
413 {
414 var data = new InstanceDescriptor[length];
415
416 for (int i = 0; i < data.Length; i++)
417 data[i] = ReadLink();
418
419 return data;
420 }
421
422 private void FillBuffer(int count)
423 {
424 int offset = 0;
425
426 while (count > 0)
427 {
428 int read = stream.Read(buffer, offset, count);
429
430 if (read == 0)
431 throw new EndOfStreamException();
432
433 offset += read;
434 count -= read;
435 }
436 }
437 }
438}
Note: See TracBrowser for help on using the repository browser.