stream.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. #include "stream.h"
  2. #include "stream_i.h"
  3. #include "file_stream.h"
  4. #include <core/check.h>
  5. #include <core/common_defines.h>
  6. #define STREAM_BUFFER_SIZE (32U)
  7. void stream_free(Stream* stream) {
  8. furi_assert(stream);
  9. stream->vtable->free(stream);
  10. }
  11. void stream_clean(Stream* stream) {
  12. furi_assert(stream);
  13. stream->vtable->clean(stream);
  14. }
  15. bool stream_eof(Stream* stream) {
  16. furi_assert(stream);
  17. return stream->vtable->eof(stream);
  18. }
  19. bool stream_seek(Stream* stream, int32_t offset, StreamOffset offset_type) {
  20. furi_assert(stream);
  21. return stream->vtable->seek(stream, offset, offset_type);
  22. }
  23. static bool stream_seek_to_char_forward(Stream* stream, char c) {
  24. // Search is starting from seconds character
  25. if(!stream_seek(stream, 1, StreamOffsetFromCurrent)) {
  26. return false;
  27. }
  28. // Search character in a stream
  29. bool result = false;
  30. while(!result) {
  31. uint8_t buffer[STREAM_BUFFER_SIZE] = {0};
  32. size_t ret = stream_read(stream, buffer, STREAM_BUFFER_SIZE);
  33. for(size_t i = 0; i < ret; i++) {
  34. if(buffer[i] == c) {
  35. stream_seek(stream, (int32_t)i - ret, StreamOffsetFromCurrent);
  36. result = true;
  37. break;
  38. }
  39. }
  40. if(ret != STREAM_BUFFER_SIZE) break;
  41. }
  42. return result;
  43. }
  44. static bool stream_seek_to_char_backward(Stream* stream, char c) {
  45. size_t anchor = stream_tell(stream);
  46. // Special case, no previous characters
  47. if(anchor == 0) {
  48. return false;
  49. }
  50. bool result = false;
  51. while(!result) {
  52. // Seek back
  53. uint8_t buffer[STREAM_BUFFER_SIZE] = {0};
  54. size_t to_read = STREAM_BUFFER_SIZE;
  55. if(to_read > anchor) {
  56. to_read = anchor;
  57. }
  58. anchor -= to_read;
  59. furi_check(stream_seek(stream, anchor, StreamOffsetFromStart));
  60. size_t ret = stream_read(stream, buffer, to_read);
  61. for(size_t i = 0; i < ret; i++) {
  62. size_t cursor = ret - i - 1;
  63. if(buffer[cursor] == c) {
  64. result = true;
  65. furi_check(stream_seek(stream, anchor + cursor, StreamOffsetFromStart));
  66. break;
  67. } else {
  68. }
  69. }
  70. if(ret != STREAM_BUFFER_SIZE) break;
  71. }
  72. return result;
  73. }
  74. bool stream_seek_to_char(Stream* stream, char c, StreamDirection direction) {
  75. const size_t old_position = stream_tell(stream);
  76. bool result = false;
  77. if(direction == StreamDirectionForward) {
  78. result = stream_seek_to_char_forward(stream, c);
  79. } else if(direction == StreamDirectionBackward) {
  80. result = stream_seek_to_char_backward(stream, c);
  81. }
  82. // Rollback
  83. if(!result) {
  84. stream_seek(stream, old_position, StreamOffsetFromStart);
  85. }
  86. return result;
  87. }
  88. size_t stream_tell(Stream* stream) {
  89. furi_assert(stream);
  90. return stream->vtable->tell(stream);
  91. }
  92. size_t stream_size(Stream* stream) {
  93. furi_assert(stream);
  94. return stream->vtable->size(stream);
  95. }
  96. size_t stream_write(Stream* stream, const uint8_t* data, size_t size) {
  97. furi_assert(stream);
  98. return stream->vtable->write(stream, data, size);
  99. }
  100. size_t stream_read(Stream* stream, uint8_t* data, size_t size) {
  101. furi_assert(stream);
  102. return stream->vtable->read(stream, data, size);
  103. }
  104. bool stream_delete_and_insert(
  105. Stream* stream,
  106. size_t delete_size,
  107. StreamWriteCB write_callback,
  108. const void* ctx) {
  109. furi_assert(stream);
  110. return stream->vtable->delete_and_insert(stream, delete_size, write_callback, ctx);
  111. }
  112. /********************************** Some random helpers starts here **********************************/
  113. typedef struct {
  114. const uint8_t* data;
  115. size_t size;
  116. } StreamWriteData;
  117. static bool stream_write_struct(Stream* stream, const void* context) {
  118. furi_assert(stream);
  119. furi_assert(context);
  120. const StreamWriteData* write_data = context;
  121. return (stream_write(stream, write_data->data, write_data->size) == write_data->size);
  122. }
  123. bool stream_read_line(Stream* stream, FuriString* str_result) {
  124. furi_string_reset(str_result);
  125. uint8_t buffer[STREAM_BUFFER_SIZE];
  126. do {
  127. uint16_t bytes_were_read = stream_read(stream, buffer, STREAM_BUFFER_SIZE);
  128. if(bytes_were_read == 0) break;
  129. bool result = false;
  130. bool error = false;
  131. for(uint16_t i = 0; i < bytes_were_read; i++) {
  132. if(buffer[i] == '\n') {
  133. if(!stream_seek(stream, i - bytes_were_read + 1, StreamOffsetFromCurrent)) {
  134. error = true;
  135. break;
  136. }
  137. furi_string_push_back(str_result, buffer[i]);
  138. result = true;
  139. break;
  140. } else if(buffer[i] == '\r') {
  141. // Ignore
  142. } else {
  143. furi_string_push_back(str_result, buffer[i]);
  144. }
  145. }
  146. if(result || error) {
  147. break;
  148. }
  149. } while(true);
  150. return furi_string_size(str_result) != 0;
  151. }
  152. bool stream_rewind(Stream* stream) {
  153. furi_assert(stream);
  154. return stream_seek(stream, 0, StreamOffsetFromStart);
  155. }
  156. size_t stream_write_char(Stream* stream, char c) {
  157. furi_assert(stream);
  158. return stream_write(stream, (const uint8_t*)&c, 1);
  159. }
  160. size_t stream_write_string(Stream* stream, FuriString* string) {
  161. furi_assert(stream);
  162. return stream_write(
  163. stream, (const uint8_t*)furi_string_get_cstr(string), furi_string_size(string));
  164. }
  165. size_t stream_write_cstring(Stream* stream, const char* string) {
  166. furi_assert(stream);
  167. return stream_write(stream, (const uint8_t*)string, strlen(string));
  168. }
  169. size_t stream_write_format(Stream* stream, const char* format, ...) {
  170. furi_assert(stream);
  171. size_t size;
  172. va_list args;
  173. va_start(args, format);
  174. size = stream_write_vaformat(stream, format, args);
  175. va_end(args);
  176. return size;
  177. }
  178. size_t stream_write_vaformat(Stream* stream, const char* format, va_list args) {
  179. furi_assert(stream);
  180. FuriString* data;
  181. data = furi_string_alloc_vprintf(format, args);
  182. size_t size = stream_write_string(stream, data);
  183. furi_string_free(data);
  184. return size;
  185. }
  186. bool stream_insert(Stream* stream, const uint8_t* data, size_t size) {
  187. furi_assert(stream);
  188. StreamWriteData write_data = {.data = data, .size = size};
  189. return stream_delete_and_insert(stream, 0, stream_write_struct, &write_data);
  190. }
  191. bool stream_insert_char(Stream* stream, char c) {
  192. furi_assert(stream);
  193. return stream_delete_and_insert_char(stream, 0, c);
  194. }
  195. bool stream_insert_string(Stream* stream, FuriString* string) {
  196. furi_assert(stream);
  197. return stream_delete_and_insert_string(stream, 0, string);
  198. }
  199. bool stream_insert_cstring(Stream* stream, const char* string) {
  200. furi_assert(stream);
  201. return stream_delete_and_insert_cstring(stream, 0, string);
  202. }
  203. bool stream_insert_format(Stream* stream, const char* format, ...) {
  204. furi_assert(stream);
  205. va_list args;
  206. va_start(args, format);
  207. bool result = stream_insert_vaformat(stream, format, args);
  208. va_end(args);
  209. return result;
  210. }
  211. bool stream_insert_vaformat(Stream* stream, const char* format, va_list args) {
  212. furi_assert(stream);
  213. return stream_delete_and_insert_vaformat(stream, 0, format, args);
  214. }
  215. bool stream_delete_and_insert_char(Stream* stream, size_t delete_size, char c) {
  216. furi_assert(stream);
  217. StreamWriteData write_data = {.data = (uint8_t*)&c, .size = 1};
  218. return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data);
  219. }
  220. bool stream_delete_and_insert_string(Stream* stream, size_t delete_size, FuriString* string) {
  221. furi_assert(stream);
  222. StreamWriteData write_data = {
  223. .data = (uint8_t*)furi_string_get_cstr(string), .size = furi_string_size(string)};
  224. return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data);
  225. }
  226. bool stream_delete_and_insert_cstring(Stream* stream, size_t delete_size, const char* string) {
  227. furi_assert(stream);
  228. StreamWriteData write_data = {.data = (uint8_t*)string, .size = strlen(string)};
  229. return stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data);
  230. }
  231. bool stream_delete_and_insert_format(Stream* stream, size_t delete_size, const char* format, ...) {
  232. furi_assert(stream);
  233. va_list args;
  234. va_start(args, format);
  235. bool result = stream_delete_and_insert_vaformat(stream, delete_size, format, args);
  236. va_end(args);
  237. return result;
  238. }
  239. bool stream_delete_and_insert_vaformat(
  240. Stream* stream,
  241. size_t delete_size,
  242. const char* format,
  243. va_list args) {
  244. furi_assert(stream);
  245. FuriString* data;
  246. data = furi_string_alloc_vprintf(format, args);
  247. StreamWriteData write_data = {
  248. .data = (uint8_t*)furi_string_get_cstr(data), .size = furi_string_size(data)};
  249. bool result = stream_delete_and_insert(stream, delete_size, stream_write_struct, &write_data);
  250. furi_string_free(data);
  251. return result;
  252. }
  253. bool stream_delete(Stream* stream, size_t size) {
  254. furi_assert(stream);
  255. return stream_delete_and_insert(stream, size, NULL, NULL);
  256. }
  257. size_t stream_copy(Stream* stream_from, Stream* stream_to, size_t size) {
  258. uint8_t* buffer = malloc(STREAM_CACHE_SIZE);
  259. size_t copied = 0;
  260. do {
  261. size_t bytes_count = MIN(STREAM_CACHE_SIZE, size - copied);
  262. if(bytes_count <= 0) {
  263. break;
  264. }
  265. uint16_t bytes_were_read = stream_read(stream_from, buffer, bytes_count);
  266. if(bytes_were_read != bytes_count) break;
  267. uint16_t bytes_were_written = stream_write(stream_to, buffer, bytes_count);
  268. if(bytes_were_written != bytes_count) break;
  269. copied += bytes_count;
  270. } while(true);
  271. free(buffer);
  272. return copied;
  273. }
  274. size_t stream_copy_full(Stream* stream_from, Stream* stream_to) {
  275. size_t was_written = 0;
  276. do {
  277. if(!stream_seek(stream_from, 0, StreamOffsetFromStart)) break;
  278. if(!stream_seek(stream_to, 0, StreamOffsetFromStart)) break;
  279. was_written = stream_copy(stream_from, stream_to, stream_size(stream_from));
  280. } while(false);
  281. return was_written;
  282. }
  283. bool stream_split(Stream* stream, Stream* stream_left, Stream* stream_right) {
  284. bool result = false;
  285. size_t size = stream_size(stream);
  286. size_t tell = stream_tell(stream);
  287. do {
  288. // copy right
  289. if(stream_copy(stream, stream_right, size - tell) != (size - tell)) break;
  290. // copy left
  291. if(!stream_rewind(stream)) break;
  292. if(stream_copy(stream, stream_left, tell) != tell) break;
  293. // restore RW pointer
  294. if(!stream_seek(stream, tell, StreamOffsetFromStart)) break;
  295. result = true;
  296. } while(false);
  297. return result;
  298. }
  299. size_t stream_load_from_file(Stream* stream, Storage* storage, const char* path) {
  300. size_t was_written = 0;
  301. Stream* file = file_stream_alloc(storage);
  302. do {
  303. if(!file_stream_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) break;
  304. was_written = stream_copy(file, stream, stream_size(file));
  305. } while(false);
  306. stream_free(file);
  307. return was_written;
  308. }
  309. size_t stream_save_to_file(Stream* stream, Storage* storage, const char* path, FS_OpenMode mode) {
  310. size_t was_written = 0;
  311. Stream* file = file_stream_alloc(storage);
  312. do {
  313. if(!file_stream_open(file, path, FSAM_WRITE, mode)) break;
  314. was_written = stream_copy(stream, file, stream_size(stream));
  315. } while(false);
  316. stream_free(file);
  317. return was_written;
  318. }
  319. void stream_dump_data(Stream* stream) {
  320. size_t size = stream_size(stream);
  321. size_t tell = stream_tell(stream);
  322. printf("stream %p\r\n", stream);
  323. printf("size = %zu\r\n", size);
  324. printf("tell = %zu\r\n", tell);
  325. printf("DATA START\r\n");
  326. uint8_t* data = malloc(STREAM_CACHE_SIZE);
  327. stream_rewind(stream);
  328. while(true) {
  329. size_t was_read = stream_read(stream, data, STREAM_CACHE_SIZE);
  330. if(was_read == 0) break;
  331. for(size_t i = 0; i < was_read; i++) {
  332. printf("%c", data[i]);
  333. }
  334. }
  335. free(data);
  336. printf("\r\n");
  337. printf("DATA END\r\n");
  338. stream_seek(stream, tell, StreamOffsetFromStart);
  339. }