mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
228 lines
5.4 KiB
C++
228 lines
5.4 KiB
C++
#include "stdafx.h"
|
|
#include "MemoryStream.h"
|
|
|
|
namespace IO
|
|
{
|
|
MemoryStream::MemoryStream()
|
|
: MemoryStream(0)
|
|
{
|
|
}
|
|
|
|
MemoryStream::MemoryStream(uint64_t Capacity)
|
|
{
|
|
this->_Buffer = new uint8_t[Capacity];
|
|
this->_BufferSize = Capacity;
|
|
this->_Length = 0;
|
|
this->_CanWrite = true;
|
|
this->_Expandable = true;
|
|
this->_Origin = 0;
|
|
this->_KeepOpen = false;
|
|
}
|
|
|
|
MemoryStream::MemoryStream(uint8_t* Buffer, uint64_t Index, uint64_t Count)
|
|
: MemoryStream(Buffer, Index, Count, true, false)
|
|
{
|
|
}
|
|
|
|
MemoryStream::MemoryStream(uint8_t* Buffer, uint64_t Index, uint64_t Count, bool Writable)
|
|
: MemoryStream(Buffer, Index, Count, Writable, false)
|
|
{
|
|
}
|
|
|
|
MemoryStream::MemoryStream(uint8_t* Buffer, uint64_t Index, uint64_t Count, bool Writable, bool LeaveOpen)
|
|
: MemoryStream(Buffer, Index, Count, Writable, LeaveOpen, false)
|
|
{
|
|
}
|
|
|
|
MemoryStream::MemoryStream(uint8_t* Buffer, uint64_t Index, uint64_t Count, bool Writable, bool LeaveOpen, bool Expandable)
|
|
{
|
|
if (!Buffer)
|
|
throw std::exception("The buffer must not be null");
|
|
|
|
this->_Buffer = Buffer;
|
|
this->_Origin = Index;
|
|
this->_Position = Index;
|
|
this->_Length = (Index + Count);
|
|
this->_BufferSize = (Index + Count);
|
|
this->_CanWrite = Writable;
|
|
this->_KeepOpen = LeaveOpen;
|
|
this->_Expandable = Expandable;
|
|
}
|
|
|
|
MemoryStream::~MemoryStream()
|
|
{
|
|
//this->Close();
|
|
}
|
|
|
|
bool MemoryStream::CanRead()
|
|
{
|
|
return (this->_Buffer);
|
|
}
|
|
|
|
bool MemoryStream::CanWrite()
|
|
{
|
|
return (this->_Buffer) ? this->_CanWrite : false;
|
|
}
|
|
|
|
bool MemoryStream::CanSeek()
|
|
{
|
|
return (this->_Buffer);
|
|
}
|
|
|
|
bool MemoryStream::GetIsEndOfFile()
|
|
{
|
|
if (!this->_Expandable)
|
|
return (this->_Position == this->_Length);
|
|
return false;
|
|
}
|
|
|
|
uint64_t MemoryStream::GetLength()
|
|
{
|
|
if (!this->_Buffer)
|
|
throw std::exception("Stream not open");
|
|
|
|
return (this->_Length - this->_Origin);
|
|
}
|
|
|
|
uint64_t MemoryStream::GetPosition()
|
|
{
|
|
if (!this->_Buffer)
|
|
throw std::exception("Stream not open");
|
|
|
|
return this->_Position;
|
|
}
|
|
|
|
void MemoryStream::SetLength(uint64_t Length)
|
|
{
|
|
auto nLength = this->_Origin + Length;
|
|
EnsureCapacity(nLength);
|
|
|
|
this->_Length = nLength;
|
|
if (this->_Position > nLength)
|
|
this->_Position = nLength;
|
|
}
|
|
|
|
void MemoryStream::SetPosition(uint64_t Position)
|
|
{
|
|
this->Seek(Position, SeekOrigin::Begin);
|
|
}
|
|
|
|
void MemoryStream::Close()
|
|
{
|
|
if (!this->_KeepOpen && this->_Buffer)
|
|
delete[] this->_Buffer;
|
|
|
|
this->_Buffer = nullptr;
|
|
this->_KeepOpen = false;
|
|
this->_BufferSize = 0;
|
|
this->_CanWrite = false;
|
|
this->_Expandable = true;
|
|
this->_Length = 0;
|
|
this->_Position = 0;
|
|
this->_Origin = 0;
|
|
}
|
|
|
|
void MemoryStream::Flush()
|
|
{
|
|
// This is a non-cached buffer, flush does nothing
|
|
}
|
|
|
|
void MemoryStream::Seek(uint64_t Offset, SeekOrigin Origin)
|
|
{
|
|
if (!this->_Buffer)
|
|
throw std::exception("Stream not open");
|
|
|
|
auto nOffset = this->_Position;
|
|
switch (Origin)
|
|
{
|
|
case SeekOrigin::Begin:
|
|
nOffset = this->_Origin + Offset;
|
|
if ((this->_Position + Offset) < this->_Origin || nOffset < this->_Origin)
|
|
throw std::exception("Attempt to seek outside the bounds of the stream");
|
|
this->_Position = nOffset;
|
|
break;
|
|
case SeekOrigin::Current:
|
|
nOffset = this->_Position + Offset;
|
|
if ((this->_Position + Offset) < this->_Origin || nOffset < this->_Origin)
|
|
throw std::exception("Attempt to seek outside the bounds of the stream");
|
|
this->_Position = nOffset;
|
|
break;
|
|
case SeekOrigin::End:
|
|
nOffset = this->_Length - Offset;
|
|
if ((this->_Length - Offset) < this->_Origin || nOffset < _Origin)
|
|
throw std::exception("Attempt to seek outside the bounds of the stream");
|
|
this->_Position = nOffset;
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint64_t MemoryStream::Read(uint8_t* Buffer, uint64_t Offset, uint64_t Count)
|
|
{
|
|
if (!this->_Buffer)
|
|
throw std::exception("Stream not open");
|
|
|
|
// Ensure we are within the bounds of the buffer
|
|
int64_t nLength = (int64_t)this->_Length - (int64_t)this->_Position;
|
|
if (nLength > (int64_t)Count) nLength = Count;
|
|
if (nLength <= 0)
|
|
return 0;
|
|
|
|
std::memcpy(Buffer + Offset, this->_Buffer + this->_Position, (size_t)nLength);
|
|
this->_Position += nLength;
|
|
|
|
return nLength;
|
|
}
|
|
|
|
uint64_t MemoryStream::Read(uint8_t* Buffer, uint64_t Offset, uint64_t Count, uint64_t Position)
|
|
{
|
|
this->SetPosition(Position);
|
|
return this->Read(Buffer, Offset, Count);
|
|
}
|
|
|
|
void MemoryStream::Write(uint8_t* Buffer, uint64_t Offset, uint64_t Count)
|
|
{
|
|
if (!this->_Buffer)
|
|
throw std::exception("Stream not open");
|
|
if (!this->_CanWrite)
|
|
throw std::exception("Write not supported");
|
|
|
|
auto nBuffer = this->_Position + Count;
|
|
if (nBuffer > this->_Length)
|
|
{
|
|
this->EnsureCapacity(nBuffer);
|
|
this->_Length = nBuffer;
|
|
}
|
|
|
|
std::memcpy(this->_Buffer + this->_Position, Buffer + Offset, Count);
|
|
this->_Position = nBuffer;
|
|
}
|
|
|
|
void MemoryStream::Write(uint8_t* Buffer, uint64_t Offset, uint64_t Count, uint64_t Position)
|
|
{
|
|
this->SetPosition(Position);
|
|
this->Write(Buffer, Offset, Count);
|
|
}
|
|
|
|
void MemoryStream::EnsureCapacity(uint64_t Size)
|
|
{
|
|
if (Size < this->_BufferSize)
|
|
return;
|
|
if (!this->_Expandable)
|
|
throw std::exception("Expand not supported");
|
|
|
|
auto nCapacity = Size;
|
|
if (nCapacity < 256)
|
|
nCapacity = 256;
|
|
|
|
if (nCapacity < this->_BufferSize * 2)
|
|
nCapacity = this->_BufferSize * 2;
|
|
|
|
auto tBuffer = this->_Buffer;
|
|
this->_Buffer = new uint8_t[nCapacity];
|
|
|
|
std::memcpy(this->_Buffer, tBuffer, this->_BufferSize);
|
|
this->_BufferSize = nCapacity;
|
|
|
|
delete[] tBuffer;
|
|
}
|
|
} |