readerwriter.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /*
  2. * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef BX_READERWRITER_H_HEADER_GUARD
  6. #define BX_READERWRITER_H_HEADER_GUARD
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "bx.h"
  10. #include "uint32_t.h"
  11. #if BX_COMPILER_MSVC
  12. # define fseeko64 _fseeki64
  13. # define ftello64 _ftelli64
  14. #elif BX_PLATFORM_ANDROID || BX_PLATFORM_FREEBSD || BX_PLATFORM_IOS || BX_PLATFORM_OSX || BX_PLATFORM_QNX
  15. # define fseeko64 fseeko
  16. # define ftello64 ftello
  17. #endif // BX_
  18. namespace bx
  19. {
  20. struct Whence
  21. {
  22. enum Enum
  23. {
  24. Begin,
  25. Current,
  26. End,
  27. };
  28. };
  29. struct BX_NO_VTABLE ReaderI
  30. {
  31. virtual ~ReaderI() = 0;
  32. virtual int32_t read(void* _data, int32_t _size) = 0;
  33. };
  34. inline ReaderI::~ReaderI()
  35. {
  36. }
  37. struct BX_NO_VTABLE WriterI
  38. {
  39. virtual ~WriterI() = 0;
  40. virtual int32_t write(const void* _data, int32_t _size) = 0;
  41. };
  42. inline WriterI::~WriterI()
  43. {
  44. }
  45. struct BX_NO_VTABLE SeekerI
  46. {
  47. virtual ~SeekerI() = 0;
  48. virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) = 0;
  49. };
  50. inline SeekerI::~SeekerI()
  51. {
  52. }
  53. /// Read data.
  54. inline int32_t read(ReaderI* _reader, void* _data, int32_t _size)
  55. {
  56. return _reader->read(_data, _size);
  57. }
  58. /// Write value.
  59. template<typename Ty>
  60. inline int32_t read(ReaderI* _reader, Ty& _value)
  61. {
  62. BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
  63. return _reader->read(&_value, sizeof(Ty) );
  64. }
  65. /// Read value and converts it to host endianess. _fromLittleEndian specifies
  66. /// underlying stream endianess.
  67. template<typename Ty>
  68. inline int32_t readHE(ReaderI* _reader, Ty& _value, bool _fromLittleEndian)
  69. {
  70. BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
  71. Ty value;
  72. int32_t result = _reader->read(&value, sizeof(Ty) );
  73. _value = toHostEndian(value, _fromLittleEndian);
  74. return result;
  75. }
  76. /// Write data.
  77. inline int32_t write(WriterI* _writer, const void* _data, int32_t _size)
  78. {
  79. return _writer->write(_data, _size);
  80. }
  81. /// Write value.
  82. template<typename Ty>
  83. inline int32_t write(WriterI* _writer, const Ty& _value)
  84. {
  85. BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
  86. return _writer->write(&_value, sizeof(Ty) );
  87. }
  88. /// Write value as little endian.
  89. template<typename Ty>
  90. inline int32_t writeLE(WriterI* _writer, const Ty& _value)
  91. {
  92. BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
  93. Ty value = toLittleEndian(_value);
  94. int32_t result = _writer->write(&value, sizeof(Ty) );
  95. return result;
  96. }
  97. /// Write value as big endian.
  98. template<typename Ty>
  99. inline int32_t writeBE(WriterI* _writer, const Ty& _value)
  100. {
  101. BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
  102. Ty value = toBigEndian(_value);
  103. int32_t result = _writer->write(&value, sizeof(Ty) );
  104. return result;
  105. }
  106. /// Skip _offset bytes forward.
  107. inline int64_t skip(SeekerI* _seeker, int64_t _offset)
  108. {
  109. return _seeker->seek(_offset, Whence::Current);
  110. }
  111. /// Seek to any position in file.
  112. inline int64_t seek(SeekerI* _seeker, int64_t _offset = 0, Whence::Enum _whence = Whence::Current)
  113. {
  114. return _seeker->seek(_offset, _whence);
  115. }
  116. /// Returns size of file.
  117. inline int64_t getSize(SeekerI* _seeker)
  118. {
  119. int64_t offset = _seeker->seek();
  120. int64_t size = _seeker->seek(0, Whence::End);
  121. _seeker->seek(offset, Whence::Begin);
  122. return size;
  123. }
  124. struct BX_NO_VTABLE ReaderSeekerI : public ReaderI, public SeekerI
  125. {
  126. };
  127. struct BX_NO_VTABLE WriterSeekerI : public WriterI, public SeekerI
  128. {
  129. };
  130. struct BX_NO_VTABLE FileReaderI : public ReaderSeekerI
  131. {
  132. virtual int32_t open(const char* _filePath) = 0;
  133. virtual int32_t close() = 0;
  134. };
  135. struct BX_NO_VTABLE FileWriterI : public WriterSeekerI
  136. {
  137. virtual int32_t open(const char* _filePath, bool _append = false) = 0;
  138. virtual int32_t close() = 0;
  139. };
  140. inline int32_t open(FileReaderI* _reader, const char* _filePath)
  141. {
  142. return _reader->open(_filePath);
  143. }
  144. inline int32_t close(FileReaderI* _reader)
  145. {
  146. return _reader->close();
  147. }
  148. inline int32_t open(FileWriterI* _writer, const char* _filePath, bool _append = false)
  149. {
  150. return _writer->open(_filePath, _append);
  151. }
  152. inline int32_t close(FileWriterI* _writer)
  153. {
  154. return _writer->close();
  155. }
  156. struct BX_NO_VTABLE MemoryBlockI
  157. {
  158. virtual void* more(uint32_t _size = 0) = 0;
  159. virtual uint32_t getSize() = 0;
  160. };
  161. class StaticMemoryBlock : public MemoryBlockI
  162. {
  163. public:
  164. StaticMemoryBlock(void* _data, uint32_t _size)
  165. : m_data(_data)
  166. , m_size(_size)
  167. {
  168. }
  169. virtual ~StaticMemoryBlock()
  170. {
  171. }
  172. virtual void* more(uint32_t /*_size*/ = 0) BX_OVERRIDE
  173. {
  174. return m_data;
  175. }
  176. virtual uint32_t getSize() BX_OVERRIDE
  177. {
  178. return m_size;
  179. }
  180. private:
  181. void* m_data;
  182. uint32_t m_size;
  183. };
  184. class SizerWriter : public WriterSeekerI
  185. {
  186. public:
  187. SizerWriter()
  188. : m_pos(0)
  189. , m_top(0)
  190. {
  191. }
  192. virtual ~SizerWriter()
  193. {
  194. }
  195. virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE
  196. {
  197. switch (_whence)
  198. {
  199. case Whence::Begin:
  200. m_pos = _offset;
  201. break;
  202. case Whence::Current:
  203. m_pos = int64_clamp(m_pos + _offset, 0, m_top);
  204. break;
  205. case Whence::End:
  206. m_pos = int64_clamp(m_top - _offset, 0, m_top);
  207. break;
  208. }
  209. return m_pos;
  210. }
  211. virtual int32_t write(const void* /*_data*/, int32_t _size) BX_OVERRIDE
  212. {
  213. int32_t morecore = int32_t(m_pos - m_top) + _size;
  214. if (0 < morecore)
  215. {
  216. m_top += morecore;
  217. }
  218. int64_t reminder = m_top-m_pos;
  219. int32_t size = uint32_min(_size, int32_t(reminder > INT32_MAX ? INT32_MAX : reminder) );
  220. m_pos += size;
  221. return size;
  222. }
  223. private:
  224. int64_t m_pos;
  225. int64_t m_top;
  226. };
  227. class MemoryReader : public ReaderSeekerI
  228. {
  229. public:
  230. MemoryReader(const void* _data, uint32_t _size)
  231. : m_data( (const uint8_t*)_data)
  232. , m_pos(0)
  233. , m_top(_size)
  234. {
  235. }
  236. virtual ~MemoryReader()
  237. {
  238. }
  239. virtual int64_t seek(int64_t _offset, Whence::Enum _whence) BX_OVERRIDE
  240. {
  241. switch (_whence)
  242. {
  243. case Whence::Begin:
  244. m_pos = _offset;
  245. break;
  246. case Whence::Current:
  247. m_pos = int64_clamp(m_pos + _offset, 0, m_top);
  248. break;
  249. case Whence::End:
  250. m_pos = int64_clamp(m_top - _offset, 0, m_top);
  251. break;
  252. }
  253. return m_pos;
  254. }
  255. virtual int32_t read(void* _data, int32_t _size) BX_OVERRIDE
  256. {
  257. int64_t reminder = m_top-m_pos;
  258. int32_t size = uint32_min(_size, int32_t(reminder > INT32_MAX ? INT32_MAX : reminder) );
  259. memcpy(_data, &m_data[m_pos], size);
  260. m_pos += size;
  261. return size;
  262. }
  263. const uint8_t* getDataPtr() const
  264. {
  265. return &m_data[m_pos];
  266. }
  267. int64_t getPos() const
  268. {
  269. return m_pos;
  270. }
  271. int64_t remaining() const
  272. {
  273. return m_top-m_pos;
  274. }
  275. private:
  276. const uint8_t* m_data;
  277. int64_t m_pos;
  278. int64_t m_top;
  279. };
  280. class MemoryWriter : public WriterSeekerI
  281. {
  282. public:
  283. MemoryWriter(MemoryBlockI* _memBlock)
  284. : m_memBlock(_memBlock)
  285. , m_data(NULL)
  286. , m_pos(0)
  287. , m_top(0)
  288. , m_size(0)
  289. {
  290. }
  291. virtual ~MemoryWriter()
  292. {
  293. }
  294. virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE
  295. {
  296. switch (_whence)
  297. {
  298. case Whence::Begin:
  299. m_pos = _offset;
  300. break;
  301. case Whence::Current:
  302. m_pos = int64_clamp(m_pos + _offset, 0, m_top);
  303. break;
  304. case Whence::End:
  305. m_pos = int64_clamp(m_top - _offset, 0, m_top);
  306. break;
  307. }
  308. return m_pos;
  309. }
  310. virtual int32_t write(const void* _data, int32_t _size) BX_OVERRIDE
  311. {
  312. int32_t morecore = int32_t(m_pos - m_size) + _size;
  313. if (0 < morecore)
  314. {
  315. morecore = BX_ALIGN_MASK(morecore, 0xfff);
  316. m_data = (uint8_t*)m_memBlock->more(morecore);
  317. m_size = m_memBlock->getSize();
  318. }
  319. int64_t reminder = m_size-m_pos;
  320. int32_t size = uint32_min(_size, int32_t(reminder > INT32_MAX ? INT32_MAX : reminder) );
  321. memcpy(&m_data[m_pos], _data, size);
  322. m_pos += size;
  323. m_top = int64_max(m_top, m_pos);
  324. return size;
  325. }
  326. private:
  327. MemoryBlockI* m_memBlock;
  328. uint8_t* m_data;
  329. int64_t m_pos;
  330. int64_t m_top;
  331. int64_t m_size;
  332. };
  333. class StaticMemoryBlockWriter : public MemoryWriter
  334. {
  335. public:
  336. StaticMemoryBlockWriter(void* _data, uint32_t _size)
  337. : MemoryWriter(&m_smb)
  338. , m_smb(_data, _size)
  339. {
  340. }
  341. ~StaticMemoryBlockWriter()
  342. {
  343. }
  344. private:
  345. StaticMemoryBlock m_smb;
  346. };
  347. #if BX_CONFIG_CRT_FILE_READER_WRITER
  348. class CrtFileReader : public FileReaderI
  349. {
  350. public:
  351. CrtFileReader()
  352. : m_file(NULL)
  353. {
  354. }
  355. virtual ~CrtFileReader()
  356. {
  357. }
  358. virtual int32_t open(const char* _filePath) BX_OVERRIDE
  359. {
  360. m_file = fopen(_filePath, "rb");
  361. return NULL == m_file;
  362. }
  363. virtual int32_t close() BX_OVERRIDE
  364. {
  365. fclose(m_file);
  366. return 0;
  367. }
  368. virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE
  369. {
  370. fseeko64(m_file, _offset, _whence);
  371. return ftello64(m_file);
  372. }
  373. virtual int32_t read(void* _data, int32_t _size) BX_OVERRIDE
  374. {
  375. return (int32_t)fread(_data, 1, _size, m_file);
  376. }
  377. private:
  378. FILE* m_file;
  379. };
  380. class CrtFileWriter : public FileWriterI
  381. {
  382. public:
  383. CrtFileWriter()
  384. : m_file(NULL)
  385. {
  386. }
  387. virtual ~CrtFileWriter()
  388. {
  389. }
  390. virtual int32_t open(const char* _filePath, bool _append = false) BX_OVERRIDE
  391. {
  392. if (_append)
  393. {
  394. m_file = fopen(_filePath, "ab");
  395. }
  396. else
  397. {
  398. m_file = fopen(_filePath, "wb");
  399. }
  400. return NULL == m_file;
  401. }
  402. virtual int32_t close() BX_OVERRIDE
  403. {
  404. fclose(m_file);
  405. return 0;
  406. }
  407. virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE
  408. {
  409. fseeko64(m_file, _offset, _whence);
  410. return ftello64(m_file);
  411. }
  412. virtual int32_t write(const void* _data, int32_t _size) BX_OVERRIDE
  413. {
  414. return (int32_t)fwrite(_data, 1, _size, m_file);
  415. }
  416. private:
  417. FILE* m_file;
  418. };
  419. #endif // BX_CONFIG_CRT_FILE_READER_WRITER
  420. } // namespace bx
  421. #endif // BX_READERWRITER_H_HEADER_GUARD