stream.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. #include "stream.h"
  2. #include "stream_i.h"
  3. #include "file_stream.h"
  4. #include <furi/check.h>
  5. #include <furi/common_defines.h>
  6. void stream_free(Stream* stream) {
  7. furi_assert(stream);
  8. stream->vtable->free(stream);
  9. }
  10. void stream_clean(Stream* stream) {
  11. furi_assert(stream);
  12. stream->vtable->clean(stream);
  13. }
  14. bool stream_eof(Stream* stream) {
  15. furi_assert(stream);
  16. return stream->vtable->eof(stream);
  17. }
  18. bool stream_seek(Stream* stream, int32_t offset, StreamOffset offset_type) {
  19. furi_assert(stream);
  20. return stream->vtable->seek(stream, offset, offset_type);
  21. }
  22. size_t stream_tell(Stream* stream) {
  23. furi_assert(stream);
  24. return stream->vtable->tell(stream);
  25. }
  26. size_t stream_size(Stream* stream) {
  27. furi_assert(stream);
  28. return stream->vtable->size(stream);
  29. }
  30. size_t stream_write(Stream* stream, const uint8_t* data, size_t size) {
  31. furi_assert(stream);
  32. return stream->vtable->write(stream, data, size);
  33. }
  34. size_t stream_read(Stream* stream, uint8_t* data, size_t size) {
  35. furi_assert(stream);
  36. return stream->vtable->read(stream, data, size);
  37. }
  38. bool stream_delete_and_insert(
  39. Stream* stream,
  40. size_t delete_size,
  41. StreamWriteCB write_callback,
  42. const void* ctx) {
  43. furi_assert(stream);
  44. return stream->vtable->delete_and_insert(stream, delete_size, write_callback, ctx);
  45. }
  46. /********************************** Some random helpers starts here **********************************/
  47. typedef struct {
  48. const uint8_t* data;
  49. size_t size;
  50. } StreamWriteData;
  51. static bool stream_write_struct(Stream* stream, const void* context) {
  52. furi_assert(stream);
  53. furi_assert(context);
  54. const StreamWriteData* write_data = context;
  55. return (stream_write(stream, write_data->data, write_data->size) == write_data->size);
  56. }
  57. bool stream_read_line(Stream* stream, string_t str_result) {
  58. string_reset(str_result);
  59. const uint8_t buffer_size = 32;
  60. uint8_t buffer[buffer_size];
  61. do {
  62. uint16_t bytes_were_read = stream_read(stream, buffer, buffer_size);
  63. if(bytes_were_read == 0) break;
  64. bool result = false;
  65. bool error = false;
  66. for(uint16_t i = 0; i < bytes_were_read; i++) {
  67. if(buffer[i] == '\n') {
  68. if(!stream_seek(stream, i - bytes_were_read + 1, StreamOffsetFromCurrent)) {
  69. error = true;
  70. break;
  71. }
  72. string_push_back(str_result, buffer[i]);
  73. result = true;
  74. break;
  75. } else if(buffer[i] == '\r') {
  76. // Ignore
  77. } else {
  78. string_push_back(str_result, buffer[i]);
  79. }
  80. }
  81. if(result || error) {
  82. break;
  83. }
  84. } while(true);
  85. return string_size(str_result) != 0;
  86. }
  87. bool stream_rewind(Stream* stream) {
  88. furi_assert(stream);
  89. return stream_seek(stream, 0, StreamOffsetFromStart);
  90. }
  91. size_t stream_write_char(Stream* stream, char c) {
  92. furi_assert(stream);
  93. return stream_write(stream, (const uint8_t*)&c, 1);
  94. }
  95. size_t stream_write_string(Stream* stream, string_t string) {
  96. furi_assert(stream);
  97. return stream_write(stream, (const uint8_t*)string_get_cstr(string), string_size(string));
  98. }
  99. size_t stream_write_cstring(Stream* stream, const char* string) {
  100. furi_assert(stream);
  101. return stream_write(stream, (const uint8_t*)string, strlen(string));
  102. }
  103. size_t stream_write_format(Stream* stream, const char* format, ...) {
  104. furi_assert(stream);
  105. size_t size;
  106. va_list args;
  107. va_start(args, format);
  108. size = stream_write_vaformat(stream, format, args);
  109. va_end(args);
  110. return size;
  111. }
  112. size_t stream_write_vaformat(Stream* stream, const char* format, va_list args) {
  113. furi_assert(stream);
  114. string_t data;
  115. string_init_vprintf(data, format, args);
  116. size_t size = stream_write_string(stream, data);
  117. string_clear(data);
  118. return size;
  119. }
  120. bool stream_insert(Stream* stream, const uint8_t* data, size_t size) {
  121. furi_assert(stream);
  122. StreamWriteData write_data = {.data = data, .size = size};
  123. return stream_delete_and_insert(stream, 0, stream_write_struct, &write_data);
  124. }
  125. bool stream_insert_char(Stream* stream, char c) {
  126. furi_assert(stream);
  127. return stream_delete_and_insert_char(stream, 0, c);
  128. }
  129. bool stream_insert_string(Stream* stream, string_t string) {
  130. furi_assert(stream);
  131. return stream_delete_and_insert_string(stream, 0, string);
  132. }
  133. bool stream_insert_cstring(Stream* stream, const char* string) {
  134. furi_assert(stream);
  135. return stream_delete_and_insert_cstring(stream, 0, string);
  136. }
  137. bool stream_insert_format(Stream* stream, const char* format, ...) {
  138. furi_assert(stream);
  139. va_list args;
  140. va_start(args, format);
  141. bool result = stream_insert_vaformat(stream, format, args);
  142. va_end(args);
  143. return result;
  144. }
  145. bool stream_insert_vaformat(Stream* stream, const char* format, va_list args) {
  146. furi_assert(stream);
  147. return stream_delete_and_insert_vaformat(stream, 0, format, args);
  148. }
  149. bool stream_delete_and_insert_char(Stream* stream, size_t delete_size, char c) {
  150. furi_assert(stream);
  151. StreamWriteData write_data = {.data = (uint8_t*)&c, .size = 1};
  152. return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data);
  153. }
  154. bool stream_delete_and_insert_string(Stream* stream, size_t delete_size, string_t string) {
  155. furi_assert(stream);
  156. StreamWriteData write_data = {
  157. .data = (uint8_t*)string_get_cstr(string), .size = string_size(string)};
  158. return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data);
  159. }
  160. bool stream_delete_and_insert_cstring(Stream* stream, size_t delete_size, const char* string) {
  161. furi_assert(stream);
  162. StreamWriteData write_data = {.data = (uint8_t*)string, .size = strlen(string)};
  163. return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data);
  164. }
  165. bool stream_delete_and_insert_format(Stream* stream, size_t delete_size, const char* format, ...) {
  166. furi_assert(stream);
  167. va_list args;
  168. va_start(args, format);
  169. bool result = stream_delete_and_insert_vaformat(stream, delete_size, format, args);
  170. va_end(args);
  171. return result;
  172. }
  173. bool stream_delete_and_insert_vaformat(
  174. Stream* stream,
  175. size_t delete_size,
  176. const char* format,
  177. va_list args) {
  178. furi_assert(stream);
  179. string_t data;
  180. string_init_vprintf(data, format, args);
  181. StreamWriteData write_data = {
  182. .data = (uint8_t*)string_get_cstr(data), .size = string_size(data)};
  183. bool result = stream_delete_and_insert(stream, 0, stream_write_struct, &write_data);
  184. string_clear(data);
  185. return result;
  186. }
  187. bool stream_delete(Stream* stream, size_t size) {
  188. furi_assert(stream);
  189. return stream_delete_and_insert(stream, size, NULL, NULL);
  190. }
  191. size_t stream_copy(Stream* stream_from, Stream* stream_to, size_t size) {
  192. uint8_t* buffer = malloc(STREAM_CACHE_SIZE);
  193. size_t copied = 0;
  194. do {
  195. size_t bytes_count = MIN(STREAM_CACHE_SIZE, size - copied);
  196. if(bytes_count <= 0) {
  197. break;
  198. }
  199. uint16_t bytes_were_read = stream_read(stream_from, buffer, bytes_count);
  200. if(bytes_were_read != bytes_count) break;
  201. uint16_t bytes_were_written = stream_write(stream_to, buffer, bytes_count);
  202. if(bytes_were_written != bytes_count) break;
  203. copied += bytes_count;
  204. } while(true);
  205. free(buffer);
  206. return copied;
  207. }
  208. size_t stream_copy_full(Stream* stream_from, Stream* stream_to) {
  209. size_t was_written = 0;
  210. do {
  211. if(!stream_seek(stream_from, 0, StreamOffsetFromStart)) break;
  212. if(!stream_seek(stream_to, 0, StreamOffsetFromStart)) break;
  213. was_written = stream_copy(stream_from, stream_to, stream_size(stream_from));
  214. } while(false);
  215. return was_written;
  216. }
  217. bool stream_split(Stream* stream, Stream* stream_left, Stream* stream_right) {
  218. bool result = false;
  219. size_t size = stream_size(stream);
  220. size_t tell = stream_tell(stream);
  221. do {
  222. // copy right
  223. if(stream_copy(stream, stream_right, size - tell) != (size - tell)) break;
  224. // copy left
  225. if(!stream_rewind(stream)) break;
  226. if(stream_copy(stream, stream_left, tell) != tell) break;
  227. // restore RW pointer
  228. if(!stream_seek(stream, tell, StreamOffsetFromStart)) break;
  229. result = true;
  230. } while(false);
  231. return result;
  232. }
  233. size_t stream_load_from_file(Stream* stream, Storage* storage, const char* path) {
  234. size_t was_written = 0;
  235. Stream* file = file_stream_alloc(storage);
  236. do {
  237. if(!file_stream_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) break;
  238. was_written = stream_copy(file, stream, stream_size(file));
  239. } while(false);
  240. stream_free(file);
  241. return was_written;
  242. }
  243. size_t stream_save_to_file(Stream* stream, Storage* storage, const char* path, FS_OpenMode mode) {
  244. size_t was_written = 0;
  245. Stream* file = file_stream_alloc(storage);
  246. do {
  247. if(!file_stream_open(file, path, FSAM_WRITE, mode)) break;
  248. was_written = stream_copy(stream, file, stream_size(stream));
  249. } while(false);
  250. stream_free(file);
  251. return was_written;
  252. }
  253. void stream_dump_data(Stream* stream) {
  254. size_t size = stream_size(stream);
  255. size_t tell = stream_tell(stream);
  256. printf("stream %p\r\n", stream);
  257. printf("size = %u\r\n", size);
  258. printf("tell = %u\r\n", tell);
  259. printf("DATA START\r\n");
  260. uint8_t* data = malloc(STREAM_CACHE_SIZE);
  261. stream_rewind(stream);
  262. while(true) {
  263. size_t was_read = stream_read(stream, data, STREAM_CACHE_SIZE);
  264. if(was_read == 0) break;
  265. for(size_t i = 0; i < was_read; i++) {
  266. printf("%c", data[i]);
  267. }
  268. }
  269. free(data);
  270. printf("\r\n");
  271. printf("DATA END\r\n");
  272. stream_seek(stream, tell, StreamOffsetFromStart);
  273. }