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);
396 explicit AutoFile(std::FILE* file, std::vector<std::byte> data_xor={});
408 if (
auto rel{
release()})
return std::fclose(rel);
428 void SetXor(std::vector<std::byte> data_xor) {
m_xor = data_xor; }
433 void seek(int64_t offset,
int origin);
440 void ignore(
size_t nSize);
443 template <
typename T>
450 template <
typename T>
481 unsigned int readNow =
vchBuf.size() - pos;
483 if (nAvail < readNow)
489 throw std::ios_base::failure{
m_src.
feof() ?
"BufferedFile::Fill: end of file" :
"BufferedFile::Fill: fread failed"};
504 throw std::ios_base::failure(
"Attempt to position past buffer limit");
510 size_t buffer_available{
static_cast<size_t>(
vchBuf.size() - buffer_offset)};
512 size_t advance{std::min({length, buffer_available, bytes_until_source_pos})};
514 return std::make_pair(&
vchBuf[buffer_offset], advance);
521 if (nRewindIn >= nBufSize)
522 throw std::ios_base::failure(
"Rewind limit must be less than buffer size");
533 while (dst.
size() > 0) {
535 memcpy(dst.
data(), buffer_pointer, length);
555 size_t bufsize =
vchBuf.size();
556 if (nPos + bufsize <
nSrcPos) {
572 bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
598 const auto it_start{
vchBuf.begin() + buf_offset};
599 const auto it_find{std::find(it_start, it_start + len, byte)};
600 const size_t inc{size_t(std::distance(it_start, it_find))};
602 if (inc < len)
break;
604 if (buf_offset >=
vchBuf.size()) buf_offset = 0;
609 #endif // BITCOIN_STREAMS_H
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
void SetXor(std::vector< std::byte > data_xor)
Continue with a different XOR key.
Span< const unsigned char > m_data
std::vector< std::byte > vchBuf
the buffer
uint64_t GetPos() const
return the current reading position
void reserve(size_type n)
vector_type::const_reference const_reference
vector_type::iterator iterator
constexpr C * end() const noexcept
VectorWriter(std::vector< unsigned char > &vchDataIn, size_t nPosIn)
AutoFile & operator>>(T &&obj)
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
void SkipTo(const uint64_t file_pos)
Move the read position ahead in the stream to the given position.
constexpr std::size_t size() const noexcept
vector_type::difference_type difference_type
uint64_t nRewind
how many bytes we guarantee to rewind
Wrapper around an AutoFile& that implements a ring buffer to deserialize from.
void ignore(size_t num_ignore)
void write(Span< const value_type > src)
void Write(uint64_t data, int nbits)
Write the nbits least significant bits of a 64-bit int to the output stream.
vector_type::value_type value_type
std::FILE * release()
Get wrapped FILE* with transfer of ownership.
Non-refcounted RAII wrapper for FILE*.
uint8_t m_buffer
Buffered byte read in from the input stream.
bool SetLimit(uint64_t nPos=std::numeric_limits< uint64_t >::max())
prevent reading beyond a certain position no argument removes the limit
Minimal stream for reading from an existing byte array by Span.
std::optional< T > CheckedAdd(const T i, const T j) noexcept
DataStream(Span< const uint8_t > sp)
vector_type::size_type m_read_pos
std::optional< int64_t > m_position
vector_type::size_type size_type
void Xor(Span< std::byte > write, Span< const std::byte > key, size_t key_offset=0)
BitStreamReader(IStream &istream)
vector_type::reverse_iterator reverse_iterator
const_iterator end() const
bool Rewind(std::optional< size_type > n=std::nullopt)
DataStream(Span< const value_type > sp)
void Unserialize(Stream &, V)=delete
Double ended buffer combining vector and stream-like interfaces.
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.
DataStream & operator<<(const T &obj)
AutoFile & operator<<(const T &obj)
BufferedFile & operator>>(T &&obj)
vector_type::allocator_type allocator_type
vector_type::const_iterator const_iterator
uint64_t nSrcPos
how many bytes have been read from source
std::vector< std::byte > m_xor
bool Fill()
read data from the source to fill the buffer
AutoFile & operator=(const AutoFile &)=delete
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)
SerializeData vector_type
uint64_t Read(int nbits)
Read the specified number of bits from the stream.
const_reference operator[](size_type pos) const
DataStream & operator>>(T &&obj)
void Flush()
Flush any unwritten bits to the output stream, padding with 0's to the next byte boundary.
void FindByte(std::byte byte)
search for a given byte in the stream, and remain positioned on it
const_iterator begin() const
constexpr C * begin() const noexcept
uint8_t m_buffer
Buffered byte waiting to be written to the output stream.
void resize(size_type n, value_type c=value_type{})
std::vector< unsigned char > & vchData
void write(Span< const std::byte > src)
int m_offset
Number of high order bits in m_buffer already written by previous Write() calls and not yet flushed t...
bool Truncate(unsigned size)
bool SetPos(uint64_t nPos)
rewind to a given reading position
const value_type * data() const
constexpr C * data() const noexcept
AutoFile(std::FILE *file, std::vector< std::byte > data_xor={})
int m_offset
Number of high order bits in m_buffer already returned by previous Read() calls.
void Serialize(Stream &, V)=delete
reference operator[](size_type pos)
void Xor(const std::vector< unsigned char > &key)
XOR the contents of this stream with a certain key.
Span< const std::byte > MakeByteSpan(V &&v) noexcept
VectorWriter & operator<<(const T &obj)
uint64_t nReadLimit
up to which position we're allowed to read
constexpr bool empty() const noexcept
Span< const std::byte > AsBytes(Span< T > s) noexcept
VectorWriter(std::vector< unsigned char > &vchDataIn, size_t nPosIn, Args &&... args)
bool eof() const
check whether we're at the end of the source file
SpanReader(Span< const unsigned char > data)
void seek(int64_t offset, int origin)
unsigned char * UCharCast(char *c)
void SerializeMany(Stream &s, const Args &... args)
Support for (un)serializing many things at once.
BufferedFile(AutoFile &file, uint64_t nBufSize, uint64_t nRewindIn)
A Span is an object that can refer to a contiguous sequence of objects.
void read(Span< std::byte > dst)
read a number of bytes
vector_type::reference reference
std::size_t detail_fread(Span< std::byte > dst)
Implementation detail, only used internally.
void read(Span< std::byte > dst)
void read(Span< value_type > dst)
SpanReader & operator>>(T &&obj)
void write(Span< const std::byte > src)
void ignore(size_t nSize)
BitStreamWriter(OStream &ostream)
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
uint64_t m_read_pos
how many bytes have been read from this