Last active
June 19, 2023 22:25
-
-
Save thatcosmonaut/5ecb4bf6b519d068d50fd4e526757968 to your computer and use it in GitHub Desktop.
DPBuffer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
using dp.type; | |
namespace SamuraiGunn2 | |
{ | |
public unsafe class DPBuffer : IBuffer, IDisposable | |
{ | |
private byte* Bytes; | |
private int Length; | |
private int Position; | |
private bool disposed; | |
public DPBuffer(int length) | |
{ | |
Bytes = (byte*) NativeMemory.Alloc((nuint) length); | |
Length = length; | |
} | |
public int Crc32(int offset, int len) | |
{ | |
// Algorithm taken from K&R C 2nd edition | |
var hashval = 0; | |
for (var i = offset; i < len; i += 1) | |
{ | |
hashval = Bytes[i] + 31 * hashval; | |
} | |
return hashval; | |
} | |
public Span<byte> GetBytes() | |
{ | |
return new Span<byte>(Bytes, Length); | |
} | |
public int GetSize() | |
{ | |
return Length; | |
} | |
public int PeekByteUnsigned(int pos) | |
{ | |
return (int) Bytes[pos]; | |
} | |
public int PeekInt(int pos) | |
{ | |
return Unsafe.Read<int>(Bytes + pos); | |
} | |
public long PeekInt64(int pos) | |
{ | |
return Unsafe.Read<long>(Bytes + pos); | |
} | |
public int PeekShortUnsigned(int pos) | |
{ | |
return Unsafe.Read<ushort>(Bytes + pos); | |
} | |
public void PokeInt(int pos, int s32) | |
{ | |
Unsafe.Write<int>(Bytes + pos, s32); | |
} | |
public void PokeInt64(int pos, long s64) | |
{ | |
Unsafe.Write<long>(Bytes + pos, s64); | |
} | |
public void PokeShortUnsigned(int pos, int u16) | |
{ | |
Unsafe.Write<ushort>(Bytes + pos, (ushort) u16); | |
} | |
public bool ReadBool() | |
{ | |
var b = Unsafe.Read<byte>(Bytes + Position) != 0; | |
Position += 1; | |
return b; | |
} | |
public int ReadByteSigned() | |
{ | |
var b = (sbyte) Bytes[Position]; | |
Position += 1; | |
return b; | |
} | |
public int ReadByteUnsigned() | |
{ | |
var b = Bytes[Position]; | |
Position += 1; | |
return b; | |
} | |
public string ReadCString() | |
{ | |
byte c = Bytes[Position]; | |
var len = 1; | |
while (c != 0) | |
{ | |
c = Bytes[Position + len]; | |
len += 1; | |
} | |
return System.Text.Encoding.UTF8.GetString(new ReadOnlySpan<byte>(Bytes + Position, len)); | |
} | |
public int ReadInt() | |
{ | |
var i = Unsafe.Read<int>(Bytes + Position); | |
Position += 4; | |
return i; | |
} | |
public long ReadInt64() | |
{ | |
var i = Unsafe.Read<long>(Bytes + Position); | |
Position += 8; | |
return i; | |
} | |
public int ReadShortSigned() | |
{ | |
var s = Unsafe.Read<short>(Bytes + Position); | |
Position += 2; | |
return s; | |
} | |
public int ReadShortUnsigned() | |
{ | |
var s = Unsafe.Read<ushort>(Bytes + Position); | |
Position += 2; | |
return s; | |
} | |
public void Resize(int newSize) | |
{ | |
if (newSize > Length) | |
{ | |
Bytes = (byte*) NativeMemory.Realloc(Bytes, (nuint) newSize); | |
Length = newSize; | |
} | |
} | |
public void Rewind() | |
{ | |
Position = 0; | |
} | |
public void SavePart(string fname, int offset, int len) | |
{ | |
using var filestream = new FileStream(fname, FileMode.Create, FileAccess.Write); | |
filestream.Write(new ReadOnlySpan<byte>(Bytes + offset, len)); | |
} | |
public void SeekRelative(int positionOffset) | |
{ | |
Position += positionOffset; | |
} | |
public void SeekStart(int newPosition) | |
{ | |
Position = newPosition; | |
} | |
public void SetToBytes(Span<byte> bytes) | |
{ | |
var span = new Span<byte>(Bytes, Length); | |
bytes.CopyTo(span); | |
} | |
public int Tell() | |
{ | |
return Position; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
private void CheckResize(int elementSize) | |
{ | |
if (Position + elementSize >= Length) | |
{ | |
Resize(Length * 2); | |
} | |
} | |
public void WriteBool(bool b) | |
{ | |
CheckResize(1); | |
Unsafe.Write<byte>(Bytes + Position, b ? (byte) 1 : (byte) 0); | |
Position += 1; | |
} | |
public void WriteByteSigned(int s8) | |
{ | |
CheckResize(1); | |
Unsafe.Write<sbyte>(Bytes + Position, (sbyte) s8); | |
Position += 1; | |
} | |
public void WriteByteUnsigned(int u8) | |
{ | |
CheckResize(1); | |
Unsafe.Write<byte>(Bytes + Position, (byte) u8); | |
Position += 1; | |
} | |
public void WriteChars(string s) | |
{ | |
var span = new Span<byte>(Bytes + Position, Length - Position); | |
var len = System.Text.Encoding.UTF8.GetBytes(s.AsSpan(), span); | |
Position += len; | |
} | |
public void WriteCString(string s) | |
{ | |
WriteChars(s); | |
Unsafe.Write<byte>(Bytes + Position, 0); | |
Position += 1; | |
} | |
public void WriteInt(int s32) | |
{ | |
CheckResize(4); | |
Unsafe.Write<int>(Bytes + Position, s32); | |
Position += 4; | |
} | |
public void WriteInt64(long s64) | |
{ | |
CheckResize(8); | |
Unsafe.Write<long>(Bytes + Position, s64); | |
Position += 8; | |
} | |
public void WriteShortSigned(int s16) | |
{ | |
CheckResize(2); | |
Unsafe.Write<short>(Bytes + Position, (short) s16); | |
Position += 2; | |
} | |
public void WriteShortUnsigned(int u16) | |
{ | |
CheckResize(2); | |
Unsafe.Write<ushort>(Bytes + Position, (ushort) u16); | |
Position += 2; | |
} | |
void IBuffer.CopyFrom<T>(int dest, T src, int srcPos, int len) | |
{ | |
var destSpan = new Span<byte>(Bytes + dest, Length - dest); | |
var srcSpan = src.GetBytes().Slice(srcPos, len); | |
srcSpan.CopyTo(destSpan); | |
} | |
void IBuffer.ReadBuffer<T>(T dest, int dstPos, int len) | |
{ | |
var destSpan = dest.GetBytes().Slice(dstPos); | |
var srcSpan = new Span<byte>(Bytes + Position, len); | |
srcSpan.CopyTo(destSpan); | |
} | |
void IBuffer.WriteBufferExt<T>(T src, int srcPos, int len) | |
{ | |
CheckResize(len); | |
var srcSpan = src.GetBytes().Slice(srcPos, len); | |
var destSpan = new Span<byte>(Bytes + Position, Length - Position); | |
srcSpan.CopyTo(destSpan); | |
Position += len; | |
} | |
protected virtual void Dispose(bool disposing) | |
{ | |
if (disposed) | |
{ | |
return; | |
} | |
if (disposing) | |
{ | |
// dispose managed state (managed objects). | |
} | |
NativeMemory.Free(Bytes); | |
Bytes = null; | |
disposed = true; | |
} | |
~DPBuffer() | |
{ | |
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | |
Dispose(disposing: false); | |
} | |
public void Dispose() | |
{ | |
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | |
Dispose(disposing: true); | |
GC.SuppressFinalize(this); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment