From 9c3749bfa0de32e8e0a4ae07a29b80939cf5da2d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 10 Jun 2024 23:49:30 +0200 Subject: [PATCH] add RingBuffer class -- FIFO but optimized for larger volumes of data --- src/FIFO.h | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/src/FIFO.h b/src/FIFO.h index 026c2c7f..daa7b230 100644 --- a/src/FIFO.h +++ b/src/FIFO.h @@ -24,6 +24,7 @@ namespace melonDS { + template class FIFO { @@ -191,5 +192,121 @@ private: u32 ReadPos, WritePos; }; +template +class RingBuffer +{ +public: + void Clear() + { + NumOccupied = 0; + ReadPos = 0; + WritePos = 0; + memset(Buffer, 0, Size); + } + + + void DoSavestate(Savestate* file) + { + file->Var32(&NumOccupied); + file->Var32(&ReadPos); + file->Var32(&WritePos); + + file->VarArray(Buffer, Size); + } + + + bool Write(const void* data, u32 len) + { + if (!CanFit(len)) return false; + + if ((WritePos + len) >= Size) + { + u32 part1 = Size - WritePos; + memcpy(&Buffer[WritePos], data, part1); + if (len > part1) + memcpy(Buffer, &((u8*)data)[part1], len - part1); + WritePos = len - part1; + } + else + { + memcpy(&Buffer[WritePos], data, len); + WritePos += len; + } + + NumOccupied += len; + + return true; + } + + bool Read(void* data, u32 len) + { + if (NumOccupied < len) return false; + + u32 readpos = ReadPos; + if ((readpos + len) >= Size) + { + u32 part1 = Size - readpos; + memcpy(data, &Buffer[readpos], part1); + if (len > part1) + memcpy(&((u8*)data)[part1], Buffer, len - part1); + ReadPos = len - part1; + } + else + { + memcpy(data, &Buffer[readpos], len); + ReadPos += len; + } + + NumOccupied -= len; + return true; + } + + bool Peek(void* data, u32 offset, u32 len) + { + if (NumOccupied < len) return false; + + u32 readpos = ReadPos + offset; + if (readpos >= Size) readpos -= Size; + + if ((readpos + len) >= Size) + { + u32 part1 = Size - readpos; + memcpy(data, &Buffer[readpos], part1); + if (len > part1) + memcpy(&((u8*)data)[part1], Buffer, len - part1); + } + else + { + memcpy(data, &Buffer[readpos], len); + } + + return true; + } + + bool Skip(u32 len) + { + if (NumOccupied < len) return false; + + ReadPos += len; + if (ReadPos >= Size) + ReadPos -= Size; + + NumOccupied -= len; + return true; + } + + u32 Level() const { return NumOccupied; } + bool IsEmpty() const { return NumOccupied == 0; } + bool IsFull() const { return NumOccupied >= Size; } + + bool CanFit(u32 num) const { return ((NumOccupied + num) <= Size); } + +private: + u8 Buffer[Size] = {0}; + u32 NumOccupied = 0; + u32 ReadPos = 0, WritePos = 0; +}; + } + #endif