Update CMakeLists.txt - play with openssl
[novacoin.git] / src / streams.cpp
1 #include "streams.h"
2
3 CDataStream::CDataStream(int nTypeIn, int nVersionIn)
4 {
5     Init(nTypeIn, nVersionIn);
6 }
7
8 CDataStream::CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
9 {
10     Init(nTypeIn, nVersionIn);
11 }
12
13 CDataStream::CDataStream(const char *pbegin, const char *pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
14 {
15     Init(nTypeIn, nVersionIn);
16 }
17
18 CDataStream::CDataStream(const vector_type &vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
19 {
20     Init(nTypeIn, nVersionIn);
21 }
22
23 CDataStream::CDataStream(const std::vector<char> &vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
24 {
25     Init(nTypeIn, nVersionIn);
26 }
27
28 CDataStream::CDataStream(const std::vector<unsigned char> &vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
29 {
30     Init(nTypeIn, nVersionIn);
31 }
32
33 void CDataStream::Init(int nTypeIn, int nVersionIn)
34 {
35     nReadPos = 0;
36     nType = nTypeIn;
37     nVersion = nVersionIn;
38     state = 0;
39     exceptmask = std::ios::badbit | std::ios::failbit;
40 }
41
42 CDataStream &CDataStream::operator+=(const CDataStream &b)
43 {
44     vch.insert(vch.end(), b.begin(), b.end());
45     return *this;
46 }
47
48 std::string CDataStream::str() const
49 {
50     return std::string(begin(), end());
51 }
52
53 bool CDataStream::Rewind(size_type n)
54 {
55     // Rewind by n characters if the buffer hasn't been compacted yet
56     if (n > nReadPos)
57         return false;
58     nReadPos -= (unsigned int)n;
59     return true;
60 }
61
62 void CDataStream::setstate(short bits, const char *psz)
63 {
64     state |= bits;
65     if (state & exceptmask)
66         throw std::ios_base::failure(psz);
67 }
68
69 CDataStream &CDataStream::read(char *pch, int nSize)
70 {
71     // Read from the beginning of the buffer
72     assert(nSize >= 0);
73     unsigned int nReadPosNext = nReadPos + nSize;
74     if (nReadPosNext >= vch.size())
75     {
76         if (nReadPosNext > vch.size())
77         {
78             setstate(std::ios::failbit, "CDataStream::read() : end of data");
79             memset(pch, 0, nSize);
80             nSize = (int)(vch.size() - nReadPos);
81         }
82         memcpy(pch, &vch[nReadPos], nSize);
83         nReadPos = 0;
84         vch.clear();
85         return (*this);
86     }
87     memcpy(pch, &vch[nReadPos], nSize);
88     nReadPos = nReadPosNext;
89     return (*this);
90 }
91
92 CDataStream &CDataStream::ignore(int nSize)
93 {
94     // Ignore from the beginning of the buffer
95     assert(nSize >= 0);
96     unsigned int nReadPosNext = nReadPos + nSize;
97     if (nReadPosNext >= vch.size())
98     {
99         if (nReadPosNext > vch.size())
100             setstate(std::ios::failbit, "CDataStream::ignore() : end of data");
101         nReadPos = 0;
102         vch.clear();
103         return (*this);
104     }
105     nReadPos = nReadPosNext;
106     return (*this);
107 }
108
109 CDataStream &CDataStream::write(const char *pch, int nSize)
110 {
111     // Write to the end of the buffer
112     assert(nSize >= 0);
113     vch.insert(vch.end(), pch, pch + nSize);
114     return (*this);
115 }
116
117 void CDataStream::GetAndClear(CSerializeData &data) {
118     vch.swap(data);
119     CSerializeData().swap(vch);
120 }
121
122 CAutoFile::CAutoFile(FILE *filenew, int nTypeIn, int nVersionIn)
123 {
124     file = filenew;
125     nType = nTypeIn;
126     nVersion = nVersionIn;
127     state = 0;
128     exceptmask = std::ios::badbit | std::ios::failbit;
129 }
130
131 CAutoFile::~CAutoFile()
132 {
133     fclose();
134 }
135
136 void CAutoFile::fclose()
137 {
138     if (file != NULL && file != stdin && file != stdout && file != stderr)
139         ::fclose(file);
140     file = NULL;
141 }
142
143 void CAutoFile::setstate(short bits, const char *psz)
144 {
145     state |= bits;
146     if (state & exceptmask)
147         throw std::ios_base::failure(psz);
148 }
149
150 CAutoFile &CAutoFile::read(char *pch, size_t nSize)
151 {
152     if (!file)
153         throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
154     if (fread(pch, 1, nSize, file) != nSize)
155         setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
156     return (*this);
157 }
158
159 CAutoFile &CAutoFile::write(const char *pch, size_t nSize)
160 {
161     if (!file)
162         throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
163     if (fwrite(pch, 1, nSize, file) != nSize)
164         setstate(std::ios::failbit, "CAutoFile::write : write failed");
165     return (*this);
166 }
167
168 void CBufferedFile::setstate(short bits, const char *psz) {
169     state |= bits;
170     if (state & exceptmask)
171         throw std::ios_base::failure(psz);
172 }
173
174 bool CBufferedFile::Fill() {
175     unsigned int pos = (unsigned int)(nSrcPos % vchBuf.size());
176     unsigned int readNow = (unsigned int)(vchBuf.size() - pos);
177     unsigned int nAvail = (unsigned int)(vchBuf.size() - (nSrcPos - nReadPos) - nRewind);
178     if (nAvail < readNow)
179         readNow = nAvail;
180     if (readNow == 0)
181         return false;
182     size_t read = fread((void*)&vchBuf[pos], 1, readNow, src);
183     if (read == 0) {
184         setstate(std::ios_base::failbit, feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed");
185         return false;
186     } else {
187         nSrcPos += read;
188         return true;
189     }
190 }
191
192 CBufferedFile &CBufferedFile::read(char *pch, size_t nSize) {
193     if (nSize + nReadPos > nReadLimit)
194         throw std::ios_base::failure("Read attempted past buffer limit");
195     if (nSize + nRewind > vchBuf.size())
196         throw std::ios_base::failure("Read larger than buffer size");
197     while (nSize > 0) {
198         if (nReadPos == nSrcPos)
199             Fill();
200         unsigned int pos = (unsigned int)(nReadPos % vchBuf.size());
201         size_t nNow = nSize;
202         if (nNow + pos > vchBuf.size())
203             nNow = vchBuf.size() - pos;
204         if (nNow + nReadPos > nSrcPos)
205             nNow = (size_t)(nSrcPos - nReadPos);
206         memcpy(pch, &vchBuf[pos], nNow);
207         nReadPos += nNow;
208         pch += nNow;
209         nSize -= nNow;
210     }
211     return (*this);
212 }
213
214 bool CBufferedFile::SetPos(uint64_t nPos) {
215     nReadPos = nPos;
216     if (nReadPos + nRewind < nSrcPos) {
217         nReadPos = nSrcPos - nRewind;
218         return false;
219     } else if (nReadPos > nSrcPos) {
220         nReadPos = nSrcPos;
221         return false;
222     } else {
223         return true;
224     }
225 }
226
227 bool CBufferedFile::Seek(uint64_t nPos) {
228     long nLongPos = (long)nPos;
229     if (nPos != (uint64_t)nLongPos)
230         return false;
231     if (fseek(src, nLongPos, SEEK_SET))
232         return false;
233     nLongPos = ftell(src);
234     nSrcPos = nLongPos;
235     nReadPos = nLongPos;
236     state = 0;
237     return true;
238 }
239
240 bool CBufferedFile::SetLimit(uint64_t nPos) {
241     if (nPos < nReadPos)
242         return false;
243     nReadLimit = nPos;
244     return true;
245 }
246
247 void CBufferedFile::FindByte(char ch) {
248     for ( ; ; ) {
249         if (nReadPos == nSrcPos)
250             Fill();
251         if (vchBuf[nReadPos % vchBuf.size()] == ch)
252             break;
253         nReadPos++;
254     }
255 }