readerwriter.h 11 KB

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