file.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. * Copyright 2010-2018 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #include "bx_p.h"
  6. #include <bx/file.h>
  7. #if !BX_CRT_NONE
  8. # include <stdio.h>
  9. # include <sys/stat.h>
  10. #endif // !BX_CRT_NONE
  11. #ifndef BX_CONFIG_CRT_FILE_READER_WRITER
  12. # define BX_CONFIG_CRT_FILE_READER_WRITER !(0 \
  13. || BX_CRT_NONE \
  14. )
  15. #endif // BX_CONFIG_CRT_FILE_READER_WRITER
  16. namespace bx
  17. {
  18. class NoopWriterImpl : public FileWriterI
  19. {
  20. public:
  21. NoopWriterImpl(void*)
  22. {
  23. }
  24. virtual ~NoopWriterImpl()
  25. {
  26. close();
  27. }
  28. virtual bool open(const FilePath& _filePath, bool _append, Error* _err) override
  29. {
  30. BX_UNUSED(_filePath, _append, _err);
  31. return false;
  32. }
  33. virtual void close() override
  34. {
  35. }
  36. virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override
  37. {
  38. BX_UNUSED(_offset, _whence);
  39. return 0;
  40. }
  41. virtual int32_t write(const void* _data, int32_t _size, Error* _err) override
  42. {
  43. BX_UNUSED(_data, _size, _err);
  44. return 0;
  45. }
  46. };
  47. #if BX_CONFIG_CRT_FILE_READER_WRITER
  48. # if BX_CRT_MSVC
  49. # define fseeko64 _fseeki64
  50. # define ftello64 _ftelli64
  51. # elif 0 \
  52. || BX_PLATFORM_ANDROID \
  53. || BX_PLATFORM_BSD \
  54. || BX_PLATFORM_IOS \
  55. || BX_PLATFORM_OSX
  56. # define fseeko64 fseeko
  57. # define ftello64 ftello
  58. # elif BX_PLATFORM_PS4
  59. # define fseeko64 fseek
  60. # define ftello64 ftell
  61. # endif // BX_
  62. class FileReaderImpl : public FileReaderI
  63. {
  64. public:
  65. FileReaderImpl(FILE* _file)
  66. : m_file(_file)
  67. , m_open(false)
  68. {
  69. }
  70. virtual ~FileReaderImpl()
  71. {
  72. close();
  73. }
  74. virtual bool open(const FilePath& _filePath, Error* _err) override
  75. {
  76. BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
  77. if (NULL != m_file)
  78. {
  79. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open.");
  80. return false;
  81. }
  82. m_file = fopen(_filePath.get(), "rb");
  83. if (NULL == m_file)
  84. {
  85. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileReader: Failed to open file.");
  86. return false;
  87. }
  88. m_open = true;
  89. return true;
  90. }
  91. virtual void close() override
  92. {
  93. if (m_open
  94. && NULL != m_file)
  95. {
  96. fclose(m_file);
  97. m_file = NULL;
  98. }
  99. }
  100. virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override
  101. {
  102. BX_CHECK(NULL != m_file, "Reader/Writer file is not open.");
  103. fseeko64(m_file, _offset, _whence);
  104. return ftello64(m_file);
  105. }
  106. virtual int32_t read(void* _data, int32_t _size, Error* _err) override
  107. {
  108. BX_CHECK(NULL != m_file, "Reader/Writer file is not open.");
  109. BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
  110. int32_t size = (int32_t)fread(_data, 1, _size, m_file);
  111. if (size != _size)
  112. {
  113. if (0 != feof(m_file) )
  114. {
  115. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "FileReader: EOF.");
  116. }
  117. else if (0 != ferror(m_file) )
  118. {
  119. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "FileReader: read error.");
  120. }
  121. return size >= 0 ? size : 0;
  122. }
  123. return size;
  124. }
  125. private:
  126. FILE* m_file;
  127. bool m_open;
  128. };
  129. class FileWriterImpl : public FileWriterI
  130. {
  131. public:
  132. FileWriterImpl(FILE* _file)
  133. : m_file(_file)
  134. , m_open(false)
  135. {
  136. }
  137. virtual ~FileWriterImpl()
  138. {
  139. close();
  140. }
  141. virtual bool open(const FilePath& _filePath, bool _append, Error* _err) override
  142. {
  143. BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
  144. if (NULL != m_file)
  145. {
  146. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open.");
  147. return false;
  148. }
  149. m_file = fopen(_filePath.get(), _append ? "ab" : "wb");
  150. if (NULL == m_file)
  151. {
  152. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileWriter: Failed to open file.");
  153. return false;
  154. }
  155. m_open = true;
  156. return true;
  157. }
  158. virtual void close() override
  159. {
  160. if (m_open
  161. && NULL != m_file)
  162. {
  163. fclose(m_file);
  164. m_file = NULL;
  165. }
  166. }
  167. virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override
  168. {
  169. BX_CHECK(NULL != m_file, "Reader/Writer file is not open.");
  170. fseeko64(m_file, _offset, _whence);
  171. return ftello64(m_file);
  172. }
  173. virtual int32_t write(const void* _data, int32_t _size, Error* _err) override
  174. {
  175. BX_CHECK(NULL != m_file, "Reader/Writer file is not open.");
  176. BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
  177. int32_t size = (int32_t)fwrite(_data, 1, _size, m_file);
  178. if (size != _size)
  179. {
  180. BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "FileWriter: write failed.");
  181. return size >= 0 ? size : 0;
  182. }
  183. return size;
  184. }
  185. private:
  186. FILE* m_file;
  187. bool m_open;
  188. };
  189. ReaderI* getStdIn()
  190. {
  191. static FileReaderImpl s_stdIn(stdout);
  192. return &s_stdIn;
  193. }
  194. WriterI* getStdOut()
  195. {
  196. static FileWriterImpl s_stdOut(stdout);
  197. return &s_stdOut;
  198. }
  199. WriterI* getStdErr()
  200. {
  201. static FileWriterImpl s_stdOut(stderr);
  202. return &s_stdOut;
  203. }
  204. #else
  205. class FileReaderImpl : public FileReaderI
  206. {
  207. public:
  208. FileReaderImpl(void*)
  209. {
  210. }
  211. virtual ~FileReaderImpl()
  212. {
  213. close();
  214. }
  215. virtual bool open(const FilePath& _filePath, Error* _err) override
  216. {
  217. BX_UNUSED(_filePath, _err);
  218. return false;
  219. }
  220. virtual void close() override
  221. {
  222. }
  223. virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override
  224. {
  225. BX_UNUSED(_offset, _whence);
  226. return 0;
  227. }
  228. virtual int32_t read(void* _data, int32_t _size, Error* _err) override
  229. {
  230. BX_UNUSED(_data, _size, _err);
  231. return 0;
  232. }
  233. };
  234. typedef NoopWriterImpl FileWriterImpl;
  235. ReaderI* getStdIn()
  236. {
  237. static FileReaderImpl s_stdIn(NULL);
  238. return &s_stdIn;
  239. }
  240. WriterI* getStdOut()
  241. {
  242. static FileWriterImpl s_stdOut(NULL);
  243. return &s_stdOut;
  244. }
  245. WriterI* getStdErr()
  246. {
  247. static FileWriterImpl s_stdOut(NULL);
  248. return &s_stdOut;
  249. }
  250. #endif // BX_CONFIG_CRT_FILE_READER_WRITER
  251. WriterI* getNullOut()
  252. {
  253. static NoopWriterImpl s_nullOut(NULL);
  254. return &s_nullOut;
  255. }
  256. FileReader::FileReader()
  257. {
  258. BX_STATIC_ASSERT(sizeof(FileReaderImpl) <= sizeof(m_internal) );
  259. BX_PLACEMENT_NEW(m_internal, FileReaderImpl)(NULL);
  260. }
  261. FileReader::~FileReader()
  262. {
  263. FileReaderImpl* impl = reinterpret_cast<FileReaderImpl*>(m_internal);
  264. impl->~FileReaderImpl();
  265. }
  266. bool FileReader::open(const FilePath& _filePath, Error* _err)
  267. {
  268. FileReaderImpl* impl = reinterpret_cast<FileReaderImpl*>(m_internal);
  269. return impl->open(_filePath, _err);
  270. }
  271. void FileReader::close()
  272. {
  273. FileReaderImpl* impl = reinterpret_cast<FileReaderImpl*>(m_internal);
  274. impl->close();
  275. }
  276. int64_t FileReader::seek(int64_t _offset, Whence::Enum _whence)
  277. {
  278. FileReaderImpl* impl = reinterpret_cast<FileReaderImpl*>(m_internal);
  279. return impl->seek(_offset, _whence);
  280. }
  281. int32_t FileReader::read(void* _data, int32_t _size, Error* _err)
  282. {
  283. FileReaderImpl* impl = reinterpret_cast<FileReaderImpl*>(m_internal);
  284. return impl->read(_data, _size, _err);
  285. }
  286. FileWriter::FileWriter()
  287. {
  288. BX_STATIC_ASSERT(sizeof(FileWriterImpl) <= sizeof(m_internal) );
  289. BX_PLACEMENT_NEW(m_internal, FileWriterImpl)(NULL);
  290. }
  291. FileWriter::~FileWriter()
  292. {
  293. FileWriterImpl* impl = reinterpret_cast<FileWriterImpl*>(m_internal);
  294. impl->~FileWriterImpl();
  295. }
  296. bool FileWriter::open(const FilePath& _filePath, bool _append, Error* _err)
  297. {
  298. FileWriterImpl* impl = reinterpret_cast<FileWriterImpl*>(m_internal);
  299. return impl->open(_filePath, _append, _err);
  300. }
  301. void FileWriter::close()
  302. {
  303. FileWriterImpl* impl = reinterpret_cast<FileWriterImpl*>(m_internal);
  304. impl->close();
  305. }
  306. int64_t FileWriter::seek(int64_t _offset, Whence::Enum _whence)
  307. {
  308. FileWriterImpl* impl = reinterpret_cast<FileWriterImpl*>(m_internal);
  309. return impl->seek(_offset, _whence);
  310. }
  311. int32_t FileWriter::write(const void* _data, int32_t _size, Error* _err)
  312. {
  313. FileWriterImpl* impl = reinterpret_cast<FileWriterImpl*>(m_internal);
  314. return impl->write(_data, _size, _err);
  315. }
  316. bool stat(const FilePath& _filePath, FileInfo& _outFileInfo)
  317. {
  318. #if BX_CRT_NONE
  319. BX_UNUSED(_filePath, _outFileInfo);
  320. return false;
  321. #else
  322. _outFileInfo.m_size = 0;
  323. _outFileInfo.m_type = FileInfo::Count;
  324. # if BX_COMPILER_MSVC
  325. struct ::_stat64 st;
  326. int32_t result = ::_stat64(_filePath.get(), &st);
  327. if (0 != result)
  328. {
  329. return false;
  330. }
  331. if (0 != (st.st_mode & _S_IFREG) )
  332. {
  333. _outFileInfo.m_type = FileInfo::Regular;
  334. }
  335. else if (0 != (st.st_mode & _S_IFDIR) )
  336. {
  337. _outFileInfo.m_type = FileInfo::Directory;
  338. }
  339. # else
  340. struct ::stat st;
  341. int32_t result = ::stat(_filePath.get(), &st);
  342. if (0 != result)
  343. {
  344. return false;
  345. }
  346. if (0 != (st.st_mode & S_IFREG) )
  347. {
  348. _outFileInfo.m_type = FileInfo::Regular;
  349. }
  350. else if (0 != (st.st_mode & S_IFDIR) )
  351. {
  352. _outFileInfo.m_type = FileInfo::Directory;
  353. }
  354. # endif // BX_COMPILER_MSVC
  355. _outFileInfo.m_size = st.st_size;
  356. return true;
  357. #endif // BX_CRT_NONE
  358. }
  359. } // namespace bx