r5sdk/r5dev/thirdparty/cppnet/cppkore/MemoryStream.cpp

228 lines
5.4 KiB
C++
Raw Normal View History

2022-05-21 19:58:09 +02:00
#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;
}
}