Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #ifndef BITCOIN_STREAMS_H
# 7 : : #define BITCOIN_STREAMS_H
# 8 : :
# 9 : : #include <serialize.h>
# 10 : : #include <span.h>
# 11 : : #include <support/allocators/zeroafterfree.h>
# 12 : :
# 13 : : #include <algorithm>
# 14 : : #include <assert.h>
# 15 : : #include <ios>
# 16 : : #include <limits>
# 17 : : #include <optional>
# 18 : : #include <stdint.h>
# 19 : : #include <stdio.h>
# 20 : : #include <string.h>
# 21 : : #include <string>
# 22 : : #include <utility>
# 23 : : #include <vector>
# 24 : :
# 25 : : template<typename Stream>
# 26 : : class OverrideStream
# 27 : : {
# 28 : : Stream* stream;
# 29 : :
# 30 : : const int nType;
# 31 : : const int nVersion;
# 32 : :
# 33 : : public:
# 34 : 4103 : OverrideStream(Stream* stream_, int nType_, int nVersion_) : stream(stream_), nType(nType_), nVersion(nVersion_) {}
# 35 : :
# 36 : : template<typename T>
# 37 : : OverrideStream<Stream>& operator<<(const T& obj)
# 38 : 2457324 : {
# 39 : : // Serialize to this stream
# 40 : 2457324 : ::Serialize(*this, obj);
# 41 : 2457324 : return (*this);
# 42 : 2457324 : }
# 43 : :
# 44 : : template<typename T>
# 45 : : OverrideStream<Stream>& operator>>(T&& obj)
# 46 : 282835 : {
# 47 : : // Unserialize from this stream
# 48 : 282835 : ::Unserialize(*this, obj);
# 49 : 282835 : return (*this);
# 50 : 282835 : }
# 51 : :
# 52 : : void write(const char* pch, size_t nSize)
# 53 : 2930715 : {
# 54 : 2930715 : stream->write(pch, nSize);
# 55 : 2930715 : }
# 56 : :
# 57 : : void read(char* pch, size_t nSize)
# 58 : 311255 : {
# 59 : 311255 : stream->read(pch, nSize);
# 60 : 311255 : }
# 61 : :
# 62 : 202983 : int GetVersion() const { return nVersion; }
# 63 : 136953 : int GetType() const { return nType; }
# 64 : 1724 : size_t size() const { return stream->size(); }
# 65 : 1 : void ignore(size_t size) { return stream->ignore(size); }
# 66 : : };
# 67 : :
# 68 : : /* Minimal stream for overwriting and/or appending to an existing byte vector
# 69 : : *
# 70 : : * The referenced vector will grow as necessary
# 71 : : */
# 72 : : class CVectorWriter
# 73 : : {
# 74 : : public:
# 75 : :
# 76 : : /*
# 77 : : * @param[in] nTypeIn Serialization Type
# 78 : : * @param[in] nVersionIn Serialization Version (including any flags)
# 79 : : * @param[in] vchDataIn Referenced byte vector to overwrite/append
# 80 : : * @param[in] nPosIn Starting position. Vector index where writes should start. The vector will initially
# 81 : : * grow as necessary to max(nPosIn, vec.size()). So to append, use vec.size().
# 82 : : */
# 83 : : CVectorWriter(int nTypeIn, int nVersionIn, std::vector<unsigned char>& vchDataIn, size_t nPosIn) : nType(nTypeIn), nVersion(nVersionIn), vchData(vchDataIn), nPos(nPosIn)
# 84 : 240017 : {
# 85 [ + + ]: 240017 : if(nPos > vchData.size())
# 86 : 2 : vchData.resize(nPos);
# 87 : 240017 : }
# 88 : : /*
# 89 : : * (other params same as above)
# 90 : : * @param[in] args A list of items to serialize starting at nPosIn.
# 91 : : */
# 92 : : template <typename... Args>
# 93 : : CVectorWriter(int nTypeIn, int nVersionIn, std::vector<unsigned char>& vchDataIn, size_t nPosIn, Args&&... args) : CVectorWriter(nTypeIn, nVersionIn, vchDataIn, nPosIn)
# 94 : 230470 : {
# 95 : 230470 : ::SerializeMany(*this, std::forward<Args>(args)...);
# 96 : 230470 : }
# 97 : : void write(const char* pch, size_t nSize)
# 98 : 10890605 : {
# 99 : 10890605 : assert(nPos <= vchData.size());
# 100 : 10890605 : size_t nOverwrite = std::min(nSize, vchData.size() - nPos);
# 101 [ + + ]: 10890605 : if (nOverwrite) {
# 102 : 38 : memcpy(vchData.data() + nPos, reinterpret_cast<const unsigned char*>(pch), nOverwrite);
# 103 : 38 : }
# 104 [ + + ]: 10890605 : if (nOverwrite < nSize) {
# 105 : 10890564 : vchData.insert(vchData.end(), reinterpret_cast<const unsigned char*>(pch) + nOverwrite, reinterpret_cast<const unsigned char*>(pch) + nSize);
# 106 : 10890564 : }
# 107 : 10890605 : nPos += nSize;
# 108 : 10890605 : }
# 109 : : template<typename T>
# 110 : : CVectorWriter& operator<<(const T& obj)
# 111 : 379379 : {
# 112 : : // Serialize to this stream
# 113 : 379379 : ::Serialize(*this, obj);
# 114 : 379379 : return (*this);
# 115 : 379379 : }
# 116 : : int GetVersion() const
# 117 : 84099 : {
# 118 : 84099 : return nVersion;
# 119 : 84099 : }
# 120 : : int GetType() const
# 121 : 23875 : {
# 122 : 23875 : return nType;
# 123 : 23875 : }
# 124 : : private:
# 125 : : const int nType;
# 126 : : const int nVersion;
# 127 : : std::vector<unsigned char>& vchData;
# 128 : : size_t nPos;
# 129 : : };
# 130 : :
# 131 : : /** Minimal stream for reading from an existing vector by reference
# 132 : : */
# 133 : : class VectorReader
# 134 : : {
# 135 : : private:
# 136 : : const int m_type;
# 137 : : const int m_version;
# 138 : : const std::vector<unsigned char>& m_data;
# 139 : : size_t m_pos = 0;
# 140 : :
# 141 : : public:
# 142 : :
# 143 : : /**
# 144 : : * @param[in] type Serialization Type
# 145 : : * @param[in] version Serialization Version (including any flags)
# 146 : : * @param[in] data Referenced byte vector to overwrite/append
# 147 : : * @param[in] pos Starting position. Vector index where reads should start.
# 148 : : */
# 149 : : VectorReader(int type, int version, const std::vector<unsigned char>& data, size_t pos)
# 150 : : : m_type(type), m_version(version), m_data(data), m_pos(pos)
# 151 : 1141 : {
# 152 [ - + ]: 1141 : if (m_pos > m_data.size()) {
# 153 : 0 : throw std::ios_base::failure("VectorReader(...): end of data (m_pos > m_data.size())");
# 154 : 0 : }
# 155 : 1141 : }
# 156 : :
# 157 : : /**
# 158 : : * (other params same as above)
# 159 : : * @param[in] args A list of items to deserialize starting at pos.
# 160 : : */
# 161 : : template <typename... Args>
# 162 : : VectorReader(int type, int version, const std::vector<unsigned char>& data, size_t pos,
# 163 : : Args&&... args)
# 164 : : : VectorReader(type, version, data, pos)
# 165 : : {
# 166 : : ::UnserializeMany(*this, std::forward<Args>(args)...);
# 167 : : }
# 168 : :
# 169 : : template<typename T>
# 170 : : VectorReader& operator>>(T&& obj)
# 171 : 28482 : {
# 172 : : // Unserialize from this stream
# 173 : 28482 : ::Unserialize(*this, obj);
# 174 : 28482 : return (*this);
# 175 : 28482 : }
# 176 : :
# 177 : 0 : int GetVersion() const { return m_version; }
# 178 : 0 : int GetType() const { return m_type; }
# 179 : :
# 180 : 10 : size_t size() const { return m_data.size() - m_pos; }
# 181 : 724 : bool empty() const { return m_data.size() == m_pos; }
# 182 : :
# 183 : : void read(char* dst, size_t n)
# 184 : 29625 : {
# 185 [ - + ]: 29625 : if (n == 0) {
# 186 : 0 : return;
# 187 : 0 : }
# 188 : :
# 189 : : // Read from the beginning of the buffer
# 190 : 29625 : size_t pos_next = m_pos + n;
# 191 [ + + ]: 29625 : if (pos_next > m_data.size()) {
# 192 : 8 : throw std::ios_base::failure("VectorReader::read(): end of data");
# 193 : 8 : }
# 194 : 29617 : memcpy(dst, m_data.data() + m_pos, n);
# 195 : 29617 : m_pos = pos_next;
# 196 : 29617 : }
# 197 : : };
# 198 : :
# 199 : : /** Double ended buffer combining vector and stream-like interfaces.
# 200 : : *
# 201 : : * >> and << read and write unformatted data using the above serialization templates.
# 202 : : * Fills with data in linear time; some stringstream implementations take N^2 time.
# 203 : : */
# 204 : : class CDataStream
# 205 : : {
# 206 : : protected:
# 207 : : using vector_type = SerializeData;
# 208 : : vector_type vch;
# 209 : : unsigned int nReadPos{0};
# 210 : :
# 211 : : int nType;
# 212 : : int nVersion;
# 213 : :
# 214 : : public:
# 215 : : typedef vector_type::allocator_type allocator_type;
# 216 : : typedef vector_type::size_type size_type;
# 217 : : typedef vector_type::difference_type difference_type;
# 218 : : typedef vector_type::reference reference;
# 219 : : typedef vector_type::const_reference const_reference;
# 220 : : typedef vector_type::value_type value_type;
# 221 : : typedef vector_type::iterator iterator;
# 222 : : typedef vector_type::const_iterator const_iterator;
# 223 : : typedef vector_type::reverse_iterator reverse_iterator;
# 224 : :
# 225 : : explicit CDataStream(int nTypeIn, int nVersionIn)
# 226 : : : nType{nTypeIn},
# 227 : 10389194 : nVersion{nVersionIn} {}
# 228 : :
# 229 : : explicit CDataStream(Span<const uint8_t> sp, int nTypeIn, int nVersionIn)
# 230 : : : vch(sp.data(), sp.data() + sp.size()),
# 231 : : nType{nTypeIn},
# 232 : 339258 : nVersion{nVersionIn} {}
# 233 : :
# 234 : : template <typename... Args>
# 235 : : CDataStream(int nTypeIn, int nVersionIn, Args&&... args)
# 236 : : : nType{nTypeIn},
# 237 : : nVersion{nVersionIn}
# 238 : 2 : {
# 239 : 2 : ::SerializeMany(*this, std::forward<Args>(args)...);
# 240 : 2 : }
# 241 : :
# 242 : : std::string str() const
# 243 : 370 : {
# 244 : 370 : return (std::string(begin(), end()));
# 245 : 370 : }
# 246 : :
# 247 : :
# 248 : : //
# 249 : : // Vector subset
# 250 : : //
# 251 : 370 : const_iterator begin() const { return vch.begin() + nReadPos; }
# 252 : 156221 : iterator begin() { return vch.begin() + nReadPos; }
# 253 : 370 : const_iterator end() const { return vch.end(); }
# 254 : 78215 : iterator end() { return vch.end(); }
# 255 : 56725554 : size_type size() const { return vch.size() - nReadPos; }
# 256 : 25561 : bool empty() const { return vch.size() == nReadPos; }
# 257 : 225890 : void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); }
# 258 : 9744359 : void reserve(size_type n) { vch.reserve(n + nReadPos); }
# 259 : 0 : const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; }
# 260 : 34980572 : reference operator[](size_type pos) { return vch[pos + nReadPos]; }
# 261 : 1038368 : void clear() { vch.clear(); nReadPos = 0; }
# 262 : 6 : iterator insert(iterator it, const uint8_t x) { return vch.insert(it, x); }
# 263 : 0 : void insert(iterator it, size_type n, const uint8_t x) { vch.insert(it, n, x); }
# 264 : 9316508 : value_type* data() { return vch.data() + nReadPos; }
# 265 : 1444 : const value_type* data() const { return vch.data() + nReadPos; }
# 266 : :
# 267 : : void insert(iterator it, std::vector<uint8_t>::const_iterator first, std::vector<uint8_t>::const_iterator last)
# 268 : 4 : {
# 269 [ - + ]: 4 : if (last == first) return;
# 270 : 4 : assert(last - first > 0);
# 271 [ + - ][ - + ]: 4 : if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
# [ - + ]
# 272 : 0 : {
# 273 : : // special case for inserting at the front when there's room
# 274 : 0 : nReadPos -= (last - first);
# 275 : 0 : memcpy(&vch[nReadPos], &first[0], last - first);
# 276 : 0 : }
# 277 : 4 : else
# 278 : 4 : vch.insert(it, first, last);
# 279 : 4 : }
# 280 : :
# 281 : : void insert(iterator it, const char* first, const char* last)
# 282 : 0 : {
# 283 : 0 : if (last == first) return;
# 284 : 0 : assert(last - first > 0);
# 285 : 0 : if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
# 286 : 0 : {
# 287 : 0 : // special case for inserting at the front when there's room
# 288 : 0 : nReadPos -= (last - first);
# 289 : 0 : memcpy(&vch[nReadPos], &first[0], last - first);
# 290 : 0 : }
# 291 : 0 : else
# 292 : 0 : vch.insert(it, first, last);
# 293 : 0 : }
# 294 : :
# 295 : : iterator erase(iterator it)
# 296 : 6 : {
# 297 [ + + ]: 6 : if (it == vch.begin() + nReadPos)
# 298 : 2 : {
# 299 : : // special case for erasing from the front
# 300 [ - + ]: 2 : if (++nReadPos >= vch.size())
# 301 : 0 : {
# 302 : : // whenever we reach the end, we take the opportunity to clear the buffer
# 303 : 0 : nReadPos = 0;
# 304 : 0 : return vch.erase(vch.begin(), vch.end());
# 305 : 0 : }
# 306 : 2 : return vch.begin() + nReadPos;
# 307 : 2 : }
# 308 : 4 : else
# 309 : 4 : return vch.erase(it);
# 310 : 6 : }
# 311 : :
# 312 : : iterator erase(iterator first, iterator last)
# 313 : 0 : {
# 314 : 0 : if (first == vch.begin() + nReadPos)
# 315 : 0 : {
# 316 : 0 : // special case for erasing from the front
# 317 : 0 : if (last == vch.end())
# 318 : 0 : {
# 319 : 0 : nReadPos = 0;
# 320 : 0 : return vch.erase(vch.begin(), vch.end());
# 321 : 0 : }
# 322 : 0 : else
# 323 : 0 : {
# 324 : 0 : nReadPos = (last - vch.begin());
# 325 : 0 : return last;
# 326 : 0 : }
# 327 : 0 : }
# 328 : 0 : else
# 329 : 0 : return vch.erase(first, last);
# 330 : 0 : }
# 331 : :
# 332 : : inline void Compact()
# 333 : 0 : {
# 334 : 0 : vch.erase(vch.begin(), vch.begin() + nReadPos);
# 335 : 0 : nReadPos = 0;
# 336 : 0 : }
# 337 : :
# 338 : : bool Rewind(std::optional<size_type> n = std::nullopt)
# 339 : 0 : {
# 340 : 0 : // Total rewind if no size is passed
# 341 : 0 : if (!n) {
# 342 : 0 : nReadPos = 0;
# 343 : 0 : return true;
# 344 : 0 : }
# 345 : 0 : // Rewind by n characters if the buffer hasn't been compacted yet
# 346 : 0 : if (*n > nReadPos)
# 347 : 0 : return false;
# 348 : 0 : nReadPos -= *n;
# 349 : 0 : return true;
# 350 : 0 : }
# 351 : :
# 352 : :
# 353 : : //
# 354 : : // Stream subset
# 355 : : //
# 356 : 135 : bool eof() const { return size() == 0; }
# 357 : 0 : CDataStream* rdbuf() { return this; }
# 358 : 1167 : int in_avail() const { return size(); }
# 359 : :
# 360 : 107112 : void SetType(int n) { nType = n; }
# 361 : 189030 : int GetType() const { return nType; }
# 362 : 107455 : void SetVersion(int n) { nVersion = n; }
# 363 : 460765 : int GetVersion() const { return nVersion; }
# 364 : :
# 365 : : void read(char* pch, size_t nSize)
# 366 : 11074097 : {
# 367 [ + + ]: 11074097 : if (nSize == 0) return;
# 368 : :
# 369 : : // Read from the beginning of the buffer
# 370 : 11071573 : unsigned int nReadPosNext = nReadPos + nSize;
# 371 [ + + ]: 11071573 : if (nReadPosNext > vch.size()) {
# 372 : 1600 : throw std::ios_base::failure("CDataStream::read(): end of data");
# 373 : 1600 : }
# 374 : 11069973 : memcpy(pch, &vch[nReadPos], nSize);
# 375 [ + + ]: 11069973 : if (nReadPosNext == vch.size())
# 376 : 694771 : {
# 377 : 694771 : nReadPos = 0;
# 378 : 694771 : vch.clear();
# 379 : 694771 : return;
# 380 : 694771 : }
# 381 : 10375202 : nReadPos = nReadPosNext;
# 382 : 10375202 : }
# 383 : :
# 384 : : void ignore(int nSize)
# 385 : 7 : {
# 386 : : // Ignore from the beginning of the buffer
# 387 [ + + ]: 7 : if (nSize < 0) {
# 388 : 2 : throw std::ios_base::failure("CDataStream::ignore(): nSize negative");
# 389 : 2 : }
# 390 : 5 : unsigned int nReadPosNext = nReadPos + nSize;
# 391 [ + + ]: 5 : if (nReadPosNext >= vch.size())
# 392 : 4 : {
# 393 [ - + ]: 4 : if (nReadPosNext > vch.size())
# 394 : 0 : throw std::ios_base::failure("CDataStream::ignore(): end of data");
# 395 : 4 : nReadPos = 0;
# 396 : 4 : vch.clear();
# 397 : 4 : return;
# 398 : 4 : }
# 399 : 1 : nReadPos = nReadPosNext;
# 400 : 1 : }
# 401 : :
# 402 : : void write(const char* pch, size_t nSize)
# 403 : 59968430 : {
# 404 : : // Write to the end of the buffer
# 405 : 59968430 : vch.insert(vch.end(), pch, pch + nSize);
# 406 : 59968430 : }
# 407 : :
# 408 : : template<typename Stream>
# 409 : : void Serialize(Stream& s) const
# 410 : 0 : {
# 411 : : // Special case: stream << stream concatenates like stream += stream
# 412 [ # # ]: 0 : if (!vch.empty())
# 413 : 0 : s.write((char*)vch.data(), vch.size() * sizeof(value_type));
# 414 : 0 : }
# 415 : :
# 416 : : template<typename T>
# 417 : : CDataStream& operator<<(const T& obj)
# 418 : 14343592 : {
# 419 : : // Serialize to this stream
# 420 : 14343592 : ::Serialize(*this, obj);
# 421 : 14343592 : return (*this);
# 422 : 14343592 : }
# 423 : :
# 424 : : template<typename T>
# 425 : : CDataStream& operator>>(T&& obj)
# 426 : 2454108 : {
# 427 : : // Unserialize from this stream
# 428 : 2454108 : ::Unserialize(*this, obj);
# 429 : 2454108 : return (*this);
# 430 : 2454108 : }
# 431 : :
# 432 : : /**
# 433 : : * XOR the contents of this stream with a certain key.
# 434 : : *
# 435 : : * @param[in] key The key used to XOR the data in this stream.
# 436 : : */
# 437 : : void Xor(const std::vector<unsigned char>& key)
# 438 : 568614 : {
# 439 [ - + ]: 568614 : if (key.size() == 0) {
# 440 : 0 : return;
# 441 : 0 : }
# 442 : :
# 443 [ + + ]: 27988224 : for (size_type i = 0, j = 0; i != size(); i++) {
# 444 : 27419610 : vch[i] ^= key[j++];
# 445 : :
# 446 : : // This potentially acts on very many bytes of data, so it's
# 447 : : // important that we calculate `j`, i.e. the `key` index in this
# 448 : : // way instead of doing a %, which would effectively be a division
# 449 : : // for each byte Xor'd -- much slower than need be.
# 450 [ + + ]: 27419610 : if (j == key.size())
# 451 : 3190364 : j = 0;
# 452 : 27419610 : }
# 453 : 568614 : }
# 454 : : };
# 455 : :
# 456 : : template <typename IStream>
# 457 : : class BitStreamReader
# 458 : : {
# 459 : : private:
# 460 : : IStream& m_istream;
# 461 : :
# 462 : : /// Buffered byte read in from the input stream. A new byte is read into the
# 463 : : /// buffer when m_offset reaches 8.
# 464 : : uint8_t m_buffer{0};
# 465 : :
# 466 : : /// Number of high order bits in m_buffer already returned by previous
# 467 : : /// Read() calls. The next bit to be returned is at this offset from the
# 468 : : /// most significant bit position.
# 469 : : int m_offset{8};
# 470 : :
# 471 : : public:
# 472 : 1113 : explicit BitStreamReader(IStream& istream) : m_istream(istream) {}
# 473 : :
# 474 : : /** Read the specified number of bits from the stream. The data is returned
# 475 : : * in the nbits least significant bits of a 64-bit uint.
# 476 : : */
# 477 : 46865 : uint64_t Read(int nbits) {
# 478 [ - + ][ - + ]: 46865 : if (nbits < 0 || nbits > 64) {
# [ - + ][ - + ]
# 479 : 0 : throw std::out_of_range("nbits must be between 0 and 64");
# 480 : 0 : }
# 481 : :
# 482 : 46865 : uint64_t data = 0;
# 483 [ + + ][ + + ]: 116406 : while (nbits > 0) {
# 484 [ + + ][ + + ]: 69541 : if (m_offset == 8) {
# 485 : 28435 : m_istream >> m_buffer;
# 486 : 28435 : m_offset = 0;
# 487 : 28435 : }
# 488 : :
# 489 : 69541 : int bits = std::min(8 - m_offset, nbits);
# 490 : 69541 : data <<= bits;
# 491 : 69541 : data |= static_cast<uint8_t>(m_buffer << m_offset) >> (8 - bits);
# 492 : 69541 : m_offset += bits;
# 493 : 69541 : nbits -= bits;
# 494 : 69541 : }
# 495 : 46865 : return data;
# 496 : 46865 : }
# 497 : : };
# 498 : :
# 499 : : template <typename OStream>
# 500 : : class BitStreamWriter
# 501 : : {
# 502 : : private:
# 503 : : OStream& m_ostream;
# 504 : :
# 505 : : /// Buffered byte waiting to be written to the output stream. The byte is
# 506 : : /// written buffer when m_offset reaches 8 or Flush() is called.
# 507 : : uint8_t m_buffer{0};
# 508 : :
# 509 : : /// Number of high order bits in m_buffer already written by previous
# 510 : : /// Write() calls and not yet flushed to the stream. The next bit to be
# 511 : : /// written to is at this offset from the most significant bit position.
# 512 : : int m_offset{0};
# 513 : :
# 514 : : public:
# 515 : 5386 : explicit BitStreamWriter(OStream& ostream) : m_ostream(ostream) {}
# 516 : :
# 517 : : ~BitStreamWriter()
# 518 : 5386 : {
# 519 : 5386 : Flush();
# 520 : 5386 : }
# 521 : :
# 522 : : /** Write the nbits least significant bits of a 64-bit int to the output
# 523 : : * stream. Data is buffered until it completes an octet.
# 524 : : */
# 525 : 13200 : void Write(uint64_t data, int nbits) {
# 526 [ - + ][ - + ]: 13200 : if (nbits < 0 || nbits > 64) {
# [ - + ][ - + ]
# 527 : 0 : throw std::out_of_range("nbits must be between 0 and 64");
# 528 : 0 : }
# 529 : :
# 530 [ + + ][ + + ]: 37570 : while (nbits > 0) {
# 531 : 24370 : int bits = std::min(8 - m_offset, nbits);
# 532 : 24370 : m_buffer |= (data << (64 - nbits)) >> (64 - 8 + m_offset);
# 533 : 24370 : m_offset += bits;
# 534 : 24370 : nbits -= bits;
# 535 : :
# 536 [ + + ][ + + ]: 24370 : if (m_offset == 8) {
# 537 : 11246 : Flush();
# 538 : 11246 : }
# 539 : 24370 : }
# 540 : 13200 : }
# 541 : :
# 542 : : /** Flush any unwritten bits to the output stream, padding with 0's to the
# 543 : : * next byte boundary.
# 544 : : */
# 545 : 22018 : void Flush() {
# 546 [ + + ][ + + ]: 22018 : if (m_offset == 0) {
# 547 : 5388 : return;
# 548 : 5388 : }
# 549 : :
# 550 : 16630 : m_ostream << m_buffer;
# 551 : 16630 : m_buffer = 0;
# 552 : 16630 : m_offset = 0;
# 553 : 16630 : }
# 554 : : };
# 555 : :
# 556 : :
# 557 : :
# 558 : : /** Non-refcounted RAII wrapper for FILE*
# 559 : : *
# 560 : : * Will automatically close the file when it goes out of scope if not null.
# 561 : : * If you're returning the file pointer, return file.release().
# 562 : : * If you need to close the file early, use file.fclose() instead of fclose(file).
# 563 : : */
# 564 : : class CAutoFile
# 565 : : {
# 566 : : private:
# 567 : : const int nType;
# 568 : : const int nVersion;
# 569 : :
# 570 : : FILE* file;
# 571 : :
# 572 : : public:
# 573 : : CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn)
# 574 : 281986 : {
# 575 : 281986 : file = filenew;
# 576 : 281986 : }
# 577 : :
# 578 : : ~CAutoFile()
# 579 : 281987 : {
# 580 : 281987 : fclose();
# 581 : 281987 : }
# 582 : :
# 583 : : // Disallow copies
# 584 : : CAutoFile(const CAutoFile&) = delete;
# 585 : : CAutoFile& operator=(const CAutoFile&) = delete;
# 586 : :
# 587 : : void fclose()
# 588 : 284797 : {
# 589 [ + + ]: 284797 : if (file) {
# 590 : 279709 : ::fclose(file);
# 591 : 279709 : file = nullptr;
# 592 : 279709 : }
# 593 : 284797 : }
# 594 : :
# 595 : : /** Get wrapped FILE* with transfer of ownership.
# 596 : : * @note This will invalidate the CAutoFile object, and makes it the responsibility of the caller
# 597 : : * of this function to clean up the returned FILE*.
# 598 : : */
# 599 : 0 : FILE* release() { FILE* ret = file; file = nullptr; return ret; }
# 600 : :
# 601 : : /** Get wrapped FILE* without transfer of ownership.
# 602 : : * @note Ownership of the FILE* will remain with this class. Use this only if the scope of the
# 603 : : * CAutoFile outlives use of the passed pointer.
# 604 : : */
# 605 : 137259 : FILE* Get() const { return file; }
# 606 : :
# 607 : : /** Return true if the wrapped FILE* is nullptr, false otherwise.
# 608 : : */
# 609 : 281325 : bool IsNull() const { return (file == nullptr); }
# 610 : :
# 611 : : //
# 612 : : // Stream subset
# 613 : : //
# 614 : 18276 : int GetType() const { return nType; }
# 615 : 420932 : int GetVersion() const { return nVersion; }
# 616 : :
# 617 : : void read(char* pch, size_t nSize)
# 618 : 15140353 : {
# 619 [ - + ]: 15140353 : if (!file)
# 620 : 0 : throw std::ios_base::failure("CAutoFile::read: file handle is nullptr");
# 621 [ + + ]: 15140353 : if (fread(pch, 1, nSize, file) != nSize)
# 622 [ + - ]: 6 : throw std::ios_base::failure(feof(file) ? "CAutoFile::read: end of file" : "CAutoFile::read: fread failed");
# 623 : 15140353 : }
# 624 : :
# 625 : : void ignore(size_t nSize)
# 626 : 0 : {
# 627 [ # # ]: 0 : if (!file)
# 628 : 0 : throw std::ios_base::failure("CAutoFile::ignore: file handle is nullptr");
# 629 : 0 : unsigned char data[4096];
# 630 [ # # ]: 0 : while (nSize > 0) {
# 631 : 0 : size_t nNow = std::min<size_t>(nSize, sizeof(data));
# 632 [ # # ]: 0 : if (fread(data, 1, nNow, file) != nNow)
# 633 [ # # ]: 0 : throw std::ios_base::failure(feof(file) ? "CAutoFile::ignore: end of file" : "CAutoFile::read: fread failed");
# 634 : 0 : nSize -= nNow;
# 635 : 0 : }
# 636 : 0 : }
# 637 : :
# 638 : : void write(const char* pch, size_t nSize)
# 639 : 27113569 : {
# 640 [ - + ]: 27113569 : if (!file)
# 641 : 0 : throw std::ios_base::failure("CAutoFile::write: file handle is nullptr");
# 642 [ + + ]: 27113569 : if (fwrite(pch, 1, nSize, file) != nSize)
# 643 : 2 : throw std::ios_base::failure("CAutoFile::write: write failed");
# 644 : 27113569 : }
# 645 : :
# 646 : : template<typename T>
# 647 : : CAutoFile& operator<<(const T& obj)
# 648 : 21001619 : {
# 649 : : // Serialize to this stream
# 650 [ - + ][ - + ]: 21001619 : if (!file)
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ # # ]
# [ # # ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ]
# 651 : 0 : throw std::ios_base::failure("CAutoFile::operator<<: file handle is nullptr");
# 652 : 21001619 : ::Serialize(*this, obj);
# 653 : 21001619 : return (*this);
# 654 : 21001619 : }
# 655 : :
# 656 : : template<typename T>
# 657 : : CAutoFile& operator>>(T&& obj)
# 658 : 9099993 : {
# 659 : : // Unserialize from this stream
# 660 [ - + ][ - + ]: 9099993 : if (!file)
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ]
# 661 : 0 : throw std::ios_base::failure("CAutoFile::operator>>: file handle is nullptr");
# 662 : 9099993 : ::Unserialize(*this, obj);
# 663 : 9099993 : return (*this);
# 664 : 9099993 : }
# 665 : : };
# 666 : :
# 667 : : /** Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to
# 668 : : * deserialize from. It guarantees the ability to rewind a given number of bytes.
# 669 : : *
# 670 : : * Will automatically close the file when it goes out of scope if not null.
# 671 : : * If you need to close the file early, use file.fclose() instead of fclose(file).
# 672 : : */
# 673 : : class CBufferedFile
# 674 : : {
# 675 : : private:
# 676 : : const int nType;
# 677 : : const int nVersion;
# 678 : :
# 679 : : FILE *src; //!< source file
# 680 : : uint64_t nSrcPos; //!< how many bytes have been read from source
# 681 : : uint64_t nReadPos; //!< how many bytes have been read from this
# 682 : : uint64_t nReadLimit; //!< up to which position we're allowed to read
# 683 : : uint64_t nRewind; //!< how many bytes we guarantee to rewind
# 684 : : std::vector<char> vchBuf; //!< the buffer
# 685 : :
# 686 : : protected:
# 687 : : //! read data from the source to fill the buffer
# 688 : 685 : bool Fill() {
# 689 : 685 : unsigned int pos = nSrcPos % vchBuf.size();
# 690 : 685 : unsigned int readNow = vchBuf.size() - pos;
# 691 : 685 : unsigned int nAvail = vchBuf.size() - (nSrcPos - nReadPos) - nRewind;
# 692 [ + + ]: 685 : if (nAvail < readNow)
# 693 : 593 : readNow = nAvail;
# 694 [ - + ]: 685 : if (readNow == 0)
# 695 : 0 : return false;
# 696 : 685 : size_t nBytes = fread((void*)&vchBuf[pos], 1, readNow, src);
# 697 [ + + ]: 685 : if (nBytes == 0) {
# 698 [ + - ]: 11 : throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed");
# 699 : 11 : }
# 700 : 674 : nSrcPos += nBytes;
# 701 : 674 : return true;
# 702 : 674 : }
# 703 : :
# 704 : : public:
# 705 : : CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
# 706 : : nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, 0)
# 707 : 114 : {
# 708 [ + + ]: 114 : if (nRewindIn >= nBufSize)
# 709 : 2 : throw std::ios_base::failure("Rewind limit must be less than buffer size");
# 710 : 112 : src = fileIn;
# 711 : 112 : }
# 712 : :
# 713 : : ~CBufferedFile()
# 714 : 112 : {
# 715 : 112 : fclose();
# 716 : 112 : }
# 717 : :
# 718 : : // Disallow copies
# 719 : : CBufferedFile(const CBufferedFile&) = delete;
# 720 : : CBufferedFile& operator=(const CBufferedFile&) = delete;
# 721 : :
# 722 : 2390 : int GetVersion() const { return nVersion; }
# 723 : 2 : int GetType() const { return nType; }
# 724 : :
# 725 : : void fclose()
# 726 : 114 : {
# 727 [ + + ]: 114 : if (src) {
# 728 : 112 : ::fclose(src);
# 729 : 112 : src = nullptr;
# 730 : 112 : }
# 731 : 114 : }
# 732 : :
# 733 : : //! check whether we're at the end of the source file
# 734 : 9057 : bool eof() const {
# 735 [ + + ][ + + ]: 9057 : return nReadPos == nSrcPos && feof(src);
# 736 : 9057 : }
# 737 : :
# 738 : : //! read a number of bytes
# 739 : 83827 : void read(char *pch, size_t nSize) {
# 740 [ + + ]: 83827 : if (nSize + nReadPos > nReadLimit)
# 741 : 2 : throw std::ios_base::failure("Read attempted past buffer limit");
# 742 [ + + ]: 167906 : while (nSize > 0) {
# 743 [ + + ]: 84081 : if (nReadPos == nSrcPos)
# 744 : 416 : Fill();
# 745 : 84081 : unsigned int pos = nReadPos % vchBuf.size();
# 746 : 84081 : size_t nNow = nSize;
# 747 [ + + ]: 84081 : if (nNow + pos > vchBuf.size())
# 748 : 74 : nNow = vchBuf.size() - pos;
# 749 [ + + ]: 84081 : if (nNow + nReadPos > nSrcPos)
# 750 : 196 : nNow = nSrcPos - nReadPos;
# 751 : 84081 : memcpy(pch, &vchBuf[pos], nNow);
# 752 : 84081 : nReadPos += nNow;
# 753 : 84081 : pch += nNow;
# 754 : 84081 : nSize -= nNow;
# 755 : 84081 : }
# 756 : 83825 : }
# 757 : :
# 758 : : //! return the current reading position
# 759 : 15343 : uint64_t GetPos() const {
# 760 : 15343 : return nReadPos;
# 761 : 15343 : }
# 762 : :
# 763 : : //! rewind to a given reading position
# 764 : 3104 : bool SetPos(uint64_t nPos) {
# 765 : 3104 : size_t bufsize = vchBuf.size();
# 766 [ + + ]: 3104 : if (nPos + bufsize < nSrcPos) {
# 767 : : // rewinding too far, rewind as far as possible
# 768 : 102 : nReadPos = nSrcPos - bufsize;
# 769 : 102 : return false;
# 770 : 102 : }
# 771 [ + + ]: 3002 : if (nPos > nSrcPos) {
# 772 : : // can't go this far forward, go as far as possible
# 773 : 36 : nReadPos = nSrcPos;
# 774 : 36 : return false;
# 775 : 36 : }
# 776 : 2966 : nReadPos = nPos;
# 777 : 2966 : return true;
# 778 : 2966 : }
# 779 : :
# 780 : : //! prevent reading beyond a certain position
# 781 : : //! no argument removes the limit
# 782 : 9347 : bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
# 783 [ - + ]: 9347 : if (nPos < nReadPos)
# 784 : 0 : return false;
# 785 : 9347 : nReadLimit = nPos;
# 786 : 9347 : return true;
# 787 : 9347 : }
# 788 : :
# 789 : : template<typename T>
# 790 : 25151 : CBufferedFile& operator>>(T&& obj) {
# 791 : : // Unserialize from this stream
# 792 : 25151 : ::Unserialize(*this, obj);
# 793 : 25151 : return (*this);
# 794 : 25151 : }
# 795 : :
# 796 : : //! search for a given byte in the stream, and remain positioned on it
# 797 : 3200 : void FindByte(char ch) {
# 798 : 150260609 : while (true) {
# 799 [ + + ]: 150260600 : if (nReadPos == nSrcPos)
# 800 : 269 : Fill();
# 801 [ + + ]: 150260600 : if (vchBuf[nReadPos % vchBuf.size()] == ch)
# 802 : 3191 : break;
# 803 : 150257409 : nReadPos++;
# 804 : 150257409 : }
# 805 : 3200 : }
# 806 : : };
# 807 : :
# 808 : : #endif // BITCOIN_STREAMS_H
|