Back to home page

Bitcoin sources

 
 

    


File indexing completed on 2020-06-26 05:01:26

0001 // Copyright (c) 2009-2010 Satoshi Nakamoto
0002 // Copyright (c) 2009-2013 The Bitcoin developers
0003 // Distributed under the MIT/X11 software license, see the accompanying
0004 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
0005 
0006 #ifndef BITCOIN_STREAMS_H
0007 #define BITCOIN_STREAMS_H
0008 
0009 #include "allocators.h"
0010 #include "serialize.h"
0011 
0012 #include <algorithm>
0013 #include <assert.h>
0014 #include <ios>
0015 #include <limits>
0016 #include <map>
0017 #include <set>
0018 #include <stdint.h>
0019 #include <string>
0020 #include <string.h>
0021 #include <utility>
0022 #include <vector>
0023 
0024 /** Double ended buffer combining vector and stream-like interfaces.
0025  *
0026  * >> and << read and write unformatted data using the above serialization templates.
0027  * Fills with data in linear time; some stringstream implementations take N^2 time.
0028  */
0029 class CDataStream
0030 {
0031 protected:
0032     typedef CSerializeData vector_type;
0033     vector_type vch;
0034     unsigned int nReadPos;
0035 public:
0036     int nType;
0037     int nVersion;
0038 
0039     typedef vector_type::allocator_type   allocator_type;
0040     typedef vector_type::size_type        size_type;
0041     typedef vector_type::difference_type  difference_type;
0042     typedef vector_type::reference        reference;
0043     typedef vector_type::const_reference  const_reference;
0044     typedef vector_type::value_type       value_type;
0045     typedef vector_type::iterator         iterator;
0046     typedef vector_type::const_iterator   const_iterator;
0047     typedef vector_type::reverse_iterator reverse_iterator;
0048 
0049     explicit CDataStream(int nTypeIn, int nVersionIn)
0050     {
0051         Init(nTypeIn, nVersionIn);
0052     }
0053 
0054     CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
0055     {
0056         Init(nTypeIn, nVersionIn);
0057     }
0058 
0059 #if !defined(_MSC_VER) || _MSC_VER >= 1300
0060     CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
0061     {
0062         Init(nTypeIn, nVersionIn);
0063     }
0064 #endif
0065 
0066     CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
0067     {
0068         Init(nTypeIn, nVersionIn);
0069     }
0070 
0071     CDataStream(const std::vector<char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
0072     {
0073         Init(nTypeIn, nVersionIn);
0074     }
0075 
0076     CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
0077     {
0078         Init(nTypeIn, nVersionIn);
0079     }
0080 
0081     void Init(int nTypeIn, int nVersionIn)
0082     {
0083         nReadPos = 0;
0084         nType = nTypeIn;
0085         nVersion = nVersionIn;
0086     }
0087 
0088     CDataStream& operator+=(const CDataStream& b)
0089     {
0090         vch.insert(vch.end(), b.begin(), b.end());
0091         return *this;
0092     }
0093 
0094     friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
0095     {
0096         CDataStream ret = a;
0097         ret += b;
0098         return (ret);
0099     }
0100 
0101     std::string str() const
0102     {
0103         return (std::string(begin(), end()));
0104     }
0105 
0106 
0107     //
0108     // Vector subset
0109     //
0110     const_iterator begin() const                     { return vch.begin() + nReadPos; }
0111     iterator begin()                                 { return vch.begin() + nReadPos; }
0112     const_iterator end() const                       { return vch.end(); }
0113     iterator end()                                   { return vch.end(); }
0114     size_type size() const                           { return vch.size() - nReadPos; }
0115     bool empty() const                               { return vch.size() == nReadPos; }
0116     void resize(size_type n, value_type c=0)         { vch.resize(n + nReadPos, c); }
0117     void reserve(size_type n)                        { vch.reserve(n + nReadPos); }
0118     const_reference operator[](size_type pos) const  { return vch[pos + nReadPos]; }
0119     reference operator[](size_type pos)              { return vch[pos + nReadPos]; }
0120     void clear()                                     { vch.clear(); nReadPos = 0; }
0121     iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
0122     void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
0123 
0124     void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
0125     {
0126         assert(last - first >= 0);
0127         if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
0128         {
0129             // special case for inserting at the front when there's room
0130             nReadPos -= (last - first);
0131             memcpy(&vch[nReadPos], &first[0], last - first);
0132         }
0133         else
0134             vch.insert(it, first, last);
0135     }
0136 
0137 #if !defined(_MSC_VER) || _MSC_VER >= 1300
0138     void insert(iterator it, const char* first, const char* last)
0139     {
0140         assert(last - first >= 0);
0141         if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
0142         {
0143             // special case for inserting at the front when there's room
0144             nReadPos -= (last - first);
0145             memcpy(&vch[nReadPos], &first[0], last - first);
0146         }
0147         else
0148             vch.insert(it, first, last);
0149     }
0150 #endif
0151 
0152     iterator erase(iterator it)
0153     {
0154         if (it == vch.begin() + nReadPos)
0155         {
0156             // special case for erasing from the front
0157             if (++nReadPos >= vch.size())
0158             {
0159                 // whenever we reach the end, we take the opportunity to clear the buffer
0160                 nReadPos = 0;
0161                 return vch.erase(vch.begin(), vch.end());
0162             }
0163             return vch.begin() + nReadPos;
0164         }
0165         else
0166             return vch.erase(it);
0167     }
0168 
0169     iterator erase(iterator first, iterator last)
0170     {
0171         if (first == vch.begin() + nReadPos)
0172         {
0173             // special case for erasing from the front
0174             if (last == vch.end())
0175             {
0176                 nReadPos = 0;
0177                 return vch.erase(vch.begin(), vch.end());
0178             }
0179             else
0180             {
0181                 nReadPos = (last - vch.begin());
0182                 return last;
0183             }
0184         }
0185         else
0186             return vch.erase(first, last);
0187     }
0188 
0189     inline void Compact()
0190     {
0191         vch.erase(vch.begin(), vch.begin() + nReadPos);
0192         nReadPos = 0;
0193     }
0194 
0195     bool Rewind(size_type n)
0196     {
0197         // Rewind by n characters if the buffer hasn't been compacted yet
0198         if (n > nReadPos)
0199             return false;
0200         nReadPos -= n;
0201         return true;
0202     }
0203 
0204 
0205     //
0206     // Stream subset
0207     //
0208     bool eof() const             { return size() == 0; }
0209     CDataStream* rdbuf()         { return this; }
0210     int in_avail()               { return size(); }
0211 
0212     void SetType(int n)          { nType = n; }
0213     int GetType()                { return nType; }
0214     void SetVersion(int n)       { nVersion = n; }
0215     int GetVersion()             { return nVersion; }
0216     void ReadVersion()           { *this >> nVersion; }
0217     void WriteVersion()          { *this << nVersion; }
0218 
0219     CDataStream& read(char* pch, size_t nSize)
0220     {
0221         // Read from the beginning of the buffer
0222         unsigned int nReadPosNext = nReadPos + nSize;
0223         if (nReadPosNext >= vch.size())
0224         {
0225             if (nReadPosNext > vch.size())
0226             {
0227                 throw std::ios_base::failure("CDataStream::read() : end of data");
0228             }
0229             memcpy(pch, &vch[nReadPos], nSize);
0230             nReadPos = 0;
0231             vch.clear();
0232             return (*this);
0233         }
0234         memcpy(pch, &vch[nReadPos], nSize);
0235         nReadPos = nReadPosNext;
0236         return (*this);
0237     }
0238 
0239     CDataStream& ignore(int nSize)
0240     {
0241         // Ignore from the beginning of the buffer
0242         assert(nSize >= 0);
0243         unsigned int nReadPosNext = nReadPos + nSize;
0244         if (nReadPosNext >= vch.size())
0245         {
0246             if (nReadPosNext > vch.size())
0247                 throw std::ios_base::failure("CDataStream::ignore() : end of data");
0248             nReadPos = 0;
0249             vch.clear();
0250             return (*this);
0251         }
0252         nReadPos = nReadPosNext;
0253         return (*this);
0254     }
0255 
0256     CDataStream& write(const char* pch, size_t nSize)
0257     {
0258         // Write to the end of the buffer
0259         vch.insert(vch.end(), pch, pch + nSize);
0260         return (*this);
0261     }
0262 
0263     template<typename Stream>
0264     void Serialize(Stream& s, int nType, int nVersion) const
0265     {
0266         // Special case: stream << stream concatenates like stream += stream
0267         if (!vch.empty())
0268             s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
0269     }
0270 
0271     template<typename T>
0272     unsigned int GetSerializeSize(const T& obj)
0273     {
0274         // Tells the size of the object if serialized to this stream
0275         return ::GetSerializeSize(obj, nType, nVersion);
0276     }
0277 
0278     template<typename T>
0279     CDataStream& operator<<(const T& obj)
0280     {
0281         // Serialize to this stream
0282         ::Serialize(*this, obj, nType, nVersion);
0283         return (*this);
0284     }
0285 
0286     template<typename T>
0287     CDataStream& operator>>(T& obj)
0288     {
0289         // Unserialize from this stream
0290         ::Unserialize(*this, obj, nType, nVersion);
0291         return (*this);
0292     }
0293 
0294     void GetAndClear(CSerializeData &data) {
0295         data.insert(data.end(), begin(), end());
0296         clear();
0297     }
0298 };
0299 
0300 
0301 
0302 
0303 
0304 
0305 
0306 
0307 
0308 
0309 /** Non-refcounted RAII wrapper for FILE*
0310  *
0311  * Will automatically close the file when it goes out of scope if not null.
0312  * If you're returning the file pointer, return file.release().
0313  * If you need to close the file early, use file.fclose() instead of fclose(file).
0314  */
0315 class CAutoFile
0316 {
0317 private:
0318     // Disallow copies
0319     CAutoFile(const CAutoFile&);
0320     CAutoFile& operator=(const CAutoFile&);
0321 
0322     int nType;
0323     int nVersion;
0324     
0325     FILE* file; 
0326 
0327 public:
0328     CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn)
0329     {
0330         file = filenew;
0331         nType = nTypeIn;
0332         nVersion = nVersionIn;
0333     }
0334 
0335     ~CAutoFile()
0336     {
0337         fclose();
0338     }
0339 
0340     void fclose()
0341     {
0342         if (file) {
0343             ::fclose(file);
0344             file = NULL;
0345         }
0346     }
0347 
0348     /** Get wrapped FILE* with transfer of ownership.
0349      * @note This will invalidate the CAutoFile object, and makes it the responsibility of the caller
0350      * of this function to clean up the returned FILE*.
0351      */
0352     FILE* release()             { FILE* ret = file; file = NULL; return ret; }
0353 
0354     /** Get wrapped FILE* without transfer of ownership.
0355      * @note Ownership of the FILE* will remain with this class. Use this only if the scope of the
0356      * CAutoFile outlives use of the passed pointer.
0357      */
0358     FILE* Get() const           { return file; }
0359 
0360     /** Return true if the wrapped FILE* is NULL, false otherwise.
0361      */
0362     bool IsNull() const         { return (file == NULL); }
0363 
0364     //
0365     // Stream subset
0366     //
0367     void SetType(int n)          { nType = n; }
0368     int GetType()                { return nType; }
0369     void SetVersion(int n)       { nVersion = n; }
0370     int GetVersion()             { return nVersion; }
0371     void ReadVersion()           { *this >> nVersion; }
0372     void WriteVersion()          { *this << nVersion; }
0373 
0374     CAutoFile& read(char* pch, size_t nSize)
0375     {
0376         if (!file)
0377             throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
0378         if (fread(pch, 1, nSize, file) != nSize)
0379             throw std::ios_base::failure(feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
0380         return (*this);
0381     }
0382 
0383     CAutoFile& write(const char* pch, size_t nSize)
0384     {
0385         if (!file)
0386             throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
0387         if (fwrite(pch, 1, nSize, file) != nSize)
0388             throw std::ios_base::failure("CAutoFile::write : write failed");
0389         return (*this);
0390     }
0391 
0392     template<typename T>
0393     unsigned int GetSerializeSize(const T& obj)
0394     {
0395         // Tells the size of the object if serialized to this stream
0396         return ::GetSerializeSize(obj, nType, nVersion);
0397     }
0398 
0399     template<typename T>
0400     CAutoFile& operator<<(const T& obj)
0401     {
0402         // Serialize to this stream
0403         if (!file)
0404             throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
0405         ::Serialize(*this, obj, nType, nVersion);
0406         return (*this);
0407     }
0408 
0409     template<typename T>
0410     CAutoFile& operator>>(T& obj)
0411     {
0412         // Unserialize from this stream
0413         if (!file)
0414             throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL");
0415         ::Unserialize(*this, obj, nType, nVersion);
0416         return (*this);
0417     }
0418 };
0419 
0420 /** Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to
0421  *  deserialize from. It guarantees the ability to rewind a given number of bytes.
0422  *
0423  *  Will automatically close the file when it goes out of scope if not null.
0424  *  If you need to close the file early, use file.fclose() instead of fclose(file).
0425  */
0426 class CBufferedFile
0427 {
0428 private:
0429     // Disallow copies
0430     CBufferedFile(const CBufferedFile&);
0431     CBufferedFile& operator=(const CBufferedFile&);
0432 
0433     int nType;
0434     int nVersion;
0435 
0436     FILE *src;            // source file
0437     uint64_t nSrcPos;     // how many bytes have been read from source
0438     uint64_t nReadPos;    // how many bytes have been read from this
0439     uint64_t nReadLimit;  // up to which position we're allowed to read
0440     uint64_t nRewind;     // how many bytes we guarantee to rewind
0441     std::vector<char> vchBuf; // the buffer
0442 
0443 protected:
0444     // read data from the source to fill the buffer
0445     bool Fill() {
0446         unsigned int pos = nSrcPos % vchBuf.size();
0447         unsigned int readNow = vchBuf.size() - pos;
0448         unsigned int nAvail = vchBuf.size() - (nSrcPos - nReadPos) - nRewind;
0449         if (nAvail < readNow)
0450             readNow = nAvail;
0451         if (readNow == 0)
0452             return false;
0453         size_t read = fread((void*)&vchBuf[pos], 1, readNow, src);
0454         if (read == 0) {
0455             throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed");
0456         } else {
0457             nSrcPos += read;
0458             return true;
0459         }
0460     }
0461 
0462 public:
0463     CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
0464         nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
0465     {
0466         src = fileIn;
0467         nType = nTypeIn;
0468         nVersion = nVersionIn;
0469     }
0470 
0471     ~CBufferedFile()
0472     {
0473         fclose();
0474     }
0475 
0476     void fclose()
0477     {
0478         if (src) {
0479             ::fclose(src);
0480             src = NULL;
0481         }
0482     }
0483 
0484     // check whether we're at the end of the source file
0485     bool eof() const {
0486         return nReadPos == nSrcPos && feof(src);
0487     }
0488 
0489     // read a number of bytes
0490     CBufferedFile& read(char *pch, size_t nSize) {
0491         if (nSize + nReadPos > nReadLimit)
0492             throw std::ios_base::failure("Read attempted past buffer limit");
0493         if (nSize + nRewind > vchBuf.size())
0494             throw std::ios_base::failure("Read larger than buffer size");
0495         while (nSize > 0) {
0496             if (nReadPos == nSrcPos)
0497                 Fill();
0498             unsigned int pos = nReadPos % vchBuf.size();
0499             size_t nNow = nSize;
0500             if (nNow + pos > vchBuf.size())
0501                 nNow = vchBuf.size() - pos;
0502             if (nNow + nReadPos > nSrcPos)
0503                 nNow = nSrcPos - nReadPos;
0504             memcpy(pch, &vchBuf[pos], nNow);
0505             nReadPos += nNow;
0506             pch += nNow;
0507             nSize -= nNow;
0508         }
0509         return (*this);
0510     }
0511 
0512     // return the current reading position
0513     uint64_t GetPos() {
0514         return nReadPos;
0515     }
0516 
0517     // rewind to a given reading position
0518     bool SetPos(uint64_t nPos) {
0519         nReadPos = nPos;
0520         if (nReadPos + nRewind < nSrcPos) {
0521             nReadPos = nSrcPos - nRewind;
0522             return false;
0523         } else if (nReadPos > nSrcPos) {
0524             nReadPos = nSrcPos;
0525             return false;
0526         } else {
0527             return true;
0528         }
0529     }
0530 
0531     bool Seek(uint64_t nPos) {
0532         long nLongPos = nPos;
0533         if (nPos != (uint64_t)nLongPos)
0534             return false;
0535         if (fseek(src, nLongPos, SEEK_SET))
0536             return false;
0537         nLongPos = ftell(src);
0538         nSrcPos = nLongPos;
0539         nReadPos = nLongPos;
0540         return true;
0541     }
0542 
0543     // prevent reading beyond a certain position
0544     // no argument removes the limit
0545     bool SetLimit(uint64_t nPos = (uint64_t)(-1)) {
0546         if (nPos < nReadPos)
0547             return false;
0548         nReadLimit = nPos;
0549         return true;
0550     }
0551 
0552     template<typename T>
0553     CBufferedFile& operator>>(T& obj) {
0554         // Unserialize from this stream
0555         ::Unserialize(*this, obj, nType, nVersion);
0556         return (*this);
0557     }
0558 
0559     // search for a given byte in the stream, and remain positioned on it
0560     void FindByte(char ch) {
0561         while (true) {
0562             if (nReadPos == nSrcPos)
0563                 Fill();
0564             if (vchBuf[nReadPos % vchBuf.size()] == ch)
0565                 break;
0566             nReadPos++;
0567         }
0568     }
0569 };
0570 
0571 #endif // BITCOIN_STREAMS_H