From 00e80c21d99d4945e81f2a91bed1deea0be00ab4 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Thu, 7 Sep 2023 11:37:00 +0200 Subject: input stream: wrap FILE --- source/kit/input_stream.c | 58 +++++++++++++++++++++++++++++++++++----- source/kit/input_stream.h | 8 ++++++ source/tests/input_stream.test.c | 23 +++++++++++++++- 3 files changed, 82 insertions(+), 7 deletions(-) (limited to 'source') diff --git a/source/kit/input_stream.c b/source/kit/input_stream.c index 0ca2ee0..f7b17fa 100644 --- a/source/kit/input_stream.c +++ b/source/kit/input_stream.c @@ -2,7 +2,7 @@ #include -enum { input_stream_str }; +enum { KIT_INPUT_STREAM_STR, KIT_INPUT_STREAM_FILE }; typedef struct { ptrdiff_t type; @@ -15,14 +15,21 @@ typedef struct { kit_str_t string; } kit_is_state_str_t; -static int check_type(void *state, ptrdiff_t type) { +typedef struct { + ptrdiff_t type; + kit_allocator_t alloc; + FILE *file; +} kit_is_state_file_t; + +static int kit_is_check_type_(void *state, ptrdiff_t type) { kit_is_state_basic_t *basic = (kit_is_state_basic_t *) state; return basic != NULL && basic->type == type; } -static ptrdiff_t read_str(void *state, kit_str_t destination) { - if (!check_type(state, input_stream_str)) +static ptrdiff_t 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; ptrdiff_t size = destination.size < str->string.size ? destination.size @@ -33,21 +40,60 @@ static ptrdiff_t read_str(void *state, kit_str_t destination) { return size; } +static ptrdiff_t 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; + + ptrdiff_t size = (ptrdiff_t) 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 = input_stream_str; + state->type = KIT_INPUT_STREAM_STR; state->string = string; state->alloc = alloc; in.state = state; - in.read = read_str; + 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; } diff --git a/source/kit/input_stream.h b/source/kit/input_stream.h index b3c3ae6..d60e37e 100644 --- a/source/kit/input_stream.h +++ b/source/kit/input_stream.h @@ -4,6 +4,8 @@ #include "allocator.h" #include "string_ref.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -19,11 +21,15 @@ typedef struct { kit_is_handle_t kit_is_wrap_string(kit_str_t string, kit_allocator_t alloc); +kit_is_handle_t kit_is_wrap_file(FILE *f, kit_allocator_t alloc); + void kit_is_destroy(kit_is_handle_t in); #define KIT_IS_WRAP_STRING(string) \ kit_is_wrap_string((string), kit_alloc_default()) +#define KIT_IS_WRAP_FILE(f) kit_is_wrap_file((f), kit_alloc_default()) + #define KIT_IS_READ(in, destination) \ (in).read((in).state, (destination)) @@ -31,9 +37,11 @@ void kit_is_destroy(kit_is_handle_t in); # define is_read_fn kit_is_read_fn # define is_handle_t kit_is_handle_t # define is_wrap_string kit_is_wrap_string +# define is_wrap_file kit_is_wrap_file # define is_destroy kit_is_destroy # define IS_WRAP_STRING KIT_IS_WRAP_STRING +# define IS_WRAP_FILE KIT_IS_WRAP_FILE # define IS_READ KIT_IS_READ #endif diff --git a/source/tests/input_stream.test.c b/source/tests/input_stream.test.c index 46ee0dd..467c227 100644 --- a/source/tests/input_stream.test.c +++ b/source/tests/input_stream.test.c @@ -1,4 +1,5 @@ #include "../kit/input_stream.h" +#include "../kit/file.h" #define KIT_TEST_FILE input_stream #include "../kit_test/test.h" @@ -15,9 +16,29 @@ TEST("input stream wrap string") { char buf[4]; str_t buf_ref = { .size = sizeof(buf), .values = buf }; - REQUIRE(IS_READ(in, buf_ref) == buf_ref.size); + REQUIRE_EQ(IS_READ(in, buf_ref), buf_ref.size); REQUIRE(AR_EQUAL(foo_ref, bar_ref)); REQUIRE(AR_EQUAL(buf_ref, bar_ref)); is_destroy(in); } + +TEST("input stream wrap file") { + char foo[] = "test"; + char bar[] = "test"; + + FILE *f = fopen("_kit_temp", "wb"); + fwrite(foo, 1, 4, f); + fclose(f); + + f = fopen("_kit_temp", "rb"); + + is_handle_t in = IS_WRAP_FILE(f); + + REQUIRE_EQ(IS_READ(in, SZ(bar)), SZ(bar).size); + REQUIRE(AR_EQUAL(SZ(foo), SZ(bar))); + + is_destroy(in); + fclose(f); + file_remove(SZ("_kit_temp")); +} -- cgit v1.2.3