[*] Fix auline macro under msvc
[*] Breakout ByteBuffer into inl files
This commit is contained in:
parent
da2b59d083
commit
62aecf3308
@ -1,7 +0,0 @@
|
||||
/***
|
||||
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Array.hpp
|
||||
Date: 2021-8-5
|
||||
Author: Reece
|
||||
***/
|
@ -176,515 +176,58 @@ namespace Aurora::Memory
|
||||
}
|
||||
|
||||
// Iterator
|
||||
AUKN_SYM AuUInt8 *begin() const;
|
||||
AUKN_SYM AuUInt8 *end() const;
|
||||
inline auline AuUInt8 * begin() const;
|
||||
inline auline AuUInt8 * end() const;
|
||||
|
||||
// To alternative types
|
||||
AUKN_SYM AuList<AuUInt8> ToVector() const;
|
||||
|
||||
// Seek
|
||||
AUKN_SYM bool ReaderTryGoForward(AuUInt32 offset);
|
||||
AUKN_SYM bool ReaderTryGoBack(AuUInt32 offset);
|
||||
|
||||
AUKN_SYM bool WriterTryGoForward(AuUInt32 offset);
|
||||
// Utils To alternative types
|
||||
inline auline AuList<AuUInt8> ToVector() const;
|
||||
|
||||
inline AuUInt32 GetAllocationPower() const;
|
||||
inline operator AuList<AuUInt8>() const;
|
||||
inline operator MemoryViewRead() const;
|
||||
|
||||
inline AuList<AuUInt8> RemainingBytesToVector(bool endAtWrite = true) const;
|
||||
|
||||
|
||||
AUKN_SYM AuOptional<AuUInt8 *> WriterTryGetWriteHeadFor(AuUInt32 nBytes);
|
||||
// Seek / Position
|
||||
inline auline bool ReaderTryGoForward(AuUInt32 offset);
|
||||
inline auline bool ReaderTryGoBack(AuUInt32 offset);
|
||||
|
||||
inline auline bool WriterTryGoForward(AuUInt32 offset);
|
||||
|
||||
inline AuUInt32 GetAllocationPower() const
|
||||
{
|
||||
return AuUInt32(1) << (AuUInt32(this->scaleSize));
|
||||
}
|
||||
inline auline AuUInt RemainingWrite(bool endAtRead = true);
|
||||
inline auline AuUInt RemainingBytes(bool endAtWrite = true);
|
||||
|
||||
inline operator AuList<AuUInt8>() const
|
||||
{
|
||||
return ToVector();
|
||||
}
|
||||
inline auline bool Skip(AuUInt count);
|
||||
inline auline AuUInt GetReadOffset() const;
|
||||
inline auline AuUInt GetWriteOffset() const;
|
||||
|
||||
inline operator MemoryViewRead() const
|
||||
{
|
||||
return MemoryViewRead(begin(), end());
|
||||
}
|
||||
|
||||
inline AuOptional<AuUInt8 *> WriterTryGetWriteHeadFor(AuUInt32 nBytes);
|
||||
|
||||
inline bool Allocate(AuUInt length, bool fast = true)
|
||||
{
|
||||
if (this->base)
|
||||
{
|
||||
Free(this->base);
|
||||
this->base = nullptr;
|
||||
}
|
||||
this->base = fast ? FAlloc<AuUInt8 *>(length) : ZAlloc<AuUInt8 *>(length);
|
||||
if (!this->base)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this->length = length;
|
||||
this->allocSize = length;
|
||||
this->readPtr = this->base;
|
||||
this->writePtr = this->readPtr + this->length;
|
||||
return true;
|
||||
}
|
||||
// Memory operations
|
||||
|
||||
inline bool SetBuffer(const void *in, AuUInt length)
|
||||
{
|
||||
if (!Allocate(length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
inline auline bool Allocate(AuUInt length, bool fast = true);
|
||||
inline auline bool SetBuffer(const void *in, AuUInt length);
|
||||
inline auline bool SetBuffer(const AuList<AuUInt8> &buffer);
|
||||
|
||||
std::memcpy(this->base, in, this->length);
|
||||
return true;
|
||||
}
|
||||
inline auline void GC();
|
||||
|
||||
inline bool SetBuffer(const AuList<AuUInt8> &buffer)
|
||||
{
|
||||
return SetBuffer(buffer.data(), buffer.size());
|
||||
}
|
||||
inline auline bool Resize(AuUInt length);
|
||||
|
||||
// Template implementation
|
||||
// TODO: move to .inl
|
||||
// Basic Read Write
|
||||
|
||||
inline auline AuUInt Write(const void *buffer, AuUInt requestLength);
|
||||
inline auline AuUInt Read(void *out, AuUInt requestedLength, bool peek = false);
|
||||
|
||||
// Typed read/write
|
||||
template<typename T>
|
||||
T Read();
|
||||
|
||||
template<typename T>
|
||||
inline bool Read(T &out)
|
||||
{
|
||||
if constexpr (std::is_class_v<T>)
|
||||
{
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, std::remove_reference_t<T>>::value)
|
||||
{
|
||||
if (Read<AuUInt32>() != sizeof(typename T::value_type))
|
||||
{
|
||||
this->flagReadError = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto len = Read<AuUInt32>();
|
||||
out.resize(len);
|
||||
|
||||
for (auto i = 0u; i < len; i++)
|
||||
{
|
||||
Read<T::value_type>(out[i]);
|
||||
}
|
||||
|
||||
return !this->flagReadError;
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::remove_reference_t<T>, AuString>)
|
||||
{
|
||||
out.resize(Read<AuUInt32>());
|
||||
Read(out.data(), out.size());
|
||||
return !this->flagReadError;
|
||||
}
|
||||
}
|
||||
|
||||
auto skipped = Read(&out, sizeof(T));
|
||||
if (skipped != sizeof(T))
|
||||
{
|
||||
this->flagReadError = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Write(const T &in);
|
||||
|
||||
template<typename T>
|
||||
inline T Read()
|
||||
{
|
||||
T a{};
|
||||
Read(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool Write(const T &in)
|
||||
{
|
||||
if constexpr (std::is_class_v<T>)
|
||||
{
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, std::remove_reference_t<T>>::value)
|
||||
{
|
||||
Write<AuUInt32>(sizeof(typename T::value_type));
|
||||
Write<AuUInt32>(AuUInt32(in.size()));
|
||||
|
||||
for (const auto &item : in)
|
||||
{
|
||||
Write<T::value_type>(item);
|
||||
}
|
||||
|
||||
return !this->flagWriteError;
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::remove_reference_t<T>, AuString>)
|
||||
{
|
||||
Write<AuUInt32>(AuUInt32(in.size()));
|
||||
Write(in.data(), in.size());
|
||||
return !this->flagWriteError;
|
||||
}
|
||||
}
|
||||
|
||||
auto skipped = Write(&in, sizeof(T));
|
||||
if (skipped != sizeof(T))
|
||||
{
|
||||
this->flagWriteError = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void GC()
|
||||
{
|
||||
if (this->allocSize == this->length) return;
|
||||
auto temp = Memory::FRealloc(this->base, this->length);
|
||||
if (!temp) return;
|
||||
this->base = temp;
|
||||
this->length = this->length;
|
||||
this->allocSize = this->length;
|
||||
}
|
||||
|
||||
inline bool Resize(AuUInt length)
|
||||
{
|
||||
AuUInt oldWriteIdx, oldReadIdx, oldLength, newLength;
|
||||
AuUInt8 *nextRead, *nextWrite, *nextPtr;
|
||||
|
||||
if (this->allocSize > length)
|
||||
{
|
||||
this->length = length;
|
||||
|
||||
oldLength = this->length;
|
||||
newLength = length;
|
||||
nextPtr = this->base;
|
||||
oldWriteIdx = this->writePtr - this->base;
|
||||
oldReadIdx = this->readPtr - this->base;
|
||||
nextRead = nextPtr + oldReadIdx;
|
||||
nextWrite = nextPtr + oldWriteIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scale = GetAllocationPower();
|
||||
oldLength = this->length;
|
||||
newLength = std::max(AuUInt(length), AuUInt(((this->allocSize / scale) + 1) * scale));
|
||||
|
||||
nextPtr = ZRealloc(this->base, newLength);
|
||||
if (!nextPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
oldWriteIdx = this->writePtr - this->base;
|
||||
oldReadIdx = this->readPtr - this->base;
|
||||
nextRead = nextPtr + oldReadIdx;
|
||||
nextWrite = nextPtr + oldWriteIdx;
|
||||
|
||||
this->allocSize = newLength;
|
||||
this->length = length;
|
||||
}
|
||||
|
||||
this->base = nextPtr;
|
||||
|
||||
if (!flagCircular)
|
||||
{
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->writePtr > this->readPtr)
|
||||
{
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto expansion = newLength - oldLength;
|
||||
auto movableTail = std::min(oldWriteIdx, expansion);
|
||||
|
||||
std::memcpy(nextPtr + oldLength, nextPtr, movableTail);
|
||||
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextPtr + oldLength + movableTail;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline AuUInt Write(const void *buffer, AuUInt requestLength)
|
||||
{
|
||||
AuUInt linearOverhead = 0, toReadOverhead = 0, linearWritable = 0, toReadWritable = 0, writable = 0;
|
||||
auto cptr = reinterpret_cast<const AuUInt8 *>(buffer);
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
// 0 1 2 3 4 5
|
||||
// W R
|
||||
// 6 - (1) = 5 -> read bound; we have zero overhead not 5
|
||||
|
||||
if (writePtr < readPtr)
|
||||
{
|
||||
// Handle read-bound writes
|
||||
linearOverhead = readPtr - writePtr;
|
||||
toReadOverhead = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle ordinary stream consume bound IO
|
||||
linearOverhead = length - (writePtr - base);
|
||||
toReadOverhead = readPtr - base;
|
||||
}
|
||||
|
||||
writable = std::min(linearOverhead + toReadOverhead, requestLength);
|
||||
|
||||
linearWritable = std::min(linearOverhead, requestLength);
|
||||
toReadWritable = writable - linearWritable;
|
||||
|
||||
if (cptr)
|
||||
{
|
||||
std::memcpy(writePtr, cptr, linearWritable);
|
||||
}
|
||||
writePtr += linearWritable;
|
||||
|
||||
if (toReadWritable)
|
||||
{
|
||||
writePtr = base;
|
||||
if (cptr)
|
||||
{
|
||||
std::memcpy(writePtr, cptr + linearOverhead, toReadWritable);
|
||||
}
|
||||
writePtr += toReadWritable;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (writePtr == base + length)
|
||||
{
|
||||
writePtr = base;
|
||||
}
|
||||
#endif
|
||||
|
||||
return linearWritable + toReadWritable;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto offset = writePtr - base;
|
||||
auto overhead = length - offset;
|
||||
|
||||
AuUInt len = std::min(overhead, requestLength);
|
||||
|
||||
if ((len != requestLength) && (flagExpandable))
|
||||
{
|
||||
if (!Resize(offset + requestLength))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
overhead = length - offset;
|
||||
len = std::min(overhead, requestLength);
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
std::memcpy(writePtr, buffer, len);
|
||||
}
|
||||
|
||||
writePtr += len;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
inline AuUInt RemainingBytes(bool endAtWrite = true)
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((readPtr < writePtr) && (endAtWrite))
|
||||
{
|
||||
return length - (writePtr - readPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (readPtr - base);
|
||||
auto toWriteOverhead = writePtr - base;
|
||||
return linearOverhead + toWriteOverhead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (endAtWrite)
|
||||
{
|
||||
if (writePtr < readPtr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return writePtr - readPtr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (length - (readPtr - base));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline AuUInt RemainingWrite(bool endAtRead = true)
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((writePtr < readPtr) && (endAtRead))
|
||||
{
|
||||
return length - (readPtr - writePtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (writePtr - base);
|
||||
auto toWriteOverhead = readPtr - base;
|
||||
return linearOverhead + toWriteOverhead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return length - (writePtr - base);
|
||||
}
|
||||
}
|
||||
|
||||
inline AuList<AuUInt8> RemainingBytesToVector(bool endAtWrite = true) const
|
||||
{
|
||||
AuList<AuUInt8> vec;
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((readPtr < writePtr) && (endAtWrite))
|
||||
{
|
||||
auto len = length - (writePtr - readPtr);
|
||||
|
||||
vec.resize(len);
|
||||
std::memcpy(vec.data(), readPtr, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (readPtr - base);
|
||||
auto toWriteOverhead = endAtWrite ? (writePtr - base) : (readPtr - base);
|
||||
|
||||
vec.resize(linearOverhead + toWriteOverhead);
|
||||
std::memcpy(vec.data(), readPtr, linearOverhead);
|
||||
std::memcpy(vec.data() + linearOverhead, base, linearOverhead);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AuUInt len;
|
||||
if (endAtWrite)
|
||||
{
|
||||
len = writePtr - readPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = length - (readPtr - base);
|
||||
}
|
||||
|
||||
vec.resize(len);
|
||||
std::memcpy(vec.data(), readPtr, len);
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
inline bool Skip(AuUInt count)
|
||||
{
|
||||
auto oldptr = readPtr;
|
||||
auto skipped = Read(nullptr, count);
|
||||
if (skipped != count)
|
||||
{
|
||||
readPtr = oldptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline AuUInt GetReadOffset() const
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return readPtr - base;
|
||||
}
|
||||
}
|
||||
|
||||
inline AuUInt GetWriteOffset() const
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return writePtr - base;
|
||||
}
|
||||
}
|
||||
|
||||
inline AuUInt Read(void *out, AuUInt requestedLength, bool peek = false)
|
||||
{
|
||||
AuUInt linearOverhead = 0, toWriteOverhead = 0, linearReadable = 0, toWriteReadable = 0;
|
||||
if (flagCircular)
|
||||
{
|
||||
if (readPtr < writePtr)
|
||||
{
|
||||
linearOverhead = writePtr - readPtr;
|
||||
toWriteOverhead = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
linearOverhead = length - (readPtr - base);
|
||||
toWriteOverhead = writePtr - base;
|
||||
}
|
||||
|
||||
auto readable = std::min(linearOverhead + toWriteOverhead, requestedLength);
|
||||
|
||||
linearReadable = std::min(linearOverhead, requestedLength);
|
||||
toWriteReadable = readable - linearReadable;
|
||||
|
||||
if (out)
|
||||
{
|
||||
std::memcpy(out, readPtr, linearOverhead);
|
||||
}
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
readPtr += linearOverhead;
|
||||
}
|
||||
|
||||
if (toWriteOverhead)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<AuUInt8 *>(out) + linearOverhead, base, toWriteReadable);
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
readPtr = base + toWriteReadable;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (readPtr == base + length)
|
||||
{
|
||||
readPtr = base;
|
||||
}
|
||||
#endif
|
||||
|
||||
return linearReadable + toWriteReadable;
|
||||
}
|
||||
else
|
||||
{
|
||||
AuUInt len = std::min(AuUInt(writePtr - readPtr), requestedLength);
|
||||
|
||||
if (out)
|
||||
{
|
||||
std::memcpy(out, readPtr, len);
|
||||
}
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
readPtr += len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
||||
bool Read(T &out);
|
||||
};
|
||||
}
|
123
Include/Aurora/Memory/ByteBuffer_Memory.inl
Normal file
123
Include/Aurora/Memory/ByteBuffer_Memory.inl
Normal file
@ -0,0 +1,123 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ByteBuffer_Memory.inl
|
||||
Date: 2022-1-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
bool ByteBuffer::Allocate(AuUInt length, bool fast)
|
||||
{
|
||||
if (this->base)
|
||||
{
|
||||
Free(this->base);
|
||||
this->base = nullptr;
|
||||
}
|
||||
this->base = fast ? FAlloc<AuUInt8 *>(length) : ZAlloc<AuUInt8 *>(length);
|
||||
if (!this->base)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this->length = length;
|
||||
this->allocSize = length;
|
||||
this->readPtr = this->base;
|
||||
this->writePtr = this->readPtr + this->length;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ByteBuffer::SetBuffer(const void *in, AuUInt length)
|
||||
{
|
||||
if (!Allocate(length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(this->base, in, this->length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ByteBuffer::SetBuffer(const AuList<AuUInt8> &buffer)
|
||||
{
|
||||
return SetBuffer(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
void ByteBuffer::GC()
|
||||
{
|
||||
if (this->allocSize == this->length) return;
|
||||
auto temp = Memory::FRealloc(this->base, this->length);
|
||||
if (!temp) return;
|
||||
this->base = temp;
|
||||
this->length = this->length;
|
||||
this->allocSize = this->length;
|
||||
}
|
||||
|
||||
bool ByteBuffer::Resize(AuUInt length)
|
||||
{
|
||||
AuUInt oldWriteIdx, oldReadIdx, oldLength, newLength;
|
||||
AuUInt8 *nextRead, *nextWrite, *nextPtr;
|
||||
|
||||
if (this->allocSize > length)
|
||||
{
|
||||
this->length = length;
|
||||
|
||||
oldLength = this->length;
|
||||
newLength = length;
|
||||
nextPtr = this->base;
|
||||
oldWriteIdx = this->writePtr - this->base;
|
||||
oldReadIdx = this->readPtr - this->base;
|
||||
nextRead = nextPtr + oldReadIdx;
|
||||
nextWrite = nextPtr + oldWriteIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scale = GetAllocationPower();
|
||||
oldLength = this->length;
|
||||
newLength = std::max(AuUInt(length), AuUInt(((this->allocSize / scale) + 1) * scale));
|
||||
|
||||
nextPtr = ZRealloc(this->base, newLength);
|
||||
if (!nextPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
oldWriteIdx = this->writePtr - this->base;
|
||||
oldReadIdx = this->readPtr - this->base;
|
||||
nextRead = nextPtr + oldReadIdx;
|
||||
nextWrite = nextPtr + oldWriteIdx;
|
||||
|
||||
this->allocSize = newLength;
|
||||
this->length = length;
|
||||
}
|
||||
|
||||
this->base = nextPtr;
|
||||
|
||||
if (!flagCircular)
|
||||
{
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->writePtr > this->readPtr)
|
||||
{
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto expansion = newLength - oldLength;
|
||||
auto movableTail = std::min(oldWriteIdx, expansion);
|
||||
|
||||
std::memcpy(nextPtr + oldLength, nextPtr, movableTail);
|
||||
|
||||
this->readPtr = nextRead;
|
||||
this->writePtr = nextPtr + oldLength + movableTail;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
206
Include/Aurora/Memory/ByteBuffer_Position.inl
Normal file
206
Include/Aurora/Memory/ByteBuffer_Position.inl
Normal file
@ -0,0 +1,206 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ByteBuffer_Position.inl
|
||||
Date: 2022-1-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
bool ByteBuffer::WriterTryGoForward(AuUInt32 offset)
|
||||
{
|
||||
auto n = Write(nullptr, offset);
|
||||
SysAssert(n == offset); // TODO: writer go back
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ByteBuffer::ReaderTryGoForward(AuUInt32 offset)
|
||||
{
|
||||
auto n = Read(nullptr, offset, false);
|
||||
if (n != offset)
|
||||
{
|
||||
SysAssert(ReaderTryGoBack(n));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AuOptional<AuUInt8 *> ByteBuffer::WriterTryGetWriteHeadFor(AuUInt32 nBytes)
|
||||
{
|
||||
if (writePtr == base + length)
|
||||
{
|
||||
writePtr = base;
|
||||
}
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
AuUInt32 linearOverhead;
|
||||
if (writePtr < readPtr)
|
||||
{
|
||||
linearOverhead = readPtr - writePtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
linearOverhead = length - (writePtr - base);
|
||||
}
|
||||
|
||||
if (linearOverhead < nBytes)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length - (writePtr - base) < nBytes)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return writePtr;
|
||||
}
|
||||
|
||||
bool ByteBuffer::ReaderTryGoBack(AuUInt32 offset)
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
auto readOffset = readPtr - base;
|
||||
|
||||
if (readOffset < offset)
|
||||
{
|
||||
auto absPosition = offset - readOffset;
|
||||
auto goAround = absPosition;
|
||||
auto backIdx = length - goAround;
|
||||
|
||||
auto writeOffset = writePtr - base;
|
||||
if (writeOffset > backIdx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
readPtr = base + backIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto writeOffset = writePtr - base;
|
||||
auto backIdx = readOffset - offset;
|
||||
|
||||
if (writeOffset > backIdx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
readPtr = base + backIdx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto readOffset = readPtr - base;
|
||||
|
||||
if (readOffset < offset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
readPtr -= offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AuUInt ByteBuffer::RemainingBytes(bool endAtWrite)
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((readPtr < writePtr) && (endAtWrite))
|
||||
{
|
||||
return length - (writePtr - readPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (readPtr - base);
|
||||
auto toWriteOverhead = writePtr - base;
|
||||
return linearOverhead + toWriteOverhead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (endAtWrite)
|
||||
{
|
||||
if (writePtr < readPtr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return writePtr - readPtr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (length - (readPtr - base));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AuUInt ByteBuffer::RemainingWrite(bool endAtRead)
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((writePtr < readPtr) && (endAtRead))
|
||||
{
|
||||
return length - (readPtr - writePtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (writePtr - base);
|
||||
auto toWriteOverhead = readPtr - base;
|
||||
return linearOverhead + toWriteOverhead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return length - (writePtr - base);
|
||||
}
|
||||
}
|
||||
|
||||
bool ByteBuffer::Skip(AuUInt count)
|
||||
{
|
||||
auto oldptr = readPtr;
|
||||
auto skipped = Read(nullptr, count);
|
||||
if (skipped != count)
|
||||
{
|
||||
readPtr = oldptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AuUInt ByteBuffer::GetReadOffset() const
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return readPtr - base;
|
||||
}
|
||||
}
|
||||
|
||||
AuUInt ByteBuffer::GetWriteOffset() const
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return writePtr - base;
|
||||
}
|
||||
}
|
||||
}
|
163
Include/Aurora/Memory/ByteBuffer_ReadWrite.inl
Normal file
163
Include/Aurora/Memory/ByteBuffer_ReadWrite.inl
Normal file
@ -0,0 +1,163 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ByteBuffer_ReadWrite.inl
|
||||
Date: 2022-1-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
AuUInt ByteBuffer::Write(const void *buffer, AuUInt requestLength)
|
||||
{
|
||||
AuUInt linearOverhead = 0, toReadOverhead = 0, linearWritable = 0, toReadWritable = 0, writable = 0;
|
||||
auto cptr = reinterpret_cast<const AuUInt8 *>(buffer);
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
// 0 1 2 3 4 5
|
||||
// W R
|
||||
// 6 - (1) = 5 -> read bound; we have zero overhead not 5
|
||||
|
||||
if (writePtr < readPtr)
|
||||
{
|
||||
// Handle read-bound writes
|
||||
linearOverhead = readPtr - writePtr;
|
||||
toReadOverhead = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle ordinary stream consume bound IO
|
||||
linearOverhead = length - (writePtr - base);
|
||||
toReadOverhead = readPtr - base;
|
||||
}
|
||||
|
||||
writable = std::min(linearOverhead + toReadOverhead, requestLength);
|
||||
|
||||
linearWritable = std::min(linearOverhead, requestLength);
|
||||
toReadWritable = writable - linearWritable;
|
||||
|
||||
if (cptr)
|
||||
{
|
||||
std::memcpy(writePtr, cptr, linearWritable);
|
||||
}
|
||||
writePtr += linearWritable;
|
||||
|
||||
if (toReadWritable)
|
||||
{
|
||||
writePtr = base;
|
||||
if (cptr)
|
||||
{
|
||||
std::memcpy(writePtr, cptr + linearOverhead, toReadWritable);
|
||||
}
|
||||
writePtr += toReadWritable;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (writePtr == base + length)
|
||||
{
|
||||
writePtr = base;
|
||||
}
|
||||
#endif
|
||||
|
||||
return linearWritable + toReadWritable;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto offset = writePtr - base;
|
||||
auto overhead = length - offset;
|
||||
|
||||
AuUInt len = std::min(overhead, requestLength);
|
||||
|
||||
if ((len != requestLength) && (flagExpandable))
|
||||
{
|
||||
if (!Resize(offset + requestLength))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
overhead = length - offset;
|
||||
len = std::min(overhead, requestLength);
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
std::memcpy(writePtr, buffer, len);
|
||||
}
|
||||
|
||||
writePtr += len;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AuUInt ByteBuffer::Read(void *out, AuUInt requestedLength, bool peek)
|
||||
{
|
||||
AuUInt linearOverhead = 0, toWriteOverhead = 0, linearReadable = 0, toWriteReadable = 0;
|
||||
if (flagCircular)
|
||||
{
|
||||
if (readPtr < writePtr)
|
||||
{
|
||||
linearOverhead = writePtr - readPtr;
|
||||
toWriteOverhead = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
linearOverhead = length - (readPtr - base);
|
||||
toWriteOverhead = writePtr - base;
|
||||
}
|
||||
|
||||
auto readable = std::min(linearOverhead + toWriteOverhead, requestedLength);
|
||||
|
||||
linearReadable = std::min(linearOverhead, requestedLength);
|
||||
toWriteReadable = readable - linearReadable;
|
||||
|
||||
if (out)
|
||||
{
|
||||
std::memcpy(out, readPtr, linearOverhead);
|
||||
}
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
readPtr += linearOverhead;
|
||||
}
|
||||
|
||||
if (toWriteOverhead)
|
||||
{
|
||||
std::memcpy(reinterpret_cast<AuUInt8 *>(out) + linearOverhead, base, toWriteReadable);
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
readPtr = base + toWriteReadable;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (readPtr == base + length)
|
||||
{
|
||||
readPtr = base;
|
||||
}
|
||||
#endif
|
||||
|
||||
return linearReadable + toWriteReadable;
|
||||
}
|
||||
else
|
||||
{
|
||||
AuUInt len = std::min(AuUInt(writePtr - readPtr), requestedLength);
|
||||
|
||||
if (out)
|
||||
{
|
||||
std::memcpy(out, readPtr, len);
|
||||
}
|
||||
|
||||
if (!peek)
|
||||
{
|
||||
readPtr += len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
13
Include/Aurora/Memory/ByteBuffer_TaggedReadWrite.inl
Normal file
13
Include/Aurora/Memory/ByteBuffer_TaggedReadWrite.inl
Normal file
@ -0,0 +1,13 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ByteBuffer_TaggedReadWrite.inl
|
||||
Date: 2022-1-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
|
||||
}
|
93
Include/Aurora/Memory/ByteBuffer_TypedReadWrite.inl
Normal file
93
Include/Aurora/Memory/ByteBuffer_TypedReadWrite.inl
Normal file
@ -0,0 +1,93 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ByteBuffer_TypedReadWrite.inl
|
||||
Date: 2022-1-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
template<typename T>
|
||||
bool ByteBuffer::Read(T &out)
|
||||
{
|
||||
if constexpr (std::is_class_v<T>)
|
||||
{
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, std::remove_reference_t<T>>::value)
|
||||
{
|
||||
if (Read<AuUInt32>() != sizeof(typename T::value_type))
|
||||
{
|
||||
this->flagReadError = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto len = Read<AuUInt32>();
|
||||
out.resize(len);
|
||||
|
||||
for (auto i = 0u; i < len; i++)
|
||||
{
|
||||
Read<T::value_type>(out[i]);
|
||||
}
|
||||
|
||||
return !this->flagReadError;
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::remove_reference_t<T>, AuString>)
|
||||
{
|
||||
out.resize(Read<AuUInt32>());
|
||||
Read(out.data(), out.size());
|
||||
return !this->flagReadError;
|
||||
}
|
||||
}
|
||||
|
||||
auto skipped = Read(&out, sizeof(T));
|
||||
if (skipped != sizeof(T))
|
||||
{
|
||||
this->flagReadError = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T ByteBuffer::Read()
|
||||
{
|
||||
T a {};
|
||||
Read(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ByteBuffer::Write(const T &in)
|
||||
{
|
||||
if constexpr (std::is_class_v<T>)
|
||||
{
|
||||
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, std::remove_reference_t<T>>::value)
|
||||
{
|
||||
Write<AuUInt32>(sizeof(typename T::value_type));
|
||||
Write<AuUInt32>(AuUInt32(in.size()));
|
||||
|
||||
for (const auto &item : in)
|
||||
{
|
||||
Write<T::value_type>(item);
|
||||
}
|
||||
|
||||
return !this->flagWriteError;
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::remove_reference_t<T>, AuString>)
|
||||
{
|
||||
Write<AuUInt32>(AuUInt32(in.size()));
|
||||
Write(in.data(), in.size());
|
||||
return !this->flagWriteError;
|
||||
}
|
||||
}
|
||||
|
||||
auto skipped = Write(&in, sizeof(T));
|
||||
if (skipped != sizeof(T))
|
||||
{
|
||||
this->flagWriteError = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
95
Include/Aurora/Memory/ByteBuffer_Utils.inl
Normal file
95
Include/Aurora/Memory/ByteBuffer_Utils.inl
Normal file
@ -0,0 +1,95 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ByteBuffer_Utils.inl
|
||||
Date: 2022-1-18
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
AuList<AuUInt8> ByteBuffer::ToVector() const
|
||||
{
|
||||
AuList<AuUInt8> vec;
|
||||
vec.resize(length);
|
||||
if (flagCircular)
|
||||
{
|
||||
return RemainingBytesToVector(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(vec.data(), base, length);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
AuUInt8 *ByteBuffer::begin() const
|
||||
{
|
||||
SysAssert(!flagCircular, "::begin is only available for linear buffers");
|
||||
return base;
|
||||
}
|
||||
|
||||
AuUInt8 *ByteBuffer::end() const
|
||||
{
|
||||
SysAssert(!flagCircular, "::end is only available for linear buffers");
|
||||
return base + length;
|
||||
}
|
||||
|
||||
AuUInt32 ByteBuffer::GetAllocationPower() const
|
||||
{
|
||||
return AuUInt32(1) << (AuUInt32(this->scaleSize));
|
||||
}
|
||||
|
||||
ByteBuffer::operator AuList<AuUInt8>() const
|
||||
{
|
||||
return ToVector();
|
||||
}
|
||||
|
||||
ByteBuffer::operator MemoryViewRead() const
|
||||
{
|
||||
return MemoryViewRead(begin(), end());
|
||||
}
|
||||
|
||||
AuList<AuUInt8> ByteBuffer::RemainingBytesToVector(bool endAtWrite) const
|
||||
{
|
||||
AuList<AuUInt8> vec;
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
if ((readPtr < writePtr) && (endAtWrite))
|
||||
{
|
||||
auto len = length - (writePtr - readPtr);
|
||||
|
||||
vec.resize(len);
|
||||
std::memcpy(vec.data(), readPtr, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto linearOverhead = length - (readPtr - base);
|
||||
auto toWriteOverhead = endAtWrite ? (writePtr - base) : (readPtr - base);
|
||||
|
||||
vec.resize(linearOverhead + toWriteOverhead);
|
||||
std::memcpy(vec.data(), readPtr, linearOverhead);
|
||||
std::memcpy(vec.data() + linearOverhead, base, linearOverhead);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AuUInt len;
|
||||
if (endAtWrite)
|
||||
{
|
||||
len = writePtr - readPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = length - (readPtr - base);
|
||||
}
|
||||
|
||||
vec.resize(len);
|
||||
std::memcpy(vec.data(), readPtr, len);
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
}
|
@ -145,5 +145,4 @@ namespace Aurora::Memory
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "Array.hpp"
|
||||
#include "ByteBuffer.hpp"
|
||||
#include "ByteBuffer.hpp"
|
7
Include/Aurora/Memory/_ByteBuffer.hpp
Normal file
7
Include/Aurora/Memory/_ByteBuffer.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "ByteBuffer_Utils.inl"
|
||||
#include "ByteBuffer_TaggedReadWrite.inl"
|
||||
#include "ByteBuffer_TypedReadWrite.inl"
|
||||
#include "ByteBuffer_ReadWrite.inl"
|
||||
#include "ByteBuffer_Memory.inl"
|
||||
#include "ByteBuffer_Utils.inl"
|
||||
#include "ByteBuffer_Position.inl"
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "../AuroraMacros.hpp"
|
||||
|
||||
#include <utilitY>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
@ -73,6 +73,8 @@
|
||||
#include "Time/Time.hpp"
|
||||
#include "Loop/Loop.hpp"
|
||||
|
||||
#include "Memory/_ByteBuffer.hpp"
|
||||
|
||||
namespace AuAsync = Aurora::Async;
|
||||
namespace AuBuild = Aurora::Build;
|
||||
namespace AuCompression = Aurora::Compression;
|
||||
|
@ -85,7 +85,7 @@
|
||||
|
||||
#if !defined(AU_INLINE)
|
||||
#if defined(AURORA_COMPILER_MSVC)
|
||||
#define AU_INLINE __declspec(__forceinline)
|
||||
#define AU_INLINE __forceinline
|
||||
#else
|
||||
#define AU_INLINE __attribute__((always_inline))
|
||||
#endif
|
||||
|
@ -10,134 +10,5 @@
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
AuList<AuUInt8> ByteBuffer::ToVector() const
|
||||
{
|
||||
AuList<AuUInt8> vec;
|
||||
vec.resize(length);
|
||||
if (flagCircular)
|
||||
{
|
||||
return RemainingBytesToVector(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(vec.data(), base, length);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
AUKN_SYM bool ByteBuffer::WriterTryGoForward(AuUInt32 offset)
|
||||
{
|
||||
auto n = Write(nullptr, offset);
|
||||
SysAssert(n == offset); // TODO: writer go back
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ByteBuffer::ReaderTryGoForward(AuUInt32 offset)
|
||||
{
|
||||
auto n = Read(nullptr, offset, false);
|
||||
if (n != offset)
|
||||
{
|
||||
SysAssert(ReaderTryGoBack(n));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AuOptional<AuUInt8 *> ByteBuffer::WriterTryGetWriteHeadFor(AuUInt32 nBytes)
|
||||
{
|
||||
if (writePtr == base + length)
|
||||
{
|
||||
writePtr = base;
|
||||
}
|
||||
|
||||
if (flagCircular)
|
||||
{
|
||||
AuUInt32 linearOverhead;
|
||||
if (writePtr < readPtr)
|
||||
{
|
||||
linearOverhead = readPtr - writePtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
linearOverhead = length - (writePtr - base);
|
||||
}
|
||||
|
||||
if (linearOverhead < nBytes)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length - (writePtr - base) < nBytes)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return writePtr;
|
||||
}
|
||||
|
||||
bool ByteBuffer::ReaderTryGoBack(AuUInt32 offset)
|
||||
{
|
||||
if (flagCircular)
|
||||
{
|
||||
auto readOffset = readPtr - base;
|
||||
|
||||
if (readOffset < offset)
|
||||
{
|
||||
auto absPosition = offset - readOffset;
|
||||
auto goAround = absPosition;
|
||||
auto backIdx = length - goAround;
|
||||
|
||||
auto writeOffset = writePtr - base;
|
||||
if (writeOffset > backIdx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
readPtr = base + backIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto writeOffset = writePtr - base;
|
||||
auto backIdx = readOffset - offset;
|
||||
|
||||
if (writeOffset > backIdx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
readPtr = base + backIdx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto readOffset = readPtr - base;
|
||||
|
||||
if (readOffset < offset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
readPtr -= offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AuUInt8 *ByteBuffer::begin() const
|
||||
{
|
||||
SysAssert(!flagCircular, "::begin is only available for linear buffers");
|
||||
return base;
|
||||
}
|
||||
|
||||
AuUInt8 *ByteBuffer::end() const
|
||||
{
|
||||
SysAssert(!flagCircular, "::end is only available for linear buffers");
|
||||
return base + length;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user