6 #ifndef BITCOIN_STREAMS_H 7 #define BITCOIN_STREAMS_H 31 : stream(stream_), nType(nType_), nVersion(nVersion_) {}
45 void write(
const char *pch,
size_t nSize) { stream->write(pch, nSize); }
47 void read(
char *pch,
size_t nSize) { stream->read(pch, nSize); }
72 CVectorWriter(
int nTypeIn,
int nVersionIn, std::vector<uint8_t> &vchDataIn,
76 if (nPos > vchData.size()) {
84 template <
typename... Args>
85 CVectorWriter(
int nTypeIn,
int nVersionIn, std::vector<uint8_t> &vchDataIn,
86 size_t nPosIn, Args &&... args)
90 void write(
const char *pch,
size_t nSize) {
91 assert(nPos <= vchData.size());
92 size_t nOverwrite = std::min(nSize, vchData.size() - nPos);
94 memcpy(vchData.data() + nPos,
95 reinterpret_cast<const uint8_t *
>(pch), nOverwrite);
97 if (nOverwrite < nSize) {
98 vchData.insert(vchData.end(),
99 reinterpret_cast<const uint8_t *
>(pch) + nOverwrite,
100 reinterpret_cast<const uint8_t *>(pch) + nSize);
113 if (nPos > vchData.size()) {
114 vchData.resize(nPos);
144 : m_type(type), m_version(version), m_data(data), m_pos(pos) {
145 if (m_pos > m_data.size()) {
146 throw std::ios_base::failure(
147 "VectorReader(...): end of data (m_pos > m_data.size())");
155 template <
typename... Args>
157 size_t pos, Args &&... args)
171 size_t size()
const {
return m_data.size() - m_pos; }
172 bool empty()
const {
return m_data.size() == m_pos; }
174 void read(
char *dst,
size_t n) {
180 size_t pos_next = m_pos + n;
181 if (pos_next > m_data.size()) {
182 throw std::ios_base::failure(
"VectorReader::read(): end of data");
184 memcpy(dst, m_data.data() + m_pos, n);
217 Init(nTypeIn, nVersionIn);
220 CDataStream(const_iterator pbegin, const_iterator pend,
int nTypeIn,
222 : vch(pbegin, pend) {
223 Init(nTypeIn, nVersionIn);
228 : vch(pbegin, pend) {
229 Init(nTypeIn, nVersionIn);
232 CDataStream(
const vector_type &vchIn,
int nTypeIn,
int nVersionIn)
233 : vch(vchIn.begin(), vchIn.end()) {
234 Init(nTypeIn, nVersionIn);
237 CDataStream(
const std::vector<char> &vchIn,
int nTypeIn,
int nVersionIn)
238 : vch(vchIn.begin(), vchIn.end()) {
239 Init(nTypeIn, nVersionIn);
242 CDataStream(
const std::vector<uint8_t> &vchIn,
int nTypeIn,
int nVersionIn)
243 : vch(vchIn.begin(), vchIn.end()) {
244 Init(nTypeIn, nVersionIn);
247 template <
typename... Args>
249 Init(nTypeIn, nVersionIn);
253 void Init(
int nTypeIn,
int nVersionIn) {
256 nVersion = nVersionIn;
270 std::string
str()
const {
return (std::string(begin(), end())); }
275 const_iterator
begin()
const {
return vch.begin() + nReadPos; }
276 iterator
begin() {
return vch.begin() + nReadPos; }
277 const_iterator
end()
const {
return vch.end(); }
278 iterator
end() {
return vch.end(); }
279 size_type
size()
const {
return vch.size() - nReadPos; }
280 bool empty()
const {
return vch.size() == nReadPos; }
281 void resize(size_type n, value_type c = 0) { vch.resize(n + nReadPos, c); }
282 void reserve(size_type n) { vch.reserve(n + nReadPos); }
284 return vch[pos + nReadPos];
286 reference
operator[](size_type pos) {
return vch[pos + nReadPos]; }
291 iterator
insert(iterator it,
const char x =
char()) {
292 return vch.insert(it, x);
294 void insert(iterator it, size_type n,
const char x) {
295 vch.insert(it, n, x);
297 value_type *
data() {
return vch.data() + nReadPos; }
298 const value_type *
data()
const {
return vch.data() + nReadPos; }
300 void insert(iterator it, std::vector<char>::const_iterator first,
301 std::vector<char>::const_iterator last) {
306 assert(last - first > 0);
307 if (it == vch.begin() + nReadPos &&
308 (
unsigned int)(last - first) <= nReadPos) {
310 nReadPos -= (last - first);
311 memcpy(&vch[nReadPos], &first[0], last - first);
313 vch.insert(it, first, last);
317 void insert(iterator it,
const char *first,
const char *last) {
322 assert(last - first > 0);
323 if (it == vch.begin() + nReadPos &&
324 (
unsigned int)(last - first) <= nReadPos) {
326 nReadPos -= (last - first);
327 memcpy(&vch[nReadPos], &first[0], last - first);
329 vch.insert(it, first, last);
334 if (it == vch.begin() + nReadPos) {
336 if (++nReadPos >= vch.size()) {
340 return vch.erase(vch.begin(), vch.end());
342 return vch.begin() + nReadPos;
344 return vch.erase(it);
348 iterator
erase(iterator first, iterator last) {
349 if (first == vch.begin() + nReadPos) {
351 if (last == vch.end()) {
353 return vch.erase(vch.begin(), vch.end());
355 nReadPos = (last - vch.begin());
359 return vch.erase(first, last);
363 vch.erase(vch.begin(), vch.begin() + nReadPos);
379 bool eof()
const {
return size() == 0; }
388 void read(
char *pch,
size_t nSize) {
394 unsigned int nReadPosNext = nReadPos + nSize;
395 if (nReadPosNext > vch.size()) {
396 throw std::ios_base::failure(
"CDataStream::read(): end of data");
398 memcpy(pch, &vch[nReadPos], nSize);
399 if (nReadPosNext == vch.size()) {
404 nReadPos = nReadPosNext;
410 throw std::ios_base::failure(
411 "CDataStream::ignore(): nSize negative");
413 unsigned int nReadPosNext = nReadPos + nSize;
414 if (nReadPosNext >= vch.size()) {
415 if (nReadPosNext > vch.size()) {
416 throw std::ios_base::failure(
417 "CDataStream::ignore(): end of data");
423 nReadPos = nReadPosNext;
426 void write(
const char *pch,
size_t nSize) {
428 vch.insert(vch.end(), pch, pch + nSize);
431 template <
typename Stream>
void Serialize(Stream &s)
const {
434 s.write((
char *)vch.data(), vch.size() *
sizeof(value_type));
451 d.insert(d.end(), begin(), end());
460 void Xor(
const std::vector<uint8_t> &key) {
461 if (key.size() == 0) {
465 for (size_type i = 0, j = 0; i != size(); i++) {
472 if (j == key.size()) j = 0;
498 if (nbits < 0 || nbits > 64) {
499 throw std::out_of_range(
"nbits must be between 0 and 64");
505 m_istream >> m_buffer;
509 int bits = std::min(8 - m_offset, nbits);
511 data |=
static_cast<uint8_t
>(m_buffer << m_offset) >> (8 - bits);
541 void Write(uint64_t data,
int nbits) {
542 if (nbits < 0 || nbits > 64) {
543 throw std::out_of_range(
"nbits must be between 0 and 64");
547 int bits = std::min(8 - m_offset, nbits);
548 m_buffer |= (data << (64 - nbits)) >> (64 - 8 + m_offset);
567 m_ostream << m_buffer;
589 : nType(nTypeIn), nVersion(nVersionIn) {
623 FILE *
Get()
const {
return file; }
626 bool IsNull()
const {
return (file ==
nullptr); }
634 void read(
char *pch,
size_t nSize) {
636 throw std::ios_base::failure(
637 "CAutoFile::read: file handle is nullptr");
639 if (fread(pch, 1, nSize, file) != nSize) {
640 throw std::ios_base::failure(feof(file)
641 ?
"CAutoFile::read: end of file" 642 :
"CAutoFile::read: fread failed");
648 throw std::ios_base::failure(
649 "CAutoFile::ignore: file handle is nullptr");
653 size_t nNow = std::min<size_t>(nSize,
sizeof(data));
654 if (fread(data, 1, nNow, file) != nNow) {
655 throw std::ios_base::failure(
656 feof(file) ?
"CAutoFile::ignore: end of file" 657 :
"CAutoFile::read: fread failed");
663 void write(
const char *pch,
size_t nSize) {
665 throw std::ios_base::failure(
666 "CAutoFile::write: file handle is nullptr");
668 if (fwrite(pch, 1, nSize, file) != nSize) {
669 throw std::ios_base::failure(
"CAutoFile::write: write failed");
676 throw std::ios_base::failure(
677 "CAutoFile::operator<<: file handle is nullptr");
686 throw std::ios_base::failure(
687 "CAutoFile::operator>>: file handle is nullptr");
723 unsigned int pos = nSrcPos % vchBuf.size();
724 unsigned int readNow = vchBuf.size() - pos;
725 unsigned int nAvail = vchBuf.size() - (nSrcPos - nReadPos) - nRewind;
726 if (nAvail < readNow) {
732 size_t nBytes = fread((
void *)&vchBuf[pos], 1, readNow, src);
734 throw std::ios_base::failure(
735 feof(src) ?
"CBufferedFile::Fill: end of file" 736 :
"CBufferedFile::Fill: fread failed");
744 int nTypeIn,
int nVersionIn)
745 : nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0),
746 nReadLimit(
std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn),
747 vchBuf(nBufSize, 0) {
748 if (nRewindIn >= nBufSize) {
749 throw std::ios_base::failure(
750 "Rewind limit must be less than buffer size");
772 bool eof()
const {
return nReadPos == nSrcPos && feof(src); }
775 void read(
char *pch,
size_t nSize) {
776 if (nSize + nReadPos > nReadLimit) {
777 throw std::ios_base::failure(
"Read attempted past buffer limit");
780 if (nReadPos == nSrcPos) {
783 unsigned int pos = nReadPos % vchBuf.size();
785 if (nNow + pos > vchBuf.size()) {
786 nNow = vchBuf.size() - pos;
788 if (nNow + nReadPos > nSrcPos) {
789 nNow = nSrcPos - nReadPos;
791 memcpy(pch, &vchBuf[pos], nNow);
799 uint64_t
GetPos()
const {
return nReadPos; }
803 size_t bufsize = vchBuf.size();
804 if (nPos + bufsize < nSrcPos) {
806 nReadPos = nSrcPos - bufsize;
809 if (nPos > nSrcPos) {
819 long nLongPos = nPos;
820 if (nPos != (uint64_t)nLongPos) {
823 if (fseek(src, nLongPos, SEEK_SET)) {
826 nLongPos = ftell(src);
834 bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
835 if (nPos < nReadPos) {
851 if (nReadPos == nSrcPos) {
854 if (vchBuf[nReadPos % vchBuf.size()] == ch) {
862 #endif // BITCOIN_STREAMS_H
CVectorWriter & operator<<(const T &obj)
void Init(int nTypeIn, int nVersionIn)
CSerializeData vector_type
void ignore(size_t nSize)
uint64_t nReadPos
how many bytes have been read from this
vector_type::iterator iterator
vector_type::allocator_type allocator_type
void read(char *dst, size_t n)
CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn)
CVectorWriter(int nTypeIn, int nVersionIn, std::vector< uint8_t > &vchDataIn, size_t nPosIn)
void write(const char *pch, size_t nSize)
vector_type::size_type size_type
void resize(size_type n, value_type c=0)
CDataStream(const vector_type &vchIn, int nTypeIn, int nVersionIn)
void Serialize(Stream &s) const
vector_type::reference reference
vector_type::value_type value_type
OverrideStream< Stream > & operator<<(const T &obj)
Double ended buffer combining vector and stream-like interfaces.
void write(const char *pch, size_t nSize)
OverrideStream< S > WithOrVersion(S *s, int nVersionFlag)
void Write(uint64_t data, int nbits)
Write the nbits least significant bits of a 64-bit int to the output stream.
vector_type::reverse_iterator reverse_iterator
iterator erase(iterator it)
CAutoFile(FILE *filenew, int nTypeIn, int nVersionIn)
void UnserializeMany(Stream &s)
const std::vector< uint8_t > & m_data
friend CDataStream operator+(const CDataStream &a, const CDataStream &b)
CDataStream(int nTypeIn, int nVersionIn)
void insert(iterator it, std::vector< char >::const_iterator first, std::vector< char >::const_iterator last)
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
iterator insert(iterator it, const char x=char())
FILE * release()
Get wrapped FILE* with transfer of ownership.
void write(const char *pch, size_t nSize)
void Serialize(Stream &s, char a)
void read(char *pch, size_t nSize)
vector_type::const_reference const_reference
void read(char *pch, size_t nSize)
CAutoFile & operator>>(T &&obj)
CDataStream(int nTypeIn, int nVersionIn, Args &&... args)
uint64_t GetPos() const
return the current reading position
BitStreamReader(IStream &istream)
CDataStream(const std::vector< char > &vchIn, int nTypeIn, int nVersionIn)
uint64_t nReadLimit
up to which position we're allowed to read
vector_type::const_iterator const_iterator
CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn)
Minimal stream for reading from an existing vector by reference.
const value_type * data() const
CDataStream(const char *pbegin, const char *pend, int nTypeIn, int nVersionIn)
CDataStream & operator+=(const CDataStream &b)
CDataStream & operator>>(T &&obj)
void GetAndClear(CSerializeData &d)
void write(const char *pch, size_t nSize)
CDataStream(const std::vector< uint8_t > &vchIn, int nTypeIn, int nVersionIn)
void read(char *pch, size_t nSize)
void read(char *pch, size_t nSize)
read a number of bytes
reference operator[](size_type pos)
uint64_t Read(int nbits)
Read the specified number of bits from the stream.
bool SetPos(uint64_t nPos)
rewind to a given reading position
OverrideStream(Stream *stream_, int nType_, int nVersion_)
VectorReader(int type, int version, const std::vector< uint8_t > &data, size_t pos)
void SerializeMany(Stream &s)
void Flush()
Flush any unwritten bits to the output stream, padding with 0's to the next byte boundary.
const_reference operator[](size_type pos) const
void Xor(const std::vector< uint8_t > &key)
XOR the contents of this stream with a certain key.
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
const_iterator end() const
const_iterator begin() const
VectorReader & operator>>(T &obj)
CDataStream & operator<<(const T &obj)
void FindByte(char ch)
search for a given byte in the stream, and remain positioned on it
void reserve(size_type n)
CBufferedFile & operator>>(T &&obj)
std::vector< uint8_t > & vchData
VectorReader(int type, int version, const std::vector< uint8_t > &data, size_t pos, Args &&... args)
(other params same as above)
void Unserialize(Stream &s, char &a)
vector_type::difference_type difference_type
void insert(iterator it, const char *first, const char *last)
uint64_t nSrcPos
how many bytes have been read from source
bool Fill()
read data from the source to fill the buffer
std::vector< char, zero_after_free_allocator< char > > CSerializeData
Minimal stream for overwriting and/or appending to an existing byte vector.
std::vector< char > vchBuf
the buffer
iterator erase(iterator first, iterator last)
uint64_t nRewind
how many bytes we guarantee to rewind
bool SetLimit(uint64_t nPos=std::numeric_limits< uint64_t >::max())
Prevent reading beyond a certain position.
Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to deserialize from...
OverrideStream< Stream > & operator>>(T &&obj)
CAutoFile & operator<<(const T &obj)
void insert(iterator it, size_type n, const char x)
CVectorWriter(int nTypeIn, int nVersionIn, std::vector< uint8_t > &vchDataIn, size_t nPosIn, Args &&... args)
(other params same as above)
Non-refcounted RAII wrapper for FILE*.
BitStreamWriter(OStream &ostream)
bool eof() const
check whether we're at the end of the source file