LCOV - code coverage report
Current view: top level - src - streams.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 338 440 76.8 %
Date: 2020-10-06 11:46:21 Functions: 419 459 91.3 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 0 0 -

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

Generated by: LCOV version 1.14