From 6337eb74d3d9028640fdffa0a0e39735a4e3ba93 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Sun, 14 Jan 2024 08:28:13 +0100 Subject: Short type names; Rework input buffer --- build_and_test.sh | 8 +- source/kit/file.c | 29 ++- source/kit/file.h | 25 ++- source/kit/input_buffer.c | 447 ++++++++++++++++++++------------------- source/kit/input_buffer.h | 60 +++--- source/kit/math.h | 2 +- source/kit/secure_random.c | 2 +- source/kit/secure_random.h | 2 +- source/kit/shared_memory.h | 10 +- source/kit/shared_memory.posix.c | 6 +- source/kit/shared_memory.win32.c | 4 +- source/kit/sockets.h | 8 +- source/kit/status.h | 7 +- source/kit/string_builder.h | 3 +- source/kit/types.h | 15 ++ source/kit/unival.h | 6 +- source/kit/xml.c | 335 +++++++++++++---------------- source/kit/xml.h | 6 +- source/tests/input_buffer.test.c | 204 ++++++++++++------ source/tests/xml.test.c | 4 +- 20 files changed, 616 insertions(+), 567 deletions(-) diff --git a/build_and_test.sh b/build_and_test.sh index 66ba8d8..46ed36a 100755 --- a/build_and_test.sh +++ b/build_and_test.sh @@ -226,10 +226,6 @@ if [ $? -ne 0 ]; then exit 1 fi -if [ $SKIP_TESTS -ne 0 ] || [ "$COMPILE" = "emcc" ]; then - exit 0 -fi - echo "Build test suite" $COMPILE $FLAGS \ $FLAG_EXE"$FOLDER/test_suite$EXE_POSTFIX" \ @@ -285,6 +281,10 @@ if [ $? -ne 0 ]; then exit 1 fi +if [ $SKIP_TESTS -ne 0 ] || [ "$COMPILE" = "emcc" ]; then + exit 0 +fi + echo "Run tests" echo "" diff --git a/source/kit/file.c b/source/kit/file.c index e5b834f..76d3249 100644 --- a/source/kit/file.c +++ b/source/kit/file.c @@ -276,7 +276,7 @@ static void kit_prepare_path_(char *buf, kit_str_t path) { char buf[PATH_BUF_SIZE]; \ kit_prepare_path_(buf, path) -kit_status_t kit_folder_create(kit_str_t path) { +s32 kit_folder_create(kit_str_t path) { PREPARE_PATH_BUF_; #if defined(_WIN32) && !defined(__CYGWIN__) return CreateDirectoryA(buf, NULL) ? KIT_OK @@ -286,14 +286,14 @@ kit_status_t kit_folder_create(kit_str_t path) { #endif } -kit_status_t kit_folder_create_recursive(kit_str_t path) { +s32 kit_folder_create_recursive(kit_str_t path) { for (i32 i = 0;; i++) { str_t part = kit_path_take(path, i); i32 type = kit_path_type(part); if (type == KIT_PATH_FILE) return KIT_ERROR_FILE_ALREADY_EXISTS; if (type == KIT_PATH_NONE) { - kit_status_t s = kit_folder_create(part); + s32 s = kit_folder_create(part); if (s != KIT_OK) return s; } @@ -304,7 +304,7 @@ kit_status_t kit_folder_create_recursive(kit_str_t path) { return KIT_OK; } -kit_status_t kit_file_remove(kit_str_t path) { +s32 kit_file_remove(kit_str_t path) { PREPARE_PATH_BUF_; #if defined(_WIN32) && !defined(__CYGWIN__) return DeleteFileA(buf) ? KIT_OK : KIT_ERROR_UNLINK_FAILED; @@ -313,7 +313,7 @@ kit_status_t kit_file_remove(kit_str_t path) { #endif } -kit_status_t kit_folder_remove(kit_str_t path) { +s32 kit_folder_remove(kit_str_t path) { PREPARE_PATH_BUF_; #if defined(_WIN32) && !defined(__CYGWIN__) return RemoveDirectoryA(buf) ? KIT_OK : KIT_ERROR_RMDIR_FAILED; @@ -322,14 +322,14 @@ kit_status_t kit_folder_remove(kit_str_t path) { #endif } -kit_status_t kit_file_remove_recursive(kit_str_t path, - kit_allocator_t *alloc) { +s32 kit_file_remove_recursive(kit_str_t path, + kit_allocator_t *alloc) { i32 type = kit_path_type(path); i64 i; switch (type) { case KIT_PATH_FILE: { - kit_status_t s = kit_file_remove(path); + s32 s = kit_file_remove(path); assert(s == KIT_OK); return s; } @@ -346,15 +346,14 @@ kit_status_t kit_file_remove_recursive(kit_str_t path, for (i = 0; i < list.files.size; i++) { str_builder_t full_path = kit_path_join( path, WRAP_STR(list.files.values[i]), alloc); - kit_status_t s = kit_file_remove_recursive( - WRAP_STR(full_path), alloc); + s32 s = kit_file_remove_recursive(WRAP_STR(full_path), alloc); DA_DESTROY(full_path); assert(s == KIT_OK); } kit_path_list_destroy(list); - kit_status_t s = kit_folder_remove(path); + s32 s = kit_folder_remove(path); assert(s == KIT_OK); return s; } @@ -652,13 +651,13 @@ kit_mapped_file_t kit_file_map(kit_str_t path, i64 size, i32 mode) { return mf; } -kit_status_t kit_file_sync(kit_mapped_file_t *mf) { +s32 kit_file_sync(kit_mapped_file_t *mf) { assert(mf != NULL); if (mf == NULL) return KIT_ERROR_INVALID_ARGUMENT; - kit_status_t status = KIT_OK; + s32 status = KIT_OK; #if !defined(_WIN32) || defined(__CYGWIN__) if (msync(mf->bytes, mf->size, MS_SYNC) != 0) @@ -668,13 +667,13 @@ kit_status_t kit_file_sync(kit_mapped_file_t *mf) { return status; } -kit_status_t kit_file_unmap(kit_mapped_file_t *mf) { +s32 kit_file_unmap(kit_mapped_file_t *mf) { assert(mf != NULL); if (mf == NULL) return KIT_ERROR_INVALID_ARGUMENT; - kit_status_t status = KIT_OK; + s32 status = KIT_OK; #if defined(_WIN32) && !defined(__CYGWIN__) if (!UnmapViewOfFile(mf->bytes)) diff --git a/source/kit/file.h b/source/kit/file.h index b9988f1..79bc574 100644 --- a/source/kit/file.h +++ b/source/kit/file.h @@ -28,7 +28,7 @@ typedef enum { } kit_path_type_t; typedef struct { - kit_status_t status; + s32 status; i64 time_modified_sec; i32 time_modified_nsec; @@ -36,16 +36,16 @@ typedef struct { } kit_file_info_t; typedef struct { - kit_status_t status; + s32 status; KIT_DA(kit_str_builder_t) files; } kit_path_list_t; enum { KIT_FILE_MAP_PRIVATE, KIT_FILE_MAP_SHARED }; typedef struct { - kit_status_t status; - i64 size; - u8 *bytes; + s32 status; + i64 size; + u8 *bytes; #if defined(_WIN32) && !defined(__CYGWIN__) void *_file; void *_map; @@ -72,16 +72,15 @@ kit_str_t kit_path_index(kit_str_t path, i64 index); kit_str_t kit_path_take(kit_str_t path, i64 count); -kit_status_t kit_folder_create(kit_str_t path); +s32 kit_folder_create(kit_str_t path); -kit_status_t kit_folder_create_recursive(kit_str_t path); +s32 kit_folder_create_recursive(kit_str_t path); -kit_status_t kit_file_remove(kit_str_t path); +s32 kit_file_remove(kit_str_t path); -kit_status_t kit_folder_remove(kit_str_t path); +s32 kit_folder_remove(kit_str_t path); -kit_status_t kit_file_remove_recursive(kit_str_t path, - kit_allocator_t *alloc); +s32 kit_file_remove_recursive(kit_str_t path, kit_allocator_t *alloc); kit_path_type_t kit_path_type(kit_str_t path); @@ -93,8 +92,8 @@ kit_path_list_t kit_folder_enum(kit_str_t path, void kit_path_list_destroy(kit_path_list_t list); kit_mapped_file_t kit_file_map(kit_str_t path, i64 size, i32 mode); -kit_status_t kit_file_sync(kit_mapped_file_t *mf); -kit_status_t kit_file_unmap(kit_mapped_file_t *mf); +s32 kit_file_sync(kit_mapped_file_t *mf); +s32 kit_file_unmap(kit_mapped_file_t *mf); #ifdef __cplusplus } diff --git a/source/kit/input_buffer.c b/source/kit/input_buffer.c index 3ee4959..db7e156 100644 --- a/source/kit/input_buffer.c +++ b/source/kit/input_buffer.c @@ -3,174 +3,178 @@ #include #include -typedef struct { - i64 ref_count; - kit_is_handle_t upstream; - kit_allocator_t *alloc; - kit_str_builder_t data; -} internal_buffer_t; - -static internal_buffer_t *kit_buf_init_(kit_is_handle_t upstream, - kit_allocator_t *alloc) { - internal_buffer_t *buf = kit_alloc_dispatch(alloc, KIT_ALLOCATE, - sizeof *buf, 0, NULL); - - if (buf != NULL) { - memset(buf, 0, sizeof *buf); - buf->ref_count = 1; - buf->upstream = upstream; - buf->alloc = alloc; - DA_INIT(buf->data, 0, alloc); - } +enum { KIT_IB_CACHE_SIZE = 256 }; - return buf; -} +static s32 kit_buf_adjust_(kit_input_buffer_t *buf, i64 size) { + assert(buf != NULL); + assert(size >= 0); -static kit_allocator_t *kit_buf_alloc_(void *p) { - assert(p != NULL); + if (buf == NULL) + return KIT_ERROR_INTERNAL; - return ((internal_buffer_t *) p)->alloc; -} + i64 offset = buf->data.size; -static void kit_buf_acquire_(void *p) { - assert(p != NULL); + if (offset >= size) + return KIT_OK; - ((internal_buffer_t *) p)->ref_count++; -} + DA_RESIZE(buf->data, size); + if (buf->data.size != size) + return KIT_ERROR_BAD_ALLOC; -static void kit_buf_release_(void *p) { - if (p == NULL) - return; + str_t destination = { .size = size - offset, + .values = buf->data.values + offset }; + i64 n = IS_READ(buf->upstream, destination); - internal_buffer_t *buf = (internal_buffer_t *) p; + DA_RESIZE(buf->data, offset + n); + if (buf->data.size != offset + n) + return KIT_ERROR_BAD_ALLOC; - if (--buf->ref_count == 0) { - DA_DESTROY(buf->data); - kit_alloc_dispatch(buf->alloc, KIT_DEALLOCATE, 0, 0, buf); - } + return KIT_OK; } -static void kit_buf_adjust_(void *p, i64 size) { - assert(p != NULL); - assert(size >= 0); +kit_input_buffer_t kit_ib_wrap(is_handle_t upstream, + kit_allocator_t *alloc) { + kit_input_buffer_t buf; + memset(&buf, 0, sizeof buf); - internal_buffer_t *buf = (internal_buffer_t *) p; - i64 offset = buf->data.size; + buf.upstream = upstream; + DA_INIT(buf.data, 0, alloc); - if (offset < size) { - DA_RESIZE(buf->data, size); - kit_str_t destination = { .size = size - offset, - .values = buf->data.values + offset }; - i64 n = KIT_IS_READ(buf->upstream, destination); - DA_RESIZE(buf->data, offset + n); - } + return buf; } -static i64 kit_buf_read_(void *p, i64 offset, kit_str_t destination) { - internal_buffer_t *buf = (internal_buffer_t *) p; - i64 n = destination.size < buf->data.size - offset - ? destination.size - : buf->data.size - offset; - memcpy(destination.values, buf->data.values + offset, n); - return n; +void kit_ib_destroy(kit_input_buffer_t *buf) { + assert(buf != NULL); + if (buf == NULL) + return; + + DA_DESTROY(buf->data); + memset(buf, 0, sizeof *buf); } -kit_ib_t kit_ib_wrap(kit_is_handle_t upstream, - kit_allocator_t *alloc) { - kit_ib_t buf; - memset(&buf, 0, sizeof buf); - buf.status = KIT_OK; - DA_INIT(buf.data, 0, alloc); - buf.internal = kit_buf_init_(upstream, alloc); - if (buf.internal == NULL) - buf.status = KIT_ERROR_BAD_ALLOC; - return buf; +kit_ib_token_t kit_ib_token(kit_input_buffer_t *buf) { + return (kit_ib_token_t) { + .status = KIT_OK, .offset = 0, .size = 0, .buffer = buf + }; } -kit_ib_t kit_ib_copy(kit_ib_t buf) { - kit_ib_t next; - memset(&next, 0, sizeof next); +kit_str_t kit_ib_str(kit_ib_token_t tok) { + assert(tok.buffer != NULL); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } + if (tok.buffer == NULL || tok.buffer->data.values == NULL) + return (str_t) { .size = 0, .values = NULL }; - kit_buf_acquire_(buf.internal); + return (str_t) { .size = tok.size, + .values = tok.buffer->data.values + tok.offset }; +} - next.offset = buf.offset; - next.internal = buf.internal; +kit_ib_token_t kit_ib_read(kit_ib_token_t tok, i64 size) { + assert(tok.buffer != NULL); - return next; -} + kit_ib_token_t next = tok; -kit_ib_t kit_ib_read(kit_ib_t buf, i64 size) { - kit_ib_t next; - memset(&next, 0, sizeof next); + next.offset = tok.offset + tok.size; + next.size = 0; - if (buf.status != KIT_OK) { - next.status = buf.status; + if (tok.status != KIT_OK) + return next; + + if (tok.buffer == NULL) { + next.status = KIT_ERROR_INVALID_ARGUMENT; return next; } - kit_buf_acquire_(buf.internal); - kit_buf_adjust_(buf.internal, buf.offset + size); + s32 s = kit_buf_adjust_(tok.buffer, tok.offset + tok.size + size); + + if (s != KIT_OK) { + next.status = s; + return next; + } - DA_INIT(next.data, size, kit_buf_alloc_(buf.internal)); - if (next.data.size != size) - next.status = KIT_ERROR_BAD_ALLOC; + assert(tok.buffer->data.values != NULL); - kit_str_t destination = { .size = next.data.size, - .values = next.data.values }; - i64 n = kit_buf_read_(buf.internal, buf.offset, destination); - next.offset = buf.offset + n; - next.internal = buf.internal; + if (tok.buffer->data.values == NULL) { + next.status = KIT_ERROR_INTERNAL; + return next; + } - DA_RESIZE(next.data, n); - if (next.data.size != n) - next.status = KIT_ERROR_BAD_ALLOC; + next.size = size < tok.buffer->data.size - tok.offset - tok.size + ? size + : tok.buffer->data.size - tok.offset - tok.size; return next; } -kit_ib_t kit_ib_any(kit_ib_t buf, kit_str_t data) { - kit_ib_t next; - memset(&next, 0, sizeof next); +#define IB_CACHE_INIT_(res_) \ + str_builder_t cache_dynamic; \ + memset(&cache_dynamic, 0, sizeof cache_dynamic); \ + char cache_static[KIT_IB_CACHE_SIZE]; \ + \ + do { \ + if (data.size > 0) { \ + if (data.size < KIT_IB_CACHE_SIZE) { \ + memcpy(cache_static, data.values, data.size); \ + data.values = cache_static; \ + } else { \ + DA_INIT(cache_dynamic, data.size, tok.buffer->data.alloc); \ + if (cache_dynamic.size != data.size) { \ + (res_).status |= KIT_ERROR_BAD_ALLOC; \ + return (res_); \ + } \ + memcpy(cache_dynamic.values, data.values, data.size); \ + data.values = cache_dynamic.values; \ + } \ + } \ + } while (0) + +#define IB_CACHE_CLEANUP_() \ + do { \ + if (cache_dynamic.values != NULL) \ + DA_DESTROY(cache_dynamic); \ + } while (0) + +kit_ib_token_t kit_ib_any(kit_ib_token_t tok, str_t data) { + assert(tok.buffer != NULL); + + kit_ib_token_t next = tok; + + next.offset = tok.offset + tok.size; + next.size = 0; + + if (tok.status != KIT_OK) + return next; - if (buf.status != KIT_OK) { - next.status = buf.status; + if (tok.buffer == NULL) { + next.status = KIT_ERROR_INVALID_ARGUMENT; return next; } - kit_buf_acquire_(buf.internal); - - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); + IB_CACHE_INIT_(next); - i64 size = 0; + for (;; ++next.size) { + s32 s = kit_buf_adjust_(tok.buffer, + tok.offset + tok.size + next.size + 1); - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); + if (s != KIT_OK) { + next.status = s; + return next; + } - DA_RESIZE(next.data, size + 1); + assert(tok.buffer->data.values != NULL); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; + if (tok.buffer->data.values == NULL) { + next.status = KIT_ERROR_INTERNAL; return next; } - kit_str_t destination = { .size = 1, - .values = next.data.values + size }; - i64 n = kit_buf_read_(buf.internal, buf.offset + size, - destination); - - if (n != 1) + if (tok.offset + tok.size + next.size >= tok.buffer->data.size) break; i8 found = 0; for (i64 i = 0; i < data.size; i++) - if (data.values[i] == destination.values[0]) { + if (data.values[i] == + tok.buffer->data.values[next.offset + next.size]) { found = 1; break; } @@ -179,54 +183,53 @@ kit_ib_t kit_ib_any(kit_ib_t buf, kit_str_t data) { break; } - next.offset = buf.offset + size; - next.internal = buf.internal; - - DA_RESIZE(next.data, size); - if (next.data.size != size) - next.status = KIT_ERROR_BAD_ALLOC; + IB_CACHE_CLEANUP_(); return next; } -kit_ib_t kit_ib_none(kit_ib_t buf, kit_str_t data) { - kit_ib_t next; - memset(&next, 0, sizeof next); +kit_ib_token_t kit_ib_none(kit_ib_token_t tok, str_t data) { + assert(tok.buffer != NULL); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } + kit_ib_token_t next = tok; - kit_buf_acquire_(buf.internal); + next.offset = tok.offset + tok.size; + next.size = 0; - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); + if (tok.status != KIT_OK) + return next; - i64 size = 0; + if (tok.buffer == NULL) { + next.status = KIT_ERROR_INVALID_ARGUMENT; + return next; + } - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); + IB_CACHE_INIT_(next); - DA_RESIZE(next.data, size + 1); + for (;; ++next.size) { + s32 s = kit_buf_adjust_(tok.buffer, + tok.offset + tok.size + next.size + 1); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; + if (s != KIT_OK) { + next.status = s; return next; } - kit_str_t destination = { .size = 1, - .values = next.data.values + size }; - i64 n = kit_buf_read_(buf.internal, buf.offset + size, - destination); + assert(tok.buffer->data.values != NULL); - if (n != 1) + if (tok.buffer->data.values == NULL) { + next.status = KIT_ERROR_INTERNAL; + return next; + } + + if (tok.offset + tok.size + next.size >= tok.buffer->data.size) break; i8 found = 0; for (i64 i = 0; i < data.size; i++) - if (data.values[i] == destination.values[0]) { + if (data.values[i] == + tok.buffer->data.values[next.offset + next.size]) { found = 1; break; } @@ -235,125 +238,123 @@ kit_ib_t kit_ib_none(kit_ib_t buf, kit_str_t data) { break; } - next.offset = buf.offset + size; - next.internal = buf.internal; - - DA_RESIZE(next.data, size); - if (next.data.size != size) - next.status = KIT_ERROR_BAD_ALLOC; + IB_CACHE_CLEANUP_(); return next; } -kit_ib_t kit_ib_exact(kit_ib_t buf, kit_str_t data) { - kit_ib_t res = kit_ib_read(buf, data.size); - if (!AR_EQUAL(res.data, data)) - res.status = KIT_ERROR_INTERNAL; +kit_ib_token_t kit_ib_exact(kit_ib_token_t tok, str_t data) { + kit_ib_token_t res = tok; + + res.offset = tok.offset + tok.size; + res.size = 0; + + IB_CACHE_INIT_(res); + + res = kit_ib_read(tok, data.size); + if (!AR_EQUAL(kit_ib_str(res), data)) + res.status = KIT_PARSING_FAILED; + + IB_CACHE_CLEANUP_(); + return res; } -kit_ib_t kit_ib_until(kit_ib_t buf, kit_str_t data) { - kit_ib_t next; - memset(&next, 0, sizeof next); +kit_ib_token_t kit_ib_until(kit_ib_token_t tok, str_t data) { + assert(tok.buffer != NULL); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } + kit_ib_token_t next = tok; - kit_buf_acquire_(buf.internal); + next.offset = tok.offset + tok.size; + next.size = 0; - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); + if (tok.status != KIT_OK) + return next; - i64 size = 0; + if (tok.buffer == NULL) { + next.status = KIT_ERROR_INVALID_ARGUMENT; + return next; + } - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); + IB_CACHE_INIT_(next); - DA_RESIZE(next.data, size + 1); + for (;; ++next.size) { + s32 s = kit_buf_adjust_(tok.buffer, + tok.offset + tok.size + next.size + 1); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; + if (s != KIT_OK) { + next.status = s; return next; } - kit_str_t destination = { .size = 1, - .values = next.data.values + size }; - i64 n = kit_buf_read_(buf.internal, buf.offset + size, - destination); + assert(tok.buffer->data.values != NULL); - if (n != 1) + if (tok.buffer->data.values == NULL) { + next.status = KIT_ERROR_INTERNAL; + return next; + } + + if (tok.offset + tok.size + next.size >= tok.buffer->data.size) break; - if (size + 1 >= data.size && - AR_EQUAL(kit_str(data.size, - next.data.values + (size + 1 - data.size)), + if (next.size + 1 >= data.size && + AR_EQUAL(kit_str(data.size, tok.buffer->data.values + + (next.offset + next.size + 1 - + data.size)), data)) { - size -= data.size - 1; + next.size -= data.size - 1; break; } } - next.offset = buf.offset + size; - next.internal = buf.internal; - - DA_RESIZE(next.data, size); - if (next.data.size != size) - next.status = KIT_ERROR_BAD_ALLOC; + IB_CACHE_CLEANUP_(); return next; } -kit_ib_t kit_ib_while(kit_ib_t buf, - kit_ib_read_condition_fn condition, - void *context) { - kit_ib_t next; - memset(&next, 0, sizeof next); +kit_ib_token_t kit_ib_while(kit_ib_token_t tok, + kit_ib_read_condition_fn condition, + void *context) { + assert(tok.buffer != NULL); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } + kit_ib_token_t next = tok; - kit_buf_acquire_(buf.internal); + next.offset = tok.offset + tok.size; + next.size = 0; + + if (tok.status != KIT_OK) + return next; - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); + if (tok.buffer == NULL) { + next.status = KIT_ERROR_INVALID_ARGUMENT; + return next; + } - i64 size = 0; + for (;; ++next.size) { + s32 s = kit_buf_adjust_(tok.buffer, + tok.offset + tok.size + next.size + 1); - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); + if (s != KIT_OK) { + next.status = s; + return next; + } - DA_RESIZE(next.data, size + 1); + assert(tok.buffer->data.values != NULL); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; + if (tok.buffer->data.values == NULL) { + next.status = KIT_ERROR_INTERNAL; return next; } - kit_str_t destination = { .size = 1, - .values = next.data.values + size }; - i64 n = kit_buf_read_(buf.internal, buf.offset + size, - destination); + if (tok.offset + tok.size + next.size >= tok.buffer->data.size) + break; - kit_str_t data = { .size = size + 1, .values = next.data.values }; - if (n != 1 || condition == NULL || condition(data, context) == 0) + if (condition == NULL || + !condition(kit_str(next.size + 1, + tok.buffer->data.values + next.offset), + context)) break; } - next.offset = buf.offset + size; - next.internal = buf.internal; - - DA_RESIZE(next.data, size); - if (next.data.size != size) - next.status = KIT_ERROR_BAD_ALLOC; - return next; } - -void kit_ib_destroy(kit_ib_t buf) { - kit_buf_release_(buf.internal); - DA_DESTROY(buf.data); -} diff --git a/source/kit/input_buffer.h b/source/kit/input_buffer.h index a40ec99..2a7c8a7 100644 --- a/source/kit/input_buffer.h +++ b/source/kit/input_buffer.h @@ -10,42 +10,46 @@ extern "C" { #endif typedef struct { - kit_status_t status; - i64 offset; - void *internal; + kit_is_handle_t upstream; kit_str_builder_t data; -} kit_ib_t; +} kit_input_buffer_t; -typedef i8 (*kit_ib_read_condition_fn)(kit_str_t data, void *context); +typedef struct { + s32 status; + i64 offset; + i64 size; + kit_input_buffer_t *buffer; +} kit_ib_token_t; + +typedef b8 (*kit_ib_read_condition_fn)(kit_str_t data, void *context); -kit_ib_t kit_ib_wrap(kit_is_handle_t upstream, - kit_allocator_t *alloc); +kit_input_buffer_t kit_ib_wrap(kit_is_handle_t upstream, + kit_allocator_t *alloc); -kit_ib_t kit_ib_copy(kit_ib_t buf); +void kit_ib_destroy(kit_input_buffer_t *buf); -kit_ib_t kit_ib_read(kit_ib_t buf, i64 size); +kit_ib_token_t kit_ib_token(kit_input_buffer_t *buf); -kit_ib_t kit_ib_any(kit_ib_t buf, kit_str_t data); +kit_str_t kit_ib_str(kit_ib_token_t tok); -kit_ib_t kit_ib_none(kit_ib_t buf, kit_str_t data); +kit_ib_token_t kit_ib_read(kit_ib_token_t tok, i64 size); -kit_ib_t kit_ib_exact(kit_ib_t buf, kit_str_t data); +kit_ib_token_t kit_ib_any(kit_ib_token_t tok, kit_str_t data); -kit_ib_t kit_ib_until(kit_ib_t buf, kit_str_t data); +kit_ib_token_t kit_ib_none(kit_ib_token_t tok, kit_str_t data); -kit_ib_t kit_ib_while(kit_ib_t buf, - kit_ib_read_condition_fn condition, - void *context); +kit_ib_token_t kit_ib_exact(kit_ib_token_t tok, kit_str_t data); -void kit_ib_destroy(kit_ib_t buf); +kit_ib_token_t kit_ib_until(kit_ib_token_t tok, kit_str_t data); -#define KIT_IB_WRAP(upstream) kit_ib_wrap(upstream, NULL) +kit_ib_token_t kit_ib_while(kit_ib_token_t buf, + kit_ib_read_condition_fn condition, + void *context); -#define KIT_IB_SKIP(buf_, proc_, ...) \ - do { \ - kit_ib_t temp_buf_ = (buf_); \ - (buf_) = proc_((buf_), __VA_ARGS__); \ - kit_ib_destroy((temp_buf_)); \ +#define KIT_IB_SKIP(buf_, proc_, ...) \ + do { \ + kit_ib_token_t temp_buf_ = (buf_); \ + (buf_) = proc_((buf_), __VA_ARGS__); \ } while (0) #ifdef __cplusplus @@ -53,19 +57,19 @@ void kit_ib_destroy(kit_ib_t buf); #endif #ifndef KIT_DISABLE_SHORT_NAMES -# define ib_t kit_ib_t +# define input_buffer_t kit_input_buffer_t +# define ib_token_t kit_ib_token_t # define ib_read_condition_fn kit_ib_read_condition_fn # define ib_wrap kit_ib_wrap -# define ib_copy kit_ib_copy +# define ib_destroy kit_ib_destroy +# define ib_token kit_ib_token +# define ib_str kit_ib_str # define ib_read kit_ib_read # define ib_any kit_ib_any # define ib_none kit_ib_none # define ib_exact kit_ib_exact # define ib_until kit_ib_until # define ib_while kit_ib_while -# define ib_destroy kit_ib_destroy - -# define IB_WRAP KIT_IB_WRAP # define IB_SKIP KIT_IB_SKIP #endif diff --git a/source/kit/math.h b/source/kit/math.h index f4ab33a..3a55276 100644 --- a/source/kit/math.h +++ b/source/kit/math.h @@ -13,7 +13,7 @@ // TODO // - Gamma correction. -// +// - Custom prefixes #ifdef __cplusplus extern "C" { diff --git a/source/kit/secure_random.c b/source/kit/secure_random.c index 02b168b..2565f6f 100644 --- a/source/kit/secure_random.c +++ b/source/kit/secure_random.c @@ -14,7 +14,7 @@ # include #endif -kit_status_t kit_secure_random(i64 size, void *data) { +s32 kit_secure_random(i64 size, void *data) { assert(size >= 0); assert(data != NULL); diff --git a/source/kit/secure_random.h b/source/kit/secure_random.h index 54a40e0..fbee23d 100644 --- a/source/kit/secure_random.h +++ b/source/kit/secure_random.h @@ -7,7 +7,7 @@ extern "C" { #endif -kit_status_t kit_secure_random(i64 size, void *data); +s32 kit_secure_random(i64 size, void *data); #ifdef __cplusplus } diff --git a/source/kit/shared_memory.h b/source/kit/shared_memory.h index bd910cb..0c0c1ce 100644 --- a/source/kit/shared_memory.h +++ b/source/kit/shared_memory.h @@ -13,9 +13,9 @@ extern "C" { #endif typedef struct { - kit_status_t status; - i64 size; - u8 *bytes; + s32 status; + i64 size; + u8 *bytes; #if defined(_WIN32) && !defined(__CYGWIN__) void *_handle; #else @@ -31,8 +31,8 @@ enum { kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, i32 mode); -kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem); -kit_status_t kit_shared_memory_clean(kit_str_t name); +s32 kit_shared_memory_close(kit_shared_memory_t *mem); +s32 kit_shared_memory_clean(kit_str_t name); #ifdef __cplusplus } diff --git a/source/kit/shared_memory.posix.c b/source/kit/shared_memory.posix.c index e109e2a..fa0db98 100644 --- a/source/kit/shared_memory.posix.c +++ b/source/kit/shared_memory.posix.c @@ -81,13 +81,13 @@ kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, return mem; } -kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem) { +s32 kit_shared_memory_close(kit_shared_memory_t *mem) { assert(mem != NULL); if (mem == NULL) return KIT_ERROR_INVALID_ARGUMENT; - kit_status_t status = KIT_OK; + s32 status = KIT_OK; if (munmap(mem->bytes, mem->size) != 0) status |= KIT_ERROR_UNMAP_FAILED; @@ -97,7 +97,7 @@ kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem) { return status; } -kit_status_t kit_shared_memory_clean(kit_str_t name) { +s32 kit_shared_memory_clean(kit_str_t name) { assert(name.size > 0); assert(name.size + 1 <= NAME_MAX); assert(name.values != NULL); diff --git a/source/kit/shared_memory.win32.c b/source/kit/shared_memory.win32.c index 34bb276..61b7317 100644 --- a/source/kit/shared_memory.win32.c +++ b/source/kit/shared_memory.win32.c @@ -67,7 +67,7 @@ kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, return mem; } -kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem) { +s32 kit_shared_memory_close(kit_shared_memory_t *mem) { assert(mem != NULL); i32 status = KIT_OK; @@ -80,7 +80,7 @@ kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem) { return status; } -kit_status_t kit_shared_memory_clean(kit_str_t name) { +s32 kit_shared_memory_clean(kit_str_t name) { // Do nothing. // diff --git a/source/kit/sockets.h b/source/kit/sockets.h index a9e2754..1fe2a3d 100644 --- a/source/kit/sockets.h +++ b/source/kit/sockets.h @@ -23,7 +23,7 @@ extern "C" { # define socket_t SOCKET # define socklen_t i32 -static kit_status_t kit_sockets_init(void) { +static s32 kit_sockets_init(void) { WSADATA data; memset(&data, 0, sizeof data); WORD version = MAKEWORD(2, 2); @@ -32,7 +32,7 @@ static kit_status_t kit_sockets_init(void) { : KIT_ERROR_SOCKETS_STARTUP_FAILED; } -static kit_status_t kit_sockets_cleanup(void) { +static s32 kit_sockets_cleanup(void) { WSACleanup(); return KIT_OK; } @@ -69,12 +69,12 @@ static i32 kit_socket_set_nonblocking(socket_t s) { # define closesocket close # define INVALID_SOCKET -1 -static kit_status_t kit_sockets_init(void) { +static s32 kit_sockets_init(void) { signal(SIGPIPE, SIG_IGN); return KIT_OK; } -static kit_status_t kit_sockets_cleanup(void) { +static s32 kit_sockets_cleanup(void) { return KIT_OK; } diff --git a/source/kit/status.h b/source/kit/status.h index be54aad..6316704 100644 --- a/source/kit/status.h +++ b/source/kit/status.h @@ -5,7 +5,7 @@ enum { KIT_OK = 0, - KIT_ERROR_INTERNAL = 1, + KIT_PARSING_FAILED = 1, KIT_ERROR_BAD_ALLOC = (1 << 1), KIT_ERROR_INVALID_ARGUMENT = (1 << 2), KIT_ERROR_MKDIR_FAILED = (1 << 3), @@ -27,9 +27,8 @@ enum { KIT_ERROR_SYNC_FAILED = (1 << 19), KIT_ERROR_CLOSE_FAILED = (1 << 20), KIT_ERROR_RESOURCE_UNAVAILABLE = (1 << 21), - KIT_ERROR_NOT_IMPLEMENTED = (1 << 30), + KIT_ERROR_INTERNAL = (1 << 30), + KIT_ERROR_NOT_IMPLEMENTED = -1, }; -typedef i32 kit_status_t; - #endif diff --git a/source/kit/string_builder.h b/source/kit/string_builder.h index 322f6e2..3f244e8 100644 --- a/source/kit/string_builder.h +++ b/source/kit/string_builder.h @@ -31,8 +31,7 @@ static kit_str_builder_t kit_str_build(kit_str_t s, return builder; } -static kit_status_t kit_str_append(kit_str_builder_t *a, - kit_str_t b) { +static s32 kit_str_append(kit_str_builder_t *a, kit_str_t b) { assert(a != NULL); if (a == NULL) return KIT_ERROR_INVALID_ARGUMENT; diff --git a/source/kit/types.h b/source/kit/types.h index b83ba39..cbb9a71 100644 --- a/source/kit/types.h +++ b/source/kit/types.h @@ -5,17 +5,32 @@ # define _GNU_SOURCE #endif +// signed integers +// typedef signed char i8; typedef signed short i16; typedef signed int i32; typedef signed long long i64; +// unsigned integers +// typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; +// floats +// typedef float f32; typedef double f64; +// chars +// +typedef signed char c8; +typedef signed int c32; + +typedef signed char b8; // 8-bit boolean +typedef signed int b32; // 32-bit boolean +typedef signed int s32; // 32-bit status + #endif diff --git a/source/kit/unival.h b/source/kit/unival.h index a87a763..905430b 100644 --- a/source/kit/unival.h +++ b/source/kit/unival.h @@ -45,17 +45,17 @@ struct kit_uv_data { }; typedef struct { - kit_status_t status; + s32 status; kit_unival_t *value; } kit_uv_decode_result_t; typedef struct { - kit_status_t status; + s32 status; kit_uv_bytes_t value; } kit_uv_encode_result_t; typedef struct { - kit_status_t status; + s32 status; kit_str_builder_t value; } kit_uv_print_result_t; diff --git a/source/kit/xml.c b/source/kit/xml.c index c62ee82..399cc5f 100644 --- a/source/kit/xml.c +++ b/source/kit/xml.c @@ -4,198 +4,178 @@ #include typedef struct { - ib_t last; + ib_token_t last; kit_str_builder_t text; kit_da_xml_t tags; } kit_xml_intermediate_t; -static kit_status_t kit_xml_unescape_(str_builder_t *str) { - assert(str != NULL); +static s32 kit_xml_alloc_and_unescape_(str_builder_t *dst, str_t str, + kit_allocator_t *alloc) { + assert(dst != NULL); + assert(str.size == 0 || str.values != NULL); - str_builder_t buf; - DA_INIT(buf, str->size, str->alloc); - buf.size = 0; + if (dst == NULL) + return KIT_ERROR_INTERNAL; + if (str.size != 0 && str.values == NULL) + return KIT_ERROR_INTERNAL; - for (i64 i = 0; i < str->size; i++) - if (str->values[i] != '&') - buf.values[buf.size++] = str->values[i]; + DA_INIT(*dst, str.size, alloc); + + if (dst->size != str.size) + return KIT_ERROR_BAD_ALLOC; + + dst->size = 0; + + for (i64 i = 0; i < str.size; i++) + if (str.values[i] != '&') + dst->values[dst->size++] = str.values[i]; else { i64 n = 1; - while (i + n < str->size && str->values[i + n] != ';') n++; - if (i + n >= str->size) { - DA_DESTROY(buf); - return KIT_ERROR_INTERNAL; + while (i + n < str.size && str.values[i + n] != ';') n++; + if (i + n >= str.size) { + DA_DESTROY(*dst); + return KIT_PARSING_FAILED; } - if (n == 3 && memcmp(str->values + i, "<", 4) == 0) - buf.values[buf.size++] = '<'; - else if (n == 3 && memcmp(str->values + i, ">", 4) == 0) - buf.values[buf.size++] = '>'; - else if (n == 4 && memcmp(str->values + i, "&", 5) == 0) - buf.values[buf.size++] = '&'; - else if (n == 5 && memcmp(str->values + i, """, 6) == 0) - buf.values[buf.size++] = '"'; - else if (n == 5 && memcmp(str->values + i, "'", 6) == 0) - buf.values[buf.size++] = '\''; + if (n == 3 && memcmp(str.values + i, "<", 4) == 0) + dst->values[dst->size++] = '<'; + else if (n == 3 && memcmp(str.values + i, ">", 4) == 0) + dst->values[dst->size++] = '>'; + else if (n == 4 && memcmp(str.values + i, "&", 5) == 0) + dst->values[dst->size++] = '&'; + else if (n == 5 && memcmp(str.values + i, """, 6) == 0) + dst->values[dst->size++] = '"'; + else if (n == 5 && memcmp(str.values + i, "'", 6) == 0) + dst->values[dst->size++] = '\''; else { - DA_DESTROY(buf); - return KIT_ERROR_INTERNAL; + DA_DESTROY(*dst); + return KIT_PARSING_FAILED; } i += n; } - DA_DESTROY(*str); - *str = buf; - return KIT_OK; } -static ib_t kit_xml_parse_text_(ib_t begin) { - ib_t text = ib_until(begin, SZ("<")); - ib_t last = ib_copy(text); +static ib_token_t kit_xml_parse_text_(ib_token_t begin, + str_builder_t *dst) { + ib_token_t last = ib_until(begin, SZ("<")); + + DA_RESIZE(*dst, last.size); + + assert(dst->size == last.size); + if (dst->size != last.size) + last.status |= KIT_ERROR_BAD_ALLOC; + else if (last.size > 0) + memcpy(dst->values, ib_str(last).values, last.size); for (;;) { - ib_t comment_open = ib_exact(last, SZ("")); - ib_t comment_close = ib_exact(comment_text, SZ("-->")); - ib_t next_text = ib_until(comment_close, SZ("<")); + ib_token_t comment_text = ib_until(comment_open, SZ("-->")); + ib_token_t comment_close = ib_exact(comment_text, SZ("-->")); + ib_token_t next_text = ib_until(comment_close, SZ("<")); - if (next_text.status == KIT_OK && next_text.data.size > 0) { - i64 n = text.data.size; - DA_RESIZE(text.data, n + next_text.data.size); + if (next_text.status == KIT_OK && next_text.size > 0) { + i64 n = dst->size; + DA_RESIZE(*dst, n + next_text.size); - assert(text.data.size == n + next_text.data.size); - if (text.data.size != n + next_text.data.size) - next_text.status = KIT_ERROR_BAD_ALLOC; + assert(dst->size == n + next_text.size); + if (dst->size != n + next_text.size) + next_text.status |= KIT_ERROR_BAD_ALLOC; else - memcpy(text.data.values + n, next_text.data.values, - next_text.data.size); + memcpy(dst->values + n, ib_str(next_text).values, + ib_str(next_text).size); } - ib_destroy(last); - last = ib_copy(next_text); - - ib_destroy(comment_open); - ib_destroy(comment_text); - ib_destroy(comment_close); - ib_destroy(next_text); + last = next_text; } - // move - DA_DESTROY(last.data); - last.data = text.data; - memset(&text.data, 0, sizeof text.data); - - kit_status_t s = kit_xml_unescape_(&last.data); - if (s != KIT_OK) - last.status = s; - - ib_destroy(text); - return last; } -static ib_t kit_xml_parse_string_(ib_t begin) { - ib_t quotes_open = ib_exact(begin, SZ("\"")); - ib_t apostr_open = ib_exact(begin, SZ("'")); - - ib_t open = quotes_open.status == KIT_OK ? quotes_open - : apostr_open; - - ib_t text = ib_until(open, WRAP_STR(open.data)); - ib_t close = ib_exact(text, WRAP_STR(open.data)); +static ib_token_t kit_xml_parse_string_(ib_token_t begin, + ib_token_t *value) { + assert(value != NULL); + if (value == NULL) { + begin.status |= KIT_ERROR_INTERNAL; + return begin; + } - // move - DA_DESTROY(close.data); - close.data = text.data; - memset(&text.data, 0, sizeof text.data); + ib_token_t quotes_open = ib_exact(begin, SZ("\"")); + ib_token_t apostr_open = ib_exact(begin, SZ("'")); - kit_status_t s = kit_xml_unescape_(&close.data); - if (s == KIT_OK) - close.status = s; + ib_token_t open = quotes_open.status == KIT_OK ? quotes_open + : apostr_open; - ib_destroy(quotes_open); - ib_destroy(apostr_open); - ib_destroy(text); + *value = ib_until(open, ib_str(open)); + ib_token_t close = ib_exact(*value, ib_str(open)); return close; } static kit_xml_intermediate_t kit_xml_parse_buf_( - ib_t begin, kit_allocator_t *alloc) { + ib_token_t begin, kit_allocator_t *alloc) { kit_xml_intermediate_t res; memset(&res, 0, sizeof res); - ib_t last, spaces; + ib_token_t last, spaces; memset(&last, 0, sizeof last); memset(&spaces, 0, sizeof spaces); - ib_t tag_text = kit_xml_parse_text_(begin); - last = ib_copy(tag_text); + str_builder_t tag_text_string; + str_builder_t tag_tail_string; + DA_INIT(tag_text_string, 0, alloc); + DA_INIT(tag_tail_string, 0, alloc); + + ib_token_t tag_text = kit_xml_parse_text_(begin, &tag_text_string); + last = tag_text; DA_INIT(res.tags, 0, alloc); for (;;) { - ib_t tagend_open = ib_exact(last, SZ("")); - ib_destroy(spaces); + spaces = ib_any(last, SZ(" \t\r\n")); + ib_token_t tag_name = ib_none(spaces, SZ(" \t\r\n/>")); DA_INIT(tag.properties, 0, alloc); - ib_destroy(last); - last = ib_copy(tag_name); + last = tag_name; for (;;) { - spaces = ib_any(last, SZ(" \t\r\n")); - ib_t property = ib_none(spaces, SZ(" \t\r\n=?/>")); - ib_destroy(spaces); + spaces = ib_any(last, SZ(" \t\r\n")); + ib_token_t property = ib_none(spaces, SZ(" \t\r\n=?/>")); - if (property.status != KIT_OK || property.data.size == 0) { - ib_destroy(property); + if (property.status != KIT_OK || property.size == 0) break; - } - spaces = ib_any(property, SZ(" \t\r\n")); - ib_t equals = ib_exact(spaces, SZ("=")); - ib_destroy(spaces); - spaces = ib_any(equals, SZ(" \t\r\n")); - ib_t value = kit_xml_parse_string_(spaces); - ib_destroy(spaces); + spaces = ib_any(property, SZ(" \t\r\n")); + ib_token_t equals = ib_exact(spaces, SZ("=")); + spaces = ib_any(equals, SZ(" \t\r\n")); - ib_destroy(last); - last = ib_copy(value); + ib_token_t value; + last = kit_xml_parse_string_(spaces, &value); if (last.status == KIT_OK) { i64 n = tag.properties.size; @@ -203,77 +183,56 @@ static kit_xml_intermediate_t kit_xml_parse_buf_( assert(tag.properties.size == n + 1); if (tag.properties.size != n + 1) { - last.status = KIT_ERROR_BAD_ALLOC; + last.status |= KIT_ERROR_BAD_ALLOC; DA_DESTROY(tag.properties); } else { - // move - tag.properties.values[n].name = property.data; - memset(&property.data, 0, sizeof property.data); - - // move - tag.properties.values[n].value = value.data; - memset(&value.data, 0, sizeof value.data); + last.status |= kit_xml_alloc_and_unescape_( + &tag.properties.values[n].name, ib_str(property), + alloc); + last.status |= kit_xml_alloc_and_unescape_( + &tag.properties.values[n].value, ib_str(value), alloc); } } - - ib_destroy(property); - ib_destroy(equals); - ib_destroy(value); } - spaces = ib_any(last, SZ(" \t\r\n")); - if (tag.is_declaration) { - ib_t tag_decl_close = ib_exact(spaces, SZ("?>")); - ib_destroy(spaces); + ib_token_t tag_decl_close = ib_exact(spaces, SZ("?>")); - ib_destroy(last); last = tag_decl_close; DA_INIT(tag.text, 0, alloc); DA_INIT(tag.children, 0, alloc); } else { - ib_t tag_close = ib_exact(spaces, SZ(">")); - ib_t tag_close_empty = ib_exact(spaces, SZ("/>")); - ib_destroy(spaces); + ib_token_t tag_close = ib_exact(spaces, SZ(">")); + ib_token_t tag_close_empty = ib_exact(spaces, SZ("/>")); if (tag_close.status == KIT_OK) { kit_xml_intermediate_t im = kit_xml_parse_buf_(tag_close, alloc); - tag.text = im.text; - tag.children = im.tags; - - tagend_open = ib_exact(im.last, SZ("")); - ib_destroy(spaces); - ib_destroy(tagend_open); - ib_destroy(tagend_name); - - ib_destroy(last); + + tag.text = im.text; + tag.children = im.tags; + + tagend_open = ib_exact(im.last, SZ("")); + last = tagend_close; } else if (tag_close_empty.status == KIT_OK) { - ib_destroy(last); - last = ib_copy(tag_close_empty); + last = tag_close_empty; DA_INIT(tag.text, 0, alloc); DA_INIT(tag.children, 0, alloc); } else - last.status = KIT_ERROR_INTERNAL; - - ib_destroy(tag_close); - ib_destroy(tag_close_empty); + last.status |= KIT_PARSING_FAILED; } - ib_t tag_tail = kit_xml_parse_text_(last); + ib_token_t tag_tail = kit_xml_parse_text_(last, &tag_tail_string); - ib_destroy(last); - last = ib_copy(tag_tail); + last = tag_tail; if (last.status == KIT_OK) { i64 n = res.tags.size; @@ -281,25 +240,18 @@ static kit_xml_intermediate_t kit_xml_parse_buf_( assert(res.tags.size == n + 1); if (res.tags.size != n + 1) { - last.status = KIT_ERROR_BAD_ALLOC; + last.status |= KIT_ERROR_BAD_ALLOC; xml_destroy(&tag); } else { - // move - tag.tag = tag_name.data; - memset(&tag_name.data, 0, sizeof tag_name.data); - - // move - tag.tail = tag_tail.data; - memset(&tag_tail.data, 0, sizeof tag_tail.data); + last.status |= kit_xml_alloc_and_unescape_( + &tag.tag, ib_str(tag_name), alloc); + last.status |= kit_xml_alloc_and_unescape_( + &tag.tail, WRAP_STR(tag_tail_string), alloc); res.tags.values[n] = tag; } } else xml_destroy(&tag); - - ib_destroy(tag_open); - ib_destroy(tag_name); - ib_destroy(tag_tail); } if (last.status != KIT_OK) { @@ -307,13 +259,12 @@ static kit_xml_intermediate_t kit_xml_parse_buf_( xml_destroy(res.tags.values + i); DA_DESTROY(res.text); DA_DESTROY(res.tags); - } else { - // move - res.text = tag_text.data; - memset(&tag_text.data, 0, sizeof tag_text.data); - } + } else + last.status |= kit_xml_alloc_and_unescape_( + &res.text, WRAP_STR(tag_text_string), alloc); - ib_destroy(tag_text); + DA_DESTROY(tag_text_string); + DA_DESTROY(tag_tail_string); res.last = last; return res; @@ -321,23 +272,25 @@ static kit_xml_intermediate_t kit_xml_parse_buf_( kit_xml_parse_result_t kit_xml_parse(kit_is_handle_t is, kit_allocator_t *alloc) { - ib_t ib = ib_wrap(is, alloc); - kit_xml_intermediate_t im = kit_xml_parse_buf_(ib, alloc); - ib_destroy(ib); + input_buffer_t ib = ib_wrap(is, alloc); + kit_xml_intermediate_t im = kit_xml_parse_buf_(ib_token(&ib), + alloc); kit_xml_parse_result_t res; memset(&res, 0, sizeof res); res.status = im.last.status; - ib_destroy(im.last); - if (res.status != KIT_OK) + if (res.status != KIT_OK) { + ib_destroy(&ib); return res; + } if (im.text.size == 0 && im.tags.size == 1) { res.xml = im.tags.values[0]; DA_DESTROY(im.text); DA_DESTROY(im.tags); + ib_destroy(&ib); return res; } @@ -348,10 +301,14 @@ kit_xml_parse_result_t kit_xml_parse(kit_is_handle_t is, res.xml.text = im.text; res.xml.children = im.tags; + ib_destroy(&ib); return res; } kit_xml_text_t kit_xml_print(kit_xml_t *xml, kit_allocator_t *alloc) { + // TODO + // + assert(xml != NULL); xml_text_t result; @@ -361,8 +318,7 @@ kit_xml_text_t kit_xml_print(kit_xml_t *xml, kit_allocator_t *alloc) { return result; } -static kit_status_t kit_xml_append_text_(str_builder_t *buf, - xml_t *xml) { +static s32 kit_xml_append_text_(str_builder_t *buf, xml_t *xml) { assert(buf != NULL); assert(xml != NULL); @@ -377,8 +333,7 @@ static kit_status_t kit_xml_append_text_(str_builder_t *buf, memcpy(buf->values + n, xml->text.values, xml->text.size); for (i64 i = 0; i < xml->children.size; i++) { - kit_status_t s = kit_xml_append_text_(buf, - xml->children.values + i); + s32 s = kit_xml_append_text_(buf, xml->children.values + i); if (s != KIT_OK) return s; diff --git a/source/kit/xml.h b/source/kit/xml.h index 0bd5744..755a918 100644 --- a/source/kit/xml.h +++ b/source/kit/xml.h @@ -29,12 +29,12 @@ struct kit_xml_ { }; typedef struct { - kit_status_t status; - kit_xml_t xml; + s32 status; + kit_xml_t xml; } kit_xml_parse_result_t; typedef struct { - kit_status_t status; + s32 status; kit_str_builder_t text; } kit_xml_text_t; diff --git a/source/tests/input_buffer.test.c b/source/tests/input_buffer.test.c index b8dc19b..1ec1ad4 100644 --- a/source/tests/input_buffer.test.c +++ b/source/tests/input_buffer.test.c @@ -4,59 +4,54 @@ #include "../kit/test.h" TEST("input buffer read once") { - str_t text = { .size = 3, .values = "foo" }; - is_handle_t in = IS_WRAP_STRING(text); - ib_t first = IB_WRAP(in); + str_t text = { .size = 3, .values = "foo" }; + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); - ib_t second = ib_read(first, 3); + ib_token_t tok = ib_read(ib_token(&buf), 3); - REQUIRE(second.status == KIT_OK); - REQUIRE(second.data.size == 3); - REQUIRE(AR_EQUAL(text, second.data)); + REQUIRE_EQ(tok.status, KIT_OK); + REQUIRE_EQ(tok.size, 3); + REQUIRE(AR_EQUAL(text, ib_str(tok))); - ib_destroy(second); - ib_destroy(first); + ib_destroy(&buf); is_destroy(in); } TEST("input buffer read again") { - str_t text = { .size = 6, .values = "foobar" }; - str_t foo = { .size = 3, .values = "foo" }; - is_handle_t in = IS_WRAP_STRING(text); - ib_t first = IB_WRAP(in); + str_t text = { .size = 6, .values = "foobar" }; + str_t foo = { .size = 3, .values = "foo" }; + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); - ib_t second = ib_read(first, 3); - ib_t third = ib_read(first, 3); + ib_token_t first = ib_read(ib_token(&buf), 3); + ib_token_t second = ib_read(ib_token(&buf), 3); - REQUIRE(AR_EQUAL(foo, second.data)); - REQUIRE(AR_EQUAL(foo, third.data)); + REQUIRE(AR_EQUAL(foo, ib_str(first))); + REQUIRE(AR_EQUAL(foo, ib_str(second))); - ib_destroy(third); - ib_destroy(second); - ib_destroy(first); + ib_destroy(&buf); is_destroy(in); } TEST("input buffer read twice") { - str_t text = { .size = 6, .values = "foobar" }; - str_t foo = { .size = 3, .values = "foo" }; - str_t bar = { .size = 3, .values = "bar" }; - is_handle_t in = IS_WRAP_STRING(text); - ib_t first = IB_WRAP(in); + str_t text = { .size = 6, .values = "foobar" }; + str_t foo = { .size = 3, .values = "foo" }; + str_t bar = { .size = 3, .values = "bar" }; + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); - ib_t second = ib_read(first, 3); - ib_t third = ib_read(second, 3); + ib_token_t first = ib_read(ib_token(&buf), 3); + ib_token_t second = ib_read(first, 3); - REQUIRE(AR_EQUAL(foo, second.data)); - REQUIRE(AR_EQUAL(bar, third.data)); + REQUIRE(AR_EQUAL(foo, ib_str(first))); + REQUIRE(AR_EQUAL(bar, ib_str(second))); - ib_destroy(third); - ib_destroy(second); - ib_destroy(first); + ib_destroy(&buf); is_destroy(in); } -static i8 is_integer_(str_t const data, void *_) { +static b8 is_integer_(str_t const data, void *_) { for (ptrdiff_t i = 0; i < data.size; i++) if (data.values[i] < '0' || data.values[i] > '9') return 0; @@ -64,43 +59,126 @@ static i8 is_integer_(str_t const data, void *_) { } TEST("input buffer read integer once") { - str_t text = { .size = 9, .values = "31415 foo" }; - str_t num = { .size = 5, .values = "31415" }; - is_handle_t in = IS_WRAP_STRING(text); - ib_t first = IB_WRAP(in); + str_t text = { .size = 9, .values = "31415 foo" }; + str_t num = { .size = 5, .values = "31415" }; + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); - ib_t second = ib_while(first, is_integer_, NULL); + ib_token_t tok = ib_while(ib_token(&buf), is_integer_, NULL); - REQUIRE(second.status == KIT_OK); - REQUIRE(second.data.size == 5); - REQUIRE(AR_EQUAL(num, second.data)); + REQUIRE_EQ(tok.status, KIT_OK); + REQUIRE_EQ(tok.size, 5); + REQUIRE(AR_EQUAL(num, ib_str(tok))); - ib_destroy(second); - ib_destroy(first); + ib_destroy(&buf); is_destroy(in); } TEST("input buffer read integer twice") { - str_t text = { .size = 6, .values = "314 15" }; - str_t num_0 = { .size = 3, .values = "314" }; - str_t num_1 = { .size = 2, .values = "15" }; - is_handle_t in = IS_WRAP_STRING(text); - ib_t first = IB_WRAP(in); - - ib_t second = ib_while(first, is_integer_, NULL); - ib_t third = ib_read(second, 1); - ib_t fourth = ib_while(third, is_integer_, NULL); - - REQUIRE(fourth.status == KIT_OK); - REQUIRE(second.data.size == 3); - REQUIRE(fourth.data.size == 2); - REQUIRE(AR_EQUAL(num_0, second.data)); - REQUIRE(AR_EQUAL(num_1, fourth.data)); - - ib_destroy(first); - ib_destroy(second); - ib_destroy(third); - ib_destroy(fourth); + str_t text = { .size = 6, .values = "314 15" }; + str_t num_0 = { .size = 3, .values = "314" }; + str_t num_1 = { .size = 2, .values = "15" }; + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); + + ib_token_t first = ib_while(ib_token(&buf), is_integer_, NULL); + ib_token_t second = ib_read(first, 1); + ib_token_t third = ib_while(second, is_integer_, NULL); + + REQUIRE_EQ(third.status, KIT_OK); + REQUIRE_EQ(first.size, 3); + REQUIRE_EQ(third.size, 2); + REQUIRE(AR_EQUAL(num_0, ib_str(first))); + REQUIRE(AR_EQUAL(num_1, ib_str(third))); + + ib_destroy(&buf); + is_destroy(in); +} + +TEST("input buffer any") { + str_t text = SZ("01234bbdac"); + str_t expect = SZ("01234"); + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); + + ib_token_t tok = ib_any(ib_token(&buf), SZ("01234")); + + REQUIRE_EQ(tok.status, KIT_OK); + REQUIRE(AR_EQUAL(expect, ib_str(tok))); + + ib_destroy(&buf); + is_destroy(in); +} + +TEST("input buffer none") { + str_t text = SZ("01234bbdac"); + str_t expect = SZ("01234"); + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); + + ib_token_t tok = ib_none(ib_token(&buf), SZ("abcd")); + + REQUIRE_EQ(tok.status, KIT_OK); + REQUIRE(AR_EQUAL(expect, ib_str(tok))); + + ib_destroy(&buf); + is_destroy(in); +} + +TEST("input buffer until") { + str_t text = SZ("01234bbdac"); + str_t expect = SZ("01234"); + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); + + ib_token_t tok = ib_none(ib_token(&buf), SZ("bbdac")); + + REQUIRE_EQ(tok.status, KIT_OK); + REQUIRE(AR_EQUAL(expect, ib_str(tok))); + + ib_destroy(&buf); + is_destroy(in); +} + +TEST("input buffer exact success") { + str_t text = SZ("01234bbdac"); + str_t expect = SZ("01234"); + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); + + ib_token_t tok = ib_exact(ib_token(&buf), SZ("01234")); + + REQUIRE_EQ(tok.status, KIT_OK); + REQUIRE(AR_EQUAL(expect, ib_str(tok))); + + ib_destroy(&buf); + is_destroy(in); +} + +TEST("input buffer exact fail") { + str_t text = SZ("01234bbdac"); + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); + + ib_token_t tok = ib_exact(ib_token(&buf), SZ("bbdac")); + + REQUIRE_EQ(tok.status, KIT_PARSING_FAILED); + + ib_destroy(&buf); + is_destroy(in); +} + +TEST("input buffer use after free") { + str_t text = SZ("foobarfoobar"); + is_handle_t in = IS_WRAP_STRING(text); + input_buffer_t buf = ib_wrap(in, NULL); + + ib_token_t first = ib_exact(ib_token(&buf), SZ("foobar")); + ib_token_t second = ib_exact(first, ib_str(first)); + + REQUIRE_EQ(second.status, KIT_OK); + + ib_destroy(&buf); is_destroy(in); } diff --git a/source/tests/xml.test.c b/source/tests/xml.test.c index a3e931d..4c72d28 100644 --- a/source/tests/xml.test.c +++ b/source/tests/xml.test.c @@ -37,7 +37,7 @@ TEST("xml parse tag not closed") { is_handle_t is = IS_WRAP_STRING(SZ("")); xml_parse_result_t res = xml_parse(is, NULL); - REQUIRE_EQ(res.status, KIT_ERROR_INTERNAL); + REQUIRE_EQ(res.status, KIT_PARSING_FAILED); if (res.status == KIT_OK) xml_destroy(&res.xml); @@ -380,7 +380,7 @@ TEST("xml parse invalid escape") { is_handle_t is = IS_WRAP_STRING(SZ("&foobar;")); xml_parse_result_t res = xml_parse(is, NULL); - REQUIRE_EQ(res.status, KIT_ERROR_INTERNAL); + REQUIRE_EQ(res.status, KIT_PARSING_FAILED); if (res.status == KIT_OK) xml_destroy(&res.xml); -- cgit v1.2.3