PageRenderTime 30ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/src/memstream.h

https://bitbucket.org/Marisa-Chan/ua_source
C Header | 477 lines | 369 code | 105 blank | 3 comment | 59 complexity | d1706941ae43efea9ac67be1068054e5 MD5 | raw file
  1. #ifndef MEBLOCK_H_INCLUDED
  2. #define MEBLOCK_H_INCLUDED
  3. #include <stdlib.h>
  4. #include <inttypes.h>
  5. #include <string.h>
  6. #include <deque>
  7. #include <vector>
  8. namespace Common
  9. {
  10. typedef std::vector<uint8_t> ByteArray;
  11. inline void Append(ByteArray* a, const ByteArray& b)
  12. {
  13. if (b.size())
  14. a->insert(a->end(), b.begin(), b.end());
  15. }
  16. inline void AppendByteUL16(ByteArray* a, uint16_t v)
  17. {
  18. a->push_back(v & 0xFF);
  19. a->push_back((v >> 8) & 0xFF);
  20. }
  21. inline void AppendByteUL32(ByteArray* a, uint32_t v)
  22. {
  23. a->push_back(v & 0xFF);
  24. a->push_back((v >> 8) & 0xFF);
  25. a->push_back((v >> 16) & 0xFF);
  26. a->push_back((v >> 24) & 0xFF);
  27. }
  28. inline ByteArray ByteUL16(uint16_t v)
  29. {
  30. ByteArray tmp(2);
  31. tmp[0] = v & 0xFF;
  32. tmp[1] = (v >> 8) & 0xFF;
  33. return tmp;
  34. }
  35. inline ByteArray ByteUL32(uint32_t v)
  36. {
  37. ByteArray tmp(4);
  38. tmp[0] = v & 0xFF;
  39. tmp[1] = (v >> 8) & 0xFF;
  40. tmp[2] = (v >> 16) & 0xFF;
  41. tmp[3] = (v >> 24) & 0xFF;
  42. return tmp;
  43. }
  44. class MeBlock
  45. {
  46. protected:
  47. uint8_t *_mem;
  48. size_t _endPos;
  49. bool _finish; // if block finished - endpos will be fixed
  50. size_t _pos;
  51. public:
  52. const size_t _reservedSize; // blocksize
  53. public:
  54. MeBlock(size_t sz = 0x400)
  55. : _reservedSize(sz)
  56. {
  57. _mem = new uint8_t[sz];
  58. _finish = false;
  59. _pos = 0;
  60. _endPos = 0;
  61. }
  62. ~MeBlock()
  63. {
  64. if (_mem)
  65. delete[] _mem;
  66. }
  67. size_t GetUnusedSize()
  68. {
  69. return _reservedSize - _endPos;
  70. }
  71. size_t GetSize()
  72. {
  73. return _endPos;
  74. }
  75. void *Alloc(size_t sz)
  76. {
  77. if (_finish)
  78. return NULL;
  79. if (_reservedSize - _endPos < sz)
  80. return NULL;
  81. void *tmp = _mem + _endPos;
  82. _endPos += sz;
  83. return tmp;
  84. }
  85. /***
  86. * Return number writed bytes
  87. ***/
  88. size_t Write(const void *data, size_t sz)
  89. {
  90. size_t e = _reservedSize;
  91. if (_finish)
  92. e = _endPos;
  93. if (_pos < 0 || _pos >= e)
  94. return 0;
  95. size_t maxWrite = e - _pos;
  96. if (maxWrite > sz)
  97. maxWrite = sz; //Can write all
  98. memcpy(_mem + _pos, data, maxWrite);
  99. _pos += maxWrite;
  100. if (!_finish && _endPos < _pos)
  101. _endPos = _pos;
  102. return maxWrite;
  103. }
  104. size_t Write(const ByteArray &data)
  105. {
  106. size_t e = _reservedSize;
  107. if (_finish)
  108. e = _endPos;
  109. if (_pos < 0 || _pos >= e)
  110. return 0;
  111. size_t maxWrite = e - _pos;
  112. if (maxWrite > data.size())
  113. maxWrite = data.size(); //Can write all
  114. memcpy(_mem + _pos, data.data(), maxWrite);
  115. _pos += maxWrite;
  116. if (!_finish && _endPos < _pos)
  117. _endPos = _pos;
  118. return maxWrite;
  119. }
  120. size_t Read(size_t pos, void *dst, size_t sz)
  121. {
  122. size_t e = _reservedSize;
  123. if (_finish)
  124. e = _endPos;
  125. if (pos < 0 || pos >= e)
  126. return 0;
  127. size_t maxRead = e - pos;
  128. if (maxRead > sz)
  129. maxRead = sz; //Can read all
  130. memcpy(dst, _mem + pos, maxRead);
  131. return maxRead;
  132. }
  133. ByteArray Read(size_t pos, size_t sz)
  134. {
  135. size_t e = _reservedSize;
  136. if (_finish)
  137. e = _endPos;
  138. if (pos < 0 || pos >= e)
  139. return ByteArray();
  140. size_t maxRead = e - pos;
  141. if (maxRead > sz)
  142. maxRead = sz; //Can read all
  143. return ByteArray(_mem + pos, _mem + pos + maxRead);
  144. }
  145. bool SetWritePos(size_t pos)
  146. {
  147. if (pos < 0 || pos > _endPos)
  148. return false;
  149. _pos = pos;
  150. return true;
  151. }
  152. void Lock()
  153. {
  154. _finish = true;
  155. }
  156. bool IsLocked()
  157. {
  158. return _finish;
  159. }
  160. void Clean()
  161. {
  162. _finish = false;
  163. _pos = 0;
  164. _endPos = 0;
  165. }
  166. };
  167. class BlocksStream
  168. {
  169. public:
  170. class Reader;
  171. friend class Reader;
  172. class Reader
  173. {
  174. friend class BlocksStream;
  175. public:
  176. size_t Size()
  177. {
  178. return _o.Size();
  179. }
  180. size_t Tell()
  181. {
  182. return _pos;
  183. }
  184. bool SetPos(size_t pos)
  185. {
  186. if (pos < 0 || pos > _o.Size())
  187. return false;
  188. size_t off = 0;
  189. size_t i = 0;
  190. for(MeBlock *blk : _o._blocks)
  191. {
  192. if (pos >= off && pos < off + blk->GetSize() )
  193. {
  194. _blockPos = pos - off;
  195. _idx = i;
  196. _pos = pos;
  197. return true;
  198. }
  199. off += blk->GetSize();
  200. i++;
  201. }
  202. return false;
  203. }
  204. size_t Read(void *data, size_t sz)
  205. {
  206. if (_o._blocks.empty())
  207. return 0;
  208. size_t readed = 0;
  209. while(readed != sz && _idx < _o._blocks.size())
  210. {
  211. MeBlock *blk = _o._blocks[_idx];
  212. size_t r = blk->Read(_blockPos, (uint8_t *)data + readed, sz - readed);
  213. readed += r;
  214. _pos += r;
  215. _blockPos += r;
  216. if (_blockPos >= blk->GetSize())
  217. {
  218. _blockPos = 0;
  219. _idx++;
  220. }
  221. }
  222. return readed;
  223. }
  224. ByteArray Read(size_t sz)
  225. {
  226. ByteArray dat;
  227. if (_o._blocks.empty())
  228. return dat;
  229. size_t readed = 0;
  230. while(readed != sz && _idx < _o._blocks.size())
  231. {
  232. MeBlock *blk = _o._blocks[_idx];
  233. ByteArray r = blk->Read(_blockPos, sz - readed);
  234. if(!r.empty())
  235. dat.insert(dat.end(), r.begin(), r.end());
  236. readed += r.size();
  237. _pos += r.size();
  238. _blockPos += r.size();
  239. if (_blockPos >= blk->GetSize())
  240. {
  241. _blockPos = 0;
  242. _idx++;
  243. }
  244. }
  245. return dat;
  246. }
  247. bool ReadU8(uint8_t *v)
  248. {
  249. return Read(v, 1) == 1;
  250. }
  251. bool ReadUL16(uint16_t *v)
  252. {
  253. return Read(v, 2) == 2;
  254. }
  255. bool ReadUL32(uint32_t *v)
  256. {
  257. return Read(v, 4) == 4;
  258. }
  259. uint8_t ReadU8()
  260. {
  261. uint8_t v = 0;
  262. Read(&v, 1);
  263. return v;
  264. }
  265. uint16_t ReadUL16()
  266. {
  267. uint16_t v = 0;
  268. if ( Read(&v, 2) == 2 )
  269. return v;
  270. return 0;
  271. }
  272. uint32_t ReadUL32()
  273. {
  274. uint32_t v = 0;
  275. if ( Read(&v, 4) == 4 )
  276. return v;
  277. return 0;
  278. }
  279. bool Eof()
  280. {
  281. return _pos >= _o.Size();
  282. }
  283. protected:
  284. Reader(BlocksStream &o)
  285. : _o(o)
  286. {
  287. _pos = 0;
  288. _idx = 0;
  289. _blockPos = 0;
  290. };
  291. protected:
  292. BlocksStream & _o;
  293. size_t _pos;
  294. size_t _idx;
  295. size_t _blockPos;
  296. };
  297. public:
  298. BlocksStream(size_t blkSize = 4096)
  299. : _blkSize(blkSize)
  300. {
  301. _size = 0;
  302. }
  303. ~BlocksStream()
  304. {
  305. for (MeBlock *blk : _blocks)
  306. delete blk;
  307. }
  308. size_t Write(const void *data, size_t sz)
  309. {
  310. size_t writen = 0;
  311. size_t err = 0;
  312. while(writen != sz && err < 3)
  313. {
  314. if (_blocks.empty())
  315. _blocks.push_back( new MeBlock(_blkSize) );
  316. else
  317. {
  318. size_t w = _blocks.back()->Write((uint8_t *)data + writen, sz - writen);
  319. writen += w;
  320. if (w == 0)
  321. err++;
  322. else
  323. err = 0;
  324. if (writen != sz) // if no space in block
  325. {
  326. _blocks.back()->Lock();
  327. _blocks.push_back( new MeBlock(_blkSize) );
  328. }
  329. }
  330. }
  331. _size += writen;
  332. return writen;
  333. }
  334. size_t Write(const ByteArray &data)
  335. {
  336. return Write(data.data(), data.size());
  337. }
  338. bool WriteU8(uint8_t v)
  339. {
  340. return Write(&v, 1) == 1;
  341. }
  342. bool WriteUL16(uint16_t v)
  343. {
  344. return Write(&v, 2) == 2;
  345. }
  346. bool WriteUL32(uint32_t v)
  347. {
  348. return Write(&v, 4) == 4;
  349. }
  350. size_t Size()
  351. {
  352. return _size;
  353. }
  354. void Clear()
  355. {
  356. for (MeBlock *blk : _blocks)
  357. delete blk;
  358. _blocks.clear();
  359. _size = 0;
  360. }
  361. Reader GetReader()
  362. {
  363. return Reader(*this);
  364. }
  365. protected:
  366. typedef std::deque<MeBlock *> _tBlockList;
  367. _tBlockList _blocks;
  368. size_t _size;
  369. const size_t _blkSize;
  370. };
  371. }
  372. #endif