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)
282 template <
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);
325 template <
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);
395 explicit AutoFile(std::FILE* file, std::vector<std::byte> data_xor={}) :
m_file{file},
m_xor{std::move(data_xor)} {}
407 if (
auto rel{
release()})
return std::fclose(rel);
433 void SetXor(std::vector<std::byte> data_xor) {
m_xor = data_xor; }
442 void ignore(
size_t nSize);
445 template <
typename T>
452 template <
typename T>
479 unsigned int readNow =
vchBuf.size() - pos;
481 if (nAvail < readNow)
487 throw std::ios_base::failure{
m_src.
feof() ?
"BufferedFile::Fill: end of file" :
"BufferedFile::Fill: fread failed"};
502 throw std::ios_base::failure(
"Attempt to position past buffer limit");
508 size_t buffer_available{
static_cast<size_t>(
vchBuf.size() - buffer_offset)};
510 size_t advance{std::min({length, buffer_available, bytes_until_source_pos})};
512 return std::make_pair(&
vchBuf[buffer_offset], advance);
519 if (nRewindIn >= nBufSize)
520 throw std::ios_base::failure(
"Rewind limit must be less than buffer size");
531 while (dst.
size() > 0) {
533 memcpy(dst.
data(), buffer_pointer, length);
553 size_t bufsize =
vchBuf.size();
554 if (nPos + bufsize <
nSrcPos) {
570 bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
596 const auto it_start{
vchBuf.begin() + buf_offset};
597 const auto it_find{std::find(it_start, it_start + len,
byte)};
598 const size_t inc{size_t(std::distance(it_start, it_find))};
600 if (inc < len)
break;
602 if (buf_offset >=
vchBuf.size()) buf_offset = 0;
Non-refcounted RAII wrapper for FILE*.
void ignore(size_t nSize)
std::vector< std::byte > m_xor
void read(Span< std::byte > dst)
std::FILE * Get() const
Get wrapped FILE* without transfer of ownership.
AutoFile(const AutoFile &)=delete
std::FILE * release()
Get wrapped FILE* with transfer of ownership.
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
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.
AutoFile(std::FILE *file, std::vector< std::byte > data_xor={})
AutoFile & operator=(const AutoFile &)=delete
AutoFile & operator<<(const T &obj)
AutoFile & operator>>(T &&obj)
void write(Span< const std::byte > src)
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.
Wrapper around an AutoFile& that implements a ring buffer to deserialize from.
std::vector< std::byte > vchBuf
the buffer
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
uint64_t m_read_pos
how many bytes have been read from this
uint64_t GetPos() const
return the current reading position
uint64_t nReadLimit
up to which position we're allowed to read
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...
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.
BufferedFile & operator>>(T &&obj)
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
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)
vector_type::difference_type difference_type
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
vector_type::const_reference const_reference
const value_type * data() const
vector_type::const_iterator const_iterator
DataStream(Span< const uint8_t > sp)
void reserve(size_type n)
vector_type::reverse_iterator reverse_iterator
DataStream & operator>>(T &&obj)
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
bool Rewind(std::optional< size_type > n=std::nullopt)
vector_type::reference reference
DataStream & operator<<(const T &obj)
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
constexpr C * data() const noexcept
constexpr C * end() const noexcept
constexpr C * begin() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
constexpr bool empty() const noexcept
Minimal stream for reading from an existing byte array by Span.
SpanReader(Span< const unsigned char > data)
Span< const unsigned char > m_data
SpanReader & operator>>(T &&obj)
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
unsigned char * UCharCast(char *c)
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Span< const std::byte > AsBytes(Span< T > s) noexcept
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.