| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #include "stream.h"
- #include "stream_i.h"
- #include "string_stream.h"
- #include <core/common_defines.h>
- typedef struct {
- Stream stream_base;
- FuriString* string;
- size_t index;
- } StringStream;
- static size_t string_stream_write_char(StringStream* stream, char c);
- static void string_stream_free(StringStream* stream);
- static bool string_stream_eof(StringStream* stream);
- static void string_stream_clean(StringStream* stream);
- static bool string_stream_seek(StringStream* stream, int32_t offset, StreamOffset offset_type);
- static size_t string_stream_tell(StringStream* stream);
- static size_t string_stream_size(StringStream* stream);
- static size_t string_stream_write(StringStream* stream, const char* data, size_t size);
- static size_t string_stream_read(StringStream* stream, char* data, size_t size);
- static bool string_stream_delete_and_insert(
- StringStream* stream,
- size_t delete_size,
- StreamWriteCB write_callback,
- const void* ctx);
- const StreamVTable string_stream_vtable = {
- .free = (StreamFreeFn)string_stream_free,
- .eof = (StreamEOFFn)string_stream_eof,
- .clean = (StreamCleanFn)string_stream_clean,
- .seek = (StreamSeekFn)string_stream_seek,
- .tell = (StreamTellFn)string_stream_tell,
- .size = (StreamSizeFn)string_stream_size,
- .write = (StreamWriteFn)string_stream_write,
- .read = (StreamReadFn)string_stream_read,
- .delete_and_insert = (StreamDeleteAndInsertFn)string_stream_delete_and_insert,
- };
- Stream* string_stream_alloc() {
- StringStream* stream = malloc(sizeof(StringStream));
- stream->string = furi_string_alloc();
- stream->index = 0;
- stream->stream_base.vtable = &string_stream_vtable;
- return (Stream*)stream;
- }
- static void string_stream_free(StringStream* stream) {
- furi_string_free(stream->string);
- free(stream);
- }
- static bool string_stream_eof(StringStream* stream) {
- return (string_stream_tell(stream) >= string_stream_size(stream));
- }
- static void string_stream_clean(StringStream* stream) {
- stream->index = 0;
- furi_string_reset(stream->string);
- }
- static bool string_stream_seek(StringStream* stream, int32_t offset, StreamOffset offset_type) {
- bool result = true;
- switch(offset_type) {
- case StreamOffsetFromStart:
- if(offset >= 0) {
- stream->index = offset;
- } else {
- result = false;
- stream->index = 0;
- }
- break;
- case StreamOffsetFromCurrent:
- if(((int32_t)stream->index + offset) >= 0) {
- stream->index += offset;
- } else {
- result = false;
- stream->index = 0;
- }
- break;
- case StreamOffsetFromEnd:
- if(((int32_t)furi_string_size(stream->string) + offset) >= 0) {
- stream->index = furi_string_size(stream->string) + offset;
- } else {
- result = false;
- stream->index = 0;
- }
- break;
- }
- int32_t diff = (stream->index - furi_string_size(stream->string));
- if(diff > 0) {
- stream->index -= diff;
- result = false;
- }
- return result;
- }
- static size_t string_stream_tell(StringStream* stream) {
- return stream->index;
- }
- static size_t string_stream_size(StringStream* stream) {
- return furi_string_size(stream->string);
- }
- static size_t string_stream_write(StringStream* stream, const char* data, size_t size) {
- // TODO: can be optimized for edge cases
- size_t i;
- for(i = 0; i < size; i++) {
- string_stream_write_char(stream, data[i]);
- }
- return i;
- }
- static size_t string_stream_read(StringStream* stream, char* data, size_t size) {
- size_t write_index = 0;
- const char* cstr = furi_string_get_cstr(stream->string);
- if(!string_stream_eof(stream)) {
- while(true) {
- if(write_index >= size) break;
- data[write_index] = cstr[stream->index];
- write_index++;
- string_stream_seek(stream, 1, StreamOffsetFromCurrent);
- if(string_stream_eof(stream)) break;
- }
- }
- return write_index;
- }
- static bool string_stream_delete_and_insert(
- StringStream* stream,
- size_t delete_size,
- StreamWriteCB write_callback,
- const void* ctx) {
- bool result = true;
- if(delete_size) {
- size_t remain_size = string_stream_size(stream) - string_stream_tell(stream);
- remain_size = MIN(delete_size, remain_size);
- if(remain_size != 0) {
- furi_string_replace_at(stream->string, stream->index, remain_size, "");
- }
- }
- if(write_callback) {
- FuriString* right;
- right = furi_string_alloc_set(&furi_string_get_cstr(stream->string)[stream->index]);
- furi_string_left(stream->string, string_stream_tell(stream));
- result &= write_callback((Stream*)stream, ctx);
- furi_string_cat(stream->string, right);
- furi_string_free(right);
- }
- return result;
- }
- /**
- * Write to string stream helper
- * @param stream
- * @param c
- * @return size_t
- */
- static size_t string_stream_write_char(StringStream* stream, char c) {
- if(string_stream_eof(stream)) {
- furi_string_push_back(stream->string, c);
- } else {
- furi_string_set_char(stream->string, stream->index, c);
- }
- stream->index++;
- return 1;
- }
|