PikaStdData_FILEIO.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include "PikaStdData_FILEIO.h"
  2. #include <stdio.h>
  3. #include "PikaCompiler.h"
  4. #include "PikaStdData_List.h"
  5. typedef struct {
  6. uint8_t* addr;
  7. size_t size;
  8. size_t pos;
  9. } PIKAFS_FILE;
  10. int PikaStdData_FILEIO_init(PikaObj* self, char* path, char* mode) {
  11. if (obj_isArgExist(self, "_f")) {
  12. /* already initialized */
  13. return 0;
  14. }
  15. if (strIsStartWith(path, "pikafs/")) {
  16. PIKAFS_FILE* f = (PIKAFS_FILE*)pikaMalloc(sizeof(PIKAFS_FILE));
  17. memset(f, 0, sizeof(PIKAFS_FILE));
  18. extern volatile PikaObj* __pikaMain;
  19. uint8_t* library_bytes = obj_getPtr((PikaObj*)__pikaMain, "@libraw");
  20. if (NULL == library_bytes) {
  21. return 1;
  22. }
  23. char* file_name = path + 7;
  24. if (PIKA_RES_OK != _loadModuleDataWithName(library_bytes, file_name,
  25. &f->addr, &f->size)) {
  26. return 1;
  27. }
  28. obj_setInt(self, "pikafs", PIKA_TRUE);
  29. obj_setPtr(self, "_f", f);
  30. obj_setStr(self, "_mode", mode);
  31. return 0;
  32. }
  33. FILE* f = __platform_fopen(path, mode);
  34. if (f == NULL) {
  35. return 1;
  36. }
  37. obj_setPtr(self, "_f", f);
  38. obj_setStr(self, "_mode", mode);
  39. return 0;
  40. }
  41. void PikaStdData_FILEIO_close(PikaObj* self) {
  42. if (PIKA_TRUE == obj_getInt(self, "pikafs")) {
  43. PIKAFS_FILE* f = obj_getPtr(self, "_f");
  44. if (NULL == f) {
  45. return;
  46. }
  47. pikaFree(f, sizeof(PIKAFS_FILE));
  48. obj_setPtr(self, "_f", NULL);
  49. return;
  50. }
  51. FILE* f = obj_getPtr(self, "_f");
  52. if (NULL == f) {
  53. return;
  54. }
  55. __platform_fclose(f);
  56. obj_setPtr(self, "_f", NULL);
  57. }
  58. size_t _pikafs_fread(void* buf, size_t size, size_t count, PIKAFS_FILE* f) {
  59. if (f->pos >= f->size) {
  60. return 0;
  61. }
  62. if (f->pos + size * count > f->size) {
  63. count = (f->size - f->pos) / size;
  64. }
  65. __platform_memcpy(buf, f->addr + f->pos, size * count);
  66. f->pos += size * count;
  67. return count;
  68. }
  69. Arg* PikaStdData_FILEIO_read(PikaObj* self, PikaTuple* size_) {
  70. int size = 0;
  71. if (pikaTuple_getSize(size_) == 0) {
  72. size = -1;
  73. } else {
  74. size = pikaTuple_getInt(size_, 0);
  75. }
  76. if (size <= 0) {
  77. /* read all */
  78. size = PIKA_READ_FILE_BUFF_SIZE;
  79. }
  80. Arg* buf_arg = arg_newBytes(NULL, size);
  81. uint8_t* buf = arg_getBytes(buf_arg);
  82. int n = 0;
  83. /* read */
  84. if (PIKA_TRUE == obj_getInt(self, "pikafs")) {
  85. PIKAFS_FILE* f = obj_getPtr(self, "_f");
  86. if (NULL == f) {
  87. return NULL;
  88. }
  89. n = _pikafs_fread(buf, 1, size, f);
  90. } else {
  91. FILE* f = obj_getPtr(self, "_f");
  92. if (f == NULL) {
  93. return NULL;
  94. }
  95. n = __platform_fread(buf, 1, size, f);
  96. }
  97. if (n < size) {
  98. /* EOF */
  99. buf[n] = '\0';
  100. }
  101. char* mode = obj_getStr(self, "_mode");
  102. if (strIsContain(mode, 'b')) {
  103. /* binary */
  104. Arg* res = arg_newBytes(buf, n);
  105. arg_deinit(buf_arg);
  106. return res;
  107. } else {
  108. /* text */
  109. Arg* res = arg_newStr((char*)buf);
  110. arg_deinit(buf_arg);
  111. return res;
  112. }
  113. }
  114. int PikaStdData_FILEIO_write(PikaObj* self, Arg* s) {
  115. if (PIKA_TRUE == obj_getInt(self, "pikafs")) {
  116. return 1;
  117. }
  118. FILE* f = obj_getPtr(self, "_f");
  119. int res = -1;
  120. if (f == NULL) {
  121. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  122. __platform_printf("Error: can't write to file\n");
  123. return res;
  124. }
  125. char* mode = obj_getStr(self, "_mode");
  126. if (strIsContain(mode, 'b')) {
  127. if (arg_getType(s) != ARG_TYPE_BYTES) {
  128. __platform_printf(
  129. "TypeError: a bytes-like object is required, not 'str'\r\n");
  130. obj_setErrorCode(self, PIKA_RES_ERR_INVALID_PARAM);
  131. return -1;
  132. }
  133. /* binary */
  134. res = __platform_fwrite(arg_getBytes(s), 1, arg_getBytesSize(s), f);
  135. } else {
  136. /* text */
  137. char* str = arg_getStr(s);
  138. res = __platform_fwrite(str, 1, strlen(str), f);
  139. }
  140. return res;
  141. }
  142. int PikaStdData_FILEIO_seek(PikaObj* self, int offset, PikaTuple* fromwhere) {
  143. FILE* f = obj_getPtr(self, "_f");
  144. if (f == NULL) {
  145. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  146. __platform_printf("Error: can't seek in file\n");
  147. return -1;
  148. }
  149. if (pikaTuple_getSize(fromwhere) == 1) {
  150. int whence = pikaTuple_getInt(fromwhere, 0);
  151. __platform_fseek(f, offset, whence);
  152. return __platform_ftell(f);
  153. }
  154. __platform_fseek(f, offset, 0);
  155. return __platform_ftell(f);
  156. }
  157. int PikaStdData_FILEIO_tell(PikaObj* self) {
  158. FILE* f = obj_getPtr(self, "_f");
  159. if (f == NULL) {
  160. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  161. __platform_printf("Error: can't tell in file\n");
  162. return -1;
  163. }
  164. return __platform_ftell(f);
  165. }
  166. char* PikaStdData_FILEIO_readline(PikaObj* self) {
  167. FILE* f = obj_getPtr(self, "_f");
  168. if (f == NULL) {
  169. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  170. __platform_printf("Error: can't read line from file\n");
  171. return NULL;
  172. }
  173. obj_setBytes(self, "_line_buff", NULL, PIKA_LINE_BUFF_SIZE);
  174. char* line_buff = (char*)obj_getBytes(self, "_line_buff");
  175. while (1) {
  176. char char_buff[2] = {0};
  177. int n = __platform_fread(char_buff, 1, 1, f);
  178. if (n == 0) {
  179. /* EOF */
  180. return NULL;
  181. }
  182. if (char_buff[0] == '\n') {
  183. /* end of line */
  184. strAppend(line_buff, char_buff);
  185. return line_buff;
  186. }
  187. if (strGetSize(line_buff) >= PIKA_LINE_BUFF_SIZE) {
  188. /* line too long */
  189. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  190. __platform_printf("Error: line too long\n");
  191. return NULL;
  192. }
  193. strAppend(line_buff, char_buff);
  194. }
  195. }
  196. PikaObj* PikaStdData_FILEIO_readlines(PikaObj* self) {
  197. FILE* f = obj_getPtr(self, "_f");
  198. if (f == NULL) {
  199. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  200. __platform_printf("Error: can't read lines from file\n");
  201. return NULL;
  202. }
  203. PikaObj* line_list = newNormalObj(New_PikaStdData_List);
  204. PikaStdData_List___init__(line_list);
  205. while (1) {
  206. char* line = PikaStdData_FILEIO_readline(self);
  207. if (line == NULL) {
  208. break;
  209. }
  210. Arg* arg_str = arg_newStr(line);
  211. PikaStdData_List_append(line_list, arg_str);
  212. arg_deinit(arg_str);
  213. }
  214. return line_list;
  215. }
  216. void PikaStdData_FILEIO_writelines(PikaObj* self, PikaObj* lines) {
  217. FILE* f = obj_getPtr(self, "_f");
  218. if (f == NULL) {
  219. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  220. __platform_printf("Error: can't write lines to file\n");
  221. return;
  222. }
  223. PikaList* list = obj_getPtr(lines, "list");
  224. if (list == NULL) {
  225. obj_setErrorCode(self, PIKA_RES_ERR_IO);
  226. __platform_printf("Error: can't write lines to file\n");
  227. return;
  228. }
  229. for (size_t i = 0; i < pikaList_getSize(list); i++) {
  230. char* line = pikaList_getStr(list, i);
  231. Arg* arg_str = arg_newStr(line);
  232. PikaStdData_FILEIO_write(self, arg_str);
  233. arg_deinit(arg_str);
  234. }
  235. return;
  236. }