Files
FS/src/MemorySink.cpp
T
jeanlemotan b344afa9fe First
2024-07-02 18:12:23 +02:00

260 lines
5.0 KiB
C++

#include "StdAfx.h"
#include "fs/MemorySink.h"
#include "fs/MemorySource.h"
#include <sys/stat.h>
#include "tl/narrow_cast.h"
//////////////////////////////////////////////////////////////////////////
namespace fs
{
///////////////////////////////////////////////////////////////////////////////
MemorySink::MemorySink(size_t reserve)
{
m_data.reserve(reserve);
}
///////////////////////////////////////////////////////////////////////////////
MemorySink::MemorySink(tl::memory_buffer&& buffer)
: m_offset(buffer.size())
, m_data(std::move(buffer))
{
}
//////////////////////////////////////////////////////////////////////////
void MemorySink::reserve(size_t capacity)
{
m_data.reserve(capacity);
}
//////////////////////////////////////////////////////////////////////////
void MemorySink::shrinkToFit()
{
m_data.shrink_to_fit();
}
///////////////////////////////////////////////////////////////////////////////
size_t MemorySink::write(tl::span<const uint8_t> data)
{
if (m_optLastError.has_value())
{
TL_FAIL();
return 0;
}
if (data.empty())
return 0;
const size_t totalSize = m_offset + data.size();
if (m_data.size() < totalSize)
m_data.resize_uninitialized(totalSize);
memcpy(m_data.data() + m_offset, data.data(), data.size());
m_offset += data.size();
return data.size();
}
///////////////////////////////////////////////////////////////////////////////
void MemorySink::seekBeg(uint64_t offset)
{
if (m_optLastError.has_value())
{
TL_FAIL();
return;
}
size_t realOffset;
if constexpr (sizeof(uint64_t) > sizeof(size_t))
realOffset = tl::narrow<size_t>(offset);
else
realOffset = offset;
if (m_offset != realOffset)
{
m_offset = realOffset;
if (m_data.size() < m_offset)
m_data.resize_uninitialized(m_offset);
}
}
///////////////////////////////////////////////////////////////////////////////
void MemorySink::seekRel(int64_t offset)
{
if (m_optLastError.has_value())
{
TL_FAIL();
return;
}
if (offset != 0)
{
int64_t newOffset = static_cast<int64_t>(tell());
newOffset += offset;
newOffset = tl::max<int64_t>(newOffset, 0);
seekBeg(static_cast<uint64_t>(newOffset));
}
}
///////////////////////////////////////////////////////////////////////////////
uint64_t MemorySink::tell() const
{
if (m_optLastError.has_value())
{
TL_FAIL();
return 0;
}
return m_offset;
}
///////////////////////////////////////////////////////////////////////////////
uint64_t MemorySink::getSize() const
{
if (m_optLastError.has_value())
{
TL_FAIL();
return 0;
}
return m_data.size();
}
///////////////////////////////////////////////////////////////////////////////
tl::span<const uint8_t> MemorySink::getDataView() const
{
if (m_optLastError.has_value())
{
TL_FAIL();
return {};
}
return tl::span<const uint8_t>{m_data.data(), m_data.size()};
}
///////////////////////////////////////////////////////////////////////////////
tl::memory_buffer MemorySink::getDataCopy() const
{
if (m_optLastError.has_value())
{
TL_FAIL();
return {};
}
return m_data;
}
///////////////////////////////////////////////////////////////////////////////
tl::memory_buffer MemorySink::getDataMove()
{
if (m_optLastError.has_value())
{
TL_FAIL();
return {};
}
return std::move(m_data);
}
///////////////////////////////////////////////////////////////////////////////
void MemorySink::clear()
{
if (m_optLastError.has_value())
{
TL_FAIL();
return;
}
m_offset = 0;
m_data.clear();
}
///////////////////////////////////////////////////////////////////////////////
void MemorySink::swap(MemorySource& source)
{
if (m_optLastError.has_value())
{
TL_FAIL();
return;
}
tl::swap(source.m_data, m_data);
source.m_offset = 0;
m_offset = 0;
}
///////////////////////////////////////////////////////////////////////////////
tl::span<uint8_t> MemorySink::map(size_t size)
{
if (m_optLastError.has_value())
{
TL_FAIL();
return {};
}
const size_t remainingBytes = m_data.size() - m_offset;
const size_t bytesToMap = tl::min(size, remainingBytes);
if (bytesToMap == 0)
return {};
const tl::span<uint8_t> mView(&m_data[m_offset], bytesToMap);
m_offset += bytesToMap;
TL_ASSERT(m_offset <= getSize());
return mView;
}
///////////////////////////////////////////////////////////////////////////////
tl::optional<Error> MemorySink::getLastError() const
{
auto error = m_optLastError;
m_optLastError = tl::nullopt;
return error;
}
//////////////////////////////////////////////////////////////////////////
size_t MemorySink::getPreferredBufferSize() const
{
return 0;
}
//////////////////////////////////////////////////////////////////////////
void MemorySink::preReserve(size_t size)
{
if (m_optLastError.has_value())
{
TL_FAIL();
return;
}
m_data.reserve(m_data.size() + size);
}
//////////////////////////////////////////////////////////////////////////
tl::memory_buffer MemorySink::extractData(MemorySink sink)
{
return sink.getDataMove();
}
///////////////////////////////////////////////////////////////////////////////
}