mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 13:55:38 +00:00
BinaryReaderWriter: Add class for files as well as spans
This commit is contained in:
parent
a3f8162488
commit
ab7a3e1934
|
@ -2,8 +2,8 @@ add_library(common
|
||||||
align.h
|
align.h
|
||||||
assert.cpp
|
assert.cpp
|
||||||
assert.h
|
assert.h
|
||||||
binary_span_reader_writer.cpp
|
binary_reader_writer.cpp
|
||||||
binary_span_reader_writer.h
|
binary_reader_writer.h
|
||||||
bitfield.h
|
bitfield.h
|
||||||
bitutils.h
|
bitutils.h
|
||||||
build_timestamp.h
|
build_timestamp.h
|
||||||
|
|
428
src/common/binary_reader_writer.cpp
Normal file
428
src/common/binary_reader_writer.cpp
Normal file
|
@ -0,0 +1,428 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#include "binary_reader_writer.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "small_string.h"
|
||||||
|
|
||||||
|
#include "common/file_system.h"
|
||||||
|
|
||||||
|
BinarySpanReader::BinarySpanReader() = default;
|
||||||
|
|
||||||
|
BinarySpanReader::BinarySpanReader(std::span<const u8> buf) : m_buf(buf)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BinarySpanReader::BinarySpanReader(BinarySpanReader&& move) : m_buf(std::move(move.m_buf)), m_pos(move.m_pos)
|
||||||
|
{
|
||||||
|
move.m_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinarySpanReader& BinarySpanReader::operator=(BinarySpanReader&& move)
|
||||||
|
{
|
||||||
|
m_buf = std::move(move.m_buf);
|
||||||
|
m_pos = move.m_pos;
|
||||||
|
move.m_pos = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::PeekCString(std::string_view* dst)
|
||||||
|
{
|
||||||
|
size_t pos = m_pos;
|
||||||
|
size_t size = 0;
|
||||||
|
while (pos < m_buf.size())
|
||||||
|
{
|
||||||
|
if (m_buf[pos] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos == m_buf.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*dst = std::string_view(reinterpret_cast<const char*>(&m_buf[m_pos]), size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::PeekSizePrefixedString(std::string_view* dst)
|
||||||
|
{
|
||||||
|
u32 length;
|
||||||
|
if (!PeekU32(&length) || (m_pos + sizeof(length) + length) > m_buf.size()) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*dst = std::string_view(reinterpret_cast<const char*>(&m_buf[m_pos + sizeof(length)]), length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const u8> BinarySpanReader::GetRemainingSpan(size_t size) const
|
||||||
|
{
|
||||||
|
DebugAssert(size <= GetBufferRemaining());
|
||||||
|
return m_buf.subspan(m_pos, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const u8> BinarySpanReader::GetRemainingSpan() const
|
||||||
|
{
|
||||||
|
return m_buf.subspan(m_pos, m_buf.size() - m_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinarySpanReader::IncrementPosition(size_t size)
|
||||||
|
{
|
||||||
|
DebugAssert(size < GetBufferRemaining());
|
||||||
|
m_pos += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::ReadCString(std::string* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekCString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
m_pos += sv.size() + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::ReadCString(std::string_view* dst)
|
||||||
|
{
|
||||||
|
if (!PeekCString(dst))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_pos += dst->size() + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::ReadCString(SmallStringBase* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekCString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
m_pos += sv.size() + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::ReadSizePrefixedString(std::string* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekSizePrefixedString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
m_pos += sizeof(u32) + sv.size();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::ReadSizePrefixedString(std::string_view* dst)
|
||||||
|
{
|
||||||
|
if (!PeekSizePrefixedString(dst))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_pos += sizeof(u32) + dst->size();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::ReadSizePrefixedString(SmallStringBase* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekSizePrefixedString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
m_pos += sizeof(u32) + sv.size();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view BinarySpanReader::ReadCString()
|
||||||
|
{
|
||||||
|
std::string_view ret;
|
||||||
|
if (PeekCString(&ret))
|
||||||
|
m_pos += ret.size() + 1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view BinarySpanReader::ReadSizePrefixedString()
|
||||||
|
{
|
||||||
|
std::string_view ret;
|
||||||
|
if (PeekSizePrefixedString(&ret))
|
||||||
|
m_pos += sizeof(u32) + ret.size();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::PeekCString(std::string* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekCString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::PeekCString(SmallStringBase* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekCString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::PeekSizePrefixedString(std::string* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekSizePrefixedString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanReader::PeekSizePrefixedString(SmallStringBase* dst)
|
||||||
|
{
|
||||||
|
std::string_view sv;
|
||||||
|
if (!PeekSizePrefixedString(&sv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->assign(sv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinarySpanWriter::BinarySpanWriter() = default;
|
||||||
|
|
||||||
|
BinarySpanWriter::BinarySpanWriter(std::span<u8> buf) : m_buf(buf)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BinarySpanWriter::BinarySpanWriter(BinarySpanWriter&& move) : m_buf(std::move(move.m_buf)), m_pos(move.m_pos)
|
||||||
|
{
|
||||||
|
move.m_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinarySpanWriter& BinarySpanWriter::operator=(BinarySpanWriter&& move)
|
||||||
|
{
|
||||||
|
m_buf = std::move(move.m_buf);
|
||||||
|
m_pos = move.m_pos;
|
||||||
|
move.m_pos = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<u8> BinarySpanWriter::GetRemainingSpan(size_t size) const
|
||||||
|
{
|
||||||
|
DebugAssert(size <= GetBufferRemaining());
|
||||||
|
return m_buf.subspan(m_pos, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<u8> BinarySpanWriter::GetRemainingSpan() const
|
||||||
|
{
|
||||||
|
return m_buf.subspan(m_pos, m_buf.size() - m_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinarySpanWriter::IncrementPosition(size_t size)
|
||||||
|
{
|
||||||
|
DebugAssert(size < GetBufferRemaining());
|
||||||
|
m_pos += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanWriter::WriteCString(std::string_view val)
|
||||||
|
{
|
||||||
|
if ((m_pos + val.size() + 1) > m_buf.size()) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!val.empty())
|
||||||
|
std::memcpy(&m_buf[m_pos], val.data(), val.size());
|
||||||
|
|
||||||
|
m_buf[m_pos + val.size()] = 0;
|
||||||
|
m_pos += val.size() + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinarySpanWriter::WriteSizePrefixedString(std::string_view val)
|
||||||
|
{
|
||||||
|
if (val.size() > std::numeric_limits<u32>::max() || (m_pos + sizeof(u32) + val.size()) > m_buf.size()) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u32 usize = static_cast<u32>(val.size());
|
||||||
|
std::memcpy(&m_buf[m_pos], &usize, sizeof(usize));
|
||||||
|
m_pos += sizeof(usize);
|
||||||
|
if (val.size() > 0)
|
||||||
|
{
|
||||||
|
std::memcpy(&m_buf[m_pos], val.data(), val.size());
|
||||||
|
m_pos += val.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileReader::BinaryFileReader() : m_fp(nullptr), m_size(0), m_good(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileReader::BinaryFileReader(std::FILE* fp)
|
||||||
|
: m_fp(fp), m_size(fp ? FileSystem::FSize64(fp) : 0), m_good(fp != nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileReader::BinaryFileReader(BinaryFileReader&& move) : m_fp(move.m_fp), m_size(move.m_size), m_good(move.m_good)
|
||||||
|
{
|
||||||
|
move.m_fp = nullptr;
|
||||||
|
move.m_size = 0;
|
||||||
|
move.m_good = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileReader& BinaryFileReader::operator=(BinaryFileReader&& move)
|
||||||
|
{
|
||||||
|
m_fp = move.m_fp;
|
||||||
|
m_size = move.m_size;
|
||||||
|
m_good = move.m_good;
|
||||||
|
|
||||||
|
move.m_fp = nullptr;
|
||||||
|
move.m_size = 0;
|
||||||
|
move.m_good = false;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileReader::IsAtEnd()
|
||||||
|
{
|
||||||
|
return (FileSystem::FTell64(m_fp) == m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileReader::ReadCString(std::string* dst)
|
||||||
|
{
|
||||||
|
dst->clear();
|
||||||
|
|
||||||
|
while (m_good)
|
||||||
|
{
|
||||||
|
u8 val;
|
||||||
|
if ((m_good = std::fread(&val, sizeof(val), 1, m_fp) == 1))
|
||||||
|
{
|
||||||
|
if (val == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
dst->push_back(static_cast<char>(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_good;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileReader::ReadCString(SmallStringBase* dst)
|
||||||
|
{
|
||||||
|
dst->clear();
|
||||||
|
|
||||||
|
while (m_good)
|
||||||
|
{
|
||||||
|
u8 val;
|
||||||
|
if ((m_good = std::fread(&val, sizeof(val), 1, m_fp) == 1))
|
||||||
|
{
|
||||||
|
if (val == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
dst->push_back(static_cast<char>(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_good;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileReader::ReadSizePrefixedString(std::string* dst)
|
||||||
|
{
|
||||||
|
u32 length;
|
||||||
|
if (!ReadU32(&length)) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->resize(length);
|
||||||
|
return (length == 0 || Read(dst->data(), dst->length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileReader::ReadSizePrefixedString(SmallStringBase* dst)
|
||||||
|
{
|
||||||
|
u32 length;
|
||||||
|
if (!ReadU32(&length)) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dst->resize(length);
|
||||||
|
return (length == 0 || Read(dst->data(), dst->length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BinaryFileReader::ReadCString()
|
||||||
|
{
|
||||||
|
std::string ret;
|
||||||
|
if (!ReadCString(&ret))
|
||||||
|
ret = {};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BinaryFileReader::ReadSizePrefixedString()
|
||||||
|
{
|
||||||
|
std::string ret;
|
||||||
|
if (!ReadSizePrefixedString(&ret))
|
||||||
|
ret = {};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileWriter::BinaryFileWriter() : m_fp(nullptr), m_good(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileWriter::BinaryFileWriter(std::FILE* fp) : m_fp(fp), m_good(fp != nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileWriter::BinaryFileWriter(BinaryFileWriter&& move) : m_fp(move.m_fp), m_good(move.m_good)
|
||||||
|
{
|
||||||
|
move.m_fp = nullptr;
|
||||||
|
move.m_good = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFileWriter& BinaryFileWriter::operator=(BinaryFileWriter&& move)
|
||||||
|
{
|
||||||
|
m_fp = move.m_fp;
|
||||||
|
m_good = move.m_good;
|
||||||
|
|
||||||
|
move.m_fp = nullptr;
|
||||||
|
move.m_good = false;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileWriter::WriteCString(std::string_view val)
|
||||||
|
{
|
||||||
|
if (!val.empty() && (!m_good && std::fwrite(val.data(), val.length(), 1, m_fp) != 1)) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u8 terminator = 0;
|
||||||
|
return (m_good = (m_good && std::fwrite(&terminator, 1, 1, m_fp) == 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileWriter::WriteSizePrefixedString(std::string_view val)
|
||||||
|
{
|
||||||
|
if (val.size() > std::numeric_limits<u32>::max()) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u32 usize = static_cast<u32>(val.size());
|
||||||
|
return (m_good = (m_good && std::fwrite(&usize, sizeof(usize), 1, m_fp) == 1 &&
|
||||||
|
(val.empty() || std::fwrite(val.data(), val.size(), 1, m_fp) == 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryFileWriter::Flush(Error* error)
|
||||||
|
{
|
||||||
|
if (!m_good)
|
||||||
|
{
|
||||||
|
Error::SetStringView(error, "Write error previously occurred.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(m_good = (m_good && std::fflush(m_fp) == 0)))
|
||||||
|
{
|
||||||
|
Error::SetErrno(error, "fflush() failed: ", errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
367
src/common/binary_reader_writer.h
Normal file
367
src/common/binary_reader_writer.h
Normal file
|
@ -0,0 +1,367 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <optional>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
class Error;
|
||||||
|
class SmallStringBase;
|
||||||
|
|
||||||
|
class BinarySpanReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BinarySpanReader();
|
||||||
|
BinarySpanReader(std::span<const u8> buf);
|
||||||
|
|
||||||
|
BinarySpanReader(const BinarySpanReader&) = delete;
|
||||||
|
BinarySpanReader& operator=(const BinarySpanReader&) = delete;
|
||||||
|
|
||||||
|
BinarySpanReader(BinarySpanReader&& move);
|
||||||
|
BinarySpanReader& operator=(BinarySpanReader&& move);
|
||||||
|
|
||||||
|
ALWAYS_INLINE const std::span<const u8>& GetSpan() const { return m_buf; }
|
||||||
|
ALWAYS_INLINE bool IsValid() const { return !m_buf.empty(); }
|
||||||
|
ALWAYS_INLINE bool CheckRemaining(size_t size) { return ((m_pos + size) <= m_buf.size()); }
|
||||||
|
ALWAYS_INLINE size_t GetBufferRemaining() const { return (m_buf.size() - m_pos); }
|
||||||
|
ALWAYS_INLINE size_t GetBufferConsumed() const { return m_pos; }
|
||||||
|
|
||||||
|
std::span<const u8> GetRemainingSpan() const;
|
||||||
|
std::span<const u8> GetRemainingSpan(size_t size) const;
|
||||||
|
void IncrementPosition(size_t size);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
template<typename T> ALWAYS_INLINE bool ReadT(T* dst) { return Read(dst, sizeof(T)); }
|
||||||
|
ALWAYS_INLINE bool ReadBool(bool* dst) { u8 val; if (!Read(&val, sizeof(val))) [[unlikely]] { return false; } *dst = (val != 0); return true; }
|
||||||
|
ALWAYS_INLINE bool ReadS8(s8* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU8(u8* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadS16(s16* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU16(u16* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadS32(s32* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU32(u32* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadS64(s64* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU64(u64* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadFloat(float* dst) { return ReadT(dst); }
|
||||||
|
bool ReadCString(std::string* dst);
|
||||||
|
bool ReadCString(std::string_view* dst);
|
||||||
|
bool ReadCString(SmallStringBase* dst);
|
||||||
|
bool ReadSizePrefixedString(std::string* dst);
|
||||||
|
bool ReadSizePrefixedString(std::string_view* dst);
|
||||||
|
bool ReadSizePrefixedString(SmallStringBase* dst);
|
||||||
|
|
||||||
|
template<typename T> ALWAYS_INLINE T ReadT() { T ret; if (!Read(&ret, sizeof(ret))) [[unlikely]] { ret = {}; } return ret; }
|
||||||
|
ALWAYS_INLINE bool ReadBool() { return (ReadT<u8>() != 0); }
|
||||||
|
ALWAYS_INLINE s8 ReadS8() { return ReadT<s8>(); }
|
||||||
|
ALWAYS_INLINE u8 ReadU8() { return ReadT<u8>(); }
|
||||||
|
ALWAYS_INLINE s16 ReadS16() { return ReadT<s16>(); }
|
||||||
|
ALWAYS_INLINE u16 ReadU16() { return ReadT<u16>(); }
|
||||||
|
ALWAYS_INLINE s32 ReadS32() { return ReadT<s32>(); }
|
||||||
|
ALWAYS_INLINE u32 ReadU32() { return ReadT<u32>(); }
|
||||||
|
ALWAYS_INLINE s64 ReadS64() { return ReadT<s64>(); }
|
||||||
|
ALWAYS_INLINE u64 ReadU64() { return ReadT<u64>(); }
|
||||||
|
ALWAYS_INLINE float ReadFloat() { return ReadT<float>(); }
|
||||||
|
std::string_view ReadCString();
|
||||||
|
std::string_view ReadSizePrefixedString();
|
||||||
|
|
||||||
|
template<typename T> ALWAYS_INLINE bool PeekT(T* dst) { return Peek(dst, sizeof(T)); }
|
||||||
|
ALWAYS_INLINE bool PeekBool(bool* dst) { u8 val; if (!Peek(&val, sizeof(val))) [[unlikely]] { return false; } *dst = (val != 0); return true; }
|
||||||
|
ALWAYS_INLINE bool PeekU8(u8* dst) { return PeekT(dst); }
|
||||||
|
ALWAYS_INLINE bool PeekU16(u16* dst) { return PeekT(dst); }
|
||||||
|
ALWAYS_INLINE bool PeekU32(u32* dst) { return PeekT(dst); }
|
||||||
|
ALWAYS_INLINE bool PeekU64(u64* dst) { return PeekT(dst); }
|
||||||
|
ALWAYS_INLINE bool PeekFloat(float* dst) { return PeekT(dst); }
|
||||||
|
bool PeekCString(std::string* dst);
|
||||||
|
bool PeekCString(std::string_view* dst);
|
||||||
|
bool PeekCString(SmallStringBase* dst);
|
||||||
|
bool PeekSizePrefixedString(std::string* dst);
|
||||||
|
bool PeekSizePrefixedString(std::string_view* dst);
|
||||||
|
bool PeekSizePrefixedString(SmallStringBase* dst);
|
||||||
|
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(s8& val) { val = ReadT<s8>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(u8& val) { val = ReadT<u8>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(s16& val) { val = ReadT<s16>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(u16& val) { val = ReadT<u16>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(s32& val) { val = ReadT<s32>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(u32& val) { val = ReadT<u32>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(s64& val) { val = ReadT<s64>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(u64& val) { val = ReadT<u64>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(float& val) { val = ReadT<float>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanReader& operator>>(std::string_view val) { val = ReadCString(); return *this; }
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ALWAYS_INLINE bool ReadOptionalT(std::optional<T>* dst)
|
||||||
|
{
|
||||||
|
u8 has_value;
|
||||||
|
if (!ReadT(&has_value)) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (has_value == 0)
|
||||||
|
{
|
||||||
|
dst->reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
T value;
|
||||||
|
if (!ReadT(&value)) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*dst = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool Read(void* buf, size_t size)
|
||||||
|
{
|
||||||
|
if ((m_pos + size) <= m_buf.size()) [[likely]]
|
||||||
|
{
|
||||||
|
std::memcpy(buf, &m_buf[m_pos], size);
|
||||||
|
m_pos += size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool Peek(void* buf, size_t size)
|
||||||
|
{
|
||||||
|
if ((m_pos + size) <= m_buf.size()) [[likely]]
|
||||||
|
{
|
||||||
|
std::memcpy(buf, &m_buf[m_pos], size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::span<const u8> m_buf;
|
||||||
|
size_t m_pos = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BinarySpanWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BinarySpanWriter();
|
||||||
|
BinarySpanWriter(std::span<u8> buf);
|
||||||
|
|
||||||
|
BinarySpanWriter(const BinarySpanWriter&) = delete;
|
||||||
|
BinarySpanWriter& operator=(const BinarySpanWriter&) = delete;
|
||||||
|
|
||||||
|
BinarySpanWriter(BinarySpanWriter&& move);
|
||||||
|
BinarySpanWriter& operator=(BinarySpanWriter&& move);
|
||||||
|
|
||||||
|
ALWAYS_INLINE const std::span<u8>& GetSpan() const { return m_buf; }
|
||||||
|
ALWAYS_INLINE bool IsValid() const { return !m_buf.empty(); }
|
||||||
|
ALWAYS_INLINE size_t GetBufferRemaining() const { return (m_buf.size() - m_pos); }
|
||||||
|
ALWAYS_INLINE size_t GetBufferWritten() const { return m_pos; }
|
||||||
|
|
||||||
|
std::span<u8> GetRemainingSpan() const;
|
||||||
|
std::span<u8> GetRemainingSpan(size_t size) const;
|
||||||
|
void IncrementPosition(size_t size);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
template<typename T> ALWAYS_INLINE bool WriteT(T dst) { return Write(&dst, sizeof(T)); }
|
||||||
|
ALWAYS_INLINE bool WriteBool(bool val) { const bool bval = static_cast<u8>(val); return Write(&bval, sizeof(bval)); }
|
||||||
|
ALWAYS_INLINE bool WriteS8(s8 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU8(u8 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteS16(s16 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU16(u16 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteS32(s32 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU32(u32 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteS64(s64 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU64(u64 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteFloat(float val) { return WriteT(val); }
|
||||||
|
bool WriteCString(std::string_view val);
|
||||||
|
bool WriteSizePrefixedString(std::string_view val);
|
||||||
|
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(s8 val) { WriteS8(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(u8 val) { WriteU8(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(s16 val) { WriteS16(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(u16 val) { WriteU16(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(s32 val) { WriteS32(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(u32 val) { WriteU32(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(s64 val) { WriteS64(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(u64 val) { WriteU64(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(float val) { WriteFloat(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinarySpanWriter& operator<<(std::string_view val) { WriteCString(val); return *this; }
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ALWAYS_INLINE bool WriteOptionalT(const std::optional<T>& val)
|
||||||
|
{
|
||||||
|
return (WriteBool(val.has_value()) && (!val.has_value() || WriteT(val.value())));
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool Write(const void* buf, size_t size)
|
||||||
|
{
|
||||||
|
if ((m_pos + size) <= m_buf.size()) [[likely]]
|
||||||
|
{
|
||||||
|
std::memcpy(&m_buf[m_pos], buf, size);
|
||||||
|
m_pos += size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::span<u8> m_buf;
|
||||||
|
size_t m_pos = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BinaryFileReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BinaryFileReader();
|
||||||
|
BinaryFileReader(std::FILE* fp);
|
||||||
|
|
||||||
|
BinaryFileReader(const BinaryFileReader&) = delete;
|
||||||
|
BinaryFileReader& operator=(const BinaryFileReader&) = delete;
|
||||||
|
|
||||||
|
BinaryFileReader(BinaryFileReader&& move);
|
||||||
|
BinaryFileReader& operator=(BinaryFileReader&& move);
|
||||||
|
|
||||||
|
ALWAYS_INLINE const std::FILE* GetFile() const { return m_fp; }
|
||||||
|
ALWAYS_INLINE bool HasError() const { return !m_good; }
|
||||||
|
ALWAYS_INLINE bool IsGood() const { return m_good; }
|
||||||
|
ALWAYS_INLINE bool IsOpen() const { return (m_fp != nullptr); }
|
||||||
|
|
||||||
|
bool IsAtEnd();
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
template<typename T> ALWAYS_INLINE bool ReadT(T* dst) { return Read(dst, sizeof(T)); }
|
||||||
|
ALWAYS_INLINE bool ReadBool(bool* dst) { u8 val; if (!Read(&val, sizeof(val))) [[unlikely]] { return false; } *dst = (val != 0); return true; }
|
||||||
|
ALWAYS_INLINE bool ReadS8(s8* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU8(u8* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadS16(s16* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU16(u16* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadS32(s32* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU32(u32* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadS64(s64* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadU64(u64* dst) { return ReadT(dst); }
|
||||||
|
ALWAYS_INLINE bool ReadFloat(float* dst) { return ReadT(dst); }
|
||||||
|
bool ReadCString(std::string* dst);
|
||||||
|
bool ReadCString(SmallStringBase* dst);
|
||||||
|
bool ReadSizePrefixedString(std::string* dst);
|
||||||
|
bool ReadSizePrefixedString(SmallStringBase* dst);
|
||||||
|
|
||||||
|
template<typename T> ALWAYS_INLINE T ReadT() { T ret; if (!Read(&ret, sizeof(ret))) [[unlikely]] { ret = {}; } return ret; }
|
||||||
|
ALWAYS_INLINE bool ReadBool() { return (ReadT<u8>() != 0); }
|
||||||
|
ALWAYS_INLINE s8 ReadS8() { return ReadT<s8>(); }
|
||||||
|
ALWAYS_INLINE u8 ReadU8() { return ReadT<u8>(); }
|
||||||
|
ALWAYS_INLINE s16 ReadS16() { return ReadT<s16>(); }
|
||||||
|
ALWAYS_INLINE u16 ReadU16() { return ReadT<u16>(); }
|
||||||
|
ALWAYS_INLINE s32 ReadS32() { return ReadT<s32>(); }
|
||||||
|
ALWAYS_INLINE u32 ReadU32() { return ReadT<u32>(); }
|
||||||
|
ALWAYS_INLINE s64 ReadS64() { return ReadT<s64>(); }
|
||||||
|
ALWAYS_INLINE u64 ReadU64() { return ReadT<u64>(); }
|
||||||
|
ALWAYS_INLINE float ReadFloat() { return ReadT<float>(); }
|
||||||
|
std::string ReadCString();
|
||||||
|
std::string ReadSizePrefixedString();
|
||||||
|
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(s8& val) { val = ReadT<s8>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(u8& val) { val = ReadT<u8>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(s16& val) { val = ReadT<s16>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(u16& val) { val = ReadT<u16>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(s32& val) { val = ReadT<s32>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(u32& val) { val = ReadT<u32>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(s64& val) { val = ReadT<s64>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(u64& val) { val = ReadT<u64>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(float& val) { val = ReadT<float>(); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileReader& operator>>(std::string_view val) { val = ReadCString(); return *this; }
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ALWAYS_INLINE bool ReadOptionalT(std::optional<T>* dst)
|
||||||
|
{
|
||||||
|
u8 has_value;
|
||||||
|
if (!ReadT(&has_value)) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (has_value == 0)
|
||||||
|
{
|
||||||
|
dst->reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
T value;
|
||||||
|
if (!ReadT(&value)) [[unlikely]]
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*dst = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool Read(void* buf, size_t size) { return (m_good = (m_good && std::fread(buf, size, 1, m_fp) == 1)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::FILE* m_fp;
|
||||||
|
s64 m_size;
|
||||||
|
bool m_good = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BinaryFileWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BinaryFileWriter();
|
||||||
|
BinaryFileWriter(std::FILE* fp);
|
||||||
|
|
||||||
|
BinaryFileWriter(const BinaryFileWriter&) = delete;
|
||||||
|
BinaryFileWriter& operator=(const BinaryFileWriter&) = delete;
|
||||||
|
|
||||||
|
BinaryFileWriter(BinaryFileWriter&& move);
|
||||||
|
BinaryFileWriter& operator=(BinaryFileWriter&& move);
|
||||||
|
|
||||||
|
ALWAYS_INLINE const std::FILE* GetFile() const { return m_fp; }
|
||||||
|
ALWAYS_INLINE bool HasError() const { return !m_good; }
|
||||||
|
ALWAYS_INLINE bool IsGood() const { return m_good; }
|
||||||
|
ALWAYS_INLINE bool IsOpen() const { return (m_fp != nullptr); }
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
template<typename T> ALWAYS_INLINE bool WriteT(T dst) { return Write(&dst, sizeof(T)); }
|
||||||
|
ALWAYS_INLINE bool WriteBool(bool val) { const bool bval = static_cast<u8>(val); return Write(&bval, sizeof(bval)); }
|
||||||
|
ALWAYS_INLINE bool WriteS8(s8 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU8(u8 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteS16(s16 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU16(u16 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteS32(s32 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU32(u32 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteS64(s64 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteU64(u64 val) { return WriteT(val); }
|
||||||
|
ALWAYS_INLINE bool WriteFloat(float val) { return WriteT(val); }
|
||||||
|
bool WriteCString(std::string_view val);
|
||||||
|
bool WriteSizePrefixedString(std::string_view val);
|
||||||
|
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(s8 val) { WriteS8(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(u8 val) { WriteU8(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(s16 val) { WriteS16(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(u16 val) { WriteU16(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(s32 val) { WriteS32(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(u32 val) { WriteU32(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(s64 val) { WriteS64(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(u64 val) { WriteU64(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(float val) { WriteFloat(val); return *this; }
|
||||||
|
ALWAYS_INLINE BinaryFileWriter& operator<<(std::string_view val) { WriteCString(val); return *this; }
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ALWAYS_INLINE bool WriteOptionalT(const std::optional<T>& val)
|
||||||
|
{
|
||||||
|
return (WriteBool(val.has_value()) && (!val.has_value() || WriteT(val.value())));
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool Write(const void* buf, size_t size)
|
||||||
|
{
|
||||||
|
return (m_good = (m_good && std::fwrite(buf, size, 1, m_fp) == 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Flush(Error* error = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::FILE* m_fp;
|
||||||
|
bool m_good;
|
||||||
|
};
|
|
@ -1,145 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Connor McLaughlin <stenzek@gmail.com>
|
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
||||||
|
|
||||||
#include "binary_span_reader_writer.h"
|
|
||||||
#include "assert.h"
|
|
||||||
#include "small_string.h"
|
|
||||||
|
|
||||||
BinarySpanReader::BinarySpanReader() = default;
|
|
||||||
|
|
||||||
BinarySpanReader::BinarySpanReader(std::span<const u8> buf) : m_buf(buf)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinarySpanReader::PeekCString(std::string_view* dst)
|
|
||||||
{
|
|
||||||
size_t pos = m_pos;
|
|
||||||
size_t size = 0;
|
|
||||||
while (pos < m_buf.size())
|
|
||||||
{
|
|
||||||
if (m_buf[pos] == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
pos++;
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos == m_buf.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*dst = std::string_view(reinterpret_cast<const char*>(&m_buf[m_pos]), size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::span<const u8> BinarySpanReader::GetRemainingSpan(size_t size) const
|
|
||||||
{
|
|
||||||
DebugAssert(size <= GetBufferRemaining());
|
|
||||||
return m_buf.subspan(m_pos, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::span<const u8> BinarySpanReader::GetRemainingSpan() const
|
|
||||||
{
|
|
||||||
return m_buf.subspan(m_pos, m_buf.size() - m_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BinarySpanReader::IncrementPosition(size_t size)
|
|
||||||
{
|
|
||||||
DebugAssert(size < GetBufferRemaining());
|
|
||||||
m_pos += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinarySpanReader::ReadCString(std::string* dst)
|
|
||||||
{
|
|
||||||
std::string_view sv;
|
|
||||||
if (!PeekCString(&sv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dst->assign(sv);
|
|
||||||
m_pos += sv.size() + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinarySpanReader::ReadCString(std::string_view* dst)
|
|
||||||
{
|
|
||||||
if (!PeekCString(dst))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_pos += dst->size() + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinarySpanReader::ReadCString(SmallStringBase* dst)
|
|
||||||
{
|
|
||||||
std::string_view sv;
|
|
||||||
if (!PeekCString(&sv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dst->assign(sv);
|
|
||||||
m_pos += sv.size() + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view BinarySpanReader::ReadCString()
|
|
||||||
{
|
|
||||||
std::string_view ret;
|
|
||||||
if (PeekCString(&ret))
|
|
||||||
m_pos += ret.size() + 1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinarySpanReader::PeekCString(std::string* dst)
|
|
||||||
{
|
|
||||||
std::string_view sv;
|
|
||||||
if (!PeekCString(&sv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dst->assign(sv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinarySpanReader::PeekCString(SmallStringBase* dst)
|
|
||||||
{
|
|
||||||
std::string_view sv;
|
|
||||||
if (!PeekCString(&sv))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dst->assign(sv);
|
|
||||||
m_pos += sv.size() + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarySpanWriter::BinarySpanWriter() = default;
|
|
||||||
|
|
||||||
BinarySpanWriter::BinarySpanWriter(std::span<u8> buf) : m_buf(buf)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::span<u8> BinarySpanWriter::GetRemainingSpan(size_t size) const
|
|
||||||
{
|
|
||||||
DebugAssert(size <= GetBufferRemaining());
|
|
||||||
return m_buf.subspan(m_pos, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::span<u8> BinarySpanWriter::GetRemainingSpan() const
|
|
||||||
{
|
|
||||||
return m_buf.subspan(m_pos, m_buf.size() - m_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BinarySpanWriter::IncrementPosition(size_t size)
|
|
||||||
{
|
|
||||||
DebugAssert(size < GetBufferRemaining());
|
|
||||||
m_pos += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinarySpanWriter::WriteCString(std::string_view val)
|
|
||||||
{
|
|
||||||
if ((m_pos + val.size() + 1) > m_buf.size()) [[unlikely]]
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!val.empty())
|
|
||||||
std::memcpy(&m_buf[m_pos], val.data(), val.size());
|
|
||||||
|
|
||||||
m_buf[m_pos + val.size()] = 0;
|
|
||||||
m_pos += val.size() + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Connor McLaughlin <stenzek@gmail.com>
|
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <span>
|
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
class SmallStringBase;
|
|
||||||
|
|
||||||
class BinarySpanReader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BinarySpanReader();
|
|
||||||
BinarySpanReader(std::span<const u8> buf);
|
|
||||||
|
|
||||||
ALWAYS_INLINE const std::span<const u8>& GetSpan() const { return m_buf; }
|
|
||||||
ALWAYS_INLINE bool IsValid() const { return !m_buf.empty(); }
|
|
||||||
ALWAYS_INLINE bool CheckRemaining(size_t size) { return ((m_pos + size) <= m_buf.size()); }
|
|
||||||
ALWAYS_INLINE size_t GetBufferRemaining() const { return (m_buf.size() - m_pos); }
|
|
||||||
ALWAYS_INLINE size_t GetBufferConsumed() const { return m_pos; }
|
|
||||||
|
|
||||||
std::span<const u8> GetRemainingSpan() const;
|
|
||||||
std::span<const u8> GetRemainingSpan(size_t size) const;
|
|
||||||
void IncrementPosition(size_t size);
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
template<typename T> ALWAYS_INLINE bool ReadT(T* dst) { return Read(dst, sizeof(T)); }
|
|
||||||
ALWAYS_INLINE bool ReadU8(u8* dst) { return ReadT(dst); }
|
|
||||||
ALWAYS_INLINE bool ReadU16(u16* dst) { return ReadT(dst); }
|
|
||||||
ALWAYS_INLINE bool ReadU32(u32* dst) { return ReadT(dst); }
|
|
||||||
ALWAYS_INLINE bool ReadU64(u64* dst) { return ReadT(dst); }
|
|
||||||
ALWAYS_INLINE bool ReadFloat(float* dst) { return ReadT(dst); }
|
|
||||||
bool ReadCString(std::string* dst);
|
|
||||||
bool ReadCString(std::string_view* dst);
|
|
||||||
bool ReadCString(SmallStringBase* dst);
|
|
||||||
|
|
||||||
template<typename T> ALWAYS_INLINE T ReadT() { T ret; if (!Read(&ret, sizeof(ret))) [[unlikely]] { ret = {}; } return ret; }
|
|
||||||
ALWAYS_INLINE u8 ReadU8() { return ReadT<u8>(); }
|
|
||||||
ALWAYS_INLINE u16 ReadU16() { return ReadT<u16>(); }
|
|
||||||
ALWAYS_INLINE u32 ReadU32() { return ReadT<u32>(); }
|
|
||||||
ALWAYS_INLINE u64 ReadU64() { return ReadT<u64>(); }
|
|
||||||
ALWAYS_INLINE float ReadFloat() { return ReadT<float>(); }
|
|
||||||
std::string_view ReadCString();
|
|
||||||
|
|
||||||
template<typename T> ALWAYS_INLINE bool PeekT(T* dst) { return Peek(dst, sizeof(T)); }
|
|
||||||
ALWAYS_INLINE bool PeekU8(u8* dst) { return PeekT(dst); }
|
|
||||||
ALWAYS_INLINE bool PeekU16(u16* dst) { return PeekT(dst); }
|
|
||||||
ALWAYS_INLINE bool PeekU32(u32* dst) { return PeekT(dst); }
|
|
||||||
ALWAYS_INLINE bool PeekU64(u64* dst) { return PeekT(dst); }
|
|
||||||
ALWAYS_INLINE bool PeekFloat(float* dst) { return PeekT(dst); }
|
|
||||||
bool PeekCString(std::string* dst);
|
|
||||||
bool PeekCString(std::string_view* dst);
|
|
||||||
bool PeekCString(SmallStringBase* dst);
|
|
||||||
|
|
||||||
ALWAYS_INLINE BinarySpanReader& operator>>(u8& val) { val = ReadT<u8>(); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanReader& operator>>(u16& val) { val = ReadT<u16>(); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanReader& operator>>(u32& val) { val = ReadT<u32>(); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanReader& operator>>(u64& val) { val = ReadT<u64>(); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanReader& operator>>(float& val) { val = ReadT<float>(); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanReader& operator>>(std::string_view val) { val = ReadCString(); return *this; }
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
private:
|
|
||||||
ALWAYS_INLINE bool Read(void* buf, size_t size)
|
|
||||||
{
|
|
||||||
if ((m_pos + size) <= m_buf.size()) [[likely]]
|
|
||||||
{
|
|
||||||
std::memcpy(buf, &m_buf[m_pos], size);
|
|
||||||
m_pos += size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE bool Peek(void* buf, size_t size)
|
|
||||||
{
|
|
||||||
if ((m_pos + size) <= m_buf.size()) [[likely]]
|
|
||||||
{
|
|
||||||
std::memcpy(buf, &m_buf[m_pos], size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::span<const u8> m_buf;
|
|
||||||
size_t m_pos = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BinarySpanWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BinarySpanWriter();
|
|
||||||
BinarySpanWriter(std::span<u8> buf);
|
|
||||||
|
|
||||||
ALWAYS_INLINE const std::span<u8>& GetSpan() const { return m_buf; }
|
|
||||||
ALWAYS_INLINE bool IsValid() const { return !m_buf.empty(); }
|
|
||||||
ALWAYS_INLINE size_t GetBufferRemaining() const { return (m_buf.size() - m_pos); }
|
|
||||||
ALWAYS_INLINE size_t GetBufferWritten() const { return m_pos; }
|
|
||||||
|
|
||||||
std::span<u8> GetRemainingSpan() const;
|
|
||||||
std::span<u8> GetRemainingSpan(size_t size) const;
|
|
||||||
void IncrementPosition(size_t size);
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
template<typename T> ALWAYS_INLINE bool WriteT(T dst) { return Write(&dst, sizeof(T)); }
|
|
||||||
ALWAYS_INLINE bool WriteU8(u8 val) { return WriteT(val); }
|
|
||||||
ALWAYS_INLINE bool WriteU16(u16 val) { return WriteT(val); }
|
|
||||||
ALWAYS_INLINE bool WriteU32(u32 val) { return WriteT(val); }
|
|
||||||
ALWAYS_INLINE bool WriteU64(u64 val) { return WriteT(val); }
|
|
||||||
ALWAYS_INLINE bool WriteFloat(float val) { return WriteT(val); }
|
|
||||||
bool WriteCString(std::string_view val);
|
|
||||||
|
|
||||||
ALWAYS_INLINE BinarySpanWriter& operator<<(u8 val) { WriteU8(val); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanWriter& operator<<(u16 val) { WriteU16(val); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanWriter& operator<<(u32 val) { WriteU32(val); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanWriter& operator<<(u64 val) { WriteU64(val); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanWriter& operator<<(float val) { WriteFloat(val); return *this; }
|
|
||||||
ALWAYS_INLINE BinarySpanWriter& operator<<(std::string_view val) { WriteCString(val); return *this; }
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
private:
|
|
||||||
ALWAYS_INLINE bool Write(void* buf, size_t size)
|
|
||||||
{
|
|
||||||
if ((m_pos + size) <= m_buf.size()) [[likely]]
|
|
||||||
{
|
|
||||||
std::memcpy(&m_buf[m_pos], buf, size);
|
|
||||||
m_pos += size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::span<u8> m_buf;
|
|
||||||
size_t m_pos = 0;
|
|
||||||
};
|
|
|
@ -38,7 +38,7 @@
|
||||||
<ClInclude Include="sha1_digest.h" />
|
<ClInclude Include="sha1_digest.h" />
|
||||||
<ClInclude Include="small_string.h" />
|
<ClInclude Include="small_string.h" />
|
||||||
<ClInclude Include="heterogeneous_containers.h" />
|
<ClInclude Include="heterogeneous_containers.h" />
|
||||||
<ClInclude Include="binary_span_reader_writer.h" />
|
<ClInclude Include="binary_reader_writer.h" />
|
||||||
<ClInclude Include="string_util.h" />
|
<ClInclude Include="string_util.h" />
|
||||||
<ClInclude Include="thirdparty\SmallVector.h" />
|
<ClInclude Include="thirdparty\SmallVector.h" />
|
||||||
<ClInclude Include="thirdparty\StackWalker.h" />
|
<ClInclude Include="thirdparty\StackWalker.h" />
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
<ClCompile Include="progress_callback.cpp" />
|
<ClCompile Include="progress_callback.cpp" />
|
||||||
<ClCompile Include="sha1_digest.cpp" />
|
<ClCompile Include="sha1_digest.cpp" />
|
||||||
<ClCompile Include="small_string.cpp" />
|
<ClCompile Include="small_string.cpp" />
|
||||||
<ClCompile Include="binary_span_reader_writer.cpp" />
|
<ClCompile Include="binary_reader_writer.cpp" />
|
||||||
<ClCompile Include="string_util.cpp" />
|
<ClCompile Include="string_util.cpp" />
|
||||||
<ClCompile Include="thirdparty\SmallVector.cpp" />
|
<ClCompile Include="thirdparty\SmallVector.cpp" />
|
||||||
<ClCompile Include="thirdparty\StackWalker.cpp" />
|
<ClCompile Include="thirdparty\StackWalker.cpp" />
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<Filter>thirdparty</Filter>
|
<Filter>thirdparty</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="dynamic_library.h" />
|
<ClInclude Include="dynamic_library.h" />
|
||||||
<ClInclude Include="binary_span_reader_writer.h" />
|
<ClInclude Include="binary_reader_writer.h" />
|
||||||
<ClInclude Include="gsvector_sse.h" />
|
<ClInclude Include="gsvector_sse.h" />
|
||||||
<ClInclude Include="gsvector_neon.h" />
|
<ClInclude Include="gsvector_neon.h" />
|
||||||
<ClInclude Include="gsvector.h" />
|
<ClInclude Include="gsvector.h" />
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
<Filter>thirdparty</Filter>
|
<Filter>thirdparty</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="dynamic_library.cpp" />
|
<ClCompile Include="dynamic_library.cpp" />
|
||||||
<ClCompile Include="binary_span_reader_writer.cpp" />
|
<ClCompile Include="binary_reader_writer.cpp" />
|
||||||
<ClCompile Include="gsvector.cpp" />
|
<ClCompile Include="gsvector.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -321,6 +321,22 @@ public:
|
||||||
std::span<T> span() { return std::span<T>(m_data, m_size); }
|
std::span<T> span() { return std::span<T>(m_data, m_size); }
|
||||||
std::span<const T> cspan() const { return std::span<const T>(m_data, m_size); }
|
std::span<const T> cspan() const { return std::span<const T>(m_data, m_size); }
|
||||||
|
|
||||||
|
std::span<T> span(size_t offset, size_t size = static_cast<size_t>(-1))
|
||||||
|
{
|
||||||
|
std::span<T> ret;
|
||||||
|
if (offset < m_size) [[likely]]
|
||||||
|
ret = std::span<T>(m_data + offset, std::min(m_size - offset, size));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const T> cspan(size_t offset, size_t size = static_cast<size_t>(-1)) const
|
||||||
|
{
|
||||||
|
std::span<const T> ret;
|
||||||
|
if (offset < m_size) [[likely]]
|
||||||
|
ret = std::span<const T>(m_data + offset, std::min(m_size - offset, size));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
this_type& operator=(const this_type& rhs)
|
this_type& operator=(const this_type& rhs)
|
||||||
{
|
{
|
||||||
assign(rhs);
|
assign(rhs);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "util/platform_misc.h"
|
#include "util/platform_misc.h"
|
||||||
#include "util/sockets.h"
|
#include "util/sockets.h"
|
||||||
|
|
||||||
#include "common/binary_span_reader_writer.h"
|
#include "common/binary_reader_writer.h"
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
|
Loading…
Reference in a new issue