diff options
Diffstat (limited to 'kit/input_stream.c')
-rw-r--r-- | kit/input_stream.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/kit/input_stream.c b/kit/input_stream.c new file mode 100644 index 0000000..369cf64 --- /dev/null +++ b/kit/input_stream.c @@ -0,0 +1,103 @@ +#include "input_stream.h" + +#include <string.h> + +enum { KIT_INPUT_STREAM_STR, KIT_INPUT_STREAM_FILE }; + +typedef struct { + i64 type; + kit_allocator_t *alloc; +} kit_is_state_basic_t; + +typedef struct { + i64 type; + kit_allocator_t *alloc; + kit_str_t string; +} kit_is_state_str_t; + +typedef struct { + i64 type; + kit_allocator_t *alloc; + FILE *file; +} kit_is_state_file_t; + +static int kit_is_check_type_(void *state, i64 type) { + kit_is_state_basic_t *basic = (kit_is_state_basic_t *) state; + return basic != NULL && basic->type == type; +} + +static i64 kit_read_str_(void *state, kit_str_t destination) { + if (!kit_is_check_type_(state, KIT_INPUT_STREAM_STR)) + return 0; + + kit_is_state_str_t *str = (kit_is_state_str_t *) state; + i64 size = destination.size < str->string.size ? destination.size + : str->string.size; + memcpy(destination.values, str->string.values, size); + str->string.values += size; + str->string.size -= size; + return size; +} + +static i64 kit_read_file_(void *state, kit_str_t destination) { + if (!kit_is_check_type_(state, KIT_INPUT_STREAM_FILE)) + return 0; + + kit_is_state_file_t *f = (kit_is_state_file_t *) state; + + if (f->file == NULL || feof(f->file)) + return 0; + + i64 size = (i64) fread(destination.values, 1, destination.size, + f->file); + + if (size <= 0) + return 0; + + return size; +} + +kit_is_handle_t kit_is_wrap_string(kit_str_t string, + kit_allocator_t *alloc) { + kit_is_handle_t in; + memset(&in, 0, sizeof in); + + kit_is_state_str_t *state = (kit_is_state_str_t *) + kit_alloc_dispatch(alloc, KIT_ALLOCATE, + sizeof(kit_is_state_str_t), 0, NULL); + if (state != NULL) { + memset(state, 0, sizeof *state); + state->type = KIT_INPUT_STREAM_STR; + state->string = string; + state->alloc = alloc; + in.state = state; + in.read = kit_read_str_; + } + return in; +} + +kit_is_handle_t kit_is_wrap_file(FILE *f, kit_allocator_t *alloc) { + kit_is_handle_t in; + memset(&in, 0, sizeof in); + + kit_is_state_file_t *state = (kit_is_state_file_t *) + kit_alloc_dispatch(alloc, KIT_ALLOCATE, + sizeof(kit_is_state_file_t), 0, NULL); + + if (state != NULL) { + memset(state, 0, sizeof *state); + state->type = KIT_INPUT_STREAM_FILE; + state->file = f; + state->alloc = alloc; + in.state = state; + in.read = kit_read_file_; + } + + return in; +} + +void kit_is_destroy(kit_is_handle_t in) { + kit_is_state_basic_t *basic = (kit_is_state_basic_t *) in.state; + if (basic != NULL) + kit_alloc_dispatch(basic->alloc, KIT_DEALLOCATE, 0, 0, in.state); +} |