EveryFileExplorer/LibEveryFileExplorer/IO/EndianBinaryReader.cs
2015-01-14 14:09:58 +01:00

401 lines
7.4 KiB
C#

using System.Text;
using System.Runtime.InteropServices;
using LibEveryFileExplorer.Collections;
using System;
using System.IO;
namespace LibEveryFileExplorer.IO
{
public class EndianBinaryReader : IDisposable
{
private bool disposed;
private byte[] buffer;
public Stream BaseStream { get; private set; }
public Endianness Endianness { get; set; }
public Endianness SystemEndianness { get { return BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian; } }
private bool Reverse { get { return SystemEndianness != Endianness; } }
public EndianBinaryReader(Stream baseStream)
: this(baseStream, Endianness.BigEndian)
{ }
public EndianBinaryReader(Stream baseStream, Endianness endianness)
{
if (baseStream == null) throw new ArgumentNullException("baseStream");
if (!baseStream.CanRead) throw new ArgumentException("baseStream");
BaseStream = baseStream;
Endianness = endianness;
}
~EndianBinaryReader()
{
Dispose(false);
}
private void FillBuffer(int bytes, int stride)
{
if (buffer == null || buffer.Length < bytes)
buffer = new byte[bytes];
BaseStream.Read(buffer, 0, bytes);
if (Reverse)
for (int i = 0; i < bytes; i += stride)
{
Array.Reverse(buffer, i, stride);
}
}
public byte ReadByte()
{
FillBuffer(1, 1);
return buffer[0];
}
public byte[] ReadBytes(int count)
{
byte[] temp;
FillBuffer(count, 1);
temp = new byte[count];
Array.Copy(buffer, 0, temp, 0, count);
return temp;
}
public sbyte ReadSByte()
{
FillBuffer(1, 1);
unchecked
{
return (sbyte)buffer[0];
}
}
public sbyte[] ReadSBytes(int count)
{
sbyte[] temp;
temp = new sbyte[count];
FillBuffer(count, 1);
unchecked
{
for (int i = 0; i < count; i++)
{
temp[i] = (sbyte)buffer[i];
}
}
return temp;
}
public char ReadChar(Encoding encoding)
{
int size;
size = GetEncodingSize(encoding);
FillBuffer(size, size);
return encoding.GetChars(buffer, 0, size)[0];
}
public char[] ReadChars(Encoding encoding, int count)
{
int size;
size = GetEncodingSize(encoding);
FillBuffer(size * count, size);
return encoding.GetChars(buffer, 0, size * count);
}
private static int GetEncodingSize(Encoding encoding)
{
if (encoding == Encoding.UTF8 || encoding == Encoding.ASCII)
return 1;
else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode)
return 2;
return 1;
}
public string ReadStringNT(Encoding encoding)
{
string text;
text = "";
do
{
text += ReadChar(encoding);
} while (!text.EndsWith("\0", StringComparison.Ordinal));
return text.Remove(text.Length - 1);
}
public string ReadString(Encoding encoding, int count)
{
return new string(ReadChars(encoding, count));
}
public double ReadDouble()
{
const int size = sizeof(double);
FillBuffer(size, size);
return BitConverter.ToDouble(buffer, 0);
}
public double[] ReadDoubles(int count)
{
const int size = sizeof(double);
double[] temp;
temp = new double[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToDouble(buffer, size * i);
}
return temp;
}
public Single ReadSingle()
{
const int size = sizeof(Single);
FillBuffer(size, size);
return BitConverter.ToSingle(buffer, 0);
}
public Single[] ReadSingles(int count)
{
const int size = sizeof(Single);
Single[] temp;
temp = new Single[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToSingle(buffer, size * i);
}
return temp;
}
public Vector2 ReadVector2()
{
return new Vector2(ReadSingle(), ReadSingle());
}
public Vector3 ReadVector3()
{
return new Vector3(ReadSingle(), ReadSingle(), ReadSingle());
}
public Vector4 ReadVector4()
{
return new Vector4(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());
}
public Single ReadFx16()
{
return ReadInt16() / 4096f;
}
public Vector3 ReadVecFx16()
{
return new Vector3(ReadFx16(), ReadFx16(), ReadFx16());
}
public Single ReadFx32()
{
return ReadInt32() / 4096f;
}
public Single[] ReadFx32s(int count)
{
Single[] result = new float[count];
for (int i = 0; i < count; i++)
{
result[i] = ReadInt32() / 4096f;
}
return result;
}
public Vector3 ReadVecFx32()
{
return new Vector3(ReadFx32(), ReadFx32(), ReadFx32());
}
public Int32 ReadInt32()
{
const int size = sizeof(Int32);
FillBuffer(size, size);
return BitConverter.ToInt32(buffer, 0);
}
public Int32[] ReadInt32s(int count)
{
const int size = sizeof(Int32);
Int32[] temp;
temp = new Int32[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToInt32(buffer, size * i);
}
return temp;
}
public Int64 ReadInt64()
{
const int size = sizeof(Int64);
FillBuffer(size, size);
return BitConverter.ToInt64(buffer, 0);
}
public Int64[] ReadInt64s(int count)
{
const int size = sizeof(Int64);
Int64[] temp;
temp = new Int64[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToInt64(buffer, size * i);
}
return temp;
}
public Int16 ReadInt16()
{
const int size = sizeof(Int16);
FillBuffer(size, size);
return BitConverter.ToInt16(buffer, 0);
}
public Int16[] ReadInt16s(int count)
{
const int size = sizeof(Int16);
Int16[] temp;
temp = new Int16[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToInt16(buffer, size * i);
}
return temp;
}
public UInt16 ReadUInt16()
{
const int size = sizeof(UInt16);
FillBuffer(size, size);
return BitConverter.ToUInt16(buffer, 0);
}
public UInt16[] ReadUInt16s(int count)
{
const int size = sizeof(UInt16);
UInt16[] temp;
temp = new UInt16[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToUInt16(buffer, size * i);
}
return temp;
}
public UInt32 ReadUInt32()
{
const int size = sizeof(UInt32);
FillBuffer(size, size);
return BitConverter.ToUInt32(buffer, 0);
}
public UInt32[] ReadUInt32s(int count)
{
const int size = sizeof(UInt32);
UInt32[] temp;
temp = new UInt32[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToUInt32(buffer, size * i);
}
return temp;
}
public UInt64 ReadUInt64()
{
const int size = sizeof(UInt64);
FillBuffer(size, size);
return BitConverter.ToUInt64(buffer, 0);
}
public UInt64[] ReadUInt64s(int count)
{
const int size = sizeof(UInt64);
UInt64[] temp;
temp = new UInt64[count];
FillBuffer(size * count, size);
for (int i = 0; i < count; i++)
{
temp[i] = BitConverter.ToUInt64(buffer, size * i);
}
return temp;
}
public void Close()
{
Dispose();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (BaseStream != null)
{
BaseStream.Close();
}
}
buffer = null;
disposed = true;
}
}
}
public enum Endianness
{
BigEndian,
LittleEndian,
}
}