Here you go:
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace DaringDev.IO
{
public enum EndianType
{
Big,
Little,
Native
}
public sealed class EndianIO
{
private EndianType _endianness;
private bool _requiresReverse;
private readonly Stream _stream;
private readonly bool _publicMemoryStream;
private readonly byte[] _buffer = new byte[8];
public EndianIO(Stream stream, EndianType endianType = EndianType.Native)
{
_stream = stream;
Endianness = endianType;
}
public EndianIO(EndianType endianType = EndianType.Native)
: this(new MemoryStream(), endianType)
{
_publicMemoryStream = true;
}
public EndianIO(int maxSize, EndianType endianType = EndianType.Native)
: this(new MemoryStream(maxSize), endianType)
{
_publicMemoryStream = true;
}
public EndianIO(byte[] buffer, EndianType endianType = EndianType.Native)
: this(new MemoryStream(buffer), endianType)
{
}
public EndianIO(string fileName, EndianType endianType = EndianType.Native, FileMode fileMode = FileMode.Open,
FileAccess fileAccess = FileAccess.ReadWrite, FileShare fileShare = FileShare.Read, int bufferSize = 4096, bool isAsync = false)
: this(new FileStream(fileName, fileMode, fileAccess, fileShare, bufferSize, isAsync), endianType)
{
}
public Stream BaseStream
{
get { return _stream; }
}
public EndianType Endianness
{
get { return _endianness; }
set
{
_endianness = value;
switch (value)
{
case EndianType.Native:
_requiresReverse = false;
break;
case EndianType.Little:
_requiresReverse = !BitConverter.IsLittleEndian;
break;
case EndianType.Big:
_requiresReverse = BitConverter.IsLittleEndian;
break;
}
}
}
public bool Eof
{
get { return Position == Length; }
}
public long Length
{
get
{
return _stream.Length;
}
}
public long Position
{
get { return _stream.Position; }
set { _stream.Position = value; }
}
public void Seek(long position, SeekOrigin origin)
{
_stream.Seek(position, origin);
}
public void Flush()
{
_stream.Flush();
}
public void SetLength(long value)
{
_stream.SetLength(value);
}
public Stream GetStream()
{
return _stream;
}
public void Close()
{
_stream.Close();
}
public byte[] ToArray(bool preferInternalReference = false)
{
var ms = _stream as MemoryStream;
if (ms == null)
{
throw new NotSupportedException("ToArray() is only supported by memory streams.");
}
return preferInternalReference && _publicMemoryStream ? ms.GetBuffer() : ms.ToArray();
}
public int Read(byte[] buffer, int offset, int count)
{
return _stream.Read(buffer, offset, count);
}
public async Task<int> ReadAsync(byte[] buffer, int offset, int count)
{
return await _stream.ReadAsync(buffer, offset, count);
}
public byte[] ReadByteArray(int count)
{
var buffer = new byte[count];
Read(buffer, 0, count);
return buffer;
}
public async Task<byte[]> ReadByteArrayAsync(int count)
{
var buffer = new byte[count];
await ReadAsync(buffer, 0, count);
return buffer;
}
public byte[] ReadByteArray(long count)
{
var buffer = new byte[count];
Read(buffer, 0, buffer.Length);
return buffer;
}
public byte[] ReadToEnd()
{
using (var ms = new MemoryStream(81920))
{
_stream.CopyTo(ms);
return ms.ToArray();
}
}
public async Task<byte[]> ReadToEndAsync()
{
using (var ms = new MemoryStream(81920))
{
await _stream.CopyToAsync(ms);
return ms.ToArray();
}
}
public sbyte ReadSByte()
{
Read(_buffer, 0, 1);
return (sbyte)_buffer[0];
}
public byte ReadByte()
{
Read(_buffer, 0, 1);
return _buffer[0];
}
public bool ReadBoolean()
{
return ReadByte() != 0x00;
}
public ushort ReadUInt16()
{
return unchecked((ushort)ReadInt16());
}
public unsafe short ReadInt16()
{
Read(_buffer, 0, 2);
if (_requiresReverse)
return (short)(_buffer[1] | (_buffer[0] << :sunglasses:);
fixed (byte* pbyte = &_buffer[0])
return *((short*)pbyte);
}
public uint ReadUInt32()
{
return unchecked((uint)ReadInt32());
}
public unsafe int ReadInt32()
{
Read(_buffer, 0, 4);
if (_requiresReverse)
return _buffer[3] | (_buffer[2] << :sunglasses: | (_buffer[1] << 16) | (_buffer[0] << 24);
fixed (byte* pbyte = &_buffer[0])
return *((int*)pbyte);
}
public async Task<int> ReadInt32Async()
{
await ReadAsync(_buffer, 0, 4);
if (_requiresReverse)
return _buffer[3] | (_buffer[2] << :sunglasses: | (_buffer[1] << 16) | (_buffer[0] << 24);
return BitConverter.ToInt32(_buffer, 0);
}
public ulong ReadUInt64()
{
return unchecked((ulong)ReadInt64());
}
public unsafe long ReadInt64()
{
Read(_buffer, 0, :sunglasses:;
if (_requiresReverse)
{
var n1 = (_buffer[3] | (_buffer[2] << :sunglasses: | (_buffer[1] << 16) | (_buffer[0] << 24)) & 0xffffffff;
var n2 = (_buffer[7] | (_buffer[6] << :sunglasses: | (_buffer[5] << 16) | (_buffer[4] << 24)) & 0xffffffff;
return n2 | (n1 << 32);
}
fixed (byte* pbyte = &_buffer[0])
return *((long*)pbyte);
}
public uint ReadUInt24()
{
Read(_buffer, 0, 3);
if (!_requiresReverse)
return (uint)(_buffer[0] | (_buffer[1] << :sunglasses: | (_buffer[2] << 16));
return (uint)(_buffer[2] | (_buffer[1] << :sunglasses: | (_buffer[0] << 16));
}
public unsafe float ReadSingle()
{
var x = ReadInt32();
return *(float*)&x;
}
public unsafe double ReadDouble()
{
var x = ReadInt64();
return *((double*)&x);
}
public string ReadString(Encoding encoding, int lengthInBytes)
{
return encoding.GetString(ReadByteArray(lengthInBytes));
}
public async Task<string> ReadStringAsync(Encoding encoding, int lengthInBytes)
{
return encoding.GetString(await ReadByteArrayAsync(lengthInBytes));
}
public string ReadNullTerminatedString(Encoding encoding)
{
var sb = new StringBuilder();
var io = new StreamReader(_stream, encoding, false, 16, true);
int currentChar;
while ((currentChar = io.Read()) != -1 && currentChar != 0)
{
sb.Append((char)currentChar);
}
io.Close();
return sb.ToString();
}
public void Write(byte[] buffer, int offset, int count)
{
_stream.Write(buffer, offset, count);
}
public void Write(byte[] buffer)
{
Write(buffer, 0, buffer.Length);
}
public void Write(bool value)
{
const byte one = 1, zero = 0;
Write(value ? one : zero);
}
public void Write(sbyte value)
{
Write(unchecked((byte)value));
}
public void Write(byte value)
{
_buffer[0] = value;
Write(_buffer, 0, 1);
}
public void Write(short value)
{
Write(unchecked((ushort)value));
}
public void Write(ushort value)
{
if (_requiresReverse)
value = (ushort)((value << :sunglasses: | (value >> :sunglasses:);
Write(BitConverter.GetBytes(value));
}
public void Write(int value)
{
Write(unchecked((uint)value));
}
public void Write(uint value)
{
if (_requiresReverse)
value = (value << 24) | (value >> 24) | ((value & 0xff00) << :sunglasses: | ((value >> :sunglasses: & 0xff00);
Write(BitConverter.GetBytes(value));
}
public void Write(long value)
{
Write(unchecked((ulong)value));
}
public void Write(ulong value)
{
if (_requiresReverse)
{
value = (value << 56) | (value >> 56) |
((value & 0xff00) << 40) | ((value >> 40) & 0xff00) |
((value & 0xff0000) << 24) | ((value >> 24) & 0xff0000) |
((value & 0xff000000) << :sunglasses: | ((value >> :sunglasses: & 0xff000000);
}
Write(BitConverter.GetBytes(value));
}
public unsafe void Write(float value)
{
Write(*((uint*)&value));
}
public unsafe void Write(double value)
{
Write(*((ulong*)&value));
}
public void WriteUInt24(uint value)
{
var buffer = BitConverter.GetBytes(value);
Array.Resize(ref buffer, 3);
if (_requiresReverse)
{
var t = buffer[0];
buffer[0] = buffer[2];
buffer[2] = t;
}
Write(buffer);
}
public void Write(string value, Encoding encoding)
{
if (value.Length != 0)
{
Write(encoding.GetBytes(value));
}
}
public void Write(string value, Encoding encoding, int fixedLength)
{
if (fixedLength < 0)
{
throw new ArgumentOutOfRangeException("fixedLength");
}
if (fixedLength == 0 || value.Length == 0)
{
return;
}
if (value.Length > fixedLength)
{
value = value.Substring(0, fixedLength);
}
else if (value.Length < fixedLength)
{
value += new string('\0', fixedLength - value.Length);
}
Write(encoding.GetBytes(value));
}
private static readonly char[] NullCharacters = { '\0' };
public void WriteNullTerminatedString(string value, Encoding encoding)
{
Write(encoding.GetBytes(value));
Write(encoding.GetBytes(NullCharacters));
}
}
}