Path: blob/master/src/common/binary_reader_writer.cpp
4212 views
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "binary_reader_writer.h"4#include "assert.h"5#include "error.h"6#include "small_string.h"78#include "common/file_system.h"910BinarySpanReader::BinarySpanReader() = default;1112BinarySpanReader::BinarySpanReader(std::span<const u8> buf) : m_buf(buf)13{14}1516BinarySpanReader::BinarySpanReader(BinarySpanReader&& move) : m_buf(std::move(move.m_buf)), m_pos(move.m_pos)17{18move.m_pos = 0;19}2021BinarySpanReader& BinarySpanReader::operator=(BinarySpanReader&& move)22{23m_buf = std::move(move.m_buf);24m_pos = move.m_pos;25move.m_pos = 0;26return *this;27}2829bool BinarySpanReader::PeekCString(std::string_view* dst)30{31size_t pos = m_pos;32size_t size = 0;33while (pos < m_buf.size())34{35if (m_buf[pos] == 0)36break;3738pos++;39size++;40}4142if (pos == m_buf.size())43return false;4445*dst = std::string_view(reinterpret_cast<const char*>(&m_buf[m_pos]), size);46return true;47}4849bool BinarySpanReader::PeekSizePrefixedString(std::string_view* dst)50{51u32 length;52if (!PeekU32(&length) || (m_pos + sizeof(length) + length) > m_buf.size()) [[unlikely]]53return false;5455*dst = std::string_view(reinterpret_cast<const char*>(&m_buf[m_pos + sizeof(length)]), length);56return true;57}5859std::span<const u8> BinarySpanReader::GetRemainingSpan(size_t size) const60{61DebugAssert(size <= GetBufferRemaining());62return m_buf.subspan(m_pos, size);63}6465std::span<const u8> BinarySpanReader::GetRemainingSpan() const66{67return m_buf.subspan(m_pos, m_buf.size() - m_pos);68}6970void BinarySpanReader::IncrementPosition(size_t size)71{72DebugAssert(size < GetBufferRemaining());73m_pos += size;74}7576bool BinarySpanReader::ReadCString(std::string* dst)77{78std::string_view sv;79if (!PeekCString(&sv))80return false;8182dst->assign(sv);83m_pos += sv.size() + 1;84return true;85}8687bool BinarySpanReader::ReadCString(std::string_view* dst)88{89if (!PeekCString(dst))90return false;9192m_pos += dst->size() + 1;93return true;94}9596bool BinarySpanReader::ReadCString(SmallStringBase* dst)97{98std::string_view sv;99if (!PeekCString(&sv))100return false;101102dst->assign(sv);103m_pos += sv.size() + 1;104return true;105}106107bool BinarySpanReader::ReadSizePrefixedString(std::string* dst)108{109std::string_view sv;110if (!PeekSizePrefixedString(&sv))111return false;112113dst->assign(sv);114m_pos += sizeof(u32) + sv.size();115return true;116}117118bool BinarySpanReader::ReadSizePrefixedString(std::string_view* dst)119{120if (!PeekSizePrefixedString(dst))121return false;122123m_pos += sizeof(u32) + dst->size();124return true;125}126127bool BinarySpanReader::ReadSizePrefixedString(SmallStringBase* dst)128{129std::string_view sv;130if (!PeekSizePrefixedString(&sv))131return false;132133dst->assign(sv);134m_pos += sizeof(u32) + sv.size();135return true;136}137138std::string_view BinarySpanReader::ReadCString()139{140std::string_view ret;141if (PeekCString(&ret))142m_pos += ret.size() + 1;143return ret;144}145146std::string_view BinarySpanReader::ReadSizePrefixedString()147{148std::string_view ret;149if (PeekSizePrefixedString(&ret))150m_pos += sizeof(u32) + ret.size();151return ret;152}153154bool BinarySpanReader::PeekCString(std::string* dst)155{156std::string_view sv;157if (!PeekCString(&sv))158return false;159160dst->assign(sv);161return true;162}163164bool BinarySpanReader::PeekCString(SmallStringBase* dst)165{166std::string_view sv;167if (!PeekCString(&sv))168return false;169170dst->assign(sv);171return true;172}173174bool BinarySpanReader::PeekSizePrefixedString(std::string* dst)175{176std::string_view sv;177if (!PeekSizePrefixedString(&sv))178return false;179180dst->assign(sv);181return true;182}183184bool BinarySpanReader::PeekSizePrefixedString(SmallStringBase* dst)185{186std::string_view sv;187if (!PeekSizePrefixedString(&sv))188return false;189190dst->assign(sv);191return true;192}193194BinarySpanWriter::BinarySpanWriter() = default;195196BinarySpanWriter::BinarySpanWriter(std::span<u8> buf) : m_buf(buf)197{198}199200BinarySpanWriter::BinarySpanWriter(BinarySpanWriter&& move) : m_buf(std::move(move.m_buf)), m_pos(move.m_pos)201{202move.m_pos = 0;203}204205BinarySpanWriter& BinarySpanWriter::operator=(BinarySpanWriter&& move)206{207m_buf = std::move(move.m_buf);208m_pos = move.m_pos;209move.m_pos = 0;210return *this;211}212213std::span<u8> BinarySpanWriter::GetRemainingSpan(size_t size) const214{215DebugAssert(size <= GetBufferRemaining());216return m_buf.subspan(m_pos, size);217}218219std::span<u8> BinarySpanWriter::GetRemainingSpan() const220{221return m_buf.subspan(m_pos, m_buf.size() - m_pos);222}223224void BinarySpanWriter::IncrementPosition(size_t size)225{226DebugAssert(size < GetBufferRemaining());227m_pos += size;228}229230bool BinarySpanWriter::WriteCString(std::string_view val)231{232if ((m_pos + val.size() + 1) > m_buf.size()) [[unlikely]]233return false;234235if (!val.empty())236std::memcpy(&m_buf[m_pos], val.data(), val.size());237238m_buf[m_pos + val.size()] = 0;239m_pos += val.size() + 1;240return true;241}242243bool BinarySpanWriter::WriteSizePrefixedString(std::string_view val)244{245if (val.size() > std::numeric_limits<u32>::max() || (m_pos + sizeof(u32) + val.size()) > m_buf.size()) [[unlikely]]246return false;247248const u32 usize = static_cast<u32>(val.size());249std::memcpy(&m_buf[m_pos], &usize, sizeof(usize));250m_pos += sizeof(usize);251if (val.size() > 0)252{253std::memcpy(&m_buf[m_pos], val.data(), val.size());254m_pos += val.size();255}256257return true;258}259260BinaryFileReader::BinaryFileReader() : m_fp(nullptr), m_size(0), m_good(false)261{262}263264BinaryFileReader::BinaryFileReader(std::FILE* fp)265: m_fp(fp), m_size(fp ? FileSystem::FSize64(fp) : 0), m_good(fp != nullptr)266{267}268269BinaryFileReader::BinaryFileReader(BinaryFileReader&& move) : m_fp(move.m_fp), m_size(move.m_size), m_good(move.m_good)270{271move.m_fp = nullptr;272move.m_size = 0;273move.m_good = false;274}275276BinaryFileReader& BinaryFileReader::operator=(BinaryFileReader&& move)277{278m_fp = move.m_fp;279m_size = move.m_size;280m_good = move.m_good;281282move.m_fp = nullptr;283move.m_size = 0;284move.m_good = false;285286return *this;287}288289bool BinaryFileReader::IsAtEnd()290{291return (!m_fp || FileSystem::FTell64(m_fp) == m_size);292}293294bool BinaryFileReader::ReadCString(std::string* dst)295{296dst->clear();297298while (m_good)299{300u8 val;301if ((m_good = std::fread(&val, sizeof(val), 1, m_fp) == 1))302{303if (val == 0)304break;305else306dst->push_back(static_cast<char>(val));307}308}309310return m_good;311}312313bool BinaryFileReader::ReadCString(SmallStringBase* dst)314{315dst->clear();316317while (m_good)318{319u8 val;320if ((m_good = std::fread(&val, sizeof(val), 1, m_fp) == 1))321{322if (val == 0)323break;324else325dst->push_back(static_cast<char>(val));326}327}328329return m_good;330}331332bool BinaryFileReader::ReadSizePrefixedString(std::string* dst)333{334u32 length;335if (!ReadU32(&length)) [[unlikely]]336return false;337338dst->resize(length);339return (length == 0 || Read(dst->data(), dst->length()));340}341342bool BinaryFileReader::ReadSizePrefixedString(SmallStringBase* dst)343{344u32 length;345if (!ReadU32(&length)) [[unlikely]]346return false;347348dst->resize(length);349return (length == 0 || Read(dst->data(), dst->length()));350}351352std::string BinaryFileReader::ReadCString()353{354std::string ret;355if (!ReadCString(&ret))356ret = {};357return ret;358}359360std::string BinaryFileReader::ReadSizePrefixedString()361{362std::string ret;363if (!ReadSizePrefixedString(&ret))364ret = {};365return ret;366}367368BinaryFileWriter::BinaryFileWriter() : m_fp(nullptr), m_good(false)369{370}371372BinaryFileWriter::BinaryFileWriter(std::FILE* fp) : m_fp(fp), m_good(fp != nullptr)373{374}375376BinaryFileWriter::BinaryFileWriter(BinaryFileWriter&& move) : m_fp(move.m_fp), m_good(move.m_good)377{378move.m_fp = nullptr;379move.m_good = false;380}381382BinaryFileWriter& BinaryFileWriter::operator=(BinaryFileWriter&& move)383{384m_fp = move.m_fp;385m_good = move.m_good;386387move.m_fp = nullptr;388move.m_good = false;389390return *this;391}392393bool BinaryFileWriter::WriteCString(std::string_view val)394{395if (!val.empty() && (!m_good && std::fwrite(val.data(), val.length(), 1, m_fp) != 1)) [[unlikely]]396return false;397398const u8 terminator = 0;399return (m_good = (m_good && std::fwrite(&terminator, 1, 1, m_fp) == 1));400}401402bool BinaryFileWriter::WriteSizePrefixedString(std::string_view val)403{404if (val.size() > std::numeric_limits<u32>::max()) [[unlikely]]405return false;406407const u32 usize = static_cast<u32>(val.size());408return (m_good = (m_good && std::fwrite(&usize, sizeof(usize), 1, m_fp) == 1 &&409(val.empty() || std::fwrite(val.data(), val.size(), 1, m_fp) == 1)));410}411412bool BinaryFileWriter::Flush(Error* error)413{414if (!m_good)415{416Error::SetStringView(error, "Write error previously occurred.");417return false;418}419420if (!(m_good = (m_good && std::fflush(m_fp) == 0)))421{422Error::SetErrno(error, "fflush() failed: ", errno);423return false;424}425426return true;427}428429430