Skip to content

Instantly share code, notes, and snippets.

@Frityet
Last active March 27, 2022 00:30
Show Gist options
  • Save Frityet/70bc35a05e08c5cfdb990e51f0b6bbe5 to your computer and use it in GitHub Desktop.
Save Frityet/70bc35a05e08c5cfdb990e51f0b6bbe5 to your computer and use it in GitHub Desktop.
public unsafe class Memory : IDisposable
{
public int Count { get; private set; }
public int MaxCount { get; private set; }
private byte* _pointer;
public byte[] Bytes
{
get
{
var arr = new byte[Count];
for (int i = 0; i < Count; i++)
arr[i] = _pointer[i];
return arr;
}
}
public Memory(int count)
{
Count = 0;
MaxCount = 0;
if (count < 1)
{
_pointer = new Pointer<byte>();
return;
}
MaxCount = (int)((UInt32) count).To2ndPower();
_pointer = new Pointer<byte>(Marshal.AllocHGlobal(sizeof(byte) * MaxCount));
}
private void Grow(int count)
{
if (count < 1)
return;
Marshal.ReAllocHGlobal((IntPtr)_pointer, (IntPtr)(sizeof(byte) * (MaxCount += (int)((UInt32)count).To2ndPower())));
}
private void Grow() => Grow(MaxCount);
public void Write(byte b)
{
if (Count >= MaxCount - 1)
Grow();
_pointer[Count++] = b;
}
public void Write(byte b, int index)
{
if (index >= MaxCount - 1)
Grow(index - MaxCount);
_pointer[index] = b;
}
public void Write(byte[] bytes)
{
if (Count + bytes.Length >= MaxCount - 1)
Grow();
foreach (byte b in bytes)
_pointer[Count++] = b;
}
public void Write(byte[] bytes, int index)
{
if (index + bytes.Length >= MaxCount - 1)
Grow(index + bytes.Length - MaxCount);
for (int i = index, j = 0; j < bytes.Length; j++, i++)
_pointer[i] = bytes[j];
}
public void Reset() => Count = 0;
public void Clear()
{
Reset();
for (int i = 0; i < MaxCount; i++)
_pointer[i] = 0;
}
public byte this[int index]
{
get => index > MaxCount ? throw new IndexOutOfRangeException($"Index {index} is out of range for memory (max {MaxCount} bytes)")
: _pointer[index];
set
{
if (index > MaxCount)
Grow(index - MaxCount);
_pointer[index] = value;
}
}
public void Dispose()
{
Marshal.FreeHGlobal((IntPtr)_pointer);
GC.SuppressFinalize(this);
}
}
@Frityet
Copy link
Author

Frityet commented Mar 27, 2022

    public class Packet : IDisposable
    {
        public const int MAX_SIZE = 4096;
        
        public int ReadPosition { get; set; }
        public int Length => _memory.Count;
        public int UnreadLength => Length - ReadPosition;
        
        private Memory _memory;
        private byte[] _readbuf;

        public Packet(int bytecount = MAX_SIZE)
        {
            _memory = new Memory(bytecount);
            _readbuf = new byte[bytecount];
            ReadPosition = 0;
        }

        public Packet(byte[] bytes)
        {
            int len = MAX_SIZE;
            if (bytes.Length > len)
                len = bytes.Length;
            
            _memory = new Memory(len);
            ReadPosition = 0;
            _readbuf = null;
            SetBytes(bytes);
        }

        public void SetBytes(byte[] bytes)
        {
            _memory.Write(bytes);
            _readbuf = _memory.Bytes;
        }

        #region Reading

        public byte ReadByte(bool moveReadPos = true)
        {
            if (_memory.Count > ReadPosition)
            {
                byte val = _readbuf[ReadPosition];
                if (moveReadPos)
                    ReadPosition++;

                return val;
            }
            else throw new Exception("Could not read byte!");
        }

        public byte[] ReadBytes(int count, bool moveReadPos = true)
        {
            if (_memory.Count > ReadPosition)
            {
                var bytes = new byte[count];
                for (int i = ReadPosition, j = 0; i < count; i++)
                {
                    bytes[j] = _memory[i];
                    if (moveReadPos)
                        ReadPosition++;
                }

                return bytes;
            }
            else throw new Exception($"Could not read {count} bytes from buffer!");
        }

        public short ReadShort(bool moveReadPos = true)     => BitConverter.ToInt16(ReadBytes(1 << 1, moveReadPos), 0);
        public int ReadInt(bool moveReadPos = true)         => BitConverter.ToInt32(ReadBytes(1 << 2, moveReadPos), 0);
        public long ReadLong(bool moveReadPos = true)       => BitConverter.ToInt64(ReadBytes(1 << 3, moveReadPos), 0);

        public float ReadFloat(bool moveReadPos = true)     => BitConverter.ToSingle(ReadBytes(1 << 2, moveReadPos), 0);
        public double ReadDouble(bool moveReadPos = true)   => BitConverter.ToDouble(ReadBytes(1 << 3, moveReadPos), 0);

        public bool ReadBool(bool moveReadPos = true)       => BitConverter.ToBoolean(ReadBytes(1 << 0, moveReadPos), 0);

        public string ReadString(bool moveReadPos = true)   => Encoding.UTF8.GetString(_readbuf, ReadPosition, ReadInt());
        
        #endregion
        
        #region Writing
        public void Write(byte b)       => _memory.Write(b);
        public void Write(byte[] bytes) => _memory.Write(bytes);
        public void Write(bool b)       => _memory.Write(BitConverter.GetBytes(b));
        public void Write(short w)      => _memory.Write(BitConverter.GetBytes(w));
        public void Write(int dw)       => _memory.Write(BitConverter.GetBytes(dw));
        public void Write(long qw)      => _memory.Write(BitConverter.GetBytes(qw));
        
        public void Write(float dw)     => _memory.Write(BitConverter.GetBytes(dw));
        public void Write(double qw)    => _memory.Write(BitConverter.GetBytes(qw));
        
        public void Write(string str)
        {
            Write(str.Length);
            _memory.Write(Encoding.UTF8.GetBytes(str));
        }
        #endregion

        private void WriteLength() => _memory.Write(BitConverter.GetBytes(_memory.Count), 0);
        
        public void Dispose()
        {
            _memory.Dispose();
            _readbuf = null;
            GC.SuppressFinalize(this);
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment