6#ifndef BITCOIN_STREAMS_H
7#define BITCOIN_STREAMS_H
51 template <
typename... Args>
56 void write(std::span<const std::byte> src)
59 size_t nOverwrite = std::min(src.size(),
vchData.size() -
nPos);
61 memcpy(
vchData.data() +
nPos, src.data(), nOverwrite);
63 if (nOverwrite < src.size()) {
104 void read(std::span<std::byte> dst)
106 if (dst.size() == 0) {
111 if (dst.size() >
m_data.size()) {
112 throw std::ios_base::failure(
"SpanReader::read(): end of data");
114 memcpy(dst.data(),
m_data.data(), dst.size());
121 throw std::ios_base::failure(
"SpanReader::ignore(): end of data");
183 bool Rewind(std::optional<size_type> n = std::nullopt)
203 void read(std::span<value_type> dst)
205 if (dst.size() == 0)
return;
209 if (!next_read_pos.has_value() || next_read_pos.value() >
vch.size()) {
210 throw std::ios_base::failure(
"DataStream::read(): end of data");
213 if (next_read_pos.value() ==
vch.size()) {
225 if (!next_read_pos.has_value() || next_read_pos.value() >
vch.size()) {
226 throw std::ios_base::failure(
"DataStream::ignore(): end of data");
228 if (next_read_pos.value() ==
vch.size()) {
236 void write(std::span<const value_type> src)
239 vch.insert(
vch.end(), src.begin(), src.end());
249 template <
typename T>
260template <typename IStream>
282 if (nbits < 0 || nbits > 64) {
283 throw std::out_of_range(
"nbits must be between 0 and 64");
293 int bits = std::min(8 -
m_offset, nbits);
295 data |=
static_cast<uint8_t
>(m_buffer << m_offset) >> (8 - bits);
303template <
typename OStream>
329 void Write(uint64_t data,
int nbits) {
330 if (nbits < 0 || nbits > 64) {
331 throw std::out_of_range(
"nbits must be between 0 and 64");
335 int bits = std::min(8 -
m_offset, nbits);
409 if (
auto rel{
release()})
return std::fclose(rel);
432 std::size_t detail_fread(std::span<std::byte> dst);
435 void seek(int64_t offset,
int origin);
447 bool Truncate(
unsigned size);
450 void write_buffer(std::span<std::byte> src);
455 void read(std::span<std::byte> dst);
456 void ignore(
size_t nSize);
457 void write(std::span<const std::byte> src);
459 template <
typename T>
466 template <
typename T>
495 unsigned int readNow =
vchBuf.size() - pos;
497 if (nAvail < readNow)
501 size_t nBytes{
m_src.detail_fread(std::span{
vchBuf}.subspan(pos, readNow))};
503 throw std::ios_base::failure{
m_src.feof() ?
"BufferedFile::Fill: end of file" :
"BufferedFile::Fill: fread failed"};
518 throw std::ios_base::failure(
"Attempt to position past buffer limit");
524 size_t buffer_available{
static_cast<size_t>(
vchBuf.size() - buffer_offset)};
526 size_t advance{std::min({length, buffer_available, bytes_until_source_pos})};
528 return std::make_pair(&
vchBuf[buffer_offset], advance);
535 if (nRewindIn >= nBufSize)
536 throw std::ios_base::failure(
"Rewind limit must be less than buffer size");
545 void read(std::span<std::byte> dst)
547 while (dst.size() > 0) {
549 memcpy(dst.data(), buffer_pointer, length);
550 dst = dst.subspan(length);
569 size_t bufsize =
vchBuf.size();
570 if (nPos + bufsize <
nSrcPos) {
586 bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
612 const auto it_start{
vchBuf.begin() + buf_offset};
613 const auto it_find{std::find(it_start, it_start + len,
byte)};
614 const size_t inc{size_t(std::distance(it_start, it_find))};
616 if (inc < len)
break;
618 if (buf_offset >=
vchBuf.size()) buf_offset = 0;
638 requires std::is_rvalue_reference_v<
S&&>
639 :
m_src{stream}, m_buf(size), m_buf_pos{size} {}
641 void read(std::span<std::byte> dst)
643 if (
const auto available{std::min(dst.size(),
m_buf.size() -
m_buf_pos)}) {
646 dst = dst.subspan(available);
657 template <
typename T>
688 void write(std::span<const std::byte> src)
690 while (
const auto available{std::min(src.size(),
m_buf.size() -
m_buf_pos)}) {
694 src = src.subspan(available);
698 template <
typename T>
#define Assume(val)
Assume is the identity function.
Non-refcounted RAII wrapper for FILE*.
std::FILE * release()
Get wrapped FILE* with transfer of ownership.
AutoFile & operator=(const AutoFile &)=delete
void SetObfuscation(const Obfuscation &obfuscation)
Continue with a different XOR key.
AutoFile & operator<<(const T &obj)
AutoFile(const AutoFile &)=delete
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
AutoFile(std::FILE *file, const Obfuscation &obfuscation={})
AutoFile & operator>>(T &&obj)
std::optional< int64_t > m_position
Obfuscation m_obfuscation
uint8_t m_buffer
Buffered byte read in from the input stream.
uint64_t Read(int nbits)
Read the specified number of bits from the stream.
BitStreamReader(IStream &istream)
int m_offset
Number of high order bits in m_buffer already returned by previous Read() calls.
void Write(uint64_t data, int nbits)
Write the nbits least significant bits of a 64-bit int to the output stream.
uint8_t m_buffer
Buffered byte waiting to be written to the output stream.
BitStreamWriter(OStream &ostream)
int m_offset
Number of high order bits in m_buffer already written by previous Write() calls and not yet flushed t...
void Flush()
Flush any unwritten bits to the output stream, padding with 0's to the next byte boundary.
std::pair< std::byte *, size_t > AdvanceStream(size_t length)
uint64_t nRewind
how many bytes we guarantee to rewind
void read(std::span< std::byte > dst)
read a number of bytes
BufferedFile(AutoFile &file LIFETIMEBOUND, uint64_t nBufSize, uint64_t nRewindIn)
bool eof() const
check whether we're at the end of the source file
bool SetLimit(uint64_t nPos=std::numeric_limits< uint64_t >::max())
uint64_t m_read_pos
how many bytes have been read from this
BufferedFile & operator>>(T &&obj)
uint64_t GetPos() const
return the current reading position
uint64_t nReadLimit
up to which position we're allowed to read
void SkipTo(const uint64_t file_pos)
uint64_t nSrcPos
how many bytes have been read from source
void FindByte(std::byte byte)
search for a given byte in the stream, and remain positioned on it
bool Fill()
read data from the source to fill the buffer
bool SetPos(uint64_t nPos)
rewind to a given reading position
BufferedReader(S &&stream LIFETIMEBOUND, size_t size=1<< 16)
Requires stream ownership to prevent leaving the stream at an unexpected position after buffered read...
BufferedReader & operator>>(T &&obj)
void read(std::span< std::byte > dst)
void write(std::span< const std::byte > src)
BufferedWriter & operator<<(const T &obj)
BufferedWriter(S &stream LIFETIMEBOUND, size_t size=1<< 16)
DataStream & operator<<(const T &obj)
vector_type::difference_type difference_type
void write(std::span< const value_type > src)
DataStream & operator>>(T &&obj)
reference operator[](size_type pos)
void resize(size_type n, value_type c=value_type{})
const_reference operator[](size_type pos) const
void read(std::span< value_type > dst)
vector_type::size_type size_type
SerializeData vector_type
const value_type * data() const
vector_type::const_reference const_reference
vector_type::const_iterator const_iterator
void reserve(size_type n)
vector_type::reverse_iterator reverse_iterator
DataStream(std::span< const value_type > sp)
const_iterator begin() const
vector_type::size_type m_read_pos
vector_type::iterator iterator
vector_type::value_type value_type
DataStream(std::span< const uint8_t > sp)
void ignore(size_t num_ignore)
vector_type::allocator_type allocator_type
const_iterator end() const
size_t GetMemoryUsage() const noexcept
Compute total memory usage of this object (own memory + any dynamic memory).
bool Rewind(std::optional< size_type > n=std::nullopt)
vector_type::reference reference
SpanReader & operator>>(T &&obj)
std::span< const std::byte > m_data
SpanReader(std::span< const std::byte > data)
void read(std::span< std::byte > dst)
SpanReader(std::span< const unsigned char > data)
std::vector< unsigned char > & vchData
VectorWriter & operator<<(const T &obj)
void write(std::span< const std::byte > src)
VectorWriter(std::vector< unsigned char > &vchDataIn, size_t nPosIn, Args &&... args)
VectorWriter(std::vector< unsigned char > &vchDataIn, size_t nPosIn)
#define T(expected, seed, data)
std::optional< T > CheckedAdd(const T i, const T j) noexcept
#define S(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
void Serialize(Stream &, V)=delete
void SerializeMany(Stream &s, const Args &... args)
Support for (un)serializing many things at once.
void Unserialize(Stream &, V)=delete
unsigned char * UCharCast(char *c)
std::vector< std::byte > DataBuffer
std::string SysErrorString(int err)
Return system error string from errno value.
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.