diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/kit.inl.h | 4697 |
1 files changed, 0 insertions, 4697 deletions
diff --git a/include/kit.inl.h b/include/kit.inl.h deleted file mode 100644 index 50e5030..0000000 --- a/include/kit.inl.h +++ /dev/null @@ -1,4697 +0,0 @@ -// ================================================================ -// -// kit.inl.h -// https://guattari.tech/git/kit -// -// Single header-only cross-platform utility library for C. -// -// ================================================================ -// -// The MIT License -// -// Copyright (c) 2022-2023 Mitya Selivanov -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// ================================================================ -#ifndef KIT_INL_H -#define KIT_INL_H -// ================================================================ -// -// File: source/kit/types.h -// -// ================================================================ -#ifndef KIT_TYPES_H -#define KIT_TYPES_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif -typedef signed char i8; -typedef signed short i16; -typedef signed int i32; -typedef signed long long i64; -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long long u64; -typedef float f32; -typedef double f64; -#endif -// ================================================================ -// -// File: source/kit/status.h -// -// ================================================================ -#ifndef KIT_STATUS_H -#define KIT_STATUS_H -enum { - KIT_OK = 0, - KIT_ERROR_INTERNAL = 1, - KIT_ERROR_BAD_ALLOC = (1 << 1), - KIT_ERROR_INVALID_ARGUMENT = (1 << 2), - KIT_ERROR_MKDIR_FAILED = (1 << 3), - KIT_ERROR_RMDIR_FAILED = (1 << 4), - KIT_ERROR_UNLINK_FAILED = (1 << 5), - KIT_ERROR_FILE_ALREADY_EXISTS = (1 << 6), - KIT_ERROR_FILE_DOES_NOT_EXIST = (1 << 7), - KIT_ERROR_PATH_TOO_LONG = (1 << 8), - KIT_ERROR_SOCKETS_STARTUP_FAILED = (1 << 9), - KIT_ERROR_SOCKET_CONTROL_FAILED = (1 << 10), - KIT_ERROR_NAME_TOO_LONG = (1 << 11), - KIT_ERROR_INVALID_SIZE = (1 << 12), - KIT_ERROR_INVALID_NAME = (1 << 13), - KIT_ERROR_INVALID_PATH = (1 << 14), - KIT_ERROR_OPEN_FAILED = (1 << 15), - KIT_ERROR_TRUNCATE_FAILED = (1 << 16), - KIT_ERROR_MAP_FAILED = (1 << 17), - KIT_ERROR_UNMAP_FAILED = (1 << 18), - KIT_ERROR_SYNC_FAILED = (1 << 19), - KIT_ERROR_CLOSE_FAILED = (1 << 20), - KIT_ERROR_RESOURCE_UNAVAILABLE = (1 << 21), - KIT_ERROR_NOT_IMPLEMENTED = (1 << 30), -}; -typedef i32 kit_status_t; -#endif -// ================================================================ -// -// File: source/kit/allocator.h -// -// ================================================================ -#ifndef KIT_ALLOCATOR_H -#define KIT_ALLOCATOR_H -#ifdef __cplusplus -extern "C" { -#endif -enum { - KIT_ALLOC_TYPE_NONE, - KIT_ALLOC_TYPE_DEFAULT, - KIT_ALLOC_TYPE_BUFFER -}; -enum { - KIT_ALLOCATE, - KIT_ALLOCATE_ZERO, - KIT_DEALLOCATE, - KIT_REALLOCATE, - KIT_REALLOCATE_ZERO, - KIT_DEALLOCATE_ALL -}; -typedef struct { - i32 type; - i64 size; - union { - u8 *bytes; - void *data; - }; -} kit_allocator_t; -// Application should implement this function if custom allocator -// dispatch is enabled. -// -// See KIT_ENABLE_CUSTOM_ALLOC_DISPATCH macro. -// -void *kit_alloc_dispatch(kit_allocator_t *alloc, i32 request, - i64 size, i64 previous_size, void *pointer); -kit_allocator_t kit_alloc_default(void); -kit_allocator_t kit_alloc_buffer(i64 size, void *buffer); -#ifdef __cplusplus -} -#endif -#endif -// ================================================================ -// -// File: source/kit/time.h -// -// ================================================================ -#ifndef KIT_TIME_H -#define KIT_TIME_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif -#include <time.h> -#ifdef __cplusplus -extern "C" { -#endif -#ifndef TIME_UTC -# define TIME_UTC 1 -#endif -#ifdef KIT_REQUIRE_TIMESPEC_GET -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 -# endif -# ifndef NOMINMAX -# define NOMINMAX 1 -# endif -# include <windows.h> -# define KIT_TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS 116444736000000000ull -# define KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS 10000000ull -static int timespec_get(struct timespec *ts, int base) { - if (ts == NULL || base != TIME_UTC) - return 0; - FILETIME ft; - ULARGE_INTEGER date; - LONGLONG ticks; - GetSystemTimeAsFileTime(&ft); - date.HighPart = ft.dwHighDateTime; - date.LowPart = ft.dwLowDateTime; - ticks = (LONGLONG) (date.QuadPart - - KIT_TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS); - ts->tv_sec = ticks / KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS; - ts->tv_nsec = (ticks % KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS) * 100; - return base; -} -#endif -#ifdef __cplusplus -} -#endif -#endif -// ================================================================ -// -// File: source/kit/atomic.h -// -// ================================================================ -#ifndef KIT_ATOMIC_H -#define KIT_ATOMIC_H -#ifndef _MSC_VER -# include <stdatomic.h> -#else -# include <assert.h> -# ifdef __cplusplus -extern "C" { -# endif -# define _Atomic volatile -enum { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -}; -void kit_atomic_store_explicit_8(u8 volatile *var, u8 value, - i32 memory_order); -void kit_atomic_store_explicit_16(u16 volatile *var, u16 value, - i32 memory_order); -void kit_atomic_store_explicit_32(u32 volatile *var, u32 value, - i32 memory_order); -void kit_atomic_store_explicit_64(u64 volatile *var, u64 value, - i32 memory_order); -u8 kit_atomic_load_explicit_8(u8 volatile *var, i32 memory_order); -u16 kit_atomic_load_explicit_16(u16 volatile *var, i32 memory_order); -u32 kit_atomic_load_explicit_32(u32 volatile *var, i32 memory_order); -u64 kit_atomic_load_explicit_64(u64 volatile *var, i32 memory_order); -u8 kit_atomic_exchange_explicit_8(u8 volatile *var, u8 value, - i32 memory_order); -u16 kit_atomic_exchange_explicit_16(u16 volatile *var, u16 value, - i32 memory_order); -u32 kit_atomic_exchange_explicit_32(u32 volatile *var, u32 value, - i32 memory_order); -u64 kit_atomic_exchange_explicit_64(u64 volatile *var, u64 value, - i32 memory_order); -i32 kit_atomic_compare_exchange_explicit_8(u8 volatile *var, - u8 *expected, u8 value, - i32 memory_order_succ_, - i32 memory_order_fail_); -i32 kit_atomic_compare_exchange_explicit_16(u16 volatile *var, - u16 *expected, u16 value, - i32 memory_order_succ_, - i32 memory_order_fail_); -i32 kit_atomic_compare_exchange_explicit_32(u32 volatile *var, - u32 *expected, u32 value, - i32 memory_order_succ_, - i32 memory_order_fail_); -i32 kit_atomic_compare_exchange_explicit_64(u64 volatile *var, - u64 *expected, u64 value, - i32 memory_order_succ_, - i32 memory_order_fail_); -u8 kit_atomic_fetch_add_explicit_8(u8 volatile *var, u8 value, - i32 memory_order); -u16 kit_atomic_fetch_add_explicit_16(u16 volatile *var, u16 value, - i32 memory_order); -u32 kit_atomic_fetch_add_explicit_32(u32 volatile *var, u32 value, - i32 memory_order); -u64 kit_atomic_fetch_add_explicit_64(u64 volatile *var, u64 value, - i32 memory_order); -# define atomic_store_explicit(var_, value_, memory_order_) \ - do { \ - assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8); \ - if (sizeof *(var_) == 1) \ - kit_atomic_store_explicit_8((u8 volatile *) (var_), \ - (u8) (value_), (memory_order_)); \ - if (sizeof *(var_) == 2) \ - kit_atomic_store_explicit_16((u16 volatile *) (var_), \ - (u16) (value_), \ - (memory_order_)); \ - if (sizeof *(var_) == 4) \ - kit_atomic_store_explicit_32((u32 volatile *) (var_), \ - (u32) (value_), \ - (memory_order_)); \ - if (sizeof *(var_) == 8) \ - kit_atomic_store_explicit_64((u64 volatile *) (var_), \ - (u64) (value_), \ - (memory_order_)); \ - } while (0) -# define atomic_load_explicit(var_, memory_order_) \ - (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8), \ - (sizeof *(var_) == 1 \ - ? kit_atomic_load_explicit_8((u8 volatile *) (var_), \ - (memory_order_)) \ - : sizeof *(var_) == 2 \ - ? kit_atomic_load_explicit_16((u16 volatile *) (var_), \ - (memory_order_)) \ - : sizeof *(var_) == 4 \ - ? kit_atomic_load_explicit_32((u32 volatile *) (var_), \ - (memory_order_)) \ - : kit_atomic_load_explicit_64((u64 volatile *) (var_), \ - (memory_order_)))) -# define atomic_exchange_explicit(var_, value_, memory_order_) \ - (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8), \ - (sizeof *(var_) == 1 ? kit_atomic_exchange_explicit_8( \ - (u8 volatile *) (var_), \ - (u8) (value_), (memory_order_)) \ - : sizeof *(var_) == 2 ? kit_atomic_exchange_explicit_16( \ - (u16 volatile *) (var_), \ - (u16) (value_), (memory_order_)) \ - : sizeof *(var_) == 4 \ - ? kit_atomic_exchange_explicit_32((u32 volatile *) (var_), \ - (u32) (value_), \ - (memory_order_)) \ - : kit_atomic_exchange_explicit_64((u64 volatile *) (var_), \ - (u64) (value_), \ - (memory_order_)))) -# define atomic_compare_exchange_strong_explicit( \ - var_, expected_, value_, memory_order_succ_, \ - memory_order_fail_) \ - (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8), \ - (sizeof *(var_) == 1 \ - ? kit_atomic_compare_exchange_explicit_8( \ - (u8 volatile *) (var_), (u8 *) (expected_), \ - (u8) (value_), (memory_order_succ_), \ - (memory_order_fail_)) \ - : sizeof *(var_) == 2 \ - ? kit_atomic_compare_exchange_explicit_16( \ - (u16 volatile *) (var_), (u16 *) (expected_), \ - (u16) (value_), (memory_order_succ_), \ - (memory_order_fail_)) \ - : sizeof *(var_) == 4 \ - ? kit_atomic_compare_exchange_explicit_32( \ - (u32 volatile *) (var_), (u32 *) (expected_), \ - (u32) (value_), (memory_order_succ_), \ - (memory_order_fail_)) \ - : kit_atomic_compare_exchange_explicit_64( \ - (u64 volatile *) (var_), (u64 *) (expected_), \ - (u64) (value_), (memory_order_succ_), \ - (memory_order_fail_)))) -# define atomic_compare_exchange_weak_explicit( \ - var_, expected_, value_, memory_order_succ_, \ - memory_order_fail_) \ - atomic_compare_exchange_strong_explicit(var_, expected_, value_, \ - memory_order_succ_, \ - memory_order_fail_) -# define atomic_fetch_add_explicit(var_, value_, memory_order_) \ - (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8), \ - (sizeof *(var_) == 1 ? kit_atomic_fetch_add_explicit_8( \ - (u8 volatile *) (var_), \ - (u8) (value_), (memory_order_)) \ - : sizeof *(var_) == 2 ? kit_atomic_fetch_add_explicit_16( \ - (u16 volatile *) (var_), \ - (u16) (value_), (memory_order_)) \ - : sizeof *(var_) == 4 ? kit_atomic_fetch_add_explicit_32( \ - (u32 volatile *) (var_), \ - (u32) (value_), (memory_order_)) \ - : kit_atomic_fetch_add_explicit_64( \ - (u64 volatile *) (var_), \ - (u64) (value_), (memory_order_)))) -# define atomic_store(var_, value_) \ - atomic_store(var_, value_, memory_order_seq_cst) -# define atomic_load(var_) atomic_load(var_, memory_order_seq_cst) -# define atomic_exchange(var_, value_) \ - atomic_exchange(var_, value_, memory_order_seq_cst) -# define atomic_compare_exchange_strong(var_, expected_, value_) \ - atomic_compare_exchange_strong_explicit(var_, expected_, value_, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -# define atomic_compare_exchange_weak(var_, expected_, value_) \ - atomic_compare_exchange_weak_explicit(var_, expected_, value_, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -# define atomic_fetch_add(var_, value_) \ - atomic_fetch_add(var_, value_, memory_order_seq_cst) -# ifdef __cplusplus -} -# endif -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define ATOMIC KIT_ATOMIC -#endif -#endif -// ================================================================ -// -// File: source/kit/threads.h -// -// ================================================================ -#ifndef KIT_THREADS_H -#define KIT_THREADS_H -#ifndef KIT_DISABLE_SYSTEM_THREADS -# include <stddef.h> -# include <stdint.h> -# if !defined(_WIN32) || defined(__CYGWIN__) -# include <pthread.h> -# endif -# if defined(__cplusplus) -# define _Noreturn [[noreturn]] -# elif defined(_MSC_VER) -# define _Noreturn __declspec(noreturn) -# endif -# ifndef _Thread_local -# if defined(__cplusplus) -// C++11 doesn't need `_Thread_local` keyword or macro -# elif !defined(__STDC_NO_THREADS__) -// threads are optional in C11, _Thread_local present in this -// condition -# elif defined(_MSC_VER) -# define _Thread_local __declspec(thread) -# elif defined(__GNUC__) -# define _Thread_local __thread -# else -// Leave _Thread_local undefined so that use of _Thread_local would -// not promote to a non-thread-local global variable -# endif -# endif -# if !defined(__cplusplus) -// C11 thread_local() macro C++11 and above already have thread_local -// keyword -# ifndef thread_local -# if _MSC_VER -# define thread_local __declspec(thread) -# else -# define thread_local _Thread_local -# endif -# endif -# endif -# ifdef __cplusplus -extern "C" { -# endif -enum { - mtx_plain, - mtx_recursive, - mtx_timed, -}; -enum { - thrd_success, - thrd_timedout, - thrd_error, - thrd_busy, - thrd_nomem, - thrd_wrong_stack_size -}; -# if defined(_WIN32) && !defined(__CYGWIN__) -typedef struct { - void *DebugInfo; - long LockCount; - long RecursionCount; - void *OwningThread; - void *LockSemaphore; - uintptr_t SpinCount; -} mtx_t; -typedef struct { - void *Ptr; -} cnd_t; -typedef struct { - volatile uintptr_t status; -} once_flag; -typedef struct { - void *handle; -} thrd_t; -typedef unsigned long tss_t; -# else -typedef pthread_mutex_t mtx_t; -typedef pthread_cond_t cnd_t; -typedef pthread_once_t once_flag; -typedef pthread_t thrd_t; -typedef pthread_key_t tss_t; -# endif -typedef void (*tss_dtor_t)(void *); -typedef int (*thrd_start_t)(void *); -void mtx_destroy(mtx_t *mtx_); -int mtx_init(mtx_t *mtx_, int); -int mtx_lock(mtx_t *mtx_); -int mtx_timedlock(mtx_t *__restrict mtx_, - struct timespec const *__restrict); -int mtx_trylock(mtx_t *mtx_); -int mtx_unlock(mtx_t *mtx_); -void call_once(once_flag *, void (*)(void)); -int cnd_broadcast(cnd_t *); -void cnd_destroy(cnd_t *); -int cnd_init(cnd_t *); -int cnd_signal(cnd_t *); -int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict mtx_, - struct timespec const *__restrict); -int cnd_wait(cnd_t *, mtx_t *mtx_); -int thrd_create(thrd_t *, thrd_start_t, void *); -int thrd_create_with_stack(thrd_t *, thrd_start_t, void *, - ptrdiff_t stack_size); -thrd_t thrd_current(void); -int thrd_detach(thrd_t); -int thrd_equal(thrd_t, thrd_t); -_Noreturn void thrd_exit(int); -int thrd_join(thrd_t, int *); -int thrd_sleep(struct timespec const *, struct timespec *); -void thrd_yield(void); -# ifdef __cplusplus -} -# endif -#endif -#endif -// ================================================================ -// -// File: source/kit/array_ref.h -// -// ================================================================ -#ifndef KIT_ARRAY_REF_H -#define KIT_ARRAY_REF_H -#ifdef __cplusplus -extern "C" { -#endif -typedef i8 (*kit_ar_compare_fn)(void *left, void *right); -i8 kit_ar_equal_bytes(i64 left_element_size, i64 left_size, - void *left_data, i64 right_element_size, - i64 right_size, void *right_data); -i8 kit_ar_compare(i64 left_element_size, i64 left_size, - void *left_data, i64 right_element_size, - i64 right_size, void *right_data, - kit_ar_compare_fn compare); -#define KIT_AR(type_) \ - struct { \ - i64 size; \ - type_ *values; \ - } -#define KIT_AR_WRAP(name_, element_type_, array_) \ - struct { \ - i64 size; \ - element_type_ *values; \ - } name_ = { .size = (sizeof(array_) / sizeof((array_)[0])), \ - .values = (array_) } -#define KIT_AR_EQUAL(left_, right_) \ - kit_ar_equal_bytes(sizeof((left_).values[0]), (left_).size, \ - (left_).values, sizeof((right_).values[0]), \ - (right_).size, (right_).values) -#define KIT_AR_COMPARE(left_, right_, compare_) \ - kit_ar_compare(sizeof((left_).values[0]), (left_).size, \ - (left_).values, sizeof((right_).values[0]), \ - (right_).size, (right_).values, \ - (kit_ar_compare_fn) (compare_)) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define ar_compare_fn kit_ar_compare_fn -# define ar_equal_bytes kit_ar_equal_bytes -# define ar_compare kit_ar_compare -# define AR KIT_AR -# define AR_WRAP KIT_AR_WRAP -# define AR_EQUAL KIT_AR_EQUAL -# define AR_COMPARE KIT_AR_COMPARE -#endif -#endif -// ================================================================ -// -// File: source/kit/dynamic_array.h -// -// ================================================================ -#ifndef KIT_DYNAMIC_ARRAY_H -#define KIT_DYNAMIC_ARRAY_H -#include <string.h> -#ifdef __cplusplus -extern "C" { -#endif -typedef struct { - i64 capacity; - i64 size; - void *values; - kit_allocator_t *alloc; -} kit_da_void_t; -void kit_da_init(kit_da_void_t *array, i64 element_size, i64 size, - kit_allocator_t *alloc); -void kit_da_resize(kit_da_void_t *array, i64 element_size, i64 size); -void kit_da_resize_exact(kit_da_void_t *array, i64 element_size, - i64 size); -/* Dynamic array type definition. - */ -#define KIT_DA(element_type_) \ - struct { \ - i64 capacity; \ - i64 size; \ - element_type_ *values; \ - kit_allocator_t *alloc; \ - } -/* Initialize dynamic array. - */ -#define KIT_DA_INIT(array_, size_, alloc_) \ - kit_da_init((kit_da_void_t *) &(array_), \ - sizeof((array_).values[0]), (size_), (alloc_)) -/* Declare and initialize dynamic array. - */ -#define KIT_DA_CREATE(name_, element_type_, size_) \ - KIT_DA(element_type_) name_; \ - KIT_DA_INIT(name_, (size_), NULL) -/* Destroy dynamic array. - */ -#define KIT_DA_DESTROY(array_) \ - do { \ - if ((array_).values != NULL) \ - kit_alloc_dispatch((array_).alloc, KIT_DEALLOCATE, 0, \ - (array_).capacity * \ - sizeof((array_).values[0]), \ - (array_).values); \ - memset(&(array_), 0, sizeof(array_)); \ - } while (0) -/* Resize dynamic array. - */ -#define KIT_DA_RESIZE(array_, size_) \ - kit_da_resize((kit_da_void_t *) &(array_), \ - sizeof((array_).values[0]), size_) -/* Resize dynamic array with exact capacity. - */ -#define KIT_DA_RESIZE_EXACT(array_, capacity_) \ - kit_da_resize_exact((kit_da_void_t *) &(array_), \ - sizeof((array_).values[0]), capacity_) -/* Append a value to dynamic array. - */ -#define KIT_DA_APPEND(array_, value_) \ - do { \ - i64 kit_index_back_ = (array_).size; \ - KIT_DA_RESIZE((array_), kit_index_back_ + 1); \ - if (kit_index_back_ < (array_).size) \ - (array_).values[kit_index_back_] = (value_); \ - } while (0) -/* Insert a value into dynamic array. - */ -#define KIT_DA_INSERT(array_, index_, value_) \ - do { \ - i64 kit_i_; \ - i64 kit_index_back_ = (array_).size; \ - i64 kit_indert_n_ = (index_); \ - KIT_DA_RESIZE((array_), kit_index_back_ + 1); \ - if (kit_index_back_ + 1 == (array_).size) { \ - for (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_); \ - } \ - } while (0) -/* Erase a value from dynamic array. - */ -#define KIT_DA_ERASE(array_, index_) \ - do { \ - i64 i_; \ - for (i_ = (index_) + 1; i_ < (array_).size; i_++) \ - (array_).values[i_ - 1] = (array_).values[i_]; \ - KIT_DA_RESIZE((array_), (array_).size - 1); \ - } while (0) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define da_void_t kit_da_void_t -# define da_init kit_da_init -# define da_resize kit_da_resize -# define DA KIT_DA -# define DA_INIT KIT_DA_INIT -# define DA_CREATE KIT_DA_CREATE -# define DA_DESTROY KIT_DA_DESTROY -# define DA_RESIZE KIT_DA_RESIZE -# define DA_RESIZE_EXACT KIT_DA_RESIZE_EXACT -# define DA_APPEND KIT_DA_APPEND -# define DA_INSERT KIT_DA_INSERT -# define DA_ERASE KIT_DA_ERASE -#endif -#endif -// ================================================================ -// -// File: source/kit/string_ref.h -// -// ================================================================ -#ifndef KIT_STRING_REF_H -#define KIT_STRING_REF_H -#include <string.h> -#ifdef __cplusplus -extern "C" { -#endif -typedef KIT_AR(char) kit_str_t; -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-function" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -# pragma GCC push_options -# pragma GCC optimize("O3") -#endif -static kit_str_t kit_str(i64 size, char const *static_string) { - kit_str_t s = { .size = size, .values = (char *) static_string }; - return s; -} -// Make a barbarian string for C standard library functions. -// Not thread safe. -// Use with caution. -// -static char *kit_make_bs(kit_str_t s) { - static char buf[8][4096]; - static i32 index = 0; - i64 n = s.size; - if (n > 4095) - n = 4095; - if (n > 0) - memcpy(buf[index], s.values, n); - buf[index][n] = '\0'; - char *result = buf[index]; - index = (index + 1) % 8; - return result; -} -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif -#define KIT_SZ(static_str_) \ - kit_str(sizeof(static_str_) - 1, (static_str_)) -#define KIT_WRAP_BS(string_) kit_str(strlen(string_), (string_)) -#define KIT_WRAP_STR(...) \ - kit_str((__VA_ARGS__).size, (__VA_ARGS__).values) -#ifndef KIT_DISABLE_SHORT_NAMES -# define BS(...) kit_make_bs(KIT_WRAP_STR(__VA_ARGS__)) -# define str_t kit_str_t -# define SZ KIT_SZ -# define WRAP_BS KIT_WRAP_BS -# define WRAP_STR KIT_WRAP_STR -#endif -#ifdef __cplusplus -} -#endif -#endif -// ================================================================ -// -// File: source/kit/string_builder.h -// -// ================================================================ -#ifndef KIT_STRING_BUILDER_H -#define KIT_STRING_BUILDER_H -#include <assert.h> -#ifdef __cplusplus -extern "C" { -#endif -typedef KIT_DA(char) kit_str_builder_t; -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-function" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -# pragma GCC push_options -# pragma GCC optimize("O3") -#endif -static kit_str_builder_t kit_str_build(kit_str_t s, - kit_allocator_t *alloc) { - kit_str_builder_t builder; - KIT_DA_INIT(builder, s.size, alloc); - assert(builder.size == s.size); - if (builder.size == s.size) - memcpy(builder.values, s.values, s.size); - return builder; -} -static kit_status_t kit_str_append(kit_str_builder_t *a, - kit_str_t b) { - assert(a != NULL); - if (a == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - if (b.size <= 0) - return KIT_OK; - i64 n = a->size; - KIT_DA_RESIZE(*a, n + b.size); - if (a->size != n + b.size) - return KIT_ERROR_BAD_ALLOC; - memcpy(a->values + n, b.values, b.size); - return KIT_OK; -} -#ifdef __GNUC__ -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define str_builder_t kit_str_builder_t -# define str_append kit_str_append -#endif -#endif -// ================================================================ -// -// File: source/kit/lower_bound.h -// -// ================================================================ -#ifndef KIT_LOWER_BOUND_H -#define KIT_LOWER_BOUND_H -#ifdef __cplusplus -extern "C" { -#endif -#define KIT_LOWER_BOUND_INL(return_val, size, ...) \ - do { \ - i64 position_ = 0; \ - i64 count_ = (size); \ - while (count_ > 0) { \ - i64 delta_ = count_ / 2; \ - i64 index_ = position_ + delta_; \ - if (__VA_ARGS__) { \ - position_ += delta_ + 1; \ - count_ -= delta_ + 1; \ - } else \ - count_ = delta_; \ - } \ - (return_val) = position_; \ - } while (0) -#define KIT_LOWER_BOUND(return_val, array, value, op) \ - KIT_LOWER_BOUND_INL(return_val, (array).size, \ - (op) ((array).values[index_], (value))) -#define KIT_LOWER_BOUND_REF(return_val, array, value, op) \ - KIT_LOWER_BOUND_INL(return_val, (array).size, \ - (op) ((array).values + index_, (value))) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define LOWER_BOUND_INL KIT_LOWER_BOUND_INL -# define LOWER_BOUND KIT_LOWER_BOUND -# define LOWER_BOUND_REF KIT_LOWER_BOUND_REF -#endif -#endif -// ================================================================ -// -// File: source/kit/move_back.h -// -// ================================================================ -#ifndef KIT_MOVE_BACK_H -#define KIT_MOVE_BACK_H -#include <string.h> -#ifdef __cplusplus -extern "C" { -#endif -#define KIT_MOVE_BACK_INL(new_size, array, ...) \ - do { \ - i64 index_; \ - i64 end_ = (array).size; \ - u8 temp_[sizeof *(array).values]; \ - for (index_ = 0; index_ < end_;) { \ - if (__VA_ARGS__) { \ - end_--; \ - if (index_ != end_) { \ - memcpy(temp_, (array).values + end_, \ - sizeof *(array).values); \ - (array).values[end_] = (array).values[index_]; \ - memcpy((array).values + index_, temp_, \ - sizeof *(array).values); \ - } \ - } else \ - index_++; \ - } \ - (new_size) = end_; \ - } while (0) -#define KIT_MOVE_BACK(new_size, array, value, cond) \ - KIT_MOVE_BACK_INL(new_size, array, \ - (cond) ((array).values[index_], (value))) -#define KIT_MOVE_BACK_REF(new_size, array, value, cond) \ - KIT_MOVE_BACK_INL(new_size, array, \ - (cond) ((array).values + index_, (value))) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define MOVE_BACK_INL KIT_MOVE_BACK_INL -# define MOVE_BACK KIT_MOVE_BACK -# define MOVE_BACK_REF KIT_MOVE_BACK_REF -#endif -#endif -// ================================================================ -// -// File: source/kit/bigint.h -// -// ================================================================ -#ifndef KIT_BIGINT_H -#define KIT_BIGINT_H -#include <assert.h> -#include <string.h> -#ifdef __cplusplus -extern "C" { -#endif -#ifndef KIT_BIGINT_SIZE -# define KIT_BIGINT_SIZE 64 -#endif -typedef struct { - u32 v[KIT_BIGINT_SIZE / 4]; -} kit_bigint_t; -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-function" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -# pragma GCC push_options -# pragma GCC optimize("O3") -#endif -static kit_bigint_t kit_bi_u32(u32 x) { - kit_bigint_t z; - memset(&z, 0, sizeof z); - z.v[0] = x; - return z; -} -static kit_bigint_t kit_bi_u64(u64 x) { - kit_bigint_t z; - memset(&z, 0, sizeof z); - z.v[0] = (u32) (x & 0xffffffff); - z.v[1] = (u32) (x >> 32); - return z; -} -static kit_bigint_t kit_bi_i32(i32 x) { - kit_bigint_t z; - memset(&z, x < 0 ? -1 : 0, sizeof z); - z.v[0] = x; - return z; -} -static kit_bigint_t kit_bi_i64(i64 x) { - kit_bigint_t z; - memset(&z, x < 0 ? -1 : 0, sizeof z); - z.v[0] = (u32) (((u64) x) & 0xffffffff); - z.v[1] = (u32) (((u64) x) >> 32); - return z; -} -static int kit_bi_is_zero(kit_bigint_t x) { - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) - if (x.v[i] != 0) - return 0; - return 1; -} -static int kit_bi_is_neg(kit_bigint_t x) { - return (x.v[KIT_BIGINT_SIZE / 4 - 1] & 0x80000000) != 0; -} -static int kit_bi_equal(kit_bigint_t x, kit_bigint_t y) { - return kit_ar_equal_bytes(1, KIT_BIGINT_SIZE, x.v, 1, - KIT_BIGINT_SIZE, y.v); -} -static int kit_bi_compare(kit_bigint_t x, kit_bigint_t y) { - i64 i; - for (i = KIT_BIGINT_SIZE / 4 - 1; i >= 0; i--) - if (x.v[i] < y.v[i]) - return -1; - else if (x.v[i] > y.v[i]) - return 1; - return 0; -} -static i64 kit_bi_significant_bit_count(kit_bigint_t x) { - i64 n = KIT_BIGINT_SIZE / 4 - 1; - while (n > 0 && x.v[n] == 0) n--; - u32 val = x.v[n]; - if (val == 0) - return 0; - i64 bits = (val & 0x80000000u) != 0 ? 32 - : (val & 0x40000000u) != 0 ? 31 - : (val & 0x20000000u) != 0 ? 30 - : (val & 0x10000000u) != 0 ? 29 - : (val & 0x8000000u) != 0 ? 28 - : (val & 0x4000000u) != 0 ? 27 - : (val & 0x2000000u) != 0 ? 26 - : (val & 0x1000000u) != 0 ? 25 - : (val & 0x800000u) != 0 ? 24 - : (val & 0x400000u) != 0 ? 23 - : (val & 0x200000u) != 0 ? 22 - : (val & 0x100000u) != 0 ? 21 - : (val & 0x80000u) != 0 ? 20 - : (val & 0x40000u) != 0 ? 19 - : (val & 0x20000u) != 0 ? 18 - : (val & 0x10000u) != 0 ? 17 - : (val & 0x8000u) != 0 ? 16 - : (val & 0x4000u) != 0 ? 15 - : (val & 0x2000u) != 0 ? 14 - : (val & 0x1000u) != 0 ? 13 - : (val & 0x800u) != 0 ? 12 - : (val & 0x400u) != 0 ? 11 - : (val & 0x200u) != 0 ? 10 - : (val & 0x100u) != 0 ? 9 - : (val & 0x80u) != 0 ? 8 - : (val & 0x40u) != 0 ? 7 - : (val & 0x20u) != 0 ? 6 - : (val & 0x10u) != 0 ? 5 - : (val & 0x08u) != 0 ? 4 - : (val & 0x04u) != 0 ? 3 - : (val & 0x02u) != 0 ? 2 - : 1; - return n * 32 + bits; -} -static kit_bigint_t kit_bi_and(kit_bigint_t x, kit_bigint_t y) { - kit_bigint_t z; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) z.v[i] = x.v[i] & y.v[i]; - return z; -} -static kit_bigint_t kit_bi_or(kit_bigint_t x, kit_bigint_t y) { - kit_bigint_t z; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) z.v[i] = x.v[i] | y.v[i]; - return z; -} -static kit_bigint_t kit_bi_xor(kit_bigint_t x, kit_bigint_t y) { - kit_bigint_t z; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) z.v[i] = x.v[i] ^ y.v[i]; - return z; -} -static kit_bigint_t kit_bi_shl_uint(kit_bigint_t x, u32 y) { - kit_bigint_t z; - memset(&z, 0, sizeof z); - i64 words = (i64) (y / 32); - i64 bits = (i64) (y % 32); - i64 i; - for (i = words; i < KIT_BIGINT_SIZE / 4; i++) { - z.v[i] |= x.v[i - words] << bits; - if (bits != 0 && i + 1 < KIT_BIGINT_SIZE / 4) - z.v[i + 1] = x.v[i - words] >> (32 - bits); - } - return z; -} -static kit_bigint_t kit_bi_shr_uint(kit_bigint_t x, u32 y) { - kit_bigint_t z; - memset(&z, 0, sizeof z); - i64 words = (i64) (y / 32); - i64 bits = (i64) (y % 32); - i64 i; - for (i = KIT_BIGINT_SIZE / 4 - words - 1; i >= 0; i--) { - z.v[i] |= x.v[i + words] >> bits; - if (bits != 0 && i > 0) - z.v[i - 1] = x.v[i + words] << (32 - bits); - } - return z; -} -static i8 kit_bi_carry(u32 x, u32 y, i8 carry) { - assert(carry == 0 || carry == 1); - return 0xffffffffu - x < y || 0xffffffffu - x - y < carry ? 1 : 0; -} -/* Increment. - */ -static kit_bigint_t kit_bi_inc(kit_bigint_t x) { - kit_bigint_t z; - i8 carry = 1; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - z.v[i] = x.v[i] + carry; - carry = kit_bi_carry(x.v[i], 0, carry); - } - return z; -} -/* Decrement - */ -static kit_bigint_t kit_bi_dec(kit_bigint_t x) { - kit_bigint_t z; - i8 carry = 0; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - z.v[i] = x.v[i] + 0xffffffff + carry; - carry = kit_bi_carry(x.v[i], 0xffffffff, carry); - } - return z; -} -/* Addition. - */ -static kit_bigint_t kit_bi_add(kit_bigint_t x, kit_bigint_t y) { - kit_bigint_t z; - i8 carry = 0; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - z.v[i] = x.v[i] + y.v[i] + carry; - carry = kit_bi_carry(x.v[i], y.v[i], carry); - } - return z; -} -/* Negation. - */ -static kit_bigint_t kit_bi_neg(kit_bigint_t x) { - kit_bigint_t y; - i8 carry = 1; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - y.v[i] = (x.v[i] ^ 0xffffffff) + carry; - carry = kit_bi_carry(x.v[i] ^ 0xffffffff, 0, carry); - } - return y; -} -/* Subtraction. - */ -static kit_bigint_t kit_bi_sub(kit_bigint_t x, kit_bigint_t y) { - kit_bigint_t z; - i8 carry = 1; - i64 i; - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - z.v[i] = x.v[i] + (y.v[i] ^ 0xffffffff) + carry; - carry = kit_bi_carry(x.v[i], (y.v[i] ^ 0xffffffff), carry); - } - return z; -} -static kit_bigint_t kit_bi_mul_u32(kit_bigint_t x, u32 y) { - kit_bigint_t z; - i64 i, k; - memset(&z, 0, sizeof z); - if (y != 0) - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - if (x.v[i] == 0) - continue; - u64 carry = ((u64) x.v[i]) * ((u64) y); - for (k = i; k < KIT_BIGINT_SIZE / 4 && carry != 0; k++) { - u64 sum = ((u64) z.v[k]) + carry; - z.v[k] = ((u32) (sum & 0xffffffffull)); - carry = sum >> 32; - } - } - return z; -} -/* Multiplication. - */ -static kit_bigint_t kit_bi_mul(kit_bigint_t x, kit_bigint_t y) { - kit_bigint_t z; - i64 i, j, k; - memset(&z, 0, sizeof z); - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - if (x.v[i] == 0) - continue; - for (j = 0; i + j < KIT_BIGINT_SIZE / 4; j++) { - if (y.v[j] == 0) - continue; - u64 carry = ((u64) x.v[i]) * ((u64) y.v[j]); - for (k = i + j; k < KIT_BIGINT_SIZE / 4 && carry != 0; k++) { - u64 sum = ((u64) z.v[k]) + carry; - z.v[k] = ((u32) (sum & 0xffffffffull)); - carry = sum >> 32; - } - } - } - return z; -} -typedef struct { - i8 undefined; - kit_bigint_t quotient; - kit_bigint_t remainder; -} kit_bi_division_t; -/* Unsigned division. - */ -static kit_bi_division_t kit_bi_udiv(kit_bigint_t x, kit_bigint_t y) { - kit_bi_division_t z; - memset(&z, 0, sizeof z); - i64 y_bits = kit_bi_significant_bit_count(y); - if (y_bits == 0) { - z.undefined = 1; - return z; - } - i64 x_bits = kit_bi_significant_bit_count(x); - i64 shift = x_bits - y_bits; - z.remainder = x; - z.quotient = kit_bi_u32(0); - y = kit_bi_shl_uint(y, (u32) shift); - while (shift >= 0) { - if (kit_bi_compare(z.remainder, y) >= 0) { - z.remainder = kit_bi_sub(z.remainder, y); - z.quotient.v[shift / 32] |= (1u << (shift % 32)); - } - y = kit_bi_shr_uint(y, 1); - shift--; - } - return z; -} -/* Signed division. - * - * Remainder is always a non-negative value less than absolute value - * of y. - */ -static kit_bi_division_t kit_bi_div(kit_bigint_t x, kit_bigint_t y) { - int x_neg = kit_bi_is_neg(x); - int y_neg = kit_bi_is_neg(y); - kit_bigint_t x_abs = x_neg ? kit_bi_neg(x) : x; - kit_bigint_t y_abs = y_neg ? kit_bi_neg(y) : y; - if (x_neg == y_neg) - return kit_bi_udiv(x_abs, y_abs); - kit_bi_division_t z = kit_bi_udiv(x_abs, y_abs); - if (!kit_bi_is_zero(z.remainder) && !y_neg) - z.quotient = kit_bi_dec(kit_bi_neg(z.quotient)); - else - z.quotient = kit_bi_neg(z.quotient); - return z; -} -static void kit_bi_serialize(kit_bigint_t in, u8 *out) { - i64 i; - assert(out != NULL); - for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - out[i * 4] = (u8) (in.v[i] & 0xff); - out[i * 4 + 1] = (u8) ((in.v[i] >> 8) & 0xff); - out[i * 4 + 2] = (u8) ((in.v[i] >> 16) & 0xff); - out[i * 4 + 3] = (u8) ((in.v[i] >> 24) & 0xff); - } -} -static kit_bigint_t kit_bi_deserialize(u8 *in) { - i64 i; - kit_bigint_t out; - assert(in != NULL); - memset(&out, 0, sizeof out); - for (i = 0; i < KIT_BIGINT_SIZE; i++) - out.v[i / 4] |= ((u32) in[i]) << (8 * (i % 4)); - return out; -} -static u8 kit_bin_digit(char hex) { - assert(hex == '0' || hex == '1'); - return hex == '1' ? 1 : 0; -} -static kit_bigint_t kit_bi_from_bin(kit_str_t bin) { - kit_bigint_t z; - i64 i; - memset(&z, 0, sizeof z); - for (i = 0; i < bin.size && i / 8 < KIT_BIGINT_SIZE; i++) { - u8 digit = kit_bin_digit(bin.values[bin.size - i - 1]); - z.v[i / 32] |= digit << (i % 32); - } - return z; -} -static u8 kit_dec_digit(char c) { - assert('c' >= '0' && c <= '9'); - return c >= '0' && c <= '9' ? (u8) (c - '0') : 0; -} -static kit_bigint_t kit_bi_from_dec(kit_str_t dec) { - kit_bigint_t z = kit_bi_u32(0); - kit_bigint_t factor = kit_bi_u32(1); - i64 i; - for (i = 0; i < dec.size; i++) { - u32 digit = kit_dec_digit(dec.values[dec.size - i - 1]); - z = kit_bi_add(z, kit_bi_mul_u32(factor, digit)); - factor = kit_bi_mul_u32(factor, 10); - } - return z; -} -static u8 kit_hex_digit(char hex) { - assert((hex >= '0' && hex <= '9') || (hex >= 'a' && hex <= 'f') || - (hex >= 'A' && hex <= 'F')); - if (hex >= '0' && hex <= '9') - return hex - '0'; - if (hex >= 'a' && hex <= 'f') - return hex - 'a'; - if (hex >= 'A' && hex <= 'F') - return hex - 'A'; - return 0; -} -static kit_bigint_t kit_bi_from_hex(kit_str_t hex) { - kit_bigint_t z; - i64 i; - memset(&z, 0, sizeof z); - for (i = 0; i < hex.size && i / 2 < KIT_BIGINT_SIZE; i++) { - u8 digit = kit_hex_digit(hex.values[hex.size - i - 1]); - z.v[i / 8] |= digit << (4 * (i % 8)); - } - return z; -} -static u8 KIT_BASE32_DIGITS[] = { - ['1'] = 0, ['2'] = 1, ['3'] = 2, ['4'] = 3, ['5'] = 4, - ['6'] = 5, ['7'] = 6, ['8'] = 7, ['9'] = 8, ['a'] = 9, - ['b'] = 10, ['c'] = 11, ['d'] = 12, ['e'] = 13, ['f'] = 14, - ['g'] = 15, ['h'] = 16, ['j'] = 17, ['k'] = 18, ['m'] = 19, - ['n'] = 20, ['p'] = 21, ['q'] = 22, ['r'] = 23, ['s'] = 24, - ['t'] = 25, ['u'] = 26, ['v'] = 27, ['w'] = 28, ['x'] = 29, - ['y'] = 30, ['z'] = 31 -}; -static u8 kit_base32_digit(char c) { - assert(c >= '\0' && c < sizeof KIT_BASE32_DIGITS); - assert(c == '1' || KIT_BASE32_DIGITS[(size_t) (u8) c] != 0); - return c >= '\0' && c < sizeof KIT_BASE32_DIGITS - ? KIT_BASE32_DIGITS[(size_t) (u8) c] - : 0; -} -static kit_bigint_t kit_bi_from_base32(kit_str_t base32) { - kit_bigint_t z; - i64 i; - memset(&z, 0, sizeof z); - for (i = 0; i < base32.size; i++) { - z = kit_bi_shl_uint(z, 5 * i); - z.v[0] |= kit_base32_digit(base32.values[i]); - } - return z; -} -static u8 KIT_BASE58_DIGITS[] = { - ['1'] = 0, ['2'] = 1, ['3'] = 2, ['4'] = 3, ['5'] = 4, - ['6'] = 5, ['7'] = 6, ['8'] = 7, ['9'] = 8, ['A'] = 9, - ['B'] = 10, ['C'] = 11, ['D'] = 12, ['E'] = 13, ['F'] = 14, - ['G'] = 15, ['H'] = 16, ['J'] = 17, ['K'] = 18, ['L'] = 19, - ['M'] = 20, ['N'] = 21, ['P'] = 22, ['Q'] = 23, ['R'] = 24, - ['S'] = 25, ['T'] = 26, ['U'] = 27, ['V'] = 28, ['W'] = 29, - ['X'] = 30, ['Y'] = 31, ['Z'] = 32, ['a'] = 33, ['b'] = 34, - ['c'] = 35, ['d'] = 36, ['e'] = 37, ['f'] = 38, ['g'] = 39, - ['h'] = 40, ['i'] = 41, ['j'] = 42, ['k'] = 43, ['m'] = 44, - ['n'] = 45, ['o'] = 46, ['p'] = 47, ['q'] = 48, ['r'] = 49, - ['s'] = 50, ['t'] = 51, ['u'] = 52, ['v'] = 53, ['w'] = 54, - ['x'] = 55, ['y'] = 56, ['z'] = 57 -}; -static u8 kit_base58_digit(char c) { - assert(c >= '\0' && c < sizeof KIT_BASE58_DIGITS); - assert(c == '1' || KIT_BASE58_DIGITS[(size_t) (u8) c] != 0); - return c >= '\0' && c < sizeof KIT_BASE58_DIGITS - ? KIT_BASE58_DIGITS[(size_t) (u8) c] - : 0; -} -static kit_bigint_t kit_bi_from_base58(kit_str_t base58) { - kit_bigint_t z = kit_bi_u32(0); - kit_bigint_t factor = kit_bi_u32(1); - i64 i; - for (i = 0; i < base58.size; i++) { - u32 digit = kit_base58_digit(base58.values[base58.size - i - 1]); - z = kit_bi_add(z, kit_bi_mul_u32(factor, digit)); - factor = kit_bi_mul_u32(factor, 58); - } - return z; -} -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif -#define KIT_BIN(static_str_) \ - kit_bi_from_bin(kit_str(sizeof(static_str_) - 1, (static_str_))) -#define KIT_DEC(static_str_) \ - kit_bi_from_dec(kit_str(sizeof(static_str_) - 1, (static_str_))) -#define KIT_HEX(static_str_) \ - kit_bi_from_hex(kit_str(sizeof(static_str_) - 1, (static_str_))) -#define KIT_BASE32(static_str_) \ - kit_bi_from_base32(kit_str(sizeof(static_str_) - 1, (static_str_))) -#define KIT_BASE58(static_str_) \ - kit_bi_from_base58(kit_str(sizeof(static_str_) - 1, (static_str_))) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define bigint_t kit_bigint_t -# define bi_u32 kit_bi_u32 -# define bi_u64 kit_bi_u64 -# define bi_i32 kit_bi_i32 -# define bi_i64 kit_bi_i64 -# define bi_is_zero kit_bi_is_zero -# define bi_is_neg kit_bi_is_neg -# define bi_equal kit_bi_equal -# define bi_compare kit_bi_compare -# define bi_carry kit_bi_carry -# define bi_inc kit_bi_inc -# define bi_dec kit_bi_dec -# define bi_add kit_bi_add -# define bi_neg kit_bi_neg -# define bi_sub kit_bi_sub -# define bi_mul kit_bi_mul -# define bi_div kit_bi_div -# define bi_serialize kit_bi_serialize -# define bi_deserialize kit_bi_deserialize -# define BIN KIT_BIN -# define DEC KIT_DEC -# define HEX KIT_HEX -# define BASE32 KIT_BASE32 -# define BASE58 KIT_BASE58 -#endif -#endif -// ================================================================ -// -// File: source/kit/input_stream.h -// -// ================================================================ -#ifndef KIT_INPUT_STREAM_H -#define KIT_INPUT_STREAM_H -#include <stdio.h> -#ifdef __cplusplus -extern "C" { -#endif -typedef i64 (*kit_is_read_fn)(void *state, kit_str_t destination); -typedef struct { - void *state; - kit_is_read_fn read; -} kit_is_handle_t; -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), NULL) -#define KIT_IS_WRAP_FILE(f) kit_is_wrap_file((f), NULL) -#define KIT_IS_READ(in, destination) \ - (in).read((in).state, (destination)) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# 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 -#endif -// ================================================================ -// -// File: source/kit/input_buffer.h -// -// ================================================================ -#ifndef KIT_INPUT_BUFFER_H -#define KIT_INPUT_BUFFER_H -#ifdef __cplusplus -extern "C" { -#endif -typedef struct { - kit_status_t status; - i64 offset; - void *internal; - kit_str_builder_t data; -} kit_ib_t; -typedef i8 (*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_ib_t kit_ib_copy(kit_ib_t buf); -kit_ib_t kit_ib_read(kit_ib_t buf, i64 size); -kit_ib_t kit_ib_any(kit_ib_t buf, kit_str_t data); -kit_ib_t kit_ib_none(kit_ib_t buf, kit_str_t data); -kit_ib_t kit_ib_exact(kit_ib_t buf, kit_str_t data); -kit_ib_t kit_ib_until(kit_ib_t buf, kit_str_t data); -kit_ib_t kit_ib_while(kit_ib_t buf, - kit_ib_read_condition_fn condition, - void *context); -void kit_ib_destroy(kit_ib_t buf); -#define KIT_IB_WRAP(upstream) kit_ib_wrap(upstream, NULL) -#define KIT_IB_SKIP(buf_, proc_, ...) \ - do { \ - kit_ib_t temp_buf_ = (buf_); \ - (buf_) = proc_((buf_), __VA_ARGS__); \ - kit_ib_destroy((temp_buf_)); \ - } while (0) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define ib_t kit_ib_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_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 -#endif -// ================================================================ -// -// File: source/kit/async_function.h -// -// ================================================================ -#ifndef KIT_ASYNC_FUNCTION_H -#define KIT_ASYNC_FUNCTION_H -#include <string.h> -#ifdef __cplusplus -extern "C" { -#endif -typedef struct { - i32 _; -} kit_af_void; -typedef void (*kit_af_state_machine)(void *self_void_); -#define KIT_AF_STATE_DATA \ - struct { \ - i32 _index; \ - i32 _id; \ - kit_af_state_machine _state_machine; \ - } -typedef struct { - KIT_AF_STATE_DATA; -} kit_af_type_void; -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-function" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -#endif -#define KIT_AF_INTERNAL(coro_) (*((kit_af_type_void *) (coro_))) -#ifdef KIT_ENABLE_CUSTOM_ASYNC_FUNCTION_DISPATCH -// Application should implement this function if custom async -// function dispatch is enabled. -// -// See KIT_ENABLE_CUSTOM_ASYNC_FUNCTION_DISPATCH macro. -// -void kit_async_function_dispatch(void *promise); -#else -static void kit_async_function_dispatch(void *promise) { - // Dynamic dispatch by default. - // - KIT_AF_INTERNAL(promise)._state_machine(promise); -} -#endif -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC diagnostic pop -#endif -#define KIT_AF_STATE(ret_type_, name_, ...) \ - struct name_##_coro_state_ { \ - KIT_AF_STATE_DATA; \ - ret_type_ return_value; \ - __VA_ARGS__ \ - } -#define KIT_AF_DECL(name_) void name_(void *self_void_) -#define KIT_CORO_IMPL(name_) \ - KIT_AF_DECL(name_) { \ - struct name_##_coro_state_ *self = \ - (struct name_##_coro_state_ *) self_void_; \ - switch (self->_index) { \ - case 0:; -#define KIT_AF_LINE_() __LINE__ -#define KIT_CORO_END \ - } \ - self->_index = -1; \ - } -#define KIT_CORO_DECL(ret_type_, name_, ...) \ - KIT_AF_STATE(ret_type_, name_, __VA_ARGS__); \ - KIT_AF_DECL(name_) -#define KIT_CORO(ret_type_, name_, ...) \ - KIT_AF_STATE(ret_type_, name_, __VA_ARGS__); \ - KIT_CORO_IMPL(name_) -#define KIT_CORO_DECL_VOID(name_, ...) \ - KIT_CORO_DECL(kit_af_void, name_, __VA_ARGS__) -#define KIT_CORO_VOID(name_, ...) \ - KIT_CORO(kit_af_void, name_, __VA_ARGS__) -#define KIT_STATIC_CORO(ret_type_, name_, ...) \ - KIT_AF_STATE(ret_type_, name_, __VA_ARGS__); \ - static KIT_CORO_IMPL(name_) -#define KIT_STATIC_CORO_VOID(name_, ...) \ - KIT_STATIC_CORO(kit_af_void, name_, __VA_ARGS__) -#define KIT_AF_EXECUTE(promise_) \ - kit_async_function_dispatch(&(promise_)) -#define KIT_AF_NEXT(promise_) \ - (kit_async_function_dispatch(&(promise_)), (promise_).return_value) -#define KIT_AF_YIELD(...) \ - do { \ - self->_index = KIT_AF_LINE_(); \ - self->return_value = __VA_ARGS__; \ - return; \ - case KIT_AF_LINE_():; \ - } while (0) -#define KIT_AF_YIELD_VOID \ - do { \ - self->_index = KIT_AF_LINE_(); \ - return; \ - case KIT_AF_LINE_():; \ - } while (0) -#define KIT_AF_RETURN(...) \ - do { \ - self->_index = -1; \ - self->return_value = __VA_ARGS__; \ - return; \ - } while (0) -#define KIT_AF_RETURN_VOID \ - do { \ - self->_index = -1; \ - return; \ - } while (0) -#define KIT_AF_AWAIT(promise_) \ - do { \ - case KIT_AF_LINE_(): \ - if ((promise_)._index != -1) { \ - self->_index = KIT_AF_LINE_(); \ - kit_async_function_dispatch(&(promise_)); \ - } \ - if ((promise_)._index != -1) \ - return; \ - } while (0) -#define KIT_AF_YIELD_AWAIT(promise_) \ - do { \ - case KIT_AF_LINE_(): \ - if ((promise_)._index != -1) { \ - self->_index = KIT_AF_LINE_(); \ - kit_async_function_dispatch(&(promise_)); \ - self->return_value = (promise_).return_value; \ - return; \ - } \ - } while (0) -#define KIT_AF_TYPE(coro_) struct coro_##_coro_state_ -#define KIT_AF_INITIAL(id_, coro_) \ - ._index = 0, ._id = (id_), ._state_machine = (coro_) -#define KIT_AF_CREATE(promise_, coro_, ...) \ - KIT_AF_TYPE(coro_) \ - promise_ = { KIT_AF_INITIAL(0, coro_), __VA_ARGS__ } -#define KIT_AF_CREATE_ID(promise_, id_, ...) \ - KIT_AF_TYPE(coro_) \ - promise_ = { KIT_AF_INITIAL(id_, NULL), __VA_ARGS__ } -#define KIT_AF_INIT(promise_, coro_, ...) \ - do { \ - KIT_AF_CREATE(kit_af_temp_, coro_, __VA_ARGS__); \ - memcpy(&(promise_), &kit_af_temp_, sizeof kit_af_temp_); \ - } while (0) -#define KIT_AF_INIT_ID(promise_, id_, ...) \ - do { \ - KIT_AF_CREATE_ID(kit_af_temp_, id_, __VA_ARGS__); \ - memcpy(&(promise_), &kit_af_temp_, sizeof kit_af_temp_); \ - } while (0) -#define KIT_AF_FINISHED(promise_) ((promise_)._index == -1) -#define KIT_AF_FINISHED_N(return_, promises_, size_) \ - do { \ - i32 kit_af_index_; \ - (return_) = 1; \ - for (kit_af_index_ = 0; kit_af_index_ < (size_); \ - kit_af_index_++) \ - if (!KIT_AF_FINISHED((promises_)[kit_af_index_])) { \ - (return_) = 0; \ - break; \ - } \ - } while (0) -#define KIT_AF_FINISHED_ALL(return_, promises_) \ - KIT_AF_FINISHED_N((return_), (promises_), \ - sizeof(promises_) / sizeof((promises_)[0])) -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define af_void kit_af_void -# define af_state_machine kit_af_state_machine -# define af_type_void kit_af_type_void -# define AF_STATE_DATA KIT_AF_STATE_DATA -# define AF_STATE KIT_AF_STATE -# define AF_DECL KIT_AF_DECL -# define CORO_IMPL KIT_CORO_IMPL -# define CORO_END KIT_CORO_END -# define CORO_DECL KIT_CORO_DECL -# define CORO KIT_CORO -# define CORO_DECL_VOID KIT_CORO_DECL_VOID -# define STATIC_CORO KIT_STATIC_CORO -# define STATIC_CORO_VOID KIT_STATIC_CORO_VOID -# define CORO_VOID KIT_CORO_VOID -# define AF_EXECUTE KIT_AF_EXECUTE -# define AF_NEXT KIT_AF_NEXT -# define AF_YIELD KIT_AF_YIELD -# define AF_YIELD_VOID KIT_AF_YIELD_VOID -# define AF_RETURN KIT_AF_RETURN -# define AF_RETURN_VOID KIT_AF_RETURN_VOID -# define AF_AWAIT KIT_AF_AWAIT -# define AF_YIELD_AWAIT KIT_AF_YIELD_AWAIT -# define AF_TYPE KIT_AF_TYPE -# define AF_INITIAL KIT_AF_INITIAL -# define AF_CREATE KIT_AF_CREATE -# define AF_INIT KIT_AF_INIT -# define AF_FINISHED KIT_AF_FINISHED -# define AF_FINISHED_N KIT_AF_FINISHED_N -# define AF_FINISHED_ALL KIT_AF_FINISHED_ALL -#endif -#endif -// ================================================================ -// -// File: source/kit/file.h -// -// ================================================================ -#ifndef KIT_FILE_H -#define KIT_FILE_H -#include <stdio.h> -#ifdef __cplusplus -extern "C" { -#endif -#if defined(_WIN32) && !defined(__CYGWIN__) -# define KIT_PATH_DELIM_C '\\' -# define KIT_PATH_DELIM "\\" -# define KIT_ENV_HOME "USERPROFILE" -#else -# define KIT_PATH_DELIM_C '/' -# define KIT_PATH_DELIM "/" -# define KIT_ENV_HOME "HOME" -#endif -typedef enum { - KIT_PATH_NONE, - KIT_PATH_FILE, - KIT_PATH_FOLDER -} kit_path_type_t; -typedef struct { - kit_status_t status; - i64 time_modified_sec; - i32 time_modified_nsec; - i64 size; -} kit_file_info_t; -typedef struct { - kit_status_t 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; -#if defined(_WIN32) && !defined(__CYGWIN__) - void *_file; - void *_map; -#else - int _fd; -#endif -} kit_mapped_file_t; -kit_str_builder_t kit_get_env(kit_str_t name, kit_allocator_t *alloc); -kit_str_builder_t kit_path_norm(kit_str_t path, - kit_allocator_t *alloc); -kit_str_builder_t kit_path_join(kit_str_t left, kit_str_t right, - kit_allocator_t *alloc); -kit_str_builder_t kit_path_user(kit_allocator_t *alloc); -kit_str_builder_t kit_path_cache(kit_allocator_t *alloc); -kit_str_builder_t kit_path_data(kit_allocator_t *alloc); -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); -kit_status_t kit_folder_create_recursive(kit_str_t path); -kit_status_t kit_file_remove(kit_str_t path); -kit_status_t kit_folder_remove(kit_str_t path); -kit_status_t kit_file_remove_recursive(kit_str_t path, - kit_allocator_t *alloc); -kit_path_type_t kit_path_type(kit_str_t path); -kit_file_info_t kit_file_info(kit_str_t path); -kit_path_list_t kit_folder_enum(kit_str_t path, - kit_allocator_t *alloc); -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); -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define path_type_t kit_path_type_t -# define file_info_t kit_file_info_t -# define path_list_t kit_path_list_t -# define mapped_file_t kit_mapped_file_t -# define get_env kit_get_env -# define path_norm kit_path_norm -# define path_join kit_path_join -# define path_user kit_path_user -# define path_cache kit_path_cache -# define path_data kit_path_data -# define path_index kit_path_index -# define path_take kit_path_take -# define folder_create kit_folder_create -# define folder_create_recursive kit_folder_create_recursive -# define file_remove kit_file_remove -# define folder_remove kit_folder_remove -# define file_remove_recursive kit_file_remove_recursive -# define path_type kit_path_type -# define file_info kit_file_info -# define folder_enum kit_folder_enum -# define path_list_destroy kit_path_list_destroy -# define file_map kit_file_map -# define file_sync kit_file_sync -# define file_unmap kit_file_unmap -# define FILE_MAP_PRIVATE KIT_FILE_MAP_PRIVATE -# define FILE_MAP_SHARED KIT_FILE_MAP_SHARED -# define PATH_DELIM_C KIT_PATH_DELIM_C -# define PATH_DELIM KIT_PATH_DELIM -# define ENV_HOME KIT_ENV_HOME -# define PATH_NONE KIT_PATH_NONE -# define PATH_FILE KIT_PATH_FILE -# define PATH_FOLDER KIT_PATH_FOLDER -#endif -#endif -// ================================================================ -// -// File: source/kit/mersenne_twister_64.h -// -// ================================================================ -#ifndef KIT_MERSENNE_TWISTER_64_H -#define KIT_MERSENNE_TWISTER_64_H -#ifdef __cplusplus -extern "C" { -#endif -enum { - KIT_MT64_N = 312, -}; -typedef struct { - u64 mt[KIT_MT64_N]; - u64 index; -} kit_mt64_state_t; -void kit_mt64_init_array(kit_mt64_state_t *state, i64 size, - u64 *seed); -void kit_mt64_init(kit_mt64_state_t *state, u64 seed); -void kit_mt64_rotate(kit_mt64_state_t *state); -u64 kit_mt64_generate(kit_mt64_state_t *state); -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define mt64_state_t kit_mt64_state_t -# define mt64_init_array kit_mt64_init_array -# define mt64_init kit_mt64_init -# define mt64_rotate kit_mt64_rotate -# define mt64_generate kit_mt64_generate -#endif -#endif -// ================================================================ -// -// File: source/kit/secure_random.h -// -// ================================================================ -#ifndef KIT_SECURE_RANDOM_H -#define KIT_SECURE_RANDOM_H -#ifdef __cplusplus -extern "C" { -#endif -kit_status_t kit_secure_random(i64 size, void *data); -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define secure_random kit_secure_random -#endif -#endif -// ================================================================ -// -// File: source/kit/sha256.h -// -// ================================================================ -#ifndef KIT_SHA256_H -#define KIT_SHA256_H -#ifdef __cplusplus -extern "C" { -#endif -enum { KIT_SHA256_BLOCK_SIZE = 32 }; -typedef struct { - u8 v[KIT_SHA256_BLOCK_SIZE]; -} kit_sha256_hash_t; -kit_sha256_hash_t kit_sha256(i64 size, u8 *data); -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define SHA256_BLOCK_SIZE KIT_SHA256_BLOCK_SIZE -# define sha256_hash_t kit_sha256_hash_t -# define sha256 kit_sha256 -#endif -#endif -// ================================================================ -// -// File: source/kit/sockets.h -// -// ================================================================ -#ifndef KIT_SOCKETS_H -#define KIT_SOCKETS_H -#ifndef KIT_DISABLE_SYSTEM_SOCKETS -# ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-function" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -# endif -# ifdef __cplusplus -extern "C" { -# endif -# if defined(_WIN32) && !defined(__CYGWIN__) -# define WIN32_LEAN_AND_MEAN -# include <winsock2.h> -# include <ws2tcpip.h> -# define socket_t SOCKET -# define socklen_t i32 -static kit_status_t kit_sockets_init(void) { - WSADATA data; - memset(&data, 0, sizeof data); - WORD version = MAKEWORD(2, 2); - return WSAStartup(version, &data) == ERROR_SUCCESS - ? KIT_OK - : KIT_ERROR_SOCKETS_STARTUP_FAILED; -} -static kit_status_t kit_sockets_cleanup(void) { - WSACleanup(); - return KIT_OK; -} -static i32 kit_socket_set_blocking(socket_t s) { - u_long flag = 0; - return ioctlsocket(s, FIONBIO, &flag) == 0 - ? KIT_OK - : KIT_ERROR_SOCKET_CONTROL_FAILED; -} -static i32 kit_socket_set_nonblocking(socket_t s) { - u_long flag = 1; - return ioctlsocket(s, FIONBIO, &flag) == 0 - ? KIT_OK - : KIT_ERROR_SOCKET_CONTROL_FAILED; -} -# else -# include <arpa/inet.h> -# include <errno.h> -# include <fcntl.h> -# include <netinet/in.h> -# include <signal.h> -# include <sys/ioctl.h> -# include <sys/select.h> -# include <sys/socket.h> -# include <sys/types.h> -# include <unistd.h> -# include <netdb.h> -# define socket_t i32 -# define closesocket close -# define INVALID_SOCKET -1 -static kit_status_t kit_sockets_init(void) { - signal(SIGPIPE, SIG_IGN); - return KIT_OK; -} -static kit_status_t kit_sockets_cleanup(void) { - return KIT_OK; -} -static i32 kit_socket_set_blocking(socket_t s) { - i32 flags = fcntl(s, F_GETFL, 0); - return fcntl(s, F_SETFL, flags & ~O_NONBLOCK) == 0 - ? KIT_OK - : KIT_ERROR_SOCKET_CONTROL_FAILED; -} -static i32 kit_socket_set_nonblocking(socket_t s) { - i32 flags = fcntl(s, F_GETFL, 0); - return fcntl(s, F_SETFL, flags | O_NONBLOCK) == 0 - ? KIT_OK - : KIT_ERROR_SOCKET_CONTROL_FAILED; -} -# endif -# ifdef __cplusplus -} -# endif -# ifdef __GNUC__ -# pragma GCC diagnostic pop -# endif -#endif -#endif -// ================================================================ -// -// File: source/kit/shared_memory.h -// -// ================================================================ -#ifndef KIT_SHARED_MEMORY_H -#define KIT_SHARED_MEMORY_H -#if !defined(_WIN32) || defined(__CYGWIN__) -# include <limits.h> -#endif -#ifdef __cplusplus -extern "C" { -#endif -typedef struct { - kit_status_t status; - i64 size; - u8 *bytes; -#if defined(_WIN32) && !defined(__CYGWIN__) - void *_handle; -#else - i8 _owned; - char _name[NAME_MAX + 1]; -#endif -} kit_shared_memory_t; -enum { - KIT_SHARED_MEMORY_OPEN, - KIT_SHARED_MEMORY_CREATE, -}; -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); -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define shared_memory_t kit_shared_memory_t -# define shared_memory_clean kit_shared_memory_clean -# define shared_memory_open kit_shared_memory_open -# define shared_memory_close kit_shared_memory_close -# define SHARED_MEMORY_OPEN KIT_SHARED_MEMORY_OPEN -# define SHARED_MEMORY_CREATE KIT_SHARED_MEMORY_CREATE -#endif -#endif -// ================================================================ -// -// File: source/kit/xml.h -// -// ================================================================ -#ifndef KIT_XML_H -#define KIT_XML_H -#ifdef __cplusplus -extern "C" { -#endif -typedef struct kit_xml_ kit_xml_t; -typedef struct { - kit_str_builder_t name; - kit_str_builder_t value; -} kit_xml_property_t; -typedef KIT_DA(kit_xml_property_t) kit_da_xml_property_t; -typedef KIT_DA(kit_xml_t) kit_da_xml_t; -struct kit_xml_ { - i8 is_declaration; - kit_str_builder_t tag; - kit_str_builder_t text; - kit_str_builder_t tail; - kit_da_xml_property_t properties; - kit_da_xml_t children; -}; -typedef struct { - kit_status_t status; - kit_xml_t xml; -} kit_xml_parse_result_t; -typedef struct { - kit_status_t status; - kit_str_builder_t text; -} kit_xml_text_t; -kit_xml_parse_result_t kit_xml_parse(kit_is_handle_t is, - kit_allocator_t *alloc); -kit_xml_text_t kit_xml_print(kit_xml_t *xml, kit_allocator_t *alloc); -kit_xml_text_t kit_xml_full_text(kit_xml_t *xml, - kit_allocator_t *alloc); -void kit_xml_destroy(kit_xml_t *xml); -#ifdef __cplusplus -} -#endif -#ifndef KIT_DISABLE_SHORT_NAMES -# define xml_parse kit_xml_parse -# define xml_print kit_xml_print -# define xml_full_text kit_xml_full_text -# define xml_destroy kit_xml_destroy -# define xml_t kit_xml_t -# define xml_property_t kit_xml_property_t -# define xml_parse_result_t kit_xml_parse_result_t -# define xml_text_t kit_xml_text_t -#endif -#endif -#endif -// ================================================================ -// -// IMPLEMENTATION -// -// ================================================================ -#if defined(KIT_IMPLEMENTATION) && !defined(KIT_INL_H_IMPL) -#define KIT_INL_H_IMPL -// ================================================================ -// -// File: source/kit/allocator.c -// -// ================================================================ -#include <assert.h> -#include <string.h> -#ifndef KIT_DISABLE_SYSTEM_MALLOC -# include <stdlib.h> -#endif -static void *kit_allocate_default_(i32 request, i64 size, - i64 previous_size, void *pointer) { -#ifndef KIT_DISABLE_SYSTEM_MALLOC - switch (request) { - case KIT_ALLOCATE: - case KIT_ALLOCATE_ZERO: { - assert(size >= 0); - assert(previous_size == 0); - assert(pointer == NULL); - if (size <= 0) - return NULL; - void *p = malloc(size); - if (p != NULL && request == KIT_ALLOCATE_ZERO) - memset(p, 0, size); - return p; - } - case KIT_REALLOCATE: - case KIT_REALLOCATE_ZERO: { - assert(size >= 0); - assert(previous_size != 0 || pointer == NULL); - assert(previous_size == 0 || pointer != NULL); - if (previous_size == 0 && pointer != NULL) - return NULL; - if (previous_size != 0 && pointer == NULL) - return NULL; - if (size == previous_size) - return pointer; - u8 *p = NULL; - if (size > 0) { - p = (u8 *) malloc(size); - if (p != NULL) { - if (size > 0 && previous_size > 0) - memcpy(p, pointer, - size < previous_size ? size : previous_size); - if (request == KIT_REALLOCATE_ZERO && size > previous_size) - memset(p + previous_size, 0, size - previous_size); - } - } - free(pointer); - return p; - } - case KIT_DEALLOCATE: - assert(size == 0); - assert(pointer != NULL); - if (pointer != NULL) - free(pointer); - return NULL; - case KIT_DEALLOCATE_ALL: - // Do nothing. - // - return NULL; - default:; - } -#endif - assert(0); - return NULL; -} -static void *kit_allocate_from_buffer_(kit_allocator_t *alloc, - i32 request, i64 size, - i64 previous_size, - void *pointer) { - assert(alloc != NULL); - assert(pointer == NULL || pointer < alloc->data); - if (alloc == NULL) - return NULL; - switch (request) { - case KIT_ALLOCATE: - case KIT_ALLOCATE_ZERO: { - assert(size >= 0); - assert(previous_size == 0); - assert(pointer == NULL); - if (size <= 0) - return NULL; - if (alloc->size < size) - return NULL; - void *p = alloc->data; - alloc->bytes += size; - alloc->size -= size; - if (request == KIT_ALLOCATE_ZERO) - memset(p, 0, size); - return p; - } - case KIT_REALLOCATE: - case KIT_REALLOCATE_ZERO: { - assert(size >= 0); - assert(previous_size != 0 || pointer == NULL); - assert(previous_size == 0 || pointer != NULL); - if (size <= 0) - return NULL; - if (size <= previous_size) - return pointer; - if (previous_size == 0 && pointer != NULL) - return NULL; - if (previous_size != 0 && pointer == NULL) - return NULL; - if ((u8 *) pointer + previous_size == alloc->data) { - if (alloc->size < size - previous_size) - return NULL; - alloc->bytes += size - previous_size; - alloc->size -= size - previous_size; - return pointer; - } - if (alloc->size < size) - return NULL; - u8 *p = alloc->bytes; - alloc->bytes += size; - alloc->size -= size; - if (previous_size > 0) - memcpy(p, pointer, previous_size); - if (request == KIT_REALLOCATE_ZERO) - memset(p + previous_size, 0, size - previous_size); - return p; - } - case KIT_DEALLOCATE: - case KIT_DEALLOCATE_ALL: return NULL; - default:; - } - assert(0); - return NULL; -} -#ifndef KIT_ENABLE_CUSTOM_ALLOC_DISPATCH -void *kit_alloc_dispatch(kit_allocator_t *alloc, i32 request, - i64 size, i64 previous_size, void *pointer) { - if (alloc == NULL) - return kit_allocate_default_(request, size, previous_size, - pointer); - switch (alloc->type) { - case KIT_ALLOC_TYPE_DEFAULT: - return kit_allocate_default_(request, size, previous_size, - pointer); - case KIT_ALLOC_TYPE_BUFFER: - return kit_allocate_from_buffer_(alloc, request, - // alignment - ((size + 7) / 8) * 8, - previous_size, pointer); - default:; - } - return NULL; -} -#endif -kit_allocator_t kit_alloc_default(void) { - kit_allocator_t alloc = { .type = KIT_ALLOC_TYPE_DEFAULT, - .size = 0, - .data = NULL }; - return alloc; -} -kit_allocator_t kit_alloc_buffer(i64 size, void *buffer) { - kit_allocator_t alloc = { .type = KIT_ALLOC_TYPE_BUFFER, - .size = size, - .data = buffer }; - return alloc; -} -// ================================================================ -// -// File: source/kit/atomic.win32.c -// -// ================================================================ -#ifdef _MSC_VER -static_assert(sizeof(char) == 1, "Wrong char size"); -static_assert(sizeof(short) == 2, "Wrong short size"); -static_assert(sizeof(int) == 4, "Wrong int size"); -# include <intrin.h> -void kit_atomic_store_explicit_8(u8 volatile *var, u8 value, - i32 memory_order) { - char volatile *dst = (char volatile *) var; - char src = (char) value; - switch (memory_order) { - case memory_order_relaxed: *dst = src; break; - default: _InterlockedExchange8(dst, src); - } -} -void kit_atomic_store_explicit_16(u16 volatile *var, u16 value, - i32 memory_order) { - short volatile *dst = (short volatile *) var; - short src = (short) value; - switch (memory_order) { - case memory_order_relaxed: *dst = src; break; - default: _InterlockedExchange16(dst, src); - } -} -void kit_atomic_store_explicit_32(u32 volatile *var, u32 value, - i32 memory_order) { - int volatile *dst = (int volatile *) var; - int src = (int) value; - switch (memory_order) { - case memory_order_relaxed: *dst = src; break; - default: _InterlockedExchange(dst, src); - } -} -void kit_atomic_store_explicit_64(u64 volatile *var, u64 value, - i32 memory_order) { - __int64 volatile *dst = (__int64 volatile *) var; - __int64 src = (__int64) value; - switch (memory_order) { - case memory_order_relaxed: *dst = src; break; - default: -# ifdef _WIN64 - _InterlockedExchange64(dst, src); -# else - assert(0); - _InterlockedExchange((int volatile *) dst, (int) src); -# endif - } -} -u8 kit_atomic_load_explicit_8(volatile u8 *var, i32 memory_order) { - char volatile *dst = (char volatile *) var; - if (memory_order == memory_order_relaxed) - return (u8) *dst; - return (u8) _InterlockedOr8(dst, 0); -} -u16 kit_atomic_load_explicit_16(u16 volatile *var, i32 memory_order) { - short volatile *dst = (short volatile *) var; - if (memory_order == memory_order_relaxed) - return (u16) *dst; - return (u16) _InterlockedOr16(dst, 0); -} -u32 kit_atomic_load_explicit_32(u32 volatile *var, i32 memory_order) { - int volatile *dst = (int volatile *) var; - if (memory_order == memory_order_relaxed) - return (u32) *dst; - return (u32) _InterlockedOr(dst, 0); -} -u64 kit_atomic_load_explicit_64(u64 volatile *var, i32 memory_order) { - __int64 volatile *dst = (__int64 volatile *) var; - if (memory_order == memory_order_relaxed) - return (u64) *dst; -# ifdef _WIN64 - return (u64) _InterlockedOr64(dst, 0); -# else - assert(0); - return (u64) _InterlockedOr((int volatile *) dst, 0); -# endif -} -u8 kit_atomic_exchange_explicit_8(volatile u8 *var, u8 value, - i32 memory_order) { - char volatile *dst = (char volatile *) var; - char src = (char) value; - return (u8) _InterlockedExchange8(dst, src); -} -u16 kit_atomic_exchange_explicit_16(u16 volatile *var, u16 value, - i32 memory_order) { - short volatile *dst = (short volatile *) var; - short src = (short) value; - return (u16) _InterlockedExchange16(dst, src); -} -u32 kit_atomic_exchange_explicit_32(u32 volatile *var, u32 value, - i32 memory_order) { - int volatile *dst = (int volatile *) var; - int src = (int) value; - return (u32) _InterlockedExchange(dst, src); -} -u64 kit_atomic_exchange_explicit_64(u64 volatile *var, u64 value, - i32 memory_order) { - __int64 volatile *dst = (__int64 volatile *) var; - __int64 src = (__int64) value; -# ifdef _WIN64 - return (u64) _InterlockedExchange64(dst, src); -# else - assert(0); - return (u64) _InterlockedExchange((int volatile *) dst, (int) src); -# endif -} -int kit_atomic_compare_exchange_explicit_8(volatile u8 *var, - u8 *expected, u8 value, - i32 memory_order_succ_, - i32 memory_order_fail_) { - char volatile *dst = (char volatile *) var; - char src = (char) value; - char exp = (char) *expected; - *expected = (u8) _InterlockedCompareExchange8(dst, src, exp); - return exp == (char) *expected; -} -int kit_atomic_compare_exchange_explicit_16(u16 volatile *var, - u16 *expected, u16 value, - i32 memory_order_succ_, - i32 memory_order_fail_) { - short volatile *dst = (short volatile *) var; - short src = (short) value; - short exp = (short) *expected; - *expected = (u16) _InterlockedCompareExchange16(dst, src, exp); - return exp == (short) *expected; -} -int kit_atomic_compare_exchange_explicit_32(u32 volatile *var, - u32 *expected, u32 value, - i32 memory_order_succ_, - i32 memory_order_fail_) { - int volatile *dst = (int volatile *) var; - int src = (int) value; - int exp = (int) *expected; - *expected = (u32) _InterlockedCompareExchange(dst, src, exp); - return exp == (int) *expected; -} -int kit_atomic_compare_exchange_explicit_64(u64 volatile *var, - u64 *expected, u64 value, - i32 memory_order_succ_, - i32 memory_order_fail_) { - __int64 volatile *dst = (__int64 volatile *) var; - __int64 src = (__int64) value; - __int64 exp = (__int64) *expected; -# ifdef _WIN64 - *expected = (u64) _InterlockedCompareExchange64(dst, src, exp); -# else - assert(0); - *expected = (u64) _InterlockedCompareExchange((int volatile *) dst, - (int) src, (int) exp); -# endif - return exp == (__int64) *expected; -} -u8 kit_atomic_fetch_add_explicit_8(volatile u8 *var, u8 value, - i32 memory_order) { - char volatile *dst = (char volatile *) var; - char src = (char) value; - return (u8) _InterlockedExchangeAdd8(dst, src); -} -u16 kit_atomic_fetch_add_explicit_16(u16 volatile *var, u16 value, - i32 memory_order) { - short volatile *dst = (short volatile *) var; - short src = (short) value; - return (u16) _InterlockedExchangeAdd16(dst, src); -} -u32 kit_atomic_fetch_add_explicit_32(u32 volatile *var, u32 value, - i32 memory_order) { - int volatile *dst = (int volatile *) var; - int src = (int) value; - return (u32) _InterlockedExchangeAdd(dst, src); -} -u64 kit_atomic_fetch_add_explicit_64(u64 volatile *var, u64 value, - i32 memory_order) { - __int64 volatile *dst = (__int64 volatile *) var; - __int64 src = (__int64) value; -# ifdef _WIN64 - return (u64) _InterlockedExchangeAdd64(dst, src); -# else - assert(0); - return (u64) _InterlockedExchangeAdd((int volatile *) dst, - (int) src); -# endif -} -#endif -// ================================================================ -// -// File: source/kit/threads.posix.c -// -// ================================================================ -#ifndef KIT_DISABLE_SYSTEM_THREADS -# if !defined(_WIN32) || defined(__CYGWIN__) -# include <assert.h> -# include <errno.h> -# include <limits.h> -# include <sched.h> -# include <stdlib.h> -# include <unistd.h> -# ifndef PTHREAD_STACK_MIN -# define PTHREAD_STACK_MIN 16384 -# endif -/* -Configuration macro: - EMULATED_THREADS_USE_NATIVE_TIMEDLOCK - Use pthread_mutex_timedlock() for `mtx_timedlock()' - Otherwise use mtx_trylock() + *busy loop* emulation. -*/ -# if !defined(__CYGWIN__) && !defined(__APPLE__) && \ - !defined(__NetBSD__) -# define EMULATED_THREADS_USE_NATIVE_TIMEDLOCK -# endif -/* -Implementation limits: - - Conditionally emulation for "mutex with timeout" - (see EMULATED_THREADS_USE_NATIVE_TIMEDLOCK macro) -*/ -typedef struct { - thrd_start_t func; - void *arg; -} impl_thrd_param_t; -static void *impl_thrd_routine(void *p) { - impl_thrd_param_t pack = *((impl_thrd_param_t *) p); - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, p); - return (void *) (intptr_t) pack.func(pack.arg); -} -void call_once(once_flag *flag, void (*func)(void)) { - pthread_once(flag, func); -} -int cnd_broadcast(cnd_t *cond) { - assert(cond != NULL); - return (pthread_cond_broadcast(cond) == 0) ? thrd_success - : thrd_error; -} -void cnd_destroy(cnd_t *cond) { - assert(cond); - pthread_cond_destroy(cond); -} -int cnd_init(cnd_t *cond) { - assert(cond != NULL); - return (pthread_cond_init(cond, NULL) == 0) ? thrd_success - : thrd_error; -} -int cnd_signal(cnd_t *cond) { - assert(cond != NULL); - return (pthread_cond_signal(cond) == 0) ? thrd_success : thrd_error; -} -int cnd_timedwait(cnd_t *cond, mtx_t *mtx, - struct timespec const *abs_time) { - int rt; - assert(mtx != NULL); - assert(cond != NULL); - assert(abs_time != NULL); - rt = pthread_cond_timedwait(cond, mtx, abs_time); - if (rt == ETIMEDOUT) - return thrd_timedout; - return (rt == 0) ? thrd_success : thrd_error; -} -int cnd_wait(cnd_t *cond, mtx_t *mtx) { - assert(mtx != NULL); - assert(cond != NULL); - return (pthread_cond_wait(cond, mtx) == 0) ? thrd_success - : thrd_error; -} -void mtx_destroy(mtx_t *mtx) { - assert(mtx != NULL); - pthread_mutex_destroy(mtx); -} -/* - * XXX: Workaround when building with -O0 and without pthreads link. - * - * In such cases constant folding and dead code elimination won't be - * available, thus the compiler will always add the pthread_mutexattr* - * functions into the binary. As we try to link, we'll fail as the - * symbols are unresolved. - * - * Ideally we'll enable the optimisations locally, yet that does not - * seem to work. - * - * So the alternative workaround is to annotate the symbols as weak. - * Thus the linker will be happy and things don't clash when building - * with -O1 or greater. - */ -# if defined(KIT_HAVE_FUNC_ATTRIBUTE_WEAK) && !defined(__CYGWIN__) -__attribute__((weak)) int pthread_mutexattr_init( - pthread_mutexattr_t *attr); -__attribute__((weak)) int pthread_mutexattr_settype( - pthread_mutexattr_t *attr, int type); -__attribute__((weak)) int pthread_mutexattr_destroy( - pthread_mutexattr_t *attr); -# endif -int mtx_init(mtx_t *mtx, int type) { -# ifdef KIT_HAVE_PTHREAD_MUTEXATTR_SETTYPE - pthread_mutexattr_t attr; -# endif - assert(mtx != NULL); - if (type != mtx_plain && type != mtx_timed && - type != (mtx_plain | mtx_recursive) && - type != (mtx_timed | mtx_recursive)) - return thrd_error; - if ((type & mtx_recursive) == 0) { - pthread_mutex_init(mtx, NULL); - return thrd_success; - } -# ifdef KIT_HAVE_PTHREAD_MUTEXATTR_SETTYPE - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(mtx, &attr); - pthread_mutexattr_destroy(&attr); - return thrd_success; -# else - return thrd_error; -# endif -} -int mtx_lock(mtx_t *mtx) { - assert(mtx != NULL); - return (pthread_mutex_lock(mtx) == 0) ? thrd_success : thrd_error; -} -int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) { - assert(mtx != NULL); - assert(ts != NULL); - { -# ifdef EMULATED_THREADS_USE_NATIVE_TIMEDLOCK - int rt; - rt = pthread_mutex_timedlock(mtx, ts); - if (rt == 0) - return thrd_success; - return (rt == ETIMEDOUT) ? thrd_timedout : thrd_error; -# else - time_t expire = time(NULL); - expire += ts->tv_sec; - while (mtx_trylock(mtx) != thrd_success) { - time_t now = time(NULL); - if (expire < now) - return thrd_timedout; - // busy loop! - thrd_yield(); - } - return thrd_success; -# endif - } -} -int mtx_trylock(mtx_t *mtx) { - assert(mtx != NULL); - return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy; -} -int mtx_unlock(mtx_t *mtx) { - assert(mtx != NULL); - return (pthread_mutex_unlock(mtx) == 0) ? thrd_success : thrd_error; -} -int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg, - ptrdiff_t const require_stack_size) { - impl_thrd_param_t *pack; - assert(thr != NULL); - assert(require_stack_size == 0 || - require_stack_size >= PTHREAD_STACK_MIN); - pthread_attr_t attr; - pthread_attr_t *attr_p = NULL; - if (require_stack_size > 0) { - ptrdiff_t const page_size = (ptrdiff_t) sysconf(_SC_PAGESIZE); - ptrdiff_t const delta = require_stack_size % page_size; - ptrdiff_t const stack_size = delta == 0 ? require_stack_size - : require_stack_size + - page_size - delta; - if (pthread_attr_init(&attr) != 0) - return thrd_nomem; - if (pthread_attr_setstacksize(&attr, (size_t) stack_size) != 0) - return thrd_wrong_stack_size; - attr_p = &attr; - } - pack = (impl_thrd_param_t *) kit_alloc_dispatch( - NULL, KIT_ALLOCATE, sizeof(impl_thrd_param_t), 0, NULL); - if (!pack) { - if (attr_p) - pthread_attr_destroy(attr_p); - return thrd_nomem; - } - pack->func = func; - pack->arg = arg; - if (pthread_create(thr, attr_p, impl_thrd_routine, pack) != 0) { - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, pack); - if (attr_p) - pthread_attr_destroy(attr_p); - return thrd_error; - } - if (attr_p) - pthread_attr_destroy(attr_p); - return thrd_success; -} -int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { - return thrd_create_with_stack(thr, func, arg, 0); -} -thrd_t thrd_current(void) { - return pthread_self(); -} -int thrd_detach(thrd_t thr) { - return (pthread_detach(thr) == 0) ? thrd_success : thrd_error; -} -int thrd_equal(thrd_t thr0, thrd_t thr1) { - return pthread_equal(thr0, thr1); -} -_Noreturn void thrd_exit(int res) { - pthread_exit((void *) (intptr_t) res); -} -int thrd_join(thrd_t thr, int *res) { - void *code; - if (pthread_join(thr, &code) != 0) - return thrd_error; - if (res) - *res = (int) (intptr_t) code; - return thrd_success; -} -int thrd_sleep(const struct timespec *time_point, - struct timespec *remaining) { - assert(time_point != NULL); - return nanosleep(time_point, remaining); -} -void thrd_yield(void) { - sched_yield(); -} -# endif -#endif -// ================================================================ -// -// File: source/kit/threads.win32.c -// -// ================================================================ -#ifndef KIT_DISABLE_SYSTEM_THREADS -# if defined(_WIN32) && !defined(__CYGWIN__) -# include <assert.h> -# include <errno.h> -# include <limits.h> -# include <process.h> -# include <stdlib.h> -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 -# endif -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include <windows.h> -/* -Configuration macro: - EMULATED_THREADS_USE_NATIVE_CALL_ONCE - Use native WindowsAPI one-time initialization function. - (requires WinVista or later) - Otherwise emulate by mtx_trylock() + *busy loop* for WinXP. - EMULATED_THREADS_TSS_DTOR_SLOTNUM - Max registerable TSS dtor number. -*/ -# if _WIN32_WINNT >= 0x0600 -/* Prefer native WindowsAPI on newer environment. */ -# if !defined(__MINGW32__) -# define EMULATED_THREADS_USE_NATIVE_CALL_ONCE -# endif -# endif -# define EMULATED_THREADS_TSS_DTOR_SLOTNUM \ - 64 /* see TLS_MINIMUM_AVAILABLE */ -/* check configuration */ -# if defined(EMULATED_THREADS_USE_NATIVE_CALL_ONCE) && \ - (_WIN32_WINNT < 0x0600) -# error EMULATED_THREADS_USE_NATIVE_CALL_ONCE requires _WIN32_WINNT>=0x0600 -# endif -static_assert(sizeof(cnd_t) == sizeof(CONDITION_VARIABLE), - "The size of cnd_t must equal to CONDITION_VARIABLE"); -static_assert(sizeof(thrd_t) == sizeof(HANDLE), - "The size of thrd_t must equal to HANDLE"); -static_assert(sizeof(tss_t) == sizeof(DWORD), - "The size of tss_t must equal to DWORD"); -static_assert(sizeof(mtx_t) == sizeof(CRITICAL_SECTION), - "The size of mtx_t must equal to CRITICAL_SECTION"); -static_assert(sizeof(once_flag) == sizeof(INIT_ONCE), - "The size of once_flag must equal to INIT_ONCE"); -/* -Implementation limits: - - Conditionally emulation for "Initialization functions" - (see EMULATED_THREADS_USE_NATIVE_CALL_ONCE macro) - - Emulated `mtx_timelock()' with mtx_trylock() + *busy loop* -*/ -typedef struct { - thrd_start_t func; - void *arg; - thrd_t thrd; -} impl_thrd_param_t; -struct thrd_state { - thrd_t thrd; - int handle_need_close; -}; -static thread_local struct thrd_state impl_current_thread = { 0 }; -static unsigned __stdcall impl_thrd_routine(void *p) { - impl_thrd_param_t *pack_p = (impl_thrd_param_t *) p; - impl_thrd_param_t pack; - int code; - impl_current_thread.thrd = pack_p->thrd; - impl_current_thread.handle_need_close = 0; - memcpy(&pack, pack_p, sizeof(impl_thrd_param_t)); - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, p); - code = pack.func(pack.arg); - return (unsigned) code; -} -static time_t impl_timespec2msec(const struct timespec *ts) { - return (ts->tv_sec * 1000U) + (ts->tv_nsec / 1000000L); -} -static DWORD impl_abs2relmsec(const struct timespec *abs_time) { - const time_t abs_ms = impl_timespec2msec(abs_time); - struct timespec now; - timespec_get(&now, TIME_UTC); - const time_t now_ms = impl_timespec2msec(&now); - const DWORD rel_ms = (abs_ms > now_ms) ? (DWORD) (abs_ms - now_ms) - : 0; - return rel_ms; -} -# ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE -struct impl_call_once_param { - void (*func)(void); -}; -static BOOL CALLBACK impl_call_once_callback(PINIT_ONCE InitOnce, - PVOID Parameter, - PVOID *Context) { - struct impl_call_once_param *param = (struct impl_call_once_param *) - Parameter; - (param->func)(); - ((void) InitOnce); - ((void) Context); /* suppress warning */ - return TRUE; -} -# endif /* ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE */ -static struct impl_tss_dtor_entry { - tss_t key; - tss_dtor_t dtor; -} impl_tss_dtor_tbl[EMULATED_THREADS_TSS_DTOR_SLOTNUM]; -static int impl_tss_dtor_register(tss_t key, tss_dtor_t dtor) { - int i; - for (i = 0; i < EMULATED_THREADS_TSS_DTOR_SLOTNUM; i++) { - if (!impl_tss_dtor_tbl[i].dtor) - break; - } - if (i == EMULATED_THREADS_TSS_DTOR_SLOTNUM) - return 1; - impl_tss_dtor_tbl[i].key = key; - impl_tss_dtor_tbl[i].dtor = dtor; - return 0; -} -static void impl_tss_dtor_invoke(void) { - int i; - for (i = 0; i < EMULATED_THREADS_TSS_DTOR_SLOTNUM; i++) { - if (impl_tss_dtor_tbl[i].dtor) { - void *val = (void *) (size_t) TlsGetValue( - impl_tss_dtor_tbl[i].key); - if (val) - (impl_tss_dtor_tbl[i].dtor)(val); - } - } -} -void call_once(once_flag *flag, void (*func)(void)) { - assert(flag && func); -# ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE - { - struct impl_call_once_param param; - param.func = func; - InitOnceExecuteOnce((PINIT_ONCE) flag, impl_call_once_callback, - (PVOID) ¶m, NULL); - } -# else - if (InterlockedCompareExchangePointer( - (PVOID volatile *) &flag->status, (PVOID) 1, (PVOID) 0) == - 0) { - (func)(); - InterlockedExchangePointer((PVOID volatile *) &flag->status, - (PVOID) 2); - } else { - while (flag->status == 1) { - // busy loop! - thrd_yield(); - } - } -# endif -} -int cnd_broadcast(cnd_t *cond) { - assert(cond != NULL); - WakeAllConditionVariable((PCONDITION_VARIABLE) cond); - return thrd_success; -} -void cnd_destroy(cnd_t *cond) { - assert(cond != NULL); - /* do nothing */ - (void) cond; -} -int cnd_init(cnd_t *cond) { - assert(cond != NULL); - InitializeConditionVariable((PCONDITION_VARIABLE) cond); - return thrd_success; -} -int cnd_signal(cnd_t *cond) { - assert(cond != NULL); - WakeConditionVariable((PCONDITION_VARIABLE) cond); - return thrd_success; -} -int cnd_timedwait(cnd_t *cond, mtx_t *mtx, - const struct timespec *abs_time) { - assert(cond != NULL); - assert(mtx != NULL); - assert(abs_time != NULL); - const DWORD timeout = impl_abs2relmsec(abs_time); - if (SleepConditionVariableCS((PCONDITION_VARIABLE) cond, - (PCRITICAL_SECTION) mtx, timeout)) - return thrd_success; - return (GetLastError() == ERROR_TIMEOUT) ? thrd_timedout - : thrd_error; -} -int cnd_wait(cnd_t *cond, mtx_t *mtx) { - assert(cond != NULL); - assert(mtx != NULL); - SleepConditionVariableCS((PCONDITION_VARIABLE) cond, - (PCRITICAL_SECTION) mtx, INFINITE); - return thrd_success; -} -void mtx_destroy(mtx_t *mtx) { - assert(mtx); - DeleteCriticalSection((PCRITICAL_SECTION) mtx); -} -int mtx_init(mtx_t *mtx, int type) { - assert(mtx != NULL); - if (type != mtx_plain && type != mtx_timed && - type != (mtx_plain | mtx_recursive) && - type != (mtx_timed | mtx_recursive)) - return thrd_error; - InitializeCriticalSection((PCRITICAL_SECTION) mtx); - return thrd_success; -} -int mtx_lock(mtx_t *mtx) { - assert(mtx != NULL); - EnterCriticalSection((PCRITICAL_SECTION) mtx); - return thrd_success; -} -int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) { - assert(mtx != NULL); - assert(ts != NULL); - while (mtx_trylock(mtx) != thrd_success) { - if (impl_abs2relmsec(ts) == 0) - return thrd_timedout; - /* busy loop! */ - thrd_yield(); - } - return thrd_success; -} -int mtx_trylock(mtx_t *mtx) { - assert(mtx != NULL); - return TryEnterCriticalSection((PCRITICAL_SECTION) mtx) - ? thrd_success - : thrd_busy; -} -int mtx_unlock(mtx_t *mtx) { - assert(mtx != NULL); - LeaveCriticalSection((PCRITICAL_SECTION) mtx); - return thrd_success; -} -int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg, - ptrdiff_t const stack_size) { - impl_thrd_param_t *pack; - uintptr_t handle; - assert(thr != NULL); - assert(stack_size >= 0 && stack_size < 0x100000000); - pack = (impl_thrd_param_t *) kit_alloc_dispatch( - NULL, KIT_ALLOCATE, (sizeof(impl_thrd_param_t)), 0, NULL); - if (!pack) - return thrd_nomem; - pack->func = func; - pack->arg = arg; - handle = _beginthreadex(NULL, (unsigned) stack_size, - impl_thrd_routine, pack, CREATE_SUSPENDED, - NULL); - if (handle == 0) { - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, pack); - if (errno == EAGAIN || errno == EACCES) - return thrd_nomem; - return thrd_error; - } - thr->handle = (void *) handle; - pack->thrd = *thr; - ResumeThread((HANDLE) handle); - return thrd_success; -} -int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { - return thrd_create_with_stack(thr, func, arg, 0); -} -thrd_t thrd_current(void) { - /* GetCurrentThread() returns a pseudo-handle, which we need - * to pass to DuplicateHandle(). Only the resulting handle can be - * used from other threads. - * - * Note that neither handle can be compared to the one by - * thread_create. Only the thread IDs - as returned by GetThreadId() - * and GetCurrentThreadId() can be compared directly. - * - * Other potential solutions would be: - * - define thrd_t as a thread Ids, but this would mean we'd need to - * OpenThread for many operations - * - use malloc'ed memory for thrd_t. This would imply using TLS for - * current thread. - * - * Neither is particularly nice. - * - * Life would be much easier if C11 threads had different - * abstractions for threads and thread IDs, just like C++11 threads - * does... - */ - struct thrd_state *state = &impl_current_thread; - if (state->thrd.handle == NULL) { - if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &(state->thrd.handle), - 0, FALSE, DUPLICATE_SAME_ACCESS)) { - abort(); - } - state->handle_need_close = 1; - } - return state->thrd; -} -int thrd_detach(thrd_t thr) { - CloseHandle(thr.handle); - return thrd_success; -} -int thrd_equal(thrd_t thr0, thrd_t thr1) { - return GetThreadId(thr0.handle) == GetThreadId(thr1.handle); -} -_Noreturn void thrd_exit(int res) { - _endthreadex((unsigned) res); -} -int thrd_join(thrd_t thr, int *res) { - DWORD w, code; - if (thr.handle == NULL) { - return thrd_error; - } - w = WaitForSingleObject(thr.handle, INFINITE); - if (w != WAIT_OBJECT_0) - return thrd_error; - if (res) { - if (!GetExitCodeThread(thr.handle, &code)) { - CloseHandle(thr.handle); - return thrd_error; - } - *res = (int) code; - } - CloseHandle(thr.handle); - return thrd_success; -} -int thrd_sleep(const struct timespec *time_point, - struct timespec *remaining) { - (void) remaining; - assert(time_point); - assert(!remaining); /* not implemented */ - Sleep((DWORD) impl_timespec2msec(time_point)); - return 0; -} -void thrd_yield(void) { - SwitchToThread(); -} -# endif -#endif -// ================================================================ -// -// File: source/kit/array_ref.c -// -// ================================================================ -#include <string.h> -i8 kit_ar_equal_bytes(i64 left_element_size, i64 left_size, - void *left_data, i64 right_element_size, - i64 right_size, void *right_data) { - i64 i; - if (left_element_size != right_element_size) - return 0; - if (left_size != right_size) - return 0; - for (i = 0; i < left_size; i++) - if (memcmp((u8 *) left_data + i * left_element_size, - (u8 *) right_data + i * left_element_size, - left_element_size) != 0) - return 0; - return 1; -} -i8 kit_ar_compare(i64 left_element_size, i64 left_size, - void *left_data, i64 right_element_size, - i64 right_size, void *right_data, - kit_ar_compare_fn compare) { - i64 i; - if (left_element_size < right_element_size) - return -1; - if (left_element_size > right_element_size) - return 1; - for (i = 0; i < left_size && i < right_size; i++) { - i8 c = compare((u8 *) left_data + i * left_element_size, - (u8 *) 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; -} -// ================================================================ -// -// File: source/kit/dynamic_array.c -// -// ================================================================ -#include <assert.h> -void kit_da_init(kit_da_void_t *array, i64 element_size, i64 size, - kit_allocator_t *alloc) { - assert(array != NULL); - assert(element_size > 0); - assert(size >= 0); - memset(array, 0, sizeof(kit_da_void_t)); - if (size > 0) - array->values = kit_alloc_dispatch(alloc, KIT_ALLOCATE, - element_size * size, 0, NULL); - if (array->values != NULL) { - array->capacity = size; - array->size = size; - } - array->alloc = alloc; -} -static i64 eval_capacity(i64 current_cap, i64 required_cap) { - if (current_cap == 0) - return required_cap; - i64 cap = current_cap; - while (cap < required_cap) cap *= 2; - return cap; -} -void kit_da_resize(kit_da_void_t *array, i64 element_size, i64 size) { - assert(array != NULL); - assert(element_size > 0); - assert(size >= 0); - if (size <= array->capacity) { - array->size = size; - } else { - i64 capacity = eval_capacity(array->capacity, size); - void *bytes = kit_alloc_dispatch( - array->alloc, KIT_ALLOCATE, element_size * capacity, 0, NULL); - if (bytes != NULL) { - if (array->size > 0) - memcpy(bytes, array->values, element_size * array->size); - if (array->values != NULL) - kit_alloc_dispatch(array->alloc, KIT_DEALLOCATE, 0, 0, - array->values); - array->capacity = capacity; - array->size = size; - array->values = bytes; - } - } -} -void kit_da_resize_exact(kit_da_void_t *array, i64 element_size, - i64 capacity) { - assert(array != NULL); - assert(element_size > 0); - assert(capacity >= 0); - void *bytes = capacity <= 0 - ? NULL - : kit_alloc_dispatch(array->alloc, KIT_ALLOCATE, - element_size * capacity, 0, - NULL); - if (bytes != NULL || capacity == 0) { - if (array->size > 0 && capacity > 0) - memcpy(bytes, array->values, element_size * array->size); - if (array->values != NULL) - kit_alloc_dispatch(array->alloc, KIT_DEALLOCATE, 0, 0, - array->values); - array->capacity = capacity; - array->size = capacity; - array->values = bytes; - } -} -// ================================================================ -// -// File: source/kit/input_stream.c -// -// ================================================================ -#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); -} -// ================================================================ -// -// File: source/kit/input_buffer.c -// -// ================================================================ -#include <assert.h> -#include <string.h> -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); - } - return buf; -} -static kit_allocator_t *kit_buf_alloc_(void *p) { - assert(p != NULL); - return ((internal_buffer_t *) p)->alloc; -} -static void kit_buf_acquire_(void *p) { - assert(p != NULL); - ((internal_buffer_t *) p)->ref_count++; -} -static void kit_buf_release_(void *p) { - if (p == NULL) - return; - internal_buffer_t *buf = (internal_buffer_t *) p; - if (--buf->ref_count == 0) { - DA_DESTROY(buf->data); - kit_alloc_dispatch(buf->alloc, KIT_DEALLOCATE, 0, 0, buf); - } -} -static void kit_buf_adjust_(void *p, i64 size) { - assert(p != NULL); - assert(size >= 0); - internal_buffer_t *buf = (internal_buffer_t *) p; - i64 offset = buf->data.size; - 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); - } -} -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; -} -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_t kit_ib_copy(kit_ib_t buf) { - kit_ib_t next; - memset(&next, 0, sizeof next); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } - kit_buf_acquire_(buf.internal); - next.offset = buf.offset; - next.internal = buf.internal; - return next; -} -kit_ib_t kit_ib_read(kit_ib_t buf, i64 size) { - kit_ib_t next; - memset(&next, 0, sizeof next); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } - kit_buf_acquire_(buf.internal); - kit_buf_adjust_(buf.internal, buf.offset + size); - DA_INIT(next.data, size, kit_buf_alloc_(buf.internal)); - if (next.data.size != size) - next.status = KIT_ERROR_BAD_ALLOC; - 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; - DA_RESIZE(next.data, n); - if (next.data.size != n) - next.status = KIT_ERROR_BAD_ALLOC; - 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); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } - kit_buf_acquire_(buf.internal); - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); - i64 size = 0; - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); - DA_RESIZE(next.data, size + 1); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; - 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) - break; - i8 found = 0; - for (i64 i = 0; i < data.size; i++) - if (data.values[i] == destination.values[0]) { - found = 1; - break; - } - if (!found) - 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; -} -kit_ib_t kit_ib_none(kit_ib_t buf, kit_str_t data) { - kit_ib_t next; - memset(&next, 0, sizeof next); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } - kit_buf_acquire_(buf.internal); - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); - i64 size = 0; - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); - DA_RESIZE(next.data, size + 1); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; - 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) - break; - i8 found = 0; - for (i64 i = 0; i < data.size; i++) - if (data.values[i] == destination.values[0]) { - found = 1; - break; - } - if (found) - 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; -} -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; - 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); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } - kit_buf_acquire_(buf.internal); - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); - i64 size = 0; - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); - DA_RESIZE(next.data, size + 1); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; - 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) - break; - if (size + 1 >= data.size && - AR_EQUAL(kit_str(data.size, - next.data.values + (size + 1 - data.size)), - data)) { - 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; - 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); - if (buf.status != KIT_OK) { - next.status = buf.status; - return next; - } - kit_buf_acquire_(buf.internal); - DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); - i64 size = 0; - for (;; ++size) { - kit_buf_adjust_(buf.internal, buf.offset + size + 1); - DA_RESIZE(next.data, size + 1); - assert(next.data.size == size + 1); - if (next.data.size != size + 1) { - next.status = KIT_ERROR_BAD_ALLOC; - return next; - } - kit_str_t destination = { .size = 1, - .values = next.data.values + size }; - i64 n = kit_buf_read_(buf.internal, buf.offset + size, - destination); - kit_str_t data = { .size = size + 1, .values = next.data.values }; - if (n != 1 || condition == NULL || condition(data, context) == 0) - 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); -} -// ================================================================ -// -// File: source/kit/file.c -// -// ================================================================ -#include <assert.h> -#include <stdlib.h> -#include <string.h> -enum { PATH_BUF_SIZE = 4096 }; -#if defined(_WIN32) && !defined(__CYGWIN__) -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include <windows.h> -# include <shlwapi.h> -#else -# include <dirent.h> -# include <sys/mman.h> -# include <sys/stat.h> -# include <fcntl.h> -# include <unistd.h> -# include <limits.h> -#endif -#ifdef __APPLE__ -# define st_mtim st_mtimespec -#endif -#ifndef PATH_MAX -# define PATH_MAX MAX_PATH -#endif -static i32 is_delim(char c) { - return c == '/' || c == '\\'; -} -kit_str_builder_t kit_get_env(kit_str_t name, - kit_allocator_t *alloc) { - char *val = getenv(BS(name)); - i64 size = val != NULL ? (i64) strlen(val) : 0; - str_builder_t result; - DA_INIT(result, size, alloc); - assert(result.size == size); - if (result.size == size && size > 0) - memcpy(result.values, val, result.size); - else - DA_RESIZE(result, 0); - return result; -} -kit_str_builder_t kit_path_norm(kit_str_t path, - kit_allocator_t *alloc) { - str_t parent = SZ(".."); - i64 i, i1, j; - str_builder_t norm; - DA_INIT(norm, path.size, alloc); - assert(norm.size == path.size); - if (norm.size != path.size) - return norm; - memcpy(norm.values, path.values, path.size); - for (i1 = 0, i = 0; i < path.size; i++) { - if (!is_delim(path.values[i])) - continue; - str_t s = { .size = i - i1 - 1, .values = path.values + i1 + 1 }; - if (AR_EQUAL(s, parent)) { - i32 have_parent = 0; - i64 i0 = 0; - for (j = 0; j < i1; j++) { - if (norm.values[j] != '\0') - have_parent = 1; - if (is_delim(norm.values[j])) - i0 = j; - } - if (have_parent) { - memset(norm.values + i0, '\0', i - i0); - if (!is_delim(path.values[i0])) - norm.values[i] = '\0'; - } - } - i1 = i; - } - i64 size = 0; - for (i = 0; i < norm.size; i++) { - if (norm.values[i] != '\0') { - if (is_delim(norm.values[i])) - norm.values[size] = KIT_PATH_DELIM_C; - else - norm.values[size] = norm.values[i]; - size++; - } - } - norm.size = size; - return norm; -} -kit_str_builder_t kit_path_join(kit_str_t left, kit_str_t right, - kit_allocator_t *alloc) { - i64 left_size = left.size; - i64 right_size = right.size; - char *right_values = right.values; - if (left_size > 0 && is_delim(left.values[left_size - 1])) - left_size--; - if (right_size > 0 && is_delim(right.values[0])) { - right_size--; - right_values++; - } - kit_str_builder_t joined; - DA_INIT(joined, left_size + right_size + 1, alloc); - assert(joined.size == left_size + right_size + 1); - if (joined.size != left_size + right_size + 1) - return joined; - memcpy(joined.values, left.values, left_size); - joined.values[left_size] = KIT_PATH_DELIM_C; - memcpy(joined.values + left_size + 1, right_values, right_size); - return joined; -} -kit_str_builder_t kit_path_user(kit_allocator_t *alloc) { - kit_str_builder_t user = kit_get_env(SZ(KIT_ENV_HOME), alloc); - if (user.size == 0) { - DA_RESIZE(user, 1); - if (user.size == 1) - user.values[0] = '.'; - } - return user; -} -kit_str_builder_t kit_path_cache(kit_allocator_t *alloc) { - kit_str_builder_t cache, user; - cache = kit_get_env(SZ("XDG_CACHE_HOME"), alloc); - if (cache.size != 0) - return cache; - DA_DESTROY(cache); -#if defined(_WIN32) && !defined(__CYGWIN__) - cache = kit_get_env(SZ("TEMP"), alloc); - if (cache.size != 0) - return cache; - DA_DESTROY(cache); -#endif - user = kit_path_user(alloc); - cache = -#ifdef __APPLE__ - kit_path_join(WRAP_STR(user), SZ("Library" PATH_DELIM "Caches"), - alloc); -#else - kit_path_join(WRAP_STR(user), SZ(".cache"), alloc); -#endif - DA_DESTROY(user); - return cache; -} -kit_str_builder_t kit_path_data(kit_allocator_t *alloc) { - kit_str_builder_t data, user; - data = kit_get_env(SZ("XDG_DATA_HOME"), alloc); - if (data.size != 0) - return data; - DA_DESTROY(data); -#if defined(_WIN32) && !defined(__CYGWIN__) - data = kit_get_env(SZ("LOCALAPPDATA"), alloc); - if (data.size != 0) - return data; - DA_DESTROY(data); -#endif - user = kit_path_user(alloc); - data = -#ifdef __APPLE__ - kit_path_join(WRAP_STR(user), SZ("Library"), alloc); -#else - kit_path_join(WRAP_STR(user), SZ(".local" PATH_DELIM "share"), - alloc); -#endif - DA_DESTROY(user); - return data; -} -kit_str_t kit_path_index(kit_str_t path, i64 index) { - str_t s = { .size = 0, .values = NULL }; - i64 i0 = 0; - i64 i = 0; - i64 n = 0; - for (; i < path.size; i++) { - if (!is_delim(path.values[i])) - continue; - if (i0 < i) { - if (n++ == index) { - s.values = path.values + i0; - s.size = i - i0; - return s; - } - } - i0 = i + 1; - } - if (n == index) { - s.values = path.values + i0; - s.size = i - i0; - } - return s; -} -kit_str_t kit_path_take(kit_str_t path, i64 count) { - str_t s = { .size = 0, .values = path.values }; - i64 i0 = 0; - i64 i = 0; - i64 n = 0; - for (; i < path.size; i++) { - if (!is_delim(path.values[i])) - continue; - if (i0 < i) { - if (n++ == count) { - s.size = i; - return s; - } - } - i0 = i + 1; - } - if (n == count) - s.size = i; - return s; -} -// TODO -// Long path support for Windows -// -static void kit_prepare_path_(char *buf, kit_str_t path) { - assert(path.size == 0 || path.values != NULL); - assert(path.size + 1 < PATH_BUF_SIZE); - memset(buf, 0, PATH_BUF_SIZE); - if (path.size > 0 && path.size + 1 < PATH_BUF_SIZE) - memcpy(buf, path.values, path.size); -} -#define PREPARE_PATH_BUF_ \ - char buf[PATH_BUF_SIZE]; \ - kit_prepare_path_(buf, path) -kit_status_t kit_folder_create(kit_str_t path) { - PREPARE_PATH_BUF_; -#if defined(_WIN32) && !defined(__CYGWIN__) - return CreateDirectoryA(buf, NULL) ? KIT_OK - : KIT_ERROR_MKDIR_FAILED; -#else - return mkdir(buf, 0775) == 0 ? KIT_OK : KIT_ERROR_MKDIR_FAILED; -#endif -} -kit_status_t 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); - if (s != KIT_OK) - return s; - } - if (part.size == path.size) - break; - } - return KIT_OK; -} -kit_status_t kit_file_remove(kit_str_t path) { - PREPARE_PATH_BUF_; -#if defined(_WIN32) && !defined(__CYGWIN__) - return DeleteFileA(buf) ? KIT_OK : KIT_ERROR_UNLINK_FAILED; -#else - return unlink(buf) == 0 ? KIT_OK : KIT_ERROR_UNLINK_FAILED; -#endif -} -kit_status_t kit_folder_remove(kit_str_t path) { - PREPARE_PATH_BUF_; -#if defined(_WIN32) && !defined(__CYGWIN__) - return RemoveDirectoryA(buf) ? KIT_OK : KIT_ERROR_RMDIR_FAILED; -#else - return rmdir(buf) == 0 ? KIT_OK : KIT_ERROR_RMDIR_FAILED; -#endif -} -kit_status_t 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); - assert(s == KIT_OK); - return s; - } - case KIT_PATH_FOLDER: { - kit_path_list_t list = kit_folder_enum(path, alloc); - assert(list.status == KIT_OK); - if (list.status != KIT_OK) { - kit_path_list_destroy(list); - return list.status; - } - 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); - DA_DESTROY(full_path); - assert(s == KIT_OK); - } - kit_path_list_destroy(list); - kit_status_t s = kit_folder_remove(path); - assert(s == KIT_OK); - return s; - } - default:; - } - return KIT_ERROR_FILE_DOES_NOT_EXIST; -} -kit_path_type_t kit_path_type(kit_str_t path) { - PREPARE_PATH_BUF_; -#if defined(_WIN32) && !defined(__CYGWIN__) - if (PathFileExistsA(buf)) { - if ((GetFileAttributesA(buf) & FILE_ATTRIBUTE_DIRECTORY) != 0) - return KIT_PATH_FOLDER; - else - return KIT_PATH_FILE; - } -#else - struct stat info; - if (stat(buf, &info) == 0) { - if (S_ISREG(info.st_mode)) - return KIT_PATH_FILE; - if (S_ISDIR(info.st_mode)) - return KIT_PATH_FOLDER; - } -#endif - return KIT_PATH_NONE; -} -kit_file_info_t kit_file_info(kit_str_t path) { - kit_file_info_t result; - memset(&result, 0, sizeof result); - PREPARE_PATH_BUF_; -#if defined(_WIN32) && !defined(__CYGWIN__) - HANDLE f = CreateFileA(buf, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (f != INVALID_HANDLE_VALUE) { - FILETIME ft; - if (GetFileTime(f, NULL, NULL, &ft) != 0) { - i64 nsec100 = (((u64) ft.dwHighDateTime) << 32) | - (u64) ft.dwLowDateTime; - result.time_modified_sec = (i64) (nsec100 / 10000000); - result.time_modified_nsec = (i32) (100 * (nsec100 % 10000000)); - } else { - assert(0); - } - DWORD high; - DWORD low = GetFileSize(f, &high); - result.size = (i64) ((((u64) high) << 32) | (u64) low); - result.status = KIT_OK; - CloseHandle(f); - return result; - } -#else - struct stat info; - if (stat(buf, &info) == 0 && S_ISREG(info.st_mode)) { - result.size = (i64) info.st_size; -# ifndef st_mtime - // No support for nanosecond timestamps. - // - result.time_modified_sec = (i64) info.st_mtime; -# else - result.time_modified_sec = (i64) info.st_mtim.tv_sec; - result.time_modified_nsec = (i32) info.st_mtim.tv_nsec; -# endif - result.status = KIT_OK; - return result; - } -#endif - result.status = KIT_ERROR_FILE_DOES_NOT_EXIST; - return result; -} -kit_path_list_t kit_folder_enum(kit_str_t path, - kit_allocator_t *alloc) { - PREPARE_PATH_BUF_; - kit_path_list_t result = { .status = KIT_OK }; - DA_INIT(result.files, 0, alloc); -#if defined(_WIN32) && !defined(__CYGWIN__) - if (path.size + 3 >= PATH_BUF_SIZE) { - result.status = KIT_ERROR_PATH_TOO_LONG; - return result; - } - buf[path.size] = '\\'; - buf[path.size + 1] = '*'; - WIN32_FIND_DATAA data; - HANDLE find = FindFirstFileA(buf, &data); - if (find == INVALID_HANDLE_VALUE) - return result; - do { - if (strcmp(data.cFileName, ".") == 0 || - strcmp(data.cFileName, "..") == 0) - continue; - i64 n = result.files.size; - DA_RESIZE(result.files, n + 1); - if (result.files.size != n + 1) { - result.status = KIT_ERROR_BAD_ALLOC; - break; - } - i64 size = (i64) strlen(data.cFileName); - DA_INIT(result.files.values[n], size, alloc); - if (result.files.values[n].size != size) { - DA_RESIZE(result.files, n); - result.status = KIT_ERROR_BAD_ALLOC; - break; - } - memcpy(result.files.values[n].values, data.cFileName, size); - } while (FindNextFileA(find, &data) != 0); - FindClose(find); -#else - DIR *directory = opendir(buf); - if (directory == NULL) - return result; - for (;;) { - struct dirent *entry = readdir(directory); - if (entry == NULL) - break; - if (entry->d_name[0] == '.') - continue; - i64 n = result.files.size; - DA_RESIZE(result.files, n + 1); - if (result.files.size != n + 1) { - result.status = KIT_ERROR_BAD_ALLOC; - break; - } - i64 size = (i64) strlen(entry->d_name); - DA_INIT(result.files.values[n], size, alloc); - if (result.files.values[n].size != size) { - DA_RESIZE(result.files, n); - result.status = KIT_ERROR_BAD_ALLOC; - break; - } - if (size > 0) - memcpy(result.files.values[n].values, entry->d_name, size); - } - closedir(directory); -#endif - return result; -} -void kit_path_list_destroy(kit_path_list_t list) { - i64 i; - for (i = 0; i < list.files.size; i++) - DA_DESTROY(list.files.values[i]); - DA_DESTROY(list.files); -} -kit_mapped_file_t kit_file_map(kit_str_t path, i64 size, i32 mode) { - assert(size > 0); - assert(path.size > 0); - assert(path.size <= PATH_MAX); - assert(path.values != NULL); - kit_mapped_file_t mf; - memset(&mf, 0, sizeof mf); - if (size <= 0) { - mf.status = KIT_ERROR_INVALID_SIZE; - return mf; - } - if (path.size <= 0) { - mf.status = KIT_ERROR_INVALID_ARGUMENT; - return mf; - } - if (path.size > PATH_MAX) { - mf.status = KIT_ERROR_PATH_TOO_LONG; - return mf; - } -#if defined(_WIN32) && !defined(__CYGWIN__) - char buf[MAX_PATH + 1]; - memcpy(buf, path.values, path.size); - buf[path.size] = '\0'; - HANDLE file = CreateFileA( - buf, GENERIC_READ | GENERIC_WRITE, - mode == FILE_MAP_SHARED ? FILE_SHARE_READ | FILE_SHARE_WRITE - : 0, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (file == INVALID_HANDLE_VALUE) { - mf.status = KIT_ERROR_OPEN_FAILED; - return mf; - } - LONG high = (LONG) (size >> 32); - if (SetFilePointer(file, (LONG) size, &high, FILE_BEGIN) == - INVALID_SET_FILE_POINTER) { - CloseHandle(file); - assert(0); - mf.status = KIT_ERROR_TRUNCATE_FAILED; - return mf; - } - if (!SetEndOfFile(file)) { - CloseHandle(file); - assert(0); - mf.status = KIT_ERROR_TRUNCATE_FAILED; - return mf; - } - HANDLE map = CreateFileMappingA(file, NULL, PAGE_READWRITE, - (DWORD) (size >> 32), (DWORD) size, - NULL); - if (map == INVALID_HANDLE_VALUE) { - CloseHandle(file); - assert(0); - mf.status = KIT_ERROR_MAP_FAILED; - return mf; - } - void *p = MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, - (SIZE_T) size); - if (p == NULL) { - CloseHandle(map); - CloseHandle(file); - assert(0); - mf.status = KIT_ERROR_MAP_FAILED; - return mf; - } - mf.status = KIT_OK; - mf.size = size; - mf.bytes = p; - mf._file = file; - mf._map = map; -#else - char buf[PATH_MAX + 1]; - memcpy(buf, path.values, path.size); - buf[path.size] = '\0'; - i32 fd = open(buf, O_RDWR | O_CREAT, 0664); - if (fd == -1) { - mf.status = KIT_ERROR_OPEN_FAILED; - return mf; - } - if (ftruncate(fd, size) == -1) { - close(fd); - assert(0); - mf.status = KIT_ERROR_TRUNCATE_FAILED; - return mf; - } - void *p = mmap( - NULL, size, PROT_READ | PROT_WRITE, - mode == KIT_FILE_MAP_SHARED ? MAP_SHARED : MAP_PRIVATE, fd, 0); - if (p == MAP_FAILED) { - close(fd); - assert(0); - mf.status = KIT_ERROR_MAP_FAILED; - return mf; - } - mf.status = KIT_OK; - mf.size = size; - mf.bytes = (u8 *) p; - mf._fd = fd; -#endif - return mf; -} -kit_status_t 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; -#if !defined(_WIN32) || defined(__CYGWIN__) - if (msync(mf->bytes, mf->size, MS_SYNC) != 0) - status |= KIT_ERROR_SYNC_FAILED; -#endif - return status; -} -kit_status_t 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; -#if defined(_WIN32) && !defined(__CYGWIN__) - if (!UnmapViewOfFile(mf->bytes)) - status |= KIT_ERROR_UNMAP_FAILED; - if (!CloseHandle(mf->_map) || !CloseHandle(mf->_file)) - status |= KIT_ERROR_CLOSE_FAILED; -#else - if (munmap(mf->bytes, mf->size) != 0) - status |= KIT_ERROR_UNMAP_FAILED; - if (close(mf->_fd) != 0) - status |= KIT_ERROR_CLOSE_FAILED; -#endif - return status; -} -// ================================================================ -// -// File: source/kit/mersenne_twister_64.c -// -// ================================================================ -#define MM 156 -#define MATRIX_A 0xb5026f5aa96619e9ull -#define UM 0xffffffff80000000ull -#define LM 0x7fffffffull -void kit_mt64_init_array(kit_mt64_state_t *state, i64 size, - u64 *seed) { - i64 i; - for (i = 0; i < size && i < KIT_MT64_N; i++) state->mt[i] = seed[i]; - for (state->index = size; state->index < KIT_MT64_N; state->index++) - state->mt[state->index] = (6364136223846793005ull * - (state->mt[state->index - 1] ^ - (state->mt[state->index - 1] >> - 62u)) + - state->index); -} -void kit_mt64_init(kit_mt64_state_t *state, u64 seed) { - kit_mt64_init_array(state, 1, &seed); -} -void kit_mt64_rotate(kit_mt64_state_t *state) { - static u64 mag01[2] = { 0ull, MATRIX_A }; - u64 x; - i32 i; - for (i = 0; i < KIT_MT64_N - MM; i++) { - x = (state->mt[i] & UM) | (state->mt[i + 1] & LM); - state->mt[i] = state->mt[i + MM] ^ (x >> 1u) ^ - mag01[(i32) (x & 1ull)]; - } - for (; i < KIT_MT64_N - 1; i++) { - x = (state->mt[i] & UM) | (state->mt[i + 1] & LM); - state->mt[i] = state->mt[i + (MM - KIT_MT64_N)] ^ (x >> 1u) ^ - mag01[(i32) (x & 1ull)]; - } - x = (state->mt[KIT_MT64_N - 1] & UM) | (state->mt[0] & LM); - state->mt[KIT_MT64_N - 1] = state->mt[MM - 1] ^ (x >> 1u) ^ - mag01[(i32) (x & 1ull)]; - state->index = 0; -} -u64 kit_mt64_generate(kit_mt64_state_t *state) { - if (state->index >= KIT_MT64_N) - kit_mt64_rotate(state); - u64 x = state->mt[state->index++]; - x ^= (x >> 29u) & 0x5555555555555555ull; - x ^= (x << 17u) & 0x71d67fffeda60000ull; - x ^= (x << 37u) & 0xfff7eee000000000ull; - x ^= (x >> 43u); - return x; -} -#undef MM -#undef MATRIX_A -#undef UM -#undef LM -// ================================================================ -// -// File: source/kit/secure_random.c -// -// ================================================================ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#if defined(_WIN32) && !defined(__CYGWIN__) -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 -# endif -# include <windows.h> -# include <wincrypt.h> -#else -# include <unistd.h> -#endif -kit_status_t kit_secure_random(i64 size, void *data) { - assert(size >= 0); - assert(data != NULL); - if (size <= 0 || data == NULL) - return KIT_ERROR_INVALID_ARGUMENT; -#if defined(_WIN32) && !defined(__CYGWIN__) - HCRYPTPROV prov = 0; - if (!CryptAcquireContextW(&prov, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT) || - !CryptGenRandom(prov, (DWORD) size, (BYTE *) data) || - !CryptReleaseContext(prov, 0)) - return KIT_ERROR_RESOURCE_UNAVAILABLE; -#else - FILE *f = fopen("/dev/urandom", "rb"); - if (f == NULL) - return KIT_ERROR_RESOURCE_UNAVAILABLE; - i64 n = (i64) fread(data, 1, size, f); - fclose(f); - if (n != size) - return KIT_ERROR_RESOURCE_UNAVAILABLE; -#endif - return KIT_OK; -} -// ================================================================ -// -// File: source/kit/sha256.c -// -// ================================================================ -#include <assert.h> -#include <string.h> -#define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) -#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b)))) -#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) -#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22)) -#define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25)) -#define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3)) -#define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10)) -static u32 kit_sha256_k[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, - 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, - 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, - 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, - 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, - 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, - 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, - 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, - 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; -static void kit_sha256_transform(u32 *state, u8 *data) { - assert(state != NULL); - assert(data != NULL); - u32 a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; - for (i = 0, j = 0; i < 16; ++i, j += 4) - m[i] = ((u32) data[j] << 24) | ((u32) data[j + 1] << 16) | - ((u32) data[j + 2] << 8) | ((u32) data[j + 3]); - for (; i < 64; ++i) - m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - f = state[5]; - g = state[6]; - h = state[7]; - for (i = 0; i < 64; ++i) { - t1 = h + EP1(e) + CH(e, f, g) + kit_sha256_k[i] + m[i]; - t2 = EP0(a) + MAJ(a, b, c); - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - } - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - state[5] += f; - state[6] += g; - state[7] += h; -} -kit_sha256_hash_t kit_sha256(i64 in_size, u8 *in_data) { - assert(in_size >= 0); - assert(in_data != NULL); - u32 state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - u8 data[64]; - i64 i; - i64 datalen = 0; - u64 bitlen = 0; - if (in_data != NULL) - for (i = 0; i < in_size; ++i) { - data[datalen] = in_data[i]; - datalen++; - if (datalen != 64) - continue; - kit_sha256_transform(state, data); - bitlen += 512; - datalen = 0; - } - i = datalen; - if (datalen < 56) { - data[i++] = 0x80; - while (i < 56) data[i++] = 0x00; - } else { - data[i++] = 0x80; - while (i < 64) data[i++] = 0x00; - kit_sha256_transform(state, data); - memset(data, 0, 56); - } - bitlen += datalen * 8; - data[63] = bitlen; - data[62] = bitlen >> 8; - data[61] = bitlen >> 16; - data[60] = bitlen >> 24; - data[59] = bitlen >> 32; - data[58] = bitlen >> 40; - data[57] = bitlen >> 48; - data[56] = bitlen >> 56; - kit_sha256_transform(state, data); - kit_sha256_hash_t hash; - memset(&hash, 0, sizeof hash); - for (i = 0; i < 4; ++i) { - hash.v[i] = (state[0] >> (24 - i * 8)) & 0xff; - hash.v[i + 4] = (state[1] >> (24 - i * 8)) & 0xff; - hash.v[i + 8] = (state[2] >> (24 - i * 8)) & 0xff; - hash.v[i + 12] = (state[3] >> (24 - i * 8)) & 0xff; - hash.v[i + 16] = (state[4] >> (24 - i * 8)) & 0xff; - hash.v[i + 20] = (state[5] >> (24 - i * 8)) & 0xff; - hash.v[i + 24] = (state[6] >> (24 - i * 8)) & 0xff; - hash.v[i + 28] = (state[7] >> (24 - i * 8)) & 0xff; - } - return hash; -} -#undef ROTLEFT -#undef ROTRIGHT -#undef CH -#undef MAJ -#undef EP0 -#undef EP1 -#undef SIG0 -#undef SIG1 -// ================================================================ -// -// File: source/kit/shared_memory.posix.c -// -// ================================================================ -#if !defined(_WIN32) || defined(__CYGWIN__) -# include <stdio.h> -# include <string.h> -# include <sys/mman.h> -# include <sys/stat.h> -# include <fcntl.h> -# include <unistd.h> -# include <assert.h> -kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, - i32 mode) { - kit_shared_memory_t mem; - memset(&mem, 0, sizeof mem); - assert(size > 0); - assert(name.size > 0); - assert(name.size + 1 <= NAME_MAX); - assert(name.values != NULL); - if (size <= 0) { - mem.status = KIT_ERROR_INVALID_SIZE; - return mem; - } - if (name.size <= 0) { - mem.status = KIT_ERROR_INVALID_NAME; - return mem; - } - if (name.size + 1 > NAME_MAX) { - mem.status = KIT_ERROR_NAME_TOO_LONG; - return mem; - } - for (i64 i = 0; i < name.size; i++) - if (name.values[i] == '/' || name.values[i] == '\\') { - mem.status = KIT_ERROR_INVALID_NAME; - return mem; - } - mem._name[0] = '/'; - memcpy(mem._name + 1, name.values, name.size); - mem._name[1 + name.size] = '\0'; - i32 fd = shm_open(mem._name, - mode == KIT_SHARED_MEMORY_CREATE - ? O_RDWR | O_CREAT | O_EXCL - : O_RDWR, - mode == KIT_SHARED_MEMORY_CREATE ? 0660 : 0); - if (fd == -1) { - mem.status = KIT_ERROR_OPEN_FAILED; - return mem; - } - if (mode == KIT_SHARED_MEMORY_CREATE && ftruncate(fd, size) == -1) { - shm_unlink(mem._name); - assert(0); - mem.status = KIT_ERROR_TRUNCATE_FAILED; - return mem; - } - void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, - 0); - close(fd); - if (p == MAP_FAILED) { - shm_unlink(mem._name); - mem.status = KIT_ERROR_MAP_FAILED; - return mem; - } - mem.status = KIT_OK; - mem.size = size; - mem.bytes = (u8 *) p; - mem._owned = (mode == KIT_SHARED_MEMORY_CREATE); - return mem; -} -kit_status_t 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; - if (munmap(mem->bytes, mem->size) != 0) - status |= KIT_ERROR_UNMAP_FAILED; - if (mem->_owned && shm_unlink(mem->_name) != 0) - status |= KIT_ERROR_UNLINK_FAILED; - return status; -} -kit_status_t kit_shared_memory_clean(kit_str_t name) { - assert(name.size > 0); - assert(name.size + 1 <= NAME_MAX); - assert(name.values != NULL); - if (name.size <= 0) - return KIT_ERROR_INVALID_NAME; - if (name.size + 1 > NAME_MAX) - return KIT_ERROR_NAME_TOO_LONG; - for (i64 i = 0; i < name.size; i++) - if (name.values[i] == '/' || name.values[i] == '\\') - return KIT_ERROR_INVALID_NAME; - char buf[NAME_MAX + 1] = "/"; - memcpy(buf + 1, name.values, name.size); - buf[1 + name.size] = '\0'; - if (shm_unlink(buf) != 0) - return KIT_ERROR_UNLINK_FAILED; - return KIT_OK; -} -#endif -// ================================================================ -// -// File: source/kit/shared_memory.win32.c -// -// ================================================================ -#if defined(_WIN32) && !defined(__CYGWIN__) -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include <windows.h> -kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, - i32 mode) { - kit_shared_memory_t mem; - memset(&mem, 0, sizeof mem); - char buf[264] = "Global\\"; - assert(size > 0); - assert(name.size > 0); - assert(name.size + 8 < sizeof buf); - assert(name.values != NULL); - if (name.size <= 0) { - mem.status = KIT_ERROR_INVALID_NAME; - return mem; - } - if (name.size + 8 >= sizeof buf) { - mem.status = KIT_ERROR_NAME_TOO_LONG; - return mem; - } - for (i64 i = 0; i < name.size; i++) - if (name.values[i] == '/' || name.values[i] == '\\') { - mem.status = KIT_ERROR_INVALID_NAME; - return mem; - } - memcpy(buf + 7, name.values, name.size); - buf[7 + name.size] = '\0'; - HANDLE h = mode == KIT_SHARED_MEMORY_CREATE - ? CreateFileMappingA( - INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - (DWORD) (size >> 32), (DWORD) size, buf) - : OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, buf); - if (h == INVALID_HANDLE_VALUE) { - mem.status = KIT_ERROR_OPEN_FAILED; - return mem; - } - void *p = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, - (SIZE_T) size); - if (p == NULL) { - CloseHandle(h); - mem.status = KIT_ERROR_MAP_FAILED; - return mem; - } - mem.status = KIT_OK; - mem.size = size; - mem.bytes = (u8 *) p; - mem._handle = h; - return mem; -} -kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem) { - assert(mem != NULL); - i32 status = KIT_OK; - if (!UnmapViewOfFile(mem->bytes)) - status |= KIT_ERROR_UNMAP_FAILED; - if (!CloseHandle(mem->_handle)) - status |= KIT_ERROR_UNLINK_FAILED; - return status; -} -kit_status_t kit_shared_memory_clean(kit_str_t name) { - // Do nothing. - // - return KIT_OK; -} -#endif -// ================================================================ -// -// File: source/kit/xml.c -// -// ================================================================ -#include <assert.h> -typedef struct { - ib_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); - str_builder_t buf; - DA_INIT(buf, str->size, str->alloc); - buf.size = 0; - for (i64 i = 0; i < str->size; i++) - if (str->values[i] != '&') - buf.values[buf.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; - } - 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++] = '\''; - else { - DA_DESTROY(buf); - return KIT_ERROR_INTERNAL; - } - 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); - for (;;) { - ib_t comment_open = ib_exact(last, SZ("<!--")); - if (comment_open.status != KIT_OK) { - ib_destroy(comment_open); - break; - } - ib_t comment_text = ib_until(comment_open, SZ("-->")); - ib_t comment_close = ib_exact(comment_text, SZ("-->")); - ib_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); - 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; - else - memcpy(text.data.values + n, next_text.data.values, - next_text.data.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); - } - // 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)); - // move - DA_DESTROY(close.data); - close.data = text.data; - memset(&text.data, 0, sizeof text.data); - kit_status_t s = kit_xml_unescape_(&close.data); - if (s == KIT_OK) - close.status = s; - ib_destroy(quotes_open); - ib_destroy(apostr_open); - ib_destroy(text); - return close; -} -static kit_xml_intermediate_t kit_xml_parse_buf_( - ib_t begin, kit_allocator_t *alloc) { - kit_xml_intermediate_t res; - memset(&res, 0, sizeof res); - ib_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); - DA_INIT(res.tags, 0, alloc); - for (;;) { - ib_t tagend_open = ib_exact(last, SZ("</")); - ib_destroy(tagend_open); - if (tagend_open.status == KIT_OK) - break; - ib_t tag_open = ib_exact(last, SZ("<")); - if (tag_open.status != KIT_OK) { - ib_destroy(tag_open); - break; - } - xml_t tag; - memset(&tag, 0, sizeof tag); - ib_t decl_open = ib_exact(tag_open, SZ("?")); - ib_destroy(last); - if (decl_open.status == KIT_OK) { - tag.is_declaration = 1; - last = ib_copy(decl_open); - } else - last = ib_copy(tag_open); - ib_destroy(decl_open); - spaces = ib_any(last, SZ(" \t\r\n")); - ib_t tag_name = ib_none(spaces, SZ(" \t\r\n/>")); - ib_destroy(spaces); - DA_INIT(tag.properties, 0, alloc); - ib_destroy(last); - last = ib_copy(tag_name); - for (;;) { - spaces = ib_any(last, SZ(" \t\r\n")); - ib_t property = ib_none(spaces, SZ(" \t\r\n=?/>")); - ib_destroy(spaces); - if (property.status != KIT_OK || property.data.size == 0) { - ib_destroy(property); - 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); - ib_destroy(last); - last = ib_copy(value); - if (last.status == KIT_OK) { - i64 n = tag.properties.size; - DA_RESIZE(tag.properties, n + 1); - assert(tag.properties.size == n + 1); - if (tag.properties.size != n + 1) { - 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); - } - } - 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_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); - 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(im.last); - spaces = ib_any(tagend_open, SZ(" \t\r\n")); - ib_t tagend_name = ib_exact(spaces, WRAP_STR(tag_name.data)); - ib_destroy(spaces); - spaces = ib_any(tagend_name, SZ(" \t\r\n")); - ib_t tagend_close = ib_exact(spaces, SZ(">")); - ib_destroy(spaces); - ib_destroy(tagend_open); - ib_destroy(tagend_name); - ib_destroy(last); - last = tagend_close; - } else if (tag_close_empty.status == KIT_OK) { - ib_destroy(last); - last = ib_copy(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); - } - ib_t tag_tail = kit_xml_parse_text_(last); - ib_destroy(last); - last = ib_copy(tag_tail); - if (last.status == KIT_OK) { - i64 n = res.tags.size; - DA_RESIZE(res.tags, n + 1); - assert(res.tags.size == n + 1); - if (res.tags.size != n + 1) { - 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); - 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) { - for (i64 i = 0; i < res.tags.size; i++) - 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); - } - ib_destroy(tag_text); - res.last = last; - return res; -} -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); - 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) - 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); - return res; - } - DA_INIT(res.xml.tag, 0, alloc); - DA_INIT(res.xml.tail, 0, alloc); - DA_INIT(res.xml.properties, 0, alloc); - res.xml.text = im.text; - res.xml.children = im.tags; - return res; -} -kit_xml_text_t kit_xml_print(kit_xml_t *xml, kit_allocator_t *alloc) { - assert(xml != NULL); - xml_text_t result; - memset(&result, 0, sizeof result); - result.status = KIT_ERROR_NOT_IMPLEMENTED; - return result; -} -static kit_status_t kit_xml_append_text_(str_builder_t *buf, - xml_t *xml) { - assert(buf != NULL); - assert(xml != NULL); - i64 n = buf->size; - DA_RESIZE(*buf, n + xml->text.size); - assert(buf->size == n + xml->text.size); - if (buf->size != n + xml->text.size) - return KIT_ERROR_BAD_ALLOC; - if (xml->text.size > 0) - 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); - if (s != KIT_OK) - return s; - str_t tail = WRAP_STR(xml->children.values[i].tail); - if (tail.size <= 0) - continue; - n = buf->size; - DA_RESIZE(*buf, n + tail.size); - assert(buf->size == n + tail.size); - if (buf->size != n + tail.size) - return KIT_ERROR_BAD_ALLOC; - if (tail.size > 0) - memcpy(buf->values + n, tail.values, tail.size); - } - return KIT_OK; -} -kit_xml_text_t kit_xml_full_text(kit_xml_t *xml, - kit_allocator_t *alloc) { - kit_xml_text_t res; - res.status = KIT_OK; - DA_INIT(res.text, 0, alloc); - if (xml != NULL) - res.status = kit_xml_append_text_(&res.text, xml); - else - res.status = KIT_ERROR_INVALID_ARGUMENT; - return res; -} -void kit_xml_destroy(kit_xml_t *xml) { - assert(xml != NULL); - if (xml == NULL) - return; - for (i64 i = 0; i < xml->properties.size; i++) { - DA_DESTROY(xml->properties.values[i].name); - DA_DESTROY(xml->properties.values[i].value); - } - for (i64 i = 0; i < xml->children.size; i++) - kit_xml_destroy(xml->children.values + i); - DA_DESTROY(xml->tag); - DA_DESTROY(xml->text); - DA_DESTROY(xml->tail); - DA_DESTROY(xml->properties); - DA_DESTROY(xml->children); -} -#endif |