2
0

iron_file.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include "iron_file.h"
  2. #include <iron_system.h>
  3. #ifdef IRON_ANDROID
  4. #include <backends/android_system.h>
  5. #endif
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #ifdef IRON_WINDOWS
  10. #include <malloc.h>
  11. #include <memory.h>
  12. #endif
  13. static bool memory_close_callback(iron_file_reader_t *reader) {
  14. return true;
  15. }
  16. static size_t memory_read_callback(iron_file_reader_t *reader, void *data, size_t size) {
  17. size_t read_size = reader->size - reader->offset < size ? reader->size - reader->offset : size;
  18. memcpy(data, (uint8_t *)reader->data + reader->offset, read_size);
  19. reader->offset += read_size;
  20. return read_size;
  21. }
  22. static size_t memory_pos_callback(iron_file_reader_t *reader) {
  23. return reader->offset;
  24. }
  25. static bool memory_seek_callback(iron_file_reader_t *reader, size_t pos) {
  26. reader->offset = pos;
  27. return true;
  28. }
  29. bool iron_file_reader_from_memory(iron_file_reader_t *reader, void *data, size_t size) {
  30. memset(reader, 0, sizeof(iron_file_reader_t));
  31. reader->data = data;
  32. reader->size = size;
  33. reader->read = memory_read_callback;
  34. reader->pos = memory_pos_callback;
  35. reader->seek = memory_seek_callback;
  36. reader->close = memory_close_callback;
  37. return true;
  38. }
  39. #ifdef IRON_IOS
  40. const char *iron_get_resource_path(void);
  41. #endif
  42. #ifdef IRON_MACOS
  43. const char *iron_get_resource_path(void);
  44. #endif
  45. #ifdef IRON_WINDOWS
  46. #include <backends/windows_mini.h>
  47. #endif
  48. static char *fileslocation = NULL;
  49. static bool (*file_reader_callback)(iron_file_reader_t *reader, const char *filename, int type) = NULL;
  50. #ifdef IRON_WINDOWS
  51. static wchar_t wfilepath[1001];
  52. #endif
  53. void iron_internal_set_files_location(char *dir) {
  54. fileslocation = dir;
  55. }
  56. char *iron_internal_get_files_location(void) {
  57. return fileslocation;
  58. }
  59. bool iron_internal_file_reader_callback(iron_file_reader_t *reader, const char *filename, int type) {
  60. return file_reader_callback ? file_reader_callback(reader, filename, type) : false;
  61. }
  62. #ifdef IRON_WINDOWS
  63. static size_t iron_libc_file_reader_read(iron_file_reader_t *reader, void *data, size_t size) {
  64. DWORD readBytes = 0;
  65. if (ReadFile(reader->data, data, (DWORD)size, &readBytes, NULL)) {
  66. return (size_t)readBytes;
  67. }
  68. else {
  69. return 0;
  70. }
  71. }
  72. static bool iron_libc_file_reader_seek(iron_file_reader_t *reader, size_t pos) {
  73. // TODO: make this 64-bit compliant
  74. SetFilePointer(reader->data, (LONG)pos, NULL, FILE_BEGIN);
  75. return true;
  76. }
  77. static bool iron_libc_file_reader_close(iron_file_reader_t *reader) {
  78. CloseHandle(reader->data);
  79. return true;
  80. }
  81. static size_t iron_libc_file_reader_pos(iron_file_reader_t *reader) {
  82. // TODO: make this 64-bit compliant
  83. return (size_t)SetFilePointer(reader->data, 0, NULL, FILE_CURRENT);
  84. }
  85. #else
  86. static size_t iron_libc_file_reader_read(iron_file_reader_t *reader, void *data, size_t size) {
  87. return fread(data, 1, size, (FILE *)reader->data);
  88. }
  89. static bool iron_libc_file_reader_seek(iron_file_reader_t *reader, size_t pos) {
  90. fseek((FILE *)reader->data, pos, SEEK_SET);
  91. return true;
  92. }
  93. static bool iron_libc_file_reader_close(iron_file_reader_t *reader) {
  94. if (reader->data != NULL) {
  95. fclose((FILE *)reader->data);
  96. reader->data = NULL;
  97. }
  98. return true;
  99. }
  100. static size_t iron_libc_file_reader_pos(iron_file_reader_t *reader) {
  101. return ftell((FILE *)reader->data);
  102. }
  103. #endif
  104. bool iron_internal_file_reader_open(iron_file_reader_t *reader, const char *filename, int type) {
  105. char filepath[1001];
  106. #ifdef IRON_IOS
  107. strcpy(filepath, type == IRON_FILE_TYPE_SAVE ? iron_internal_save_path() : iron_get_resource_path());
  108. if (type != IRON_FILE_TYPE_SAVE) {
  109. strcat(filepath, "/");
  110. strcat(filepath, IRON_OUTDIR);
  111. strcat(filepath, "/");
  112. }
  113. strcat(filepath, filename);
  114. #endif
  115. #ifdef IRON_MACOS
  116. strcpy(filepath, type == IRON_FILE_TYPE_SAVE ? iron_internal_save_path() : iron_get_resource_path());
  117. if (type != IRON_FILE_TYPE_SAVE) {
  118. strcat(filepath, "/");
  119. strcat(filepath, IRON_OUTDIR);
  120. strcat(filepath, "/");
  121. }
  122. strcat(filepath, filename);
  123. #endif
  124. #ifdef IRON_WINDOWS
  125. if (type == IRON_FILE_TYPE_SAVE) {
  126. strcpy(filepath, iron_internal_save_path());
  127. strcat(filepath, filename);
  128. }
  129. else {
  130. strcpy(filepath, filename);
  131. }
  132. size_t filepathlength = strlen(filepath);
  133. for (size_t i = 0; i < filepathlength; ++i)
  134. if (filepath[i] == '/')
  135. filepath[i] = '\\';
  136. #endif
  137. #if defined(IRON_LINUX) || defined(IRON_ANDROID)
  138. if (type == IRON_FILE_TYPE_SAVE) {
  139. strcpy(filepath, iron_internal_save_path());
  140. strcat(filepath, filename);
  141. }
  142. else {
  143. strcpy(filepath, filename);
  144. }
  145. #endif
  146. #ifdef IRON_WASM
  147. strcpy(filepath, filename);
  148. #endif
  149. #ifdef IRON_WINDOWS
  150. // Drive letter or network
  151. bool isAbsolute = (filename[1] == ':' && filename[2] == '\\') || (filename[0] == '\\' && filename[1] == '\\');
  152. #else
  153. bool isAbsolute = filename[0] == '/';
  154. #endif
  155. if (isAbsolute) {
  156. strcpy(filepath, filename);
  157. }
  158. else if (fileslocation != NULL && type != IRON_FILE_TYPE_SAVE) {
  159. strcpy(filepath, fileslocation);
  160. strcat(filepath, "/");
  161. strcat(filepath, filename);
  162. }
  163. #ifdef IRON_WINDOWS
  164. MultiByteToWideChar(CP_UTF8, 0, filepath, -1, wfilepath, 1000);
  165. reader->data = CreateFileW(wfilepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  166. if (reader->data == INVALID_HANDLE_VALUE) {
  167. return false;
  168. }
  169. #else
  170. reader->data = fopen(filepath, "rb");
  171. if (reader->data == NULL) {
  172. return false;
  173. }
  174. #endif
  175. #ifdef IRON_WINDOWS
  176. // TODO: make this 64-bit compliant
  177. reader->size = (size_t)GetFileSize(reader->data, NULL);
  178. #else
  179. fseek((FILE *)reader->data, 0, SEEK_END);
  180. reader->size = ftell((FILE *)reader->data);
  181. fseek((FILE *)reader->data, 0, SEEK_SET);
  182. #endif
  183. reader->read = iron_libc_file_reader_read;
  184. reader->seek = iron_libc_file_reader_seek;
  185. reader->close = iron_libc_file_reader_close;
  186. reader->pos = iron_libc_file_reader_pos;
  187. return true;
  188. }
  189. #if !defined(IRON_ANDROID)
  190. bool iron_file_reader_open(iron_file_reader_t *reader, const char *filename, int type) {
  191. memset(reader, 0, sizeof(*reader));
  192. return iron_internal_file_reader_callback(reader, filename, type) ||
  193. iron_internal_file_reader_open(reader, filename, type);
  194. }
  195. #endif
  196. void iron_file_reader_set_callback(bool (*callback)(iron_file_reader_t *reader, const char *filename, int type)) {
  197. file_reader_callback = callback;
  198. }
  199. size_t iron_file_reader_read(iron_file_reader_t *reader, void *data, size_t size) {
  200. return reader->read(reader, data, size);
  201. }
  202. bool iron_file_reader_seek(iron_file_reader_t *reader, size_t pos) {
  203. return reader->seek(reader, pos);
  204. }
  205. bool iron_file_reader_close(iron_file_reader_t *reader) {
  206. return reader->close(reader);
  207. }
  208. size_t iron_file_reader_pos(iron_file_reader_t *reader) {
  209. return reader->pos(reader);
  210. }
  211. size_t iron_file_reader_size(iron_file_reader_t *reader) {
  212. return reader->size;
  213. }
  214. float iron_read_f32le(uint8_t *data) {
  215. return *(float *)data;
  216. }
  217. uint64_t iron_read_u64le(uint8_t *data) {
  218. return *(uint64_t *)data;
  219. }
  220. int64_t iron_read_s64le(uint8_t *data) {
  221. return *(int64_t *)data;
  222. }
  223. uint32_t iron_read_u32le(uint8_t *data) {
  224. return *(uint32_t *)data;
  225. }
  226. int32_t iron_read_s32le(uint8_t *data) {
  227. return *(int32_t *)data;
  228. }
  229. uint16_t iron_read_u16le(uint8_t *data) {
  230. return *(uint16_t *)data;
  231. }
  232. int16_t iron_read_s16le(uint8_t *data) {
  233. return *(int16_t *)data;
  234. }
  235. uint8_t iron_read_u8(uint8_t *data) {
  236. return *data;
  237. }
  238. int8_t iron_read_s8(uint8_t *data) {
  239. return *(int8_t *)data;
  240. }
  241. bool iron_file_writer_open(iron_file_writer_t *writer, const char *filepath) {
  242. writer->file = NULL;
  243. char path[1001];
  244. strcpy(path, iron_internal_save_path());
  245. strcat(path, filepath);
  246. #ifdef IRON_WINDOWS
  247. wchar_t wpath[MAX_PATH];
  248. MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, MAX_PATH);
  249. writer->file = CreateFileW(wpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  250. #else
  251. writer->file = fopen(path, "wb");
  252. #endif
  253. if (writer->file == NULL) {
  254. iron_log("Could not open file %s.", filepath);
  255. return false;
  256. }
  257. return true;
  258. }
  259. void iron_file_writer_close(iron_file_writer_t *writer) {
  260. if (writer->file != NULL) {
  261. #ifdef IRON_WINDOWS
  262. CloseHandle(writer->file);
  263. #else
  264. fclose((FILE *)writer->file);
  265. #endif
  266. writer->file = NULL;
  267. }
  268. }
  269. void iron_file_writer_write(iron_file_writer_t *writer, void *data, int size) {
  270. #ifdef IRON_WINDOWS
  271. DWORD written = 0;
  272. WriteFile(writer->file, data, (DWORD)size, &written, NULL);
  273. #else
  274. fwrite(data, 1, size, (FILE *)writer->file);
  275. #endif
  276. }