Skip to content

Instantly share code, notes, and snippets.

@GlaireDaggers
Last active August 3, 2017 05:16
Show Gist options
  • Save GlaireDaggers/a74d9342cd2ead8a82655bb50a5a2a72 to your computer and use it in GitHub Desktop.
Save GlaireDaggers/a74d9342cd2ead8a82655bb50a5a2a72 to your computer and use it in GitHub Desktop.
A simple interface to allow for quick in-line and non-allocating reading and writing with byte arrays.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace JetFistGames.Utils.IO
{
/// <summary>
/// Helper class for a quick non-allocating way to read or write from/to temporary byte arrays as streams
/// Use like this:
/// using( var reader = ByteArrayReaderWriter.Get( byteArray ) )
/// { ... }
/// The reader is automatically released back to the pool after the using code block.
/// Note that reader and writer positions are completely independant of each other.
/// </summary>
public class ByteArrayReaderWriter : IDisposable
{
protected static Queue<ByteArrayReaderWriter> readerPool = new Queue<ByteArrayReaderWriter>();
/// <summary>
/// Get a reader/writer for the given byte array
/// </summary>
public static ByteArrayReaderWriter Get(byte[] byteArray)
{
ByteArrayReaderWriter reader = null;
if (readerPool.Count > 0)
{
reader = readerPool.Dequeue();
}
else
{
reader = new ByteArrayReaderWriter();
}
reader.SetStream(byteArray);
return reader;
}
/// <summary>
/// Release a reader/writer to the pool
/// </summary>
public static void Release(ByteArrayReaderWriter reader)
{
readerPool.Enqueue(reader);
}
public long ReadPosition
{
get { return readStream.Position; }
}
public long WritePosition
{
get { return writeStream.Position; }
}
protected ByteStream readStream;
protected BinaryReader reader;
protected ByteStream writeStream;
protected BinaryWriter writer;
public ByteArrayReaderWriter()
{
this.readStream = new ByteStream();
this.reader = new BinaryReader(readStream);
this.writeStream = new ByteStream();
this.writer = new BinaryWriter(writeStream);
}
public void SetStream(byte[] byteArray)
{
this.readStream.SetStreamSource(byteArray);
this.writeStream.SetStreamSource(byteArray);
}
public void Write(byte val) { writer.Write(val); }
public void Write(byte[] val) { writer.Write(val); }
public void Write(char val) { writer.Write(val); }
public void Write(char[] val) { writer.Write(val); }
public void Write(string val) { writer.Write(val); }
public void Write(short val) { writer.Write(val); }
public void Write(int val) { writer.Write(val); }
public void Write(long val) { writer.Write(val); }
public void Write(ushort val) { writer.Write(val); }
public void Write(uint val) { writer.Write(val); }
public void Write(ulong val) { writer.Write(val); }
public void WriteASCII(char[] chars)
{
for (int i = 0; i < chars.Length; i++)
{
byte asciiCode = (byte)(chars[i] & 0xFF);
Write(asciiCode);
}
}
public void WriteASCII(string str)
{
for (int i = 0; i < str.Length; i++)
{
byte asciiCode = (byte)(str[i] & 0xFF);
Write(asciiCode);
}
}
public void WriteBuffer(byte[] buffer, int length)
{
for (int i = 0; i < length; i++)
Write(buffer[i]);
}
public byte ReadByte() { return reader.ReadByte(); }
public byte[] ReadBytes(int length) { return reader.ReadBytes(length); }
public char ReadChar() { return reader.ReadChar(); }
public char[] ReadChars(int length) { return reader.ReadChars(length); }
public string ReadString() { return reader.ReadString(); }
public short ReadInt16() { return reader.ReadInt16(); }
public int ReadInt32() { return reader.ReadInt32(); }
public long ReadInt64() { return reader.ReadInt64(); }
public ushort ReadUInt16() { return reader.ReadUInt16(); }
public uint ReadUInt32() { return reader.ReadUInt32(); }
public ulong ReadUInt64() { return reader.ReadUInt64(); }
public void ReadASCIICharsIntoBuffer(char[] buffer, int length)
{
for (int i = 0; i < length; i++)
buffer[i] = (char)ReadByte();
}
public void ReadBytesIntoBuffer(byte[] buffer, int length)
{
for (int i = 0; i < length; i++)
buffer[i] = ReadByte();
}
public void Dispose()
{
Release(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace JetFistGames.Utils.IO
{
/// <summary>
/// A simple stream implementation for reading/writing from/to byte arrays which can be reused
/// </summary>
public class ByteStream : Stream
{
protected byte[] srcByteArray;
public override long Position
{
get; set;
}
public override long Length
{
get
{
return srcByteArray.Length;
}
}
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
/// <summary>
/// Set a new byte array for this stream to read from
/// </summary>
public void SetStreamSource(byte[] sourceBuffer)
{
this.srcByteArray = sourceBuffer;
this.Position = 0;
}
public override int Read(byte[] buffer, int offset, int count)
{
int readBytes = 0;
long pos = this.Position;
long len = this.Length;
for (int i = 0; i < count && pos < len; i++)
{
buffer[i + offset] = srcByteArray[pos++];
readBytes++;
}
this.Position = pos;
return readBytes;
}
public override void Write(byte[] buffer, int offset, int count)
{
long pos = this.Position;
for (int i = 0; i < count; i++)
srcByteArray[pos++] = buffer[i + offset];
this.Position = pos;
}
public override void Flush()
{
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin == SeekOrigin.Begin)
this.Position = offset;
else if (origin == SeekOrigin.Current)
this.Position += offset;
else
this.Position = this.Length - offset - 1;
return this.Position;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment