diff options
Diffstat (limited to 'source/kit')
-rw-r--r-- | source/kit/CMakeLists.txt | 11 | ||||
-rw-r--r-- | source/kit/allocator.c | 18 | ||||
-rw-r--r-- | source/kit/allocator.h | 25 | ||||
-rw-r--r-- | source/kit/array_ref.c | 41 | ||||
-rw-r--r-- | source/kit/array_ref.h | 61 | ||||
-rw-r--r-- | source/kit/async_function.h | 12 | ||||
-rw-r--r-- | source/kit/dynamic_array.c | 48 | ||||
-rw-r--r-- | source/kit/dynamic_array.h | 108 | ||||
-rw-r--r-- | source/kit/input_buffer.c | 107 | ||||
-rw-r--r-- | source/kit/input_buffer.h | 31 | ||||
-rw-r--r-- | source/kit/input_stream.c | 62 | ||||
-rw-r--r-- | source/kit/input_stream.h | 32 | ||||
-rw-r--r-- | source/kit/string_ref.c | 1 | ||||
-rw-r--r-- | source/kit/string_ref.h | 20 |
14 files changed, 569 insertions, 8 deletions
diff --git a/source/kit/CMakeLists.txt b/source/kit/CMakeLists.txt index 24d1aed..761f572 100644 --- a/source/kit/CMakeLists.txt +++ b/source/kit/CMakeLists.txt @@ -1,6 +1,13 @@ target_sources( ${KIT_LIBRARY} PRIVATE - async_function.c + input_buffer.c input_stream.c string_ref.c + async_function.c allocator.c array_ref.c dynamic_array.c PUBLIC - $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/async_function.h>) + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/allocator.h> + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/string_ref.h> + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/dynamic_array.h> + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/async_function.h> + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/input_stream.h> + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/input_buffer.h> + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/array_ref.h>) diff --git a/source/kit/allocator.c b/source/kit/allocator.c new file mode 100644 index 0000000..fbad11f --- /dev/null +++ b/source/kit/allocator.c @@ -0,0 +1,18 @@ +#include "allocator.h" + +#include <stdlib.h> + +static void *allocate(void *_, size_t size) { + return malloc(size); +} + +static void deallocate(void *_, void *pointer) { + free(pointer); +} + +struct kit_allocator kit_alloc_default() { + struct kit_allocator alloc = { .state = NULL, + .allocate = allocate, + .deallocate = deallocate }; + return alloc; +} diff --git a/source/kit/allocator.h b/source/kit/allocator.h new file mode 100644 index 0000000..24ad5aa --- /dev/null +++ b/source/kit/allocator.h @@ -0,0 +1,25 @@ +#ifndef KIT_ALLOCATOR_H +#define KIT_ALLOCATOR_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*kit_allocate_fn)(void *state, size_t size); +typedef void (*kit_deallocate_fn)(void *state, void *pointer); + +struct kit_allocator { + void *state; + kit_allocate_fn allocate; + kit_deallocate_fn deallocate; +}; + +struct kit_allocator kit_alloc_default(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/kit/array_ref.c b/source/kit/array_ref.c new file mode 100644 index 0000000..2e46324 --- /dev/null +++ b/source/kit/array_ref.c @@ -0,0 +1,41 @@ +#include "array_ref.h" + +#include <string.h> + +_Bool ar_equal_bytes(ptrdiff_t left_element_size, ptrdiff_t left_size, + void const *left_data, + ptrdiff_t right_element_size, + ptrdiff_t right_size, void const *right_data) { + if (left_element_size != right_element_size) + return 0; + if (left_size != right_size) + return 0; + for (ptrdiff_t i = 0; i < left_size; i++) + if (memcmp((char const *) left_data + i * left_element_size, + (char const *) right_data + i * left_element_size, + left_element_size) != 0) + return 0; + return 1; +} + +int ar_compare(ptrdiff_t left_element_size, ptrdiff_t left_size, + void const *left_data, ptrdiff_t right_element_size, + ptrdiff_t right_size, void const *right_data, + ar_compare_fn compare) { + if (left_element_size < right_element_size) + return -1; + if (left_element_size > right_element_size) + return 1; + for (ptrdiff_t i = 0; i < left_size && i < right_size; i++) { + int const c = compare( + (char const *) left_data + i * left_element_size, + (char const *) right_data + i * left_element_size); + if (c != 0) + return c; + } + if (left_size < right_size) + return -1; + if (left_size > right_size) + return 1; + return 0; +} diff --git a/source/kit/array_ref.h b/source/kit/array_ref.h new file mode 100644 index 0000000..649af8b --- /dev/null +++ b/source/kit/array_ref.h @@ -0,0 +1,61 @@ +#ifndef KIT_ARRAY_REF_H +#define KIT_ARRAY_REF_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*ar_compare_fn)(void const *left, void const *right); + +_Bool ar_equal_bytes(ptrdiff_t left_element_size, ptrdiff_t left_size, + void const *left_data, + ptrdiff_t right_element_size, + ptrdiff_t right_size, void const *right_data); + +int ar_compare(ptrdiff_t left_element_size, ptrdiff_t left_size, + void const *left_data, ptrdiff_t right_element_size, + ptrdiff_t right_size, void const *right_data, + ar_compare_fn compare); + +#define AR(name_, type_) \ + struct { \ + ptrdiff_t size; \ + type_ *values; \ + } name_ + +#define AR_CONST(name_, type_) \ + struct { \ + ptrdiff_t size; \ + type_ const *values; \ + } name_ + +#define AR_TYPE(name_, element_type_) \ + struct name_ { \ + ptrdiff_t size; \ + element_type_ *values; \ + } + +#define AR_TYPE_CONST(name_, element_type_) \ + struct name_ { \ + ptrdiff_t size; \ + element_type_ const *values; \ + } + +#define AR_EQUAL(left_, right_) \ + ar_equal_bytes(sizeof((left_).values[0]), (left_).size, \ + (left_).values, sizeof((right_).values[0]), \ + (right_).size, (right_).values) + +#define AR_COMPARE(left_, right_, compare_) \ + ar_compare(sizeof((left_).values[0]), (left_).size, \ + (left_).values, sizeof((right_).values[0]), \ + (right_).size, (right_).values, \ + (ar_compare_fn) (compare_)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/kit/async_function.h b/source/kit/async_function.h index 77a88ef..69b9453 100644 --- a/source/kit/async_function.h +++ b/source/kit/async_function.h @@ -1,15 +1,15 @@ -#ifndef AF_AF_H -#define AF_AF_H +#ifndef KIT_ASYNC_FUNCTION_H +#define KIT_ASYNC_FUNCTION_H #ifdef __cplusplus extern "C" { #endif enum af_request { - af_request_resume, - af_request_join, - af_request_resume_and_join, - af_request_execute + af_request_execute = 0, + af_request_resume = 1, + af_request_join = 2, + af_request_resume_and_join = 3 }; typedef struct { diff --git a/source/kit/dynamic_array.c b/source/kit/dynamic_array.c new file mode 100644 index 0000000..a3ba3dc --- /dev/null +++ b/source/kit/dynamic_array.c @@ -0,0 +1,48 @@ +#include "dynamic_array.h" + +#include <string.h> + +void da_init(struct da_void *array, ptrdiff_t element_size, + ptrdiff_t size, struct kit_allocator alloc) { + memset(array, 0, sizeof(struct da_void)); + + if (size > 0) + array->values = alloc.allocate(alloc.state, element_size * size); + + if (array->values != NULL) { + array->capacity = size; + array->size = size; + } + + array->alloc = alloc; +} + +static ptrdiff_t eval_capacity(ptrdiff_t current_cap, + ptrdiff_t required_cap) { + if (current_cap == 0) + return required_cap; + ptrdiff_t cap = current_cap; + while (cap < required_cap) cap *= 2; + return cap; +} + +void da_resize(struct da_void *array, ptrdiff_t element_size, + ptrdiff_t size) { + if (size <= array->capacity) { + array->size = size; + } else { + ptrdiff_t capacity = eval_capacity(array->capacity, size); + + void *bytes = array->alloc.allocate(array->alloc.state, + element_size * capacity); + if (bytes != NULL) { + if (array->size > 0) + memcpy(bytes, array->values, element_size * array->size); + if (array->values != NULL) + array->alloc.deallocate(array->alloc.state, array->values); + array->capacity = capacity; + array->size = size; + array->values = bytes; + } + } +}
\ No newline at end of file diff --git a/source/kit/dynamic_array.h b/source/kit/dynamic_array.h new file mode 100644 index 0000000..245da63 --- /dev/null +++ b/source/kit/dynamic_array.h @@ -0,0 +1,108 @@ +#ifndef KIT_DYNAMIC_ARRAY_H +#define KIT_DYNAMIC_ARRAY_H + +#include "allocator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct da_void { + ptrdiff_t capacity; + ptrdiff_t size; + void *values; + struct kit_allocator alloc; +}; + +void da_init(struct da_void *array, ptrdiff_t element_size, + ptrdiff_t size, struct kit_allocator alloc); + +void da_resize(struct da_void *array, ptrdiff_t element_size, + ptrdiff_t size); + +/* Declare dynamic array type. + */ +#define DA_TYPE(name_, element_type_) \ + struct name_ { \ + ptrdiff_t capacity; \ + ptrdiff_t size; \ + element_type_ *values; \ + struct kit_allocator alloc; \ + } + +/* Declare dynamic array. + */ +#define DA(name_, element_type_) \ + struct { \ + ptrdiff_t capacity; \ + ptrdiff_t size; \ + element_type_ *values; \ + struct kit_allocator alloc; \ + } name_ + +/* Initialize dynamic array. + */ +#define DA_INIT(array_, size_, alloc_) \ + da_init((struct da_void *) &(array_), sizeof((array_).values[0]), \ + (size_), (alloc_)) + +/* Declare and initialize dynamic array. + */ +#define DA_CREATE(name_, element_type_, size_) \ + DA(name_, element_type_); \ + DA_INIT(name_, (size_), kit_alloc_default()) + +/* Destroy dynamic array. + */ +#define DA_DESTROY(array_) \ + { \ + if ((array_).values != NULL) \ + (array_).alloc.deallocate((array_).alloc.state, \ + (array_).values); \ + } + +/* Resize dynamic array. + */ +#define DA_RESIZE(array_, size_) \ + da_resize((struct da_void *) &(array_), \ + sizeof((array_).values[0]), size_) + +/* Append a value to dynamic array. + */ +#define DA_APPEND(array_, value_) \ + { \ + ptrdiff_t const kit_index_back_ = (array_).size; \ + DA_RESIZE((array_), kit_index_back_ + 1); \ + if (kit_index_back_ < (array_).size) \ + (array_).values[kit_index_back_] = (value_); \ + } + +/* Insert a value into dynamic array. + */ +#define DA_INSERT(array_, index_, value_) \ + { \ + ptrdiff_t const kit_index_back_ = (array_).size; \ + ptrdiff_t const kit_indert_n_ = (index_); \ + DA_RESIZE((array_), kit_index_back_ + 1); \ + if (kit_index_back_ + 1 == (array_).size) { \ + for (ptrdiff_t kit_i_ = kit_index_back_; \ + kit_i_ > kit_indert_n_; kit_i_--) \ + (array_).values[kit_i_] = (array_).values[kit_i_ - 1]; \ + (array_).values[kit_indert_n_] = (value_); \ + } \ + } + +/* Erase a value from dynamic array. + */ +#define DA_ERASE(array_, index_) \ + { \ + for (ptrdiff_t i_ = (index_) + 1; i_ < (array_).size; i_++) \ + (array_).values[i_ - 1] = (array_).values[i_]; \ + DA_RESIZE((array_), (array_).size - 1); \ + } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/kit/input_buffer.c b/source/kit/input_buffer.c new file mode 100644 index 0000000..e1e0cea --- /dev/null +++ b/source/kit/input_buffer.c @@ -0,0 +1,107 @@ +#include "input_buffer.h" + +#include <string.h> + +struct internal_buffer { + ptrdiff_t ref_count; + struct is_handle upstream; + struct kit_allocator alloc; + DA(data, char); +}; + +static struct internal_buffer *buf_init(struct is_handle upstream, + struct kit_allocator alloc) { + struct internal_buffer *buf; + buf = alloc.allocate(alloc.state, sizeof *buf); + if (buf != NULL) { + memset(buf, 0, sizeof *buf); + buf->ref_count = 1; + buf->upstream = upstream; + buf->alloc = alloc; + DA_INIT(buf->data, 0, alloc); + } + return buf; +} + +static struct kit_allocator buf_alloc(void *p) { + return ((struct internal_buffer *) p)->alloc; +} + +static void buf_acquire(void *p) { + struct internal_buffer *buf = (struct internal_buffer *) p; + buf->ref_count++; +} + +static void buf_release(void *p) { + struct internal_buffer *buf = (struct internal_buffer *) p; + if (--buf->ref_count == 0) { + DA_DESTROY(buf->data); + buf->alloc.deallocate(buf->alloc.state, buf); + } +} + +static void buf_adjust(void *p, ptrdiff_t size) { + struct internal_buffer *buf = (struct internal_buffer *) p; + ptrdiff_t offset = buf->data.size; + if (offset < size) { + DA_RESIZE(buf->data, size); + out_str destination = { .size = size - offset, + .values = buf->data.values + offset }; + ptrdiff_t n = IS_READ(buf->upstream, destination); + DA_RESIZE(buf->data, offset + n); + } +} + +static ptrdiff_t min(ptrdiff_t a, ptrdiff_t b) { + if (a < b) + return a; + return b; +} + +static ptrdiff_t buf_read(void *p, ptrdiff_t offset, + out_str destination) { + struct internal_buffer *buf = (struct internal_buffer *) p; + ptrdiff_t n = min(destination.size, buf->data.size - offset); + memcpy(destination.values, buf->data.values + offset, n); + return n; +} + +struct ib_handle ib_wrap(struct is_handle upstream, + struct kit_allocator alloc) { + struct ib_handle buf; + memset(&buf, 0, sizeof buf); + buf.error = 0; + DA_INIT(buf.data, 0, alloc); + buf.internal = buf_init(upstream, alloc); + if (buf.internal == NULL) + buf.error = 1; + return buf; +} + +struct ib_handle ib_read(struct ib_handle buf, ptrdiff_t size) { + struct ib_handle next; + memset(&next, 0, sizeof next); + if (buf.error) { + next.error = 1; + } else { + buf_acquire(buf.internal); + buf_adjust(buf.internal, buf.offset + size); + DA_INIT(next.data, size, buf_alloc(buf.internal)); + if (next.data.size != size) + next.error = 1; + out_str destination = { .size = next.data.size, + .values = next.data.values }; + ptrdiff_t n = buf_read(buf.internal, buf.offset, destination); + next.offset = buf.offset + n; + next.internal = buf.internal; + DA_RESIZE(next.data, n); + if (next.data.size != n) + next.error = 1; + } + return next; +} + +void ib_destroy(struct ib_handle buf) { + buf_release(buf.internal); + DA_DESTROY(buf.data); +} diff --git a/source/kit/input_buffer.h b/source/kit/input_buffer.h new file mode 100644 index 0000000..38ece8d --- /dev/null +++ b/source/kit/input_buffer.h @@ -0,0 +1,31 @@ +#ifndef KIT_INPUT_BUFFER_H +#define KIT_INPUT_BUFFER_H + +#include "dynamic_array.h" +#include "input_stream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ib_handle { + _Bool error; + ptrdiff_t offset; + void *internal; + DA(data, char); +}; + +struct ib_handle ib_wrap(struct is_handle upstream, + struct kit_allocator alloc); + +struct ib_handle ib_read(struct ib_handle buf, ptrdiff_t size); + +void ib_destroy(struct ib_handle buf); + +#define IB_WRAP(upstream) ib_wrap(upstream, kit_alloc_default()) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/kit/input_stream.c b/source/kit/input_stream.c new file mode 100644 index 0000000..500e83d --- /dev/null +++ b/source/kit/input_stream.c @@ -0,0 +1,62 @@ +#include "input_stream.h" + +#include <string.h> + +enum input_stream_type { input_stream_cstr }; + +struct is_state_basic { + ptrdiff_t type; + struct kit_allocator alloc; +}; + +struct is_state_cstr { + ptrdiff_t type; + struct kit_allocator alloc; + cstr string; +}; + +static _Bool check_type(void *state, ptrdiff_t type) { + struct is_state_basic *basic = (struct is_state_basic *) state; + return basic != NULL && basic->type == type; +} + +static ptrdiff_t min(ptrdiff_t a, ptrdiff_t b) { + if (a < b) + return a; + return b; +} + +static ptrdiff_t read_cstr(void *state, out_str destination) { + if (!check_type(state, input_stream_cstr)) + return 0; + struct is_state_cstr *cstr = (struct is_state_cstr *) state; + ptrdiff_t size = min(destination.size, cstr->string.size); + memcpy(destination.values, cstr->string.values, size); + cstr->string.values += size; + cstr->string.size -= size; + return size; +} + +struct is_handle is_wrap_string(cstr string, + struct kit_allocator alloc) { + struct is_handle in; + memset(&in, 0, sizeof in); + struct is_state_cstr *state = + (struct is_state_cstr *) alloc.allocate( + alloc.state, sizeof(struct is_state_cstr)); + if (state != NULL) { + memset(state, 0, sizeof *state); + state->type = input_stream_cstr; + state->string = string; + state->alloc = alloc; + in.state = state; + in.read = read_cstr; + } + return in; +} + +void is_destroy(struct is_handle in) { + struct is_state_basic *basic = (struct is_state_basic *) in.state; + if (basic != NULL) + basic->alloc.deallocate(basic->alloc.state, in.state); +} diff --git a/source/kit/input_stream.h b/source/kit/input_stream.h new file mode 100644 index 0000000..c59a720 --- /dev/null +++ b/source/kit/input_stream.h @@ -0,0 +1,32 @@ +#ifndef KIT_INPUT_STREAM_H +#define KIT_INPUT_STREAM_H + +#include "allocator.h" +#include "string_ref.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ptrdiff_t (*is_read_fn)(void *state, out_str destination); + +struct is_handle { + void *state; + is_read_fn read; +}; + +struct is_handle is_wrap_string(cstr string, + struct kit_allocator alloc); + +void is_destroy(struct is_handle in); + +#define IS_WRAP_STRING(string) \ + is_wrap_string((string), kit_alloc_default()) + +#define IS_READ(in, destination) (in).read((in).state, (destination)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/kit/string_ref.c b/source/kit/string_ref.c new file mode 100644 index 0000000..b7d385f --- /dev/null +++ b/source/kit/string_ref.c @@ -0,0 +1 @@ +#include "string_ref.h" diff --git a/source/kit/string_ref.h b/source/kit/string_ref.h new file mode 100644 index 0000000..d1af90f --- /dev/null +++ b/source/kit/string_ref.h @@ -0,0 +1,20 @@ +#ifndef KIT_STRING_REF_H +#define KIT_STRING_REF_H + +#include "array_ref.h" + +#ifdef __cplusplus +extern "C" { +#endif + +AR_TYPE(string_ref, char); +AR_TYPE_CONST(string_cref, char); + +typedef struct string_ref out_str; +typedef struct string_cref cstr; + +#ifdef __cplusplus +} +#endif + +#endif |