4 template<typename Stream>
5 void WriteCompactSize(Stream& os, uint64_t nSize)
9 auto chSize = (uint8_t)nSize;
10 WRITEDATA(os, chSize);
12 else if (nSize <= std::numeric_limits<uint16_t>::max())
14 uint8_t chSize = 0xfd;
15 auto xSize = (uint16_t)nSize;
16 WRITEDATA(os, chSize);
19 else if (nSize <= std::numeric_limits<uint32_t>::max())
21 uint8_t chSize = 0xfe;
22 auto xSize = (uint32_t)nSize;
23 WRITEDATA(os, chSize);
28 uint8_t chSize = 0xff;
30 WRITEDATA(os, chSize);
37 template<typename Stream>
38 uint64_t ReadCompactSize(Stream& is)
42 uint64_t nSizeRet = 0;
47 else if (chSize == 0xfd)
53 else if (chSize == 0xfe)
65 if (nSizeRet > (uint64_t)MAX_SIZE)
66 throw std::ios_base::failure("ReadCompactSize() : size too large");
72 // Template instantiation
74 template void WriteCompactSize<CAutoFile>(CAutoFile&, uint64_t);
75 template void WriteCompactSize<CDataStream>(CDataStream&, uint64_t);
76 template void WriteCompactSize<CHashWriter>(CHashWriter&, uint64_t);
78 template uint64_t ReadCompactSize<CAutoFile>(CAutoFile&);
79 template uint64_t ReadCompactSize<CDataStream>(CDataStream&);
86 bool CDataStream::Rewind(size_type n)
88 // Rewind by n characters if the buffer hasn't been compacted yet
91 nReadPos -= (unsigned int)n;
95 void CDataStream::setstate(short bits, const char* psz)
98 if (state & exceptmask)
99 throw std::ios_base::failure(psz);
102 CDataStream& CDataStream::read(char* pch, int nSize)
104 // Read from the beginning of the buffer
106 unsigned int nReadPosNext = nReadPos + nSize;
107 if (nReadPosNext >= vch.size())
109 if (nReadPosNext > vch.size())
111 setstate(std::ios::failbit, "CDataStream::read() : end of data");
112 memset(pch, 0, nSize);
113 nSize = (int)(vch.size() - nReadPos);
115 memcpy(pch, &vch[nReadPos], nSize);
120 memcpy(pch, &vch[nReadPos], nSize);
121 nReadPos = nReadPosNext;
125 CDataStream& CDataStream::ignore(int nSize)
127 // Ignore from the beginning of the buffer
129 unsigned int nReadPosNext = nReadPos + nSize;
130 if (nReadPosNext >= vch.size())
132 if (nReadPosNext > vch.size())
133 setstate(std::ios::failbit, "CDataStream::ignore() : end of data");
138 nReadPos = nReadPosNext;
142 CDataStream& CDataStream::write(const char* pch, int nSize)
144 // Write to the end of the buffer
146 vch.insert(vch.end(), pch, pch + nSize);
150 void CDataStream::GetAndClear(CSerializeData &data) {
152 CSerializeData().swap(vch);
159 CAutoFile::CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn)
163 nVersion = nVersionIn;
165 exceptmask = std::ios::badbit | std::ios::failbit;
168 CAutoFile::~CAutoFile()
173 void CAutoFile::fclose()
175 if (file != NULL && file != stdin && file != stdout && file != stderr)
180 void CAutoFile::setstate(short bits, const char* psz)
183 if (state & exceptmask)
184 throw std::ios_base::failure(psz);
187 CAutoFile& CAutoFile::read(char* pch, size_t nSize)
190 throw std::ios_base::failure("CAutoFile::read : file handle is NULL");
191 if (fread(pch, 1, nSize, file) != nSize)
192 setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed");
196 CAutoFile& CAutoFile::write(const char* pch, size_t nSize)
199 throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
200 if (fwrite(pch, 1, nSize, file) != nSize)
201 setstate(std::ios::failbit, "CAutoFile::write : write failed");
209 void CBufferedFile::setstate(short bits, const char *psz)
212 if (state & exceptmask)
213 throw std::ios_base::failure(psz);
216 bool CBufferedFile::Fill()
218 auto pos = (uint32_t)(nSrcPos % vchBuf.size());
219 auto readNow = (uint32_t)(vchBuf.size() - pos);
220 auto nAvail = (uint32_t)(vchBuf.size() - (nSrcPos - nReadPos) - nRewind);
221 if (nAvail < readNow)
225 size_t read = fread((void*)&vchBuf[pos], 1, readNow, src);
227 setstate(std::ios_base::failbit, feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed");
235 CBufferedFile::CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
236 src(fileIn), nSrcPos(0), nReadPos(0), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, 0),
237 state(0), exceptmask(std::ios_base::badbit | std::ios_base::failbit), nType(nTypeIn), nVersion(nVersionIn) { }
239 bool CBufferedFile::good() const
244 bool CBufferedFile::eof() const
246 return nReadPos == nSrcPos && feof(src);
249 CBufferedFile& CBufferedFile::read(char *pch, size_t nSize)
251 if (nSize + nReadPos > nReadLimit)
252 throw std::ios_base::failure("Read attempted past buffer limit");
253 if (nSize + nRewind > vchBuf.size())
254 throw std::ios_base::failure("Read larger than buffer size");
256 if (nReadPos == nSrcPos)
258 auto pos = (uint32_t)(nReadPos % vchBuf.size());
260 if (nNow + pos > vchBuf.size())
261 nNow = vchBuf.size() - pos;
262 if (nNow + nReadPos > nSrcPos)
263 nNow = (size_t)(nSrcPos - nReadPos);
264 memcpy(pch, &vchBuf[pos], nNow);
272 uint64_t CBufferedFile::GetPos()
277 bool CBufferedFile::SetPos(uint64_t nPos)
280 if (nReadPos + nRewind < nSrcPos) {
281 nReadPos = nSrcPos - nRewind;
283 } else if (nReadPos > nSrcPos) {
291 bool CBufferedFile::Seek(uint64_t nPos)
293 long nLongPos = (long)nPos;
294 if (nPos != (uint64_t)nLongPos)
296 if (fseek(src, nLongPos, SEEK_SET))
298 nLongPos = ftell(src);
305 bool CBufferedFile::SetLimit(uint64_t nPos)
313 void CBufferedFile::FindByte(char ch)
316 if (nReadPos == nSrcPos)
318 if (vchBuf[nReadPos % vchBuf.size()] == ch)