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