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");
136 template <
typename... Args>
142 void write(std::span<const std::byte> src)
144 if (src.size() >
m_dest.size()) {
145 throw std::ios_base::failure(
"SpanWriter::write(): exceeded buffer size");
147 memcpy(
m_dest.data(), src.data(), src.size());
211 void read(std::span<value_type> dst)
213 if (dst.size() == 0)
return;
217 if (!next_read_pos.has_value() || next_read_pos.value() >
vch.size()) {
218 throw std::ios_base::failure(
"DataStream::read(): end of data");
221 if (next_read_pos.value() ==
vch.size()) {
233 if (!next_read_pos.has_value() || next_read_pos.value() >
vch.size()) {
234 throw std::ios_base::failure(
"DataStream::ignore(): end of data");
236 if (next_read_pos.value() ==
vch.size()) {
244 void write(std::span<const value_type> src)
247 vch.insert(
vch.end(), src.begin(), src.end());
257 template <
typename T>
282template <
typename IStream>
304 if (nbits < 0 || nbits > 64) {
305 throw std::out_of_range(
"nbits must be between 0 and 64");
315 int bits = std::min(8 -
m_offset, nbits);
317 data |=
static_cast<uint8_t
>(m_buffer << m_offset) >> (8 - bits);
325template <
typename OStream>
351 void Write(uint64_t data,
int nbits) {
352 if (nbits < 0 || nbits > 64) {
353 throw std::out_of_range(
"nbits must be between 0 and 64");
357 int bits = std::min(8 -
m_offset, nbits);
431 if (
auto rel{
release()})
return std::fclose(rel);
454 std::size_t detail_fread(std::span<std::byte> dst);
457 void seek(int64_t offset,
int origin);
469 bool Truncate(uint64_t size);
472 void write_buffer(std::span<std::byte> src);
477 void read(std::span<std::byte> dst);
478 void ignore(
size_t nSize);
479 void write(std::span<const std::byte> src);
481 template <
typename T>
488 template <
typename T>
517 unsigned int readNow =
vchBuf.size() - pos;
519 if (nAvail < readNow)
525 throw std::ios_base::failure{
m_src.
feof() ?
"BufferedFile::Fill: end of file" :
"BufferedFile::Fill: fread failed"};
540 throw std::ios_base::failure(
"Attempt to position past buffer limit");
546 size_t buffer_available{
static_cast<size_t>(
vchBuf.size() - buffer_offset)};
548 size_t advance{std::min({length, buffer_available, bytes_until_source_pos})};
550 return std::make_pair(&
vchBuf[buffer_offset], advance);
557 if (nRewindIn >= nBufSize)
558 throw std::ios_base::failure(
"Rewind limit must be less than buffer size");
567 void read(std::span<std::byte> dst)
569 while (dst.size() > 0) {
571 memcpy(dst.data(), buffer_pointer, length);
572 dst = dst.subspan(length);
591 size_t bufsize =
vchBuf.size();
592 if (nPos + bufsize <
nSrcPos) {
608 bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
634 const auto it_start{
vchBuf.begin() + buf_offset};
635 const auto it_find{std::find(it_start, it_start + len,
byte)};
636 const size_t inc{size_t(std::distance(it_start, it_find))};
638 if (inc < len)
break;
640 if (buf_offset >=
vchBuf.size()) buf_offset = 0;
660 requires std::is_rvalue_reference_v<
S&&>
661 :
m_src{stream}, m_buf(size), m_buf_pos{size} {}
663 void read(std::span<std::byte> dst)
665 if (
const auto available{std::min(dst.size(),
m_buf.size() -
m_buf_pos)}) {
668 dst = dst.subspan(available);
679 template <
typename T>
710 void write(std::span<const std::byte> src)
712 while (
const auto available{std::min(src.size(),
m_buf.size() -
m_buf_pos)}) {
716 src = src.subspan(available);
720 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)
std::size_t detail_fread(std::span< std::byte > dst)
Implementation detail, only used internally.
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)
Double ended buffer combining vector and stream-like interfaces.
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).
vector_type::reference reference
ScopedDataStreamUsage & operator=(const ScopedDataStreamUsage &)=delete
ScopedDataStreamUsage(DataStream &stream)
ScopedDataStreamUsage(const ScopedDataStreamUsage &)=delete
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)
void write(std::span< const std::byte > src)
SpanWriter & operator<<(const T &obj)
SpanWriter(std::span< std::byte > dest)
SpanWriter(std::span< std::byte > dest, Args &&... args)
std::span< std::byte > m_dest
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.