#include "StdAfx.h" #include "fs/MemorySink.h" #include "fs/MemorySource.h" #include #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 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(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(tell()); newOffset += offset; newOffset = tl::max(newOffset, 0); seekBeg(static_cast(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 MemorySink::getDataView() const { if (m_optLastError.has_value()) { TL_FAIL(); return {}; } return tl::span{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 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 mView(&m_data[m_offset], bytesToMap); m_offset += bytesToMap; TL_ASSERT(m_offset <= getSize()); return mView; } /////////////////////////////////////////////////////////////////////////////// tl::optional 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(); } /////////////////////////////////////////////////////////////////////////////// }