Dash Core  0.12.2.1
P2P Digital Currency
streams.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 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 
10 #include "serialize.h"
11 
12 #include <algorithm>
13 #include <assert.h>
14 #include <ios>
15 #include <limits>
16 #include <map>
17 #include <set>
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <string>
21 #include <string.h>
22 #include <utility>
23 #include <vector>
24 
31 {
32 protected:
35  unsigned int nReadPos;
36 public:
37  int nType;
38  int nVersion;
39 
40  typedef vector_type::allocator_type allocator_type;
41  typedef vector_type::size_type size_type;
42  typedef vector_type::difference_type difference_type;
43  typedef vector_type::reference reference;
44  typedef vector_type::const_reference const_reference;
45  typedef vector_type::value_type value_type;
46  typedef vector_type::iterator iterator;
47  typedef vector_type::const_iterator const_iterator;
48  typedef vector_type::reverse_iterator reverse_iterator;
49 
50  explicit CDataStream(int nTypeIn, int nVersionIn)
51  {
52  Init(nTypeIn, nVersionIn);
53  }
54 
55  CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
56  {
57  Init(nTypeIn, nVersionIn);
58  }
59 
60 #if !defined(_MSC_VER) || _MSC_VER >= 1300
61  CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
62  {
63  Init(nTypeIn, nVersionIn);
64  }
65 #endif
66 
67  CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
68  {
69  Init(nTypeIn, nVersionIn);
70  }
71 
72  CDataStream(const std::vector<char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
73  {
74  Init(nTypeIn, nVersionIn);
75  }
76 
77  CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
78  {
79  Init(nTypeIn, nVersionIn);
80  }
81 
82  template <typename... Args>
83  CDataStream(int nTypeIn, int nVersionIn, Args&&... args)
84  {
85  Init(nTypeIn, nVersionIn);
86  ::SerializeMany(*this, nType, nVersion, std::forward<Args>(args)...);
87  }
88 
89  void Init(int nTypeIn, int nVersionIn)
90  {
91  nReadPos = 0;
92  nType = nTypeIn;
93  nVersion = nVersionIn;
94  }
95 
97  {
98  vch.insert(vch.end(), b.begin(), b.end());
99  return *this;
100  }
101 
102  friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
103  {
104  CDataStream ret = a;
105  ret += b;
106  return (ret);
107  }
108 
109  std::string str() const
110  {
111  return (std::string(begin(), end()));
112  }
113 
114 
115  //
116  // Vector subset
117  //
118  const_iterator begin() const { return vch.begin() + nReadPos; }
119  iterator begin() { return vch.begin() + nReadPos; }
120  const_iterator end() const { return vch.end(); }
121  iterator end() { return vch.end(); }
122  size_type size() const { return vch.size() - nReadPos; }
123  bool empty() const { return vch.size() == nReadPos; }
124  void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); }
125  void reserve(size_type n) { vch.reserve(n + nReadPos); }
126  const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; }
127  reference operator[](size_type pos) { return vch[pos + nReadPos]; }
128  void clear() { vch.clear(); nReadPos = 0; }
129  iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
130  void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
131 
132  void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
133  {
134  assert(last - first >= 0);
135  if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
136  {
137  // special case for inserting at the front when there's room
138  nReadPos -= (last - first);
139  memcpy(&vch[nReadPos], &first[0], last - first);
140  }
141  else
142  vch.insert(it, first, last);
143  }
144 
145 #if !defined(_MSC_VER) || _MSC_VER >= 1300
146  void insert(iterator it, const char* first, const char* last)
147  {
148  assert(last - first >= 0);
149  if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
150  {
151  // special case for inserting at the front when there's room
152  nReadPos -= (last - first);
153  memcpy(&vch[nReadPos], &first[0], last - first);
154  }
155  else
156  vch.insert(it, first, last);
157  }
158 #endif
159 
161  {
162  if (it == vch.begin() + nReadPos)
163  {
164  // special case for erasing from the front
165  if (++nReadPos >= vch.size())
166  {
167  // whenever we reach the end, we take the opportunity to clear the buffer
168  nReadPos = 0;
169  return vch.erase(vch.begin(), vch.end());
170  }
171  return vch.begin() + nReadPos;
172  }
173  else
174  return vch.erase(it);
175  }
176 
178  {
179  if (first == vch.begin() + nReadPos)
180  {
181  // special case for erasing from the front
182  if (last == vch.end())
183  {
184  nReadPos = 0;
185  return vch.erase(vch.begin(), vch.end());
186  }
187  else
188  {
189  nReadPos = (last - vch.begin());
190  return last;
191  }
192  }
193  else
194  return vch.erase(first, last);
195  }
196 
197  inline void Compact()
198  {
199  vch.erase(vch.begin(), vch.begin() + nReadPos);
200  nReadPos = 0;
201  }
202 
204  {
205  // Rewind by n characters if the buffer hasn't been compacted yet
206  if (n > nReadPos)
207  return false;
208  nReadPos -= n;
209  return true;
210  }
211 
212 
213  //
214  // Stream subset
215  //
216  bool eof() const { return size() == 0; }
217  CDataStream* rdbuf() { return this; }
218  int in_avail() { return size(); }
219 
220  void SetType(int n) { nType = n; }
221  int GetType() { return nType; }
222  void SetVersion(int n) { nVersion = n; }
223  int GetVersion() { return nVersion; }
224  void ReadVersion() { *this >> nVersion; }
225  void WriteVersion() { *this << nVersion; }
226 
227  CDataStream& read(char* pch, size_t nSize)
228  {
229  // Read from the beginning of the buffer
230  unsigned int nReadPosNext = nReadPos + nSize;
231  if (nReadPosNext >= vch.size())
232  {
233  if (nReadPosNext > vch.size())
234  {
235  throw std::ios_base::failure("CDataStream::read(): end of data");
236  }
237  memcpy(pch, &vch[nReadPos], nSize);
238  nReadPos = 0;
239  vch.clear();
240  return (*this);
241  }
242  memcpy(pch, &vch[nReadPos], nSize);
243  nReadPos = nReadPosNext;
244  return (*this);
245  }
246 
247  CDataStream& ignore(int nSize)
248  {
249  // Ignore from the beginning of the buffer
250  assert(nSize >= 0);
251  unsigned int nReadPosNext = nReadPos + nSize;
252  if (nReadPosNext >= vch.size())
253  {
254  if (nReadPosNext > vch.size())
255  throw std::ios_base::failure("CDataStream::ignore(): end of data");
256  nReadPos = 0;
257  vch.clear();
258  return (*this);
259  }
260  nReadPos = nReadPosNext;
261  return (*this);
262  }
263 
264  CDataStream& write(const char* pch, size_t nSize)
265  {
266  // Write to the end of the buffer
267  vch.insert(vch.end(), pch, pch + nSize);
268  return (*this);
269  }
270 
271  template<typename Stream>
272  void Serialize(Stream& s, int nType, int nVersion) const
273  {
274  // Special case: stream << stream concatenates like stream += stream
275  if (!vch.empty())
276  s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
277  }
278 
279  template<typename T>
280  unsigned int GetSerializeSize(const T& obj)
281  {
282  // Tells the size of the object if serialized to this stream
284  }
285 
286  template<typename T>
287  CDataStream& operator<<(const T& obj)
288  {
289  // Serialize to this stream
290  ::Serialize(*this, obj, nType, nVersion);
291  return (*this);
292  }
293 
294  template<typename T>
296  {
297  // Unserialize from this stream
298  ::Unserialize(*this, obj, nType, nVersion);
299  return (*this);
300  }
301 
303  data.insert(data.end(), begin(), end());
304  clear();
305  }
306 
312  void Xor(const std::vector<unsigned char>& key)
313  {
314  if (key.size() == 0) {
315  return;
316  }
317 
318  for (size_type i = 0, j = 0; i != size(); i++) {
319  vch[i] ^= key[j++];
320 
321  // This potentially acts on very many bytes of data, so it's
322  // important that we calculate `j`, i.e. the `key` index in this
323  // way instead of doing a %, which would effectively be a division
324  // for each byte Xor'd -- much slower than need be.
325  if (j == key.size())
326  j = 0;
327  }
328  }
329 };
330 
331 
332 
333 
334 
335 
336 
337 
338 
339 
347 {
348 private:
349  // Disallow copies
350  CAutoFile(const CAutoFile&);
351  CAutoFile& operator=(const CAutoFile&);
352 
353  int nType;
354  int nVersion;
355 
356  FILE* file;
357 
358 public:
359  CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn)
360  {
361  file = filenew;
362  nType = nTypeIn;
363  nVersion = nVersionIn;
364  }
365 
367  {
368  fclose();
369  }
370 
371  void fclose()
372  {
373  if (file) {
374  ::fclose(file);
375  file = NULL;
376  }
377  }
378 
383  FILE* release() { FILE* ret = file; file = NULL; return ret; }
384 
389  FILE* Get() const { return file; }
390 
393  bool IsNull() const { return (file == NULL); }
394 
395  //
396  // Stream subset
397  //
398  void SetType(int n) { nType = n; }
399  int GetType() { return nType; }
400  void SetVersion(int n) { nVersion = n; }
401  int GetVersion() { return nVersion; }
402  void ReadVersion() { *this >> nVersion; }
403  void WriteVersion() { *this << nVersion; }
404 
405  CAutoFile& read(char* pch, size_t nSize)
406  {
407  if (!file)
408  throw std::ios_base::failure("CAutoFile::read: file handle is NULL");
409  if (fread(pch, 1, nSize, file) != nSize)
410  throw std::ios_base::failure(feof(file) ? "CAutoFile::read: end of file" : "CAutoFile::read: fread failed");
411  return (*this);
412  }
413 
414  CAutoFile& write(const char* pch, size_t nSize)
415  {
416  if (!file)
417  throw std::ios_base::failure("CAutoFile::write: file handle is NULL");
418  if (fwrite(pch, 1, nSize, file) != nSize)
419  throw std::ios_base::failure("CAutoFile::write: write failed");
420  return (*this);
421  }
422 
423  template<typename T>
424  unsigned int GetSerializeSize(const T& obj)
425  {
426  // Tells the size of the object if serialized to this stream
428  }
429 
430  template<typename T>
431  CAutoFile& operator<<(const T& obj)
432  {
433  // Serialize to this stream
434  if (!file)
435  throw std::ios_base::failure("CAutoFile::operator<<: file handle is NULL");
436  ::Serialize(*this, obj, nType, nVersion);
437  return (*this);
438  }
439 
440  template<typename T>
442  {
443  // Unserialize from this stream
444  if (!file)
445  throw std::ios_base::failure("CAutoFile::operator>>: file handle is NULL");
446  ::Unserialize(*this, obj, nType, nVersion);
447  return (*this);
448  }
449 };
450 
458 {
459 private:
460  // Disallow copies
463 
464  int nType;
465  int nVersion;
466 
467  FILE *src; // source file
468  uint64_t nSrcPos; // how many bytes have been read from source
469  uint64_t nReadPos; // how many bytes have been read from this
470  uint64_t nReadLimit; // up to which position we're allowed to read
471  uint64_t nRewind; // how many bytes we guarantee to rewind
472  std::vector<char> vchBuf; // the buffer
473 
474 protected:
475  // read data from the source to fill the buffer
476  bool Fill() {
477  unsigned int pos = nSrcPos % vchBuf.size();
478  unsigned int readNow = vchBuf.size() - pos;
479  unsigned int nAvail = vchBuf.size() - (nSrcPos - nReadPos) - nRewind;
480  if (nAvail < readNow)
481  readNow = nAvail;
482  if (readNow == 0)
483  return false;
484  size_t read = fread((void*)&vchBuf[pos], 1, readNow, src);
485  if (read == 0) {
486  throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed");
487  } else {
488  nSrcPos += read;
489  return true;
490  }
491  }
492 
493 public:
494  CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
495  nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
496  {
497  src = fileIn;
498  nType = nTypeIn;
499  nVersion = nVersionIn;
500  }
501 
503  {
504  fclose();
505  }
506 
507  void fclose()
508  {
509  if (src) {
510  ::fclose(src);
511  src = NULL;
512  }
513  }
514 
515  // check whether we're at the end of the source file
516  bool eof() const {
517  return nReadPos == nSrcPos && feof(src);
518  }
519 
520  // read a number of bytes
521  CBufferedFile& read(char *pch, size_t nSize) {
522  if (nSize + nReadPos > nReadLimit)
523  throw std::ios_base::failure("Read attempted past buffer limit");
524  if (nSize + nRewind > vchBuf.size())
525  throw std::ios_base::failure("Read larger than buffer size");
526  while (nSize > 0) {
527  if (nReadPos == nSrcPos)
528  Fill();
529  unsigned int pos = nReadPos % vchBuf.size();
530  size_t nNow = nSize;
531  if (nNow + pos > vchBuf.size())
532  nNow = vchBuf.size() - pos;
533  if (nNow + nReadPos > nSrcPos)
534  nNow = nSrcPos - nReadPos;
535  memcpy(pch, &vchBuf[pos], nNow);
536  nReadPos += nNow;
537  pch += nNow;
538  nSize -= nNow;
539  }
540  return (*this);
541  }
542 
543  // return the current reading position
544  uint64_t GetPos() {
545  return nReadPos;
546  }
547 
548  // rewind to a given reading position
549  bool SetPos(uint64_t nPos) {
550  nReadPos = nPos;
551  if (nReadPos + nRewind < nSrcPos) {
553  return false;
554  } else if (nReadPos > nSrcPos) {
555  nReadPos = nSrcPos;
556  return false;
557  } else {
558  return true;
559  }
560  }
561 
562  bool Seek(uint64_t nPos) {
563  long nLongPos = nPos;
564  if (nPos != (uint64_t)nLongPos)
565  return false;
566  if (fseek(src, nLongPos, SEEK_SET))
567  return false;
568  nLongPos = ftell(src);
569  nSrcPos = nLongPos;
570  nReadPos = nLongPos;
571  return true;
572  }
573 
574  // prevent reading beyond a certain position
575  // no argument removes the limit
576  bool SetLimit(uint64_t nPos = (uint64_t)(-1)) {
577  if (nPos < nReadPos)
578  return false;
579  nReadLimit = nPos;
580  return true;
581  }
582 
583  template<typename T>
585  // Unserialize from this stream
586  ::Unserialize(*this, obj, nType, nVersion);
587  return (*this);
588  }
589 
590  // search for a given byte in the stream, and remain positioned on it
591  void FindByte(char ch) {
592  while (true) {
593  if (nReadPos == nSrcPos)
594  Fill();
595  if (vchBuf[nReadPos % vchBuf.size()] == ch)
596  break;
597  nReadPos++;
598  }
599  }
600 };
601 
602 #endif // BITCOIN_STREAMS_H
reference operator[](size_type pos)
Definition: streams.h:127
void SetVersion(int n)
Definition: streams.h:222
CDataStream & operator+=(const CDataStream &b)
Definition: streams.h:96
FILE * release()
Definition: streams.h:383
void insert(iterator it, size_type n, const char &x)
Definition: streams.h:130
int nType
Definition: streams.h:353
void Compact()
Definition: streams.h:197
void ReadVersion()
Definition: streams.h:224
CBufferedFile(const CBufferedFile &)
bool empty() const
Definition: streams.h:123
uint64_t nReadPos
Definition: streams.h:469
bool Fill()
Definition: streams.h:476
vector_type::const_iterator const_iterator
Definition: streams.h:47
void Serialize(Stream &s, char a, int, int=0)
Definition: serialize.h:214
uint64_t nReadLimit
Definition: streams.h:470
vector_type::size_type size_type
Definition: streams.h:41
void Serialize(Stream &s, int nType, int nVersion) const
Definition: streams.h:272
CAutoFile & operator<<(const T &obj)
Definition: streams.h:431
CAutoFile & operator>>(T &obj)
Definition: streams.h:441
vector_type::value_type value_type
Definition: streams.h:45
iterator erase(iterator it)
Definition: streams.h:160
const_iterator end() const
Definition: streams.h:120
void Xor(const std::vector< unsigned char > &key)
Definition: streams.h:312
int in_avail()
Definition: streams.h:218
int nVersion
Definition: streams.h:354
CDataStream(const vector_type &vchIn, int nTypeIn, int nVersionIn)
Definition: streams.h:67
vector_type::reference reference
Definition: streams.h:43
int GetVersion()
Definition: streams.h:401
CDataStream & operator<<(const T &obj)
Definition: streams.h:287
unsigned int nReadPos
Definition: streams.h:35
CDataStream & ignore(int nSize)
Definition: streams.h:247
bool IsNull() const
Definition: streams.h:393
void resize(size_type n, value_type c=0)
Definition: streams.h:124
CDataStream & write(const char *pch, size_t nSize)
Definition: streams.h:264
int GetVersion()
Definition: streams.h:223
CDataStream(int nTypeIn, int nVersionIn)
Definition: streams.h:50
unsigned int GetSerializeSize(const T &obj)
Definition: streams.h:280
int GetType()
Definition: streams.h:399
void SerializeMany(Stream &s, int nType, int nVersion)
Definition: serialize.h:988
void reserve(size_type n)
Definition: streams.h:125
void insert(iterator it, const char *first, const char *last)
Definition: streams.h:146
CAutoFile(const CAutoFile &)
CDataStream & read(char *pch, size_t nSize)
Definition: streams.h:227
vector_type::allocator_type allocator_type
Definition: streams.h:40
void Init(int nTypeIn, int nVersionIn)
Definition: streams.h:89
void SetVersion(int n)
Definition: streams.h:400
int GetType()
Definition: streams.h:221
CDataStream(const std::vector< unsigned char > &vchIn, int nTypeIn, int nVersionIn)
Definition: streams.h:77
int nType
Definition: streams.h:37
int nVersion
Definition: streams.h:38
unsigned int GetSerializeSize(char a, int, int=0)
Definition: serialize.h:202
friend CDataStream operator+(const CDataStream &a, const CDataStream &b)
Definition: streams.h:102
vector_type::const_reference const_reference
Definition: streams.h:44
iterator begin()
Definition: streams.h:119
uint64_t nRewind
Definition: streams.h:471
void clear()
Definition: streams.h:128
const_iterator begin() const
Definition: streams.h:118
void insert(iterator it, std::vector< char >::const_iterator first, std::vector< char >::const_iterator last)
Definition: streams.h:132
CAutoFile & write(const char *pch, size_t nSize)
Definition: streams.h:414
CDataStream(const std::vector< char > &vchIn, int nTypeIn, int nVersionIn)
Definition: streams.h:72
void Unserialize(Stream &s, char &a, int, int=0)
Definition: serialize.h:226
void fclose()
Definition: streams.h:507
CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn)
Definition: streams.h:494
void GetAndClear(CSerializeData &data)
Definition: streams.h:302
CDataStream(const char *pbegin, const char *pend, int nTypeIn, int nVersionIn)
Definition: streams.h:61
bool Rewind(size_type n)
Definition: streams.h:203
CDataStream & operator>>(T &obj)
Definition: streams.h:295
bool eof() const
Definition: streams.h:516
void fclose()
Definition: streams.h:371
vector_type vch
Definition: streams.h:34
void ReadVersion()
Definition: streams.h:402
void FindByte(char ch)
Definition: streams.h:591
FILE * Get() const
Definition: streams.h:389
~CAutoFile()
Definition: streams.h:366
unsigned int GetSerializeSize(const T &obj)
Definition: streams.h:424
vector_type::difference_type difference_type
Definition: streams.h:42
vector_type::reverse_iterator reverse_iterator
Definition: streams.h:48
void WriteVersion()
Definition: streams.h:225
CAutoFile & read(char *pch, size_t nSize)
Definition: streams.h:405
void * memcpy(void *a, const void *b, size_t c)
uint64_t GetPos()
Definition: streams.h:544
int nVersion
Definition: streams.h:465
CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn)
Definition: streams.h:55
FILE * file
Definition: streams.h:356
void WriteVersion()
Definition: streams.h:403
CAutoFile(FILE *filenew, int nTypeIn, int nVersionIn)
Definition: streams.h:359
iterator insert(iterator it, const char &x=char())
Definition: streams.h:129
std::vector< char > vchBuf
Definition: streams.h:472
uint64_t nSrcPos
Definition: streams.h:468
bool eof() const
Definition: streams.h:216
void SetType(int n)
Definition: streams.h:220
CBufferedFile & read(char *pch, size_t nSize)
Definition: streams.h:521
CBufferedFile & operator=(const CBufferedFile &)
~CBufferedFile()
Definition: streams.h:502
std::string str() const
Definition: streams.h:109
std::vector< char, zero_after_free_allocator< char > > CSerializeData
Definition: zeroafterfree.h:46
FILE * src
Definition: streams.h:467
bool SetLimit(uint64_t nPos=(uint64_t)(-1))
Definition: streams.h:576
void SetType(int n)
Definition: streams.h:398
CBufferedFile & operator>>(T &obj)
Definition: streams.h:584
size_type size() const
Definition: streams.h:122
CDataStream * rdbuf()
Definition: streams.h:217
bool Seek(uint64_t nPos)
Definition: streams.h:562
CAutoFile & operator=(const CAutoFile &)
vector_type::iterator iterator
Definition: streams.h:46
iterator erase(iterator first, iterator last)
Definition: streams.h:177
CDataStream(int nTypeIn, int nVersionIn, Args &&... args)
Definition: streams.h:83
CSerializeData vector_type
Definition: streams.h:33
iterator end()
Definition: streams.h:121
bool SetPos(uint64_t nPos)
Definition: streams.h:549
const_reference operator[](size_type pos) const
Definition: streams.h:126