6#ifndef BITCOIN_STREAMS_H
7#define BITCOIN_STREAMS_H
30 if (key.
size() == 0) {
33 key_offset %= key.
size();
35 for (
size_t i = 0, j = key_offset; i != write.
size(); i++) {
69 template <
typename... Args>
81 if (nOverwrite < src.
size()) {
123 if (dst.
size() == 0) {
129 throw std::ios_base::failure(
"SpanReader::read(): end of data");
197 bool Rewind(std::optional<size_type> n = std::nullopt)
220 if (dst.
size() == 0)
return;
224 if (!next_read_pos.has_value() || next_read_pos.value() >
vch.size()) {
225 throw std::ios_base::failure(
"DataStream::read(): end of data");
228 if (next_read_pos.value() ==
vch.size()) {
240 if (!next_read_pos.has_value() || next_read_pos.value() >
vch.size()) {
241 throw std::ios_base::failure(
"DataStream::ignore(): end of data");
243 if (next_read_pos.value() ==
vch.size()) {
276 void Xor(
const std::vector<unsigned char>& key)
285template <typename IStream>
307 if (nbits < 0 || nbits > 64) {
308 throw std::out_of_range(
"nbits must be between 0 and 64");
314 m_istream >> m_buffer;
318 int bits = std::min(8 - m_offset, nbits);
320 data |=
static_cast<uint8_t
>(m_buffer << m_offset) >> (8 - bits);
328template <
typename OStream>
355 if (nbits < 0 || nbits > 64) {
356 throw std::out_of_range(
"nbits must be between 0 and 64");
360 int bits = std::min(8 - m_offset, nbits);
361 m_buffer |= (
data << (64 - nbits)) >> (64 - 8 + m_offset);
379 m_ostream << m_buffer;
399 explicit AutoFile(std::FILE* file, std::vector<std::byte> data_xor={});
407 bool feof()
const {
return std::feof(m_file); }
411 if (
auto rel{release()})
return std::fclose(rel);
421 std::FILE*
ret{m_file};
428 bool IsNull()
const {
return m_file ==
nullptr; }
431 void SetXor(std::vector<std::byte> data_xor) { m_xor = data_xor; }
437 void seek(int64_t offset,
int origin);
446 bool Truncate(
unsigned size);
452 void ignore(
size_t nSize);
455 template <
typename T>
462 template <
typename T>
488 unsigned int pos = nSrcPos % vchBuf.size();
489 unsigned int readNow = vchBuf.size() - pos;
490 unsigned int nAvail = vchBuf.size() - (nSrcPos -
m_read_pos) - nRewind;
491 if (nAvail < readNow)
497 throw std::ios_base::failure{m_src.
feof() ?
"BufferedFile::Fill: end of file" :
"BufferedFile::Fill: fread failed"};
512 throw std::ios_base::failure(
"Attempt to position past buffer limit");
515 if (
m_read_pos == nSrcPos && length > 0) Fill();
517 size_t buffer_offset{
static_cast<size_t>(
m_read_pos % vchBuf.size())};
518 size_t buffer_available{
static_cast<size_t>(vchBuf.size() - buffer_offset)};
519 size_t bytes_until_source_pos{
static_cast<size_t>(nSrcPos -
m_read_pos)};
520 size_t advance{std::min({length, buffer_available, bytes_until_source_pos})};
522 return std::make_pair(&vchBuf[buffer_offset], advance);
527 : m_src{file}, nReadLimit{
std::numeric_limits<uint64_t>::max()}, nRewind{nRewindIn}, vchBuf(nBufSize,
std::byte{0})
529 if (nRewindIn >= nBufSize)
530 throw std::ios_base::failure(
"Rewind limit must be less than buffer size");
541 while (dst.
size() > 0) {
542 auto [buffer_pointer, length]{AdvanceStream(dst.
size())};
543 memcpy(dst.
data(), buffer_pointer, length);
563 size_t bufsize = vchBuf.size();
564 if (nPos + bufsize < nSrcPos) {
569 if (nPos > nSrcPos) {
580 bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
597 size_t buf_offset{size_t(
m_read_pos % uint64_t(vchBuf.size()))};
605 const size_t len{std::min<size_t>(vchBuf.size() - buf_offset, nSrcPos -
m_read_pos)};
606 const auto it_start{vchBuf.begin() + buf_offset};
607 const auto it_find{std::find(it_start, it_start + len,
byte)};
608 const size_t inc{size_t(std::distance(it_start, it_find))};
610 if (inc < len)
break;
612 if (buf_offset >= vchBuf.size()) buf_offset = 0;
Non-refcounted RAII wrapper for FILE*.
std::FILE * release()
Get wrapped FILE* with transfer of ownership.
AutoFile & operator=(const AutoFile &)=delete
std::vector< std::byte > m_xor
AutoFile & operator<<(const T &obj)
AutoFile(const AutoFile &)=delete
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
AutoFile & operator>>(T &&obj)
void SetXor(std::vector< std::byte > data_xor)
Continue with a different XOR key.
std::size_t detail_fread(Span< std::byte > dst)
Implementation detail, only used internally.
std::optional< int64_t > m_position
uint64_t Read(int nbits)
Read the specified number of bits from the stream.
BitStreamReader(IStream &istream)
void Write(uint64_t data, int nbits)
Write the nbits least significant bits of a 64-bit int to the output stream.
BitStreamWriter(OStream &ostream)
void Flush()
Flush any unwritten bits to the output stream, padding with 0's to the next byte boundary.
Wrapper around an AutoFile& that implements a ring buffer to deserialize from.
std::vector< std::byte > vchBuf
the buffer
std::pair< std::byte *, size_t > AdvanceStream(size_t length)
Advance the stream's read pointer (m_read_pos) by up to 'length' bytes, filling the buffer from the f...
uint64_t nRewind
how many bytes we guarantee to rewind
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())
prevent reading beyond a certain position no argument removes the limit
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 read(Span< std::byte > dst)
read a number of bytes
void SkipTo(const uint64_t file_pos)
Move the read position ahead in the stream to the given position.
void FindByte(std::byte byte)
search for a given byte in the stream, and remain positioned on it
BufferedFile(AutoFile &file, uint64_t nBufSize, uint64_t nRewindIn)
bool Fill()
read data from the source to fill the buffer
bool SetPos(uint64_t nPos)
rewind to a given reading position
Double ended buffer combining vector and stream-like interfaces.
void write(Span< const value_type > src)
DataStream & operator<<(const T &obj)
vector_type::difference_type difference_type
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 Xor(const std::vector< unsigned char > &key)
XOR the contents of this stream with a certain key.
DataStream(Span< const value_type > sp)
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
DataStream(Span< const uint8_t > sp)
void reserve(size_type n)
vector_type::reverse_iterator reverse_iterator
const_iterator begin() const
void read(Span< value_type > dst)
vector_type::size_type m_read_pos
vector_type::iterator iterator
vector_type::value_type value_type
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
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
constexpr C * data() const noexcept
constexpr C * begin() const noexcept
constexpr bool empty() const noexcept
constexpr C * end() const noexcept
Minimal stream for reading from an existing byte array by Span.
SpanReader & operator>>(T &&obj)
SpanReader(Span< const unsigned char > data)
Span< const unsigned char > m_data
void read(Span< std::byte > dst)
std::vector< unsigned char > & vchData
VectorWriter & operator<<(const T &obj)
void write(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)
void Xor(Span< std::byte > write, Span< const std::byte > key, size_t key_offset=0)
std::optional< T > CheckedAdd(const T i, const T j) noexcept
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
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Span< const std::byte > AsBytes(Span< T > s) noexcept
unsigned char * UCharCast(char *c)
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.