diff options
author | MarcoFalke <falke.marco@gmail.com> | 2022-01-02 11:31:25 +0100 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2022-01-02 11:40:31 +0100 |
commit | fa24493d6394b3a477535f480664c9596f18e3c5 (patch) | |
tree | 56fb2f98aba2055c959c57ffb8022dbcd21f8d27 /src/streams.h | |
parent | fa65bbf217b725ada35107b4ad646d250228355c (diff) |
Use spans of std::byte in serialize
This switches .read() and .write() to take spans of bytes.
Diffstat (limited to 'src/streams.h')
-rw-r--r-- | src/streams.h | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/src/streams.h b/src/streams.h index 384bb632b0..2f26be6dd8 100644 --- a/src/streams.h +++ b/src/streams.h @@ -49,14 +49,14 @@ public: return (*this); } - void write(const char* pch, size_t nSize) + void write(Span<const std::byte> src) { - stream->write(pch, nSize); + stream->write(src); } - void read(char* pch, size_t nSize) + void read(Span<std::byte> dst) { - stream->read(pch, nSize); + stream->read(dst); } int GetVersion() const { return nVersion; } @@ -94,17 +94,17 @@ class CVectorWriter { ::SerializeMany(*this, std::forward<Args>(args)...); } - void write(const char* pch, size_t nSize) + void write(Span<const std::byte> src) { assert(nPos <= vchData.size()); - size_t nOverwrite = std::min(nSize, vchData.size() - nPos); + size_t nOverwrite = std::min(src.size(), vchData.size() - nPos); if (nOverwrite) { - memcpy(vchData.data() + nPos, reinterpret_cast<const unsigned char*>(pch), nOverwrite); + memcpy(vchData.data() + nPos, src.data(), nOverwrite); } - if (nOverwrite < nSize) { - vchData.insert(vchData.end(), reinterpret_cast<const unsigned char*>(pch) + nOverwrite, reinterpret_cast<const unsigned char*>(pch) + nSize); + if (nOverwrite < src.size()) { + vchData.insert(vchData.end(), UCharCast(src.data()) + nOverwrite, UCharCast(src.end())); } - nPos += nSize; + nPos += src.size(); } template<typename T> CVectorWriter& operator<<(const T& obj) @@ -161,18 +161,18 @@ public: size_t size() const { return m_data.size(); } bool empty() const { return m_data.empty(); } - void read(char* dst, size_t n) + void read(Span<std::byte> dst) { - if (n == 0) { + if (dst.size() == 0) { return; } // Read from the beginning of the buffer - if (n > m_data.size()) { + if (dst.size() > m_data.size()) { throw std::ios_base::failure("SpanReader::read(): end of data"); } - memcpy(dst, m_data.data(), n); - m_data = m_data.subspan(n); + memcpy(dst.data(), m_data.data(), dst.size()); + m_data = m_data.subspan(dst.size()); } }; @@ -206,6 +206,7 @@ public: : nType{nTypeIn}, nVersion{nVersionIn} {} + explicit CDataStream(Span<const uint8_t> sp, int type, int version) : CDataStream{AsBytes(sp), type, version} {} explicit CDataStream(Span<const value_type> sp, int nTypeIn, int nVersionIn) : vch(sp.data(), sp.data() + sp.size()), nType{nTypeIn}, @@ -221,7 +222,7 @@ public: std::string str() const { - return (std::string(begin(), end())); + return std::string{UCharCast(data()), UCharCast(data() + size())}; } @@ -342,16 +343,16 @@ public: void SetVersion(int n) { nVersion = n; } int GetVersion() const { return nVersion; } - void read(char* pch, size_t nSize) + void read(Span<value_type> dst) { - if (nSize == 0) return; + if (dst.size() == 0) return; // Read from the beginning of the buffer - unsigned int nReadPosNext = nReadPos + nSize; + unsigned int nReadPosNext = nReadPos + dst.size(); if (nReadPosNext > vch.size()) { throw std::ios_base::failure("CDataStream::read(): end of data"); } - memcpy(pch, &vch[nReadPos], nSize); + memcpy(dst.data(), &vch[nReadPos], dst.size()); if (nReadPosNext == vch.size()) { nReadPos = 0; @@ -379,10 +380,10 @@ public: nReadPos = nReadPosNext; } - void write(const char* pch, size_t nSize) + void write(Span<const value_type> src) { // Write to the end of the buffer - vch.insert(vch.end(), pch, pch + nSize); + vch.insert(vch.end(), src.begin(), src.end()); } template<typename Stream> @@ -390,7 +391,7 @@ public: { // Special case: stream << stream concatenates like stream += stream if (!vch.empty()) - s.write((char*)vch.data(), vch.size() * sizeof(value_type)); + s.write(MakeByteSpan(vch)); } template<typename T> @@ -421,7 +422,7 @@ public: } for (size_type i = 0, j = 0; i != size(); i++) { - vch[i] ^= key[j++]; + vch[i] ^= std::byte{key[j++]}; // This potentially acts on very many bytes of data, so it's // important that we calculate `j`, i.e. the `key` index in this @@ -594,12 +595,13 @@ public: int GetType() const { return nType; } int GetVersion() const { return nVersion; } - void read(char* pch, size_t nSize) + void read(Span<std::byte> dst) { if (!file) throw std::ios_base::failure("CAutoFile::read: file handle is nullptr"); - if (fread(pch, 1, nSize, file) != nSize) + if (fread(dst.data(), 1, dst.size(), file) != dst.size()) { throw std::ios_base::failure(feof(file) ? "CAutoFile::read: end of file" : "CAutoFile::read: fread failed"); + } } void ignore(size_t nSize) @@ -615,12 +617,13 @@ public: } } - void write(const char* pch, size_t nSize) + void write(Span<const std::byte> src) { if (!file) throw std::ios_base::failure("CAutoFile::write: file handle is nullptr"); - if (fwrite(pch, 1, nSize, file) != nSize) + if (fwrite(src.data(), 1, src.size(), file) != src.size()) { throw std::ios_base::failure("CAutoFile::write: write failed"); + } } template<typename T> @@ -661,7 +664,7 @@ private: uint64_t nReadPos; //!< how many bytes have been read from this uint64_t nReadLimit; //!< up to which position we're allowed to read uint64_t nRewind; //!< how many bytes we guarantee to rewind - std::vector<char> vchBuf; //!< the buffer + std::vector<std::byte> vchBuf; //!< the buffer protected: //! read data from the source to fill the buffer @@ -682,8 +685,8 @@ protected: } public: - CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : - nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, 0) + CBufferedFile(FILE* fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) + : nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, std::byte{0}) { if (nRewindIn >= nBufSize) throw std::ios_base::failure("Rewind limit must be less than buffer size"); @@ -716,22 +719,23 @@ public: } //! read a number of bytes - void read(char *pch, size_t nSize) { - if (nSize + nReadPos > nReadLimit) + void read(Span<std::byte> dst) + { + if (dst.size() + nReadPos > nReadLimit) { throw std::ios_base::failure("Read attempted past buffer limit"); - while (nSize > 0) { + } + while (dst.size() > 0) { if (nReadPos == nSrcPos) Fill(); unsigned int pos = nReadPos % vchBuf.size(); - size_t nNow = nSize; + size_t nNow = dst.size(); if (nNow + pos > vchBuf.size()) nNow = vchBuf.size() - pos; if (nNow + nReadPos > nSrcPos) nNow = nSrcPos - nReadPos; - memcpy(pch, &vchBuf[pos], nNow); + memcpy(dst.data(), &vchBuf[pos], nNow); nReadPos += nNow; - pch += nNow; - nSize -= nNow; + dst = dst.subspan(nNow); } } @@ -774,12 +778,14 @@ public: } //! search for a given byte in the stream, and remain positioned on it - void FindByte(char ch) { + void FindByte(uint8_t ch) + { while (true) { if (nReadPos == nSrcPos) Fill(); - if (vchBuf[nReadPos % vchBuf.size()] == ch) + if (vchBuf[nReadPos % vchBuf.size()] == std::byte{ch}) { break; + } nReadPos++; } } |