file.cpp 8.2 KB

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