mp_flipper_fileio.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdint.h>
  4. #include "py/obj.h"
  5. #include "py/stream.h"
  6. #include "py/runtime.h"
  7. #include "py/mperrno.h"
  8. #include "mp_flipper_fileio.h"
  9. extern const mp_obj_type_t mp_flipper_fileio_type;
  10. extern const mp_obj_type_t mp_flipper_textio_type;
  11. typedef struct _mp_flipper_fileio_file_descriptor_t {
  12. mp_obj_base_t base;
  13. void* handle;
  14. size_t offset;
  15. uint8_t access_mode;
  16. uint8_t open_mode;
  17. } mp_flipper_fileio_file_descriptor_t;
  18. void* mp_flipper_file_new_file_descriptor(void* handle, size_t offset, uint8_t access_mode, uint8_t open_mode, bool is_text) {
  19. mp_obj_type_t type = is_text ? mp_flipper_textio_type : mp_flipper_fileio_type;
  20. mp_flipper_fileio_file_descriptor_t* fd = mp_obj_malloc_with_finaliser(mp_flipper_fileio_file_descriptor_t, &type);
  21. fd->handle = handle;
  22. fd->offset = offset;
  23. fd->access_mode = access_mode;
  24. fd->open_mode = open_mode;
  25. return fd;
  26. }
  27. static mp_uint_t mp_flipper_fileio_read(mp_obj_t self, void* buf, mp_uint_t size, int* errcode) {
  28. mp_flipper_fileio_file_descriptor_t* fd = MP_OBJ_TO_PTR(self);
  29. return mp_flipper_file_read(fd->handle, buf, size, errcode);
  30. }
  31. static mp_uint_t mp_flipper_fileio_write(mp_obj_t self, const void* buf, mp_uint_t size, int* errcode) {
  32. mp_flipper_fileio_file_descriptor_t* fd = MP_OBJ_TO_PTR(self);
  33. return mp_flipper_file_write(fd->handle, buf, size, errcode);
  34. }
  35. static mp_uint_t mp_flipper_fileio_ioctl(mp_obj_t self, mp_uint_t request, uintptr_t arg, int* errcode) {
  36. mp_flipper_fileio_file_descriptor_t* fd = MP_OBJ_TO_PTR(self);
  37. if(request == MP_STREAM_SEEK) {
  38. struct mp_stream_seek_t* seek = (struct mp_stream_seek_t*)(uintptr_t)arg;
  39. size_t position;
  40. bool success;
  41. switch(seek->whence) {
  42. case MP_SEEK_SET:
  43. mp_flipper_file_seek(fd->handle, seek->offset);
  44. break;
  45. case MP_SEEK_CUR:
  46. position = mp_flipper_file_tell(fd->handle);
  47. mp_flipper_file_seek(fd->handle, position + seek->offset);
  48. break;
  49. case MP_SEEK_END:
  50. position = mp_flipper_file_size(fd->handle);
  51. mp_flipper_file_seek(fd->handle, position + seek->offset);
  52. break;
  53. }
  54. seek->offset = mp_flipper_file_tell(fd->handle);
  55. return 0;
  56. }
  57. if(request == MP_STREAM_FLUSH) {
  58. if(!mp_flipper_file_sync(fd->handle)) {
  59. *errcode = MP_EIO;
  60. return MP_STREAM_ERROR;
  61. }
  62. return 0;
  63. }
  64. if(request == MP_STREAM_CLOSE) {
  65. if(fd->handle != NULL) {
  66. if(!mp_flipper_file_close(fd->handle)) {
  67. *errcode = MP_EIO;
  68. return MP_STREAM_ERROR;
  69. }
  70. }
  71. return 0;
  72. }
  73. *errcode = MP_EINVAL;
  74. return MP_STREAM_ERROR;
  75. }
  76. static mp_obj_t mp_flipper_fileio_writable(mp_obj_t self) {
  77. mp_flipper_fileio_file_descriptor_t* fd = MP_OBJ_TO_PTR(self);
  78. return (fd->access_mode & MP_FLIPPER_FILE_ACCESS_MODE_WRITE) ? mp_const_true : mp_const_false;
  79. }
  80. static MP_DEFINE_CONST_FUN_OBJ_1(mp_flipper_fileio_writable_obj, mp_flipper_fileio_writable);
  81. static const mp_map_elem_t mp_flipper_file_locals_dict_table[] = {
  82. {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj)},
  83. {MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj)},
  84. {MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
  85. {MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)},
  86. {MP_OBJ_NEW_QSTR(MP_QSTR_writable), MP_ROM_PTR(&mp_flipper_fileio_writable_obj)},
  87. {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj)},
  88. {MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj)},
  89. {MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj)},
  90. {MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj)},
  91. {MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj)},
  92. {MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj)},
  93. {MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj)},
  94. {MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj)},
  95. };
  96. static MP_DEFINE_CONST_DICT(mp_flipper_file_locals_dict, mp_flipper_file_locals_dict_table);
  97. static const mp_stream_p_t mp_flipper_fileio_stream_p = {
  98. .read = mp_flipper_fileio_read,
  99. .write = mp_flipper_fileio_write,
  100. .ioctl = mp_flipper_fileio_ioctl,
  101. .is_text = false,
  102. };
  103. MP_DEFINE_CONST_OBJ_TYPE(
  104. mp_flipper_fileio_type,
  105. MP_QSTR_FileIO,
  106. MP_TYPE_FLAG_ITER_IS_STREAM,
  107. protocol,
  108. &mp_flipper_fileio_stream_p,
  109. locals_dict,
  110. &mp_flipper_file_locals_dict);
  111. static const mp_stream_p_t mp_flipper_textio_stream_p = {
  112. .read = mp_flipper_fileio_read,
  113. .write = mp_flipper_fileio_write,
  114. .ioctl = mp_flipper_fileio_ioctl,
  115. .is_text = true,
  116. };
  117. MP_DEFINE_CONST_OBJ_TYPE(
  118. mp_flipper_textio_type,
  119. MP_QSTR_TextIO,
  120. MP_TYPE_FLAG_ITER_IS_STREAM,
  121. protocol,
  122. &mp_flipper_textio_stream_p,
  123. locals_dict,
  124. &mp_flipper_file_locals_dict);