diff options
Diffstat (limited to 'source/kit')
65 files changed, 0 insertions, 20184 deletions
diff --git a/source/kit/LICENSE b/source/kit/LICENSE deleted file mode 100644 index 8ac4c29..0000000 --- a/source/kit/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2022-2024 Mitya Selivanov - -HTTP1 -Copyright (c) 2016 Christian C. Sachs - -miniz -Copyright (c) 2013-2014 RAD Game Tools and Valve Software -Copyright (c) 2010-2014 Rich Geldreich and Tenacious Software LLC - -C11 threads from Mesa -Copyright (c) 2022 Yonggang Luo -Copyright (c) 2012 yohhoy - -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. diff --git a/source/kit/_lib.c b/source/kit/_lib.c deleted file mode 100644 index 0f7cc19..0000000 --- a/source/kit/_lib.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "allocator.c" -#include "array_ref.c" -#include "dynamic_array.c" -#include "file.c" -#include "input_buffer.c" -#include "input_stream.c" -#include "mersenne_twister_64.c" -#include "secure_random.c" -#include "sha256.c" -#include "atomic.win32.c" -#include "threads.posix.c" -#include "threads.win32.c" -#include "process.posix.c" -#include "process.win32.c" -#include "shared_memory.posix.c" -#include "shared_memory.win32.c" -#include "xml.c" diff --git a/source/kit/allocator.c b/source/kit/allocator.c deleted file mode 100644 index 9fd7bad..0000000 --- a/source/kit/allocator.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "allocator.h" - -#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) { - return (kit_allocator_t) { .type = KIT_ALLOC_TYPE_DEFAULT, - .size = 0, - .data = NULL }; -} - -kit_allocator_t kit_alloc_buffer(i64 size, void *buffer) { - return (kit_allocator_t) { .type = KIT_ALLOC_TYPE_BUFFER, - .size = size, - .data = buffer }; -} diff --git a/source/kit/allocator.h b/source/kit/allocator.h deleted file mode 100644 index 97e453e..0000000 --- a/source/kit/allocator.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef KIT_ALLOCATOR_H -#define KIT_ALLOCATOR_H - -#include "types.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 diff --git a/source/kit/array_ref.c b/source/kit/array_ref.c deleted file mode 100644 index a9df2c4..0000000 --- a/source/kit/array_ref.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "array_ref.h" - -#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; -} diff --git a/source/kit/array_ref.h b/source/kit/array_ref.h deleted file mode 100644 index 3a7244e..0000000 --- a/source/kit/array_ref.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef KIT_ARRAY_REF_H -#define KIT_ARRAY_REF_H - -#include "types.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 - -#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 diff --git a/source/kit/astar.h b/source/kit/astar.h deleted file mode 100644 index b4a5909..0000000 --- a/source/kit/astar.h +++ /dev/null @@ -1,401 +0,0 @@ -// ================================================================ -// -// A* graph search algorithm -// -// ================================================================ - -// TODO -// - Nearest: save the nearest node when the search is failed or not -// yet finished. -// - Sight: when two nodes are in direct sight of each other, skip -// nodes between them (Theta*). - -#ifndef KIT_ASTAR_INL_H -#define KIT_ASTAR_INL_H - -#include "types.h" -#include "status.h" - -#include <assert.h> -#include <stddef.h> -#include <string.h> - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - ASTAR_PROGRESS = 0, - ASTAR_SUCCESS, - ASTAR_FAIL, - ASTAR_OUT_OF_MEMORY, - ASTAR_INVALID_ARGUMENT, -}; - -typedef struct { - b8 stop; - b8 skip; - i64 neighbor; - i64 distance; -} astar_link_t; - -typedef struct { - i64 id; - i64 previous; - i64 exact_source_to_node; - i64 estimated_source_to_destination; -} astar_node_t; - -typedef struct { - i64 capacity; - i64 size; - astar_node_t *values; -} astar_set_t; - -typedef struct { - astar_set_t open; - astar_set_t closed; - void *user_data; - i64 source; - i64 destination; -} astar_state_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 s32 astar_init(astar_state_t *state, astar_set_t open, - astar_set_t closed, void *user_data, i64 source, - i64 destination) { - assert(state != NULL && open.capacity > 0 && open.values != NULL && - closed.capacity > 0 && closed.values != NULL); - - if (state == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - - memset(state, 0, sizeof *state); - - state->source = source; - state->destination = destination; - state->open = open; - state->closed = closed; - state->user_data = user_data; - - if (state->open.capacity <= 0) - return KIT_ERROR_INVALID_ARGUMENT; - - state->open.values[0] = (astar_node_t) { - .id = source, - .previous = -1, - .exact_source_to_node = 0, - .estimated_source_to_destination = -1, - }; - - state->open.size = 1; - state->closed.size = 0; - - return KIT_OK; -} - -static s32 astar_path(astar_state_t *state, i64 *size, i64 *path) { - assert(state != NULL && size != NULL); - - if (state == NULL || size == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - - i64 path_size = *size; - - *size = 1; - - i64 id = state->destination; - - while (id != state->source) { - if (*size > state->closed.size) - return KIT_ERROR_INTERNAL; - - i64 index = 0; - for (; index < state->closed.size; index++) - if (state->closed.values[index].id == id) - break; - if (index == state->closed.size) - return KIT_ERROR_INTERNAL; - - if (path != NULL && *size <= path_size) - path[*size - 1] = id; - - id = state->closed.values[index].previous; - ++*size; - } - - if (path != NULL && *size <= path_size) - path[*size - 1] = id; - - if (path != NULL) { - if (*size < path_size) - path_size = *size; - - for (i64 i = 0; i < path_size / 2; ++i) { - i64 z = path[i]; - path[i] = path[path_size - 1 - i]; - path[path_size - 1 - i] = z; - } - } - - return KIT_OK; -} - -#ifdef __GNUC__ -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#endif - -// ================================================================ -// -// Algorithm template -// -// ================================================================ - -#ifdef ASTAR_TEMPLATE - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ASTAR_SUFFIX -# define ASTAR_SUFFIX -#endif - -#ifndef ASTAR_NEIGHBOR -# define ASTAR_NEIGHBOR(user_data_, node_, index_) \ - (astar_link_t) { \ - .stop = 1, \ - } -#endif - -#ifndef ASTAR_HEURISTIC -# define ASTAR_HEURISTIC(user_data_, node_0_, node_2_) (-1) -#endif - -#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 - -#define CAT1_(x, y) x##y -#define CAT2_(x, y) CAT1_(x, y) -#define NAME_(x) CAT2_(x, ASTAR_SUFFIX) - -static s32 NAME_(astar_iteration)(astar_state_t *state) { - assert(state != NULL); - - if (state == NULL) - return ASTAR_INVALID_ARGUMENT; - - if (state->open.size == 0) - return ASTAR_FAIL; - - if (state->open.values == NULL || state->closed.values == NULL) - return ASTAR_OUT_OF_MEMORY; - - // Find a node in the open set that is closest to the destination - // - astar_node_t nearest_node; - { - i64 index_in_open = 0; - for (i64 i = 1; i < state->open.size; i++) - if (state->open.values[i].estimated_source_to_destination < - state->open.values[index_in_open] - .estimated_source_to_destination) - index_in_open = i; - nearest_node = state->open.values[index_in_open]; - if (index_in_open != state->open.size - 1) - state->open.values[index_in_open] = - state->open.values[state->open.size - 1]; - --state->open.size; - } - - // Check if we reached the destination - // - if (nearest_node.id == state->destination) { - if (state->closed.size + 1 > state->closed.capacity) { - // Restore the state - state->open.values[state->open.size - 1] = nearest_node; - ++state->open.size; - - return ASTAR_OUT_OF_MEMORY; - } - - // Add the nearest node to the closed set - // - state->closed.values[state->closed.size] = nearest_node; - ++state->closed.size; - - // Finish the search - return ASTAR_SUCCESS; - } - - // Enumerate all neighbors - // - for (i64 k = 0;; ++k) { - // Get a link to the next neighbor node - // - (void) state->user_data; - (void) nearest_node.id; - (void) k; - astar_link_t link = ASTAR_NEIGHBOR(state->user_data, - nearest_node.id, k); - - // If there is no more neighbors, break the loop - if (link.stop) - break; - // If there is no link, proceed to the next link - if (link.skip) - continue; - - astar_node_t neighbor_node = { - .id = link.neighbor, - .previous = nearest_node.id, - .exact_source_to_node = nearest_node.exact_source_to_node + - link.distance, - .estimated_source_to_destination = -1, - }; - - // Calculate distance estimations - // - (void) state->user_data; - (void) neighbor_node.id; - (void) state->destination; - i64 estimated_node_to_destination = ASTAR_HEURISTIC( - state->user_data, neighbor_node.id, state->destination); - - neighbor_node.estimated_source_to_destination = - neighbor_node.exact_source_to_node + - estimated_node_to_destination; - - // Check if we reached the destination - // - if (neighbor_node.id == state->destination) { - if (state->closed.size + 2 > state->closed.capacity) { - // Restore the state - state->open.values[state->open.size - 1] = nearest_node; - ++state->open.size; - - return ASTAR_OUT_OF_MEMORY; - } - - // Add the nearest node to the closed set - // - state->closed.values[state->closed.size] = nearest_node; - ++state->closed.size; - - // Add the neighbor node to the closed set - // - state->closed.values[state->closed.size] = neighbor_node; - ++state->closed.size; - - // Finish the search - return ASTAR_SUCCESS; - } - - // Check if this node is already in the closed set - // - { - i64 index_in_closed = -1; - for (i64 i = 0; i < state->closed.size; ++i) - if (state->closed.values[i].id == neighbor_node.id) { - index_in_closed = i; - break; - } - if (index_in_closed != -1) { - if (state->closed.values[index_in_closed] - .exact_source_to_node < - neighbor_node.exact_source_to_node) - // Skip this node - continue; - // Replace the node - state->closed.values[index_in_closed] = neighbor_node; - } - } - - // Check if this node is already in the open set - // - { - i64 index_in_open = -1; - for (i64 i = 0; i < state->closed.size; ++i) - if (state->open.values[i].id == neighbor_node.id) { - index_in_open = i; - break; - } - if (index_in_open != -1) { - // Check if this node has a better estimate - // - if (neighbor_node.estimated_source_to_destination < - state->open.values[index_in_open] - .estimated_source_to_destination) - // Replace the node - state->open.values[index_in_open] = neighbor_node; - continue; - } - } - - if (state->open.size + 1 > state->open.capacity) { - // Restore the state - state->open.values[state->open.size - 1] = nearest_node; - ++state->open.size; - - return ASTAR_OUT_OF_MEMORY; - } - - // Add this node to the open set - // - state->open.values[state->open.size] = neighbor_node; - ++state->open.size; - } - - // Check if we can add a node to the closed set - // - if (state->closed.size + 1 > state->closed.capacity) { - // Restore the state - state->open.values[state->open.size - 1] = nearest_node; - ++state->open.size; - - return ASTAR_OUT_OF_MEMORY; - } - - // Add the nearest node to the closed set - // - state->closed.values[state->closed.size] = nearest_node; - ++state->closed.size; - - // Continue the search - return ASTAR_PROGRESS; -} - -#undef NAME_ -#undef CAT1_ -#undef CAT2_ - -#ifdef __GNUC__ -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#undef ASTAR_TEMPLATE -#endif diff --git a/source/kit/async_function.h b/source/kit/async_function.h deleted file mode 100644 index 70a81cd..0000000 --- a/source/kit/async_function.h +++ /dev/null @@ -1,233 +0,0 @@ -#ifndef KIT_ASYNC_FUNCTION_H -#define KIT_ASYNC_FUNCTION_H - -#include "types.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 - -#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 diff --git a/source/kit/atomic.h b/source/kit/atomic.h deleted file mode 100644 index 8ec7bad..0000000 --- a/source/kit/atomic.h +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef KIT_ATOMIC_H -#define KIT_ATOMIC_H - -#include "types.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 - -#define ATOMIC KIT_ATOMIC - -#endif diff --git a/source/kit/atomic.win32.c b/source/kit/atomic.win32.c deleted file mode 100644 index 791f8fe..0000000 --- a/source/kit/atomic.win32.c +++ /dev/null @@ -1,234 +0,0 @@ -#include "atomic.h" - -#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 diff --git a/source/kit/bigint.h b/source/kit/bigint.h deleted file mode 100644 index 159996a..0000000 --- a/source/kit/bigint.h +++ /dev/null @@ -1,603 +0,0 @@ -#ifndef KIT_BIGINT_H -#define KIT_BIGINT_H - -#include "string_ref.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 - -#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 diff --git a/source/kit/defer.h b/source/kit/defer.h deleted file mode 100644 index bb78b69..0000000 --- a/source/kit/defer.h +++ /dev/null @@ -1,39 +0,0 @@ -// Requres GCC or Clang with `-fblocks` option available. -// - -#ifndef KIT_DEFER_H -#define KIT_DEFER_H - -#if !defined(__clang__) && !defined(__APPLE__) -# error C blocks support required -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-function" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -#endif - -static void kit_defer_cleanup_(void (^*b)(void)) { (*b)(); } - -#define kit_defer_merge_(a,b) a##b -#define kit_defer_varname_(a) \ - kit_defer_merge_(kit_defer_scopevar_,a) -#define defer \ - __attribute__((unused, cleanup(kit_defer_cleanup_))) \ - void (^kit_defer_varname_(__COUNTER__))(void) = ^ -#define defer_ref __block - -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/dynamic_array.c b/source/kit/dynamic_array.c deleted file mode 100644 index ede817b..0000000 --- a/source/kit/dynamic_array.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "dynamic_array.h" - -#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; - } -} diff --git a/source/kit/dynamic_array.h b/source/kit/dynamic_array.h deleted file mode 100644 index 571f344..0000000 --- a/source/kit/dynamic_array.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef KIT_DYNAMIC_ARRAY_H -#define KIT_DYNAMIC_ARRAY_H - -#include "allocator.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 - -#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 diff --git a/source/kit/file.c b/source/kit/file.c deleted file mode 100644 index 3eafc70..0000000 --- a/source/kit/file.c +++ /dev/null @@ -1,691 +0,0 @@ -#include "file.h" - -#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) - -s32 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 -} - -s32 kit_folder_create_recursive(kit_str_t path) { - for (i32 i = 0;; i++) { - str_t part = kit_path_take(path, i); - i32 type = kit_path_type(part); - if (type == KIT_PATH_FILE) - return KIT_ERROR_FILE_ALREADY_EXISTS; - if (type == KIT_PATH_NONE) { - s32 s = kit_folder_create(part); - if (s != KIT_OK) - return s; - } - if (part.size == path.size) - break; - } - - return KIT_OK; -} - -s32 kit_file_remove(kit_str_t path) { - PREPARE_PATH_BUF_; -#if defined(_WIN32) && !defined(__CYGWIN__) - return DeleteFileA(buf) ? KIT_OK : KIT_ERROR_UNLINK_FAILED; -#else - return unlink(buf) == 0 ? KIT_OK : KIT_ERROR_UNLINK_FAILED; -#endif -} - -s32 kit_folder_remove(kit_str_t path) { - PREPARE_PATH_BUF_; -#if defined(_WIN32) && !defined(__CYGWIN__) - return RemoveDirectoryA(buf) ? KIT_OK : KIT_ERROR_RMDIR_FAILED; -#else - return rmdir(buf) == 0 ? KIT_OK : KIT_ERROR_RMDIR_FAILED; -#endif -} - -s32 kit_file_remove_recursive(kit_str_t path, - kit_allocator_t *alloc) { - i32 type = kit_path_type(path); - i64 i; - - switch (type) { - case KIT_PATH_FILE: { - s32 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); - s32 s = kit_file_remove_recursive(WRAP_STR(full_path), alloc); - DA_DESTROY(full_path); - assert(s == KIT_OK); - } - - kit_path_list_destroy(list); - - s32 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_OUT_OF_MEMORY; - 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_OUT_OF_MEMORY; - 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_OUT_OF_MEMORY; - 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_OUT_OF_MEMORY; - 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; -} - -s32 kit_file_sync(kit_mapped_file_t *mf) { - assert(mf != NULL); - - if (mf == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - - s32 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; -} - -s32 kit_file_unmap(kit_mapped_file_t *mf) { - assert(mf != NULL); - - if (mf == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - - s32 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; -} diff --git a/source/kit/file.h b/source/kit/file.h deleted file mode 100644 index 12f00a2..0000000 --- a/source/kit/file.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef KIT_FILE_H -#define KIT_FILE_H - -#include "dynamic_array.h" -#include "string_builder.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 { - s32 status; - - i64 time_modified_sec; - i32 time_modified_nsec; - i64 size; -} kit_file_info_t; - -typedef struct { - s32 status; - KIT_DA(kit_str_builder_t) files; -} kit_path_list_t; - -enum { KIT_FILE_MAP_PRIVATE, KIT_FILE_MAP_SHARED }; - -typedef struct { - s32 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); - -s32 kit_folder_create(kit_str_t path); - -s32 kit_folder_create_recursive(kit_str_t path); - -s32 kit_file_remove(kit_str_t path); - -s32 kit_folder_remove(kit_str_t path); - -s32 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); -s32 kit_file_sync(kit_mapped_file_t *mf); -s32 kit_file_unmap(kit_mapped_file_t *mf); - -#ifdef __cplusplus -} -#endif - -#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 diff --git a/source/kit/http1.h b/source/kit/http1.h deleted file mode 100644 index 98190ea..0000000 --- a/source/kit/http1.h +++ /dev/null @@ -1,511 +0,0 @@ -// TODO -// - Error handling -// - HTTPS support - -#ifndef KIT_HTTP1_H -#define KIT_HTTP1_H - -#include "types.h" -#include "string_builder.h" -#include "sockets.h" - -#include <stdio.h> -#include <assert.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define KIT_HTTP1_NEWLINE "\r\n" -#define KIT_HTTP1_SPACE " " -#define KIT_HTTP1_HEADER_SEPARATOR ": " -#define KIT_HTTP1_BUFFER_SIZE 8192 - -enum { - KIT_HTTP1_OPTIONS, - KIT_HTTP1_GET, - KIT_HTTP1_HEAD, - KIT_HTTP1_POST, - KIT_HTTP1_PUT, - KIT_HTTP1_DELETE, - KIT_HTTP1_TRACE, - KIT_HTTP1_CONNECT, -}; - -typedef struct { - kit_str_t key; - kit_str_t value; -} kit_http1_str_pair_t; - -typedef KIT_DA(kit_http1_str_pair_t) kit_http1_str_map_t; - -typedef struct { - kit_str_t str; - i64 position; -} kit_http1_tok_t; - -typedef struct { - kit_str_t protocol; - kit_str_t host; - kit_str_t port; - kit_str_t address; - kit_str_t query_string; - kit_str_t hash; - kit_http1_str_map_t parameters; -} kit_http1_uri_t; - -typedef struct { - i8 success; - kit_str_builder_t protocol; - kit_str_builder_t response; - kit_str_builder_t response_str; - kit_http1_str_map_t header; - kit_str_builder_t header_str; - kit_str_builder_t body; -} kit_http1_response_t; - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-function" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -#endif - -static kit_str_t kit_http1_tok_tail(kit_http1_tok_t *tok) { - assert(tok != NULL); - - if (tok == NULL) - return (kit_str_t) { .size = 0, .values = NULL }; - - i64 previous_position = tok->position; - tok->position = tok->str.size; - - return (kit_str_t) { .size = tok->position - previous_position, - .values = tok->str.values + - previous_position }; -} - -static kit_str_t kit_http1_tok_next(kit_http1_tok_t *tok, - kit_str_t search, - i8 return_tail) { - assert(tok != NULL); - if (tok == NULL) - return (kit_str_t) { .size = 0, .values = NULL }; - - i64 hit = tok->position; - - while (hit + search.size <= tok->str.size) { - kit_str_t s = { .size = search.size, - .values = tok->str.values + hit }; - if (KIT_AR_EQUAL(s, search)) - break; - } - - if (hit + search.size > tok->str.size) { - if (return_tail) - return kit_http1_tok_tail(tok); - else - return (kit_str_t) { .size = 0, .values = NULL }; - } - - i64 previous_position = tok->position; - tok->position = hit + search.size; - - return (kit_str_t) { .size = hit - previous_position, - .values = tok->str.values + - previous_position }; -} - -// TODO -// - Return error status -static void kit_http1_uri_init(kit_http1_uri_t *uri, kit_str_t input, - kit_allocator_t *alloc) { - static const kit_str_t port_80 = { .size = 2, .values = "80" }; - - assert(uri != NULL); - if (uri == NULL) - return; - - memset(uri, 0, sizeof *uri); - - kit_http1_tok_t input_tok = { .str = input, .position = 0 }; - - uri->protocol = kit_http1_tok_next(&input_tok, SZ("://"), 0); - kit_str_t host_port_str = kit_http1_tok_next(&input_tok, SZ("/"), - 0); - - // FIXME - // Handle invalid host port error - assert(host_port_str.size > 0); - if (host_port_str.size == 0) - return; - - kit_http1_tok_t host_port_tok = { .str = host_port_str, - .position = 0 }; - - uri->host = kit_http1_tok_next( - &host_port_tok, - host_port_str.values[0] == '[' ? SZ("]:") : SZ(":"), 1); - - if (uri->host.values[0] == '[') - uri->host = (kit_str_t) { .size = uri->host.size - 1, - .values = uri->host.values + 1 }; - - // TODO - // - HTTPS default port 443 - uri->port = kit_http1_tok_tail(&host_port_tok); - if (uri->port.size == 0) - uri->port = port_80; - - uri->address = kit_http1_tok_next(&input_tok, SZ("?"), 1); - uri->query_string = kit_http1_tok_next(&input_tok, SZ("#"), 1); - - uri->hash = kit_http1_tok_tail(&input_tok); - - KIT_DA_INIT(uri->parameters, 0, alloc); - - kit_http1_tok_t query_tok = { - .str = { .size = uri->query_string.size, - .values = uri->query_string.values }, - .position = 0 - }; - - for (;;) { - kit_str_t key = kit_http1_tok_next(&query_tok, SZ("="), 0); - if (key.size == 0) - break; - kit_str_t value = kit_http1_tok_next(&query_tok, SZ("&"), 1); - - i64 index = uri->parameters.size; - - KIT_DA_RESIZE(uri->parameters, index + 1); - - assert(uri->parameters.size == index + 1); - if (uri->parameters.size != index + 1) - // FIXME - // Handle bad alloc error - break; - - uri->parameters.values[index] = (kit_http1_str_pair_t) { - .key = key, .value = value - }; - } -} - -static void kit_http1_uri_destroy(kit_http1_uri_t *uri) { - assert(uri != NULL); - if (uri == NULL) - return; - - KIT_DA_DESTROY(uri->parameters); - - memset(uri, 0, sizeof *uri); -} - -static kit_str_t kit_http1_method_to_str(i32 method) { - static kit_str_t methods[] = { { .size = 7, .values = "OPTIONS" }, - { .size = 3, .values = "GET" }, - { .size = 4, .values = "HEAD" }, - { .size = 4, .values = "POST" }, - { .size = 3, .values = "PUT" }, - { .size = 6, .values = "DELETE" }, - { .size = 5, .values = "TRACE" }, - { .size = 7, .values = "CONNECT" } }; - - assert(method >= 0 && method < sizeof methods / sizeof *methods); - if (method < 0 || method >= sizeof methods / sizeof *methods) - return (kit_str_t) { .size = 0, .values = NULL }; - - return methods[method]; -} - -// TODO -// - Return error status -static socket_t kit_http1_connect_to_uri(kit_http1_uri_t *uri) { - assert(uri != NULL); - if (uri == NULL) - return INVALID_SOCKET; - - struct addrinfo hints, *result, *rp; - - memset(&hints, 0, sizeof hints); - - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - char host_str[128]; - char port_str[128]; - - assert(uri->host.size < sizeof host_str); - memcpy(host_str, uri->host.values, uri->host.size); - host_str[uri->host.size] = '\0'; - - assert(uri->port.size < sizeof port_str); - memcpy(port_str, uri->port.values, uri->port.size); - port_str[uri->port.size] = '\0'; - - i32 getaddrinfo_result = getaddrinfo(host_str, port_str, &hints, - &result); - - if (getaddrinfo_result != 0) - return INVALID_SOCKET; - - socket_t fd = INVALID_SOCKET; - - for (rp = result; rp != NULL; rp = rp->ai_next) { - fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - - if (fd == INVALID_SOCKET) - continue; - - i32 connect_result = connect(fd, rp->ai_addr, - (socklen_t) rp->ai_addrlen); - - if (connect_result == -1) { - closesocket(fd); - fd = INVALID_SOCKET; - continue; - } - - break; - } - - freeaddrinfo(result); - - return fd; -} - -// TODO -// - Return error status -static kit_str_builder_t kit_http1_buffered_read( - socket_t fd, kit_allocator_t *alloc) { - kit_str_builder_t buf; - KIT_DA_INIT(buf, KIT_HTTP1_BUFFER_SIZE, alloc); - - // FIXME - // Handle bad alloc error - assert(buf.size == KIT_HTTP1_BUFFER_SIZE); - if (buf.size != KIT_HTTP1_BUFFER_SIZE) - return buf; - - i64 offset = 0; - - for (;;) { - i64 chunk = buf.size - offset; - i64 n = recv(fd, buf.values + offset, (socklen_t) chunk, 0); - if (n < chunk) - break; - offset += n; - KIT_DA_RESIZE(buf, offset + KIT_HTTP1_BUFFER_SIZE); - - // FIXME - // Handle bad alloc error - assert(buf.size == offset + KIT_HTTP1_BUFFER_SIZE); - if (buf.size != offset + KIT_HTTP1_BUFFER_SIZE) - break; - } - - return buf; -} - -// TODO -// - Return error status -static kit_http1_response_t kit_http1_request( - i32 method, kit_http1_uri_t *uri, kit_str_t body, - kit_allocator_t *alloc) { - - socket_t fd = kit_http1_connect_to_uri(uri); - - assert(fd != INVALID_SOCKET); - if (fd == INVALID_SOCKET) { - kit_http1_response_t res; - memset(&res, 0, sizeof res); - res.success = 0; - return res; - } - - kit_str_builder_t req; - - // reserve - KIT_DA_INIT(req, 512, alloc); - - assert(req.size == 512); - if (req.size != 512) { - // bad alloc - // - - closesocket(fd); - - kit_http1_response_t res; - memset(&res, 0, sizeof res); - res.success = 0; - return res; - } - - req.size = 0; - - // FIXME - // Handle errors - // - - kit_str_append(&req, kit_http1_method_to_str(method)); - kit_str_append(&req, SZ(" /")); - kit_str_append(&req, uri->address); - kit_str_append(&req, - uri->query_string.size == 0 ? SZ("") : SZ("?")); - kit_str_append(&req, uri->query_string); - kit_str_append(&req, SZ(" HTTP/1.1")); - kit_str_append(&req, SZ(KIT_HTTP1_NEWLINE)); - - kit_str_append(&req, SZ("Host: ")); - kit_str_append(&req, uri->host); - kit_str_append(&req, SZ(":")); - kit_str_append(&req, uri->port); - kit_str_append(&req, SZ(KIT_HTTP1_NEWLINE)); - - kit_str_append(&req, SZ("Accept: */*")); - kit_str_append(&req, SZ(KIT_HTTP1_NEWLINE)); - - kit_str_append( - &req, - SZ("Content-Type: text/plain; version=0.0.4; charset=utf-8")); - kit_str_append(&req, SZ(KIT_HTTP1_NEWLINE)); - - // FIXME - // Use our own print instead - char content_length_str[11]; - sprintf(content_length_str, "%lld", body.size); - - kit_str_append(&req, SZ("Content-Length: ")); - kit_str_append(&req, - (kit_str_t) { .size = strlen(content_length_str), - .values = content_length_str }); - kit_str_append(&req, SZ(KIT_HTTP1_NEWLINE)); - - kit_str_append(&req, SZ(KIT_HTTP1_NEWLINE)); - kit_str_append(&req, body); - - // Append '\0' at the end - // - { - i64 n = req.size; - KIT_DA_RESIZE(req, n + 1); - - assert(req.size == n + 1); - if (req.size != n + 1) { - KIT_DA_DESTROY(req); - closesocket(fd); - - kit_http1_response_t res; - memset(&res, 0, sizeof res); - res.success = 0; - return res; - } - - req.size = n; - req.values[n] = '\0'; - } - - i64 req_size = req.size; - i64 n = send(fd, req.values, (socklen_t) req.size, 0); - - KIT_DA_DESTROY(req); - - if (n != req_size) { - // send failed - // - - closesocket(fd); - - kit_http1_response_t res; - memset(&res, 0, sizeof res); - res.success = 0; - return res; - } - - kit_str_builder_t buffer = kit_http1_buffered_read(fd, alloc); - - closesocket(fd); - - kit_http1_response_t res; - memset(&res, 0, sizeof res); - res.success = 1; - - kit_http1_tok_t buf_tok = { .str = { .size = buffer.size, - .values = buffer.values }, - .position = 0 }; - - res.protocol = kit_str_build( - kit_http1_tok_next(&buf_tok, SZ(KIT_HTTP1_SPACE), 0), alloc); - res.response = kit_str_build( - kit_http1_tok_next(&buf_tok, SZ(KIT_HTTP1_SPACE), 0), alloc); - res.response_str = kit_str_build( - kit_http1_tok_next(&buf_tok, SZ(KIT_HTTP1_NEWLINE), 0), alloc); - - res.header_str = kit_str_build( - kit_http1_tok_next(&buf_tok, - SZ(KIT_HTTP1_NEWLINE KIT_HTTP1_NEWLINE), 0), - alloc); - - res.body = kit_str_build(kit_http1_tok_tail(&buf_tok), alloc); - - kit_http1_tok_t header_tok = { - .str = (kit_str_t) { .size = res.header_str.size, - .values = res.header_str.values }, - .position = 0 - }; - - KIT_DA_INIT(res.header, 0, alloc); - - for (;;) { - kit_str_t key = kit_http1_tok_next( - &header_tok, SZ(KIT_HTTP1_HEADER_SEPARATOR), 0); - if (key.size == 0) - break; - kit_str_t value = kit_http1_tok_next(&header_tok, - SZ(KIT_HTTP1_NEWLINE), 1); - - i64 index = res.header.size; - - KIT_DA_RESIZE(res.header, index + 1); - - assert(res.header.size == index + 1); - if (res.header.size != index + 1) { - // FIXME - // Handle bad alloc error - res.success = 0; - break; - } - - res.header.values[index] = (kit_http1_str_pair_t) { - .key = key, .value = value - }; - } - - return res; -} - -static void kit_http1_response_destroy( - kit_http1_response_t *response) { - assert(response != NULL); - if (response == NULL) - return; - - KIT_DA_DESTROY(response->protocol); - KIT_DA_DESTROY(response->response); - KIT_DA_DESTROY(response->response_str); - KIT_DA_DESTROY(response->header); - KIT_DA_DESTROY(response->header_str); - KIT_DA_DESTROY(response->body); - - memset(response, 0, sizeof *response); -} - -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/input_buffer.c b/source/kit/input_buffer.c deleted file mode 100644 index 59298c8..0000000 --- a/source/kit/input_buffer.c +++ /dev/null @@ -1,360 +0,0 @@ -#include "input_buffer.h" - -#include <assert.h> -#include <string.h> - -enum { KIT_IB_CACHE_SIZE = 256 }; - -static s32 kit_buf_adjust_(kit_input_buffer_t *buf, i64 size) { - assert(buf != NULL); - assert(size >= 0); - - if (buf == NULL) - return KIT_ERROR_INTERNAL; - - i64 offset = buf->data.size; - - if (offset >= size) - return KIT_OK; - - DA_RESIZE(buf->data, size); - if (buf->data.size != size) - return KIT_ERROR_OUT_OF_MEMORY; - - str_t destination = { .size = size - offset, - .values = buf->data.values + offset }; - i64 n = IS_READ(buf->upstream, destination); - - DA_RESIZE(buf->data, offset + n); - if (buf->data.size != offset + n) - return KIT_ERROR_OUT_OF_MEMORY; - - return KIT_OK; -} - -kit_input_buffer_t kit_ib_wrap(is_handle_t upstream, - kit_allocator_t *alloc) { - kit_input_buffer_t buf; - memset(&buf, 0, sizeof buf); - - buf.upstream = upstream; - DA_INIT(buf.data, 0, alloc); - - return buf; -} - -void kit_ib_destroy(kit_input_buffer_t *buf) { - assert(buf != NULL); - if (buf == NULL) - return; - - DA_DESTROY(buf->data); - memset(buf, 0, sizeof *buf); -} - -kit_ib_token_t kit_ib_token(kit_input_buffer_t *buf) { - return (kit_ib_token_t) { - .status = KIT_OK, .offset = 0, .size = 0, .buffer = buf - }; -} - -kit_str_t kit_ib_str(kit_ib_token_t tok) { - assert(tok.buffer != NULL); - - if (tok.buffer == NULL || tok.buffer->data.values == NULL) - return (str_t) { .size = 0, .values = NULL }; - - return (str_t) { .size = tok.size, - .values = tok.buffer->data.values + tok.offset }; -} - -kit_ib_token_t kit_ib_read(kit_ib_token_t tok, i64 size) { - assert(tok.buffer != NULL); - - kit_ib_token_t next = tok; - - next.offset = tok.offset + tok.size; - next.size = 0; - - if (tok.status != KIT_OK) - return next; - - if (tok.buffer == NULL) { - next.status = KIT_ERROR_INVALID_ARGUMENT; - return next; - } - - s32 s = kit_buf_adjust_(tok.buffer, tok.offset + tok.size + size); - - if (s != KIT_OK) { - next.status = s; - return next; - } - - assert(tok.buffer->data.values != NULL); - - if (tok.buffer->data.values == NULL) { - next.status = KIT_ERROR_INTERNAL; - return next; - } - - next.size = size < tok.buffer->data.size - tok.offset - tok.size - ? size - : tok.buffer->data.size - tok.offset - tok.size; - - return next; -} - -#define IB_CACHE_INIT_(res_) \ - str_builder_t cache_dynamic; \ - memset(&cache_dynamic, 0, sizeof cache_dynamic); \ - char cache_static[KIT_IB_CACHE_SIZE]; \ - \ - do { \ - if (data.size > 0) { \ - if (data.size < KIT_IB_CACHE_SIZE) { \ - memcpy(cache_static, data.values, data.size); \ - data.values = cache_static; \ - } else { \ - DA_INIT(cache_dynamic, data.size, tok.buffer->data.alloc); \ - if (cache_dynamic.size != data.size) { \ - (res_).status |= KIT_ERROR_OUT_OF_MEMORY; \ - return (res_); \ - } \ - memcpy(cache_dynamic.values, data.values, data.size); \ - data.values = cache_dynamic.values; \ - } \ - } \ - } while (0) - -#define IB_CACHE_CLEANUP_() \ - do { \ - if (cache_dynamic.values != NULL) \ - DA_DESTROY(cache_dynamic); \ - } while (0) - -kit_ib_token_t kit_ib_any(kit_ib_token_t tok, str_t data) { - assert(tok.buffer != NULL); - - kit_ib_token_t next = tok; - - next.offset = tok.offset + tok.size; - next.size = 0; - - if (tok.status != KIT_OK) - return next; - - if (tok.buffer == NULL) { - next.status = KIT_ERROR_INVALID_ARGUMENT; - return next; - } - - IB_CACHE_INIT_(next); - - for (;; ++next.size) { - s32 s = kit_buf_adjust_(tok.buffer, - tok.offset + tok.size + next.size + 1); - - if (s != KIT_OK) { - next.status = s; - return next; - } - - assert(tok.buffer->data.values != NULL); - - if (tok.buffer->data.values == NULL) { - next.status = KIT_ERROR_INTERNAL; - return next; - } - - if (tok.offset + tok.size + next.size >= tok.buffer->data.size) - break; - - i8 found = 0; - - for (i64 i = 0; i < data.size; i++) - if (data.values[i] == - tok.buffer->data.values[next.offset + next.size]) { - found = 1; - break; - } - - if (!found) - break; - } - - IB_CACHE_CLEANUP_(); - - return next; -} - -kit_ib_token_t kit_ib_none(kit_ib_token_t tok, str_t data) { - assert(tok.buffer != NULL); - - kit_ib_token_t next = tok; - - next.offset = tok.offset + tok.size; - next.size = 0; - - if (tok.status != KIT_OK) - return next; - - if (tok.buffer == NULL) { - next.status = KIT_ERROR_INVALID_ARGUMENT; - return next; - } - - IB_CACHE_INIT_(next); - - for (;; ++next.size) { - s32 s = kit_buf_adjust_(tok.buffer, - tok.offset + tok.size + next.size + 1); - - if (s != KIT_OK) { - next.status = s; - return next; - } - - assert(tok.buffer->data.values != NULL); - - if (tok.buffer->data.values == NULL) { - next.status = KIT_ERROR_INTERNAL; - return next; - } - - if (tok.offset + tok.size + next.size >= tok.buffer->data.size) - break; - - i8 found = 0; - - for (i64 i = 0; i < data.size; i++) - if (data.values[i] == - tok.buffer->data.values[next.offset + next.size]) { - found = 1; - break; - } - - if (found) - break; - } - - IB_CACHE_CLEANUP_(); - - return next; -} - -kit_ib_token_t kit_ib_exact(kit_ib_token_t tok, str_t data) { - kit_ib_token_t res = tok; - - res.offset = tok.offset + tok.size; - res.size = 0; - - IB_CACHE_INIT_(res); - - res = kit_ib_read(tok, data.size); - if (!AR_EQUAL(kit_ib_str(res), data)) - res.status = KIT_PARSING_FAILED; - - IB_CACHE_CLEANUP_(); - - return res; -} - -kit_ib_token_t kit_ib_until(kit_ib_token_t tok, str_t data) { - assert(tok.buffer != NULL); - - kit_ib_token_t next = tok; - - next.offset = tok.offset + tok.size; - next.size = 0; - - if (tok.status != KIT_OK) - return next; - - if (tok.buffer == NULL) { - next.status = KIT_ERROR_INVALID_ARGUMENT; - return next; - } - - IB_CACHE_INIT_(next); - - for (;; ++next.size) { - s32 s = kit_buf_adjust_(tok.buffer, - tok.offset + tok.size + next.size + 1); - - if (s != KIT_OK) { - next.status = s; - return next; - } - - assert(tok.buffer->data.values != NULL); - - if (tok.buffer->data.values == NULL) { - next.status = KIT_ERROR_INTERNAL; - return next; - } - - if (tok.offset + tok.size + next.size >= tok.buffer->data.size) - break; - - if (next.size + 1 >= data.size && - AR_EQUAL(kit_str(data.size, tok.buffer->data.values + - (next.offset + next.size + 1 - - data.size)), - data)) { - next.size -= data.size - 1; - break; - } - } - - IB_CACHE_CLEANUP_(); - - return next; -} - -kit_ib_token_t kit_ib_while(kit_ib_token_t tok, - kit_ib_read_condition_fn condition, - void *context) { - assert(tok.buffer != NULL); - - kit_ib_token_t next = tok; - - next.offset = tok.offset + tok.size; - next.size = 0; - - if (tok.status != KIT_OK) - return next; - - if (tok.buffer == NULL) { - next.status = KIT_ERROR_INVALID_ARGUMENT; - return next; - } - - for (;; ++next.size) { - s32 s = kit_buf_adjust_(tok.buffer, - tok.offset + tok.size + next.size + 1); - - if (s != KIT_OK) { - next.status = s; - return next; - } - - assert(tok.buffer->data.values != NULL); - - if (tok.buffer->data.values == NULL) { - next.status = KIT_ERROR_INTERNAL; - return next; - } - - if (tok.offset + tok.size + next.size >= tok.buffer->data.size) - break; - - if (condition == NULL || - !condition(kit_str(next.size + 1, - tok.buffer->data.values + next.offset), - context)) - break; - } - - return next; -} diff --git a/source/kit/input_buffer.h b/source/kit/input_buffer.h deleted file mode 100644 index 4320ee7..0000000 --- a/source/kit/input_buffer.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef KIT_INPUT_BUFFER_H -#define KIT_INPUT_BUFFER_H - -#include "string_builder.h" -#include "input_stream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - kit_is_handle_t upstream; - kit_str_builder_t data; -} kit_input_buffer_t; - -typedef struct { - s32 status; - i64 offset; - i64 size; - kit_input_buffer_t *buffer; -} kit_ib_token_t; - -typedef b8 (*kit_ib_read_condition_fn)(kit_str_t data, void *context); - -kit_input_buffer_t kit_ib_wrap(kit_is_handle_t upstream, - kit_allocator_t *alloc); - -void kit_ib_destroy(kit_input_buffer_t *buf); - -kit_ib_token_t kit_ib_token(kit_input_buffer_t *buf); - -kit_str_t kit_ib_str(kit_ib_token_t tok); - -kit_ib_token_t kit_ib_read(kit_ib_token_t tok, i64 size); - -kit_ib_token_t kit_ib_any(kit_ib_token_t tok, kit_str_t data); - -kit_ib_token_t kit_ib_none(kit_ib_token_t tok, kit_str_t data); - -kit_ib_token_t kit_ib_exact(kit_ib_token_t tok, kit_str_t data); - -kit_ib_token_t kit_ib_until(kit_ib_token_t tok, kit_str_t data); - -kit_ib_token_t kit_ib_while(kit_ib_token_t buf, - kit_ib_read_condition_fn condition, - void *context); - -#define KIT_IB_SKIP(buf_, proc_, ...) \ - do { \ - kit_ib_token_t temp_buf_ = (buf_); \ - (buf_) = proc_((buf_), __VA_ARGS__); \ - } while (0) - -#ifdef __cplusplus -} -#endif - -#define input_buffer_t kit_input_buffer_t -#define ib_token_t kit_ib_token_t -#define ib_read_condition_fn kit_ib_read_condition_fn -#define ib_wrap kit_ib_wrap -#define ib_destroy kit_ib_destroy -#define ib_token kit_ib_token -#define ib_str kit_ib_str -#define ib_read kit_ib_read -#define ib_any kit_ib_any -#define ib_none kit_ib_none -#define ib_exact kit_ib_exact -#define ib_until kit_ib_until -#define ib_while kit_ib_while -#define IB_SKIP KIT_IB_SKIP - -#endif diff --git a/source/kit/input_stream.c b/source/kit/input_stream.c deleted file mode 100644 index 369cf64..0000000 --- a/source/kit/input_stream.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "input_stream.h" - -#include <string.h> - -enum { KIT_INPUT_STREAM_STR, KIT_INPUT_STREAM_FILE }; - -typedef struct { - i64 type; - kit_allocator_t *alloc; -} kit_is_state_basic_t; - -typedef struct { - i64 type; - kit_allocator_t *alloc; - kit_str_t string; -} kit_is_state_str_t; - -typedef struct { - i64 type; - kit_allocator_t *alloc; - FILE *file; -} kit_is_state_file_t; - -static int kit_is_check_type_(void *state, i64 type) { - kit_is_state_basic_t *basic = (kit_is_state_basic_t *) state; - return basic != NULL && basic->type == type; -} - -static i64 kit_read_str_(void *state, kit_str_t destination) { - if (!kit_is_check_type_(state, KIT_INPUT_STREAM_STR)) - return 0; - - kit_is_state_str_t *str = (kit_is_state_str_t *) state; - i64 size = destination.size < str->string.size ? destination.size - : str->string.size; - memcpy(destination.values, str->string.values, size); - str->string.values += size; - str->string.size -= size; - return size; -} - -static i64 kit_read_file_(void *state, kit_str_t destination) { - if (!kit_is_check_type_(state, KIT_INPUT_STREAM_FILE)) - return 0; - - kit_is_state_file_t *f = (kit_is_state_file_t *) state; - - if (f->file == NULL || feof(f->file)) - return 0; - - i64 size = (i64) fread(destination.values, 1, destination.size, - f->file); - - if (size <= 0) - return 0; - - return size; -} - -kit_is_handle_t kit_is_wrap_string(kit_str_t string, - kit_allocator_t *alloc) { - kit_is_handle_t in; - memset(&in, 0, sizeof in); - - kit_is_state_str_t *state = (kit_is_state_str_t *) - kit_alloc_dispatch(alloc, KIT_ALLOCATE, - sizeof(kit_is_state_str_t), 0, NULL); - if (state != NULL) { - memset(state, 0, sizeof *state); - state->type = KIT_INPUT_STREAM_STR; - state->string = string; - state->alloc = alloc; - in.state = state; - in.read = kit_read_str_; - } - return in; -} - -kit_is_handle_t kit_is_wrap_file(FILE *f, kit_allocator_t *alloc) { - kit_is_handle_t in; - memset(&in, 0, sizeof in); - - kit_is_state_file_t *state = (kit_is_state_file_t *) - kit_alloc_dispatch(alloc, KIT_ALLOCATE, - sizeof(kit_is_state_file_t), 0, NULL); - - if (state != NULL) { - memset(state, 0, sizeof *state); - state->type = KIT_INPUT_STREAM_FILE; - state->file = f; - state->alloc = alloc; - in.state = state; - in.read = kit_read_file_; - } - - return in; -} - -void kit_is_destroy(kit_is_handle_t in) { - kit_is_state_basic_t *basic = (kit_is_state_basic_t *) in.state; - if (basic != NULL) - kit_alloc_dispatch(basic->alloc, KIT_DEALLOCATE, 0, 0, in.state); -} diff --git a/source/kit/input_stream.h b/source/kit/input_stream.h deleted file mode 100644 index 51a7520..0000000 --- a/source/kit/input_stream.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef KIT_INPUT_STREAM_H -#define KIT_INPUT_STREAM_H - -#include "allocator.h" -#include "string_ref.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 - -#define is_read_fn kit_is_read_fn -#define is_handle_t kit_is_handle_t -#define is_wrap_string kit_is_wrap_string -#define is_wrap_file kit_is_wrap_file -#define is_destroy kit_is_destroy -#define IS_WRAP_STRING KIT_IS_WRAP_STRING -#define IS_WRAP_FILE KIT_IS_WRAP_FILE -#define IS_READ KIT_IS_READ - -#endif diff --git a/source/kit/lower_bound.h b/source/kit/lower_bound.h deleted file mode 100644 index eb437ed..0000000 --- a/source/kit/lower_bound.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef KIT_LOWER_BOUND_H -#define KIT_LOWER_BOUND_H - -#include "types.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 - -#define LOWER_BOUND_INL KIT_LOWER_BOUND_INL -#define LOWER_BOUND KIT_LOWER_BOUND -#define LOWER_BOUND_REF KIT_LOWER_BOUND_REF - -#endif diff --git a/source/kit/math.h b/source/kit/math.h deleted file mode 100644 index d7044f1..0000000 --- a/source/kit/math.h +++ /dev/null @@ -1,780 +0,0 @@ -#ifndef KIT_MATH_H -#define KIT_MATH_H - -#include "types.h" - -#ifndef _USE_MATH_DEFINES -# define _USE_MATH_DEFINES -#endif -#include <math.h> - -#include <assert.h> -#include <string.h> - -// TODO -// - Gamma correction. -// - Custom prefixes -// - Unnecesary XYZ scaling. - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif - -#ifndef M_E -# define M_E 2.71828182845904523536 -#endif - -#ifndef KIT_VEC_TYPE -# define KIT_VEC_TYPE f32 -#endif - -#define KIT_EPSILON .00001 - -#define KIT_COLOR_REF_X 95.047f -#define KIT_COLOR_REF_Y 100.0f -#define KIT_COLOR_REF_Z 108.883f - -typedef KIT_VEC_TYPE vec_t; - -typedef struct { - vec_t v[2]; -} vec2_t; - -typedef struct { - vec_t v[3]; -} vec3_t; - -typedef struct { - vec_t v[4]; -} vec4_t, quat_t; - -typedef struct { - vec_t v[9]; -} mat3_t; - -typedef struct { - vec_t v[16]; -} mat4_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 vec2_t vec2(vec_t x, vec_t y) { - vec2_t v = { { x, y } }; - return v; -} - -static vec3_t vec3(vec_t x, vec_t y, vec_t z) { - vec3_t v = { { x, y, z } }; - return v; -} - -static vec4_t vec4(vec_t x, vec_t y, vec_t z, vec_t w) { - vec4_t v = { { x, y, z, w } }; - return v; -} - -static mat3_t mat3( // - vec_t _00, vec_t _01, vec_t _02, // - vec_t _10, vec_t _11, vec_t _12, // - vec_t _20, vec_t _21, vec_t _22) { - mat3_t m = { { - _00, _01, _02, // - _10, _11, _12, // - _20, _21, _22 // - } }; - return m; -} - -static mat4_t mat4(vec_t _00, vec_t _01, vec_t _02, vec_t _03, - vec_t _10, vec_t _11, vec_t _12, vec_t _13, - vec_t _20, vec_t _21, vec_t _22, vec_t _23, - vec_t _30, vec_t _31, vec_t _32, vec_t _33) { - mat4_t m = { { - _00, _01, _02, _03, // - _10, _11, _12, _13, // - _20, _21, _22, _23, // - _30, _31, _32, _33 // - } }; - return m; -} - -static mat3_t vec3_to_mat3(vec3_t a, vec3_t b, vec3_t c) { - return mat3(a.v[0], a.v[1], a.v[2], // - b.v[0], b.v[1], b.v[2], // - c.v[0], c.v[1], c.v[2]); -} - -static mat4_t vec4_to_mat4(vec4_t a, vec4_t b, vec4_t c, vec4_t d) { - return mat4(a.v[0], a.v[1], a.v[2], a.v[3], // - b.v[0], b.v[1], b.v[2], b.v[3], // - c.v[0], c.v[1], c.v[2], c.v[3], // - d.v[0], d.v[1], d.v[2], d.v[3]); -} - -static mat4_t mat3_to_mat4(mat3_t a) { - return mat4(a.v[0], a.v[1], a.v[2], 0.f, // - a.v[3], a.v[4], a.v[5], 0.f, // - a.v[6], a.v[7], a.v[8], 0.f, // - 0.f, 0.f, 0.f, 1.f); -} - -static mat3_t mat4_to_mat3(mat4_t a) { - return mat3(a.v[0], a.v[1], a.v[2], // - a.v[4], a.v[5], a.v[6], // - a.v[8], a.v[9], a.v[10]); -} - -static quat_t quat(vec_t x, vec_t y, vec_t z, vec_t w) { - return vec4(x, y, z, w); -} - -static quat_t vec3_to_quat(vec3_t v, vec_t w) { - return quat(v.v[0], v.v[1], v.v[2], w); -} - -static vec3_t vec4_to_vec3(vec4_t a) { - return vec3(a.v[0], a.v[1], a.v[2]); -} - -static vec3_t quat_to_vec3(quat_t a) { - return vec4_to_vec3(a); -} - -static vec_t vec_abs(vec_t x) { - return fabs(x); -} - -static vec_t vec_min(vec_t x, vec_t y) { - return fmin(x, y); -} - -static vec_t vec_max(vec_t x, vec_t y) { - return fmax(x, y); -} - -static vec_t vec_clamp(vec_t x, vec_t x0, vec_t x1) { - return fmax(x0, fmin(x, x1)); -} - -static vec3_t vec3_clamp(vec3_t x, vec3_t x0, vec3_t x1) { - return vec3(vec_clamp(x.v[0], x0.v[0], x1.v[0]), - vec_clamp(x.v[1], x0.v[1], x1.v[1]), - vec_clamp(x.v[2], x0.v[2], x1.v[2])); -} - -static vec_t vec_sqrt(vec_t x) { - return sqrtf(x); -} - -static vec_t vec_pow(vec_t x, vec_t y) { - return powf(x, y); -} - -static vec_t vec_sin(vec_t x) { - return sinf(x); -} - -static vec_t vec_cos(vec_t x) { - return cosf(x); -} - -static vec_t vec_asin(vec_t x) { - return asinf(x); -} - -static vec_t vec_acos(vec_t x) { - return acosf(x); -} - -static vec_t vec_atan(vec_t x) { - return atanf(x); -} - -static vec_t vec_atan2(vec_t y, vec_t x) { - return atan2f(y, x); -} - -static vec3_t vec3_neg(vec3_t a) { - return vec3(-a.v[0], -a.v[1], -a.v[2]); -} - -static vec3_t vec3_add(vec3_t a, vec3_t b) { - return vec3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]); -} - -static vec3_t vec3_add3(vec3_t a, vec3_t b, vec3_t c) { - return vec3(a.v[0] + b.v[0] + c.v[0], a.v[1] + b.v[1] + c.v[1], - a.v[2] + b.v[2] + c.v[2]); -} - -static vec3_t vec3_sub(vec3_t a, vec3_t b) { - return vec3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]); -} - -static vec3_t vec3_mul(vec3_t v, vec_t x) { - return vec3(v.v[0] * x, v.v[1] * x, v.v[2] * x); -} - -static vec_t vec3_dot(vec3_t a, vec3_t b) { - return a.v[0] * b.v[0] + a.v[1] * b.v[1] + a.v[2] * b.v[2]; -} - -static vec3_t vec3_cross(vec3_t a, vec3_t b) { - return vec3(a.v[1] * b.v[2] - a.v[2] * b.v[1], // - a.v[2] * b.v[0] - a.v[0] * b.v[2], // - a.v[0] * b.v[1] - a.v[1] * b.v[0]); -} - -static vec3_t vec3_normal(vec3_t v) { - vec_t x = v.v[0]; - vec_t y = v.v[1]; - vec_t z = v.v[2]; - - vec_t length_squared = x * x + y * y + z * z; - assert(length_squared >= KIT_EPSILON); - - if (length_squared < KIT_EPSILON) { - vec3_t n = { { 0.f, 0.f, 1.f } }; - return n; - } - - vec_t length = vec_sqrt(length_squared); - vec3_t n = { { x / length, y / length, z / length } }; - - return n; -} - -static vec4_t vec4_neg(vec4_t a) { - return vec4(-a.v[0], -a.v[1], -a.v[2], -a.v[3]); -} - -static vec4_t vec4_add(vec4_t a, vec4_t b) { - return vec4(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2], - a.v[3] + b.v[3]); -} - -static vec4_t vec4_mul(vec4_t v, vec_t x) { - return vec4(v.v[0] * x, v.v[1] * x, v.v[2] * x, v.v[3] * x); -} - -static vec4_t vec4_div(vec4_t v, vec_t x) { - assert(x < KIT_EPSILON); - assert(x > -KIT_EPSILON); - - if (x >= -KIT_EPSILON || x < KIT_EPSILON) - return vec4(0.f, 0.f, 0.f, 0.f); - - return vec4(v.v[0] / x, v.v[1] / x, v.v[2] / x, v.v[3] / x); -} - -static vec_t vec4_dot(vec4_t a, vec4_t b) { - return a.v[0] * b.v[0] + a.v[1] * b.v[1] + a.v[2] * b.v[2] + - a.v[3] * b.v[3]; -} - -static vec4_t vec4_normal(vec4_t v) { - vec_t x = v.v[0]; - vec_t y = v.v[1]; - vec_t z = v.v[2]; - vec_t w = v.v[3]; - - vec_t length_squared = x * x + y * y + z * z + w * w; - assert(length_squared >= KIT_EPSILON); - - if (length_squared < KIT_EPSILON) { - vec4_t n = { { 0.f, 0.f, 0.f, 1.f } }; - return n; - } - - vec_t length = vec_sqrt(length_squared); - vec4_t n = { { x / length, y / length, z / length, w / length } }; - - return n; -} - -static quat_t quat_conjugate(quat_t q) { - return quat(-q.v[0], -q.v[1], -q.v[2], q.v[3]); -} - -static quat_t quat_normal(quat_t q) { - return vec4_normal(q); -} - -static quat_t quat_mul(quat_t left, quat_t right) { - vec_t i0 = left.v[0]; - vec_t j0 = left.v[1]; - vec_t k0 = left.v[2]; - vec_t r0 = left.v[3]; - - vec_t i1 = right.v[0]; - vec_t j1 = right.v[1]; - vec_t k1 = right.v[2]; - vec_t r1 = right.v[3]; - - quat_t q = { { r0 * i1 + i0 * r1 + j0 * k1 - k0 * j1, // - r0 * j1 - i0 * k1 + j0 * r1 + k0 * i1, // - r0 * k1 + i0 * j1 - j0 * i1 + k0 * r1, // - r0 * r1 - i0 * i1 - j0 * j1 - k0 * k1 } }; - - return q; -} - -static quat_t quat_rotation(vec_t angle, vec3_t axis) { - vec_t s = vec_sin(angle / 2.f); - vec_t c = vec_cos(angle / 2.f); - - vec_t x = axis.v[0]; - vec_t y = axis.v[1]; - vec_t z = axis.v[2]; - - quat_t q = { { x * s, y * s, z * s, c } }; - - return q; -} - -static mat3_t mat3_transpose(mat3_t m) { - return mat3(m.v[0], m.v[3], m.v[6], // - m.v[1], m.v[4], m.v[7], // - m.v[2], m.v[5], m.v[8]); -} - -static mat4_t mat4_transpose(mat4_t m) { - return mat4(m.v[0], m.v[4], m.v[8], m.v[12], // - m.v[1], m.v[5], m.v[9], m.v[13], // - m.v[2], m.v[6], m.v[10], m.v[14], // - m.v[3], m.v[7], m.v[11], m.v[15]); -} - -static mat3_t mat3_look_at(vec3_t direction, vec3_t up) { - vec3_t f = vec3_normal(vec3_neg(direction)); - vec3_t s = vec3_normal(vec3_cross(f, up)); - vec3_t u = vec3_cross(s, f); - - return mat3(s.v[0], u.v[0], f.v[0], // - s.v[1], u.v[1], f.v[1], // - s.v[2], u.v[2], f.v[2]); -} - -static vec3_t vec3_rotate(vec3_t v, quat_t rotation) { - vec3_t u = vec3(rotation.v[0], rotation.v[1], rotation.v[2]); - vec_t s = rotation.v[3]; - - return vec3_add3(vec3_mul(u, 2.f * vec3_dot(u, v)), - vec3_mul(v, s * s - vec3_dot(u, u)), - vec3_mul(vec3_cross(u, v), 2.f * s)); -} - -static mat3_t quat_to_mat3(quat_t q) { - vec_t xx = q.v[0] * q.v[0]; - vec_t yy = q.v[1] * q.v[1]; - vec_t zz = q.v[2] * q.v[2]; - vec_t xz = q.v[0] * q.v[2]; - vec_t xy = q.v[0] * q.v[1]; - vec_t yz = q.v[1] * q.v[2]; - vec_t wx = q.v[3] * q.v[0]; - vec_t wy = q.v[3] * q.v[1]; - vec_t wz = q.v[3] * q.v[2]; - - return mat3(1.f - 2.f * (yy + zz), // - 2.f * (xy + wz), // - 2.f * (xz - wy), // - 2.f * (xy - wz), // - 1.f - 2.f * (xx + zz), // - 2.f * (yz + wx), // - 2.f * (xz + wy), // - 2.f * (yz - wx), // - 1.f - 2.f * (xx + yy)); -} - -static quat_t mat3_to_quat(mat3_t m) { - vec_t a = m.v[0] - m.v[4] - m.v[8]; - vec_t b = m.v[4] - m.v[0] - m.v[8]; - vec_t c = m.v[8] - m.v[0] - m.v[4]; - vec_t d = m.v[0] + m.v[4] + m.v[8]; - - int n = 0; - vec_t h = d; - if (a > h) { - h = a; - n = 1; - } - if (b > h) { - h = b; - n = 2; - } - if (c > h) { - h = c; - n = 3; - } - - vec_t s = vec_sqrt(h + 1.f) * .5f; - vec_t k = .25f / s; - - switch (n) { - case 0: - return quat((m.v[5] - m.v[7]) * k, // - (m.v[6] - m.v[2]) * k, // - (m.v[1] - m.v[3]) * k, // - s); - case 1: - return quat(s, // - (m.v[1] + m.v[3]) * k, // - (m.v[6] + m.v[2]) * k, // - (m.v[5] - m.v[7]) * k); - case 2: - return quat((m.v[1] + m.v[3]) * k, // - s, // - (m.v[5] + m.v[7]) * k, // - (m.v[6] - m.v[2]) * k); - case 3: - return quat((m.v[6] + m.v[2]) * k, // - (m.v[5] + m.v[7]) * k, // - s, // - (m.v[1] - m.v[3]) * k); - default:; - } - - assert(0); - return quat(0.f, 0.f, 0.f, 1.f); -} - -static quat_t quat_look_at(vec3_t direction, vec3_t up) { - vec3_t z = vec3_normal(vec3_neg(direction)); - vec3_t right = vec3_cross(up, z); - vec3_t x = vec3_mul( - right, - 1.f / vec_sqrt(vec_max(KIT_EPSILON, vec3_dot(right, right)))); - vec3_t y = vec3_cross(z, x); - - return mat3_to_quat(vec3_to_mat3(x, y, z)); -} - -static mat3_t mat3_mul(mat3_t left, mat3_t right) { - mat3_t m; - memset(&m, 0, sizeof m); - - for (int j = 0; j < 3; j++) - for (int i = 0; i < 3; i++) - for (int k = 0; k < 3; k++) - m.v[j * 3 + i] += left.v[k * 3 + i] * right.v[j * 3 + k]; - - return m; -} - -static mat4_t mat4_mul(mat4_t left, mat4_t right) { - mat4_t m; - memset(&m, 0, sizeof m); - - for (int j = 0; j < 4; j++) - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - m.v[j * 4 + i] += left.v[k * 4 + i] * right.v[j * 4 + k]; - - return m; -} - -static mat4_t mat4_move(vec3_t offset) { - vec_t x = offset.v[0]; - vec_t y = offset.v[1]; - vec_t z = offset.v[2]; - - return mat4(1.f, 0.f, 0.f, 0.f, // - 0.f, 1.f, 0.f, 0.f, // - 0.f, 0.f, 1.f, 0.f, // - x, y, z, 1.f); -} - -static mat4_t mat4_scale(vec3_t scale) { - vec_t x = scale.v[0]; - vec_t y = scale.v[1]; - vec_t z = scale.v[2]; - - return mat4(x, 0.f, 0.f, 0.f, // - 0.f, y, 0.f, 0.f, // - 0.f, 0.f, z, 0.f, // - 0.f, 0.f, 0.f, 1.f); -} - -static mat4_t mat4_frustum(vec_t left, vec_t right, vec_t bottom, - vec_t top, vec_t znear, vec_t zfar) { - vec_t t0 = 2.f * znear; - vec_t t1 = right - left; - vec_t t2 = top - bottom; - vec_t t3 = zfar - znear; - - return mat4(t0 / t1, // - 0.f, // - 0.f, // - 0.f, // - 0.f, // - t0 / t2, // - 0.f, // - 0.f, // - (right + left) / t1, // - (top + bottom) / t2, // - (-zfar - znear) / t3, // - -1.f, // - 0.f, // - 0.f, // - (-t0 * zfar) / t3, // - 0.f); -} - -static mat4_t mat4_perspective(vec_t fovy, vec_t aspect_ratio_, - vec_t znear, vec_t zfar) { - vec_t ymax = znear * tanf(fovy); - vec_t xmax = ymax * aspect_ratio_; - - return mat4_frustum(-xmax, xmax, -ymax, ymax, znear, zfar); -} - -static vec_t vec_lerp(vec_t x0, vec_t x1, vec_t t) { - assert(t >= 0.f); - assert(t <= 1.f); - - if (t <= 0.f) - return x0; - if (t >= 1.f) - return x1; - - return x0 + (x1 - x0) * t; -} - -static vec3_t vec3_lerp(vec3_t x0, vec3_t x1, vec_t t) { - return vec3(vec_lerp(x0.v[0], x1.v[0], t), - vec_lerp(x0.v[1], x1.v[1], t), - vec_lerp(x0.v[2], x1.v[2], t)); -} - -static vec4_t vec4_lerp(vec4_t x0, vec4_t x1, vec_t t) { - return vec4( - vec_lerp(x0.v[0], x1.v[0], t), vec_lerp(x0.v[1], x1.v[1], t), - vec_lerp(x0.v[2], x1.v[2], t), vec_lerp(x0.v[3], x1.v[3], t)); -} - -static quat_t quat_slerp(quat_t q0, quat_t q1, vec_t t) { - assert(t >= 0.f); - assert(t <= 1.f); - - if (t <= 0.f) - return q0; - if (t >= 1.f) - return q1; - - quat_t q = q1; - - vec_t cos_theta = vec4_dot(q0, q1); - - if (cos_theta < 0.f) { - q = vec4_neg(q1); - cos_theta = -cos_theta; - } - - if (cos_theta > 1.f - KIT_EPSILON) - return vec4_lerp(q0, q1, t); - - vec_t angle = vec_acos(cos_theta); - - return vec4_div(vec4_add(vec4_mul(q0, vec_sin((1.f - t) * angle)), - vec4_mul(q, vec_sin(t * angle))), - vec_sin(angle)); -} - -static vec3_t rgb_to_xyz(vec3_t rgb) { - // FIXME - // Remove unnecessary x100 scaling. - // - - vec_t red = rgb.v[0]; - vec_t green = rgb.v[1]; - vec_t blue = rgb.v[2]; - - // Gamma correction - // - /* - if (red > 0.04045f) - red = vec_pow(((red + 0.055f) / 1.055f), 2.4f); - else - red = red / 12.92f; - - if (green > 0.04045f) - green = vec_pow(((green + 0.055f) / 1.055f), 2.4f); - else - green = green / 12.92f; - - if (blue > 0.04045f) - blue = vec_pow(((blue + 0.055f) / 1.055f), 2.4f); - else - blue = blue / 12.92f; - */ - - red = red * 100.f; - green = green * 100.f; - blue = blue * 100.f; - - return vec3(red * 0.4124f + green * 0.3576f + blue * 0.1805f, - red * 0.2126f + green * 0.7152f + blue * 0.0722f, - red * 0.0193f + green * 0.1192f + blue * 0.9505f); -} - -static vec3_t xyz_to_rgb(vec3_t xyz) { - // FIXME - // Remove unnecessary x100 scaling. - // - - vec_t x = xyz.v[0] / 100.f; - vec_t y = xyz.v[1] / 100.f; - vec_t z = xyz.v[2] / 100.f; - - vec_t red = x * 3.2406f + (y * -1.5372f) + z * (-0.4986f); - vec_t green = x * (-0.9689f) + y * 1.8758f + z * 0.0415f; - vec_t blue = x * 0.0557f + y * (-0.2040f) + z * 1.0570f; - - // Gamma correction - // - /* - if (red > 0.0031308f) - red = 1.055f * vec_pow(red, (1.0f / 2.4)) - 0.055f; - else - red = 12.92f * red; - - if (green > 0.0031308f) - green = 1.055f * vec_pow(green, (1.0f / 2.4)) - 0.055f; - else - green = 12.92f * green; - - if (blue > 0.0031308f) - blue = 1.055f * vec_pow(blue, (1.0f / 2.4)) - 0.055f; - else - blue = 12.92f * blue; - */ - - return vec3_clamp(vec3(red, green, blue), vec3(0.f, 0.f, 0.f), - vec3(1.f, 1.f, 1.f)); -} - -static vec3_t lab_to_xyz(vec3_t lab) { - // FIXME - // Remove unnecessary x100 scaling. - // - - vec_t lightness = lab.v[0]; - vec_t a = lab.v[1]; - vec_t b = lab.v[2]; - - vec_t y = (lightness + 16.f) / 116.f; - vec_t x = (a / 500.f) + y; - vec_t z = y - (b / 200.f); - - if (vec_pow(y, 3.f) > 0.008856) - y = vec_pow(y, 3.f); - else - y = (y - (16.f / 116.f)) / 7.787f; - - if (vec_pow(x, 3.f) > 0.008856f) - x = vec_pow(x, 3.f); - else - x = (x - (16.f / 116.f)) / 7.787f; - - if (vec_pow(z, 3.f) > 0.008856f) - z = vec_pow(z, 3.f); - else - z = (z - (16.f / 116.f)) / 7.787f; - - return vec3(KIT_COLOR_REF_X * x, KIT_COLOR_REF_Y * y, - KIT_COLOR_REF_Z * z); -} - -static vec3_t xyz_to_lab(vec3_t xyz) { - // FIXME - // Remove unnecessary x100 scaling. - // - - vec_t x = (xyz.v[0] / KIT_COLOR_REF_X); - vec_t y = (xyz.v[1] / KIT_COLOR_REF_Y); - vec_t z = (xyz.v[2] / KIT_COLOR_REF_Z); - - if (x > 0.008856f) - x = vec_pow(x, (1.f / 3.f)); - else - x = (7.787f * x) + (16.f / 116.f); - - if (y > 0.008856f) - y = vec_pow(y, (1.f / 3.f)); - else - y = (7.787f * y) + (16.f / 116.f); - - if (z > 0.008856f) - z = vec_pow(z, (1.f / 3.f)); - else - z = (7.787f * z) + (16.f / 116.f); - - vec_t lightness = (116.f * y) - 16.f; - vec_t a = 500.f * (x - y); - vec_t b = 200.f * (y - z); - - return vec3(lightness, a, b); -} - -static vec3_t lab_to_lch(vec3_t lab) { - vec_t lightness = lab.v[0]; - vec_t a = lab.v[1]; - vec_t b = lab.v[2]; - - vec_t chroma = sqrtf(a * a + b * b); - vec_t hue = a == 0.f ? 0.f : vec_atan(b / a); - - return vec3(lightness, chroma, hue); -} - -static vec3_t lch_to_lab(vec3_t lch) { - vec_t lightness = lch.v[0]; - vec_t chroma = lch.v[1]; - vec_t hue = lch.v[2]; - - vec_t a = chroma * cos(hue); - vec_t b = chroma * sin(hue); - - return vec3(lightness, a, b); -} - -static vec3_t rgb_to_lch(vec3_t rgb) { - vec3_t xyz = rgb_to_xyz(rgb); - vec3_t lab = xyz_to_lab(xyz); - - return lab_to_lch(lab); -} - -static vec3_t lch_to_rgb(vec3_t lch) { - vec3_t lab = lch_to_lab(lch); - vec3_t xyz = lab_to_xyz(lab); - - return xyz_to_rgb(xyz); -} - -static vec4_t rgba_from_lcha(vec_t lightness, vec_t chroma, vec_t hue, - vec_t alpha) { - vec3_t rgb = lch_to_rgb(vec3(lightness, chroma, hue)); - return vec4(rgb.v[0], rgb.v[1], rgb.v[2], alpha); -} - -#ifdef __GNUC__ -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/mersenne_twister_64.c b/source/kit/mersenne_twister_64.c deleted file mode 100644 index 4032dc9..0000000 --- a/source/kit/mersenne_twister_64.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "mersenne_twister_64.h" - -#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 diff --git a/source/kit/mersenne_twister_64.h b/source/kit/mersenne_twister_64.h deleted file mode 100644 index 2709dd7..0000000 --- a/source/kit/mersenne_twister_64.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef KIT_MERSENNE_TWISTER_64_H -#define KIT_MERSENNE_TWISTER_64_H - -#include "types.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 - -#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 diff --git a/source/kit/miniz/miniz.c b/source/kit/miniz/miniz.c deleted file mode 100644 index b96c176..0000000 --- a/source/kit/miniz/miniz.c +++ /dev/null @@ -1,692 +0,0 @@ -/************************************************************************** - * - * Copyright 2013-2014 RAD Game Tools and Valve Software - * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC - * All Rights Reserved. - * - * 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. - * - **************************************************************************/ - -#include "miniz.h" - -typedef unsigned char - mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1]; -typedef unsigned char - mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1]; -typedef unsigned char - mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; - -#ifdef __cplusplus -extern "C" { -#endif - -/* ------------------- zlib-style API's */ - -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, - size_t buf_len) { - mz_uint32 i, s1 = (mz_uint32) (adler & 0xffff), - s2 = (mz_uint32) (adler >> 16); - size_t block_len = buf_len % 5552; - if (!ptr) - return MZ_ADLER32_INIT; - while (buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { - s1 += ptr[0], s2 += s1; - s1 += ptr[1], s2 += s1; - s1 += ptr[2], s2 += s1; - s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; - s1 += ptr[5], s2 += s1; - s1 += ptr[6], s2 += s1; - s1 += ptr[7], s2 += s1; - } - for (; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; - buf_len -= block_len; - block_len = 5552; - } - return (s2 << 16) + s1; -} - -/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and - * crc32 C implementation that balances processor cache usage against - * speed": http://www.geocities.com/malbrain/ */ -#if 0 - mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) - { - static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; - mz_uint32 crcu32 = (mz_uint32)crc; - if (!ptr) - return MZ_CRC32_INIT; - crcu32 = ~crcu32; - while (buf_len--) - { - mz_uint8 b = *ptr++; - crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; - crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; - } - return ~crcu32; - } -#elif defined(USE_EXTERNAL_MZCRC) -/* If USE_EXTERNAL_CRC is defined, an external module will export the - * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version. - * Depending on the impl, it may be necessary to ~ the input/output - * crc values. - */ -mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len); -#else -/* Faster, but larger CPU cache footprint. - */ -mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) { - static const mz_uint32 s_crc_table[256] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, - 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, - 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, - 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, - 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, - 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, - 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, - 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, - 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, - 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, - 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, - 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, - 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, - 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, - 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, - 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, - 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, - 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, - 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, - 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, - 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, - 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, - 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, - 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, - 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, - 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, - 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, - 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, - 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, - 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, - 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, - 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, - 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, - 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, - 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, - 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, - 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, - 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, - 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, - 0x2D02EF8D - }; - - mz_uint32 crc32 = (mz_uint32) crc ^ 0xFFFFFFFF; - const mz_uint8 *pByte_buf = (const mz_uint8 *) ptr; - - while (buf_len >= 4) { - crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; - crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF]; - crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF]; - crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF]; - pByte_buf += 4; - buf_len -= 4; - } - - while (buf_len) { - crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF]; - ++pByte_buf; - --buf_len; - } - - return ~crc32; -} -#endif - -void mz_free(void *p) { - MZ_FREE(p); -} - -void *miniz_def_alloc_func(void *opaque, size_t items, size_t size) { - (void) opaque, (void) items, (void) size; - return MZ_MALLOC(items * size); -} -void miniz_def_free_func(void *opaque, void *address) { - (void) opaque, (void) address; - MZ_FREE(address); -} -void *miniz_def_realloc_func(void *opaque, void *address, - size_t items, size_t size) { - (void) opaque, (void) address, (void) items, (void) size; - return MZ_REALLOC(address, items * size); -} - -const char *mz_version(void) { - return MZ_VERSION; -} - -#ifndef MINIZ_NO_ZLIB_APIS - -# ifndef MINIZ_NO_DEFLATE_APIS - -int mz_deflateInit(mz_streamp pStream, int level) { - return mz_deflateInit2(pStream, level, MZ_DEFLATED, - MZ_DEFAULT_WINDOW_BITS, 9, - MZ_DEFAULT_STRATEGY); -} - -int mz_deflateInit2(mz_streamp pStream, int level, int method, - int window_bits, int mem_level, int strategy) { - tdefl_compressor *pComp; - mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | - tdefl_create_comp_flags_from_zip_params( - level, window_bits, strategy); - - if (!pStream) - return MZ_STREAM_ERROR; - if ((method != MZ_DEFLATED) || - ((mem_level < 1) || (mem_level > 9)) || - ((window_bits != MZ_DEFAULT_WINDOW_BITS) && - (-window_bits != MZ_DEFAULT_WINDOW_BITS))) - return MZ_PARAM_ERROR; - - pStream->data_type = 0; - pStream->adler = MZ_ADLER32_INIT; - pStream->msg = NULL; - pStream->reserved = 0; - pStream->total_in = 0; - pStream->total_out = 0; - if (!pStream->zalloc) - pStream->zalloc = miniz_def_alloc_func; - if (!pStream->zfree) - pStream->zfree = miniz_def_free_func; - - pComp = (tdefl_compressor *) pStream->zalloc( - pStream->opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - return MZ_MEM_ERROR; - - pStream->state = (struct mz_internal_state *) pComp; - - if (tdefl_init(pComp, NULL, NULL, comp_flags) != - TDEFL_STATUS_OKAY) { - mz_deflateEnd(pStream); - return MZ_PARAM_ERROR; - } - - return MZ_OK; -} - -int mz_deflateReset(mz_streamp pStream) { - if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || - (!pStream->zfree)) - return MZ_STREAM_ERROR; - pStream->total_in = pStream->total_out = 0; - tdefl_init((tdefl_compressor *) pStream->state, NULL, NULL, - ((tdefl_compressor *) pStream->state)->m_flags); - return MZ_OK; -} - -int mz_deflate(mz_streamp pStream, int flush) { - size_t in_bytes, out_bytes; - mz_ulong orig_total_in, orig_total_out; - int mz_status = MZ_OK; - - if ((!pStream) || (!pStream->state) || (flush < 0) || - (flush > MZ_FINISH) || (!pStream->next_out)) - return MZ_STREAM_ERROR; - if (!pStream->avail_out) - return MZ_BUF_ERROR; - - if (flush == MZ_PARTIAL_FLUSH) - flush = MZ_SYNC_FLUSH; - - if (((tdefl_compressor *) pStream->state)->m_prev_return_status == - TDEFL_STATUS_DONE) - return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; - - orig_total_in = pStream->total_in; - orig_total_out = pStream->total_out; - for (;;) { - tdefl_status defl_status; - in_bytes = pStream->avail_in; - out_bytes = pStream->avail_out; - - defl_status = tdefl_compress((tdefl_compressor *) pStream->state, - pStream->next_in, &in_bytes, - pStream->next_out, &out_bytes, - (tdefl_flush) flush); - pStream->next_in += (mz_uint) in_bytes; - pStream->avail_in -= (mz_uint) in_bytes; - pStream->total_in += (mz_uint) in_bytes; - pStream->adler = tdefl_get_adler32( - (tdefl_compressor *) pStream->state); - - pStream->next_out += (mz_uint) out_bytes; - pStream->avail_out -= (mz_uint) out_bytes; - pStream->total_out += (mz_uint) out_bytes; - - if (defl_status < 0) { - mz_status = MZ_STREAM_ERROR; - break; - } else if (defl_status == TDEFL_STATUS_DONE) { - mz_status = MZ_STREAM_END; - break; - } else if (!pStream->avail_out) - break; - else if ((!pStream->avail_in) && (flush != MZ_FINISH)) { - if ((flush) || (pStream->total_in != orig_total_in) || - (pStream->total_out != orig_total_out)) - break; - return MZ_BUF_ERROR; /* Can't make forward progress without some - * input. - */ - } - } - return mz_status; -} - -int mz_deflateEnd(mz_streamp pStream) { - if (!pStream) - return MZ_STREAM_ERROR; - if (pStream->state) { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} - -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) { - (void) pStream; - /* This is really over conservative. (And lame, but it's actually - * pretty tricky to compute a true upper bound given the way tdefl's - * blocking works.) */ - return MZ_MAX(128 + (source_len * 110) / 100, - 128 + source_len + - ((source_len / (31 * 1024)) + 1) * 5); -} - -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, mz_ulong source_len, - int level) { - int status; - mz_stream stream; - memset(&stream, 0, sizeof(stream)); - - /* In case mz_ulong is 64-bits (argh I hate longs). */ - if ((mz_uint64) (source_len | *pDest_len) > 0xFFFFFFFFU) - return MZ_PARAM_ERROR; - - stream.next_in = pSource; - stream.avail_in = (mz_uint32) source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32) *pDest_len; - - status = mz_deflateInit(&stream, level); - if (status != MZ_OK) - return status; - - status = mz_deflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) { - mz_deflateEnd(&stream); - return (status == MZ_OK) ? MZ_BUF_ERROR : status; - } - - *pDest_len = stream.total_out; - return mz_deflateEnd(&stream); -} - -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, mz_ulong source_len) { - return mz_compress2(pDest, pDest_len, pSource, source_len, - MZ_DEFAULT_COMPRESSION); -} - -mz_ulong mz_compressBound(mz_ulong source_len) { - return mz_deflateBound(NULL, source_len); -} - -# endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ - -# ifndef MINIZ_NO_INFLATE_APIS - -typedef struct { - tinfl_decompressor m_decomp; - mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; - int m_window_bits; - mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; - tinfl_status m_last_status; -} inflate_state; - -int mz_inflateInit2(mz_streamp pStream, int window_bits) { - inflate_state *pDecomp; - if (!pStream) - return MZ_STREAM_ERROR; - if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && - (-window_bits != MZ_DEFAULT_WINDOW_BITS)) - return MZ_PARAM_ERROR; - - pStream->data_type = 0; - pStream->adler = 0; - pStream->msg = NULL; - pStream->total_in = 0; - pStream->total_out = 0; - pStream->reserved = 0; - if (!pStream->zalloc) - pStream->zalloc = miniz_def_alloc_func; - if (!pStream->zfree) - pStream->zfree = miniz_def_free_func; - - pDecomp = (inflate_state *) pStream->zalloc(pStream->opaque, 1, - sizeof(inflate_state)); - if (!pDecomp) - return MZ_MEM_ERROR; - - pStream->state = (struct mz_internal_state *) pDecomp; - - tinfl_init(&pDecomp->m_decomp); - pDecomp->m_dict_ofs = 0; - pDecomp->m_dict_avail = 0; - pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; - pDecomp->m_first_call = 1; - pDecomp->m_has_flushed = 0; - pDecomp->m_window_bits = window_bits; - - return MZ_OK; -} - -int mz_inflateInit(mz_streamp pStream) { - return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); -} - -int mz_inflateReset(mz_streamp pStream) { - inflate_state *pDecomp; - if (!pStream) - return MZ_STREAM_ERROR; - - pStream->data_type = 0; - pStream->adler = 0; - pStream->msg = NULL; - pStream->total_in = 0; - pStream->total_out = 0; - pStream->reserved = 0; - - pDecomp = (inflate_state *) pStream->state; - - tinfl_init(&pDecomp->m_decomp); - pDecomp->m_dict_ofs = 0; - pDecomp->m_dict_avail = 0; - pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; - pDecomp->m_first_call = 1; - pDecomp->m_has_flushed = 0; - /* pDecomp->m_window_bits = window_bits */; - - return MZ_OK; -} - -int mz_inflate(mz_streamp pStream, int flush) { - inflate_state *pState; - mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; - size_t in_bytes, out_bytes, orig_avail_in; - tinfl_status status; - - if ((!pStream) || (!pStream->state)) - return MZ_STREAM_ERROR; - if (flush == MZ_PARTIAL_FLUSH) - flush = MZ_SYNC_FLUSH; - if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) - return MZ_STREAM_ERROR; - - pState = (inflate_state *) pStream->state; - if (pState->m_window_bits > 0) - decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; - orig_avail_in = pStream->avail_in; - - first_call = pState->m_first_call; - pState->m_first_call = 0; - if (pState->m_last_status < 0) - return MZ_DATA_ERROR; - - if (pState->m_has_flushed && (flush != MZ_FINISH)) - return MZ_STREAM_ERROR; - pState->m_has_flushed |= (flush == MZ_FINISH); - - if ((flush == MZ_FINISH) && (first_call)) { - /* MZ_FINISH on the first call implies that the input and output - * buffers are large enough to hold the entire - * compressed/decompressed file. */ - decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; - in_bytes = pStream->avail_in; - out_bytes = pStream->avail_out; - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, - &in_bytes, pStream->next_out, - pStream->next_out, &out_bytes, - decomp_flags); - pState->m_last_status = status; - pStream->next_in += (mz_uint) in_bytes; - pStream->avail_in -= (mz_uint) in_bytes; - pStream->total_in += (mz_uint) in_bytes; - pStream->adler = tinfl_get_adler32(&pState->m_decomp); - pStream->next_out += (mz_uint) out_bytes; - pStream->avail_out -= (mz_uint) out_bytes; - pStream->total_out += (mz_uint) out_bytes; - - if (status < 0) - return MZ_DATA_ERROR; - else if (status != TINFL_STATUS_DONE) { - pState->m_last_status = TINFL_STATUS_FAILED; - return MZ_BUF_ERROR; - } - return MZ_STREAM_END; - } - /* flush != MZ_FINISH then we must assume there's more input. */ - if (flush != MZ_FINISH) - decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; - - if (pState->m_dict_avail) { - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; - pStream->avail_out -= n; - pStream->total_out += n; - pState->m_dict_avail -= n; - pState->m_dict_ofs = (pState->m_dict_ofs + n) & - (TINFL_LZ_DICT_SIZE - 1); - return ((pState->m_last_status == TINFL_STATUS_DONE) && - (!pState->m_dict_avail)) - ? MZ_STREAM_END - : MZ_OK; - } - - for (;;) { - in_bytes = pStream->avail_in; - out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; - - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, - &in_bytes, pState->m_dict, - pState->m_dict + pState->m_dict_ofs, - &out_bytes, decomp_flags); - pState->m_last_status = status; - - pStream->next_in += (mz_uint) in_bytes; - pStream->avail_in -= (mz_uint) in_bytes; - pStream->total_in += (mz_uint) in_bytes; - pStream->adler = tinfl_get_adler32(&pState->m_decomp); - - pState->m_dict_avail = (mz_uint) out_bytes; - - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; - pStream->avail_out -= n; - pStream->total_out += n; - pState->m_dict_avail -= n; - pState->m_dict_ofs = (pState->m_dict_ofs + n) & - (TINFL_LZ_DICT_SIZE - 1); - - if (status < 0) - return MZ_DATA_ERROR; /* Stream is corrupted (there could be - some uncompressed data left in the - output dictionary - oh well). */ - else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && - (!orig_avail_in)) - return MZ_BUF_ERROR; /* Signal caller that we can't make forward - progress without supplying more input or - by setting flush to MZ_FINISH. */ - else if (flush == MZ_FINISH) { - /* The output buffer MUST be large to hold the remaining - * uncompressed data when flush==MZ_FINISH. */ - if (status == TINFL_STATUS_DONE) - return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; - /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means - * there's at least 1 more byte on the way. If there's no more - * room left in the output buffer then something is wrong. */ - else if (!pStream->avail_out) - return MZ_BUF_ERROR; - } else if ((status == TINFL_STATUS_DONE) || - (!pStream->avail_in) || (!pStream->avail_out) || - (pState->m_dict_avail)) - break; - } - - return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) - ? MZ_STREAM_END - : MZ_OK; -} - -int mz_inflateEnd(mz_streamp pStream) { - if (!pStream) - return MZ_STREAM_ERROR; - if (pStream->state) { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} -int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, - mz_ulong *pSource_len) { - mz_stream stream; - int status; - memset(&stream, 0, sizeof(stream)); - - /* In case mz_ulong is 64-bits (argh I hate longs). */ - if ((mz_uint64) (*pSource_len | *pDest_len) > 0xFFFFFFFFU) - return MZ_PARAM_ERROR; - - stream.next_in = pSource; - stream.avail_in = (mz_uint32) *pSource_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32) *pDest_len; - - status = mz_inflateInit(&stream); - if (status != MZ_OK) - return status; - - status = mz_inflate(&stream, MZ_FINISH); - *pSource_len = *pSource_len - stream.avail_in; - if (status != MZ_STREAM_END) { - mz_inflateEnd(&stream); - return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) - ? MZ_DATA_ERROR - : status; - } - *pDest_len = stream.total_out; - - return mz_inflateEnd(&stream); -} - -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, mz_ulong source_len) { - return mz_uncompress2(pDest, pDest_len, pSource, &source_len); -} - -# endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ - -const char *mz_error(int err) { - static struct { - int m_err; - const char *m_pDesc; - } s_error_descs[] = { { MZ_OK, "" }, - { MZ_STREAM_END, "stream end" }, - { MZ_NEED_DICT, "need dictionary" }, - { MZ_ERRNO, "file error" }, - { MZ_STREAM_ERROR, "stream error" }, - { MZ_DATA_ERROR, "data error" }, - { MZ_MEM_ERROR, "out of memory" }, - { MZ_BUF_ERROR, "buf error" }, - { MZ_VERSION_ERROR, "version error" }, - { MZ_PARAM_ERROR, "parameter error" } }; - mz_uint i; - for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); - ++i) - if (s_error_descs[i].m_err == err) - return s_error_descs[i].m_pDesc; - return NULL; -} - -#endif /*MINIZ_NO_ZLIB_APIS */ - -#ifdef __cplusplus -} -#endif - -/* - This is free and unencumbered software released into the public - domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this software, either in source code form or as a - compiled binary, for any purpose, commercial or non-commercial, and - by any means. - - In jurisdictions that recognize copyright laws, the author or - authors of this software dedicate any and all copyright interest in - the software to the public domain. We make this dedication for the - benefit of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to - this software under copyright law. - - 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 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. - - For more information, please refer to <http://unlicense.org/> -*/ diff --git a/source/kit/miniz/miniz.h b/source/kit/miniz/miniz.h deleted file mode 100644 index a80c389..0000000 --- a/source/kit/miniz/miniz.h +++ /dev/null @@ -1,658 +0,0 @@ -/* miniz.c 3.0.2 - public domain deflate/inflate, zlib-subset, ZIP - reading/writing/appending, PNG writing See "unlicense" statement at - the end of this file. Rich Geldreich <richgel99@gmail.com>, last - updated Oct. 13, 2013 Implements RFC 1950: - http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: - http://www.ietf.org/rfc/rfc1951.txt - - Most API's defined in miniz.c are optional. For example, to disable - the archive related functions just define MINIZ_NO_ARCHIVE_APIS, or - to get rid of all stdio usage define MINIZ_NO_STDIO (see the list - below for more macros). - - * Low-level Deflate/Inflate implementation notes: - - Compression: Use the "tdefl" API's. The compressor supports raw, - static, and dynamic blocks, lazy or greedy parsing, match length - filtering, RLE-only, and Huffman-only streams. It performs and - compresses approximately as well as zlib. - - Decompression: Use the "tinfl" API's. The entire decompressor is - implemented as a single function coroutine: see tinfl_decompress(). - It supports decompression into a 32KB (or larger power of 2) - wrapping buffer, or into a memory block large enough to hold the - entire file. - - The low-level tdefl/tinfl API's do not make any use of dynamic - memory allocation. - - * zlib-style API notes: - - miniz.c implements a fairly large subset of zlib. There's enough - functionality present for it to be a drop-in zlib replacement in - many apps: The z_stream struct, optional memory allocation - callbacks - deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound - inflateInit/inflateInit2/inflate/inflateReset/inflateEnd - compress, compress2, compressBound, uncompress - CRC-32, Adler-32 - Using modern, minimal code size, CPU cache - friendly routines. Supports raw deflate streams or standard zlib - streams with adler-32 checking. - - Limitations: - The callback API's are not implemented yet. No support for gzip - headers or zlib static dictionaries. I've tried to closely emulate - zlib's various flavors of stream flushing and return status codes, - but there are no guarantees that miniz.c pulls this off perfectly. - - * PNG writing: See the tdefl_write_image_to_png_file_in_memory() - function, originally written by Alex Evans. Supports 1-4 - bytes/pixel images. - - * ZIP archive API notes: - - The ZIP archive API's where designed with simplicity and - efficiency in mind, with just enough abstraction to get the job - done with minimal fuss. There are simple API's to retrieve file - information, read files from existing archives, create new - archives, append new files to existing archives, or clone archive - data from one archive to another. It supports archives located in - memory or the heap, on disk (using stdio.h), or you can specify - custom file read/write callbacks. - - - Archive reading: Just call this function to read a single file - from a disk archive: - - void *mz_zip_extract_archive_file_to_heap(const char - *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint - zip_flags); - - For more complex cases, use the "mz_zip_reader" functions. Upon - opening an archive, the entire central directory is located and - read as-is into memory, and subsequent file access only occurs when - reading individual files. - - - Archives file scanning: The simple way is to use this function - to scan a loaded archive for a specific file: - - int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char - *pName, const char *pComment, mz_uint flags); - - The locate operation can optionally check file comments too, - which (as one example) can be used to identify multiple versions of - the same file in an archive. This function uses a simple linear - search through the central directory, so it's not very fast. - - Alternately, you can iterate through all the files in an archive - (using mz_zip_reader_get_num_files()) and retrieve detailed info on - each file by calling mz_zip_reader_file_stat(). - - - Archive creation: Use the "mz_zip_writer" functions. The ZIP - writer immediately writes compressed file data to disk and builds - an exact image of the central directory in memory. The central - directory image is written all at once at the end of the archive - file when the archive is finalized. - - The archive writer can optionally align each file's local header - and file data to any power of 2 alignment, which can be useful when - the archive will be read from optical media. Also, the writer - supports placing arbitrary data blobs at the very beginning of ZIP - archives. Archives written using either feature are still readable - by any ZIP tool. - - - Archive appending: The simple way to add a single file to an - archive is to call this function: - - mz_bool mz_zip_add_mem_to_archive_file_in_place(const char - *pZip_filename, const char *pArchive_name, const void *pBuf, size_t - buf_size, const void *pComment, mz_uint16 comment_size, mz_uint - level_and_flags); - - The archive will be created if it doesn't already exist, - otherwise it'll be appended to. Note the appending is done in-place - and is not an atomic operation, so if something goes wrong during - the operation it's possible the archive could be left without a - central directory (although the local file headers and file data - will be fine, so the archive will be recoverable). - - For more complex archive modification scenarios: - 1. The safest way is to use a mz_zip_reader to read the existing - archive, cloning only those bits you want to preserve into a new - archive using using the mz_zip_writer_add_from_zip_reader() - function (which compiles the compressed file data as-is). When - you're done, delete the old archive and rename the newly written - archive, and you're done. This is safe but requires a bunch of - temporary disk space or heap memory. - - 2. Or, you can convert an mz_zip_reader in-place to an - mz_zip_writer using mz_zip_writer_init_from_reader(), append new - files as needed, then finalize the archive which will write an - updated central directory to the original archive. (This is - basically what mz_zip_add_mem_to_archive_file_in_place() does.) - There's a possibility that the archive's central directory could be - lost with this method if anything goes wrong, though. - - - ZIP archive support limitations: - No spanning support. Extraction functions can only handle - unencrypted, stored or deflated files. Requires streams capable of - seeking. - - * This is a header file library, like stb_image.c. To get only a - header file, either cut and paste the below header, or create - miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c - from it. - - * Important: For best perf. be sure to customize the below macros - for your target platform: #define - MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define MINIZ_LITTLE_ENDIAN - 1 #define MINIZ_HAS_64BIT_REGISTERS 1 - - * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE - 1" before including miniz.c to ensure miniz uses the 64-bit - variants: fopen64(), stat64(), etc. Otherwise you won't be able to - process large files (i.e. 32-bit stat() fails for me on files > - 0x7FFFFFFF bytes). -*/ - -#ifndef KIT_MINIZ_MINIZ_H -#define KIT_MINIZ_MINIZ_H - -/* Defines to completely disable specific portions of miniz.c: - If all macros here are defined the only functionality remaining - will be CRC-32 and adler-32. */ - -/* Define MINIZ_NO_STDIO to disable all usage and any functions which - * rely on stdio for file I/O. */ -/*#define MINIZ_NO_STDIO */ - -/* If MINIZ_NO_TIME is specified then the ZIP archive functions will - * not be able to get the current time, or */ -/* get/set file times, and the C run-time funcs that get/set times - * won't be called. */ -/* The current downside is the times written to your archives will be - * from 1979. */ -/*#define MINIZ_NO_TIME */ - -/* Define MINIZ_NO_DEFLATE_APIS to disable all compression API's. */ -/*#define MINIZ_NO_DEFLATE_APIS */ - -/* Define MINIZ_NO_INFLATE_APIS to disable all decompression API's. */ -/*#define MINIZ_NO_INFLATE_APIS */ - -/* Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. */ -/*#define MINIZ_NO_ARCHIVE_APIS */ - -/* Define MINIZ_NO_ARCHIVE_WRITING_APIS to disable all writing related - * ZIP archive API's. */ -/*#define MINIZ_NO_ARCHIVE_WRITING_APIS */ - -/* Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style - * compression/decompression API's. */ -/*#define MINIZ_NO_ZLIB_APIS */ - -/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to - * prevent conflicts against stock zlib. */ -/*#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ - -/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and - realloc. Note if MINIZ_NO_MALLOC is defined then the user must - always provide custom user alloc/free/realloc callbacks to the zlib - and archive API's, and a few stand-alone helper API's which don't - provide custom user - functions (such as tdefl_compress_mem_to_heap() and - tinfl_decompress_mem_to_heap()) won't work. */ -/*#define MINIZ_NO_MALLOC */ - -#ifdef MINIZ_NO_INFLATE_APIS -# define MINIZ_NO_ARCHIVE_APIS -#endif - -#ifdef MINIZ_NO_DEFLATE_APIS -# define MINIZ_NO_ARCHIVE_WRITING_APIS -#endif - -#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) -/* TODO: Work around "error: include file 'sys\utime.h' when compiling - * with tcc on Linux */ -# define MINIZ_NO_TIME -#endif - -#include "miniz_common.h" - -#include <stddef.h> - -#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) -# include <time.h> -#endif - -#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ - defined(__i386) || defined(__i486__) || defined(__i486) || \ - defined(i386) || defined(__ia64__) || defined(__x86_64__) -/* MINIZ_X86_OR_X64_CPU is only used to help set the below macros. */ -# define MINIZ_X86_OR_X64_CPU 1 -#else -# define MINIZ_X86_OR_X64_CPU 0 -#endif - -/* Set MINIZ_LITTLE_ENDIAN only if not set */ -#if !defined(MINIZ_LITTLE_ENDIAN) -# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) - -# if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */ -# define MINIZ_LITTLE_ENDIAN 1 -# else -# define MINIZ_LITTLE_ENDIAN 0 -# endif - -# else - -# if MINIZ_X86_OR_X64_CPU -# define MINIZ_LITTLE_ENDIAN 1 -# else -# define MINIZ_LITTLE_ENDIAN 0 -# endif - -# endif -#endif - -/* Using unaligned loads and stores causes errors when using UBSan */ -#if defined(__has_feature) -# if __has_feature(undefined_behavior_sanitizer) -# define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 -# endif -#endif - -/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */ -#if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES) -# if MINIZ_X86_OR_X64_CPU -/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit - * efficient integer loads and stores from unaligned addresses. */ -# define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 -# define MINIZ_UNALIGNED_USE_MEMCPY -# else -# define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 -# endif -#endif - -#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || \ - defined(_LP64) || defined(__LP64__) || defined(__ia64__) || \ - defined(__x86_64__) -/* Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers - * are reasonably fast (and don't involve compiler generated calls to - * helper functions). */ -# define MINIZ_HAS_64BIT_REGISTERS 1 -#else -# define MINIZ_HAS_64BIT_REGISTERS 0 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* ------------------- zlib-style API Definitions. */ - -/* For more compatibility with zlib, miniz.c uses unsigned long for - * some parameters/struct members. Beware: mz_ulong can be either 32 - * or 64-bits! */ -typedef unsigned long mz_ulong; - -/* mz_free() internally uses the MZ_FREE() macro (which by default - * calls free() unless you've modified the MZ_MALLOC macro) to release - * a block allocated from the heap. */ -void mz_free(void *p); - -#define MZ_ADLER32_INIT (1) -/* mz_adler32() returns the initial adler-32 value to use when called - * with ptr==NULL. */ -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, - size_t buf_len); - -#define MZ_CRC32_INIT (0) -/* mz_crc32() returns the initial CRC-32 value to use when called with - * ptr==NULL. */ -mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, - size_t buf_len); - -/* Compression strategies. */ -enum { - MZ_DEFAULT_STRATEGY = 0, - MZ_FILTERED = 1, - MZ_HUFFMAN_ONLY = 2, - MZ_RLE = 3, - MZ_FIXED = 4 -}; - -/* Method */ -#define MZ_DEFLATED 8 - -/* Compression levels: 0-9 are the standard zlib-style levels, 10 is - * best possible compression (not zlib compatible, and may be very - * slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. */ -enum { - MZ_NO_COMPRESSION = 0, - MZ_BEST_SPEED = 1, - MZ_BEST_COMPRESSION = 9, - MZ_UBER_COMPRESSION = 10, - MZ_DEFAULT_LEVEL = 6, - MZ_DEFAULT_COMPRESSION = -1 -}; - -#define MZ_VERSION "11.0.2" -#define MZ_VERNUM 0xB002 -#define MZ_VER_MAJOR 11 -#define MZ_VER_MINOR 2 -#define MZ_VER_REVISION 0 -#define MZ_VER_SUBREVISION 0 - -#ifndef MINIZ_NO_ZLIB_APIS - -/* Flush values. For typical usage you only need MZ_NO_FLUSH and - * MZ_FINISH. The other values are for advanced use (refer to the zlib - * docs). */ -enum { - MZ_NO_FLUSH = 0, - MZ_PARTIAL_FLUSH = 1, - MZ_SYNC_FLUSH = 2, - MZ_FULL_FLUSH = 3, - MZ_FINISH = 4, - MZ_BLOCK = 5 -}; - -/* Return status codes. MZ_PARAM_ERROR is non-standard. */ -enum { - MZ_OK = 0, - MZ_STREAM_END = 1, - MZ_NEED_DICT = 2, - MZ_ERRNO = -1, - MZ_STREAM_ERROR = -2, - MZ_DATA_ERROR = -3, - MZ_MEM_ERROR = -4, - MZ_BUF_ERROR = -5, - MZ_VERSION_ERROR = -6, - MZ_PARAM_ERROR = -10000 -}; - -/* Window bits */ -# define MZ_DEFAULT_WINDOW_BITS 15 - -struct mz_internal_state; - -/* Compression/decompression stream struct. */ -typedef struct mz_stream_s { - const unsigned char *next_in; /* pointer to next byte to read */ - unsigned int avail_in; /* number of bytes available at next_in */ - mz_ulong total_in; /* total number of bytes consumed so far */ - - unsigned char *next_out; /* pointer to next byte to write */ - unsigned int - avail_out; /* number of bytes that can be written to next_out */ - mz_ulong total_out; /* total number of bytes produced so far */ - - char *msg; /* error msg (unused) */ - struct mz_internal_state - *state; /* internal state, allocated by zalloc/zfree */ - - mz_alloc_func zalloc; /* optional heap allocation function (defaults - to malloc) */ - mz_free_func - zfree; /* optional heap free function (defaults to free) */ - void *opaque; /* heap alloc function user pointer */ - - int data_type; /* data_type (unused) */ - mz_ulong adler; /* adler32 of the source or uncompressed data */ - mz_ulong reserved; /* not used */ -} mz_stream; - -typedef mz_stream *mz_streamp; - -/* Returns the version string of miniz.c. */ -const char *mz_version(void); - -# ifndef MINIZ_NO_DEFLATE_APIS - -/* mz_deflateInit() initializes a compressor with default options: */ -/* Parameters: */ -/* pStream must point to an initialized mz_stream struct. */ -/* level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. */ -/* level 1 enables a specially optimized compression function that's - * been optimized purely for performance, not ratio. */ -/* (This special func. is currently only enabled when - * MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are - * defined.) */ -/* Return values: */ -/* MZ_OK on success. */ -/* MZ_STREAM_ERROR if the stream is bogus. */ -/* MZ_PARAM_ERROR if the input parameters are bogus. */ -/* MZ_MEM_ERROR on out of memory. */ -int mz_deflateInit(mz_streamp pStream, int level); - -/* mz_deflateInit2() is like mz_deflate(), except with more control: - */ -/* Additional parameters: */ -/* method must be MZ_DEFLATED */ -/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate - * stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS - * (raw deflate/no header or footer) */ -/* mem_level must be between [1, 9] (it's checked but ignored by - * miniz.c) */ -int mz_deflateInit2(mz_streamp pStream, int level, int method, - int window_bits, int mem_level, int strategy); - -/* Quickly resets a compressor without having to reallocate anything. - * Same as calling mz_deflateEnd() followed by - * mz_deflateInit()/mz_deflateInit2(). */ -int mz_deflateReset(mz_streamp pStream); - -/* mz_deflate() compresses the input to output, consuming as much of - * the input and producing as much output as possible. */ -/* Parameters: */ -/* pStream is the stream to read from and write to. You must - * initialize/update the next_in, avail_in, next_out, and avail_out - * members. */ -/* flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, - * MZ_FULL_FLUSH, or MZ_FINISH. */ -/* Return values: */ -/* MZ_OK on success (when flushing, or if more input is needed but - * not available, and/or there's more output to be written but the - * output buffer is full). */ -/* MZ_STREAM_END if all input has been consumed and all output bytes - * have been written. Don't call mz_deflate() on the stream anymore. - */ -/* MZ_STREAM_ERROR if the stream is bogus. */ -/* MZ_PARAM_ERROR if one of the parameters is invalid. */ -/* MZ_BUF_ERROR if no forward progress is possible because the input - * and/or output buffers are empty. (Fill up the input buffer or free - * up some output space and try again.) */ -int mz_deflate(mz_streamp pStream, int flush); - -/* mz_deflateEnd() deinitializes a compressor: */ -/* Return values: */ -/* MZ_OK on success. */ -/* MZ_STREAM_ERROR if the stream is bogus. */ -int mz_deflateEnd(mz_streamp pStream); - -/* mz_deflateBound() returns a (very) conservative upper bound on the - * amount of data that could be generated by deflate(), assuming flush - * is set to only MZ_NO_FLUSH or MZ_FINISH. */ -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); - -/* Single-call compression functions mz_compress() and mz_compress2(): - */ -/* Returns MZ_OK on success, or one of the error codes from - * mz_deflate() on failure. */ -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, mz_ulong source_len); -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, mz_ulong source_len, - int level); - -/* mz_compressBound() returns a (very) conservative upper bound on the - * amount of data that could be generated by calling mz_compress(). */ -mz_ulong mz_compressBound(mz_ulong source_len); - -# endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ - -# ifndef MINIZ_NO_INFLATE_APIS - -/* Initializes a decompressor. */ -int mz_inflateInit(mz_streamp pStream); - -/* mz_inflateInit2() is like mz_inflateInit() with an additional - * option that controls the window size and whether or not the stream - * has been wrapped with a zlib header/footer: */ -/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib - * header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). */ -int mz_inflateInit2(mz_streamp pStream, int window_bits); - -/* Quickly resets a compressor without having to reallocate anything. - * Same as calling mz_inflateEnd() followed by - * mz_inflateInit()/mz_inflateInit2(). */ -int mz_inflateReset(mz_streamp pStream); - -/* Decompresses the input stream to the output, consuming only as much - * of the input as needed, and writing as much to the output as - * possible. */ -/* Parameters: */ -/* pStream is the stream to read from and write to. You must - * initialize/update the next_in, avail_in, next_out, and avail_out - * members. */ -/* flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. */ -/* On the first call, if flush is MZ_FINISH it's assumed the input - * and output buffers are both sized large enough to decompress the - * entire stream in a single call (this is slightly faster). */ -/* MZ_FINISH implies that there are no more source bytes available - * beside what's already in the input buffer, and that the output - * buffer is large enough to hold the rest of the decompressed data. - */ -/* Return values: */ -/* MZ_OK on success. Either more input is needed but not available, - * and/or there's more output to be written but the output buffer is - * full. */ -/* MZ_STREAM_END if all needed input has been consumed and all - * output bytes have been written. For zlib streams, the adler-32 of - * the decompressed data has also been verified. */ -/* MZ_STREAM_ERROR if the stream is bogus. */ -/* MZ_DATA_ERROR if the deflate stream is invalid. */ -/* MZ_PARAM_ERROR if one of the parameters is invalid. */ -/* MZ_BUF_ERROR if no forward progress is possible because the input - * buffer is empty but the inflater needs more input to continue, or - * if the output buffer is not large enough. Call mz_inflate() again - */ -/* with more input data, or with more room in the output buffer - * (except when using single call decompression, described above). */ -int mz_inflate(mz_streamp pStream, int flush); - -/* Deinitializes a decompressor. */ -int mz_inflateEnd(mz_streamp pStream); - -/* Single-call decompression. */ -/* Returns MZ_OK on success, or one of the error codes from - * mz_inflate() on failure. */ -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, mz_ulong source_len); -int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, - const unsigned char *pSource, - mz_ulong *pSource_len); -# endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ - -/* Returns a string description of the specified error code, or NULL - * if the error code is invalid. */ -const char *mz_error(int err); - -/* Redefine zlib-compatible names to miniz equivalents, so miniz.c can - * be used as a drop-in replacement for the subset of zlib that - * miniz.c supports. */ -/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility - * if you use zlib in the same project. */ -# ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES -typedef unsigned char Byte; -typedef unsigned int uInt; -typedef mz_ulong uLong; -typedef Byte Bytef; -typedef uInt uIntf; -typedef char charf; -typedef int intf; -typedef void *voidpf; -typedef uLong uLongf; -typedef void *voidp; -typedef void *const voidpc; -# define Z_NULL 0 -# define Z_NO_FLUSH MZ_NO_FLUSH -# define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH -# define Z_SYNC_FLUSH MZ_SYNC_FLUSH -# define Z_FULL_FLUSH MZ_FULL_FLUSH -# define Z_FINISH MZ_FINISH -# define Z_BLOCK MZ_BLOCK -# define Z_OK MZ_OK -# define Z_STREAM_END MZ_STREAM_END -# define Z_NEED_DICT MZ_NEED_DICT -# define Z_ERRNO MZ_ERRNO -# define Z_STREAM_ERROR MZ_STREAM_ERROR -# define Z_DATA_ERROR MZ_DATA_ERROR -# define Z_MEM_ERROR MZ_MEM_ERROR -# define Z_BUF_ERROR MZ_BUF_ERROR -# define Z_VERSION_ERROR MZ_VERSION_ERROR -# define Z_PARAM_ERROR MZ_PARAM_ERROR -# define Z_NO_COMPRESSION MZ_NO_COMPRESSION -# define Z_BEST_SPEED MZ_BEST_SPEED -# define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION -# define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION -# define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY -# define Z_FILTERED MZ_FILTERED -# define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY -# define Z_RLE MZ_RLE -# define Z_FIXED MZ_FIXED -# define Z_DEFLATED MZ_DEFLATED -# define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS -# define alloc_func mz_alloc_func -# define free_func mz_free_func -# define internal_state mz_internal_state -# define z_stream mz_stream - -# ifndef MINIZ_NO_DEFLATE_APIS -# define deflateInit mz_deflateInit -# define deflateInit2 mz_deflateInit2 -# define deflateReset mz_deflateReset -# define deflate mz_deflate -# define deflateEnd mz_deflateEnd -# define deflateBound mz_deflateBound -# define compress mz_compress -# define compress2 mz_compress2 -# define compressBound mz_compressBound -# endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ - -# ifndef MINIZ_NO_INFLATE_APIS -# define inflateInit mz_inflateInit -# define inflateInit2 mz_inflateInit2 -# define inflateReset mz_inflateReset -# define inflate mz_inflate -# define inflateEnd mz_inflateEnd -# define uncompress mz_uncompress -# define uncompress2 mz_uncompress2 -# endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ - -# define crc32 mz_crc32 -# define adler32 mz_adler32 -# define MAX_WBITS 15 -# define MAX_MEM_LEVEL 9 -# define zError mz_error -# define ZLIB_VERSION MZ_VERSION -# define ZLIB_VERNUM MZ_VERNUM -# define ZLIB_VER_MAJOR MZ_VER_MAJOR -# define ZLIB_VER_MINOR MZ_VER_MINOR -# define ZLIB_VER_REVISION MZ_VER_REVISION -# define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION -# define zlibVersion mz_version -# define zlib_version mz_version() -# endif /* #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ - -#endif /* MINIZ_NO_ZLIB_APIS */ - -#ifdef __cplusplus -} -#endif - -#include "miniz_zip.h" - -#endif diff --git a/source/kit/miniz/miniz_common.h b/source/kit/miniz/miniz_common.h deleted file mode 100644 index 26306f3..0000000 --- a/source/kit/miniz/miniz_common.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef KIT_MINIZ_MINIZ_COMMON_H -#define KIT_MINIZ_MINIZ_COMMON_H - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include <assert.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -/* ------------------- Types and macros */ -typedef unsigned char mz_uint8; -typedef signed short mz_int16; -typedef unsigned short mz_uint16; -typedef unsigned int mz_uint32; -typedef unsigned int mz_uint; -typedef int64_t mz_int64; -typedef uint64_t mz_uint64; -typedef int mz_bool; - -#define MZ_FALSE (0) -#define MZ_TRUE (1) - -/* Works around MSVC's spammy "warning C4127: conditional expression - * is constant" message. */ -#ifdef _MSC_VER -# define MZ_MACRO_END while (0, 0) -#else -# define MZ_MACRO_END while (0) -#endif - -#ifdef MINIZ_NO_STDIO -# define MZ_FILE void * -#else -# include <stdio.h> -# define MZ_FILE FILE -#endif /* #ifdef MINIZ_NO_STDIO */ - -#ifdef MINIZ_NO_TIME -typedef struct mz_dummy_time_t_tag { - mz_uint32 m_dummy1; - mz_uint32 m_dummy2; -} mz_dummy_time_t; -# define MZ_TIME_T mz_dummy_time_t -#else -# define MZ_TIME_T time_t -#endif - -#define MZ_ASSERT(x) assert(x) - -#ifdef MINIZ_NO_MALLOC -# define MZ_MALLOC(x) NULL -# define MZ_FREE(x) (void) x, ((void) 0) -# define MZ_REALLOC(p, x) NULL -#else -# define MZ_MALLOC(x) malloc(x) -# define MZ_FREE(x) free(x) -# define MZ_REALLOC(p, x) realloc(p, x) -#endif - -#define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) -#define MZ_CLEAR_ARR(obj) memset((obj), 0, sizeof(obj)) -#define MZ_CLEAR_PTR(obj) memset((obj), 0, sizeof(*obj)) - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -# define MZ_READ_LE16(p) *((const mz_uint16 *) (p)) -# define MZ_READ_LE32(p) *((const mz_uint32 *) (p)) -#else -# define MZ_READ_LE16(p) \ - ((mz_uint32) (((const mz_uint8 *) (p))[0]) | \ - ((mz_uint32) (((const mz_uint8 *) (p))[1]) << 8U)) -# define MZ_READ_LE32(p) \ - ((mz_uint32) (((const mz_uint8 *) (p))[0]) | \ - ((mz_uint32) (((const mz_uint8 *) (p))[1]) << 8U) | \ - ((mz_uint32) (((const mz_uint8 *) (p))[2]) << 16U) | \ - ((mz_uint32) (((const mz_uint8 *) (p))[3]) << 24U)) -#endif - -#define MZ_READ_LE64(p) \ - (((mz_uint64) MZ_READ_LE32(p)) | \ - (((mz_uint64) MZ_READ_LE32((const mz_uint8 *) (p) + \ - sizeof(mz_uint32))) \ - << 32U)) - -#ifdef _MSC_VER -# define MZ_FORCEINLINE __forceinline -#elif defined(__GNUC__) -# define MZ_FORCEINLINE __inline__ __attribute__((__always_inline__)) -#else -# define MZ_FORCEINLINE inline -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Heap allocation callbacks. -Note that mz_alloc_func parameter types purposely differ from zlib's: -items/size is size_t, not unsigned long. */ -typedef void *(*mz_alloc_func)(void *opaque, size_t items, - size_t size); -typedef void (*mz_free_func)(void *opaque, void *address); -typedef void *(*mz_realloc_func)(void *opaque, void *address, - size_t items, size_t size); - -void *miniz_def_alloc_func(void *opaque, size_t items, size_t size); -void miniz_def_free_func(void *opaque, void *address); -void *miniz_def_realloc_func(void *opaque, void *address, - size_t items, size_t size); - -#define MZ_UINT16_MAX (0xFFFFU) -#define MZ_UINT32_MAX (0xFFFFFFFFU) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/miniz/miniz_tdef.c b/source/kit/miniz/miniz_tdef.c deleted file mode 100644 index 5220466..0000000 --- a/source/kit/miniz/miniz_tdef.c +++ /dev/null @@ -1,1792 +0,0 @@ -/************************************************************************** - * - * Copyright 2013-2014 RAD Game Tools and Valve Software - * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC - * All Rights Reserved. - * - * 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. - * - **************************************************************************/ - -#include "miniz.h" - -#ifndef MINIZ_NO_DEFLATE_APIS - -# ifdef __cplusplus -extern "C" { -# endif - -/* ------------------- Low-level Compression (independent from all - * decompression API's) */ - -/* Purposely making these tables static for faster init and thread - * safety. */ -static const mz_uint16 s_tdefl_len_sym[256] = { - 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, - 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, - 271, 271, 272, 272, 272, 272, 273, 273, 273, 273, 273, 273, 273, - 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, - 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, - 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 285 -}; - -static const mz_uint8 s_tdefl_len_extra[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0 -}; - -static const mz_uint8 s_tdefl_small_dist_sym[512] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17 -}; - -static const mz_uint8 s_tdefl_small_dist_extra[512] = { - 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7 -}; - -static const mz_uint8 s_tdefl_large_dist_sym[128] = { - 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -static const mz_uint8 s_tdefl_large_dist_extra[128] = { - 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 -}; - -/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr - * to sorted values. */ -typedef struct { - mz_uint16 m_key, m_sym_index; -} tdefl_sym_freq; -static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, - tdefl_sym_freq *pSyms0, - tdefl_sym_freq *pSyms1) { - mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; - tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1; - MZ_CLEAR_ARR(hist); - for (i = 0; i < num_syms; i++) { - mz_uint freq = pSyms0[i].m_key; - hist[freq & 0xFF]++; - hist[256 + ((freq >> 8) & 0xFF)]++; - } - while ((total_passes > 1) && - (num_syms == hist[(total_passes - 1) * 256])) - total_passes--; - for (pass_shift = 0, pass = 0; pass < total_passes; - pass++, pass_shift += 8) { - const mz_uint32 *pHist = &hist[pass << 8]; - mz_uint offsets[256], cur_ofs = 0; - for (i = 0; i < 256; i++) { - offsets[i] = cur_ofs; - cur_ofs += pHist[i]; - } - for (i = 0; i < num_syms; i++) - pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & - 0xFF]++] = pCur_syms[i]; - { - tdefl_sym_freq *t = pCur_syms; - pCur_syms = pNew_syms; - pNew_syms = t; - } - } - return pCur_syms; -} - -/* tdefl_calculate_minimum_redundancy() originally written by: - * Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, - * jyrki@diku.dk, November 1996. */ -static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, - int n) { - int root, leaf, next, avbl, used, dpth; - if (n == 0) - return; - else if (n == 1) { - A[0].m_key = 1; - return; - } - A[0].m_key += A[1].m_key; - root = 0; - leaf = 2; - for (next = 1; next < n - 1; next++) { - if (leaf >= n || A[root].m_key < A[leaf].m_key) { - A[next].m_key = A[root].m_key; - A[root++].m_key = (mz_uint16) next; - } else - A[next].m_key = A[leaf++].m_key; - if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) { - A[next].m_key = (mz_uint16) (A[next].m_key + A[root].m_key); - A[root++].m_key = (mz_uint16) next; - } else - A[next].m_key = (mz_uint16) (A[next].m_key + A[leaf++].m_key); - } - A[n - 2].m_key = 0; - for (next = n - 3; next >= 0; next--) - A[next].m_key = A[A[next].m_key].m_key + 1; - avbl = 1; - used = dpth = 0; - root = n - 2; - next = n - 1; - while (avbl > 0) { - while (root >= 0 && (int) A[root].m_key == dpth) { - used++; - root--; - } - while (avbl > used) { - A[next--].m_key = (mz_uint16) (dpth); - avbl--; - } - avbl = 2 * used; - dpth++; - used = 0; - } -} - -/* Limits canonical Huffman code table's max code size. */ -enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; -static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, - int code_list_len, - int max_code_size) { - int i; - mz_uint32 total = 0; - if (code_list_len <= 1) - return; - for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; - i++) - pNum_codes[max_code_size] += pNum_codes[i]; - for (i = max_code_size; i > 0; i--) - total += (((mz_uint32) pNum_codes[i]) << (max_code_size - i)); - while (total != (1UL << max_code_size)) { - pNum_codes[max_code_size]--; - for (i = max_code_size - 1; i > 0; i--) - if (pNum_codes[i]) { - pNum_codes[i]--; - pNum_codes[i + 1] += 2; - break; - } - total--; - } -} - -static void tdefl_optimize_huffman_table(tdefl_compressor *d, - int table_num, int table_len, - int code_size_limit, - int static_table) { - int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; - mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; - MZ_CLEAR_ARR(num_codes); - if (static_table) { - for (i = 0; i < table_len; i++) - num_codes[d->m_huff_code_sizes[table_num][i]]++; - } else { - tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], - syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; - int num_used_syms = 0; - const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; - for (i = 0; i < table_len; i++) - if (pSym_count[i]) { - syms0[num_used_syms].m_key = (mz_uint16) pSym_count[i]; - syms0[num_used_syms++].m_sym_index = (mz_uint16) i; - } - - pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); - tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); - - for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; - - tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, - code_size_limit); - - MZ_CLEAR_ARR(d->m_huff_code_sizes[table_num]); - MZ_CLEAR_ARR(d->m_huff_codes[table_num]); - for (i = 1, j = num_used_syms; i <= code_size_limit; i++) - for (l = num_codes[i]; l > 0; l--) - d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = - (mz_uint8) (i); - } - - next_code[1] = 0; - for (j = 0, i = 2; i <= code_size_limit; i++) - next_code[i] = j = ((j + num_codes[i - 1]) << 1); - - for (i = 0; i < table_len; i++) { - mz_uint rev_code = 0, code, code_size; - if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) - continue; - code = next_code[code_size]++; - for (l = code_size; l > 0; l--, code >>= 1) - rev_code = (rev_code << 1) | (code & 1); - d->m_huff_codes[table_num][i] = (mz_uint16) rev_code; - } -} - -# define TDEFL_PUT_BITS(b, l) \ - do { \ - mz_uint bits = b; \ - mz_uint len = l; \ - MZ_ASSERT(bits <= ((1U << len) - 1U)); \ - d->m_bit_buffer |= (bits << d->m_bits_in); \ - d->m_bits_in += len; \ - while (d->m_bits_in >= 8) { \ - if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ - *d->m_pOutput_buf++ = (mz_uint8) (d->m_bit_buffer); \ - d->m_bit_buffer >>= 8; \ - d->m_bits_in -= 8; \ - } \ - } \ - MZ_MACRO_END - -# define TDEFL_RLE_PREV_CODE_SIZE() \ - { \ - if (rle_repeat_count) { \ - if (rle_repeat_count < 3) { \ - d->m_huff_count[2][prev_code_size] = \ - (mz_uint16) (d->m_huff_count[2][prev_code_size] + \ - rle_repeat_count); \ - while (rle_repeat_count--) \ - packed_code_sizes[num_packed_code_sizes++] = \ - prev_code_size; \ - } else { \ - d->m_huff_count[2][16] = \ - (mz_uint16) (d->m_huff_count[2][16] + 1); \ - packed_code_sizes[num_packed_code_sizes++] = 16; \ - packed_code_sizes[num_packed_code_sizes++] = \ - (mz_uint8) (rle_repeat_count - 3); \ - } \ - rle_repeat_count = 0; \ - } \ - } - -# define TDEFL_RLE_ZERO_CODE_SIZE() \ - { \ - if (rle_z_count) { \ - if (rle_z_count < 3) { \ - d->m_huff_count[2][0] = \ - (mz_uint16) (d->m_huff_count[2][0] + rle_z_count); \ - while (rle_z_count--) \ - packed_code_sizes[num_packed_code_sizes++] = 0; \ - } else if (rle_z_count <= 10) { \ - d->m_huff_count[2][17] = \ - (mz_uint16) (d->m_huff_count[2][17] + 1); \ - packed_code_sizes[num_packed_code_sizes++] = 17; \ - packed_code_sizes[num_packed_code_sizes++] = \ - (mz_uint8) (rle_z_count - 3); \ - } else { \ - d->m_huff_count[2][18] = \ - (mz_uint16) (d->m_huff_count[2][18] + 1); \ - packed_code_sizes[num_packed_code_sizes++] = 18; \ - packed_code_sizes[num_packed_code_sizes++] = \ - (mz_uint8) (rle_z_count - 11); \ - } \ - rle_z_count = 0; \ - } \ - } - -static const mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 -}; - -static void tdefl_start_dynamic_block(tdefl_compressor *d) { - int num_lit_codes, num_dist_codes, num_bit_lengths; - mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, - rle_z_count, rle_repeat_count, packed_code_sizes_index; - mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + - TDEFL_MAX_HUFF_SYMBOLS_1], - packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + - TDEFL_MAX_HUFF_SYMBOLS_1], - prev_code_size = 0xFF; - - d->m_huff_count[0][256] = 1; - - tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, - MZ_FALSE); - tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, - MZ_FALSE); - - for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) - if (d->m_huff_code_sizes[0][num_lit_codes - 1]) - break; - for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) - if (d->m_huff_code_sizes[1][num_dist_codes - 1]) - break; - - memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], - num_lit_codes); - memcpy(code_sizes_to_pack + num_lit_codes, - &d->m_huff_code_sizes[1][0], num_dist_codes); - total_code_sizes_to_pack = num_lit_codes + num_dist_codes; - num_packed_code_sizes = 0; - rle_z_count = 0; - rle_repeat_count = 0; - - memset(&d->m_huff_count[2][0], 0, - sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); - for (i = 0; i < total_code_sizes_to_pack; i++) { - mz_uint8 code_size = code_sizes_to_pack[i]; - if (!code_size) { - TDEFL_RLE_PREV_CODE_SIZE(); - if (++rle_z_count == 138) { - TDEFL_RLE_ZERO_CODE_SIZE(); - } - } else { - TDEFL_RLE_ZERO_CODE_SIZE(); - if (code_size != prev_code_size) { - TDEFL_RLE_PREV_CODE_SIZE(); - d->m_huff_count[2][code_size] = - (mz_uint16) (d->m_huff_count[2][code_size] + 1); - packed_code_sizes[num_packed_code_sizes++] = code_size; - } else if (++rle_repeat_count == 6) { - TDEFL_RLE_PREV_CODE_SIZE(); - } - } - prev_code_size = code_size; - } - if (rle_repeat_count) { - TDEFL_RLE_PREV_CODE_SIZE(); - } else { - TDEFL_RLE_ZERO_CODE_SIZE(); - } - - tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, - MZ_FALSE); - - TDEFL_PUT_BITS(2, 2); - - TDEFL_PUT_BITS(num_lit_codes - 257, 5); - TDEFL_PUT_BITS(num_dist_codes - 1, 5); - - for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) - if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle - [num_bit_lengths]]) - break; - num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); - TDEFL_PUT_BITS(num_bit_lengths - 4, 4); - for (i = 0; (int) i < num_bit_lengths; i++) - TDEFL_PUT_BITS(d->m_huff_code_sizes - [2][s_tdefl_packed_code_size_syms_swizzle[i]], - 3); - - for (packed_code_sizes_index = 0; - packed_code_sizes_index < num_packed_code_sizes;) { - mz_uint code = packed_code_sizes[packed_code_sizes_index++]; - MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); - TDEFL_PUT_BITS(d->m_huff_codes[2][code], - d->m_huff_code_sizes[2][code]); - if (code >= 16) - TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], - "\02\03\07"[code - 16]); - } -} - -static void tdefl_start_static_block(tdefl_compressor *d) { - mz_uint i; - mz_uint8 *p = &d->m_huff_code_sizes[0][0]; - - for (i = 0; i <= 143; ++i) *p++ = 8; - for (; i <= 255; ++i) *p++ = 9; - for (; i <= 279; ++i) *p++ = 7; - for (; i <= 287; ++i) *p++ = 8; - - memset(d->m_huff_code_sizes[1], 5, 32); - - tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); - tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); - - TDEFL_PUT_BITS(1, 2); -} - -static const mz_uint mz_bitmasks[17] = { - 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, - 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, - 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF -}; - -# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && \ - MINIZ_HAS_64BIT_REGISTERS -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) { - mz_uint flags; - mz_uint8 *pLZ_codes; - mz_uint8 *pOutput_buf = d->m_pOutput_buf; - mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; - mz_uint64 bit_buffer = d->m_bit_buffer; - mz_uint bits_in = d->m_bits_in; - -# define TDEFL_PUT_BITS_FAST(b, l) \ - { \ - bit_buffer |= (((mz_uint64) (b)) << bits_in); \ - bits_in += (l); \ - } - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; - flags >>= 1) { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - - if (flags & 1) { - mz_uint s0, s1, n0, n1, sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0]; - mz_uint match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); - pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST( - d->m_huff_codes[0][s_tdefl_len_sym[match_len]], - d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST( - match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], - s_tdefl_len_extra[match_len]); - - /* This sequence coaxes MSVC into using cmov's vs. jmp's. */ - s0 = s_tdefl_small_dist_sym[match_dist & 511]; - n0 = s_tdefl_small_dist_extra[match_dist & 511]; - s1 = s_tdefl_large_dist_sym[match_dist >> 8]; - n1 = s_tdefl_large_dist_extra[match_dist >> 8]; - sym = (match_dist < 512) ? s0 : s1; - num_extra_bits = (match_dist < 512) ? n0 : n1; - - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], - d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], - num_extra_bits); - } else { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], - d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], - d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], - d->m_huff_code_sizes[0][lit]); - } - } - } - - if (pOutput_buf >= d->m_pOutput_buf_end) - return MZ_FALSE; - - memcpy(pOutput_buf, &bit_buffer, sizeof(mz_uint64)); - pOutput_buf += (bits_in >> 3); - bit_buffer >>= (bits_in & ~7); - bits_in &= 7; - } - -# undef TDEFL_PUT_BITS_FAST - - d->m_pOutput_buf = pOutput_buf; - d->m_bits_in = 0; - d->m_bit_buffer = 0; - - while (bits_in) { - mz_uint32 n = MZ_MIN(bits_in, 16); - TDEFL_PUT_BITS((mz_uint) bit_buffer & mz_bitmasks[n], n); - bit_buffer >>= n; - bits_in -= n; - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], - d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -# else -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) { - mz_uint flags; - mz_uint8 *pLZ_codes; - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; - flags >>= 1) { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - if (flags & 1) { - mz_uint sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], - match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); - pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS( - d->m_huff_codes[0][s_tdefl_len_sym[match_len]], - d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(match_len & - mz_bitmasks[s_tdefl_len_extra[match_len]], - s_tdefl_len_extra[match_len]); - - if (match_dist < 512) { - sym = s_tdefl_small_dist_sym[match_dist]; - num_extra_bits = s_tdefl_small_dist_extra[match_dist]; - } else { - sym = s_tdefl_large_dist_sym[match_dist >> 8]; - num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; - } - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(d->m_huff_codes[1][sym], - d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], - num_extra_bits); - } else { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS(d->m_huff_codes[0][lit], - d->m_huff_code_sizes[0][lit]); - } - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], - d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -# endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && \ - MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */ - -static mz_bool tdefl_compress_block(tdefl_compressor *d, - mz_bool static_block) { - if (static_block) - tdefl_start_static_block(d); - else - tdefl_start_dynamic_block(d); - return tdefl_compress_lz_codes(d); -} - -static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, - 16, 32, 128, 256, - 512, 768, 1500 }; - -static int tdefl_flush_block(tdefl_compressor *d, int flush) { - mz_uint saved_bit_buf, saved_bits_in; - mz_uint8 *pSaved_output_buf; - mz_bool comp_block_succeeded = MZ_FALSE; - int n, - use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != - 0) && - (d->m_lookahead_pos - - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; - mz_uint8 *pOutput_buf_start = - ((d->m_pPut_buf_func == NULL) && - ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= - TDEFL_OUT_BUF_SIZE)) - ? ((mz_uint8 *) d->m_pOut_buf + d->m_out_buf_ofs) - : d->m_output_buf; - - d->m_pOutput_buf = pOutput_buf_start; - d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; - - MZ_ASSERT(!d->m_output_flush_remaining); - d->m_output_flush_ofs = 0; - d->m_output_flush_remaining = 0; - - *d->m_pLZ_flags = (mz_uint8) (*d->m_pLZ_flags >> - d->m_num_flags_left); - d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - - if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) { - const mz_uint8 cmf = 0x78; - mz_uint8 flg, flevel = 3; - mz_uint header, i, - mz_un = sizeof(s_tdefl_num_probes) / sizeof(mz_uint); - - /* Determine compression level by reversing the process in - * tdefl_create_comp_flags_from_zip_params() */ - for (i = 0; i < mz_un; i++) - if (s_tdefl_num_probes[i] == (d->m_flags & 0xFFF)) - break; - - if (i < 2) - flevel = 0; - else if (i < 6) - flevel = 1; - else if (i == 6) - flevel = 2; - - header = cmf << 8 | (flevel << 6); - header += 31 - (header % 31); - flg = header & 0xFF; - - TDEFL_PUT_BITS(cmf, 8); - TDEFL_PUT_BITS(flg, 8); - } - - TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); - - pSaved_output_buf = d->m_pOutput_buf; - saved_bit_buf = d->m_bit_buffer; - saved_bits_in = d->m_bits_in; - - if (!use_raw_block) - comp_block_succeeded = tdefl_compress_block( - d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || - (d->m_total_lz_bytes < 48)); - - /* If the block gets expanded, forget the current contents of the - * output buffer and send a raw block instead. */ - if (((use_raw_block) || ((d->m_total_lz_bytes) && - ((d->m_pOutput_buf - pSaved_output_buf + - 1U) >= d->m_total_lz_bytes))) && - ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= - d->m_dict_size)) { - mz_uint i; - d->m_pOutput_buf = pSaved_output_buf; - d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - TDEFL_PUT_BITS(0, 2); - if (d->m_bits_in) { - TDEFL_PUT_BITS(0, 8 - d->m_bits_in); - } - for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) { - TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); - } - for (i = 0; i < d->m_total_lz_bytes; ++i) { - TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & - TDEFL_LZ_DICT_SIZE_MASK], - 8); - } - } - /* Check for the extremely unlikely (if not impossible) case of the - compressed block not fitting into the output buffer when using - dynamic codes. */ - else if (!comp_block_succeeded) { - d->m_pOutput_buf = pSaved_output_buf; - d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - tdefl_compress_block(d, MZ_TRUE); - } - - if (flush) { - if (flush == TDEFL_FINISH) { - if (d->m_bits_in) { - TDEFL_PUT_BITS(0, 8 - d->m_bits_in); - } - if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { - mz_uint i, a = d->m_adler32; - for (i = 0; i < 4; i++) { - TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); - a <<= 8; - } - } - } else { - mz_uint i, z = 0; - TDEFL_PUT_BITS(0, 3); - if (d->m_bits_in) { - TDEFL_PUT_BITS(0, 8 - d->m_bits_in); - } - for (i = 2; i; --i, z ^= 0xFFFF) { - TDEFL_PUT_BITS(z & 0xFFFF, 16); - } - } - } - - MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); - - memset(&d->m_huff_count[0][0], 0, - sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, - sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; - d->m_pLZ_flags = d->m_lz_code_buf; - d->m_num_flags_left = 8; - d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; - d->m_total_lz_bytes = 0; - d->m_block_index++; - - if ((n = (int) (d->m_pOutput_buf - pOutput_buf_start)) != 0) { - if (d->m_pPut_buf_func) { - *d->m_pIn_buf_size = d->m_pSrc - - (const mz_uint8 *) d->m_pIn_buf; - if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, - d->m_pPut_buf_user)) - return ( - d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); - } else if (pOutput_buf_start == d->m_output_buf) { - int bytes_to_copy = (int) MZ_MIN( - (size_t) n, - (size_t) (*d->m_pOut_buf_size - d->m_out_buf_ofs)); - memcpy((mz_uint8 *) d->m_pOut_buf + d->m_out_buf_ofs, - d->m_output_buf, bytes_to_copy); - d->m_out_buf_ofs += bytes_to_copy; - if ((n -= bytes_to_copy) != 0) { - d->m_output_flush_ofs = bytes_to_copy; - d->m_output_flush_remaining = n; - } - } else { - d->m_out_buf_ofs += n; - } - } - - return d->m_output_flush_remaining; -} - -# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES -# ifdef MINIZ_UNALIGNED_USE_MEMCPY -static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8 *p) { - mz_uint16 ret; - memcpy(&ret, p, sizeof(mz_uint16)); - return ret; -} -static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16 *p) { - mz_uint16 ret; - memcpy(&ret, p, sizeof(mz_uint16)); - return ret; -} -# else -# define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *) (p) -# define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *) (p) -# endif -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, - mz_uint lookahead_pos, - mz_uint max_dist, - mz_uint max_match_len, - mz_uint *pMatch_dist, - mz_uint *pMatch_len) { - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, - match_len = *pMatch_len, probe_pos = pos, - next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint16 *s = (const mz_uint16 *) (d->m_dict + pos), *p, *q; - mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD( - &d->m_dict[pos + match_len - 1]), - s01 = TDEFL_READ_UNALIGNED_WORD2(s); - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); - if (max_match_len <= match_len) - return; - for (;;) { - for (;;) { - if (--num_probes_left == 0) - return; -# define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || \ - ((dist = (mz_uint16) (lookahead_pos - next_probe_pos)) > \ - max_dist)) \ - return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if (TDEFL_READ_UNALIGNED_WORD( \ - &d->m_dict[probe_pos + match_len - 1]) == c01) \ - break; - TDEFL_PROBE; - TDEFL_PROBE; - TDEFL_PROBE; - } - if (!dist) - break; - q = (const mz_uint16 *) (d->m_dict + probe_pos); - if (TDEFL_READ_UNALIGNED_WORD2(q) != s01) - continue; - p = s; - probe_len = 32; - do { - } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (--probe_len > 0)); - if (!probe_len) { - *pMatch_dist = dist; - *pMatch_len = MZ_MIN(max_match_len, - (mz_uint) TDEFL_MAX_MATCH_LEN); - break; - } else if ((probe_len = ((mz_uint) (p - s) * 2) + - (mz_uint) (*(const mz_uint8 *) p == - *(const mz_uint8 *) q)) > - match_len) { - *pMatch_dist = dist; - if ((*pMatch_len = match_len = MZ_MIN( - max_match_len, probe_len)) == max_match_len) - break; - c01 = TDEFL_READ_UNALIGNED_WORD( - &d->m_dict[pos + match_len - 1]); - } - } -} -# else -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, - mz_uint lookahead_pos, - mz_uint max_dist, - mz_uint max_match_len, - mz_uint *pMatch_dist, - mz_uint *pMatch_len) { - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, - match_len = *pMatch_len, probe_pos = pos, - next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint8 *s = d->m_dict + pos, *p, *q; - mz_uint8 c0 = d->m_dict[pos + match_len], - c1 = d->m_dict[pos + match_len - 1]; - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); - if (max_match_len <= match_len) - return; - for (;;) { - for (;;) { - if (--num_probes_left == 0) - return; -# define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || \ - ((dist = (mz_uint16) (lookahead_pos - next_probe_pos)) > \ - max_dist)) \ - return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if ((d->m_dict[probe_pos + match_len] == c0) && \ - (d->m_dict[probe_pos + match_len - 1] == c1)) \ - break; - TDEFL_PROBE; - TDEFL_PROBE; - TDEFL_PROBE; - } - if (!dist) - break; - p = s; - q = d->m_dict + probe_pos; - for (probe_len = 0; probe_len < max_match_len; probe_len++) - if (*p++ != *q++) - break; - if (probe_len > match_len) { - *pMatch_dist = dist; - if ((*pMatch_len = match_len = probe_len) == max_match_len) - return; - c0 = d->m_dict[pos + match_len]; - c1 = d->m_dict[pos + match_len - 1]; - } - } -} -# endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */ - -# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -# ifdef MINIZ_UNALIGNED_USE_MEMCPY -static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8 *p) { - mz_uint32 ret; - memcpy(&ret, p, sizeof(mz_uint32)); - return ret; -} -# else -# define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *) (p) -# endif -static mz_bool tdefl_compress_fast(tdefl_compressor *d) { - /* Faster, minimally featured LZRW1-style match+parse loop with - * better register utilization. Intended for applications where raw - * throughput is valued more highly than ratio. */ - mz_uint lookahead_pos = d->m_lookahead_pos, - lookahead_size = d->m_lookahead_size, - dict_size = d->m_dict_size, - total_lz_bytes = d->m_total_lz_bytes, - num_flags_left = d->m_num_flags_left; - mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, - *pLZ_flags = d->m_pLZ_flags; - mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - - while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) { - const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; - mz_uint dst_pos = (lookahead_pos + lookahead_size) & - TDEFL_LZ_DICT_SIZE_MASK; - mz_uint num_bytes_to_process = (mz_uint) MZ_MIN( - d->m_src_buf_left, - TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); - d->m_src_buf_left -= num_bytes_to_process; - lookahead_size += num_bytes_to_process; - - while (num_bytes_to_process) { - mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, - num_bytes_to_process); - memcpy(d->m_dict + dst_pos, d->m_pSrc, n); - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, - MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); - d->m_pSrc += n; - dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; - num_bytes_to_process -= n; - } - - dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, - dict_size); - if ((!d->m_flush) && - (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) - break; - - while (lookahead_size >= 4) { - mz_uint cur_match_dist, cur_match_len = 1; - mz_uint8 *pCur_dict = d->m_dict + cur_pos; - mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & - 0xFFFFFF; - mz_uint hash = (first_trigram ^ - (first_trigram >> - (24 - (TDEFL_LZ_HASH_BITS - 8)))) & - TDEFL_LEVEL1_HASH_SIZE_MASK; - mz_uint probe_pos = d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16) lookahead_pos; - - if (((cur_match_dist = (mz_uint16) (lookahead_pos - - probe_pos)) <= dict_size) && - ((TDEFL_READ_UNALIGNED_WORD32( - d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & - 0xFFFFFF) == first_trigram)) { - const mz_uint16 *p = (const mz_uint16 *) pCur_dict; - const mz_uint16 *q = (const mz_uint16 *) (d->m_dict + - probe_pos); - mz_uint32 probe_len = 32; - do { - } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (TDEFL_READ_UNALIGNED_WORD2(++p) == - TDEFL_READ_UNALIGNED_WORD2(++q)) && - (--probe_len > 0)); - cur_match_len = - ((mz_uint) (p - (const mz_uint16 *) pCur_dict) * 2) + - (mz_uint) (*(const mz_uint8 *) p == - *(const mz_uint8 *) q); - if (!probe_len) - cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; - - if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || - ((cur_match_len == TDEFL_MIN_MATCH_LEN) && - (cur_match_dist >= 8U * 1024U))) { - cur_match_len = 1; - *pLZ_code_buf++ = (mz_uint8) first_trigram; - *pLZ_flags = (mz_uint8) (*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8) first_trigram]++; - } else { - mz_uint32 s0, s1; - cur_match_len = MZ_MIN(cur_match_len, lookahead_size); - - MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && - (cur_match_dist >= 1) && - (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); - - cur_match_dist--; - - pLZ_code_buf[0] = (mz_uint8) (cur_match_len - - TDEFL_MIN_MATCH_LEN); -# ifdef MINIZ_UNALIGNED_USE_MEMCPY - memcpy(&pLZ_code_buf[1], &cur_match_dist, - sizeof(cur_match_dist)); -# else - *(mz_uint16 *) (&pLZ_code_buf[1]) = (mz_uint16) - cur_match_dist; -# endif - pLZ_code_buf += 3; - *pLZ_flags = (mz_uint8) ((*pLZ_flags >> 1) | 0x80); - - s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; - s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; - d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; - - d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - - TDEFL_MIN_MATCH_LEN]]++; - } - } else { - *pLZ_code_buf++ = (mz_uint8) first_trigram; - *pLZ_flags = (mz_uint8) (*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8) first_trigram]++; - } - - if (--num_flags_left == 0) { - num_flags_left = 8; - pLZ_flags = pLZ_code_buf++; - } - - total_lz_bytes += cur_match_len; - lookahead_pos += cur_match_len; - dict_size = MZ_MIN(dict_size + cur_match_len, - (mz_uint) TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; - MZ_ASSERT(lookahead_size >= cur_match_len); - lookahead_size -= cur_match_len; - - if (pLZ_code_buf > - &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { - int n; - d->m_lookahead_pos = lookahead_pos; - d->m_lookahead_size = lookahead_size; - d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; - d->m_pLZ_code_buf = pLZ_code_buf; - d->m_pLZ_flags = pLZ_flags; - d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; - pLZ_code_buf = d->m_pLZ_code_buf; - pLZ_flags = d->m_pLZ_flags; - num_flags_left = d->m_num_flags_left; - } - } - - while (lookahead_size) { - mz_uint8 lit = d->m_dict[cur_pos]; - - total_lz_bytes++; - *pLZ_code_buf++ = lit; - *pLZ_flags = (mz_uint8) (*pLZ_flags >> 1); - if (--num_flags_left == 0) { - num_flags_left = 8; - pLZ_flags = pLZ_code_buf++; - } - - d->m_huff_count[0][lit]++; - - lookahead_pos++; - dict_size = MZ_MIN(dict_size + 1, (mz_uint) TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; - lookahead_size--; - - if (pLZ_code_buf > - &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { - int n; - d->m_lookahead_pos = lookahead_pos; - d->m_lookahead_size = lookahead_size; - d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; - d->m_pLZ_code_buf = pLZ_code_buf; - d->m_pLZ_flags = pLZ_flags; - d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; - pLZ_code_buf = d->m_pLZ_code_buf; - pLZ_flags = d->m_pLZ_flags; - num_flags_left = d->m_num_flags_left; - } - } - } - - d->m_lookahead_pos = lookahead_pos; - d->m_lookahead_size = lookahead_size; - d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; - d->m_pLZ_code_buf = pLZ_code_buf; - d->m_pLZ_flags = pLZ_flags; - d->m_num_flags_left = num_flags_left; - return MZ_TRUE; -} -# endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && \ - MINIZ_LITTLE_ENDIAN */ - -static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, - mz_uint8 lit) { - d->m_total_lz_bytes++; - *d->m_pLZ_code_buf++ = lit; - *d->m_pLZ_flags = (mz_uint8) (*d->m_pLZ_flags >> 1); - if (--d->m_num_flags_left == 0) { - d->m_num_flags_left = 8; - d->m_pLZ_flags = d->m_pLZ_code_buf++; - } - d->m_huff_count[0][lit]++; -} - -static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, - mz_uint match_len, - mz_uint match_dist) { - mz_uint32 s0, s1; - - MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && - (match_dist <= TDEFL_LZ_DICT_SIZE)); - - d->m_total_lz_bytes += match_len; - - d->m_pLZ_code_buf[0] = (mz_uint8) (match_len - TDEFL_MIN_MATCH_LEN); - - match_dist -= 1; - d->m_pLZ_code_buf[1] = (mz_uint8) (match_dist & 0xFF); - d->m_pLZ_code_buf[2] = (mz_uint8) (match_dist >> 8); - d->m_pLZ_code_buf += 3; - - *d->m_pLZ_flags = (mz_uint8) ((*d->m_pLZ_flags >> 1) | 0x80); - if (--d->m_num_flags_left == 0) { - d->m_num_flags_left = 8; - d->m_pLZ_flags = d->m_pLZ_code_buf++; - } - - s0 = s_tdefl_small_dist_sym[match_dist & 511]; - s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; - d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; - d->m_huff_count[0] - [s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; -} - -static mz_bool tdefl_compress_normal(tdefl_compressor *d) { - const mz_uint8 *pSrc = d->m_pSrc; - size_t src_buf_left = d->m_src_buf_left; - tdefl_flush flush = d->m_flush; - - while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) { - mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; - /* Update dictionary and hash chains. Keeps the lookahead size - * equal to TDEFL_MAX_MATCH_LEN. */ - if ((d->m_lookahead_size + d->m_dict_size) >= - (TDEFL_MIN_MATCH_LEN - 1)) { - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & - TDEFL_LZ_DICT_SIZE_MASK, - ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; - mz_uint hash = - (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] - << TDEFL_LZ_HASH_SHIFT) ^ - d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; - mz_uint num_bytes_to_process = (mz_uint) MZ_MIN( - src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); - const mz_uint8 *pSrc_end = pSrc ? pSrc + num_bytes_to_process - : NULL; - src_buf_left -= num_bytes_to_process; - d->m_lookahead_size += num_bytes_to_process; - while (pSrc != pSrc_end) { - mz_uint8 c = *pSrc++; - d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & - (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = - d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16) (ins_pos); - dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; - ins_pos++; - } - } else { - while ((src_buf_left) && - (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) { - mz_uint8 c = *pSrc++; - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & - TDEFL_LZ_DICT_SIZE_MASK; - src_buf_left--; - d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - if ((++d->m_lookahead_size + d->m_dict_size) >= - TDEFL_MIN_MATCH_LEN) { - mz_uint ins_pos = d->m_lookahead_pos + - (d->m_lookahead_size - 1) - 2; - mz_uint hash = - ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] - << (TDEFL_LZ_HASH_SHIFT * 2)) ^ - (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] - << TDEFL_LZ_HASH_SHIFT) ^ - c) & - (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = - d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16) (ins_pos); - } - } - } - d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, - d->m_dict_size); - if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - break; - - /* Simple lazy/greedy parsing state machine. */ - len_to_move = 1; - cur_match_dist = 0; - cur_match_len = d->m_saved_match_len ? d->m_saved_match_len - : (TDEFL_MIN_MATCH_LEN - 1); - cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - if (d->m_flags & - (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) { - if ((d->m_dict_size) && - (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) { - mz_uint8 c = - d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; - cur_match_len = 0; - while (cur_match_len < d->m_lookahead_size) { - if (d->m_dict[cur_pos + cur_match_len] != c) - break; - cur_match_len++; - } - if (cur_match_len < TDEFL_MIN_MATCH_LEN) - cur_match_len = 0; - else - cur_match_dist = 1; - } - } else { - tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, - d->m_lookahead_size, &cur_match_dist, - &cur_match_len); - } - if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && - (cur_match_dist >= 8U * 1024U)) || - (cur_pos == cur_match_dist) || - ((d->m_flags & TDEFL_FILTER_MATCHES) && - (cur_match_len <= 5))) { - cur_match_dist = cur_match_len = 0; - } - if (d->m_saved_match_len) { - if (cur_match_len > d->m_saved_match_len) { - tdefl_record_literal(d, (mz_uint8) d->m_saved_lit); - if (cur_match_len >= 128) { - tdefl_record_match(d, cur_match_len, cur_match_dist); - d->m_saved_match_len = 0; - len_to_move = cur_match_len; - } else { - d->m_saved_lit = d->m_dict[cur_pos]; - d->m_saved_match_dist = cur_match_dist; - d->m_saved_match_len = cur_match_len; - } - } else { - tdefl_record_match(d, d->m_saved_match_len, - d->m_saved_match_dist); - len_to_move = d->m_saved_match_len - 1; - d->m_saved_match_len = 0; - } - } else if (!cur_match_dist) - tdefl_record_literal( - d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); - else if ((d->m_greedy_parsing) || - (d->m_flags & TDEFL_RLE_MATCHES) || - (cur_match_len >= 128)) { - tdefl_record_match(d, cur_match_len, cur_match_dist); - len_to_move = cur_match_len; - } else { - d->m_saved_lit = - d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; - d->m_saved_match_dist = cur_match_dist; - d->m_saved_match_len = cur_match_len; - } - /* Move the lookahead forward by len_to_move bytes. */ - d->m_lookahead_pos += len_to_move; - MZ_ASSERT(d->m_lookahead_size >= len_to_move); - d->m_lookahead_size -= len_to_move; - d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, - (mz_uint) TDEFL_LZ_DICT_SIZE); - /* Check if it's time to flush the current LZ codes to the - * internal output buffer. */ - if ((d->m_pLZ_code_buf > - &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || - ((d->m_total_lz_bytes > 31 * 1024) && - (((((mz_uint) (d->m_pLZ_code_buf - d->m_lz_code_buf) * - 115) >> - 7) >= d->m_total_lz_bytes) || - (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) { - int n; - d->m_pSrc = pSrc; - d->m_src_buf_left = src_buf_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - } - } - - d->m_pSrc = pSrc; - d->m_src_buf_left = src_buf_left; - return MZ_TRUE; -} - -static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) { - if (d->m_pIn_buf_size) { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *) d->m_pIn_buf; - } - - if (d->m_pOut_buf_size) { - size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, - d->m_output_flush_remaining); - memcpy((mz_uint8 *) d->m_pOut_buf + d->m_out_buf_ofs, - d->m_output_buf + d->m_output_flush_ofs, n); - d->m_output_flush_ofs += (mz_uint) n; - d->m_output_flush_remaining -= (mz_uint) n; - d->m_out_buf_ofs += n; - - *d->m_pOut_buf_size = d->m_out_buf_ofs; - } - - return (d->m_finished && !d->m_output_flush_remaining) - ? TDEFL_STATUS_DONE - : TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, - size_t *pIn_buf_size, void *pOut_buf, - size_t *pOut_buf_size, - tdefl_flush flush) { - if (!d) { - if (pIn_buf_size) - *pIn_buf_size = 0; - if (pOut_buf_size) - *pOut_buf_size = 0; - return TDEFL_STATUS_BAD_PARAM; - } - - d->m_pIn_buf = pIn_buf; - d->m_pIn_buf_size = pIn_buf_size; - d->m_pOut_buf = pOut_buf; - d->m_pOut_buf_size = pOut_buf_size; - d->m_pSrc = (const mz_uint8 *) (pIn_buf); - d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; - d->m_out_buf_ofs = 0; - d->m_flush = flush; - - if (((d->m_pPut_buf_func != NULL) == - ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || - (d->m_prev_return_status != TDEFL_STATUS_OKAY) || - (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || - (pIn_buf_size && *pIn_buf_size && !pIn_buf) || - (pOut_buf_size && *pOut_buf_size && !pOut_buf)) { - if (pIn_buf_size) - *pIn_buf_size = 0; - if (pOut_buf_size) - *pOut_buf_size = 0; - return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); - } - d->m_wants_to_finish |= (flush == TDEFL_FINISH); - - if ((d->m_output_flush_remaining) || (d->m_finished)) - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); - -# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && - ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && - ((d->m_flags & - (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | - TDEFL_RLE_MATCHES)) == 0)) { - if (!tdefl_compress_fast(d)) - return d->m_prev_return_status; - } else -# endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && \ - MINIZ_LITTLE_ENDIAN */ - { - if (!tdefl_compress_normal(d)) - return d->m_prev_return_status; - } - - if ((d->m_flags & - (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && - (pIn_buf)) - d->m_adler32 = (mz_uint32) mz_adler32( - d->m_adler32, (const mz_uint8 *) pIn_buf, - d->m_pSrc - (const mz_uint8 *) pIn_buf); - - if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && - (!d->m_output_flush_remaining)) { - if (tdefl_flush_block(d, flush) < 0) - return d->m_prev_return_status; - d->m_finished = (flush == TDEFL_FINISH); - if (flush == TDEFL_FULL_FLUSH) { - MZ_CLEAR_ARR(d->m_hash); - MZ_CLEAR_ARR(d->m_next); - d->m_dict_size = 0; - } - } - - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); -} - -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, - const void *pIn_buf, - size_t in_buf_size, - tdefl_flush flush) { - MZ_ASSERT(d->m_pPut_buf_func); - return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); -} - -tdefl_status tdefl_init(tdefl_compressor *d, - tdefl_put_buf_func_ptr pPut_buf_func, - void *pPut_buf_user, int flags) { - d->m_pPut_buf_func = pPut_buf_func; - d->m_pPut_buf_user = pPut_buf_user; - d->m_flags = (mz_uint) (flags); - d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; - d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; - d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) - MZ_CLEAR_ARR(d->m_hash); - d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = - d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = - 0; - d->m_output_flush_ofs = d->m_output_flush_remaining = - d->m_finished = d->m_block_index = d->m_bit_buffer = - d->m_wants_to_finish = 0; - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; - d->m_pLZ_flags = d->m_lz_code_buf; - *d->m_pLZ_flags = 0; - d->m_num_flags_left = 8; - d->m_pOutput_buf = d->m_output_buf; - d->m_pOutput_buf_end = d->m_output_buf; - d->m_prev_return_status = TDEFL_STATUS_OKAY; - d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; - d->m_adler32 = 1; - d->m_pIn_buf = NULL; - d->m_pOut_buf = NULL; - d->m_pIn_buf_size = NULL; - d->m_pOut_buf_size = NULL; - d->m_flush = TDEFL_NO_FLUSH; - d->m_pSrc = NULL; - d->m_src_buf_left = 0; - d->m_out_buf_ofs = 0; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) - MZ_CLEAR_ARR(d->m_dict); - memset(&d->m_huff_count[0][0], 0, - sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, - sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - return TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) { - return d->m_prev_return_status; -} - -mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { - return d->m_adler32; -} - -mz_bool tdefl_compress_mem_to_output( - const void *pBuf, size_t buf_len, - tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, - int flags) { - tdefl_compressor *pComp; - mz_bool succeeded; - if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) - return MZ_FALSE; - pComp = (tdefl_compressor *) MZ_MALLOC(sizeof(tdefl_compressor)); - if (!pComp) - return MZ_FALSE; - succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, - flags) == TDEFL_STATUS_OKAY); - succeeded = succeeded && (tdefl_compress_buffer( - pComp, pBuf, buf_len, TDEFL_FINISH) == - TDEFL_STATUS_DONE); - MZ_FREE(pComp); - return succeeded; -} - -typedef struct { - size_t m_size, m_capacity; - mz_uint8 *m_pBuf; - mz_bool m_expandable; -} tdefl_output_buffer; - -static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, - void *pUser) { - tdefl_output_buffer *p = (tdefl_output_buffer *) pUser; - size_t new_size = p->m_size + len; - if (new_size > p->m_capacity) { - size_t new_capacity = p->m_capacity; - mz_uint8 *pNew_buf; - if (!p->m_expandable) - return MZ_FALSE; - do { - new_capacity = MZ_MAX(128U, new_capacity << 1U); - } while (new_size > new_capacity); - pNew_buf = (mz_uint8 *) MZ_REALLOC(p->m_pBuf, new_capacity); - if (!pNew_buf) - return MZ_FALSE; - p->m_pBuf = pNew_buf; - p->m_capacity = new_capacity; - } - memcpy((mz_uint8 *) p->m_pBuf + p->m_size, pBuf, len); - p->m_size = new_size; - return MZ_TRUE; -} - -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, - size_t src_buf_len, size_t *pOut_len, - int flags) { - tdefl_output_buffer out_buf; - MZ_CLEAR_OBJ(out_buf); - if (!pOut_len) - return MZ_FALSE; - else - *pOut_len = 0; - out_buf.m_expandable = MZ_TRUE; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, - tdefl_output_buffer_putter, - &out_buf, flags)) - return NULL; - *pOut_len = out_buf.m_size; - return out_buf.m_pBuf; -} - -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, - const void *pSrc_buf, - size_t src_buf_len, int flags) { - tdefl_output_buffer out_buf; - MZ_CLEAR_OBJ(out_buf); - if (!pOut_buf) - return 0; - out_buf.m_pBuf = (mz_uint8 *) pOut_buf; - out_buf.m_capacity = out_buf_len; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, - tdefl_output_buffer_putter, - &out_buf, flags)) - return 0; - return out_buf.m_size; -} - -/* level may actually range from [0,10] (10 is a "hidden" max level, - * where we want a bit more compression and it's fine if throughput to - * fall off a cliff on some files). */ -mz_uint tdefl_create_comp_flags_from_zip_params(int level, - int window_bits, - int strategy) { - mz_uint comp_flags = - s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) - : MZ_DEFAULT_LEVEL] | - ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (window_bits > 0) - comp_flags |= TDEFL_WRITE_ZLIB_HEADER; - - if (!level) - comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - else if (strategy == MZ_FILTERED) - comp_flags |= TDEFL_FILTER_MATCHES; - else if (strategy == MZ_HUFFMAN_ONLY) - comp_flags &= ~TDEFL_MAX_PROBES_MASK; - else if (strategy == MZ_FIXED) - comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; - else if (strategy == MZ_RLE) - comp_flags |= TDEFL_RLE_MATCHES; - - return comp_flags; -} - -# ifdef _MSC_VER -# pragma warning(push) -# pragma warning( \ - disable : 4204) /* nonstandard extension used : non-constant \ - aggregate initializer (also supported by \ - GNU C and C99, so no big deal) */ -# endif - -/* Simple PNG writer function by Alex Evans, 2011. Released into the - public domain: https://gist.github.com/908299, more context at - http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. - This is actually a modification of Alex's original code so PNG files - generated by this function pass pngcheck. */ -void *tdefl_write_image_to_png_file_in_memory_ex( - const void *pImage, int w, int h, int num_chans, size_t *pLen_out, - mz_uint level, mz_bool flip) { - /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS - * was defined. */ - static const mz_uint s_tdefl_png_num_probes[11] = { - 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 - }; - tdefl_compressor *pComp = (tdefl_compressor *) MZ_MALLOC( - sizeof(tdefl_compressor)); - tdefl_output_buffer out_buf; - int i, bpl = w * num_chans, y, z; - mz_uint32 c; - *pLen_out = 0; - if (!pComp) - return NULL; - MZ_CLEAR_OBJ(out_buf); - out_buf.m_expandable = MZ_TRUE; - out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h); - if (NULL == - (out_buf.m_pBuf = (mz_uint8 *) MZ_MALLOC(out_buf.m_capacity))) { - MZ_FREE(pComp); - return NULL; - } - /* write dummy header */ - for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); - /* compress image data */ - tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, - s_tdefl_png_num_probes[MZ_MIN(10, level)] | - TDEFL_WRITE_ZLIB_HEADER); - for (y = 0; y < h; ++y) { - tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); - tdefl_compress_buffer( - pComp, (mz_uint8 *) pImage + (flip ? (h - 1 - y) : y) * bpl, - bpl, TDEFL_NO_FLUSH); - } - if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != - TDEFL_STATUS_DONE) { - MZ_FREE(pComp); - MZ_FREE(out_buf.m_pBuf); - return NULL; - } - /* write real header */ - *pLen_out = out_buf.m_size - 41; - { - static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 }; - mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, - 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, - 0x44, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x49, 0x44, 0x41, 0x54 }; - pnghdr[18] = (mz_uint8) (w >> 8); - pnghdr[19] = (mz_uint8) w; - pnghdr[22] = (mz_uint8) (h >> 8); - pnghdr[23] = (mz_uint8) h; - pnghdr[25] = chans[num_chans]; - pnghdr[33] = (mz_uint8) (*pLen_out >> 24); - pnghdr[34] = (mz_uint8) (*pLen_out >> 16); - pnghdr[35] = (mz_uint8) (*pLen_out >> 8); - pnghdr[36] = (mz_uint8) *pLen_out; - c = (mz_uint32) mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17); - for (i = 0; i < 4; ++i, c <<= 8) - ((mz_uint8 *) (pnghdr + 29))[i] = (mz_uint8) (c >> 24); - memcpy(out_buf.m_pBuf, pnghdr, 41); - } - /* write footer (IDAT CRC-32, followed by IEND chunk) */ - if (!tdefl_output_buffer_putter( - "\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, - &out_buf)) { - *pLen_out = 0; - MZ_FREE(pComp); - MZ_FREE(out_buf.m_pBuf); - return NULL; - } - c = (mz_uint32) mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, - *pLen_out + 4); - for (i = 0; i < 4; ++i, c <<= 8) - (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8) (c >> 24); - /* compute final size of file, grab compressed data buffer and - * return */ - *pLen_out += 57; - MZ_FREE(pComp); - return out_buf.m_pBuf; -} -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, - int w, int h, - int num_chans, - size_t *pLen_out) { - /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or - * MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being - * available in case the zlib API's where #defined out) */ - return tdefl_write_image_to_png_file_in_memory_ex( - pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); -} - -# ifndef MINIZ_NO_MALLOC -/* Allocate the tdefl_compressor and tinfl_decompressor structures in - * C so that */ -/* non-C language bindings to tdefL_ and tinfl_ API don't need to - * worry about */ -/* structure size and allocation mechanism. */ -tdefl_compressor *tdefl_compressor_alloc(void) { - return (tdefl_compressor *) MZ_MALLOC(sizeof(tdefl_compressor)); -} - -void tdefl_compressor_free(tdefl_compressor *pComp) { - MZ_FREE(pComp); -} -# endif - -# ifdef _MSC_VER -# pragma warning(pop) -# endif - -# ifdef __cplusplus -} -# endif - -#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ diff --git a/source/kit/miniz/miniz_tdef.h b/source/kit/miniz/miniz_tdef.h deleted file mode 100644 index f7adaa6..0000000 --- a/source/kit/miniz/miniz_tdef.h +++ /dev/null @@ -1,271 +0,0 @@ -#ifndef KIT_MINIZ_MINIZ_TDEF_H -#define KIT_MINIZ_MINIZ_TDEF_H - -#include "miniz_common.h" - -#ifndef MINIZ_NO_DEFLATE_APIS - -# ifdef __cplusplus -extern "C" { -# endif -/* ------------------- Low-level Compression API Definitions */ - -/* Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be - * slightly slower, and raw/dynamic blocks will be output more - * frequently). */ -# define TDEFL_LESS_MEMORY 0 - -/* tdefl_init() compression flags logically OR'd together (low 12 bits - * contain the max. number of probes per dictionary search): */ -/* TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary - * probes per dictionary search. 0=Huffman only, 1=Huffman+LZ - * (fastest/crap compression), 4095=Huffman+LZ (slowest/best - * compression). */ -enum { - TDEFL_HUFFMAN_ONLY = 0, - TDEFL_DEFAULT_MAX_PROBES = 128, - TDEFL_MAX_PROBES_MASK = 0xFFF -}; - -/* TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib - * header before the deflate data, and the Adler-32 of the source data - * at the end. Otherwise, you'll get raw deflate data. */ -/* TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input - * data (even when not writing zlib headers). */ -/* TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, - * instead of more efficient lazy parsing. */ -/* TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the - * compressor's initialization time to the minimum, but the output may - * vary from run to run given the same input (depending on the - * contents of memory). */ -/* TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a - * distance of 1) */ -/* TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. */ -/* TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman - * tables. */ -/* TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate - * blocks. */ -/* The low 12 bits are reserved to control the max # of hash probes - * per dictionary lookup (see TDEFL_MAX_PROBES_MASK). */ -enum { - TDEFL_WRITE_ZLIB_HEADER = 0x01000, - TDEFL_COMPUTE_ADLER32 = 0x02000, - TDEFL_GREEDY_PARSING_FLAG = 0x04000, - TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, - TDEFL_RLE_MATCHES = 0x10000, - TDEFL_FILTER_MATCHES = 0x20000, - TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, - TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 -}; - -/* High level compression functions: */ -/* tdefl_compress_mem_to_heap() compresses a block in memory to a heap - * block allocated via malloc(). */ -/* On entry: */ -/* pSrc_buf, src_buf_len: Pointer and size of source block to - * compress. */ -/* flags: The max match finder probes (default is 128) logically OR'd - * against the above flags. Higher probes are slower but improve - * compression. */ -/* On return: */ -/* Function returns a pointer to the compressed data, or NULL on - * failure. */ -/* *pOut_len will be set to the compressed data's size, which could - * be larger than src_buf_len on uncompressible data. */ -/* The caller must free() the returned block when it's no longer - * needed. */ -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, - size_t src_buf_len, size_t *pOut_len, - int flags); - -/* tdefl_compress_mem_to_mem() compresses a block in memory to another - * block in memory. */ -/* Returns 0 on failure. */ -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, - const void *pSrc_buf, - size_t src_buf_len, int flags); - -/* Compresses an image to a compressed PNG file in memory. */ -/* On entry: */ -/* pImage, w, h, and num_chans describe the image to compress. - * num_chans may be 1, 2, 3, or 4. */ -/* The image pitch in bytes per scanline will be w*num_chans. The - * leftmost pixel on the top scanline is stored first in memory. */ -/* level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, - * MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL - */ -/* If flip is true, the image will be flipped on the Y axis (useful - * for OpenGL apps). */ -/* On return: */ -/* Function returns a pointer to the compressed data, or NULL on - * failure. */ -/* *pLen_out will be set to the size of the PNG image file. */ -/* The caller must mz_free() the returned heap block (which will - * typically be larger than *pLen_out) when it's no longer needed. */ -void *tdefl_write_image_to_png_file_in_memory_ex( - const void *pImage, int w, int h, int num_chans, size_t *pLen_out, - mz_uint level, mz_bool flip); -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, - int w, int h, - int num_chans, - size_t *pLen_out); - -/* Output stream interface. The compressor uses this interface to - * write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE - * at a time. */ -typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len, - void *pUser); - -/* tdefl_compress_mem_to_output() compresses a block to an output - * stream. The above helpers use this function internally. */ -mz_bool tdefl_compress_mem_to_output( - const void *pBuf, size_t buf_len, - tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, - int flags); - -enum { - TDEFL_MAX_HUFF_TABLES = 3, - TDEFL_MAX_HUFF_SYMBOLS_0 = 288, - TDEFL_MAX_HUFF_SYMBOLS_1 = 32, - TDEFL_MAX_HUFF_SYMBOLS_2 = 19, - TDEFL_LZ_DICT_SIZE = 32768, - TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, - TDEFL_MIN_MATCH_LEN = 3, - TDEFL_MAX_MATCH_LEN = 258 -}; - -/* TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire - * compressed output block (using static/fixed Huffman codes). */ -# if TDEFL_LESS_MEMORY -enum { - TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, - TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, - TDEFL_MAX_HUFF_SYMBOLS = 288, - TDEFL_LZ_HASH_BITS = 12, - TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, - TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, - TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS -}; -# else -enum { - TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, - TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, - TDEFL_MAX_HUFF_SYMBOLS = 288, - TDEFL_LZ_HASH_BITS = 15, - TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, - TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, - TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS -}; -# endif - -/* The low-level tdefl functions below may be used directly if the - * above helper functions aren't flexible enough. The low-level - * functions don't make any heap allocations, unlike the above helper - * functions. */ -typedef enum { - TDEFL_STATUS_BAD_PARAM = -2, - TDEFL_STATUS_PUT_BUF_FAILED = -1, - TDEFL_STATUS_OKAY = 0, - TDEFL_STATUS_DONE = 1 -} tdefl_status; - -/* Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums */ -typedef enum { - TDEFL_NO_FLUSH = 0, - TDEFL_SYNC_FLUSH = 2, - TDEFL_FULL_FLUSH = 3, - TDEFL_FINISH = 4 -} tdefl_flush; - -/* tdefl's compression state structure. */ -typedef struct { - tdefl_put_buf_func_ptr m_pPut_buf_func; - void *m_pPut_buf_user; - mz_uint m_flags, m_max_probes[2]; - int m_greedy_parsing; - mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; - mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, - *m_pOutput_buf_end; - mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, - m_bits_in, m_bit_buffer; - mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, - m_output_flush_ofs, m_output_flush_remaining, m_finished, - m_block_index, m_wants_to_finish; - tdefl_status m_prev_return_status; - const void *m_pIn_buf; - void *m_pOut_buf; - size_t *m_pIn_buf_size, *m_pOut_buf_size; - tdefl_flush m_flush; - const mz_uint8 *m_pSrc; - size_t m_src_buf_left, m_out_buf_ofs; - mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; - mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES] - [TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES] - [TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES] - [TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; - mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; - mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; - mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; -} tdefl_compressor; - -/* Initializes the compressor. */ -/* There is no corresponding deinit() function because the tdefl API's - * do not dynamically allocate memory. */ -/* pBut_buf_func: If NULL, output data will be supplied to the - * specified callback. In this case, the user should call the - * tdefl_compress_buffer() API for compression. */ -/* If pBut_buf_func is NULL the user should always call the - * tdefl_compress() API. */ -/* flags: See the above enums (TDEFL_HUFFMAN_ONLY, - * TDEFL_WRITE_ZLIB_HEADER, etc.) */ -tdefl_status tdefl_init(tdefl_compressor *d, - tdefl_put_buf_func_ptr pPut_buf_func, - void *pPut_buf_user, int flags); - -/* Compresses a block of data, consuming as much of the specified - * input buffer as possible, and writing as much compressed data to - * the specified output buffer as possible. */ -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, - size_t *pIn_buf_size, void *pOut_buf, - size_t *pOut_buf_size, tdefl_flush flush); - -/* tdefl_compress_buffer() is only usable when the tdefl_init() is - * called with a non-NULL tdefl_put_buf_func_ptr. */ -/* tdefl_compress_buffer() always consumes the entire input buffer. */ -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, - const void *pIn_buf, - size_t in_buf_size, - tdefl_flush flush); - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); -mz_uint32 tdefl_get_adler32(tdefl_compressor *d); - -/* Create tdefl_compress() flags given zlib-style compression - * parameters. */ -/* level may range from [0,10] (where 10 is absolute max compression, - * but may be much slower on some files) */ -/* window_bits may be -15 (raw deflate) or 15 (zlib) */ -/* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, - * MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */ -mz_uint tdefl_create_comp_flags_from_zip_params(int level, - int window_bits, - int strategy); - -# ifndef MINIZ_NO_MALLOC -/* Allocate the tdefl_compressor structure in C so that */ -/* non-C language bindings to tdefl_ API don't need to worry about */ -/* structure size and allocation mechanism. */ -tdefl_compressor *tdefl_compressor_alloc(void); -void tdefl_compressor_free(tdefl_compressor *pComp); -# endif - -# ifdef __cplusplus -} -# endif - -#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ - -#endif diff --git a/source/kit/miniz/miniz_tinfl.c b/source/kit/miniz/miniz_tinfl.c deleted file mode 100644 index c8843ad..0000000 --- a/source/kit/miniz/miniz_tinfl.c +++ /dev/null @@ -1,818 +0,0 @@ -/************************************************************************** - * - * Copyright 2013-2014 RAD Game Tools and Valve Software - * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC - * All Rights Reserved. - * - * 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. - * - **************************************************************************/ - -#include "miniz.h" - -#ifndef MINIZ_NO_INFLATE_APIS - -# ifdef __cplusplus -extern "C" { -# endif - -/* ------------------- Low-level Decompression (completely independent - * from all compression API's) */ - -# define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) -# define TINFL_MEMSET(p, c, l) memset(p, c, l) - -# define TINFL_CR_BEGIN \ - switch (r->m_state) { \ - case 0: -# define TINFL_CR_RETURN(state_index, result) \ - do { \ - status = result; \ - r->m_state = state_index; \ - goto common_exit; \ - case state_index:; \ - } \ - MZ_MACRO_END -# define TINFL_CR_RETURN_FOREVER(state_index, result) \ - do { \ - for (;;) { TINFL_CR_RETURN(state_index, result); } \ - } \ - MZ_MACRO_END -# define TINFL_CR_FINISH } - -# define TINFL_GET_BYTE(state_index, c) \ - do { \ - while (pIn_buf_cur >= pIn_buf_end) { \ - TINFL_CR_RETURN( \ - state_index, \ - (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) \ - ? TINFL_STATUS_NEEDS_MORE_INPUT \ - : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \ - } \ - c = *pIn_buf_cur++; \ - } \ - MZ_MACRO_END - -# define TINFL_NEED_BITS(state_index, n) \ - do { \ - mz_uint c; \ - TINFL_GET_BYTE(state_index, c); \ - bit_buf |= (((tinfl_bit_buf_t) c) << num_bits); \ - num_bits += 8; \ - } while (num_bits < (mz_uint) (n)) -# define TINFL_SKIP_BITS(state_index, n) \ - do { \ - if (num_bits < (mz_uint) (n)) { \ - TINFL_NEED_BITS(state_index, n); \ - } \ - bit_buf >>= (n); \ - num_bits -= (n); \ - } \ - MZ_MACRO_END -# define TINFL_GET_BITS(state_index, b, n) \ - do { \ - if (num_bits < (mz_uint) (n)) { \ - TINFL_NEED_BITS(state_index, n); \ - } \ - b = bit_buf & ((1 << (n)) - 1); \ - bit_buf >>= (n); \ - num_bits -= (n); \ - } \ - MZ_MACRO_END - -/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of - * bytes remaining in the input buffer falls below 2. */ -/* It reads just enough bytes from the input stream that are needed to - * decode the next Huffman code (and absolutely no more). It works by - * trying to fully decode a */ -/* Huffman code by using whatever bits are currently present in the - * bit buffer. If this fails, it reads another byte, and tries again - * until it succeeds or until the */ -/* bit buffer contains >=15 bits (deflate's max. Huffman code size). - */ -# define TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree) \ - do { \ - temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ - if (temp >= 0) { \ - code_len = temp >> 9; \ - if ((code_len) && (num_bits >= code_len)) \ - break; \ - } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ - code_len = TINFL_FAST_LOOKUP_BITS; \ - do { \ - temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while ((temp < 0) && (num_bits >= (code_len + 1))); \ - if (temp >= 0) \ - break; \ - } \ - TINFL_GET_BYTE(state_index, c); \ - bit_buf |= (((tinfl_bit_buf_t) c) << num_bits); \ - num_bits += 8; \ - } while (num_bits < 15); - -/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's - * more complex than you would initially expect because the zlib API - * expects the decompressor to never read */ -/* beyond the final byte of the deflate stream. (In other words, when - * this macro wants to read another byte from the input, it REALLY - * needs another byte in order to fully */ -/* decode the next Huffman code.) Handling this properly is - * particularly important on raw deflate (non-zlib) streams, which - * aren't followed by a byte aligned adler-32. */ -/* The slow path is only executed at the very end of the input buffer. - */ -/* v1.16: The original macro handled the case at the very end of the - * passed-in input buffer, but we also need to handle the case where - * the user passes in 1+zillion bytes */ -/* following the deflate data and our non-conservative read-ahead path - * won't kick in here on this code. This is much trickier. */ -# define TINFL_HUFF_DECODE(state_index, sym, pLookUp, pTree) \ - do { \ - int temp; \ - mz_uint code_len, c; \ - if (num_bits < 15) { \ - if ((pIn_buf_end - pIn_buf_cur) < 2) { \ - TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree); \ - } else { \ - bit_buf |= (((tinfl_bit_buf_t) pIn_buf_cur[0]) \ - << num_bits) | \ - (((tinfl_bit_buf_t) pIn_buf_cur[1]) \ - << (num_bits + 8)); \ - pIn_buf_cur += 2; \ - num_bits += 16; \ - } \ - } \ - if ((temp = \ - pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= \ - 0) \ - code_len = temp >> 9, temp &= 511; \ - else { \ - code_len = TINFL_FAST_LOOKUP_BITS; \ - do { \ - temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while (temp < 0); \ - } \ - sym = temp; \ - bit_buf >>= code_len; \ - num_bits -= code_len; \ - } \ - MZ_MACRO_END - -static void tinfl_clear_tree(tinfl_decompressor *r) { - if (r->m_type == 0) - MZ_CLEAR_ARR(r->m_tree_0); - else if (r->m_type == 1) - MZ_CLEAR_ARR(r->m_tree_1); - else - MZ_CLEAR_ARR(r->m_tree_2); -} - -tinfl_status tinfl_decompress(tinfl_decompressor *r, - const mz_uint8 *pIn_buf_next, - size_t *pIn_buf_size, - mz_uint8 *pOut_buf_start, - mz_uint8 *pOut_buf_next, - size_t *pOut_buf_size, - const mz_uint32 decomp_flags) { - static const mz_uint16 s_length_base[31] = { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, - 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, - 99, 115, 131, 163, 195, 227, 258, 0, 0 - }; - static const mz_uint8 s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, - 5, 5, 5, 5, 0, 0, 0 }; - static const mz_uint16 s_dist_base[32] = { - 1, 2, 3, 4, 5, 7, 9, 13, - 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, - 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 - }; - static const mz_uint8 s_dist_extra[32] = { - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, - 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 - }; - static const mz_uint8 s_length_dezigzag[19] = { - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - }; - static const mz_uint16 s_min_table_sizes[3] = { 257, 1, 4 }; - - mz_int16 *pTrees[3]; - mz_uint8 *pCode_sizes[3]; - - tinfl_status status = TINFL_STATUS_FAILED; - mz_uint32 num_bits, dist, counter, num_extra; - tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = - pIn_buf_next + - *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = - pOut_buf_next - ? pOut_buf_next + - *pOut_buf_size - : NULL; - size_t out_buf_size_mask = - (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) - ? (size_t) -1 - : ((pOut_buf_next - pOut_buf_start) + - *pOut_buf_size) - - 1, - dist_from_out_buf_start; - - /* Ensure the output buffer's size is a power of 2, unless the - * output buffer is large enough to hold the entire output file (in - * which case it doesn't matter). */ - if (((out_buf_size_mask + 1) & out_buf_size_mask) || - (pOut_buf_next < pOut_buf_start)) { - *pIn_buf_size = *pOut_buf_size = 0; - return TINFL_STATUS_BAD_PARAM; - } - - pTrees[0] = r->m_tree_0; - pTrees[1] = r->m_tree_1; - pTrees[2] = r->m_tree_2; - pCode_sizes[0] = r->m_code_size_0; - pCode_sizes[1] = r->m_code_size_1; - pCode_sizes[2] = r->m_code_size_2; - - num_bits = r->m_num_bits; - bit_buf = r->m_bit_buf; - dist = r->m_dist; - counter = r->m_counter; - num_extra = r->m_num_extra; - dist_from_out_buf_start = r->m_dist_from_out_buf_start; - TINFL_CR_BEGIN - - bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = - r->m_zhdr1 = 0; - r->m_z_adler32 = r->m_check_adler32 = 1; - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { - TINFL_GET_BYTE(1, r->m_zhdr0); - TINFL_GET_BYTE(2, r->m_zhdr1); - counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || - (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); - if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) - counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || - ((out_buf_size_mask + 1) < - (size_t) ((size_t) 1 - << (8U + (r->m_zhdr0 >> 4))))); - if (counter) { - TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); - } - } - - do { - TINFL_GET_BITS(3, r->m_final, 3); - r->m_type = r->m_final >> 1; - if (r->m_type == 0) { - TINFL_SKIP_BITS(5, num_bits & 7); - for (counter = 0; counter < 4; ++counter) { - if (num_bits) - TINFL_GET_BITS(6, r->m_raw_header[counter], 8); - else - TINFL_GET_BYTE(7, r->m_raw_header[counter]); - } - if ((counter = (r->m_raw_header[0] | - (r->m_raw_header[1] << 8))) != - (mz_uint) (0xFFFF ^ (r->m_raw_header[2] | - (r->m_raw_header[3] << 8)))) { - TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); - } - while ((counter) && (num_bits)) { - TINFL_GET_BITS(51, dist, 8); - while (pOut_buf_cur >= pOut_buf_end) { - TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); - } - *pOut_buf_cur++ = (mz_uint8) dist; - counter--; - } - while (counter) { - size_t n; - while (pOut_buf_cur >= pOut_buf_end) { - TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); - } - while (pIn_buf_cur >= pIn_buf_end) { - TINFL_CR_RETURN( - 38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) - ? TINFL_STATUS_NEEDS_MORE_INPUT - : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); - } - n = MZ_MIN(MZ_MIN((size_t) (pOut_buf_end - pOut_buf_cur), - (size_t) (pIn_buf_end - pIn_buf_cur)), - counter); - TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); - pIn_buf_cur += n; - pOut_buf_cur += n; - counter -= (mz_uint) n; - } - } else if (r->m_type == 3) { - TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); - } else { - if (r->m_type == 1) { - mz_uint8 *p = r->m_code_size_0; - mz_uint i; - r->m_table_sizes[0] = 288; - r->m_table_sizes[1] = 32; - TINFL_MEMSET(r->m_code_size_1, 5, 32); - for (i = 0; i <= 143; ++i) *p++ = 8; - for (; i <= 255; ++i) *p++ = 9; - for (; i <= 279; ++i) *p++ = 7; - for (; i <= 287; ++i) *p++ = 8; - } else { - for (counter = 0; counter < 3; counter++) { - TINFL_GET_BITS(11, r->m_table_sizes[counter], - "\05\05\04"[counter]); - r->m_table_sizes[counter] += s_min_table_sizes[counter]; - } - MZ_CLEAR_ARR(r->m_code_size_2); - for (counter = 0; counter < r->m_table_sizes[2]; counter++) { - mz_uint s; - TINFL_GET_BITS(14, s, 3); - r->m_code_size_2[s_length_dezigzag[counter]] = (mz_uint8) s; - } - r->m_table_sizes[2] = 19; - } - for (; (int) r->m_type >= 0; r->m_type--) { - int tree_next, tree_cur; - mz_int16 *pLookUp; - mz_int16 *pTree; - mz_uint8 *pCode_size; - mz_uint i, j, used_syms, total, sym_index, next_code[17], - total_syms[16]; - pLookUp = r->m_look_up[r->m_type]; - pTree = pTrees[r->m_type]; - pCode_size = pCode_sizes[r->m_type]; - MZ_CLEAR_ARR(total_syms); - TINFL_MEMSET(pLookUp, 0, sizeof(r->m_look_up[0])); - tinfl_clear_tree(r); - for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) - total_syms[pCode_size[i]]++; - used_syms = 0, total = 0; - next_code[0] = next_code[1] = 0; - for (i = 1; i <= 15; ++i) { - used_syms += total_syms[i]; - next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); - } - if ((65536 != total) && (used_syms > 1)) { - TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); - } - for (tree_next = -1, sym_index = 0; - sym_index < r->m_table_sizes[r->m_type]; ++sym_index) { - mz_uint rev_code = 0, l, cur_code, - code_size = pCode_size[sym_index]; - if (!code_size) - continue; - cur_code = next_code[code_size]++; - for (l = code_size; l > 0; l--, cur_code >>= 1) - rev_code = (rev_code << 1) | (cur_code & 1); - if (code_size <= TINFL_FAST_LOOKUP_BITS) { - mz_int16 k = (mz_int16) ((code_size << 9) | sym_index); - while (rev_code < TINFL_FAST_LOOKUP_SIZE) { - pLookUp[rev_code] = k; - rev_code += (1 << code_size); - } - continue; - } - if (0 == - (tree_cur = pLookUp[rev_code & - (TINFL_FAST_LOOKUP_SIZE - 1)])) { - pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = - (mz_int16) tree_next; - tree_cur = tree_next; - tree_next -= 2; - } - rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); - for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) { - tree_cur -= ((rev_code >>= 1) & 1); - if (!pTree[-tree_cur - 1]) { - pTree[-tree_cur - 1] = (mz_int16) tree_next; - tree_cur = tree_next; - tree_next -= 2; - } else - tree_cur = pTree[-tree_cur - 1]; - } - tree_cur -= ((rev_code >>= 1) & 1); - pTree[-tree_cur - 1] = (mz_int16) sym_index; - } - if (r->m_type == 2) { - for (counter = 0; counter < (r->m_table_sizes[0] + - r->m_table_sizes[1]);) { - mz_uint s; - TINFL_HUFF_DECODE(16, dist, r->m_look_up[2], r->m_tree_2); - if (dist < 16) { - r->m_len_codes[counter++] = (mz_uint8) dist; - continue; - } - if ((dist == 16) && (!counter)) { - TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); - } - num_extra = "\02\03\07"[dist - 16]; - TINFL_GET_BITS(18, s, num_extra); - s += "\03\03\013"[dist - 16]; - TINFL_MEMSET( - r->m_len_codes + counter, - (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); - counter += s; - } - if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != - counter) { - TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); - } - TINFL_MEMCPY(r->m_code_size_0, r->m_len_codes, - r->m_table_sizes[0]); - TINFL_MEMCPY(r->m_code_size_1, - r->m_len_codes + r->m_table_sizes[0], - r->m_table_sizes[1]); - } - } - for (;;) { - mz_uint8 *pSrc; - for (;;) { - if (((pIn_buf_end - pIn_buf_cur) < 4) || - ((pOut_buf_end - pOut_buf_cur) < 2)) { - TINFL_HUFF_DECODE(23, counter, r->m_look_up[0], - r->m_tree_0); - if (counter >= 256) - break; - while (pOut_buf_cur >= pOut_buf_end) { - TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); - } - *pOut_buf_cur++ = (mz_uint8) counter; - } else { - int sym2; - mz_uint code_len; -# if TINFL_USE_64BIT_BITBUF - if (num_bits < 30) { - bit_buf |= - (((tinfl_bit_buf_t) MZ_READ_LE32(pIn_buf_cur)) - << num_bits); - pIn_buf_cur += 4; - num_bits += 32; - } -# else - if (num_bits < 15) { - bit_buf |= - (((tinfl_bit_buf_t) MZ_READ_LE16(pIn_buf_cur)) - << num_bits); - pIn_buf_cur += 2; - num_bits += 16; - } -# endif - if ((sym2 = - r->m_look_up[0][bit_buf & - (TINFL_FAST_LOOKUP_SIZE - 1)]) >= - 0) - code_len = sym2 >> 9; - else { - code_len = TINFL_FAST_LOOKUP_BITS; - do { - sym2 = r->m_tree_0[~sym2 + - ((bit_buf >> code_len++) & 1)]; - } while (sym2 < 0); - } - counter = sym2; - bit_buf >>= code_len; - num_bits -= code_len; - if (counter & 256) - break; - -# if !TINFL_USE_64BIT_BITBUF - if (num_bits < 15) { - bit_buf |= - (((tinfl_bit_buf_t) MZ_READ_LE16(pIn_buf_cur)) - << num_bits); - pIn_buf_cur += 2; - num_bits += 16; - } -# endif - if ((sym2 = - r->m_look_up[0][bit_buf & - (TINFL_FAST_LOOKUP_SIZE - 1)]) >= - 0) - code_len = sym2 >> 9; - else { - code_len = TINFL_FAST_LOOKUP_BITS; - do { - sym2 = r->m_tree_0[~sym2 + - ((bit_buf >> code_len++) & 1)]; - } while (sym2 < 0); - } - bit_buf >>= code_len; - num_bits -= code_len; - - pOut_buf_cur[0] = (mz_uint8) counter; - if (sym2 & 256) { - pOut_buf_cur++; - counter = sym2; - break; - } - pOut_buf_cur[1] = (mz_uint8) sym2; - pOut_buf_cur += 2; - } - } - if ((counter &= 511) == 256) - break; - - num_extra = s_length_extra[counter - 257]; - counter = s_length_base[counter - 257]; - if (num_extra) { - mz_uint extra_bits; - TINFL_GET_BITS(25, extra_bits, num_extra); - counter += extra_bits; - } - - TINFL_HUFF_DECODE(26, dist, r->m_look_up[1], r->m_tree_1); - num_extra = s_dist_extra[dist]; - dist = s_dist_base[dist]; - if (num_extra) { - mz_uint extra_bits; - TINFL_GET_BITS(27, extra_bits, num_extra); - dist += extra_bits; - } - - dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; - if ((dist == 0 || dist > dist_from_out_buf_start || - dist_from_out_buf_start == 0) && - (decomp_flags & - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) { - TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); - } - - pSrc = pOut_buf_start + - ((dist_from_out_buf_start - dist) & out_buf_size_mask); - - if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) { - while (counter--) { - while (pOut_buf_cur >= pOut_buf_end) { - TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); - } - *pOut_buf_cur++ = - pOut_buf_start[(dist_from_out_buf_start++ - dist) & - out_buf_size_mask]; - } - continue; - } -# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - else if ((counter >= 9) && (counter <= dist)) { - const mz_uint8 *pSrc_end = pSrc + (counter & ~7); - do { -# ifdef MINIZ_UNALIGNED_USE_MEMCPY - memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32) * 2); -# else - ((mz_uint32 *) pOut_buf_cur)[0] = (( - const mz_uint32 *) pSrc)[0]; - ((mz_uint32 *) pOut_buf_cur)[1] = (( - const mz_uint32 *) pSrc)[1]; -# endif - pOut_buf_cur += 8; - } while ((pSrc += 8) < pSrc_end); - if ((counter &= 7) < 3) { - if (counter) { - pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - continue; - } - } -# endif - while (counter > 2) { - pOut_buf_cur[0] = pSrc[0]; - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur[2] = pSrc[2]; - pOut_buf_cur += 3; - pSrc += 3; - counter -= 3; - } - if (counter > 0) { - pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; - } - } - } - } while (!(r->m_final & 1)); - - /* Ensure byte alignment and put back any bytes from the bitbuf if - * we've looked ahead too far on gzip, or other Deflate streams - * followed by arbitrary data. */ - /* I'm being super conservative here. A number of simplifications - * can be made to the byte alignment part, and the Adler32 check - * shouldn't ever need to worry about reading from the bitbuf now. - */ - TINFL_SKIP_BITS(32, num_bits & 7); - while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) { - --pIn_buf_cur; - num_bits -= 8; - } - bit_buf &= ~(~(tinfl_bit_buf_t) 0 << num_bits); - MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond - the end of non-deflate/zlib streams with - following data (such as gzip streams). */ - - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { - for (counter = 0; counter < 4; ++counter) { - mz_uint s; - if (num_bits) - TINFL_GET_BITS(41, s, 8); - else - TINFL_GET_BYTE(42, s); - r->m_z_adler32 = (r->m_z_adler32 << 8) | s; - } - } - TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); - - TINFL_CR_FINISH - -common_exit: - /* As long as we aren't telling the caller that we NEED more input - * to make forward progress: */ - /* Put back any bytes from the bitbuf in case we've looked ahead too - * far on gzip, or other Deflate streams followed by arbitrary data. - */ - /* We need to be very careful here to NOT push back any bytes we - * definitely know we need to make forward progress, though, or - * we'll lock the caller up into an inf loop. */ - if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && - (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS)) { - while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) { - --pIn_buf_cur; - num_bits -= 8; - } - } - r->m_num_bits = num_bits; - r->m_bit_buf = bit_buf & ~(~(tinfl_bit_buf_t) 0 << num_bits); - r->m_dist = dist; - r->m_counter = counter; - r->m_num_extra = num_extra; - r->m_dist_from_out_buf_start = dist_from_out_buf_start; - *pIn_buf_size = pIn_buf_cur - pIn_buf_next; - *pOut_buf_size = pOut_buf_cur - pOut_buf_next; - if ((decomp_flags & - (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && - (status >= 0)) { - const mz_uint8 *ptr = pOut_buf_next; - size_t buf_len = *pOut_buf_size; - mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, - s2 = r->m_check_adler32 >> 16; - size_t block_len = buf_len % 5552; - while (buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { - s1 += ptr[0], s2 += s1; - s1 += ptr[1], s2 += s1; - s1 += ptr[2], s2 += s1; - s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; - s1 += ptr[5], s2 += s1; - s1 += ptr[6], s2 += s1; - s1 += ptr[7], s2 += s1; - } - for (; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; - buf_len -= block_len; - block_len = 5552; - } - r->m_check_adler32 = (s2 << 16) + s1; - if ((status == TINFL_STATUS_DONE) && - (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && - (r->m_check_adler32 != r->m_z_adler32)) - status = TINFL_STATUS_ADLER32_MISMATCH; - } - return status; -} - -/* Higher level helper functions. */ -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, - size_t src_buf_len, - size_t *pOut_len, int flags) { - tinfl_decompressor decomp; - void *pBuf = NULL, *pNew_buf; - size_t src_buf_ofs = 0, out_buf_capacity = 0; - *pOut_len = 0; - tinfl_init(&decomp); - for (;;) { - size_t src_buf_size = src_buf_len - src_buf_ofs, - dst_buf_size = out_buf_capacity - *pOut_len, - new_out_buf_capacity; - tinfl_status status = tinfl_decompress( - &decomp, (const mz_uint8 *) pSrc_buf + src_buf_ofs, - &src_buf_size, (mz_uint8 *) pBuf, - pBuf ? (mz_uint8 *) pBuf + *pOut_len : NULL, &dst_buf_size, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) { - MZ_FREE(pBuf); - *pOut_len = 0; - return NULL; - } - src_buf_ofs += src_buf_size; - *pOut_len += dst_buf_size; - if (status == TINFL_STATUS_DONE) - break; - new_out_buf_capacity = out_buf_capacity * 2; - if (new_out_buf_capacity < 128) - new_out_buf_capacity = 128; - pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); - if (!pNew_buf) { - MZ_FREE(pBuf); - *pOut_len = 0; - return NULL; - } - pBuf = pNew_buf; - out_buf_capacity = new_out_buf_capacity; - } - return pBuf; -} - -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, - const void *pSrc_buf, - size_t src_buf_len, int flags) { - tinfl_decompressor decomp; - tinfl_status status; - tinfl_init(&decomp); - status = tinfl_decompress( - &decomp, (const mz_uint8 *) pSrc_buf, &src_buf_len, - (mz_uint8 *) pOut_buf, (mz_uint8 *) pOut_buf, &out_buf_len, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - return (status != TINFL_STATUS_DONE) - ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED - : out_buf_len; -} - -int tinfl_decompress_mem_to_callback( - const void *pIn_buf, size_t *pIn_buf_size, - tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, - int flags) { - int result = 0; - tinfl_decompressor decomp; - mz_uint8 *pDict = (mz_uint8 *) MZ_MALLOC(TINFL_LZ_DICT_SIZE); - size_t in_buf_ofs = 0, dict_ofs = 0; - if (!pDict) - return TINFL_STATUS_FAILED; - memset(pDict, 0, TINFL_LZ_DICT_SIZE); - tinfl_init(&decomp); - for (;;) { - size_t in_buf_size = *pIn_buf_size - in_buf_ofs, - dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; - tinfl_status status = tinfl_decompress( - &decomp, (const mz_uint8 *) pIn_buf + in_buf_ofs, - &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); - in_buf_ofs += in_buf_size; - if ((dst_buf_size) && - (!(*pPut_buf_func)(pDict + dict_ofs, (int) dst_buf_size, - pPut_buf_user))) - break; - if (status != TINFL_STATUS_HAS_MORE_OUTPUT) { - result = (status == TINFL_STATUS_DONE); - break; - } - dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); - } - MZ_FREE(pDict); - *pIn_buf_size = in_buf_ofs; - return result; -} - -# ifndef MINIZ_NO_MALLOC -tinfl_decompressor *tinfl_decompressor_alloc(void) { - tinfl_decompressor *pDecomp = (tinfl_decompressor *) MZ_MALLOC( - sizeof(tinfl_decompressor)); - if (pDecomp) - tinfl_init(pDecomp); - return pDecomp; -} - -void tinfl_decompressor_free(tinfl_decompressor *pDecomp) { - MZ_FREE(pDecomp); -} -# endif - -# ifdef __cplusplus -} -# endif - -#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ diff --git a/source/kit/miniz/miniz_tinfl.h b/source/kit/miniz/miniz_tinfl.h deleted file mode 100644 index 14da110..0000000 --- a/source/kit/miniz/miniz_tinfl.h +++ /dev/null @@ -1,218 +0,0 @@ -#ifndef KIT_MINIZ_MINIZ_TINFL_H -#define KIT_MINIZ_MINIZ_TINFL_H - -#include "miniz_common.h" -/* ------------------- Low-level Decompression API Definitions */ - -#ifndef MINIZ_NO_INFLATE_APIS - -# ifdef __cplusplus -extern "C" { -# endif -/* Decompression flags used by tinfl_decompress(). */ -/* TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib - * header and ends with an adler32 checksum (it's a valid zlib - * stream). Otherwise, the input is a raw deflate stream. */ -/* TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes - * available beyond the end of the supplied input buffer. If clear, - * the input buffer contains all remaining input. */ -/* TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer - * is large enough to hold the entire decompressed stream. If clear, - * the output buffer is at least the size of the dictionary (typically - * 32KB). */ -/* TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of - * the decompressed bytes. */ -enum { - TINFL_FLAG_PARSE_ZLIB_HEADER = 1, - TINFL_FLAG_HAS_MORE_INPUT = 2, - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, - TINFL_FLAG_COMPUTE_ADLER32 = 8 -}; - -/* High level decompression functions: */ -/* tinfl_decompress_mem_to_heap() decompresses a block in memory to a - * heap block allocated via malloc(). */ -/* On entry: */ -/* pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib - * source data to decompress. */ -/* On return: */ -/* Function returns a pointer to the decompressed data, or NULL on - * failure. */ -/* *pOut_len will be set to the decompressed data's size, which could - * be larger than src_buf_len on uncompressible data. */ -/* The caller must call mz_free() on the returned block when it's no - * longer needed. */ -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, - size_t src_buf_len, - size_t *pOut_len, int flags); - -/* tinfl_decompress_mem_to_mem() decompresses a block in memory to - * another block in memory. */ -/* Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the - * number of bytes written on success. */ -# define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t) (-1)) -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, - const void *pSrc_buf, - size_t src_buf_len, int flags); - -/* tinfl_decompress_mem_to_callback() decompresses a block in memory - * to an internal 32KB buffer, and a user provided callback function - * will be called to flush the buffer. */ -/* Returns 1 on success or 0 on failure. */ -typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, - void *pUser); -int tinfl_decompress_mem_to_callback( - const void *pIn_buf, size_t *pIn_buf_size, - tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, - int flags); - -struct tinfl_decompressor_tag; -typedef struct tinfl_decompressor_tag tinfl_decompressor; - -# ifndef MINIZ_NO_MALLOC -/* Allocate the tinfl_decompressor structure in C so that */ -/* non-C language bindings to tinfl_ API don't need to worry about */ -/* structure size and allocation mechanism. */ -tinfl_decompressor *tinfl_decompressor_alloc(void); -void tinfl_decompressor_free(tinfl_decompressor *pDecomp); -# endif - -/* Max size of LZ dictionary. */ -# define TINFL_LZ_DICT_SIZE 32768 - -/* Return status. */ -typedef enum { - /* This flags indicates the inflator needs 1 or more input bytes to - make forward progress, but the caller is indicating that no more - are available. The compressed data */ - /* is probably corrupted. If you call the inflator again with more - bytes it'll try to continue processing the input but this is a - BAD sign (either the data is corrupted or you called it - incorrectly). */ - /* If you call it again with no input you'll just get - TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS again. */ - TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS = -4, - - /* This flag indicates that one or more of the input parameters was - obviously bogus. (You can try calling it again, but if you get - this error the calling code is wrong.) */ - TINFL_STATUS_BAD_PARAM = -3, - - /* This flags indicate the inflator is finished but the adler32 - check of the uncompressed data didn't match. If you call it again - it'll return TINFL_STATUS_DONE. */ - TINFL_STATUS_ADLER32_MISMATCH = -2, - - /* This flags indicate the inflator has somehow failed (bad code, - corrupted input, etc.). If you call it again without resetting - via tinfl_init() it it'll just keep on returning the same status - failure code. */ - TINFL_STATUS_FAILED = -1, - - /* Any status code less than TINFL_STATUS_DONE must indicate a - failure. */ - - /* This flag indicates the inflator has returned every byte of - uncompressed data that it can, has consumed every byte that it - needed, has successfully reached the end of the deflate stream, - and */ - /* if zlib headers and adler32 checking enabled that it has - successfully checked the uncompressed data's adler32. If you call - it again you'll just get TINFL_STATUS_DONE over and over again. - */ - TINFL_STATUS_DONE = 0, - - /* This flag indicates the inflator MUST have more input data (even - 1 byte) before it can make any more forward progress, or you need - to clear the TINFL_FLAG_HAS_MORE_INPUT */ - /* flag on the next call if you don't have any more source data. If - the source data was somehow corrupted it's also possible (but - unlikely) for the inflator to keep on demanding input to */ - /* proceed, so be sure to properly set the TINFL_FLAG_HAS_MORE_INPUT - flag. */ - TINFL_STATUS_NEEDS_MORE_INPUT = 1, - - /* This flag indicates the inflator definitely has 1 or more bytes - of uncompressed data available, but it cannot write this data - into the output buffer. */ - /* Note if the source compressed data was corrupted it's possible - for the inflator to return a lot of uncompressed data to the - caller. I've been assuming you know how much uncompressed data to - expect */ - /* (either exact or worst case) and will stop calling the inflator - and fail after receiving too much. In pure streaming scenarios - where you have no idea how many bytes to expect this may not be - possible */ - /* so I may need to add some code to address this. */ - TINFL_STATUS_HAS_MORE_OUTPUT = 2 -} tinfl_status; - -/* Initializes the decompressor to its initial state. */ -# define tinfl_init(r) \ - do { (r)->m_state = 0; } \ - MZ_MACRO_END -# define tinfl_get_adler32(r) (r)->m_check_adler32 - -/* Main low-level decompressor coroutine function. This is the only - * function actually needed for decompression. All the other functions - * are just high-level helpers for improved usability. */ -/* This is a universal API, i.e. it can be used as a building block to - * build any desired higher level decompression API. In the limit - * case, it can be called once per every byte input or output. */ -tinfl_status tinfl_decompress(tinfl_decompressor *r, - const mz_uint8 *pIn_buf_next, - size_t *pIn_buf_size, - mz_uint8 *pOut_buf_start, - mz_uint8 *pOut_buf_next, - size_t *pOut_buf_size, - const mz_uint32 decomp_flags); - -/* Internal/private bits follow. */ -enum { - TINFL_MAX_HUFF_TABLES = 3, - TINFL_MAX_HUFF_SYMBOLS_0 = 288, - TINFL_MAX_HUFF_SYMBOLS_1 = 32, - TINFL_MAX_HUFF_SYMBOLS_2 = 19, - TINFL_FAST_LOOKUP_BITS = 10, - TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS -}; - -# if MINIZ_HAS_64BIT_REGISTERS -# define TINFL_USE_64BIT_BITBUF 1 -# else -# define TINFL_USE_64BIT_BITBUF 0 -# endif - -# if TINFL_USE_64BIT_BITBUF -typedef mz_uint64 tinfl_bit_buf_t; -# define TINFL_BITBUF_SIZE (64) -# else -typedef mz_uint32 tinfl_bit_buf_t; -# define TINFL_BITBUF_SIZE (32) -# endif - -struct tinfl_decompressor_tag { - mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, - m_final, m_type, m_check_adler32, m_dist, m_counter, - m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; - tinfl_bit_buf_t m_bit_buf; - size_t m_dist_from_out_buf_start; - mz_int16 m_look_up[TINFL_MAX_HUFF_TABLES][TINFL_FAST_LOOKUP_SIZE]; - mz_int16 m_tree_0[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; - mz_int16 m_tree_1[TINFL_MAX_HUFF_SYMBOLS_1 * 2]; - mz_int16 m_tree_2[TINFL_MAX_HUFF_SYMBOLS_2 * 2]; - mz_uint8 m_code_size_0[TINFL_MAX_HUFF_SYMBOLS_0]; - mz_uint8 m_code_size_1[TINFL_MAX_HUFF_SYMBOLS_1]; - mz_uint8 m_code_size_2[TINFL_MAX_HUFF_SYMBOLS_2]; - mz_uint8 m_raw_header[4], - m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + - TINFL_MAX_HUFF_SYMBOLS_1 + 137]; -}; - -# ifdef __cplusplus -} -# endif - -#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ - -#endif diff --git a/source/kit/miniz/miniz_zip.c b/source/kit/miniz/miniz_zip.c deleted file mode 100644 index 0af4bf0..0000000 --- a/source/kit/miniz/miniz_zip.c +++ /dev/null @@ -1,5473 +0,0 @@ -/************************************************************************** - * - * Copyright 2013-2014 RAD Game Tools and Valve Software - * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC - * Copyright 2016 Martin Raiber - * All Rights Reserved. - * - * 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. - * - **************************************************************************/ -#include "miniz.h" - -#ifndef MINIZ_NO_ARCHIVE_APIS - -# ifdef __cplusplus -extern "C" { -# endif - -/* ------------------- .ZIP archive reading */ - -# ifdef MINIZ_NO_STDIO -# define MZ_FILE void * -# else -# include <stdio.h> -# include <sys/stat.h> - -# if defined(_MSC_VER) || defined(__MINGW64__) || \ - defined(__MINGW32__) - -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# ifndef __cplusplus -# define MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS \ - 0 -# endif -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include <windows.h> - -static WCHAR *mz_utf8z_to_widechar(const char *str) { - int reqChars = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); - WCHAR *wStr = (WCHAR *) malloc(reqChars * sizeof(WCHAR)); - MultiByteToWideChar(CP_UTF8, 0, str, -1, wStr, reqChars); - return wStr; -} - -static FILE *mz_fopen(const char *pFilename, const char *pMode) { - WCHAR *wFilename = mz_utf8z_to_widechar(pFilename); - WCHAR *wMode = mz_utf8z_to_widechar(pMode); - FILE *pFile = NULL; - errno_t err = _wfopen_s(&pFile, wFilename, wMode); - free(wFilename); - free(wMode); - return err ? NULL : pFile; -} - -static FILE *mz_freopen(const char *pPath, const char *pMode, - FILE *pStream) { - WCHAR *wPath = mz_utf8z_to_widechar(pPath); - WCHAR *wMode = mz_utf8z_to_widechar(pMode); - FILE *pFile = NULL; - errno_t err = _wfreopen_s(&pFile, wPath, wMode, pStream); - free(wPath); - free(wMode); - return err ? NULL : pFile; -} - -# if defined(__MINGW32__) -static int mz_stat(const char *path, struct _stat *buffer) { - WCHAR *wPath = mz_utf8z_to_widechar(path); - int res = _wstat(wPath, buffer); - free(wPath); - return res; -} -# else -static int mz_stat64(const char *path, struct __stat64 *buffer) { - WCHAR *wPath = mz_utf8z_to_widechar(path); - int res = _wstat64(wPath, buffer); - free(wPath); - return res; -} -# endif - -# ifndef MINIZ_NO_TIME -# include <sys/utime.h> -# endif -# define MZ_FOPEN mz_fopen -# define MZ_FCLOSE fclose -# define MZ_FREAD fread -# define MZ_FWRITE fwrite -# define MZ_FTELL64 _ftelli64 -# define MZ_FSEEK64 _fseeki64 -# if defined(__MINGW32__) -# define MZ_FILE_STAT_STRUCT _stat -# define MZ_FILE_STAT mz_stat -# else -# define MZ_FILE_STAT_STRUCT _stat64 -# define MZ_FILE_STAT mz_stat64 -# endif -# define MZ_FFLUSH fflush -# define MZ_FREOPEN mz_freopen -# define MZ_DELETE_FILE remove - -# elif defined(__WATCOMC__) -# ifndef MINIZ_NO_TIME -# include <sys/utime.h> -# endif -# define MZ_FOPEN(f, m) fopen(f, m) -# define MZ_FCLOSE fclose -# define MZ_FREAD fread -# define MZ_FWRITE fwrite -# define MZ_FTELL64 _ftelli64 -# define MZ_FSEEK64 _fseeki64 -# define MZ_FILE_STAT_STRUCT stat -# define MZ_FILE_STAT stat -# define MZ_FFLUSH fflush -# define MZ_FREOPEN(f, m, s) freopen(f, m, s) -# define MZ_DELETE_FILE remove - -# elif defined(__TINYC__) -# ifndef MINIZ_NO_TIME -# include <sys/utime.h> -# endif -# define MZ_FOPEN(f, m) fopen(f, m) -# define MZ_FCLOSE fclose -# define MZ_FREAD fread -# define MZ_FWRITE fwrite -# define MZ_FTELL64 ftell -# define MZ_FSEEK64 fseek -# define MZ_FILE_STAT_STRUCT stat -# define MZ_FILE_STAT stat -# define MZ_FFLUSH fflush -# define MZ_FREOPEN(f, m, s) freopen(f, m, s) -# define MZ_DELETE_FILE remove - -# elif defined(__USE_LARGEFILE64) /* gcc, clang */ -# ifndef MINIZ_NO_TIME -# include <utime.h> -# endif -# define MZ_FOPEN(f, m) fopen64(f, m) -# define MZ_FCLOSE fclose -# define MZ_FREAD fread -# define MZ_FWRITE fwrite -# define MZ_FTELL64 ftello64 -# define MZ_FSEEK64 fseeko64 -# define MZ_FILE_STAT_STRUCT stat64 -# define MZ_FILE_STAT stat64 -# define MZ_FFLUSH fflush -# define MZ_FREOPEN(p, m, s) freopen64(p, m, s) -# define MZ_DELETE_FILE remove - -# elif defined(__APPLE__) || defined(__FreeBSD__) || \ - (defined(__linux__) && defined(__x86_64__)) -# ifndef MINIZ_NO_TIME -# include <utime.h> -# endif -# define MZ_FOPEN(f, m) fopen(f, m) -# define MZ_FCLOSE fclose -# define MZ_FREAD fread -# define MZ_FWRITE fwrite -# define MZ_FTELL64 ftello -# define MZ_FSEEK64 fseeko -# define MZ_FILE_STAT_STRUCT stat -# define MZ_FILE_STAT stat -# define MZ_FFLUSH fflush -# define MZ_FREOPEN(p, m, s) freopen(p, m, s) -# define MZ_DELETE_FILE remove - -# else -# pragma message( \ - "Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.") -# ifndef MINIZ_NO_TIME -# include <utime.h> -# endif -# define MZ_FOPEN(f, m) fopen(f, m) -# define MZ_FCLOSE fclose -# define MZ_FREAD fread -# define MZ_FWRITE fwrite -# ifdef __STRICT_ANSI__ -# define MZ_FTELL64 ftell -# define MZ_FSEEK64 fseek -# else -# define MZ_FTELL64 ftello -# define MZ_FSEEK64 fseeko -# endif -# define MZ_FILE_STAT_STRUCT stat -# define MZ_FILE_STAT stat -# define MZ_FFLUSH fflush -# define MZ_FREOPEN(f, m, s) freopen(f, m, s) -# define MZ_DELETE_FILE remove -# endif /* #ifdef _MSC_VER */ -# endif /* #ifdef MINIZ_NO_STDIO */ - -# define MZ_TOLOWER(c) \ - ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) - -/* Various ZIP archive enums. To completely avoid cross platform - * compiler alignment and platform endian issues, miniz.c doesn't use - * structs for any of this stuff. */ -enum { - /* ZIP archive identifiers and record sizes */ - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, - MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, - MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, - - /* ZIP64 archive identifier and record sizes */ - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50, - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50, - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56, - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20, - MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001, - MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50, - MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24, - MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16, - - /* Central directory header record offsets */ - MZ_ZIP_CDH_SIG_OFS = 0, - MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, - MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, - MZ_ZIP_CDH_BIT_FLAG_OFS = 8, - MZ_ZIP_CDH_METHOD_OFS = 10, - MZ_ZIP_CDH_FILE_TIME_OFS = 12, - MZ_ZIP_CDH_FILE_DATE_OFS = 14, - MZ_ZIP_CDH_CRC32_OFS = 16, - MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, - MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, - MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, - MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, - MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, - MZ_ZIP_CDH_DISK_START_OFS = 34, - MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, - MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, - MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, - - /* Local directory header offsets */ - MZ_ZIP_LDH_SIG_OFS = 0, - MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, - MZ_ZIP_LDH_BIT_FLAG_OFS = 6, - MZ_ZIP_LDH_METHOD_OFS = 8, - MZ_ZIP_LDH_FILE_TIME_OFS = 10, - MZ_ZIP_LDH_FILE_DATE_OFS = 12, - MZ_ZIP_LDH_CRC32_OFS = 14, - MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, - MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, - MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, - MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, - MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3, - - /* End of central directory offsets */ - MZ_ZIP_ECDH_SIG_OFS = 0, - MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, - MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, - MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, - MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, - MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, - MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, - MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, - - /* ZIP64 End of central directory locator offsets */ - MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */ - MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */ - MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */ - MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */ - - /* ZIP64 End of central directory header offsets */ - MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */ - MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */ - MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */ - MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */ - MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */ - MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */ - MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */ - MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */ - MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */ - MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */ - MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0, - MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10, - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1, - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32, - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64, - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192, - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11 -}; - -typedef struct { - void *m_p; - size_t m_size, m_capacity; - mz_uint m_element_size; -} mz_zip_array; - -struct mz_zip_internal_state_tag { - mz_zip_array m_central_dir; - mz_zip_array m_central_dir_offsets; - mz_zip_array m_sorted_central_dir_offsets; - - /* The flags passed in when the archive is initially opened. */ - mz_uint32 m_init_flags; - - /* MZ_TRUE if the archive has a zip64 end of central directory - * headers, etc. */ - mz_bool m_zip64; - - /* MZ_TRUE if we found zip64 extended info in the central directory - * (m_zip64 will also be slammed to true too, even if we didn't find - * a zip64 end of central dir header, etc.) */ - mz_bool m_zip64_has_extended_info_fields; - - /* These fields are used by the file, FILE, memory, and memory/heap - * read/write helpers. */ - MZ_FILE *m_pFile; - mz_uint64 m_file_archive_start_ofs; - - void *m_pMem; - size_t m_mem_size; - size_t m_mem_capacity; -}; - -# define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) \ - (array_ptr)->m_element_size = element_size - -# if defined(DEBUG) || defined(_DEBUG) -static MZ_FORCEINLINE mz_uint -mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index) { - MZ_ASSERT(index < pArray->m_size); - return index; -} -# define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) \ - ((element_type *) ((array_ptr)->m_p)) \ - [mz_zip_array_range_check(array_ptr, index)] -# else -# define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) \ - ((element_type *) ((array_ptr)->m_p))[index] -# endif - -static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, - mz_uint32 element_size) { - memset(pArray, 0, sizeof(mz_zip_array)); - pArray->m_element_size = element_size; -} - -static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, - mz_zip_array *pArray) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); - memset(pArray, 0, sizeof(mz_zip_array)); -} - -static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, - mz_zip_array *pArray, - size_t min_new_capacity, - mz_uint growing) { - void *pNew_p; - size_t new_capacity = min_new_capacity; - MZ_ASSERT(pArray->m_element_size); - if (pArray->m_capacity >= min_new_capacity) - return MZ_TRUE; - if (growing) { - new_capacity = MZ_MAX(1, pArray->m_capacity); - while (new_capacity < min_new_capacity) new_capacity *= 2; - } - if (NULL == (pNew_p = pZip->m_pRealloc( - pZip->m_pAlloc_opaque, pArray->m_p, - pArray->m_element_size, new_capacity))) - return MZ_FALSE; - pArray->m_p = pNew_p; - pArray->m_capacity = new_capacity; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool -mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, - size_t new_capacity, mz_uint growing) { - if (new_capacity > pArray->m_capacity) { - if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, - growing)) - return MZ_FALSE; - } - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool -mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, - size_t new_size, mz_uint growing) { - if (new_size > pArray->m_capacity) { - if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, - growing)) - return MZ_FALSE; - } - pArray->m_size = new_size; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room( - mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) { - return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, - MZ_TRUE); -} - -static MZ_FORCEINLINE mz_bool -mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, - const void *pElements, size_t n) { - size_t orig_size = pArray->m_size; - if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) - return MZ_FALSE; - if (n > 0) - memcpy((mz_uint8 *) pArray->m_p + - orig_size * pArray->m_element_size, - pElements, n * pArray->m_element_size); - return MZ_TRUE; -} - -# ifndef MINIZ_NO_TIME -static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date) { - struct tm tm; - memset(&tm, 0, sizeof(tm)); - tm.tm_isdst = -1; - tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; - tm.tm_mon = ((dos_date >> 5) & 15) - 1; - tm.tm_mday = dos_date & 31; - tm.tm_hour = (dos_time >> 11) & 31; - tm.tm_min = (dos_time >> 5) & 63; - tm.tm_sec = (dos_time << 1) & 62; - return mktime(&tm); -} - -# ifndef MINIZ_NO_ARCHIVE_WRITING_APIS -static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, - mz_uint16 *pDOS_time, - mz_uint16 *pDOS_date) { -# ifdef _MSC_VER - struct tm tm_struct; - struct tm *tm = &tm_struct; - errno_t err = localtime_s(tm, &time); - if (err) { - *pDOS_date = 0; - *pDOS_time = 0; - return; - } -# else - struct tm *tm = localtime(&time); -# endif /* #ifdef _MSC_VER */ - - *pDOS_time = (mz_uint16) (((tm->tm_hour) << 11) + - ((tm->tm_min) << 5) + - ((tm->tm_sec) >> 1)); - *pDOS_date = (mz_uint16) (((tm->tm_year + 1900 - 1980) << 9) + - ((tm->tm_mon + 1) << 5) + tm->tm_mday); -} -# endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */ - -# ifndef MINIZ_NO_STDIO -# ifndef MINIZ_NO_ARCHIVE_WRITING_APIS -static mz_bool mz_zip_get_file_modified_time(const char *pFilename, - MZ_TIME_T *pTime) { - struct MZ_FILE_STAT_STRUCT file_stat; - - /* On Linux with x86 glibc, this call will fail on large files (I - * think >= 0x80000000 bytes) unless you compiled with - * _LARGEFILE64_SOURCE. Argh. */ - if (MZ_FILE_STAT(pFilename, &file_stat) != 0) - return MZ_FALSE; - - *pTime = file_stat.st_mtime; - - return MZ_TRUE; -} -# endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/ - -static mz_bool mz_zip_set_file_times(const char *pFilename, - MZ_TIME_T access_time, - MZ_TIME_T modified_time) { - struct utimbuf t; - - memset(&t, 0, sizeof(t)); - t.actime = access_time; - t.modtime = modified_time; - - return !utime(pFilename, &t); -} -# endif /* #ifndef MINIZ_NO_STDIO */ -# endif /* #ifndef MINIZ_NO_TIME */ - -static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, - mz_zip_error err_num) { - if (pZip) - pZip->m_last_error = err_num; - return MZ_FALSE; -} - -static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, - mz_uint flags) { - (void) flags; - if ((!pZip) || (pZip->m_pState) || - (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (!pZip->m_pAlloc) - pZip->m_pAlloc = miniz_def_alloc_func; - if (!pZip->m_pFree) - pZip->m_pFree = miniz_def_free_func; - if (!pZip->m_pRealloc) - pZip->m_pRealloc = miniz_def_realloc_func; - - pZip->m_archive_size = 0; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - pZip->m_last_error = MZ_ZIP_NO_ERROR; - - if (NULL == - (pZip->m_pState = (mz_zip_internal_state *) pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, - sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE( - &pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE( - &pZip->m_pState->m_sorted_central_dir_offsets, - sizeof(mz_uint32)); - pZip->m_pState->m_init_flags = flags; - pZip->m_pState->m_zip64 = MZ_FALSE; - pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE; - - pZip->m_zip_mode = MZ_ZIP_MODE_READING; - - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool -mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, - const mz_zip_array *pCentral_dir_offsets, - mz_uint l_index, mz_uint r_index) { - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT( - pCentral_dir_array, mz_uint8, - MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, - mz_uint32, l_index)), - *pE; - const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT( - pCentral_dir_array, mz_uint8, - MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), - r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; - pR++; - } - return (pL == pE) ? (l_len < r_len) : (l < r); -} - -# define MZ_SWAP_UINT32(a, b) \ - do { \ - mz_uint32 t = a; \ - a = b; \ - b = t; \ - } \ - MZ_MACRO_END - -/* Heap sort of lowercased filenames, used to help accelerate plain - * central directory searches by mz_zip_reader_locate_file(). (Could - * also use qsort(), but it could allocate memory.) */ -static void mz_zip_reader_sort_central_dir_offsets_by_filename( - mz_zip_archive *pZip) { - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = - &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices; - mz_uint32 start, end; - const mz_uint32 size = pZip->m_total_files; - - if (size <= 1U) - return; - - pIndices = &MZ_ZIP_ARRAY_ELEMENT( - &pState->m_sorted_central_dir_offsets, mz_uint32, 0); - - start = (size - 2U) >> 1U; - for (;;) { - mz_uint64 child, root = start; - for (;;) { - if ((child = (root << 1U) + 1U) >= size) - break; - child += (((child + 1U) < size) && - (mz_zip_reader_filename_less( - pCentral_dir, pCentral_dir_offsets, - pIndices[child], pIndices[child + 1U]))); - if (!mz_zip_reader_filename_less( - pCentral_dir, pCentral_dir_offsets, pIndices[root], - pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); - root = child; - } - if (!start) - break; - start--; - } - - end = size - 1; - while (end > 0) { - mz_uint64 child, root = 0; - MZ_SWAP_UINT32(pIndices[end], pIndices[0]); - for (;;) { - if ((child = (root << 1U) + 1U) >= end) - break; - child += (((child + 1U) < end) && - mz_zip_reader_filename_less( - pCentral_dir, pCentral_dir_offsets, - pIndices[child], pIndices[child + 1U])); - if (!mz_zip_reader_filename_less( - pCentral_dir, pCentral_dir_offsets, pIndices[root], - pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); - root = child; - } - end--; - } -} - -static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, - mz_uint32 record_sig, - mz_uint32 record_size, - mz_int64 *pOfs) { - mz_int64 cur_file_ofs; - mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; - mz_uint8 *pBuf = (mz_uint8 *) buf_u32; - - /* Basic sanity checks - reject files which are too small */ - if (pZip->m_archive_size < record_size) - return MZ_FALSE; - - /* Find the record by scanning the file from the end towards the - * beginning. */ - cur_file_ofs = MZ_MAX((mz_int64) pZip->m_archive_size - - (mz_int64) sizeof(buf_u32), - 0); - for (;;) { - int i, n = (int) MZ_MIN(sizeof(buf_u32), - pZip->m_archive_size - cur_file_ofs); - - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != - (mz_uint) n) - return MZ_FALSE; - - for (i = n - 4; i >= 0; --i) { - mz_uint s = MZ_READ_LE32(pBuf + i); - if (s == record_sig) { - if ((pZip->m_archive_size - (cur_file_ofs + i)) >= - record_size) - break; - } - } - - if (i >= 0) { - cur_file_ofs += i; - break; - } - - /* Give up if we've searched the entire file, or we've gone back - * "too far" (~64kb) */ - if ((!cur_file_ofs) || - ((pZip->m_archive_size - cur_file_ofs) >= - ((mz_uint64) (MZ_UINT16_MAX) + record_size))) - return MZ_FALSE; - - cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); - } - - *pOfs = cur_file_ofs; - return MZ_TRUE; -} - -static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, - mz_uint flags) { - mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, - num_this_disk = 0, cdir_disk_index = 0; - mz_uint64 cdir_ofs = 0; - mz_int64 cur_file_ofs = 0; - const mz_uint8 *p; - - mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; - mz_uint8 *pBuf = (mz_uint8 *) buf_u32; - mz_bool sort_central_dir = - ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); - mz_uint32 zip64_end_of_central_dir_locator_u32 - [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - - 1) / - sizeof(mz_uint32)]; - mz_uint8 *pZip64_locator = (mz_uint8 *) - zip64_end_of_central_dir_locator_u32; - - mz_uint32 zip64_end_of_central_dir_header_u32 - [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - - 1) / - sizeof(mz_uint32)]; - mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *) - zip64_end_of_central_dir_header_u32; - - mz_uint64 zip64_end_of_central_dir_ofs = 0; - - /* Basic sanity checks - reject files which are too small, and check - * the first 4 bytes of the file to make sure a local header is - * there. */ - if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - - if (!mz_zip_reader_locate_header_sig( - pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) - return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR); - - /* Read and verify the end of central directory record. */ - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - - if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) - return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - - if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) { - if (pZip->m_pRead(pZip->m_pIO_opaque, - cur_file_ofs - - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, - pZip64_locator, - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) { - if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) { - zip64_end_of_central_dir_ofs = MZ_READ_LE64( - pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS); - if (zip64_end_of_central_dir_ofs > - (pZip->m_archive_size - - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) - return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - - if (pZip->m_pRead(pZip->m_pIO_opaque, - zip64_end_of_central_dir_ofs, - pZip64_end_of_central_dir, - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) { - if (MZ_READ_LE32(pZip64_end_of_central_dir + - MZ_ZIP64_ECDH_SIG_OFS) == - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) { - pZip->m_pState->m_zip64 = MZ_TRUE; - } - } - } - } - } - - pZip->m_total_files = MZ_READ_LE16( - pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS); - cdir_entries_on_this_disk = MZ_READ_LE16( - pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); - num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); - cdir_disk_index = MZ_READ_LE16(pBuf + - MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); - cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS); - cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); - - if (pZip->m_pState->m_zip64) { - mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32( - pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS); - mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64( - pZip64_end_of_central_dir + - MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS); - mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64( - pZip64_end_of_central_dir + - MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); - mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64( - pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS); - mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64( - pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS); - - if (zip64_size_of_end_of_central_dir_record < - (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - if (zip64_total_num_of_disks != 1U) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - - /* Check for miniz's practical limits */ - if (zip64_cdir_total_entries > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - - pZip->m_total_files = (mz_uint32) zip64_cdir_total_entries; - - if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - - cdir_entries_on_this_disk = (mz_uint32) - zip64_cdir_total_entries_on_this_disk; - - /* Check for miniz's current practical limits (sorry, this should - * be enough for millions of files) */ - if (zip64_size_of_central_directory > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - - cdir_size = (mz_uint32) zip64_size_of_central_directory; - - num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + - MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS); - - cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + - MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS); - - cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + - MZ_ZIP64_ECDH_CDIR_OFS_OFS); - } - - if (pZip->m_total_files != cdir_entries_on_this_disk) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - - if (((num_this_disk | cdir_disk_index) != 0) && - ((num_this_disk != 1) || (cdir_disk_index != 1))) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - - if (cdir_size < (mz_uint64) pZip->m_total_files * - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - if ((cdir_ofs + (mz_uint64) cdir_size) > pZip->m_archive_size) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - pZip->m_central_directory_file_ofs = cdir_ofs; - - if (pZip->m_total_files) { - mz_uint i, n; - /* Read the entire central directory into a heap block, and - * allocate another heap block to hold the unsorted central dir - * file record offsets, and possibly another to hold the sorted - * indices. */ - if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, - cdir_size, MZ_FALSE)) || - (!mz_zip_array_resize(pZip, - &pZip->m_pState->m_central_dir_offsets, - pZip->m_total_files, MZ_FALSE))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - if (sort_central_dir) { - if (!mz_zip_array_resize( - pZip, &pZip->m_pState->m_sorted_central_dir_offsets, - pZip->m_total_files, MZ_FALSE)) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, - pZip->m_pState->m_central_dir.m_p, - cdir_size) != cdir_size) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - - /* Now create an index into the central directory file records, do - * some basic sanity checking on each record */ - p = (const mz_uint8 *) pZip->m_pState->m_central_dir.m_p; - for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { - mz_uint total_header_size, disk_index, bit_flags, filename_size, - ext_data_size; - mz_uint64 comp_size, decomp_size, local_header_ofs; - - if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || - (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - MZ_ZIP_ARRAY_ELEMENT( - &pZip->m_pState->m_central_dir_offsets, mz_uint32, - i) = (mz_uint32) (p - (const mz_uint8 *) pZip->m_pState - ->m_central_dir.m_p); - - if (sort_central_dir) - MZ_ZIP_ARRAY_ELEMENT( - &pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, - i) = i; - - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - decomp_size = MZ_READ_LE32(p + - MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - local_header_ofs = MZ_READ_LE32(p + - MZ_ZIP_CDH_LOCAL_HEADER_OFS); - filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); - - if ((!pZip->m_pState->m_zip64_has_extended_info_fields) && - (ext_data_size) && - (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == - MZ_UINT32_MAX)) { - /* Attempt to find zip64 extended information field in the - * entry's extra data */ - mz_uint32 extra_size_remaining = ext_data_size; - - if (extra_size_remaining) { - const mz_uint8 *pExtra_data; - void *buf = NULL; - - if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + - ext_data_size > - n) { - buf = MZ_MALLOC(ext_data_size); - if (buf == NULL) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - if (pZip->m_pRead(pZip->m_pIO_opaque, - cdir_ofs + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - filename_size, - buf, ext_data_size) != ext_data_size) { - MZ_FREE(buf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - } - - pExtra_data = (mz_uint8 *) buf; - } else { - pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - filename_size; - } - - do { - mz_uint32 field_id; - mz_uint32 field_data_size; - - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) { - MZ_FREE(buf); - return mz_zip_set_error( - pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } - - field_id = MZ_READ_LE16(pExtra_data); - field_data_size = MZ_READ_LE16(pExtra_data + - sizeof(mz_uint16)); - - if ((field_data_size + sizeof(mz_uint16) * 2) > - extra_size_remaining) { - MZ_FREE(buf); - return mz_zip_set_error( - pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } - - if (field_id == - MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { - /* Ok, the archive didn't have any zip64 headers but it - * uses a zip64 extended information field so mark it as - * zip64 anyway (this can occur with infozip's zip util - * when it reads compresses files from stdin). */ - pZip->m_pState->m_zip64 = MZ_TRUE; - pZip->m_pState->m_zip64_has_extended_info_fields = - MZ_TRUE; - break; - } - - pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; - extra_size_remaining = extra_size_remaining - - sizeof(mz_uint16) * 2 - - field_data_size; - } while (extra_size_remaining); - - MZ_FREE(buf); - } - } - - /* I've seen archives that aren't marked as zip64 that uses - * zip64 ext data, argh */ - if ((comp_size != MZ_UINT32_MAX) && - (decomp_size != MZ_UINT32_MAX)) { - if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && - (decomp_size != comp_size)) || - (decomp_size && !comp_size)) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } - - disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); - if ((disk_index == MZ_UINT16_MAX) || - ((disk_index != num_this_disk) && (disk_index != 1))) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - - if (comp_size != MZ_UINT32_MAX) { - if (((mz_uint64) MZ_READ_LE32(p + - MZ_ZIP_CDH_LOCAL_HEADER_OFS) + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > - pZip->m_archive_size) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } - - bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - if (bit_flags & - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); - - if ((total_header_size = - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + - MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + - MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - n -= total_header_size; - p += total_header_size; - } - } - - if (sort_central_dir) - mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); - - return MZ_TRUE; -} - -void mz_zip_zero_struct(mz_zip_archive *pZip) { - if (pZip) - MZ_CLEAR_PTR(pZip); -} - -static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, - mz_bool set_last_error) { - mz_bool status = MZ_TRUE; - - if (!pZip) - return MZ_FALSE; - - if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || - (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) { - if (set_last_error) - pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER; - - return MZ_FALSE; - } - - if (pZip->m_pState) { - mz_zip_internal_state *pState = pZip->m_pState; - pZip->m_pState = NULL; - - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -# ifndef MINIZ_NO_STDIO - if (pState->m_pFile) { - if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) { - if (MZ_FCLOSE(pState->m_pFile) == EOF) { - if (set_last_error) - pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED; - status = MZ_FALSE; - } - } - pState->m_pFile = NULL; - } -# endif /* #ifndef MINIZ_NO_STDIO */ - - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - } - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - - return status; -} - -mz_bool mz_zip_reader_end(mz_zip_archive *pZip) { - return mz_zip_reader_end_internal(pZip, MZ_TRUE); -} -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, - mz_uint flags) { - if ((!pZip) || (!pZip->m_pRead)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - - pZip->m_zip_type = MZ_ZIP_TYPE_USER; - pZip->m_archive_size = size; - - if (!mz_zip_reader_read_central_dir(pZip, flags)) { - mz_zip_reader_end_internal(pZip, MZ_FALSE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, - void *pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *) pOpaque; - size_t s = (file_ofs >= pZip->m_archive_size) - ? 0 - : (size_t) MZ_MIN(pZip->m_archive_size - file_ofs, - n); - memcpy(pBuf, (const mz_uint8 *) pZip->m_pState->m_pMem + file_ofs, - s); - return s; -} - -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, - size_t size, mz_uint flags) { - if (!pMem) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - - pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY; - pZip->m_archive_size = size; - pZip->m_pRead = mz_zip_mem_read_func; - pZip->m_pIO_opaque = pZip; - pZip->m_pNeeds_keepalive = NULL; - -# ifdef __cplusplus - pZip->m_pState->m_pMem = const_cast<void *>(pMem); -# else - pZip->m_pState->m_pMem = (void *) pMem; -# endif - - pZip->m_pState->m_mem_size = size; - - if (!mz_zip_reader_read_central_dir(pZip, flags)) { - mz_zip_reader_end_internal(pZip, MZ_FALSE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -# ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, - void *pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *) pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - - file_ofs += pZip->m_pState->m_file_archive_start_ofs; - - if (((mz_int64) file_ofs < 0) || - (((cur_ofs != (mz_int64) file_ofs)) && - (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64) file_ofs, - SEEK_SET)))) - return 0; - - return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); -} - -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, - const char *pFilename, - mz_uint32 flags) { - return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0); -} - -mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, - const char *pFilename, - mz_uint flags, - mz_uint64 file_start_ofs, - mz_uint64 archive_size) { - mz_uint64 file_size; - MZ_FILE *pFile; - - if ((!pZip) || (!pFilename) || - ((archive_size) && - (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pFile = MZ_FOPEN(pFilename, "rb"); - if (!pFile) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); - - file_size = archive_size; - if (!file_size) { - if (MZ_FSEEK64(pFile, 0, SEEK_END)) { - MZ_FCLOSE(pFile); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); - } - - file_size = MZ_FTELL64(pFile); - } - - /* TODO: Better sanity check archive_size and the # of actual - * remaining bytes */ - - if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) { - MZ_FCLOSE(pFile); - return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - } - - if (!mz_zip_reader_init_internal(pZip, flags)) { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - - pZip->m_zip_type = MZ_ZIP_TYPE_FILE; - pZip->m_pRead = mz_zip_file_read_func; - pZip->m_pIO_opaque = pZip; - pZip->m_pState->m_pFile = pFile; - pZip->m_archive_size = file_size; - pZip->m_pState->m_file_archive_start_ofs = file_start_ofs; - - if (!mz_zip_reader_read_central_dir(pZip, flags)) { - mz_zip_reader_end_internal(pZip, MZ_FALSE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, - mz_uint64 archive_size, - mz_uint flags) { - mz_uint64 cur_file_ofs; - - if ((!pZip) || (!pFile)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); - - cur_file_ofs = MZ_FTELL64(pFile); - - if (!archive_size) { - if (MZ_FSEEK64(pFile, 0, SEEK_END)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); - - archive_size = MZ_FTELL64(pFile) - cur_file_ofs; - - if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); - } - - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - - pZip->m_zip_type = MZ_ZIP_TYPE_CFILE; - pZip->m_pRead = mz_zip_file_read_func; - - pZip->m_pIO_opaque = pZip; - pZip->m_pState->m_pFile = pFile; - pZip->m_archive_size = archive_size; - pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs; - - if (!mz_zip_reader_read_central_dir(pZip, flags)) { - mz_zip_reader_end_internal(pZip, MZ_FALSE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -# endif /* #ifndef MINIZ_NO_STDIO */ - -static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh( - mz_zip_archive *pZip, mz_uint file_index) { - if ((!pZip) || (!pZip->m_pState) || - (file_index >= pZip->m_total_files)) - return NULL; - return &MZ_ZIP_ARRAY_ELEMENT( - &pZip->m_pState->m_central_dir, mz_uint8, - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, - mz_uint32, file_index)); -} - -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, - mz_uint file_index) { - mz_uint m_bit_flag; - const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - return MZ_FALSE; - } - - m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - return (m_bit_flag & - (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != - 0; -} - -mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, - mz_uint file_index) { - mz_uint bit_flag; - mz_uint method; - - const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - return MZ_FALSE; - } - - method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); - bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - - if ((method != 0) && (method != MZ_DEFLATED)) { - mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); - return MZ_FALSE; - } - - if (bit_flag & - (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) { - mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); - return MZ_FALSE; - } - - if (bit_flag & - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG) { - mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, - mz_uint file_index) { - mz_uint filename_len, attribute_mapping_id, external_attr; - const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - return MZ_FALSE; - } - - filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_len) { - if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == - '/') - return MZ_TRUE; - } - - /* Bugfix: This code was also checking if the internal attribute was - * non-zero, which wasn't correct. */ - /* Most/all zip writers (hopefully) set DOS file/directory - * attributes in the low 16-bits, so check for the DOS directory - * flag and ignore the source OS ID in the created by field. */ - /* FIXME: Remove this check? Is it necessary - we already check the - * filename. */ - attribute_mapping_id = MZ_READ_LE16( - p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> - 8; - (void) attribute_mapping_id; - - external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0) { - return MZ_TRUE; - } - - return MZ_FALSE; -} - -static mz_bool mz_zip_file_stat_internal( - mz_zip_archive *pZip, mz_uint file_index, - const mz_uint8 *pCentral_dir_header, - mz_zip_archive_file_stat *pStat, - mz_bool *pFound_zip64_extra_data) { - mz_uint n; - const mz_uint8 *p = pCentral_dir_header; - - if (pFound_zip64_extra_data) - *pFound_zip64_extra_data = MZ_FALSE; - - if ((!p) || (!pStat)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - /* Extract fields from the central directory record. */ - pStat->m_file_index = file_index; - pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT( - &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); - pStat->m_version_made_by = MZ_READ_LE16( - p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); - pStat->m_version_needed = MZ_READ_LE16( - p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); - pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); -# ifndef MINIZ_NO_TIME - pStat->m_time = mz_zip_dos_to_time_t( - MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), - MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); -# endif - pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); - pStat->m_comp_size = MZ_READ_LE32(p + - MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - pStat->m_uncomp_size = MZ_READ_LE32( - p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - pStat->m_internal_attr = MZ_READ_LE16(p + - MZ_ZIP_CDH_INTERNAL_ATTR_OFS); - pStat->m_external_attr = MZ_READ_LE32(p + - MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - pStat->m_local_header_ofs = MZ_READ_LE32( - p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - - /* Copy as much of the filename and comment as possible. */ - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); - memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); - pStat->m_filename[n] = '\0'; - - n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); - n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); - pStat->m_comment_size = n; - memcpy(pStat->m_comment, - p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + - MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), - n); - pStat->m_comment[n] = '\0'; - - /* Set some flags for convienance */ - pStat->m_is_directory = mz_zip_reader_is_file_a_directory( - pZip, file_index); - pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, - file_index); - pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, - file_index); - - /* See if we need to read any zip64 extended information fields. */ - /* Confusingly, these zip64 fields can be present even on non-zip64 - * archives (Debian zip on a huge files from stdin piped to stdout - * creates them). */ - if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), - pStat->m_local_header_ofs) == MZ_UINT32_MAX) { - /* Attempt to find zip64 extended information field in the entry's - * extra data */ - mz_uint32 extra_size_remaining = MZ_READ_LE16( - p + MZ_ZIP_CDH_EXTRA_LEN_OFS); - - if (extra_size_remaining) { - const mz_uint8 *pExtra_data = - p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - - do { - mz_uint32 field_id; - mz_uint32 field_data_size; - - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - field_id = MZ_READ_LE16(pExtra_data); - field_data_size = MZ_READ_LE16(pExtra_data + - sizeof(mz_uint16)); - - if ((field_data_size + sizeof(mz_uint16) * 2) > - extra_size_remaining) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - if (field_id == - MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { - const mz_uint8 *pField_data = pExtra_data + - sizeof(mz_uint16) * 2; - mz_uint32 field_data_remaining = field_data_size; - - if (pFound_zip64_extra_data) - *pFound_zip64_extra_data = MZ_TRUE; - - if (pStat->m_uncomp_size == MZ_UINT32_MAX) { - if (field_data_remaining < sizeof(mz_uint64)) - return mz_zip_set_error( - pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - pStat->m_uncomp_size = MZ_READ_LE64(pField_data); - pField_data += sizeof(mz_uint64); - field_data_remaining -= sizeof(mz_uint64); - } - - if (pStat->m_comp_size == MZ_UINT32_MAX) { - if (field_data_remaining < sizeof(mz_uint64)) - return mz_zip_set_error( - pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - pStat->m_comp_size = MZ_READ_LE64(pField_data); - pField_data += sizeof(mz_uint64); - field_data_remaining -= sizeof(mz_uint64); - } - - if (pStat->m_local_header_ofs == MZ_UINT32_MAX) { - if (field_data_remaining < sizeof(mz_uint64)) - return mz_zip_set_error( - pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - pStat->m_local_header_ofs = MZ_READ_LE64(pField_data); - pField_data += sizeof(mz_uint64); - field_data_remaining -= sizeof(mz_uint64); - } - - break; - } - - pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; - extra_size_remaining = extra_size_remaining - - sizeof(mz_uint16) * 2 - - field_data_size; - } while (extra_size_remaining); - } - } - - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, - const char *pB, - mz_uint len, - mz_uint flags) { - mz_uint i; - if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) - return 0 == memcmp(pA, pB, len); - for (i = 0; i < len; ++i) - if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) - return MZ_FALSE; - return MZ_TRUE; -} - -static MZ_FORCEINLINE int mz_zip_filename_compare( - const mz_zip_array *pCentral_dir_array, - const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, - const char *pR, mz_uint r_len) { - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT( - pCentral_dir_array, mz_uint8, - MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, - mz_uint32, l_index)), - *pE; - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; - pR++; - } - return (pL == pE) ? (int) (l_len - r_len) : (l - r); -} - -static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, - const char *pFilename, - mz_uint32 *pIndex) { - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = - &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT( - &pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const mz_uint32 size = pZip->m_total_files; - const mz_uint filename_len = (mz_uint) strlen(pFilename); - - if (pIndex) - *pIndex = 0; - - if (size) { - /* yes I could use uint32_t's, but then we would have to add some - * special case checks in the loop, argh, and */ - /* honestly the major expense here on 32-bit CPU's will still be - * the filename compare */ - mz_int64 l = 0, h = (mz_int64) size - 1; - - while (l <= h) { - mz_int64 m = l + ((h - l) >> 1); - mz_uint32 file_index = pIndices[(mz_uint32) m]; - - int comp = mz_zip_filename_compare( - pCentral_dir, pCentral_dir_offsets, file_index, pFilename, - filename_len); - if (!comp) { - if (pIndex) - *pIndex = file_index; - return MZ_TRUE; - } else if (comp < 0) - l = m + 1; - else - h = m - 1; - } - } - - return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND); -} - -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, - const char *pComment, mz_uint flags) { - mz_uint32 index; - if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, - &index)) - return -1; - else - return (int) index; -} - -mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, - const char *pName, - const char *pComment, - mz_uint flags, - mz_uint32 *pIndex) { - mz_uint file_index; - size_t name_len, comment_len; - - if (pIndex) - *pIndex = 0; - - if ((!pZip) || (!pZip->m_pState) || (!pName)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - /* See if we can use a binary search */ - if (((pZip->m_pState->m_init_flags & - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) && - (pZip->m_zip_mode == MZ_ZIP_MODE_READING) && - ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | - MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && - (!pComment) && - (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) { - return mz_zip_locate_file_binary_search(pZip, pName, pIndex); - } - - /* Locate the entry by scanning the entire central directory */ - name_len = strlen(pName); - if (name_len > MZ_UINT16_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - comment_len = pComment ? strlen(pComment) : 0; - if (comment_len > MZ_UINT16_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - for (file_index = 0; file_index < pZip->m_total_files; - file_index++) { - const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT( - &pZip->m_pState->m_central_dir, mz_uint8, - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, - mz_uint32, file_index)); - mz_uint filename_len = MZ_READ_LE16(pHeader + - MZ_ZIP_CDH_FILENAME_LEN_OFS); - const char *pFilename = (const char *) pHeader + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - if (filename_len < name_len) - continue; - if (comment_len) { - mz_uint file_extra_len = MZ_READ_LE16(pHeader + - MZ_ZIP_CDH_EXTRA_LEN_OFS), - file_comment_len = MZ_READ_LE16( - pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); - const char *pFile_comment = pFilename + filename_len + - file_extra_len; - if ((file_comment_len != comment_len) || - (!mz_zip_string_equal(pComment, pFile_comment, - file_comment_len, flags))) - continue; - } - if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) { - int ofs = filename_len - 1; - do { - if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || - (pFilename[ofs] == ':')) - break; - } while (--ofs >= 0); - ofs++; - pFilename += ofs; - filename_len -= ofs; - } - if ((filename_len == name_len) && - (mz_zip_string_equal(pName, pFilename, filename_len, - flags))) { - if (pIndex) - *pIndex = file_index; - return MZ_TRUE; - } - } - - return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND); -} - -static mz_bool mz_zip_reader_extract_to_mem_no_alloc1( - mz_zip_archive *pZip, mz_uint file_index, void *pBuf, - size_t buf_size, mz_uint flags, void *pUser_read_buf, - size_t user_read_buf_size, const mz_zip_archive_file_stat *st) { - int status = TINFL_STATUS_DONE; - mz_uint64 needed_size, cur_file_ofs, comp_remaining, - out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, - read_buf_avail; - mz_zip_archive_file_stat file_stat; - void *pRead_buf; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - sizeof(mz_uint32) - 1) / - sizeof(mz_uint32)]; - mz_uint8 *pLocal_header = (mz_uint8 *) local_header_u32; - tinfl_decompressor inflator; - - if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || - ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (st) { - file_stat = *st; - } else if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - /* A directory or zero length file */ - if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) - return MZ_TRUE; - - /* Encryption and patch files are not supported. */ - if (file_stat.m_bit_flag & - (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); - - /* This function only supports decompressing stored and deflate. */ - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && - (file_stat.m_method != 0) && - (file_stat.m_method != MZ_DEFLATED)) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); - - /* Ensure supplied output buffer is large enough. */ - needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - ? file_stat.m_comp_size - : file_stat.m_uncomp_size; - if (buf_size < needed_size) - return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL); - - /* Read and parse the local directory entry. */ - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - cur_file_ofs += - (mz_uint64) (MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + - MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + - MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || - (!file_stat.m_method)) { - /* The file is stored or the caller has requested the compressed - * data. */ - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, - (size_t) needed_size) != needed_size) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0) { - if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *) pBuf, - (size_t) file_stat.m_uncomp_size) != - file_stat.m_crc32) - return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); - } -# endif - - return MZ_TRUE; - } - - /* Decompress the file either directly from memory or from a file - * input buffer. */ - tinfl_init(&inflator); - - if (pZip->m_pState->m_pMem) { - /* Read directly from the archive in memory. */ - pRead_buf = (mz_uint8 *) pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } else if (pUser_read_buf) { - /* Use a user provided read buffer. */ - if (!user_read_buf_size) - return MZ_FALSE; - pRead_buf = (mz_uint8 *) pUser_read_buf; - read_buf_size = user_read_buf_size; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } else { - /* Temporarily allocate a read buffer. */ - read_buf_size = MZ_MIN(file_stat.m_comp_size, - (mz_uint64) MZ_ZIP_MAX_IO_BUF_SIZE); - if (((sizeof(size_t) == sizeof(mz_uint32))) && - (read_buf_size > 0x7FFFFFFF)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, - (size_t) read_buf_size))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - do { - /* The size_t cast here should be OK because we've verified that - * the output buffer is >= file_stat.m_uncomp_size above */ - size_t in_buf_size, - out_buf_size = (size_t) (file_stat.m_uncomp_size - - out_buf_ofs); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, - (size_t) read_buf_avail) != read_buf_avail) { - status = TINFL_STATUS_FAILED; - mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - in_buf_size = (size_t) read_buf_avail; - status = tinfl_decompress( - &inflator, (mz_uint8 *) pRead_buf + read_buf_ofs, - &in_buf_size, (mz_uint8 *) pBuf, - (mz_uint8 *) pBuf + out_buf_ofs, &out_buf_size, - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | - (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - out_buf_ofs += out_buf_size; - } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); - - if (status == TINFL_STATUS_DONE) { - /* Make sure the entire file was decompressed, and check its CRC. - */ - if (out_buf_ofs != file_stat.m_uncomp_size) { - mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); - status = TINFL_STATUS_FAILED; - } -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *) pBuf, - (size_t) file_stat.m_uncomp_size) != - file_stat.m_crc32) { - mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED); - status = TINFL_STATUS_FAILED; - } -# endif - } - - if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_to_mem_no_alloc( - mz_zip_archive *pZip, mz_uint file_index, void *pBuf, - size_t buf_size, mz_uint flags, void *pUser_read_buf, - size_t user_read_buf_size) { - return mz_zip_reader_extract_to_mem_no_alloc1( - pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, - user_read_buf_size, NULL); -} - -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc( - mz_zip_archive *pZip, const char *pFilename, void *pBuf, - size_t buf_size, mz_uint flags, void *pUser_read_buf, - size_t user_read_buf_size) { - mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, - &file_index)) - return MZ_FALSE; - return mz_zip_reader_extract_to_mem_no_alloc1( - pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, - user_read_buf_size, NULL); -} - -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, - mz_uint file_index, void *pBuf, - size_t buf_size, mz_uint flags) { - return mz_zip_reader_extract_to_mem_no_alloc1( - pZip, file_index, pBuf, buf_size, flags, NULL, 0, NULL); -} - -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, - const char *pFilename, - void *pBuf, size_t buf_size, - mz_uint flags) { - return mz_zip_reader_extract_file_to_mem_no_alloc( - pZip, pFilename, pBuf, buf_size, flags, NULL, 0); -} - -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, - mz_uint file_index, size_t *pSize, - mz_uint flags) { - mz_zip_archive_file_stat file_stat; - mz_uint64 alloc_size; - void *pBuf; - - if (pSize) - *pSize = 0; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return NULL; - - alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - ? file_stat.m_comp_size - : file_stat.m_uncomp_size; - if (((sizeof(size_t) == sizeof(mz_uint32))) && - (alloc_size > 0x7FFFFFFF)) { - mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - return NULL; - } - - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, - (size_t) alloc_size))) { - mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - return NULL; - } - - if (!mz_zip_reader_extract_to_mem_no_alloc1( - pZip, file_index, pBuf, (size_t) alloc_size, flags, NULL, 0, - &file_stat)) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return NULL; - } - - if (pSize) - *pSize = (size_t) alloc_size; - return pBuf; -} - -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, - const char *pFilename, - size_t *pSize, - mz_uint flags) { - mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, - &file_index)) { - if (pSize) - *pSize = 0; - return MZ_FALSE; - } - return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, - flags); -} - -mz_bool mz_zip_reader_extract_to_callback( - mz_zip_archive *pZip, mz_uint file_index, - mz_file_write_func pCallback, void *pOpaque, mz_uint flags) { - int status = TINFL_STATUS_DONE; -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - mz_uint file_crc32 = MZ_CRC32_INIT; -# endif - mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, - comp_remaining, out_buf_ofs = 0, - cur_file_ofs; - mz_zip_archive_file_stat file_stat; - void *pRead_buf = NULL; - void *pWrite_buf = NULL; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - sizeof(mz_uint32) - 1) / - sizeof(mz_uint32)]; - mz_uint8 *pLocal_header = (mz_uint8 *) local_header_u32; - - if ((!pZip) || (!pZip->m_pState) || (!pCallback) || - (!pZip->m_pRead)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - /* A directory or zero length file */ - if ((file_stat.m_is_directory) || (!file_stat.m_comp_size)) - return MZ_TRUE; - - /* Encryption and patch files are not supported. */ - if (file_stat.m_bit_flag & - (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); - - /* This function only supports decompressing stored and deflate. */ - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && - (file_stat.m_method != 0) && - (file_stat.m_method != MZ_DEFLATED)) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); - - /* Read and do some minimal validation of the local directory entry - * (this doesn't crack the zip64 stuff, which we already have from - * the central dir) */ - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - cur_file_ofs += - (mz_uint64) (MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + - MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + - MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - /* Decompress the file either directly from memory or from a file - * input buffer. */ - if (pZip->m_pState->m_pMem) { - pRead_buf = (mz_uint8 *) pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } else { - read_buf_size = MZ_MIN(file_stat.m_comp_size, - (mz_uint64) MZ_ZIP_MAX_IO_BUF_SIZE); - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, - (size_t) read_buf_size))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || - (!file_stat.m_method)) { - /* The file is stored or the caller has requested the compressed - * data. */ - if (pZip->m_pState->m_pMem) { - if (((sizeof(size_t) == sizeof(mz_uint32))) && - (file_stat.m_comp_size > MZ_UINT32_MAX)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, - (size_t) file_stat.m_comp_size) != - file_stat.m_comp_size) { - mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); - status = TINFL_STATUS_FAILED; - } else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - file_crc32 = (mz_uint32) mz_crc32( - file_crc32, (const mz_uint8 *) pRead_buf, - (size_t) file_stat.m_comp_size); -# endif - } - - cur_file_ofs += file_stat.m_comp_size; - out_buf_ofs += file_stat.m_comp_size; - comp_remaining = 0; - } else { - while (comp_remaining) { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, - (size_t) read_buf_avail) != - read_buf_avail) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - status = TINFL_STATUS_FAILED; - break; - } - -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { - file_crc32 = (mz_uint32) mz_crc32( - file_crc32, (const mz_uint8 *) pRead_buf, - (size_t) read_buf_avail); - } -# endif - - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, - (size_t) read_buf_avail) != read_buf_avail) { - mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); - status = TINFL_STATUS_FAILED; - break; - } - - cur_file_ofs += read_buf_avail; - out_buf_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - } - } - } else { - tinfl_decompressor inflator; - tinfl_init(&inflator); - - if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, - TINFL_LZ_DICT_SIZE))) { - mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - status = TINFL_STATUS_FAILED; - } else { - do { - mz_uint8 *pWrite_buf_cur = (mz_uint8 *) pWrite_buf + - (out_buf_ofs & - (TINFL_LZ_DICT_SIZE - 1)); - size_t in_buf_size, - out_buf_size = TINFL_LZ_DICT_SIZE - - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, - pRead_buf, (size_t) read_buf_avail) != - read_buf_avail) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - - in_buf_size = (size_t) read_buf_avail; - status = tinfl_decompress( - &inflator, (const mz_uint8 *) pRead_buf + read_buf_ofs, - &in_buf_size, (mz_uint8 *) pWrite_buf, pWrite_buf_cur, - &out_buf_size, - comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - - if (out_buf_size) { - if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, - out_buf_size) != out_buf_size) { - mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED); - status = TINFL_STATUS_FAILED; - break; - } - -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - file_crc32 = (mz_uint32) mz_crc32( - file_crc32, pWrite_buf_cur, out_buf_size); -# endif - if ((out_buf_ofs += out_buf_size) > - file_stat.m_uncomp_size) { - mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); - status = TINFL_STATUS_FAILED; - break; - } - } - } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || - (status == TINFL_STATUS_HAS_MORE_OUTPUT)); - } - } - - if ((status == TINFL_STATUS_DONE) && - (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) { - /* Make sure the entire file was decompressed, and check its CRC. - */ - if (out_buf_ofs != file_stat.m_uncomp_size) { - mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); - status = TINFL_STATUS_FAILED; - } -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - else if (file_crc32 != file_stat.m_crc32) { - mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED); - status = TINFL_STATUS_FAILED; - } -# endif - } - - if (!pZip->m_pState->m_pMem) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - - if (pWrite_buf) - pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_file_to_callback( - mz_zip_archive *pZip, const char *pFilename, - mz_file_write_func pCallback, void *pOpaque, mz_uint flags) { - mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, - &file_index)) - return MZ_FALSE; - - return mz_zip_reader_extract_to_callback(pZip, file_index, - pCallback, pOpaque, flags); -} - -mz_zip_reader_extract_iter_state *mz_zip_reader_extract_iter_new( - mz_zip_archive *pZip, mz_uint file_index, mz_uint flags) { - mz_zip_reader_extract_iter_state *pState; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - sizeof(mz_uint32) - 1) / - sizeof(mz_uint32)]; - mz_uint8 *pLocal_header = (mz_uint8 *) local_header_u32; - - /* Argument sanity check */ - if ((!pZip) || (!pZip->m_pState)) - return NULL; - - /* Allocate an iterator status structure */ - pState = (mz_zip_reader_extract_iter_state *) pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, - sizeof(mz_zip_reader_extract_iter_state)); - if (!pState) { - mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - return NULL; - } - - /* Fetch file details */ - if (!mz_zip_reader_file_stat(pZip, file_index, - &pState->file_stat)) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - - /* Encryption and patch files are not supported. */ - if (pState->file_stat.m_bit_flag & - (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | - MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) { - mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - - /* This function only supports decompressing stored and deflate. */ - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && - (pState->file_stat.m_method != 0) && - (pState->file_stat.m_method != MZ_DEFLATED)) { - mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - - /* Init state - save args */ - pState->pZip = pZip; - pState->flags = flags; - - /* Init state - reset variables to defaults */ - pState->status = TINFL_STATUS_DONE; -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - pState->file_crc32 = MZ_CRC32_INIT; -# endif - pState->read_buf_ofs = 0; - pState->out_buf_ofs = 0; - pState->pRead_buf = NULL; - pState->pWrite_buf = NULL; - pState->out_blk_remain = 0; - - /* Read and parse the local directory entry. */ - pState->cur_file_ofs = pState->file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, - pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - - pState->cur_file_ofs += - (mz_uint64) (MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + - MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + - MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > - pZip->m_archive_size) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - - /* Decompress the file either directly from memory or from a file - * input buffer. */ - if (pZip->m_pState->m_pMem) { - pState->pRead_buf = (mz_uint8 *) pZip->m_pState->m_pMem + - pState->cur_file_ofs; - pState->read_buf_size = pState->read_buf_avail = - pState->file_stat.m_comp_size; - pState->comp_remaining = pState->file_stat.m_comp_size; - } else { - if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || - (!pState->file_stat.m_method))) { - /* Decompression required, therefore intermediate read buffer - * required */ - pState->read_buf_size = MZ_MIN( - pState->file_stat.m_comp_size, - (mz_uint64) MZ_ZIP_MAX_IO_BUF_SIZE); - if (NULL == (pState->pRead_buf = pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, - (size_t) pState->read_buf_size))) { - mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - } else { - /* Decompression not required - we will be reading directly into - * user buffer, no temp buf required */ - pState->read_buf_size = 0; - } - pState->read_buf_avail = 0; - pState->comp_remaining = pState->file_stat.m_comp_size; - } - - if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || - (!pState->file_stat.m_method))) { - /* Decompression required, init decompressor */ - tinfl_init(&pState->inflator); - - /* Allocate write buffer */ - if (NULL == (pState->pWrite_buf = pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) { - mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - if (pState->pRead_buf) - pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf); - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - return NULL; - } - } - - return pState; -} - -mz_zip_reader_extract_iter_state *mz_zip_reader_extract_file_iter_new( - mz_zip_archive *pZip, const char *pFilename, mz_uint flags) { - mz_uint32 file_index; - - /* Locate file index by name */ - if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, - &file_index)) - return NULL; - - /* Construct iterator */ - return mz_zip_reader_extract_iter_new(pZip, file_index, flags); -} - -size_t mz_zip_reader_extract_iter_read( - mz_zip_reader_extract_iter_state *pState, void *pvBuf, - size_t buf_size) { - size_t copied_to_caller = 0; - - /* Argument sanity check */ - if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || - (!pvBuf)) - return 0; - - if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || - (!pState->file_stat.m_method)) { - /* The file is stored or the caller has requested the compressed - * data, calc amount to return. */ - copied_to_caller = (size_t) MZ_MIN(buf_size, - pState->comp_remaining); - - /* Zip is in memory....or requires reading from a file? */ - if (pState->pZip->m_pState->m_pMem) { - /* Copy data to caller's buffer */ - memcpy(pvBuf, pState->pRead_buf, copied_to_caller); - pState->pRead_buf = ((mz_uint8 *) pState->pRead_buf) + - copied_to_caller; - } else { - /* Read directly into caller's buffer */ - if (pState->pZip->m_pRead( - pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, - copied_to_caller) != copied_to_caller) { - /* Failed to read all that was asked for, flag failure and - * alert user */ - mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED); - pState->status = TINFL_STATUS_FAILED; - copied_to_caller = 0; - } - } - -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - /* Compute CRC if not returning compressed data only */ - if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - pState->file_crc32 = (mz_uint32) mz_crc32( - pState->file_crc32, (const mz_uint8 *) pvBuf, - copied_to_caller); -# endif - - /* Advance offsets, dec counters */ - pState->cur_file_ofs += copied_to_caller; - pState->out_buf_ofs += copied_to_caller; - pState->comp_remaining -= copied_to_caller; - } else { - do { - /* Calc ptr to write buffer - given current output pos and block - * size */ - mz_uint8 *pWrite_buf_cur = (mz_uint8 *) pState->pWrite_buf + - (pState->out_buf_ofs & - (TINFL_LZ_DICT_SIZE - 1)); - - /* Calc max output size - given current output pos and block - * size */ - size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - - (pState->out_buf_ofs & - (TINFL_LZ_DICT_SIZE - 1)); - - if (!pState->out_blk_remain) { - /* Read more data from file if none available (and reading - * from file) */ - if ((!pState->read_buf_avail) && - (!pState->pZip->m_pState->m_pMem)) { - /* Calc read size */ - pState->read_buf_avail = MZ_MIN(pState->read_buf_size, - pState->comp_remaining); - if (pState->pZip->m_pRead( - pState->pZip->m_pIO_opaque, pState->cur_file_ofs, - pState->pRead_buf, - (size_t) pState->read_buf_avail) != - pState->read_buf_avail) { - mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED); - pState->status = TINFL_STATUS_FAILED; - break; - } - - /* Advance offsets, dec counters */ - pState->cur_file_ofs += pState->read_buf_avail; - pState->comp_remaining -= pState->read_buf_avail; - pState->read_buf_ofs = 0; - } - - /* Perform decompression */ - in_buf_size = (size_t) pState->read_buf_avail; - pState->status = tinfl_decompress( - &pState->inflator, - (const mz_uint8 *) pState->pRead_buf + - pState->read_buf_ofs, - &in_buf_size, (mz_uint8 *) pState->pWrite_buf, - pWrite_buf_cur, &out_buf_size, - pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); - pState->read_buf_avail -= in_buf_size; - pState->read_buf_ofs += in_buf_size; - - /* Update current output block size remaining */ - pState->out_blk_remain = out_buf_size; - } - - if (pState->out_blk_remain) { - /* Calc amount to return. */ - size_t to_copy = MZ_MIN((buf_size - copied_to_caller), - pState->out_blk_remain); - - /* Copy data to caller's buffer */ - memcpy((mz_uint8 *) pvBuf + copied_to_caller, pWrite_buf_cur, - to_copy); - -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - /* Perform CRC */ - pState->file_crc32 = (mz_uint32) mz_crc32( - pState->file_crc32, pWrite_buf_cur, to_copy); -# endif - - /* Decrement data consumed from block */ - pState->out_blk_remain -= to_copy; - - /* Inc output offset, while performing sanity check */ - if ((pState->out_buf_ofs += to_copy) > - pState->file_stat.m_uncomp_size) { - mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED); - pState->status = TINFL_STATUS_FAILED; - break; - } - - /* Increment counter of data copied to caller */ - copied_to_caller += to_copy; - } - } while ((copied_to_caller < buf_size) && - ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || - (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT))); - } - - /* Return how many bytes were copied into user buffer */ - return copied_to_caller; -} - -mz_bool mz_zip_reader_extract_iter_free( - mz_zip_reader_extract_iter_state *pState) { - int status; - - /* Argument sanity check */ - if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState)) - return MZ_FALSE; - - /* Was decompression completed and requested? */ - if ((pState->status == TINFL_STATUS_DONE) && - (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) { - /* Make sure the entire file was decompressed, and check its CRC. - */ - if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size) { - mz_zip_set_error(pState->pZip, - MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE); - pState->status = TINFL_STATUS_FAILED; - } -# ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - else if (pState->file_crc32 != pState->file_stat.m_crc32) { - mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED); - pState->status = TINFL_STATUS_FAILED; - } -# endif - } - - /* Free buffers */ - if (!pState->pZip->m_pState->m_pMem) - pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, - pState->pRead_buf); - if (pState->pWrite_buf) - pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, - pState->pWrite_buf); - - /* Save status */ - status = pState->status; - - /* Free context */ - pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState); - - return status == TINFL_STATUS_DONE; -} - -# ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, - const void *pBuf, size_t n) { - (void) ofs; - - return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *) pOpaque); -} - -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, - mz_uint file_index, - const char *pDst_filename, - mz_uint flags) { - mz_bool status; - mz_zip_archive_file_stat file_stat; - MZ_FILE *pFile; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); - - pFile = MZ_FOPEN(pDst_filename, "wb"); - if (!pFile) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); - - status = mz_zip_reader_extract_to_callback( - pZip, file_index, mz_zip_file_write_callback, pFile, flags); - - if (MZ_FCLOSE(pFile) == EOF) { - if (status) - mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); - - status = MZ_FALSE; - } - -# if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) - if (status) - mz_zip_set_file_times(pDst_filename, file_stat.m_time, - file_stat.m_time); -# endif - - return status; -} - -mz_bool mz_zip_reader_extract_file_to_file( - mz_zip_archive *pZip, const char *pArchive_filename, - const char *pDst_filename, mz_uint flags) { - mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, - flags, &file_index)) - return MZ_FALSE; - - return mz_zip_reader_extract_to_file(pZip, file_index, - pDst_filename, flags); -} - -mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, - mz_uint file_index, - MZ_FILE *pFile, - mz_uint flags) { - mz_zip_archive_file_stat file_stat; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - if ((file_stat.m_is_directory) || (!file_stat.m_is_supported)) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); - - return mz_zip_reader_extract_to_callback( - pZip, file_index, mz_zip_file_write_callback, pFile, flags); -} - -mz_bool mz_zip_reader_extract_file_to_cfile( - mz_zip_archive *pZip, const char *pArchive_filename, - MZ_FILE *pFile, mz_uint flags) { - mz_uint32 file_index; - if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, - flags, &file_index)) - return MZ_FALSE; - - return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, - flags); -} -# endif /* #ifndef MINIZ_NO_STDIO */ - -static size_t mz_zip_compute_crc32_callback(void *pOpaque, - mz_uint64 file_ofs, - const void *pBuf, - size_t n) { - mz_uint32 *p = (mz_uint32 *) pOpaque; - (void) file_ofs; - *p = (mz_uint32) mz_crc32(*p, (const mz_uint8 *) pBuf, n); - return n; -} - -mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, - mz_uint flags) { - mz_zip_archive_file_stat file_stat; - mz_zip_internal_state *pState; - const mz_uint8 *pCentral_dir_header; - mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE; - mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - sizeof(mz_uint32) - 1) / - sizeof(mz_uint32)]; - mz_uint8 *pLocal_header = (mz_uint8 *) local_header_u32; - mz_uint64 local_header_ofs = 0; - mz_uint32 local_header_filename_len, local_header_extra_len, - local_header_crc32; - mz_uint64 local_header_comp_size, local_header_uncomp_size; - mz_uint32 uncomp_crc32 = MZ_CRC32_INIT; - mz_bool has_data_descriptor; - mz_uint32 local_header_bit_flags; - - mz_zip_array file_data_array; - mz_zip_array_init(&file_data_array, 1); - - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || - (!pZip->m_pFree) || (!pZip->m_pRead)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (file_index > pZip->m_total_files) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pState = pZip->m_pState; - - pCentral_dir_header = mz_zip_get_cdh(pZip, file_index); - - if (!mz_zip_file_stat_internal(pZip, file_index, - pCentral_dir_header, &file_stat, - &found_zip64_ext_data_in_cdir)) - return MZ_FALSE; - - /* A directory or zero length file */ - if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size)) - return MZ_TRUE; - - /* Encryption and patch files are not supported. */ - if (file_stat.m_is_encrypted) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); - - /* This function only supports stored and deflate. */ - if ((file_stat.m_method != 0) && - (file_stat.m_method != MZ_DEFLATED)) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD); - - if (!file_stat.m_is_supported) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE); - - /* Read and parse the local directory entry. */ - local_header_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, - pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - local_header_filename_len = MZ_READ_LE16( - pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS); - local_header_extra_len = MZ_READ_LE16(pLocal_header + - MZ_ZIP_LDH_EXTRA_LEN_OFS); - local_header_comp_size = MZ_READ_LE32( - pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS); - local_header_uncomp_size = MZ_READ_LE32( - pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS); - local_header_crc32 = MZ_READ_LE32(pLocal_header + - MZ_ZIP_LDH_CRC32_OFS); - local_header_bit_flags = MZ_READ_LE16(pLocal_header + - MZ_ZIP_LDH_BIT_FLAG_OFS); - has_data_descriptor = (local_header_bit_flags & 8) != 0; - - if (local_header_filename_len != strlen(file_stat.m_filename)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - local_header_filename_len + local_header_extra_len + - file_stat.m_comp_size) > pZip->m_archive_size) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - if (!mz_zip_array_resize( - pZip, &file_data_array, - MZ_MAX(local_header_filename_len, local_header_extra_len), - MZ_FALSE)) { - mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - goto handle_failure; - } - - if (local_header_filename_len) { - if (pZip->m_pRead(pZip->m_pIO_opaque, - local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, - file_data_array.m_p, - local_header_filename_len) != - local_header_filename_len) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - goto handle_failure; - } - - /* I've seen 1 archive that had the same pathname, but used - * backslashes in the local dir and forward slashes in the central - * dir. Do we care about this? For now, this case will fail - * validation. */ - if (memcmp(file_stat.m_filename, file_data_array.m_p, - local_header_filename_len) != 0) { - mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); - goto handle_failure; - } - } - - if ((local_header_extra_len) && - ((local_header_comp_size == MZ_UINT32_MAX) || - (local_header_uncomp_size == MZ_UINT32_MAX))) { - mz_uint32 extra_size_remaining = local_header_extra_len; - const mz_uint8 *pExtra_data = (const mz_uint8 *) - file_data_array.m_p; - - if (pZip->m_pRead(pZip->m_pIO_opaque, - local_header_ofs + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - local_header_filename_len, - file_data_array.m_p, local_header_extra_len) != - local_header_extra_len) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - goto handle_failure; - } - - do { - mz_uint32 field_id, field_data_size, field_total_size; - - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - goto handle_failure; - } - - field_id = MZ_READ_LE16(pExtra_data); - field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); - field_total_size = field_data_size + sizeof(mz_uint16) * 2; - - if (field_total_size > extra_size_remaining) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - goto handle_failure; - } - - if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { - const mz_uint8 *pSrc_field_data = pExtra_data + - sizeof(mz_uint32); - - if (field_data_size < sizeof(mz_uint64) * 2) { - mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - goto handle_failure; - } - - local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data); - local_header_comp_size = MZ_READ_LE64(pSrc_field_data + - sizeof(mz_uint64)); - - found_zip64_ext_data_in_ldir = MZ_TRUE; - break; - } - - pExtra_data += field_total_size; - extra_size_remaining -= field_total_size; - } while (extra_size_remaining); - } - - /* TODO: parse local header extra data when local_header_comp_size - * is 0xFFFFFFFF! (big_descriptor.zip) */ - /* I've seen zips in the wild with the data descriptor bit set, but - * proper local header values and bogus data descriptors */ - if ((has_data_descriptor) && (!local_header_comp_size) && - (!local_header_crc32)) { - mz_uint8 descriptor_buf[32]; - mz_bool has_id; - const mz_uint8 *pSrc; - mz_uint32 file_crc32; - mz_uint64 comp_size = 0, uncomp_size = 0; - - mz_uint32 num_descriptor_uint32s = - ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4; - - if (pZip->m_pRead( - pZip->m_pIO_opaque, - local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - local_header_filename_len + local_header_extra_len + - file_stat.m_comp_size, - descriptor_buf, - sizeof(mz_uint32) * num_descriptor_uint32s) != - (sizeof(mz_uint32) * num_descriptor_uint32s)) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - goto handle_failure; - } - - has_id = (MZ_READ_LE32(descriptor_buf) == - MZ_ZIP_DATA_DESCRIPTOR_ID); - pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) - : descriptor_buf; - - file_crc32 = MZ_READ_LE32(pSrc); - - if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) { - comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32)); - uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + - sizeof(mz_uint64)); - } else { - comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32)); - uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + - sizeof(mz_uint32)); - } - - if ((file_crc32 != file_stat.m_crc32) || - (comp_size != file_stat.m_comp_size) || - (uncomp_size != file_stat.m_uncomp_size)) { - mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); - goto handle_failure; - } - } else { - if ((local_header_crc32 != file_stat.m_crc32) || - (local_header_comp_size != file_stat.m_comp_size) || - (local_header_uncomp_size != file_stat.m_uncomp_size)) { - mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); - goto handle_failure; - } - } - - mz_zip_array_clear(pZip, &file_data_array); - - if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0) { - if (!mz_zip_reader_extract_to_callback( - pZip, file_index, mz_zip_compute_crc32_callback, - &uncomp_crc32, 0)) - return MZ_FALSE; - - /* 1 more check to be sure, although the extract checks too. */ - if (uncomp_crc32 != file_stat.m_crc32) { - mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); - return MZ_FALSE; - } - } - - return MZ_TRUE; - -handle_failure: - mz_zip_array_clear(pZip, &file_data_array); - return MZ_FALSE; -} - -mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags) { - mz_zip_internal_state *pState; - mz_uint32 i; - - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || - (!pZip->m_pFree) || (!pZip->m_pRead)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pState = pZip->m_pState; - - /* Basic sanity checks */ - if (!pState->m_zip64) { - if (pZip->m_total_files > MZ_UINT16_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - - if (pZip->m_archive_size > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - } else { - if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - } - - for (i = 0; i < pZip->m_total_files; i++) { - if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags) { - mz_uint32 found_index; - mz_zip_archive_file_stat stat; - - if (!mz_zip_reader_file_stat(pZip, i, &stat)) - return MZ_FALSE; - - if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, - 0, &found_index)) - return MZ_FALSE; - - /* This check can fail if there are duplicate filenames in the - * archive (which we don't check for when writing - that's up to - * the user) */ - if (found_index != i) - return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED); - } - - if (!mz_zip_validate_file(pZip, i, flags)) - return MZ_FALSE; - } - - return MZ_TRUE; -} - -mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, - mz_uint flags, - mz_zip_error *pErr) { - mz_bool success = MZ_TRUE; - mz_zip_archive zip; - mz_zip_error actual_err = MZ_ZIP_NO_ERROR; - - if ((!pMem) || (!size)) { - if (pErr) - *pErr = MZ_ZIP_INVALID_PARAMETER; - return MZ_FALSE; - } - - mz_zip_zero_struct(&zip); - - if (!mz_zip_reader_init_mem(&zip, pMem, size, flags)) { - if (pErr) - *pErr = zip.m_last_error; - return MZ_FALSE; - } - - if (!mz_zip_validate_archive(&zip, flags)) { - actual_err = zip.m_last_error; - success = MZ_FALSE; - } - - if (!mz_zip_reader_end_internal(&zip, success)) { - if (!actual_err) - actual_err = zip.m_last_error; - success = MZ_FALSE; - } - - if (pErr) - *pErr = actual_err; - - return success; -} - -# ifndef MINIZ_NO_STDIO -mz_bool mz_zip_validate_file_archive(const char *pFilename, - mz_uint flags, - mz_zip_error *pErr) { - mz_bool success = MZ_TRUE; - mz_zip_archive zip; - mz_zip_error actual_err = MZ_ZIP_NO_ERROR; - - if (!pFilename) { - if (pErr) - *pErr = MZ_ZIP_INVALID_PARAMETER; - return MZ_FALSE; - } - - mz_zip_zero_struct(&zip); - - if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0)) { - if (pErr) - *pErr = zip.m_last_error; - return MZ_FALSE; - } - - if (!mz_zip_validate_archive(&zip, flags)) { - actual_err = zip.m_last_error; - success = MZ_FALSE; - } - - if (!mz_zip_reader_end_internal(&zip, success)) { - if (!actual_err) - actual_err = zip.m_last_error; - success = MZ_FALSE; - } - - if (pErr) - *pErr = actual_err; - - return success; -} -# endif /* #ifndef MINIZ_NO_STDIO */ - -/* ------------------- .ZIP archive writing */ - -# ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v) { - p[0] = (mz_uint8) v; - p[1] = (mz_uint8) (v >> 8); -} -static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v) { - p[0] = (mz_uint8) v; - p[1] = (mz_uint8) (v >> 8); - p[2] = (mz_uint8) (v >> 16); - p[3] = (mz_uint8) (v >> 24); -} -static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v) { - mz_write_le32(p, (mz_uint32) v); - mz_write_le32(p + sizeof(mz_uint32), (mz_uint32) (v >> 32)); -} - -# define MZ_WRITE_LE16(p, v) \ - mz_write_le16((mz_uint8 *) (p), (mz_uint16) (v)) -# define MZ_WRITE_LE32(p, v) \ - mz_write_le32((mz_uint8 *) (p), (mz_uint32) (v)) -# define MZ_WRITE_LE64(p, v) \ - mz_write_le64((mz_uint8 *) (p), (mz_uint64) (v)) - -static size_t mz_zip_heap_write_func(void *pOpaque, - mz_uint64 file_ofs, - const void *pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *) pOpaque; - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); - - if (!n) - return 0; - - /* An allocation this big is likely to just fail on 32-bit systems, - * so don't even go there. */ - if ((sizeof(size_t) == sizeof(mz_uint32)) && - (new_size > 0x7FFFFFFF)) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); - return 0; - } - - if (new_size > pState->m_mem_capacity) { - void *pNew_block; - size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); - - while (new_capacity < new_size) new_capacity *= 2; - - if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, - pState->m_pMem, 1, - new_capacity))) { - mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - return 0; - } - - pState->m_pMem = pNew_block; - pState->m_mem_capacity = new_capacity; - } - memcpy((mz_uint8 *) pState->m_pMem + file_ofs, pBuf, n); - pState->m_mem_size = (size_t) new_size; - return n; -} - -static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, - mz_bool set_last_error) { - mz_zip_internal_state *pState; - mz_bool status = MZ_TRUE; - - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || - (!pZip->m_pFree) || - ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && - (pZip->m_zip_mode != - MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) { - if (set_last_error) - mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - return MZ_FALSE; - } - - pState = pZip->m_pState; - pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -# ifndef MINIZ_NO_STDIO - if (pState->m_pFile) { - if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) { - if (MZ_FCLOSE(pState->m_pFile) == EOF) { - if (set_last_error) - mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); - status = MZ_FALSE; - } - } - - pState->m_pFile = NULL; - } -# endif /* #ifndef MINIZ_NO_STDIO */ - - if ((pZip->m_pWrite == mz_zip_heap_write_func) && - (pState->m_pMem)) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); - pState->m_pMem = NULL; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - return status; -} - -mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, - mz_uint64 existing_size, - mz_uint flags) { - mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0; - - if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || - (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) { - if (!pZip->m_pRead) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - } - - if (pZip->m_file_offset_alignment) { - /* Ensure user specified file offset alignment is a power of 2. */ - if (pZip->m_file_offset_alignment & - (pZip->m_file_offset_alignment - 1)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - } - - if (!pZip->m_pAlloc) - pZip->m_pAlloc = miniz_def_alloc_func; - if (!pZip->m_pFree) - pZip->m_pFree = miniz_def_free_func; - if (!pZip->m_pRealloc) - pZip->m_pRealloc = miniz_def_realloc_func; - - pZip->m_archive_size = existing_size; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - - if (NULL == - (pZip->m_pState = (mz_zip_internal_state *) pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, - sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE( - &pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE( - &pZip->m_pState->m_sorted_central_dir_offsets, - sizeof(mz_uint32)); - - pZip->m_pState->m_zip64 = zip64; - pZip->m_pState->m_zip64_has_extended_info_fields = zip64; - - pZip->m_zip_type = MZ_ZIP_TYPE_USER; - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, - mz_uint64 existing_size) { - return mz_zip_writer_init_v2(pZip, existing_size, 0); -} - -mz_bool mz_zip_writer_init_heap_v2( - mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, - size_t initial_allocation_size, mz_uint flags) { - pZip->m_pWrite = mz_zip_heap_write_func; - pZip->m_pNeeds_keepalive = NULL; - - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) - pZip->m_pRead = mz_zip_mem_read_func; - - pZip->m_pIO_opaque = pZip; - - if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, - flags)) - return MZ_FALSE; - - pZip->m_zip_type = MZ_ZIP_TYPE_HEAP; - - if (0 != - (initial_allocation_size = MZ_MAX( - initial_allocation_size, size_to_reserve_at_beginning))) { - if (NULL == - (pZip->m_pState->m_pMem = pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, initial_allocation_size))) { - mz_zip_writer_end_internal(pZip, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - pZip->m_pState->m_mem_capacity = initial_allocation_size; - } - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, - size_t size_to_reserve_at_beginning, - size_t initial_allocation_size) { - return mz_zip_writer_init_heap_v2( - pZip, size_to_reserve_at_beginning, initial_allocation_size, 0); -} - -# ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_func(void *pOpaque, - mz_uint64 file_ofs, - const void *pBuf, size_t n) { - mz_zip_archive *pZip = (mz_zip_archive *) pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - - file_ofs += pZip->m_pState->m_file_archive_start_ofs; - - if (((mz_int64) file_ofs < 0) || - (((cur_ofs != (mz_int64) file_ofs)) && - (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64) file_ofs, - SEEK_SET)))) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED); - return 0; - } - - return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); -} - -mz_bool mz_zip_writer_init_file( - mz_zip_archive *pZip, const char *pFilename, - mz_uint64 size_to_reserve_at_beginning) { - return mz_zip_writer_init_file_v2(pZip, pFilename, - size_to_reserve_at_beginning, 0); -} - -mz_bool mz_zip_writer_init_file_v2( - mz_zip_archive *pZip, const char *pFilename, - mz_uint64 size_to_reserve_at_beginning, mz_uint flags) { - MZ_FILE *pFile; - - pZip->m_pWrite = mz_zip_file_write_func; - pZip->m_pNeeds_keepalive = NULL; - - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) - pZip->m_pRead = mz_zip_file_read_func; - - pZip->m_pIO_opaque = pZip; - - if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, - flags)) - return MZ_FALSE; - - if (NULL == - (pFile = MZ_FOPEN(pFilename, - (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) - ? "w+b" - : "wb"))) { - mz_zip_writer_end(pZip); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); - } - - pZip->m_pState->m_pFile = pFile; - pZip->m_zip_type = MZ_ZIP_TYPE_FILE; - - if (size_to_reserve_at_beginning) { - mz_uint64 cur_ofs = 0; - char buf[4096]; - - MZ_CLEAR_ARR(buf); - - do { - size_t n = (size_t) MZ_MIN(sizeof(buf), - size_to_reserve_at_beginning); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) { - mz_zip_writer_end(pZip); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - cur_ofs += n; - size_to_reserve_at_beginning -= n; - } while (size_to_reserve_at_beginning); - } - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, - mz_uint flags) { - pZip->m_pWrite = mz_zip_file_write_func; - pZip->m_pNeeds_keepalive = NULL; - - if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) - pZip->m_pRead = mz_zip_file_read_func; - - pZip->m_pIO_opaque = pZip; - - if (!mz_zip_writer_init_v2(pZip, 0, flags)) - return MZ_FALSE; - - pZip->m_pState->m_pFile = pFile; - pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64( - pZip->m_pState->m_pFile); - pZip->m_zip_type = MZ_ZIP_TYPE_CFILE; - - return MZ_TRUE; -} -# endif /* #ifndef MINIZ_NO_STDIO */ - -mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, - const char *pFilename, - mz_uint flags) { - mz_zip_internal_state *pState; - - if ((!pZip) || (!pZip->m_pState) || - (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (flags & MZ_ZIP_FLAG_WRITE_ZIP64) { - /* We don't support converting a non-zip64 file to zip64 - this - * seems like more trouble than it's worth. (What about the - * existing 32-bit data descriptors that could follow the - * compressed data?) */ - if (!pZip->m_pState->m_zip64) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - } - - /* No sense in trying to write to an archive that's already at the - * support max size */ - if (pZip->m_pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - } else { - if (pZip->m_total_files == MZ_UINT16_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - - if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); - } - - pState = pZip->m_pState; - - if (pState->m_pFile) { -# ifdef MINIZ_NO_STDIO - (void) pFilename; - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); -# else - if (pZip->m_pIO_opaque != pZip) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) { - if (!pFilename) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - /* Archive is being read from stdio and was originally opened - * only for reading. Try to reopen as writable. */ - if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", - pState->m_pFile))) { - /* The mz_zip_archive is now in a bogus state because - * pState->m_pFile is NULL, so just close it. */ - mz_zip_reader_end_internal(pZip, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); - } - } - - pZip->m_pWrite = mz_zip_file_write_func; - pZip->m_pNeeds_keepalive = NULL; -# endif /* #ifdef MINIZ_NO_STDIO */ - } else if (pState->m_pMem) { - /* Archive lives in a memory block. Assume it's from the heap that - * we can resize using the realloc callback. */ - if (pZip->m_pIO_opaque != pZip) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pState->m_mem_capacity = pState->m_mem_size; - pZip->m_pWrite = mz_zip_heap_write_func; - pZip->m_pNeeds_keepalive = NULL; - } - /* Archive is being read via a user provided read function - make - sure the user has specified a write function too. */ - else if (!pZip->m_pWrite) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - /* Start writing new files at the archive's current central - * directory location. */ - /* TODO: We could add a flag that lets the user start writing - * immediately AFTER the existing central dir - this would be safer. - */ - pZip->m_archive_size = pZip->m_central_directory_file_ofs; - pZip->m_central_directory_file_ofs = 0; - - /* Clear the sorted central dir offsets, they aren't useful or - * maintained now. */ - /* Even though we're now in write mode, files can still be extracted - * and verified, but file locates will be slow. */ - /* TODO: We could easily maintain the sorted central directory - * offsets. */ - mz_zip_array_clear(pZip, - &pZip->m_pState->m_sorted_central_dir_offsets); - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, - const char *pFilename) { - return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0); -} - -/* TODO: pArchive_name is a terrible name here! */ -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, - const char *pArchive_name, - const void *pBuf, size_t buf_size, - mz_uint level_and_flags) { - return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, - NULL, 0, level_and_flags, 0, 0); -} - -typedef struct { - mz_zip_archive *m_pZip; - mz_uint64 m_cur_archive_file_ofs; - mz_uint64 m_comp_size; -} mz_zip_writer_add_state; - -static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, - int len, - void *pUser) { - mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *) pUser; - if ((int) pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, - pState->m_cur_archive_file_ofs, - pBuf, len) != len) - return MZ_FALSE; - - pState->m_cur_archive_file_ofs += len; - pState->m_comp_size += len; - return MZ_TRUE; -} - -# define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE \ - (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2) -# define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE \ - (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3) -static mz_uint32 mz_zip_writer_create_zip64_extra_data( - mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, - mz_uint64 *pLocal_header_ofs) { - mz_uint8 *pDst = pBuf; - mz_uint32 field_size = 0; - - MZ_WRITE_LE16(pDst + 0, - MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID); - MZ_WRITE_LE16(pDst + 2, 0); - pDst += sizeof(mz_uint16) * 2; - - if (pUncomp_size) { - MZ_WRITE_LE64(pDst, *pUncomp_size); - pDst += sizeof(mz_uint64); - field_size += sizeof(mz_uint64); - } - - if (pComp_size) { - MZ_WRITE_LE64(pDst, *pComp_size); - pDst += sizeof(mz_uint64); - field_size += sizeof(mz_uint64); - } - - if (pLocal_header_ofs) { - MZ_WRITE_LE64(pDst, *pLocal_header_ofs); - pDst += sizeof(mz_uint64); - field_size += sizeof(mz_uint64); - } - - MZ_WRITE_LE16(pBuf + 2, field_size); - - return (mz_uint32) (pDst - pBuf); -} - -static mz_bool mz_zip_writer_create_local_dir_header( - mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, - mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, - mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, - mz_uint16 dos_time, mz_uint16 dos_date) { - (void) pZip; - memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, - MZ_ZIP_LOCAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, - method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, - MZ_MIN(comp_size, MZ_UINT32_MAX)); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, - MZ_MIN(uncomp_size, MZ_UINT32_MAX)); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_create_central_dir_header( - mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, - mz_uint16 extra_size, mz_uint16 comment_size, - mz_uint64 uncomp_size, mz_uint64 comp_size, - mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, - mz_uint16 dos_time, mz_uint16 dos_date, - mz_uint64 local_header_ofs, mz_uint32 ext_attributes) { - (void) pZip; - memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, - MZ_ZIP_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, - method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, - MZ_MIN(comp_size, MZ_UINT32_MAX)); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, - MZ_MIN(uncomp_size, MZ_UINT32_MAX)); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, - MZ_MIN(local_header_ofs, MZ_UINT32_MAX)); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_add_to_central_dir( - mz_zip_archive *pZip, const char *pFilename, - mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, - const void *pComment, mz_uint16 comment_size, - mz_uint64 uncomp_size, mz_uint64 comp_size, - mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, - mz_uint16 dos_time, mz_uint16 dos_date, - mz_uint64 local_header_ofs, mz_uint32 ext_attributes, - const char *user_extra_data, mz_uint user_extra_data_len) { - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint32 central_dir_ofs = (mz_uint32) - pState->m_central_dir.m_size; - size_t orig_central_dir_size = pState->m_central_dir.m_size; - mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - - if (!pZip->m_pState->m_zip64) { - if (local_header_ofs > 0xFFFFFFFF) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE); - } - - /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ - if (((mz_uint64) pState->m_central_dir.m_size + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + - user_extra_data_len + comment_size) >= MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - - if (!mz_zip_writer_create_central_dir_header( - pZip, central_dir_header, filename_size, - (mz_uint16) (extra_size + user_extra_data_len), - comment_size, uncomp_size, comp_size, uncomp_crc32, method, - bit_flags, dos_time, dos_date, local_header_ofs, - ext_attributes)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, - central_dir_header, - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, - pFilename, filename_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, - extra_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, - user_extra_data, - user_extra_data_len)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, - comment_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, - ¢ral_dir_ofs, 1))) { - /* Try to resize the central directory array back into its - * original state. */ - mz_zip_array_resize(pZip, &pState->m_central_dir, - orig_central_dir_size, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_validate_archive_name( - const char *pArchive_name) { - /* Basic ZIP archive filename validity checks: Valid filenames - * cannot start with a forward slash, cannot contain a drive letter, - * and cannot use DOS-style backward slashes. */ - if (*pArchive_name == '/') - return MZ_FALSE; - - /* Making sure the name does not contain drive letters or DOS style - * backward slashes is the responsibility of the program using - * miniz*/ - - return MZ_TRUE; -} - -static mz_uint -mz_zip_writer_compute_padding_needed_for_file_alignment( - mz_zip_archive *pZip) { - mz_uint32 n; - if (!pZip->m_file_offset_alignment) - return 0; - n = (mz_uint32) (pZip->m_archive_size & - (pZip->m_file_offset_alignment - 1)); - return (mz_uint) ((pZip->m_file_offset_alignment - n) & - (pZip->m_file_offset_alignment - 1)); -} - -static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, - mz_uint64 cur_file_ofs, - mz_uint32 n) { - char buf[4096]; - memset(buf, 0, MZ_MIN(sizeof(buf), n)); - while (n) { - mz_uint32 s = MZ_MIN(sizeof(buf), n); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_file_ofs += s; - n -= s; - } - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_mem_ex( - mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, - size_t buf_size, const void *pComment, mz_uint16 comment_size, - mz_uint level_and_flags, mz_uint64 uncomp_size, - mz_uint32 uncomp_crc32) { - return mz_zip_writer_add_mem_ex_v2( - pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, - level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, - 0); -} - -mz_bool mz_zip_writer_add_mem_ex_v2( - mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, - size_t buf_size, const void *pComment, mz_uint16 comment_size, - mz_uint level_and_flags, mz_uint64 uncomp_size, - mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, - const char *user_extra_data, mz_uint user_extra_data_len, - const char *user_extra_data_central, - mz_uint user_extra_data_central_len) { - mz_uint16 method = 0, dos_time = 0, dos_date = 0; - mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, - cur_archive_file_ofs = pZip->m_archive_size, - comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - tdefl_compressor *pComp = NULL; - mz_bool store_data_uncompressed; - mz_zip_internal_state *pState; - mz_uint8 *pExtra_data = NULL; - mz_uint32 extra_size = 0; - mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; - mz_uint16 bit_flags = 0; - - if ((int) level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - - if (uncomp_size || - (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) - bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; - - if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME)) - bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; - - level = level_and_flags & 0xF; - store_data_uncompressed = - ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); - - if ((!pZip) || (!pZip->m_pState) || - (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || - ((buf_size) && (!pBuf)) || (!pArchive_name) || - ((comment_size) && (!pComment)) || - (level > MZ_UBER_COMPRESSION)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pState = pZip->m_pState; - - if (pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - } else { - if (pZip->m_total_files == MZ_UINT16_MAX) { - pState->m_zip64 = MZ_TRUE; - /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ - } - if (((mz_uint64) buf_size > 0xFFFFFFFF) || - (uncomp_size > 0xFFFFFFFF)) { - pState->m_zip64 = MZ_TRUE; - /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ - } - } - - if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && - (uncomp_size)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); - -# ifndef MINIZ_NO_TIME - if (last_modified != NULL) { - mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date); - } else { - MZ_TIME_T cur_time; - time(&cur_time); - mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date); - } -# endif /* #ifndef MINIZ_NO_TIME */ - - if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { - uncomp_crc32 = (mz_uint32) mz_crc32( - MZ_CRC32_INIT, (const mz_uint8 *) pBuf, buf_size); - uncomp_size = buf_size; - if (uncomp_size <= 3) { - level = 0; - store_data_uncompressed = MZ_TRUE; - } - } - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > MZ_UINT16_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); - - num_alignment_padding_bytes = - mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ - if (((mz_uint64) pState->m_central_dir.m_size + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + - MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= - MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - - if (!pState->m_zip64) { - /* Bail early if the archive would obviously become too large */ - if ((pZip->m_archive_size + num_alignment_padding_bytes + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + - comment_size + user_extra_data_len + - pState->m_central_dir.m_size + - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + - user_extra_data_central_len + - MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF) { - pState->m_zip64 = MZ_TRUE; - /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ - } - } - - if ((archive_name_size) && - (pArchive_name[archive_name_size - 1] == '/')) { - /* Set DOS Subdirectory attribute bit. */ - ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG; - - /* Subdirectories cannot contain data. */ - if ((buf_size) || (uncomp_size)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - } - - /* Try to do any allocations before writing to the archive, so if an - * allocation fails the file remains unmodified. (A good idea if - * we're doing an in-place modification.) */ - if ((!mz_zip_array_ensure_room( - pZip, &pState->m_central_dir, - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + - comment_size + - (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE - : 0))) || - (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, - 1))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - if ((!store_data_uncompressed) && (buf_size)) { - if (NULL == - (pComp = (tdefl_compressor *) pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, - num_alignment_padding_bytes)) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { - MZ_ASSERT((local_dir_header_ofs & - (pZip->m_file_offset_alignment - 1)) == 0); - } - cur_archive_file_ofs += num_alignment_padding_bytes; - - MZ_CLEAR_ARR(local_dir_header); - - if (!store_data_uncompressed || - (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { - method = MZ_DEFLATED; - } - - if (pState->m_zip64) { - if (uncomp_size >= MZ_UINT32_MAX || - local_dir_header_ofs >= MZ_UINT32_MAX) { - pExtra_data = extra_data; - extra_size = mz_zip_writer_create_zip64_extra_data( - extra_data, - (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, - (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, - (local_dir_header_ofs >= MZ_UINT32_MAX) - ? &local_dir_header_ofs - : NULL); - } - - if (!mz_zip_writer_create_local_dir_header( - pZip, local_dir_header, (mz_uint16) archive_name_size, - (mz_uint16) (extra_size + user_extra_data_len), 0, 0, 0, - method, bit_flags, dos_time, dos_date)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, - local_dir_header, sizeof(local_dir_header)) != - sizeof(local_dir_header)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += sizeof(local_dir_header); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - pArchive_name, - archive_name_size) != archive_name_size) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - cur_archive_file_ofs += archive_name_size; - - if (pExtra_data != NULL) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - extra_data, extra_size) != extra_size) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += extra_size; - } - } else { - if ((comp_size > MZ_UINT32_MAX) || - (cur_archive_file_ofs > MZ_UINT32_MAX)) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (!mz_zip_writer_create_local_dir_header( - pZip, local_dir_header, (mz_uint16) archive_name_size, - (mz_uint16) user_extra_data_len, 0, 0, 0, method, - bit_flags, dos_time, dos_date)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, - local_dir_header, sizeof(local_dir_header)) != - sizeof(local_dir_header)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += sizeof(local_dir_header); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - pArchive_name, - archive_name_size) != archive_name_size) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - cur_archive_file_ofs += archive_name_size; - } - - if (user_extra_data_len > 0) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - user_extra_data, - user_extra_data_len) != user_extra_data_len) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += user_extra_data_len; - } - - if (store_data_uncompressed) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, - buf_size) != buf_size) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - - cur_archive_file_ofs += buf_size; - comp_size = buf_size; - } else if (buf_size) { - mz_zip_writer_add_state state; - - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; - - if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, - tdefl_create_comp_flags_from_zip_params( - level, -15, MZ_DEFAULT_STRATEGY)) != - TDEFL_STATUS_OKAY) || - (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != - TDEFL_STATUS_DONE)) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED); - } - - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pComp = NULL; - - if (uncomp_size) { - mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64]; - mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32; - - MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR); - - MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); - MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); - if (pExtra_data == NULL) { - if (comp_size > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - - MZ_WRITE_LE32(local_dir_footer + 8, comp_size); - MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size); - } else { - MZ_WRITE_LE64(local_dir_footer + 8, comp_size); - MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size); - local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; - } - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - local_dir_footer, local_dir_footer_size) != - local_dir_footer_size) - return MZ_FALSE; - - cur_archive_file_ofs += local_dir_footer_size; - } - - if (pExtra_data != NULL) { - extra_size = mz_zip_writer_create_zip64_extra_data( - extra_data, - (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, - (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, - (local_dir_header_ofs >= MZ_UINT32_MAX) - ? &local_dir_header_ofs - : NULL); - } - - if (!mz_zip_writer_add_to_central_dir( - pZip, pArchive_name, (mz_uint16) archive_name_size, - pExtra_data, (mz_uint16) extra_size, pComment, comment_size, - uncomp_size, comp_size, uncomp_crc32, method, bit_flags, - dos_time, dos_date, local_dir_header_ofs, ext_attributes, - user_extra_data_central, user_extra_data_central_len)) - return MZ_FALSE; - - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_read_buf_callback( - mz_zip_archive *pZip, const char *pArchive_name, - mz_file_read_func read_callback, void *callback_opaque, - mz_uint64 max_size, const MZ_TIME_T *pFile_time, - const void *pComment, mz_uint16 comment_size, - mz_uint level_and_flags, const char *user_extra_data, - mz_uint user_extra_data_len, const char *user_extra_data_central, - mz_uint user_extra_data_central_len) { - mz_uint16 gen_flags; - mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, - num_alignment_padding_bytes; - mz_uint16 method = 0, dos_time = 0, dos_date = 0, - ext_attributes = 0; - mz_uint64 local_dir_header_ofs, - cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, - comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - mz_uint8 *pExtra_data = NULL; - mz_uint32 extra_size = 0; - mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; - mz_zip_internal_state *pState; - mz_uint64 file_ofs = 0, cur_archive_header_file_ofs; - - if ((int) level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - - gen_flags = (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) - ? 0 - : MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; - - if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME)) - gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; - - /* Sanity checks */ - if ((!pZip) || (!pZip->m_pState) || - (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || - ((comment_size) && (!pComment)) || - (level > MZ_UBER_COMPRESSION)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pState = pZip->m_pState; - - if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX)) { - /* Source file is too large for non-zip64 */ - /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ - pState->m_zip64 = MZ_TRUE; - } - - /* We could support this, but why? */ - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); - - if (pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - } else { - if (pZip->m_total_files == MZ_UINT16_MAX) { - pState->m_zip64 = MZ_TRUE; - /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */ - } - } - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > MZ_UINT16_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); - - num_alignment_padding_bytes = - mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */ - if (((mz_uint64) pState->m_central_dir.m_size + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + - MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= - MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - - if (!pState->m_zip64) { - /* Bail early if the archive would obviously become too large */ - if ((pZip->m_archive_size + num_alignment_padding_bytes + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + - comment_size + user_extra_data_len + - pState->m_central_dir.m_size + - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024 + - MZ_ZIP_DATA_DESCRIPTER_SIZE32 + - user_extra_data_central_len) > 0xFFFFFFFF) { - pState->m_zip64 = MZ_TRUE; - /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ - } - } - -# ifndef MINIZ_NO_TIME - if (pFile_time) { - mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date); - } -# endif - - if (max_size <= 3) - level = 0; - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, - num_alignment_padding_bytes)) { - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - - cur_archive_file_ofs += num_alignment_padding_bytes; - local_dir_header_ofs = cur_archive_file_ofs; - - if (pZip->m_file_offset_alignment) { - MZ_ASSERT((cur_archive_file_ofs & - (pZip->m_file_offset_alignment - 1)) == 0); - } - - if (max_size && level) { - method = MZ_DEFLATED; - } - - MZ_CLEAR_ARR(local_dir_header); - if (pState->m_zip64) { - if (max_size >= MZ_UINT32_MAX || - local_dir_header_ofs >= MZ_UINT32_MAX) { - pExtra_data = extra_data; - if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) - extra_size = mz_zip_writer_create_zip64_extra_data( - extra_data, - (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, - (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, - (local_dir_header_ofs >= MZ_UINT32_MAX) - ? &local_dir_header_ofs - : NULL); - else - extra_size = mz_zip_writer_create_zip64_extra_data( - extra_data, NULL, NULL, - (local_dir_header_ofs >= MZ_UINT32_MAX) - ? &local_dir_header_ofs - : NULL); - } - - if (!mz_zip_writer_create_local_dir_header( - pZip, local_dir_header, (mz_uint16) archive_name_size, - (mz_uint16) (extra_size + user_extra_data_len), 0, 0, 0, - method, gen_flags, dos_time, dos_date)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - local_dir_header, sizeof(local_dir_header)) != - sizeof(local_dir_header)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += sizeof(local_dir_header); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - pArchive_name, - archive_name_size) != archive_name_size) { - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - - cur_archive_file_ofs += archive_name_size; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - extra_data, extra_size) != extra_size) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += extra_size; - } else { - if ((comp_size > MZ_UINT32_MAX) || - (cur_archive_file_ofs > MZ_UINT32_MAX)) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (!mz_zip_writer_create_local_dir_header( - pZip, local_dir_header, (mz_uint16) archive_name_size, - (mz_uint16) user_extra_data_len, 0, 0, 0, method, - gen_flags, dos_time, dos_date)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - local_dir_header, sizeof(local_dir_header)) != - sizeof(local_dir_header)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += sizeof(local_dir_header); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - pArchive_name, - archive_name_size) != archive_name_size) { - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - - cur_archive_file_ofs += archive_name_size; - } - - if (user_extra_data_len > 0) { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - user_extra_data, - user_extra_data_len) != user_extra_data_len) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_file_ofs += user_extra_data_len; - } - - if (max_size) { - void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, - MZ_ZIP_MAX_IO_BUF_SIZE); - if (!pRead_buf) { - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if (!level) { - while (1) { - size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, - MZ_ZIP_MAX_IO_BUF_SIZE); - if (n == 0) - break; - - if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || - (file_ofs + n > max_size)) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - } - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - pRead_buf, n) != n) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - file_ofs += n; - uncomp_crc32 = (mz_uint32) mz_crc32( - uncomp_crc32, (const mz_uint8 *) pRead_buf, n); - cur_archive_file_ofs += n; - } - uncomp_size = file_ofs; - comp_size = uncomp_size; - } else { - mz_bool result = MZ_FALSE; - mz_zip_writer_add_state state; - tdefl_compressor *pComp = (tdefl_compressor *) pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; - - if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, - &state, - tdefl_create_comp_flags_from_zip_params( - level, -15, MZ_DEFAULT_STRATEGY)) != - TDEFL_STATUS_OKAY) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - } - - for (;;) { - tdefl_status status; - tdefl_flush flush = TDEFL_NO_FLUSH; - - size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, - MZ_ZIP_MAX_IO_BUF_SIZE); - if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || - (file_ofs + n > max_size)) { - mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - break; - } - - file_ofs += n; - uncomp_crc32 = (mz_uint32) mz_crc32( - uncomp_crc32, (const mz_uint8 *) pRead_buf, n); - - if (pZip->m_pNeeds_keepalive != NULL && - pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque)) - flush = TDEFL_FULL_FLUSH; - - if (n == 0) - flush = TDEFL_FINISH; - - status = tdefl_compress_buffer(pComp, pRead_buf, n, flush); - if (status == TDEFL_STATUS_DONE) { - result = MZ_TRUE; - break; - } else if (status != TDEFL_STATUS_OKAY) { - mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED); - break; - } - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - - if (!result) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - return MZ_FALSE; - } - - uncomp_size = file_ofs; - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - } - - if (!(level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)) { - mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64]; - mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32; - - MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); - MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); - if (pExtra_data == NULL) { - if (comp_size > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - - MZ_WRITE_LE32(local_dir_footer + 8, comp_size); - MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size); - } else { - MZ_WRITE_LE64(local_dir_footer + 8, comp_size); - MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size); - local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64; - } - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, - local_dir_footer, local_dir_footer_size) != - local_dir_footer_size) - return MZ_FALSE; - - cur_archive_file_ofs += local_dir_footer_size; - } - - if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) { - if (pExtra_data != NULL) { - extra_size = mz_zip_writer_create_zip64_extra_data( - extra_data, - (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, - (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, - (local_dir_header_ofs >= MZ_UINT32_MAX) - ? &local_dir_header_ofs - : NULL); - } - - if (!mz_zip_writer_create_local_dir_header( - pZip, local_dir_header, (mz_uint16) archive_name_size, - (mz_uint16) (extra_size + user_extra_data_len), - (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size, - (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size, - uncomp_crc32, method, gen_flags, dos_time, dos_date)) - return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); - - cur_archive_header_file_ofs = local_dir_header_ofs; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, - cur_archive_header_file_ofs, local_dir_header, - sizeof(local_dir_header)) != - sizeof(local_dir_header)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - if (pExtra_data != NULL) { - cur_archive_header_file_ofs += sizeof(local_dir_header); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, - cur_archive_header_file_ofs, pArchive_name, - archive_name_size) != archive_name_size) { - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - - cur_archive_header_file_ofs += archive_name_size; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, - cur_archive_header_file_ofs, extra_data, - extra_size) != extra_size) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_archive_header_file_ofs += extra_size; - } - } - - if (pExtra_data != NULL) { - extra_size = mz_zip_writer_create_zip64_extra_data( - extra_data, - (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, - (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, - (local_dir_header_ofs >= MZ_UINT32_MAX) - ? &local_dir_header_ofs - : NULL); - } - - if (!mz_zip_writer_add_to_central_dir( - pZip, pArchive_name, (mz_uint16) archive_name_size, - pExtra_data, (mz_uint16) extra_size, pComment, comment_size, - uncomp_size, comp_size, uncomp_crc32, method, gen_flags, - dos_time, dos_date, local_dir_header_ofs, ext_attributes, - user_extra_data_central, user_extra_data_central_len)) - return MZ_FALSE; - - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; - - return MZ_TRUE; -} - -# ifndef MINIZ_NO_STDIO - -static size_t mz_file_read_func_stdio(void *pOpaque, - mz_uint64 file_ofs, void *pBuf, - size_t n) { - MZ_FILE *pSrc_file = (MZ_FILE *) pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pSrc_file); - - if (((mz_int64) file_ofs < 0) || - (((cur_ofs != (mz_int64) file_ofs)) && - (MZ_FSEEK64(pSrc_file, (mz_int64) file_ofs, SEEK_SET)))) - return 0; - - return MZ_FREAD(pBuf, 1, n, pSrc_file); -} - -mz_bool mz_zip_writer_add_cfile( - mz_zip_archive *pZip, const char *pArchive_name, - MZ_FILE *pSrc_file, mz_uint64 max_size, - const MZ_TIME_T *pFile_time, const void *pComment, - mz_uint16 comment_size, mz_uint level_and_flags, - const char *user_extra_data, mz_uint user_extra_data_len, - const char *user_extra_data_central, - mz_uint user_extra_data_central_len) { - return mz_zip_writer_add_read_buf_callback( - pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, - max_size, pFile_time, pComment, comment_size, level_and_flags, - user_extra_data, user_extra_data_len, user_extra_data_central, - user_extra_data_central_len); -} - -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, - const char *pArchive_name, - const char *pSrc_filename, - const void *pComment, - mz_uint16 comment_size, - mz_uint level_and_flags) { - MZ_FILE *pSrc_file = NULL; - mz_uint64 uncomp_size = 0; - MZ_TIME_T file_modified_time; - MZ_TIME_T *pFile_time = NULL; - mz_bool status; - - memset(&file_modified_time, 0, sizeof(file_modified_time)); - -# if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO) - pFile_time = &file_modified_time; - if (!mz_zip_get_file_modified_time(pSrc_filename, - &file_modified_time)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED); -# endif - - pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); - if (!pSrc_file) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); - - MZ_FSEEK64(pSrc_file, 0, SEEK_END); - uncomp_size = MZ_FTELL64(pSrc_file); - MZ_FSEEK64(pSrc_file, 0, SEEK_SET); - - status = mz_zip_writer_add_cfile( - pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, - pComment, comment_size, level_and_flags, NULL, 0, NULL, 0); - - MZ_FCLOSE(pSrc_file); - - return status; -} -# endif /* #ifndef MINIZ_NO_STDIO */ - -static mz_bool mz_zip_writer_update_zip64_extension_block( - mz_zip_array *pNew_ext, mz_zip_archive *pZip, - const mz_uint8 *pExt, mz_uint32 ext_len, mz_uint64 *pComp_size, - mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, - mz_uint32 *pDisk_start) { - /* + 64 should be enough for any new zip64 data */ - if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE)) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE); - - if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || - (pDisk_start)) { - mz_uint8 new_ext_block[64]; - mz_uint8 *pDst = new_ext_block; - mz_write_le16(pDst, - MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID); - mz_write_le16(pDst + sizeof(mz_uint16), 0); - pDst += sizeof(mz_uint16) * 2; - - if (pUncomp_size) { - mz_write_le64(pDst, *pUncomp_size); - pDst += sizeof(mz_uint64); - } - - if (pComp_size) { - mz_write_le64(pDst, *pComp_size); - pDst += sizeof(mz_uint64); - } - - if (pLocal_header_ofs) { - mz_write_le64(pDst, *pLocal_header_ofs); - pDst += sizeof(mz_uint64); - } - - if (pDisk_start) { - mz_write_le32(pDst, *pDisk_start); - pDst += sizeof(mz_uint32); - } - - mz_write_le16( - new_ext_block + sizeof(mz_uint16), - (mz_uint16) ((pDst - new_ext_block) - sizeof(mz_uint16) * 2)); - - if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, - pDst - new_ext_block)) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if ((pExt) && (ext_len)) { - mz_uint32 extra_size_remaining = ext_len; - const mz_uint8 *pExtra_data = pExt; - - do { - mz_uint32 field_id, field_data_size, field_total_size; - - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - field_id = MZ_READ_LE16(pExtra_data); - field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); - field_total_size = field_data_size + sizeof(mz_uint16) * 2; - - if (field_total_size > extra_size_remaining) - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { - if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, - field_total_size)) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - pExtra_data += field_total_size; - extra_size_remaining -= field_total_size; - } while (extra_size_remaining); - } - - return MZ_TRUE; -} - -/* TODO: This func is now pretty freakin complex due to zip64, split - * it up? */ -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, - mz_zip_archive *pSource_zip, - mz_uint src_file_index) { - mz_uint n, bit_flags, num_alignment_padding_bytes, - src_central_dir_following_data_size; - mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs; - mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - sizeof(mz_uint32) - 1) / - sizeof(mz_uint32)]; - mz_uint8 *pLocal_header = (mz_uint8 *) local_header_u32; - mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - size_t orig_central_dir_size; - mz_zip_internal_state *pState; - void *pBuf; - const mz_uint8 *pSrc_central_header; - mz_zip_archive_file_stat src_file_stat; - mz_uint32 src_filename_len, src_comment_len, src_ext_len; - mz_uint32 local_header_filename_size, local_header_extra_len; - mz_uint64 local_header_comp_size, local_header_uncomp_size; - mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE; - - /* Sanity checks */ - if ((!pZip) || (!pZip->m_pState) || - (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || - (!pSource_zip->m_pRead)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pState = pZip->m_pState; - - /* Don't support copying files from zip64 archives to non-zip64, - * even though in some cases this is possible */ - if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - /* Get pointer to the source central dir header and crack it */ - if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, - src_file_index))) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != - MZ_ZIP_CENTRAL_DIR_HEADER_SIG) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - src_filename_len = MZ_READ_LE16(pSrc_central_header + - MZ_ZIP_CDH_FILENAME_LEN_OFS); - src_comment_len = MZ_READ_LE16(pSrc_central_header + - MZ_ZIP_CDH_COMMENT_LEN_OFS); - src_ext_len = MZ_READ_LE16(pSrc_central_header + - MZ_ZIP_CDH_EXTRA_LEN_OFS); - src_central_dir_following_data_size = src_filename_len + - src_ext_len + src_comment_len; - - /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right - * now (+32 fudge factor in case we need to add more extra data) */ - if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - - num_alignment_padding_bytes = - mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - if (!pState->m_zip64) { - if (pZip->m_total_files == MZ_UINT16_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - } else { - /* TODO: Our zip64 support still has some 32-bit limits that may - * not be worth fixing. */ - if (pZip->m_total_files == MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - } - - if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, - pSrc_central_header, &src_file_stat, - NULL)) - return MZ_FALSE; - - cur_src_file_ofs = src_file_stat.m_local_header_ofs; - cur_dst_file_ofs = pZip->m_archive_size; - - /* Read the source archive's local dir header */ - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, - cur_src_file_ofs, pLocal_header, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - - cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - /* Compute the total size we need to copy (filename+extra - * data+compressed data) */ - local_header_filename_size = MZ_READ_LE16( - pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS); - local_header_extra_len = MZ_READ_LE16(pLocal_header + - MZ_ZIP_LDH_EXTRA_LEN_OFS); - local_header_comp_size = MZ_READ_LE32( - pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS); - local_header_uncomp_size = MZ_READ_LE32( - pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS); - src_archive_bytes_remaining = src_file_stat.m_comp_size + - local_header_filename_size + - local_header_extra_len; - - /* Try to find a zip64 extended information field */ - if ((local_header_extra_len) && - ((local_header_comp_size == MZ_UINT32_MAX) || - (local_header_uncomp_size == MZ_UINT32_MAX))) { - mz_zip_array file_data_array; - const mz_uint8 *pExtra_data; - mz_uint32 extra_size_remaining = local_header_extra_len; - - mz_zip_array_init(&file_data_array, 1); - if (!mz_zip_array_resize(pZip, &file_data_array, - local_header_extra_len, MZ_FALSE)) { - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, - src_file_stat.m_local_header_ofs + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE + - local_header_filename_size, - file_data_array.m_p, - local_header_extra_len) != - local_header_extra_len) { - mz_zip_array_clear(pZip, &file_data_array); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - } - - pExtra_data = (const mz_uint8 *) file_data_array.m_p; - - do { - mz_uint32 field_id, field_data_size, field_total_size; - - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) { - mz_zip_array_clear(pZip, &file_data_array); - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } - - field_id = MZ_READ_LE16(pExtra_data); - field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); - field_total_size = field_data_size + sizeof(mz_uint16) * 2; - - if (field_total_size > extra_size_remaining) { - mz_zip_array_clear(pZip, &file_data_array); - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } - - if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { - const mz_uint8 *pSrc_field_data = pExtra_data + - sizeof(mz_uint32); - - if (field_data_size < sizeof(mz_uint64) * 2) { - mz_zip_array_clear(pZip, &file_data_array); - return mz_zip_set_error(pZip, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } - - local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data); - local_header_comp_size = MZ_READ_LE64( - pSrc_field_data + - sizeof(mz_uint64)); /* may be 0 if there's a descriptor */ - - found_zip64_ext_data_in_ldir = MZ_TRUE; - break; - } - - pExtra_data += field_total_size; - extra_size_remaining -= field_total_size; - } while (extra_size_remaining); - - mz_zip_array_clear(pZip, &file_data_array); - } - - if (!pState->m_zip64) { - /* Try to detect if the new archive will most likely wind up too - * big and bail early (+(sizeof(mz_uint32) * 4) is for the - * optional descriptor which could be present, +64 is a fudge - * factor). */ - /* We also check when the archive is finalized so this doesn't - * need to be perfect. */ - mz_uint64 approx_new_archive_size = - cur_dst_file_ofs + num_alignment_padding_bytes + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + - (sizeof(mz_uint32) * 4) + pState->m_central_dir.m_size + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - src_central_dir_following_data_size + - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64; - - if (approx_new_archive_size >= MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - } - - /* Write dest archive padding */ - if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, - num_alignment_padding_bytes)) - return MZ_FALSE; - - cur_dst_file_ofs += num_alignment_padding_bytes; - - local_dir_header_ofs = cur_dst_file_ofs; - if (pZip->m_file_offset_alignment) { - MZ_ASSERT((local_dir_header_ofs & - (pZip->m_file_offset_alignment - 1)) == 0); - } - - /* The original zip's local header+ext block doesn't change, even - * with zip64, so we can just copy it over to the dest zip */ - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, - pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != - MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - /* Copy over the source archive bytes to the dest archive, also - * ensure we have enough buf space to handle optional data - * descriptor */ - if (NULL == (pBuf = pZip->m_pAlloc( - pZip->m_pAlloc_opaque, 1, - (size_t) MZ_MAX( - 32U, MZ_MIN((mz_uint64) MZ_ZIP_MAX_IO_BUF_SIZE, - src_archive_bytes_remaining))))) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - while (src_archive_bytes_remaining) { - n = (mz_uint) MZ_MIN((mz_uint64) MZ_ZIP_MAX_IO_BUF_SIZE, - src_archive_bytes_remaining); - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, - cur_src_file_ofs, pBuf, n) != n) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - } - cur_src_file_ofs += n; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, - n) != n) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - cur_dst_file_ofs += n; - - src_archive_bytes_remaining -= n; - } - - /* Now deal with the optional data descriptor */ - bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); - if (bit_flags & 8) { - /* Copy data descriptor */ - if ((pSource_zip->m_pState->m_zip64) || - (found_zip64_ext_data_in_ldir)) { - /* src is zip64, dest must be zip64 */ - - /* name uint32_t's */ - /* id 1 (optional in zip64?) */ - /* crc 1 */ - /* comp_size 2 */ - /* uncomp_size 2 */ - if (pSource_zip->m_pRead( - pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, - (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6)) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - } - - n = sizeof(mz_uint32) * - ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5); - } else { - /* src is NOT zip64 */ - mz_bool has_id; - - if (pSource_zip->m_pRead( - pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, - sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - } - - has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID); - - if (pZip->m_pState->m_zip64) { - /* dest is zip64, so upgrade the data descriptor */ - const mz_uint8 *pSrc_descriptor = (const mz_uint8 *) pBuf + - (has_id ? sizeof(mz_uint32) - : 0); - const mz_uint32 src_crc32 = MZ_READ_LE32(pSrc_descriptor); - const mz_uint64 src_comp_size = MZ_READ_LE32( - pSrc_descriptor + sizeof(mz_uint32)); - const mz_uint64 src_uncomp_size = MZ_READ_LE32( - pSrc_descriptor + 2 * sizeof(mz_uint32)); - - mz_write_le32((mz_uint8 *) pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID); - mz_write_le32((mz_uint8 *) pBuf + sizeof(mz_uint32) * 1, - src_crc32); - mz_write_le64((mz_uint8 *) pBuf + sizeof(mz_uint32) * 2, - src_comp_size); - mz_write_le64((mz_uint8 *) pBuf + sizeof(mz_uint32) * 4, - src_uncomp_size); - - n = sizeof(mz_uint32) * 6; - } else { - /* dest is NOT zip64, just copy it as-is */ - n = sizeof(mz_uint32) * (has_id ? 4 : 3); - } - } - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, - n) != n) { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - } - - cur_src_file_ofs += n; - cur_dst_file_ofs += n; - } - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - - /* Finally, add the new central dir header */ - orig_central_dir_size = pState->m_central_dir.m_size; - - memcpy(new_central_header, pSrc_central_header, - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - - if (pState->m_zip64) { - /* This is the painful part: We need to write a new central dir - * header + ext block with updated zip64 fields, and ensure the - * old fields (if any) are not included. */ - const mz_uint8 *pSrc_ext = pSrc_central_header + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - src_filename_len; - mz_zip_array new_ext_block; - - mz_zip_array_init(&new_ext_block, sizeof(mz_uint8)); - - MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, - MZ_UINT32_MAX); - MZ_WRITE_LE32(new_central_header + - MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, - MZ_UINT32_MAX); - MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, - MZ_UINT32_MAX); - - if (!mz_zip_writer_update_zip64_extension_block( - &new_ext_block, pZip, pSrc_ext, src_ext_len, - &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, - &local_dir_header_ofs, NULL)) { - mz_zip_array_clear(pZip, &new_ext_block); - return MZ_FALSE; - } - - MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, - new_ext_block.m_size); - - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, - new_central_header, - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) { - mz_zip_array_clear(pZip, &new_ext_block); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, - pSrc_central_header + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, - src_filename_len)) { - mz_zip_array_clear(pZip, &new_ext_block); - mz_zip_array_resize(pZip, &pState->m_central_dir, - orig_central_dir_size, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, - new_ext_block.m_p, - new_ext_block.m_size)) { - mz_zip_array_clear(pZip, &new_ext_block); - mz_zip_array_resize(pZip, &pState->m_central_dir, - orig_central_dir_size, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, - pSrc_central_header + - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - src_filename_len + src_ext_len, - src_comment_len)) { - mz_zip_array_clear(pZip, &new_ext_block); - mz_zip_array_resize(pZip, &pState->m_central_dir, - orig_central_dir_size, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - mz_zip_array_clear(pZip, &new_ext_block); - } else { - /* sanity checks */ - if (cur_dst_file_ofs > MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - - if (local_dir_header_ofs >= MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - - MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, - local_dir_header_ofs); - - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, - new_central_header, - MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - if (!mz_zip_array_push_back( - pZip, &pState->m_central_dir, - pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, - src_central_dir_following_data_size)) { - mz_zip_array_resize(pZip, &pState->m_central_dir, - orig_central_dir_size, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - } - - /* This shouldn't trigger unless we screwed up during the initial - * sanity checks */ - if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) { - /* TODO: Support central dirs >= 32-bits in size */ - mz_zip_array_resize(pZip, &pState->m_central_dir, - orig_central_dir_size, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - } - - n = (mz_uint32) orig_central_dir_size; - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, - &n, 1)) { - mz_zip_array_resize(pZip, &pState->m_central_dir, - orig_central_dir_size, MZ_FALSE); - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - } - - pZip->m_total_files++; - pZip->m_archive_size = cur_dst_file_ofs; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) { - mz_zip_internal_state *pState; - mz_uint64 central_dir_ofs, central_dir_size; - mz_uint8 hdr[256]; - - if ((!pZip) || (!pZip->m_pState) || - (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - pState = pZip->m_pState; - - if (pState->m_zip64) { - if ((mz_uint64) pState->m_central_dir.m_size >= MZ_UINT32_MAX) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - } else { - if ((pZip->m_total_files > MZ_UINT16_MAX) || - ((pZip->m_archive_size + pState->m_central_dir.m_size + - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)) - return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); - } - - central_dir_ofs = 0; - central_dir_size = 0; - if (pZip->m_total_files) { - /* Write central directory */ - central_dir_ofs = pZip->m_archive_size; - central_dir_size = pState->m_central_dir.m_size; - pZip->m_central_directory_file_ofs = central_dir_ofs; - if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, - pState->m_central_dir.m_p, - (size_t) central_dir_size) != central_dir_size) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - pZip->m_archive_size += central_dir_size; - } - - if (pState->m_zip64) { - /* Write zip64 end of central directory header */ - mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size; - - MZ_CLEAR_ARR(hdr); - MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - - sizeof(mz_uint32) - sizeof(mz_uint64)); - MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, - 0x031E); /* TODO: always Unix */ - MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D); - MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, - pZip->m_total_files); - MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, - pZip->m_total_files); - MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, - central_dir_size); - MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE; - - /* Write zip64 end of central directory locator */ - MZ_CLEAR_ARR(hdr); - MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG); - MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, - rel_ofs_to_zip64_ecdr); - MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1); - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - - pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE; - } - - /* Write end of central directory record */ - MZ_CLEAR_ARR(hdr); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, - MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files)); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, - MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files)); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, - MZ_MIN(MZ_UINT32_MAX, central_dir_size)); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, - MZ_MIN(MZ_UINT32_MAX, central_dir_ofs)); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - -# ifndef MINIZ_NO_STDIO - if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED); -# endif /* #ifndef MINIZ_NO_STDIO */ - - pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE; - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, - void **ppBuf, - size_t *pSize) { - if ((!ppBuf) || (!pSize)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - *ppBuf = NULL; - *pSize = 0; - - if ((!pZip) || (!pZip->m_pState)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (pZip->m_pWrite != mz_zip_heap_write_func) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - if (!mz_zip_writer_finalize_archive(pZip)) - return MZ_FALSE; - - *ppBuf = pZip->m_pState->m_pMem; - *pSize = pZip->m_pState->m_mem_size; - pZip->m_pState->m_pMem = NULL; - pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_end(mz_zip_archive *pZip) { - return mz_zip_writer_end_internal(pZip, MZ_TRUE); -} - -# ifndef MINIZ_NO_STDIO -mz_bool mz_zip_add_mem_to_archive_file_in_place( - const char *pZip_filename, const char *pArchive_name, - const void *pBuf, size_t buf_size, const void *pComment, - mz_uint16 comment_size, mz_uint level_and_flags) { - return mz_zip_add_mem_to_archive_file_in_place_v2( - pZip_filename, pArchive_name, pBuf, buf_size, pComment, - comment_size, level_and_flags, NULL); -} - -mz_bool mz_zip_add_mem_to_archive_file_in_place_v2( - const char *pZip_filename, const char *pArchive_name, - const void *pBuf, size_t buf_size, const void *pComment, - mz_uint16 comment_size, mz_uint level_and_flags, - mz_zip_error *pErr) { - mz_bool status, created_new_archive = MZ_FALSE; - mz_zip_archive zip_archive; - struct MZ_FILE_STAT_STRUCT file_stat; - mz_zip_error actual_err = MZ_ZIP_NO_ERROR; - - mz_zip_zero_struct(&zip_archive); - if ((int) level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - - if ((!pZip_filename) || (!pArchive_name) || - ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || - ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) { - if (pErr) - *pErr = MZ_ZIP_INVALID_PARAMETER; - return MZ_FALSE; - } - - if (!mz_zip_writer_validate_archive_name(pArchive_name)) { - if (pErr) - *pErr = MZ_ZIP_INVALID_FILENAME; - return MZ_FALSE; - } - - /* Important: The regular non-64 bit version of stat() can fail here - * if the file is very large, which could cause the archive to be - * overwritten. */ - /* So be sure to compile with _LARGEFILE64_SOURCE 1 */ - if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) { - /* Create a new archive. */ - if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, - level_and_flags)) { - if (pErr) - *pErr = zip_archive.m_last_error; - return MZ_FALSE; - } - - created_new_archive = MZ_TRUE; - } else { - /* Append to an existing archive. */ - if (!mz_zip_reader_init_file_v2( - &zip_archive, pZip_filename, - level_and_flags | - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, - 0, 0)) { - if (pErr) - *pErr = zip_archive.m_last_error; - return MZ_FALSE; - } - - if (!mz_zip_writer_init_from_reader_v2( - &zip_archive, pZip_filename, level_and_flags)) { - if (pErr) - *pErr = zip_archive.m_last_error; - - mz_zip_reader_end_internal(&zip_archive, MZ_FALSE); - - return MZ_FALSE; - } - } - - status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, - buf_size, pComment, comment_size, - level_and_flags, 0, 0); - actual_err = zip_archive.m_last_error; - - /* Always finalize, even if adding failed for some reason, so we - * have a valid central directory. (This may not always succeed, but - * we can try.) */ - if (!mz_zip_writer_finalize_archive(&zip_archive)) { - if (!actual_err) - actual_err = zip_archive.m_last_error; - - status = MZ_FALSE; - } - - if (!mz_zip_writer_end_internal(&zip_archive, status)) { - if (!actual_err) - actual_err = zip_archive.m_last_error; - - status = MZ_FALSE; - } - - if ((!status) && (created_new_archive)) { - /* It's a new archive and something went wrong, so just delete it. - */ - int ignoredStatus = MZ_DELETE_FILE(pZip_filename); - (void) ignoredStatus; - } - - if (pErr) - *pErr = actual_err; - - return status; -} - -void *mz_zip_extract_archive_file_to_heap_v2( - const char *pZip_filename, const char *pArchive_name, - const char *pComment, size_t *pSize, mz_uint flags, - mz_zip_error *pErr) { - mz_uint32 file_index; - mz_zip_archive zip_archive; - void *p = NULL; - - if (pSize) - *pSize = 0; - - if ((!pZip_filename) || (!pArchive_name)) { - if (pErr) - *pErr = MZ_ZIP_INVALID_PARAMETER; - - return NULL; - } - - mz_zip_zero_struct(&zip_archive); - if (!mz_zip_reader_init_file_v2( - &zip_archive, pZip_filename, - flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) { - if (pErr) - *pErr = zip_archive.m_last_error; - - return NULL; - } - - if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, - pComment, flags, &file_index)) { - p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, - flags); - } - - mz_zip_reader_end_internal(&zip_archive, p != NULL); - - if (pErr) - *pErr = zip_archive.m_last_error; - - return p; -} - -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, - const char *pArchive_name, - size_t *pSize, - mz_uint flags) { - return mz_zip_extract_archive_file_to_heap_v2( - pZip_filename, pArchive_name, NULL, pSize, flags, NULL); -} - -# endif /* #ifndef MINIZ_NO_STDIO */ - -# endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */ - -/* ------------------- Misc utils */ - -mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip) { - return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID; -} - -mz_zip_type mz_zip_get_type(mz_zip_archive *pZip) { - return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID; -} - -mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, - mz_zip_error err_num) { - mz_zip_error prev_err; - - if (!pZip) - return MZ_ZIP_INVALID_PARAMETER; - - prev_err = pZip->m_last_error; - - pZip->m_last_error = err_num; - return prev_err; -} - -mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip) { - if (!pZip) - return MZ_ZIP_INVALID_PARAMETER; - - return pZip->m_last_error; -} - -mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip) { - return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR); -} - -mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip) { - mz_zip_error prev_err; - - if (!pZip) - return MZ_ZIP_INVALID_PARAMETER; - - prev_err = pZip->m_last_error; - - pZip->m_last_error = MZ_ZIP_NO_ERROR; - return prev_err; -} - -const char *mz_zip_get_error_string(mz_zip_error mz_err) { - switch (mz_err) { - case MZ_ZIP_NO_ERROR: return "no error"; - case MZ_ZIP_UNDEFINED_ERROR: return "undefined error"; - case MZ_ZIP_TOO_MANY_FILES: return "too many files"; - case MZ_ZIP_FILE_TOO_LARGE: return "file too large"; - case MZ_ZIP_UNSUPPORTED_METHOD: return "unsupported method"; - case MZ_ZIP_UNSUPPORTED_ENCRYPTION: - return "unsupported encryption"; - case MZ_ZIP_UNSUPPORTED_FEATURE: return "unsupported feature"; - case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR: - return "failed finding central directory"; - case MZ_ZIP_NOT_AN_ARCHIVE: return "not a ZIP archive"; - case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED: - return "invalid header or archive is corrupted"; - case MZ_ZIP_UNSUPPORTED_MULTIDISK: - return "unsupported multidisk archive"; - case MZ_ZIP_DECOMPRESSION_FAILED: - return "decompression failed or archive is corrupted"; - case MZ_ZIP_COMPRESSION_FAILED: return "compression failed"; - case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE: - return "unexpected decompressed size"; - case MZ_ZIP_CRC_CHECK_FAILED: return "CRC-32 check failed"; - case MZ_ZIP_UNSUPPORTED_CDIR_SIZE: - return "unsupported central directory size"; - case MZ_ZIP_ALLOC_FAILED: return "allocation failed"; - case MZ_ZIP_FILE_OPEN_FAILED: return "file open failed"; - case MZ_ZIP_FILE_CREATE_FAILED: return "file create failed"; - case MZ_ZIP_FILE_WRITE_FAILED: return "file write failed"; - case MZ_ZIP_FILE_READ_FAILED: return "file read failed"; - case MZ_ZIP_FILE_CLOSE_FAILED: return "file close failed"; - case MZ_ZIP_FILE_SEEK_FAILED: return "file seek failed"; - case MZ_ZIP_FILE_STAT_FAILED: return "file stat failed"; - case MZ_ZIP_INVALID_PARAMETER: return "invalid parameter"; - case MZ_ZIP_INVALID_FILENAME: return "invalid filename"; - case MZ_ZIP_BUF_TOO_SMALL: return "buffer too small"; - case MZ_ZIP_INTERNAL_ERROR: return "internal error"; - case MZ_ZIP_FILE_NOT_FOUND: return "file not found"; - case MZ_ZIP_ARCHIVE_TOO_LARGE: return "archive is too large"; - case MZ_ZIP_VALIDATION_FAILED: return "validation failed"; - case MZ_ZIP_WRITE_CALLBACK_FAILED: return "write callback failed"; - case MZ_ZIP_TOTAL_ERRORS: return "total errors"; - default: break; - } - - return "unknown error"; -} - -/* Note: Just because the archive is not zip64 doesn't necessarily - * mean it doesn't have Zip64 extended information extra field, argh. - */ -mz_bool mz_zip_is_zip64(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) - return MZ_FALSE; - - return pZip->m_pState->m_zip64; -} - -size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) - return 0; - - return pZip->m_pState->m_central_dir.m_size; -} - -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) { - return pZip ? pZip->m_total_files : 0; -} - -mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip) { - if (!pZip) - return 0; - return pZip->m_archive_size; -} - -mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) - return 0; - return pZip->m_pState->m_file_archive_start_ofs; -} - -MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip) { - if ((!pZip) || (!pZip->m_pState)) - return 0; - return pZip->m_pState->m_pFile; -} - -size_t mz_zip_read_archive_data(mz_zip_archive *pZip, - mz_uint64 file_ofs, void *pBuf, - size_t n) { - if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - - return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n); -} - -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, - mz_uint file_index, - char *pFilename, - mz_uint filename_buf_size) { - mz_uint n; - const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index); - if (!p) { - if (filename_buf_size) - pFilename[0] = '\0'; - mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); - return 0; - } - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_buf_size) { - n = MZ_MIN(n, filename_buf_size - 1); - memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); - pFilename[n] = '\0'; - } - return n + 1; -} - -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, - mz_uint file_index, - mz_zip_archive_file_stat *pStat) { - return mz_zip_file_stat_internal(pZip, file_index, - mz_zip_get_cdh(pZip, file_index), - pStat, NULL); -} - -mz_bool mz_zip_end(mz_zip_archive *pZip) { - if (!pZip) - return MZ_FALSE; - - if (pZip->m_zip_mode == MZ_ZIP_MODE_READING) - return mz_zip_reader_end(pZip); -# ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || - (pZip->m_zip_mode == - MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)) - return mz_zip_writer_end(pZip); -# endif - - return MZ_FALSE; -} - -# ifdef __cplusplus -} -# endif - -#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/ diff --git a/source/kit/miniz/miniz_zip.h b/source/kit/miniz/miniz_zip.h deleted file mode 100644 index 46c0b43..0000000 --- a/source/kit/miniz/miniz_zip.h +++ /dev/null @@ -1,668 +0,0 @@ -#ifndef KIT_MINIZ_MINIZ_ZIP_H -#define KIT_MINIZ_MINIZ_ZIP_H - -#include "miniz_common.h" -#include "miniz_tdef.h" -#include "miniz_tinfl.h" - -/* ------------------- ZIP archive reading/writing */ - -#ifndef MINIZ_NO_ARCHIVE_APIS - -# ifdef __cplusplus -extern "C" { -# endif - -enum { - /* Note: These enums can be reduced as needed to save memory or - stack space - they are pretty conservative. */ - MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024, - MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 512, - MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 512 -}; - -typedef struct { - /* Central directory file index. */ - mz_uint32 m_file_index; - - /* Byte offset of this entry in the archive's central directory. - * Note we currently only support up to UINT_MAX or less bytes in - * the central dir. */ - mz_uint64 m_central_dir_ofs; - - /* These fields are copied directly from the zip's central dir. */ - mz_uint16 m_version_made_by; - mz_uint16 m_version_needed; - mz_uint16 m_bit_flag; - mz_uint16 m_method; - - /* CRC-32 of uncompressed data. */ - mz_uint32 m_crc32; - - /* File's compressed size. */ - mz_uint64 m_comp_size; - - /* File's uncompressed size. Note, I've seen some old archives where - * directory entries had 512 bytes for their uncompressed sizes, but - * when you try to unpack them you actually get 0 bytes. */ - mz_uint64 m_uncomp_size; - - /* Zip internal and external file attributes. */ - mz_uint16 m_internal_attr; - mz_uint32 m_external_attr; - - /* Entry's local header file offset in bytes. */ - mz_uint64 m_local_header_ofs; - - /* Size of comment in bytes. */ - mz_uint32 m_comment_size; - - /* MZ_TRUE if the entry appears to be a directory. */ - mz_bool m_is_directory; - - /* MZ_TRUE if the entry uses encryption/strong encryption (which - * miniz_zip doesn't support) */ - mz_bool m_is_encrypted; - - /* MZ_TRUE if the file is not encrypted, a patch file, and if it - * uses a compression method we support. */ - mz_bool m_is_supported; - - /* Filename. If string ends in '/' it's a subdirectory entry. */ - /* Guaranteed to be zero terminated, may be truncated to fit. */ - char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; - - /* Comment field. */ - /* Guaranteed to be zero terminated, may be truncated to fit. */ - char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; - -# ifdef MINIZ_NO_TIME - MZ_TIME_T m_padding; -# else - MZ_TIME_T m_time; -# endif -} mz_zip_archive_file_stat; - -typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, - void *pBuf, size_t n); -typedef size_t (*mz_file_write_func)(void *pOpaque, - mz_uint64 file_ofs, - const void *pBuf, size_t n); -typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque); - -struct mz_zip_internal_state_tag; -typedef struct mz_zip_internal_state_tag mz_zip_internal_state; - -typedef enum { - MZ_ZIP_MODE_INVALID = 0, - MZ_ZIP_MODE_READING = 1, - MZ_ZIP_MODE_WRITING = 2, - MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 -} mz_zip_mode; - -typedef enum { - MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, - MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, - MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800, - MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG = - 0x1000, /* if enabled, mz_zip_reader_locate_file() will be - called on each file as its validated to ensure the - func finds the file in the central dir (intended for - testing) */ - MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY = - 0x2000, /* validate the local headers, but don't decompress the - entire file and check the crc32 */ - MZ_ZIP_FLAG_WRITE_ZIP64 = - 0x4000, /* always use the zip64 file format, instead of the - original zip file format with automatic switch to - zip64. Use as flags parameter with - mz_zip_writer_init*_v2 */ - MZ_ZIP_FLAG_WRITE_ALLOW_READING = 0x8000, - MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000, - /*After adding a compressed file, seek back - to local file header and set the correct sizes*/ - MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE = 0x20000 -} mz_zip_flags; - -typedef enum { - MZ_ZIP_TYPE_INVALID = 0, - MZ_ZIP_TYPE_USER, - MZ_ZIP_TYPE_MEMORY, - MZ_ZIP_TYPE_HEAP, - MZ_ZIP_TYPE_FILE, - MZ_ZIP_TYPE_CFILE, - MZ_ZIP_TOTAL_TYPES -} mz_zip_type; - -/* miniz error codes. Be sure to update mz_zip_get_error_string() if - * you add or modify this enum. */ -typedef enum { - MZ_ZIP_NO_ERROR = 0, - MZ_ZIP_UNDEFINED_ERROR, - MZ_ZIP_TOO_MANY_FILES, - MZ_ZIP_FILE_TOO_LARGE, - MZ_ZIP_UNSUPPORTED_METHOD, - MZ_ZIP_UNSUPPORTED_ENCRYPTION, - MZ_ZIP_UNSUPPORTED_FEATURE, - MZ_ZIP_FAILED_FINDING_CENTRAL_DIR, - MZ_ZIP_NOT_AN_ARCHIVE, - MZ_ZIP_INVALID_HEADER_OR_CORRUPTED, - MZ_ZIP_UNSUPPORTED_MULTIDISK, - MZ_ZIP_DECOMPRESSION_FAILED, - MZ_ZIP_COMPRESSION_FAILED, - MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE, - MZ_ZIP_CRC_CHECK_FAILED, - MZ_ZIP_UNSUPPORTED_CDIR_SIZE, - MZ_ZIP_ALLOC_FAILED, - MZ_ZIP_FILE_OPEN_FAILED, - MZ_ZIP_FILE_CREATE_FAILED, - MZ_ZIP_FILE_WRITE_FAILED, - MZ_ZIP_FILE_READ_FAILED, - MZ_ZIP_FILE_CLOSE_FAILED, - MZ_ZIP_FILE_SEEK_FAILED, - MZ_ZIP_FILE_STAT_FAILED, - MZ_ZIP_INVALID_PARAMETER, - MZ_ZIP_INVALID_FILENAME, - MZ_ZIP_BUF_TOO_SMALL, - MZ_ZIP_INTERNAL_ERROR, - MZ_ZIP_FILE_NOT_FOUND, - MZ_ZIP_ARCHIVE_TOO_LARGE, - MZ_ZIP_VALIDATION_FAILED, - MZ_ZIP_WRITE_CALLBACK_FAILED, - MZ_ZIP_TOTAL_ERRORS -} mz_zip_error; - -typedef struct { - mz_uint64 m_archive_size; - mz_uint64 m_central_directory_file_ofs; - - /* We only support up to UINT32_MAX files in zip64 mode. */ - mz_uint32 m_total_files; - mz_zip_mode m_zip_mode; - mz_zip_type m_zip_type; - mz_zip_error m_last_error; - - mz_uint64 m_file_offset_alignment; - - mz_alloc_func m_pAlloc; - mz_free_func m_pFree; - mz_realloc_func m_pRealloc; - void *m_pAlloc_opaque; - - mz_file_read_func m_pRead; - mz_file_write_func m_pWrite; - mz_file_needs_keepalive m_pNeeds_keepalive; - void *m_pIO_opaque; - - mz_zip_internal_state *m_pState; - -} mz_zip_archive; - -typedef struct { - mz_zip_archive *pZip; - mz_uint flags; - - int status; - - mz_uint64 read_buf_size, read_buf_ofs, read_buf_avail, - comp_remaining, out_buf_ofs, cur_file_ofs; - mz_zip_archive_file_stat file_stat; - void *pRead_buf; - void *pWrite_buf; - - size_t out_blk_remain; - - tinfl_decompressor inflator; - -# ifdef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS - mz_uint padding; -# else - mz_uint file_crc32; -# endif - -} mz_zip_reader_extract_iter_state; - -/* -------- ZIP reading */ - -/* Inits a ZIP archive reader. */ -/* These functions read and validate the archive's central directory. - */ -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, - mz_uint flags); - -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, - size_t size, mz_uint flags); - -# ifndef MINIZ_NO_STDIO -/* Read a archive from a disk file. */ -/* file_start_ofs is the file offset where the archive actually - * begins, or 0. */ -/* actual_archive_size is the true total size of the archive, which - * may be smaller than the file's actual size on disk. If zero the - * entire file is treated as the archive. */ -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, - const char *pFilename, - mz_uint32 flags); -mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, - const char *pFilename, - mz_uint flags, - mz_uint64 file_start_ofs, - mz_uint64 archive_size); - -/* Read an archive from an already opened FILE, beginning at the - * current file position. */ -/* The archive is assumed to be archive_size bytes long. If - * archive_size is 0, then the entire rest of the file is assumed to - * contain the archive. */ -/* The FILE will NOT be closed when mz_zip_reader_end() is called. */ -mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, - mz_uint64 archive_size, - mz_uint flags); -# endif - -/* Ends archive reading, freeing all allocations, and closing the - * input archive file if mz_zip_reader_init_file() was used. */ -mz_bool mz_zip_reader_end(mz_zip_archive *pZip); - -/* -------- ZIP reading or writing */ - -/* Clears a mz_zip_archive struct to all zeros. */ -/* Important: This must be done before passing the struct to any - * mz_zip functions. */ -void mz_zip_zero_struct(mz_zip_archive *pZip); - -mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip); -mz_zip_type mz_zip_get_type(mz_zip_archive *pZip); - -/* Returns the total number of files in the archive. */ -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); - -mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip); -mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip); -MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip); - -/* Reads n bytes of raw archive data, starting at file offset - * file_ofs, to pBuf. */ -size_t mz_zip_read_archive_data(mz_zip_archive *pZip, - mz_uint64 file_ofs, void *pBuf, - size_t n); - -/* All mz_zip funcs set the m_last_error field in the mz_zip_archive - * struct. These functions retrieve/manipulate this field. */ -/* Note that the m_last_error functionality is not thread safe. */ -mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, - mz_zip_error err_num); -mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip); -mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip); -mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip); -const char *mz_zip_get_error_string(mz_zip_error mz_err); - -/* MZ_TRUE if the archive file entry is a directory entry. */ -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, - mz_uint file_index); - -/* MZ_TRUE if the file is encrypted/strong encrypted. */ -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, - mz_uint file_index); - -/* MZ_TRUE if the compression method is supported, and the file is not - * encrypted, and the file is not a compressed patch file. */ -mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, - mz_uint file_index); - -/* Retrieves the filename of an archive file entry. */ -/* Returns the number of bytes written to pFilename, or if - * filename_buf_size is 0 this function returns the number of bytes - * needed to fully store the filename. */ -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, - mz_uint file_index, - char *pFilename, - mz_uint filename_buf_size); - -/* Attempts to locates a file in the archive's central directory. */ -/* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */ -/* Returns -1 if the file cannot be found. */ -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, - const char *pComment, mz_uint flags); -mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, - const char *pName, - const char *pComment, - mz_uint flags, - mz_uint32 *file_index); - -/* Returns detailed information about an archive file entry. */ -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, - mz_uint file_index, - mz_zip_archive_file_stat *pStat); - -/* MZ_TRUE if the file is in zip64 format. */ -/* A file is considered zip64 if it contained a zip64 end of central - * directory marker, or if it contained any zip64 extended file - * information fields in the central directory. */ -mz_bool mz_zip_is_zip64(mz_zip_archive *pZip); - -/* Returns the total central directory size in bytes. */ -/* The current max supported size is <= MZ_UINT32_MAX. */ -size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip); - -/* Extracts a archive file to a memory buffer using no memory - * allocation. */ -/* There must be at least enough room on the stack to store the - * inflator's state (~34KB or so). */ -mz_bool mz_zip_reader_extract_to_mem_no_alloc( - mz_zip_archive *pZip, mz_uint file_index, void *pBuf, - size_t buf_size, mz_uint flags, void *pUser_read_buf, - size_t user_read_buf_size); -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc( - mz_zip_archive *pZip, const char *pFilename, void *pBuf, - size_t buf_size, mz_uint flags, void *pUser_read_buf, - size_t user_read_buf_size); - -/* Extracts a archive file to a memory buffer. */ -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, - mz_uint file_index, void *pBuf, - size_t buf_size, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, - const char *pFilename, - void *pBuf, size_t buf_size, - mz_uint flags); - -/* Extracts a archive file to a dynamically allocated heap buffer. */ -/* The memory will be allocated via the mz_zip_archive's alloc/realloc - * functions. */ -/* Returns NULL and sets the last error on failure. */ -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, - mz_uint file_index, size_t *pSize, - mz_uint flags); -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, - const char *pFilename, - size_t *pSize, - mz_uint flags); - -/* Extracts a archive file using a callback function to output the - * file's data. */ -mz_bool mz_zip_reader_extract_to_callback( - mz_zip_archive *pZip, mz_uint file_index, - mz_file_write_func pCallback, void *pOpaque, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_callback( - mz_zip_archive *pZip, const char *pFilename, - mz_file_write_func pCallback, void *pOpaque, mz_uint flags); - -/* Extract a file iteratively */ -mz_zip_reader_extract_iter_state *mz_zip_reader_extract_iter_new( - mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); -mz_zip_reader_extract_iter_state *mz_zip_reader_extract_file_iter_new( - mz_zip_archive *pZip, const char *pFilename, mz_uint flags); -size_t mz_zip_reader_extract_iter_read( - mz_zip_reader_extract_iter_state *pState, void *pvBuf, - size_t buf_size); -mz_bool mz_zip_reader_extract_iter_free( - mz_zip_reader_extract_iter_state *pState); - -# ifndef MINIZ_NO_STDIO -/* Extracts a archive file to a disk file and sets its last accessed - * and modified times. */ -/* This function only extracts files, not archive directory records. - */ -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, - mz_uint file_index, - const char *pDst_filename, - mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_file( - mz_zip_archive *pZip, const char *pArchive_filename, - const char *pDst_filename, mz_uint flags); - -/* Extracts a archive file starting at the current position in the - * destination FILE stream. */ -mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, - mz_uint file_index, - MZ_FILE *File, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_cfile( - mz_zip_archive *pZip, const char *pArchive_filename, - MZ_FILE *pFile, mz_uint flags); -# endif - -# if 0 -/* TODO */ - typedef void *mz_zip_streaming_extract_state_ptr; - mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); - mz_uint64 mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); - mz_uint64 mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); - mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, mz_uint64 new_ofs); - size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size); - mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); -# endif - -/* This function compares the archive's local headers, the optional - * local zip64 extended information block, and the optional descriptor - * following the compressed data vs. the data in the central - * directory. */ -/* It also validates that each file can be successfully uncompressed - * unless the MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY is specified. */ -mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, - mz_uint flags); - -/* Validates an entire archive by calling mz_zip_validate_file() on - * each file. */ -mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags); - -/* Misc utils/helpers, valid for ZIP reading or writing */ -mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, - mz_uint flags, - mz_zip_error *pErr); -# ifndef MINIZ_NO_STDIO -mz_bool mz_zip_validate_file_archive(const char *pFilename, - mz_uint flags, - mz_zip_error *pErr); -# endif - -/* Universal end function - calls either mz_zip_reader_end() or - * mz_zip_writer_end(). */ -mz_bool mz_zip_end(mz_zip_archive *pZip); - -/* -------- ZIP writing */ - -# ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -/* Inits a ZIP archive writer. */ -/*Set pZip->m_pWrite (and pZip->m_pIO_opaque) before calling - * mz_zip_writer_init or mz_zip_writer_init_v2*/ -/*The output is streamable, i.e. file_ofs in mz_file_write_func always - * increases only by n*/ -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, - mz_uint64 existing_size); -mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, - mz_uint64 existing_size, mz_uint flags); - -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, - size_t size_to_reserve_at_beginning, - size_t initial_allocation_size); -mz_bool mz_zip_writer_init_heap_v2( - mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, - size_t initial_allocation_size, mz_uint flags); - -# ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_init_file( - mz_zip_archive *pZip, const char *pFilename, - mz_uint64 size_to_reserve_at_beginning); -mz_bool mz_zip_writer_init_file_v2( - mz_zip_archive *pZip, const char *pFilename, - mz_uint64 size_to_reserve_at_beginning, mz_uint flags); -mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, - mz_uint flags); -# endif - -/* Converts a ZIP archive reader object into a writer object, to allow - * efficient in-place file appends to occur on an existing archive. */ -/* For archives opened using mz_zip_reader_init_file, pFilename must - * be the archive's filename so it can be reopened for writing. If the - * file can't be reopened, mz_zip_reader_end() will be called. */ -/* For archives opened using mz_zip_reader_init_mem, the memory block - * must be growable using the realloc callback (which defaults to - * realloc unless you've overridden it). */ -/* Finally, for archives opened using mz_zip_reader_init, the - * mz_zip_archive's user provided m_pWrite function cannot be NULL. */ -/* Note: In-place archive modification is not recommended unless you - * know what you're doing, because if execution stops or something - * goes wrong before */ -/* the archive is finalized the file's central directory will be - * hosed. */ -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, - const char *pFilename); -mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, - const char *pFilename, - mz_uint flags); - -/* Adds the contents of a memory buffer to an archive. These functions - * record the current local time into the archive. */ -/* To add a directory entry, call this method with an archive name - * ending in a forwardslash with an empty buffer. */ -/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, - * MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more - * mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, - const char *pArchive_name, - const void *pBuf, size_t buf_size, - mz_uint level_and_flags); - -/* Like mz_zip_writer_add_mem(), except you can specify a file comment - * field, and optionally supply the function with already compressed - * data. */ -/* uncomp_size/uncomp_crc32 are only used if the - * MZ_ZIP_FLAG_COMPRESSED_DATA flag is specified. */ -mz_bool mz_zip_writer_add_mem_ex( - mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, - size_t buf_size, const void *pComment, mz_uint16 comment_size, - mz_uint level_and_flags, mz_uint64 uncomp_size, - mz_uint32 uncomp_crc32); - -mz_bool mz_zip_writer_add_mem_ex_v2( - mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, - size_t buf_size, const void *pComment, mz_uint16 comment_size, - mz_uint level_and_flags, mz_uint64 uncomp_size, - mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, - const char *user_extra_data_local, - mz_uint user_extra_data_local_len, - const char *user_extra_data_central, - mz_uint user_extra_data_central_len); - -/* Adds the contents of a file to an archive. This function also - * records the disk file's modified time into the archive. */ -/* File data is supplied via a read callback function. User - * mz_zip_writer_add_(c)file to add a file directly.*/ -mz_bool mz_zip_writer_add_read_buf_callback( - mz_zip_archive *pZip, const char *pArchive_name, - mz_file_read_func read_callback, void *callback_opaque, - mz_uint64 max_size, const MZ_TIME_T *pFile_time, - const void *pComment, mz_uint16 comment_size, - mz_uint level_and_flags, const char *user_extra_data_local, - mz_uint user_extra_data_local_len, - const char *user_extra_data_central, - mz_uint user_extra_data_central_len); - -# ifndef MINIZ_NO_STDIO -/* Adds the contents of a disk file to an archive. This function also - * records the disk file's modified time into the archive. */ -/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, - * MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more - * mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, - const char *pArchive_name, - const char *pSrc_filename, - const void *pComment, - mz_uint16 comment_size, - mz_uint level_and_flags); - -/* Like mz_zip_writer_add_file(), except the file data is read from - * the specified FILE stream. */ -mz_bool mz_zip_writer_add_cfile( - mz_zip_archive *pZip, const char *pArchive_name, - MZ_FILE *pSrc_file, mz_uint64 max_size, - const MZ_TIME_T *pFile_time, const void *pComment, - mz_uint16 comment_size, mz_uint level_and_flags, - const char *user_extra_data_local, - mz_uint user_extra_data_local_len, - const char *user_extra_data_central, - mz_uint user_extra_data_central_len); -# endif - -/* Adds a file to an archive by fully cloning the data from another - * archive. */ -/* This function fully clones the source file's compressed data (no - * recompression), along with its full filename, extra data (it may - * add or modify the zip64 local header extra data field), and the - * optional descriptor following the compressed data. */ -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, - mz_zip_archive *pSource_zip, - mz_uint src_file_index); - -/* Finalizes the archive by writing the central directory records - * followed by the end of central directory record. */ -/* After an archive is finalized, the only valid call on the - * mz_zip_archive struct is mz_zip_writer_end(). */ -/* An archive must be manually finalized by calling this function for - * it to be valid. */ -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); - -/* Finalizes a heap archive, returning a pointer to the heap block and - * its size. */ -/* The heap block will be allocated using the mz_zip_archive's - * alloc/realloc callbacks. */ -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, - void **ppBuf, - size_t *pSize); - -/* Ends archive writing, freeing all allocations, and closing the - * output file if mz_zip_writer_init_file() was used. */ -/* Note for the archive to be valid, it *must* have been finalized - * before ending (this function will not do it for you). */ -mz_bool mz_zip_writer_end(mz_zip_archive *pZip); - -/* -------- Misc. high-level helper functions: */ - -/* mz_zip_add_mem_to_archive_file_in_place() efficiently (but not - * atomically) appends a memory blob to a ZIP archive. */ -/* Note this is NOT a fully safe operation. If it crashes or dies in - * some way your archive can be left in a screwed up state (without a - * central directory). */ -/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, - * MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more - * mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ -/* TODO: Perhaps add an option to leave the existing central dir in - * place in case the add dies? We could then truncate the file (so the - * old central dir would be at the end) if something goes wrong. */ -mz_bool mz_zip_add_mem_to_archive_file_in_place( - const char *pZip_filename, const char *pArchive_name, - const void *pBuf, size_t buf_size, const void *pComment, - mz_uint16 comment_size, mz_uint level_and_flags); -mz_bool mz_zip_add_mem_to_archive_file_in_place_v2( - const char *pZip_filename, const char *pArchive_name, - const void *pBuf, size_t buf_size, const void *pComment, - mz_uint16 comment_size, mz_uint level_and_flags, - mz_zip_error *pErr); - -# ifndef MINIZ_NO_STDIO -/* Reads a single file from an archive into a heap block. */ -/* If pComment is not NULL, only the file with the specified comment - * will be extracted. */ -/* Returns NULL on failure. */ -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, - const char *pArchive_name, - size_t *pSize, - mz_uint flags); -void *mz_zip_extract_archive_file_to_heap_v2( - const char *pZip_filename, const char *pArchive_name, - const char *pComment, size_t *pSize, mz_uint flags, - mz_zip_error *pErr); -# endif - -# endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */ - -# ifdef __cplusplus -} -# endif - -#endif /* MINIZ_NO_ARCHIVE_APIS */ - -#endif diff --git a/source/kit/move_back.h b/source/kit/move_back.h deleted file mode 100644 index 1885f5d..0000000 --- a/source/kit/move_back.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef KIT_MOVE_BACK_H -#define KIT_MOVE_BACK_H - -#include "types.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 - -#define MOVE_BACK_INL KIT_MOVE_BACK_INL -#define MOVE_BACK KIT_MOVE_BACK -#define MOVE_BACK_REF KIT_MOVE_BACK_REF - -#endif diff --git a/source/kit/parse.c b/source/kit/parse.c deleted file mode 100644 index 042e2d0..0000000 --- a/source/kit/parse.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "parse.h" - diff --git a/source/kit/parse.h b/source/kit/parse.h deleted file mode 100644 index efb8156..0000000 --- a/source/kit/parse.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef KIT_PARSE_H -#define KIT_PARSE_H - -#include "string_builder.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/print.c b/source/kit/print.c deleted file mode 100644 index 5c98910..0000000 --- a/source/kit/print.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "print.h" - diff --git a/source/kit/print.h b/source/kit/print.h deleted file mode 100644 index 5a64a20..0000000 --- a/source/kit/print.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef KIT_PRINT_H -#define KIT_PRINT_H - -#include "string_builder.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - KIT_PRINT_ALIGN_RIGHT = 1, - KIT_PRINT_UNSIGNED = (1 << 1), - KIT_PRINT_BIN = (1 << 2), - KIT_PRINT_OCT = (1 << 3), - KIT_PRINT_DEC = (1 << 4), - KIT_PRINT_HEX = (1 << 5), - KIT_PRINT_PRECISE = (1 << 6), - KIT_PRINT_UTF8 = (1 << 7), -}; - -s32 kit_print_int(kit_str_builder_t *s, i64 value, i64 width, c8 fill, - u32 flags); - -s32 kit_print_float(kit_str_builder_t *s, f64 value, i64 width, - c8 fill, u32 flags); - -s32 kit_print_esc(kit_str_builder_t *s, kit_str_t value, - c8 escape_char, kit_str_t special_symbols, - u32 flags); - -#ifdef __cplusplus -} -#endif - -#define PRINT_ALIGN_RIGHT KIT_PRINT_ALIGN_RIGHT -#define PRINT_UNSIGNED KIT_PRINT_UNSIGNED -#define PRINT_BIN KIT_PRINT_BIN -#define PRINT_OCT KIT_PRINT_OCT -#define PRINT_DEC KIT_PRINT_DEC -#define PRINT_HEX KIT_PRINT_HEX -#define PRINT_PRECISE KIT_PRINT_PRECISE -#define PRINT_UTF8 KIT_PRINT_UTF8 -#define print_int kit_print_int -#define print_float kit_print_float -#define print_esckit_print_esc - -#endif diff --git a/source/kit/process.h b/source/kit/process.h deleted file mode 100644 index 8031cc1..0000000 --- a/source/kit/process.h +++ /dev/null @@ -1,71 +0,0 @@ -// TODO -// - -#ifndef KIT_PROCESS_H -#define KIT_PROCESS_H - -#include "types.h" -#include "string_ref.h" - -#if !defined(_WIN32) || defined(__CYGWIN__) -# include <unistd.h> -#else -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - KIT_PROCESS_NO_ARGUMENTS = 1, - KIT_PROCESS_NO_ENVIRONMENT = (1 << 1), - KIT_PROCESS_NO_PIPES = (1 << 2), - KIT_PROCESS_FORK = (1 << 3), -}; - -typedef struct { - s32 status; - u8 exit_code; - b8 current_is_forked; -#if !defined(_WIN32) || defined(__CYGWIN__) - b8 _ready; - b8 _running; - pid_t _id; - i32 _stdin; - i32 _stdout; - i32 _stderr; -#else -#endif -} kit_process_t; - -typedef struct { - kit_str_t name; - kit_str_t value; -} kit_process_env_var_t; - -typedef KIT_AR(kit_str_t) kit_process_args_t; -typedef KIT_AR(kit_process_env_var_t) kit_process_env_t; - -typedef struct { - u32 flags; - kit_str_t file_name; - kit_process_args_t command_line; - kit_process_env_t environment; - kit_str_t working_directory; -} kit_process_info_t; - -s32 kit_process_init(kit_process_t *p, kit_process_info_t info); -void kit_process_cleanup(kit_process_t *p); - -i64 kit_process_write_stdin(kit_process_t *p, kit_str_t in_data); -i64 kit_process_read_stdout(kit_process_t *p, kit_str_t out_data); -i64 kit_process_read_stderr(kit_process_t *p, kit_str_t out_data); -s32 kit_process_terminate(kit_process_t *p); -b8 kit_process_alive(kit_process_t *p); -s32 kit_process_wait(kit_process_t *p); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/process.posix.c b/source/kit/process.posix.c deleted file mode 100644 index 961f058..0000000 --- a/source/kit/process.posix.c +++ /dev/null @@ -1,319 +0,0 @@ -#include "process.h" - -#if !defined(_WIN32) || defined(__CYGWIN__) -# include "status.h" - -# include <assert.h> -# include <fcntl.h> -# include <signal.h> -# include <sys/wait.h> - -static char *kit_process_argv_null_[] = { "", NULL }; -static char *kit_process_env_null_[] = { NULL }; - -static char *kit_process_str_(kit_str_t s) { - // FIXME - // - - return BS(s); -} - -static char **kit_init_argv_(kit_process_args_t args, u32 flags) { - // TODO - // - - if ((flags & KIT_PROCESS_NO_ARGUMENTS) != 0) - return kit_process_argv_null_; - - return NULL; -} - -static char **kit_init_envp_(kit_process_env_t env, u32 flags) { - // TODO - // - - if ((flags & KIT_PROCESS_NO_ENVIRONMENT) != 0) - return kit_process_env_null_; - - return NULL; -} - -s32 kit_process_init(kit_process_t *p, kit_process_info_t info) { - assert(p != NULL); - assert(info.working_directory.size == 0 || - info.working_directory.values != NULL); - - if (p == NULL || (info.working_directory.size != 0 && - info.working_directory.values == NULL)) - return KIT_ERROR_INVALID_ARGUMENT; - - memset(p, 0, sizeof *p); - - p->_stdin = -1; - p->_stdout = -1; - p->_stderr = -1; - - signal(SIGCHLD, SIG_IGN); - signal(SIGALRM, SIG_IGN); // pipes - - i32 pipe_in[2]; - i32 pipe_out[2]; - i32 pipe_err[2]; - - if ((info.flags & KIT_PROCESS_NO_PIPES) == 0) { - if (pipe(pipe_in) == -1) { - assert(0); - return KIT_ERROR_PIPE_FAILED; - } - - if (pipe(pipe_out) == -1) { - assert(0); - close(pipe_in[0]); - close(pipe_in[1]); - return KIT_ERROR_PIPE_FAILED; - } - - if (pipe(pipe_err) == -1) { - assert(0); - close(pipe_in[0]); - close(pipe_in[1]); - close(pipe_out[0]); - close(pipe_out[1]); - return KIT_ERROR_PIPE_FAILED; - } - - // non-blocking writing for stdout, stderr - if (fcntl(pipe_out[1], F_SETFL, O_NONBLOCK) == -1 || - fcntl(pipe_err[1], F_SETFL, O_NONBLOCK) == -1) { - assert(0); - close(pipe_in[0]); - close(pipe_in[1]); - close(pipe_out[0]); - close(pipe_out[1]); - close(pipe_err[0]); - close(pipe_err[1]); - return KIT_ERROR_PIPE_FAILED; - } - } - - pid_t id = fork(); - - switch (id) { - case -1: return KIT_ERROR_FORK_FAILED; - - case 0: - // Child process - // - - p->status = KIT_OK; - p->current_is_forked = 1; - - if ((info.flags & KIT_PROCESS_NO_PIPES) == 0) { - // Redirect IO - if (dup2(pipe_in[0], STDIN_FILENO) == -1 || - dup2(pipe_out[1], STDOUT_FILENO) == -1 || - dup2(pipe_err[1], STDERR_FILENO) == -1) { - assert(0); - close(pipe_in[0]); - close(pipe_in[1]); - close(pipe_out[0]); - close(pipe_out[1]); - close(pipe_err[0]); - close(pipe_err[1]); - return KIT_ERROR_DUP2_FAILED; - } - - // Close pipes - close(pipe_in[0]); - close(pipe_in[1]); - close(pipe_out[0]); - close(pipe_out[1]); - close(pipe_err[0]); - close(pipe_err[1]); - } - - // Change working directory - if (info.working_directory.size != 0 && - chdir(kit_process_str_(info.working_directory)) == -1) { - assert(0); - return KIT_ERROR_CHDIR_FAILED; - } - - if ((info.flags & KIT_PROCESS_FORK) == 0) { - execve(kit_process_str_(info.file_name), - kit_init_argv_(info.command_line, info.flags), - kit_init_envp_(info.environment, info.flags)); - // Doesn't return on success - - return KIT_ERROR_EXECVE_FAILED; - } - - return KIT_OK; - - default: - // Parent process - // - - p->status = KIT_OK; - p->current_is_forked = 0; - p->_ready = 1; - p->_running = 1; - p->_id = id; - - if ((info.flags & KIT_PROCESS_NO_PIPES) == 0) { - p->_stdin = pipe_in[1]; - p->_stdout = pipe_out[0]; - p->_stderr = pipe_err[0]; - - // Close unused pipes - close(pipe_in[0]); - close(pipe_out[1]); - close(pipe_err[1]); - } - } - - return KIT_OK; -} - -void kit_process_cleanup(kit_process_t *p) { - assert(p != NULL); - assert(p->_ready); - - if (p == NULL || !p->_ready) - return; - - if (p->_stdin != -1) - close(p->_stdin); - if (p->_stdout != -1) - close(p->_stdout); - if (p->_stderr != -1) - close(p->_stderr); - - memset(p, 0, sizeof *p); -} - -i64 kit_process_write_stdin(kit_process_t *p, kit_str_t in_data) { - assert(p != NULL && (in_data.size == 0 || in_data.values != NULL) && - p->_running); - - if (p == NULL || (in_data.size != 0 && in_data.values == NULL)) - return KIT_ERROR_INVALID_ARGUMENT; - if (in_data.size == 0 || !p->_running || p->_stdin == -1) - return 0; - - i64 n = write(p->_stdin, in_data.values, in_data.size); - - assert(n >= 0); - if (n < 0) - return 0; - - return n; -} - -i64 kit_process_read_stdout(kit_process_t *p, kit_str_t out_data) { - assert(p != NULL && - (out_data.size == 0 || out_data.values != NULL) && - p->_ready); - - if (p == NULL || (out_data.size != 0 && out_data.values == NULL)) - return KIT_ERROR_INVALID_ARGUMENT; - if (out_data.size == 0 || !p->_ready || p->_stdout == -1) - return 0; - - i64 n = read(p->_stdout, out_data.values, out_data.size); - - assert(n >= 0); - if (n < 0) - return 0; - - return n; -} - -i64 kit_process_read_stderr(kit_process_t *p, kit_str_t out_data) { - assert(p != NULL && - (out_data.size == 0 || out_data.values != NULL) && - p->_ready); - - if (p == NULL || (out_data.size != 0 && out_data.values == NULL)) - return KIT_ERROR_INVALID_ARGUMENT; - if (out_data.size == 0 || !p->_ready || p->_stderr == -1) - return 0; - - i64 n = read(p->_stderr, out_data.values, out_data.size); - - assert(n >= 0); - if (n < 0) - return 0; - - return n; -} - -s32 kit_process_terminate(kit_process_t *p) { - assert(p != NULL && p->_running); - if (p == NULL || !p->_running) - return KIT_ERROR_INVALID_ARGUMENT; - - if (kill(p->_id, SIGTERM) == -1) - return KIT_ERROR_KILL_FAILED; - - return KIT_OK; -} - -b8 kit_process_alive(kit_process_t *p) { - assert(p != NULL); - if (p == NULL || p->status != KIT_OK) - return 0; - - if (!p->_running) - return 0; - - int status; - - pid_t id = waitpid(p->_id, &status, WNOHANG); - - if (id == -1) { - p->status = KIT_ERROR_WAITPID_FAILED; - return 0; - } - - if (id == 0) - return 1; - - if (WIFEXITED(status)) { - p->exit_code = WEXITSTATUS(status); - p->_running = 0; - return 0; - } - - return 1; -} - -s32 kit_process_wait(kit_process_t *p) { - assert(p != NULL); - if (p == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - - if (p->status != KIT_OK) - return p->status; - if (!p->_running) - return KIT_OK; - - for (;;) { - int status; - - pid_t id = waitpid(p->_id, &status, 0); - - if (id == -1) - return KIT_ERROR_WAITPID_FAILED; - - if (WIFEXITED(status)) { - p->exit_code = WEXITSTATUS(status); - p->_running = 0; - break; - } - } - - return KIT_OK; -} - -#endif diff --git a/source/kit/process.win32.c b/source/kit/process.win32.c deleted file mode 100644 index ebff7b1..0000000 --- a/source/kit/process.win32.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "process.h" - -#if defined(_WIN32) && !defined(__CYGWIN__) - -#endif diff --git a/source/kit/secure_random.c b/source/kit/secure_random.c deleted file mode 100644 index 2f53866..0000000 --- a/source/kit/secure_random.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "secure_random.h" - -#include "status.h" - -#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 - -s32 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; -} diff --git a/source/kit/secure_random.h b/source/kit/secure_random.h deleted file mode 100644 index d09ea56..0000000 --- a/source/kit/secure_random.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef KIT_SECURE_RANDOM_H -#define KIT_SECURE_RANDOM_H - -#include "types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -s32 kit_secure_random(i64 size, void *data); - -#ifdef __cplusplus -} -#endif - -#define secure_random kit_secure_random - -#endif diff --git a/source/kit/sha256.c b/source/kit/sha256.c deleted file mode 100644 index 3abe972..0000000 --- a/source/kit/sha256.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "sha256.h" - -#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 diff --git a/source/kit/sha256.h b/source/kit/sha256.h deleted file mode 100644 index da05385..0000000 --- a/source/kit/sha256.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef KIT_SHA256_H -#define KIT_SHA256_H - -#include "types.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 - -#define SHA256_BLOCK_SIZE KIT_SHA256_BLOCK_SIZE -#define sha256_hash_t kit_sha256_hash_t -#define sha256 kit_sha256 - -#endif diff --git a/source/kit/shared_memory.h b/source/kit/shared_memory.h deleted file mode 100644 index a13ccee..0000000 --- a/source/kit/shared_memory.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef KIT_SHARED_MEMORY_H -#define KIT_SHARED_MEMORY_H - -#include "status.h" -#include "string_ref.h" - -#if !defined(_WIN32) || defined(__CYGWIN__) -# include <limits.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - s32 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); -s32 kit_shared_memory_close(kit_shared_memory_t *mem); -s32 kit_shared_memory_clean(kit_str_t name); - -#ifdef __cplusplus -} -#endif - -#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 diff --git a/source/kit/shared_memory.posix.c b/source/kit/shared_memory.posix.c deleted file mode 100644 index fa0db98..0000000 --- a/source/kit/shared_memory.posix.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "shared_memory.h" - -#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; -} - -s32 kit_shared_memory_close(kit_shared_memory_t *mem) { - assert(mem != NULL); - - if (mem == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - - s32 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; -} - -s32 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 diff --git a/source/kit/shared_memory.win32.c b/source/kit/shared_memory.win32.c deleted file mode 100644 index 61b7317..0000000 --- a/source/kit/shared_memory.win32.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "shared_memory.h" - -#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; -} - -s32 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; -} - -s32 kit_shared_memory_clean(kit_str_t name) { - // Do nothing. - // - - return KIT_OK; -} -#endif diff --git a/source/kit/shared_mutex.h b/source/kit/shared_mutex.h deleted file mode 100644 index ad83418..0000000 --- a/source/kit/shared_mutex.h +++ /dev/null @@ -1,176 +0,0 @@ -// Shared mutex can be used in shared memory for interprocess -// synchronization. -// - -#ifndef KIT_SHARED_MUTEX_H -#define KIT_SHARED_MUTEX_H - -#include "atomic.h" -#include "threads.h" - -#include <assert.h> -#include <string.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#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 - -enum { - KIT_SHARED_MUTEX_READY = 1, - KIT_SHARED_MUTEX_LOCKED, - KIT_SHARED_MUTEX_WRITER -}; - -typedef union { - struct { - i8 _Atomic state; - i32 readers; - }; - struct { - u8 _pad[16]; - }; -} kit_shared_mutex_t; - -static void kit_shared_mutex_init(kit_shared_mutex_t *m) { - assert(m != NULL); - memset(m, 0, sizeof *m); - - atomic_store_explicit(&m->state, KIT_SHARED_MUTEX_READY, - memory_order_relaxed); -} - -static b8 kit_shared_try_lock(kit_shared_mutex_t *m) { - assert(m != NULL); - - for (;;) { - i8 prev_state = KIT_SHARED_MUTEX_READY; - if (atomic_compare_exchange_strong_explicit( - &m->state, &prev_state, KIT_SHARED_MUTEX_LOCKED, - memory_order_seq_cst, memory_order_seq_cst)) - break; - if (prev_state == KIT_SHARED_MUTEX_WRITER) - return 0; - // FIXME - // Check performance - thrd_yield(); - } - - assert(m->readers >= 0); - ++m->readers; - - i8 prev_state = KIT_SHARED_MUTEX_LOCKED; - if (!atomic_compare_exchange_strong_explicit( - &m->state, &prev_state, KIT_SHARED_MUTEX_READY, - memory_order_seq_cst, memory_order_seq_cst)) - assert(0); - - return 1; -} - -static void kit_shared_lock(kit_shared_mutex_t *m) { - assert(m != NULL); - - while (!kit_shared_try_lock(m)) - // FIXME - // Check performance - thrd_yield(); -} - -static void kit_shared_unlock(kit_shared_mutex_t *m) { - assert(m != NULL); - - for (;;) { - i8 prev_state = KIT_SHARED_MUTEX_READY; - if (atomic_compare_exchange_strong_explicit( - &m->state, &prev_state, KIT_SHARED_MUTEX_LOCKED, - memory_order_seq_cst, memory_order_seq_cst)) - break; - // FIXME - // Check performance - thrd_yield(); - } - - assert(m->readers > 0); - m->readers--; - - i8 prev_state = KIT_SHARED_MUTEX_LOCKED; - if (!atomic_compare_exchange_strong_explicit( - &m->state, &prev_state, KIT_SHARED_MUTEX_READY, - memory_order_seq_cst, memory_order_seq_cst)) - assert(0); -} - -static b8 kit_unique_try_lock(kit_shared_mutex_t *m) { - assert(m != NULL); - - i8 prev_state = KIT_SHARED_MUTEX_READY; - if (!atomic_compare_exchange_strong_explicit( - &m->state, &prev_state, KIT_SHARED_MUTEX_WRITER, - memory_order_seq_cst, memory_order_seq_cst)) - return 0; - - i8 is_locked = (m->readers == 0); - - prev_state = KIT_SHARED_MUTEX_WRITER; - if (!is_locked && - !atomic_compare_exchange_strong_explicit( - &m->state, &prev_state, KIT_SHARED_MUTEX_READY, - memory_order_seq_cst, memory_order_seq_cst)) - assert(0); - - return is_locked; -} - -static void kit_unique_lock(kit_shared_mutex_t *m) { - assert(m != NULL); - - while (!kit_unique_try_lock(m)) - // FIXME - // Check performance - thrd_yield(); -} - -static void kit_unique_unlock(kit_shared_mutex_t *m) { - assert(m != NULL); - - i8 prev_state = KIT_SHARED_MUTEX_WRITER; - if (!atomic_compare_exchange_strong_explicit( - &m->state, &prev_state, KIT_SHARED_MUTEX_READY, - memory_order_seq_cst, memory_order_seq_cst)) - assert(0); -} - -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#define shared_mutex_t kit_shared_mutex_t -#define shared_mutex_init kit_shared_mutex_init -#define shared_try_lock kit_shared_try_lock -#define shared_lock kit_shared_lock -#define shared_unlock kit_shared_unlock -#define unique_try_lock kit_unique_try_lock -#define unique_lock kit_unique_lock -#define unique_unlock kit_unique_unlock -#define shared_mutex_init kit_shared_mutex_init -#define shared_try_lock kit_shared_try_lock -#define shared_lock kit_shared_lock -#define shared_unlock kit_shared_unlock -#define unique_try_lock kit_unique_try_lock -#define unique_lock kit_unique_lock -#define unique_unlock kit_unique_unlock - -#endif diff --git a/source/kit/sockets.h b/source/kit/sockets.h deleted file mode 100644 index 276ecc5..0000000 --- a/source/kit/sockets.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef KIT_SOCKETS_H -#define KIT_SOCKETS_H - -#include "types.h" -#include "status.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 s32 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 s32 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 s32 kit_sockets_init(void) { - signal(SIGPIPE, SIG_IGN); - return KIT_OK; -} - -static s32 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 diff --git a/source/kit/status.h b/source/kit/status.h deleted file mode 100644 index 88eb5e0..0000000 --- a/source/kit/status.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef KIT_STATUS_H -#define KIT_STATUS_H - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -enum { - KIT_OK = 0, - KIT_PARSING_FAILED = 1, - KIT_ERROR_OUT_OF_MEMORY = (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_FORK_FAILED = (1 << 22), - KIT_ERROR_EXECVE_FAILED = (1 << 23), - KIT_ERROR_WAITPID_FAILED = (1 << 24), - KIT_ERROR_PIPE_FAILED = (1 << 25), - KIT_ERROR_DUP2_FAILED = (1 << 26), - KIT_ERROR_CHDIR_FAILED = (1 << 27), - KIT_ERROR_KILL_FAILED = (1 << 28), - KIT_ERROR_INTERNAL = (1 << 30), - KIT_ERROR_NOT_IMPLEMENTED = -1, -}; - -#endif diff --git a/source/kit/string_builder.h b/source/kit/string_builder.h deleted file mode 100644 index 23eda65..0000000 --- a/source/kit/string_builder.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef KIT_STRING_BUILDER_H -#define KIT_STRING_BUILDER_H - -#include "status.h" -#include "string_ref.h" -#include "dynamic_array.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) { - assert(s.size >= 0 && (s.size == 0 || s.values != NULL)); - kit_str_builder_t builder; - memset(&builder, 0, sizeof builder); - if (s.size < 0 || (s.size != 0 && s.values == NULL)) - return 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_str_builder_t kit_substr_build(kit_str_t s, i64 index, - i64 size, - kit_allocator_t *alloc) { - assert(index + size <= s.size); - if (index + size > s.size) { - kit_str_builder_t builder; - memset(&builder, 0, sizeof builder); - return builder; - } - return kit_str_build(kit_str(size, s.values + index), alloc); -} - -static s32 kit_str_append(kit_str_builder_t *a, kit_str_t b) { - assert(a != NULL); - if (a == NULL) - return KIT_ERROR_INVALID_ARGUMENT; - 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_OUT_OF_MEMORY; - memcpy(a->values + n, b.values, b.size); - return KIT_OK; -} - -static s32 kit_str_insert(kit_str_builder_t *a, i64 index, - kit_str_t b) { - assert(a != NULL && index >= 0 && index <= a->size); - if (a == NULL || index < 0 || index > a->size) - 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_OUT_OF_MEMORY; - if (index < n) - memmove(a->values + (index + b.size), a->values + index, - n - index); - memcpy(a->values + index, b.values, b.size); - return KIT_OK; -} - -static s32 kit_str_erase(kit_str_builder_t *a, i64 index, i64 size) { - assert(a != NULL && index >= 0 && size >= 0 && - index + size <= a->size); - if (a == NULL || index < 0 || size < 0 || index + size > a->size) - return KIT_ERROR_INVALID_ARGUMENT; - if (size <= 0) - return KIT_OK; - if (index + size < a->size) - memmove(a->values + index, a->values + (index + size), - a->size - index - size); - KIT_DA_RESIZE(*a, a->size - size); - return KIT_OK; -} - -#ifdef __GNUC__ -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#define str_builder_t kit_str_builder_t -#define str_build kit_str_build -#define substr_build kit_substr_build -#define str_append kit_str_append -#define str_insert kit_str_insert -#define str_erase kit_str_erase - -#endif diff --git a/source/kit/string_ref.h b/source/kit/string_ref.h deleted file mode 100644 index e7ea809..0000000 --- a/source/kit/string_ref.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef KIT_STRING_REF_H -#define KIT_STRING_REF_H - -#include "array_ref.h" - -#include <assert.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; -} - -enum { - KIT_STR_NOT_FOUND = -1, -}; - -static i64 kit_str_find(kit_str_t a, kit_str_t b) { - assert(a.size >= 0 && (a.size == 0 || a.values != NULL) && - b.size >= 0 && (b.size == 0 || b.values != NULL)); - if (a.size < 0 || (a.size != 0 && a.values == NULL) || b.size < 0 || - (b.size != 0 && b.values == NULL)) - return -1; - for (i64 index = 0; index + b.size <= a.size; index++) - if (KIT_AR_EQUAL(kit_str(b.size, a.values + index), b)) - return index; - return -1; -} - -static i64 kit_str_find_back(kit_str_t a, kit_str_t b) { - assert(a.size >= 0 && (a.size == 0 || a.values != NULL) && - b.size >= 0 && (b.size == 0 || b.values != NULL)); - if (a.size < 0 || (a.size != 0 && a.values == NULL) || b.size < 0 || - (b.size != 0 && b.values == NULL)) - return -1; - for (i64 index = a.size - b.size; index >= 0; index--) - if (KIT_AR_EQUAL(kit_str(b.size, a.values + index), b)) - return index; - return -1; -} - -static i64 kit_str_find_n(kit_str_t a, kit_str_t b, i64 n) { - assert(a.size >= 0 && (a.size == 0 || a.values != NULL) && - b.size >= 0 && (b.size == 0 || b.values != NULL)); - if (a.size < 0 || (a.size != 0 && a.values == NULL) || b.size < 0 || - (b.size != 0 && b.values == NULL)) - return -1; - i64 count = 0; - for (i64 index = 0; index + b.size <= a.size; index++) - if (KIT_AR_EQUAL(kit_str(b.size, a.values + index), b)) { - if (count == n) - return index; - else - count++; - } - return -1; -} - -static i64 kit_str_find_back_n(kit_str_t a, kit_str_t b, i64 n) { - assert(a.size >= 0 && (a.size == 0 || a.values != NULL) && - b.size >= 0 && (b.size == 0 || b.values != NULL)); - if (a.size < 0 || (a.size != 0 && a.values == NULL) || b.size < 0 || - (b.size != 0 && b.values == NULL)) - return -1; - i64 count = 0; - for (i64 index = a.size - b.size; index >= 0; index--) - if (KIT_AR_EQUAL(kit_str(b.size, a.values + index), b)) { - if (count == n) - return index; - else - count++; - } - return -1; -} - -// 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) - -#ifdef __cplusplus -} -#endif - -#define BS(...) kit_make_bs(KIT_WRAP_STR(__VA_ARGS__)) -#define str_t kit_str_t -#define str kit_str -#define str_find kit_str_find -#define str_find_back kit_str_find_back -#define str_find_n kit_str_find_n -#define str_find_back_n kit_str_find_back_n -#define STR_NOT_FOUND KIT_STR_NOT_FOUND -#define SZ KIT_SZ -#define WRAP_BS KIT_WRAP_BS -#define WRAP_STR KIT_WRAP_STR - -#endif diff --git a/source/kit/test.h b/source/kit/test.h deleted file mode 100644 index ca2b7c0..0000000 --- a/source/kit/test.h +++ /dev/null @@ -1,1111 +0,0 @@ -// ================================================================ -// -// test.h -// https://guattari.tech/git/kit -// -// Header-only unit-testing and microbenchmarks library for C. -// -// -// - Define a unique KIT_TEST_FILE for each file to avoid name -// collisions. -// -// - Define KIT_TEST_IMPLEMENTATION to include the implementation. -// -// -// Optional settings -// -// - KIT_TESTS_SIZE_LIMIT -// - KIT_TEST_ASSERTIONS_LIMIT -// - KIT_BENCHS_SIZE_LIMIT -// - KIT_BENCH_MAX_REPEATS -// - KIT_BENCH_MAX_CYCLES -// - KIT_BENCH_REPEATS_DEFAULT_1 -// - KIT_BENCH_REPEATS_DEFAULT_2 -// -// -// Usage example -// -// // foo.test.c -// #define KIT_TEST_FILE foo // This is required if you want to -// // use multiple test files. -// #include "test.h" -// TEST("foo") { -// REQUIRE(1); -// REQUIRE_EQ(2 + 2, 4); -// } -// -// // main.c -// #define KIT_TEST_IMPLEMENTATION -// #include "test.h" -// int main(int argc, char **argv) { -// return run_tests(argc, argv); -// } -// -// ================================================================ -// -// The MIT License -// -// Copyright (c) 2022-2024 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_TEST_H -#define KIT_TEST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include <stddef.h> -#include <stdint.h> - -#ifndef KIT_TEST_FILE -# define KIT_TEST_FILE kit_test -#endif - -#ifndef KIT_TESTS_SIZE_LIMIT -# define KIT_TESTS_SIZE_LIMIT 0x1000 -#endif - -#ifndef KIT_TEST_ASSERTIONS_LIMIT -# define KIT_TEST_ASSERTIONS_LIMIT 0x50 -#endif - -#ifndef KIT_BENCHS_SIZE_LIMIT -# define KIT_BENCHS_SIZE_LIMIT 200 -#endif - -#ifndef KIT_BENCH_MAX_REPEATS -# define KIT_BENCH_MAX_REPEATS 4000 -#endif - -#ifndef KIT_BENCH_MAX_CYCLES -# define KIT_BENCH_MAX_CYCLES 40 -#endif - -#ifndef KIT_BENCH_REPEATS_DEFAULT_1 -# define KIT_BENCH_REPEATS_DEFAULT_1 40 -#endif - -#ifndef KIT_BENCH_REPEATS_DEFAULT_2 -# define KIT_BENCH_REPEATS_DEFAULT_2 400 -#endif - -typedef void (*kit_test_report_fn)(int test_index, int line, - int64_t value, int64_t expected); -typedef void (*kit_test_run_fn)( - int kit_test_index_, kit_test_report_fn kit_test_report_fn_); - -typedef struct { - char const *test_name; - char const *test_file; - kit_test_run_fn test_fn; - int assertions; - int line[KIT_TEST_ASSERTIONS_LIMIT]; - int status[KIT_TEST_ASSERTIONS_LIMIT]; - int64_t value[KIT_TEST_ASSERTIONS_LIMIT]; - int64_t expected[KIT_TEST_ASSERTIONS_LIMIT]; - int signal; -} kit_test_case_t; - -typedef struct { - int size; - kit_test_case_t v[KIT_TESTS_SIZE_LIMIT]; -} kit_tests_list_t; - -extern kit_tests_list_t kit_tests_list; - -#define KIT_TEST_CONCAT4_(a, b, c, d) a##b##c##d -#define KIT_TEST_CONCAT3_(a, b, c) KIT_TEST_CONCAT4_(a, b, _, c) - -#ifdef __cplusplus -# define KIT_TEST_ON_START_(f) \ - static void f(void); \ - static int KIT_TEST_CONCAT3_(_kit_test_init_, __LINE__, \ - f) = (f(), 0); \ - static void f(void) -#else -# ifdef _MSC_VER -# pragma section(".CRT$XCU", read) -# define KIT_TEST_ON_START_2_(f, p) \ - static void f(void); \ - __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ - __pragma(comment(linker, "/include:" p #f "_")) static void f( \ - void) -# ifdef _WIN64 -# define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "") -# else -# define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "_") -# endif -# else -# define KIT_TEST_ON_START_(f) \ - static void f(void) __attribute__((constructor)); \ - static void f(void) -# endif -#endif - -void kit_test_register(char const *name, char const *file, - kit_test_run_fn fn); - -#define KIT_TEST(name) \ - static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \ - KIT_TEST_FILE)(int, \ - kit_test_report_fn); \ - KIT_TEST_ON_START_( \ - KIT_TEST_CONCAT3_(kit_test_case_, __LINE__, KIT_TEST_FILE)) { \ - kit_test_register( \ - name, __FILE__, \ - KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, KIT_TEST_FILE)); \ - } \ - static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \ - KIT_TEST_FILE)( \ - int kit_test_index_, kit_test_report_fn kit_test_report_fn_) - -#define KIT_REQUIRE(...) \ - kit_test_report_fn_(kit_test_index_, __LINE__, (__VA_ARGS__), 1) - -#define KIT_REQUIRE_EQ(...) \ - kit_test_report_fn_(kit_test_index_, __LINE__, __VA_ARGS__) - -int kit_run_tests(int argc, char **argv); - -typedef void (*kit_bench_set_repeats_limit_fn)(int bench_index, - int repeats_limit); -typedef int (*kit_bench_loop_fn)(int bench_index); -typedef void (*kit_bench_begin_fn)(int bench_index); -typedef void (*kit_bench_end_fn)(int bench_index); - -typedef void (*kit_bench_run_fn)( - int kit_bench_index_, - kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_, - kit_bench_loop_fn kit_bench_loop_, - kit_bench_begin_fn kit_bench_begin_, - kit_bench_end_fn kit_bench_end_); - -typedef struct { - char const *bench_name; - char const *bench_file; - kit_bench_run_fn bench_fn; - int64_t sec[KIT_BENCH_MAX_REPEATS]; - int32_t nsec[KIT_BENCH_MAX_REPEATS]; - int64_t duration_nsec[KIT_BENCH_MAX_REPEATS]; - int64_t duration_sorted_nsec[KIT_BENCH_MAX_REPEATS]; - int repeats; - int cycles_size; - int cycles[KIT_BENCH_MAX_CYCLES]; - int cycle; - int signal; - int ready; -} kit_benchmark_t; - -typedef struct { - int size; - kit_benchmark_t v[KIT_BENCHS_SIZE_LIMIT]; -} kit_benchs_list_t; - -extern kit_benchs_list_t kit_benchs_list; - -void kit_bench_register(char const *name, char const *file, - kit_bench_run_fn fn); - -#define KIT_BENCHMARK(name) \ - static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \ - KIT_TEST_FILE)( \ - int, kit_bench_set_repeats_limit_fn, kit_bench_loop_fn, \ - kit_bench_begin_fn, kit_bench_end_fn); \ - KIT_TEST_ON_START_( \ - KIT_TEST_CONCAT3_(kit_benchmark_, __LINE__, KIT_TEST_FILE)) { \ - kit_bench_register( \ - name, __FILE__, \ - KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, KIT_TEST_FILE)); \ - } \ - static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \ - KIT_TEST_FILE)( \ - int kit_bench_index_, \ - kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_, \ - kit_bench_loop_fn kit_bench_loop_, \ - kit_bench_begin_fn kit_bench_begin_, \ - kit_bench_end_fn kit_bench_end_) - -#define KIT_BENCHMARK_REPEAT(repeats_limit_) \ - kit_bench_set_repeats_limit_(kit_bench_index_, repeats_limit_) - -#define KIT_BENCHMARK_BEGIN \ - while (kit_bench_loop_(kit_bench_index_)) { \ - kit_bench_begin_(kit_bench_index_); \ - { - -#define KIT_BENCHMARK_END \ - } \ - kit_bench_end_(kit_bench_index_); \ - } - -// FIXME -// -#define KIT_DO_NOT_OPTIMIZE(x) \ - do { \ - volatile void *bench_ptr_ = &(x); \ - (void) bench_ptr_; \ - } while (0) - -int kit_run_benchmarks(int argc, char **argv); - -#define TEST KIT_TEST -#define REQUIRE KIT_REQUIRE -#define REQUIRE_EQ KIT_REQUIRE_EQ -#define BENCHMARK KIT_BENCHMARK -#define BENCHMARK_REPEAT KIT_BENCHMARK_REPEAT -#define BENCHMARK_BEGIN KIT_BENCHMARK_BEGIN -#define BENCHMARK_END KIT_BENCHMARK_END -#define DO_NOT_OPTIMIZE KIT_DO_NOT_OPTIMIZE -#define test_register kit_test_register -#define run_tests kit_run_tests -#define bench_register kit_bench_register -#define run_benchmarks kit_run_benchmarks - -#ifdef __cplusplus -} -#endif - -#endif - -#if defined(KIT_TEST_IMPLEMENTATION) && !defined(KIT_TEST_H_IMPL) -#define KIT_TEST_H_IMPL - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef KIT_TIME_H -# define KIT_TIME_H - -# include <time.h> - -# 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 -# 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 - -#endif - -#include <setjmp.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -enum { - kit_white_, - kit_blue_, - kit_light_, - kit_yellow_, - kit_red_, - kit_green_ -}; - -static char const *kit_color_codes_[] = { "\x1b[38m", "\x1b[34m", - "\x1b[37m", "\x1b[33m", - "\x1b[31m", "\x1b[32m" }; - -static int kit_print_color_(int c) { - return printf("%s", kit_color_codes_[c]); -} - -static int kit_signums_[] = { SIGINT, SIGILL, SIGABRT, - SIGFPE, SIGSEGV, SIGTERM }; - -static char const *kit_signames_[64]; - -static void kit_signames_init_(void) { - memset(kit_signames_, 0, sizeof kit_signames_); - kit_signames_[SIGINT] = "Interactive attention signal"; - kit_signames_[SIGILL] = "Illegal instruction"; - kit_signames_[SIGABRT] = "Abnormal termination"; - kit_signames_[SIGFPE] = "Erroneous arithmetic operation"; - kit_signames_[SIGSEGV] = "Invalid access to storage"; - kit_signames_[SIGTERM] = "Termination request"; -} - -kit_tests_list_t kit_tests_list = { 0 }; - -static void kit_report_(int i, int line, int64_t value, - int64_t expected) { - int n = kit_tests_list.v[i].assertions++; - - if (n >= KIT_TEST_ASSERTIONS_LIMIT) - return; - - kit_tests_list.v[i].line[n] = line; - kit_tests_list.v[i].status[n] = value == expected; - kit_tests_list.v[i].value[n] = value; - kit_tests_list.v[i].expected[n] = expected; -} - -static int64_t ns_to_ms(int64_t ns) { - return (ns + 500000) / 1000000; -} - -static int64_t sec_to_ms(int64_t sec) { - return 1000 * sec; -} - -void kit_test_register(char const *name, char const *file, - kit_test_run_fn fn) { - int n = kit_tests_list.size++; - if (n < KIT_TESTS_SIZE_LIMIT) { - kit_tests_list.v[n].test_fn = fn; - kit_tests_list.v[n].test_name = name; - kit_tests_list.v[n].test_file = file; - kit_tests_list.v[n].assertions = 0; - } -} - -static jmp_buf kit_test_restore_execution; - -static void kit_test_handle_signal(int signum) { - longjmp(kit_test_restore_execution, signum); -} - -static void kit_test_setup_signals() { - for (int i = 0; i < sizeof kit_signums_ / sizeof *kit_signums_; i++) - signal(kit_signums_[i], kit_test_handle_signal); -} - -static int kit_run_test_(volatile int i) { - int signum = setjmp(kit_test_restore_execution); - - if (signum != 0) { - kit_tests_list.v[i].signal = signum; - return 0; - } - - kit_tests_list.v[i].test_fn(i, kit_report_); - return 1; -} - -int kit_run_tests(int argc, char **argv) { - kit_signames_init_(); - - int success_count = 0; - int fail_assertion_count = 0; - int total_assertion_count = 0; - int status = 0; - int quiet = 0; - int no_color = 0; - int line_width = 20; - int carriage_return = 1; - - int i, j; - - char const *specific_test = NULL; - - kit_test_setup_signals(); - - for (i = 0; i < argc; i++) - if (strcmp("--no-term-color", argv[i]) == 0) - no_color = 1; - else if (strcmp("--no-carriage-return", argv[i]) == 0) - carriage_return = 0; - else if (strcmp("--quiet", argv[i]) == 0) - quiet = 1; - else if (strcmp("--match", argv[i]) == 0) - specific_test = argv[++i]; - - quiet && (no_color = 1); - - if (specific_test != NULL) { - no_color || kit_print_color_(kit_light_); - quiet || printf("Run tests matching "); - no_color || kit_print_color_(kit_white_); - quiet || printf("*%s*", specific_test); - no_color || kit_print_color_(kit_light_); - quiet || printf("\n\n"); - } - - char const *file = NULL; - ptrdiff_t file_root = -1; - int tests_total = 0; - - for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; - i++) { - if (specific_test != NULL && - strstr(kit_tests_list.v[i].test_name, specific_test) == NULL) - continue; - tests_total++; - int l = 2 + (int) strlen(kit_tests_list.v[i].test_name); - if (line_width < l) - line_width = l; - } - - if (tests_total > 0) { - char const *s = kit_tests_list.v[0].test_file; - - for (j = 1; j < kit_tests_list.size && j < KIT_TESTS_SIZE_LIMIT; - j++) { - if (specific_test != NULL && - strstr(kit_tests_list.v[j].test_name, specific_test) == - NULL) - continue; - if (strcmp(s, kit_tests_list.v[j].test_file) == 0) - continue; - int k = 0; - for (; - s[k] != '\0' && kit_tests_list.v[j].test_file[k] != '\0' && - s[k] == kit_tests_list.v[j].test_file[k]; - k++) { } - if (file_root == -1 || file_root > k) - file_root = k; - } - - if (file_root == -1) { - for (i = 0; s[i] != '\0'; i++) - if (s[i] == '/' || s[i] == '\\') - file_root = i + 1; - } - } - - for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; - i++) { - if (specific_test != NULL && - strstr(kit_tests_list.v[i].test_name, specific_test) == NULL) - continue; - if (file == NULL || - strcmp(file, kit_tests_list.v[i].test_file) != 0) { - if (file != NULL) - quiet || printf("\n"); - file = kit_tests_list.v[i].test_file; - no_color || kit_print_color_(kit_blue_); - quiet || printf("* "); - no_color || kit_print_color_(kit_white_); - quiet || printf("%s\n", file + file_root); - } - - !carriage_return || no_color || kit_print_color_(kit_yellow_); - carriage_return || no_color || kit_print_color_(kit_light_); - quiet || printf("` %s ", kit_tests_list.v[i].test_name); - !carriage_return || quiet || printf("\r"); - quiet || fflush(stdout); - - struct timespec begin, end; - timespec_get(&begin, TIME_UTC); - - int test_status = kit_run_test_(i); - - timespec_get(&end, TIME_UTC); - int duration = (int) (ns_to_ms(end.tv_nsec - begin.tv_nsec) + - sec_to_ms(end.tv_sec - begin.tv_sec)); - - for (j = 0; j < kit_tests_list.v[i].assertions && - j < KIT_TEST_ASSERTIONS_LIMIT; - j++) - if (kit_tests_list.v[i].status[j] == 0) { - fail_assertion_count++; - test_status = 0; - } - - if (kit_tests_list.v[i].assertions > KIT_TEST_ASSERTIONS_LIMIT) - test_status = 0; - - total_assertion_count += kit_tests_list.v[i].assertions; - - !carriage_return || no_color || kit_print_color_(kit_light_); - !carriage_return || quiet || - printf("` %s ", kit_tests_list.v[i].test_name); - - int l = (int) strlen(kit_tests_list.v[i].test_name); - quiet || printf("%*c", line_width - l, ' '); - - if (test_status == 0) { - no_color || kit_print_color_(kit_red_); - quiet || printf("FAIL"); - no_color || kit_print_color_(kit_light_); - duration == 0 || quiet || printf(" %d ms", duration); - quiet || printf("\n"); - status = 1; - } else { - no_color || kit_print_color_(kit_green_); - quiet || printf("OK"); - no_color || kit_print_color_(kit_light_); - duration == 0 || quiet || printf(" %d ms", duration); - quiet || printf("\n"); - success_count++; - } - - quiet || fflush(stdout); - } - - no_color || kit_print_color_(kit_white_); - quiet || printf("\n%d of %d tests passed.\n", success_count, - tests_total); - quiet || printf("%d of %d assertions passed.\n\n", - total_assertion_count - fail_assertion_count, - total_assertion_count); - - no_color || kit_print_color_(kit_light_); - - if (!quiet && status != 0) { - int have_kit_report_s = 0; - - for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; - i++) { - if (specific_test != NULL && - strstr(kit_tests_list.v[i].test_name, specific_test) == - NULL) - continue; - if (kit_tests_list.v[i].signal != 0) { - int signum = kit_tests_list.v[i].signal; - if (signum >= 0 && - signum < sizeof kit_signames_ / sizeof *kit_signames_ && - kit_signames_[signum] != NULL) { - no_color || kit_print_color_(kit_light_); - printf("Signal \"%s\" (%d) for \"", kit_signames_[signum], - signum); - no_color || kit_print_color_(kit_white_); - printf("%s", kit_tests_list.v[i].test_name); - no_color || kit_print_color_(kit_light_); - printf("\" in \""); - no_color || kit_print_color_(kit_white_); - - printf("%s", kit_tests_list.v[i].test_file + file_root); - no_color || kit_print_color_(kit_light_); - printf("\"!\n"); - } else { - no_color || kit_print_color_(kit_light_); - printf("Unknown signal (%d) for \"", signum); - no_color || kit_print_color_(kit_white_); - printf("%s", kit_tests_list.v[i].test_name); - no_color || kit_print_color_(kit_light_); - printf("\" in \""); - no_color || kit_print_color_(kit_white_); - - printf("%s", kit_tests_list.v[i].test_file + file_root); - no_color || kit_print_color_(kit_light_); - printf("\"!\n"); - } - have_kit_report_s = 1; - } - if (kit_tests_list.v[i].assertions > - KIT_TEST_ASSERTIONS_LIMIT) { - no_color || kit_print_color_(kit_light_); - printf("Too many assertions for \""); - no_color || kit_print_color_(kit_white_); - printf("%s", kit_tests_list.v[i].test_name); - no_color || kit_print_color_(kit_light_); - printf("\" in \""); - no_color || kit_print_color_(kit_white_); - - printf("%s", kit_tests_list.v[i].test_file + file_root); - no_color || kit_print_color_(kit_light_); - printf("\"!\n"); - have_kit_report_s = 1; - } - } - - have_kit_report_s &&printf("\n"); - } - - if (!quiet && status != 0) { - for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; - i++) { - if (specific_test != NULL && - strstr(kit_tests_list.v[i].test_name, specific_test) == - NULL) - continue; - - if (kit_tests_list.v[i].assertions <= KIT_TEST_ASSERTIONS_LIMIT) - for (j = 0; j < kit_tests_list.v[i].assertions; j++) - if (!kit_tests_list.v[i].status[j]) { - no_color || kit_print_color_(kit_light_); - printf("Assertion on line "); - no_color || kit_print_color_(kit_white_); - printf("%d", kit_tests_list.v[i].line[j]); - no_color || kit_print_color_(kit_light_); - printf(" in \""); - no_color || kit_print_color_(kit_white_); - printf("%s", kit_tests_list.v[i].test_file + file_root); - no_color || kit_print_color_(kit_light_); - printf("\" failed.\n"); - no_color || kit_print_color_(kit_red_); - printf(" -> "); - no_color || kit_print_color_(kit_light_); - printf("Got wrong value "); - no_color || kit_print_color_(kit_white_); - printf("%10lld", - (long long) kit_tests_list.v[i].value[j]); - no_color || kit_print_color_(kit_light_); - printf(" ("); - no_color || kit_print_color_(kit_white_); - printf("0x%08llx", - (unsigned long long) kit_tests_list.v[i].value[j]); - no_color || kit_print_color_(kit_light_); - printf(")\n"); - no_color || kit_print_color_(kit_green_); - printf(" -> "); - no_color || kit_print_color_(kit_light_); - printf("Expected value "); - no_color || kit_print_color_(kit_white_); - printf("%10lld", - (long long) kit_tests_list.v[i].expected[j]); - no_color || kit_print_color_(kit_light_); - printf(" ("); - no_color || kit_print_color_(kit_white_); - printf( - "0x%08llx", - (unsigned long long) kit_tests_list.v[i].expected[j]); - no_color || kit_print_color_(kit_light_); - printf(")\n\n"); - } - } - } - - if (kit_tests_list.size > KIT_TESTS_SIZE_LIMIT) { - no_color || kit_print_color_(kit_light_); - quiet || printf("Too many tests!\n\n"); - status = 1; - } - - if (status == 0) { - no_color || kit_print_color_(kit_green_); - quiet || printf("OK\n"); - } else { - no_color || kit_print_color_(kit_red_); - quiet || printf("FAILED\n"); - } - - no_color || kit_print_color_(kit_light_); - quiet || printf("\n"); - return status; -} - -kit_benchs_list_t kit_benchs_list = { 0 }; - -static void bench_set_repeats_limit(int i, int repeats_limit) { - if (kit_benchs_list.v[i].ready) - return; - if (kit_benchs_list.v[i].cycles_size >= KIT_BENCH_MAX_CYCLES) - return; - kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycles_size] = - repeats_limit; - kit_benchs_list.v[i].cycles_size++; -} - -static int bench_loop(int i) { - if (!kit_benchs_list.v[i].ready) - return 0; - return kit_benchs_list.v[i].repeats < - kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycle]; -} - -static void bench_begin(int i) { - int n = kit_benchs_list.v[i].repeats++; - - if (n >= KIT_BENCH_MAX_REPEATS) - return; - - struct timespec tv; - timespec_get(&tv, TIME_UTC); - - kit_benchs_list.v[i].sec[n] = (int64_t) tv.tv_sec; - kit_benchs_list.v[i].nsec[n] = (int64_t) tv.tv_nsec; -} - -static void bench_end(int i) { - int n = kit_benchs_list.v[i].repeats - 1; - - if (n < 0 || n >= KIT_BENCH_MAX_REPEATS) - return; - - struct timespec tv; - timespec_get(&tv, TIME_UTC); - - int64_t sec = ((int64_t) tv.tv_sec) - kit_benchs_list.v[i].sec[n]; - int64_t nsec = ((int64_t) tv.tv_nsec) - - kit_benchs_list.v[i].nsec[n]; - - kit_benchs_list.v[i].duration_nsec[n] = sec * 1000000000 + nsec; -} - -void kit_bench_register(char const *name, char const *file, - kit_bench_run_fn fn) { - int n = kit_benchs_list.size++; - if (n < KIT_BENCHS_SIZE_LIMIT) { - kit_benchmark_t *bench = kit_benchs_list.v + n; - - bench->bench_fn = fn; - bench->bench_name = name; - bench->bench_file = file; - bench->cycles_size = 0; - bench->ready = 0; - } -} - -static void kit_bench_setup_signals() { - for (int i = 0; i < sizeof kit_signums_ / sizeof *kit_signums_; i++) - signal(kit_signums_[i], kit_test_handle_signal); -} - -static int kit_run_bench_(volatile int i) { - int signum = setjmp(kit_test_restore_execution); - - if (signum != 0) { - kit_benchs_list.v[i].signal = signum; - return 0; - } - - kit_benchs_list.v[i].bench_fn(i, bench_set_repeats_limit, - bench_loop, bench_begin, bench_end); - return 1; -} - -static int kit_compare_64_(void const *x_, void const *y_) { - int64_t const *x = (int64_t const *) x_; - int64_t const *y = (int64_t const *) y_; - return *x - *y; -} - -static int kit_compare_32_(void const *x_, void const *y_) { - int const *x = (int const *) x_; - int const *y = (int const *) y_; - return *x - *y; -} - -int kit_run_benchmarks(int argc, char **argv) { - int success_count = 0; - int status = 0; - int no_color = 0; - int line_width = 20; - int carriage_return = 1; - - char const *specific_bench = NULL; - - kit_bench_setup_signals(); - - for (int i = 0; i < argc; i++) - if (strcmp("--no-term-color", argv[i]) == 0) - no_color = 1; - else if (strcmp("--no-carriage-return", argv[i]) == 0) - carriage_return = 0; - else if (strcmp("--match", argv[i]) == 0) - specific_bench = argv[++i]; - - if (specific_bench != NULL) { - no_color || kit_print_color_(kit_light_); - printf("Run benchmarks matching "); - no_color || kit_print_color_(kit_white_); - printf("*%s*", specific_bench); - no_color || kit_print_color_(kit_light_); - printf("\n\n"); - } - - char const *file = NULL; - ptrdiff_t file_root = -1; - int benchs_total = 0; - - for (int i = 0; - i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { - if (specific_bench != NULL && - strstr(kit_benchs_list.v[i].bench_name, specific_bench) == - NULL) - continue; - benchs_total++; - int l = 2 + (int) strlen(kit_benchs_list.v[i].bench_name); - if (line_width < l) - line_width = l; - } - - if (benchs_total > 0) { - char const *s = kit_benchs_list.v[0].bench_file; - - for (int j = 1; - j < kit_benchs_list.size && j < KIT_BENCHS_SIZE_LIMIT; j++) { - kit_benchmark_t *bench = kit_benchs_list.v + j; - - if (specific_bench != NULL && - strstr(bench->bench_name, specific_bench) == NULL) - continue; - if (strcmp(s, bench->bench_file) == 0) - continue; - int k = 0; - for (; s[k] != '\0' && bench->bench_file[k] != '\0' && - s[k] == bench->bench_file[k]; - k++) { } - if (file_root == -1 || file_root > k) - file_root = k; - } - - if (file_root == -1) { - for (int i = 0; s[i] != '\0'; i++) - if (s[i] == '/' || s[i] == '\\') - file_root = i + 1; - } - } - - no_color || kit_print_color_(kit_blue_); - printf("# "); - no_color || kit_print_color_(kit_light_); - printf("BENCHMARK"); - printf("%*c", line_width - 9, ' '); - no_color || kit_print_color_(kit_green_); - printf(" LOW "); - no_color || kit_print_color_(kit_light_); - printf("|"); - no_color || kit_print_color_(kit_blue_); - printf(" MEDIAN "); - no_color || kit_print_color_(kit_light_); - printf("|"); - no_color || kit_print_color_(kit_yellow_); - printf(" HIGH\n"); - no_color || kit_print_color_(kit_light_); - printf(" (in microseconds)\n\n"); - - /* Prepare cycles. - */ - - for (int i = 0; - i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { - kit_benchmark_t *bench = kit_benchs_list.v + i; - - if (specific_bench != NULL && - strstr(bench->bench_name, specific_bench) == NULL) - continue; - - kit_run_bench_(i); - - if (bench->cycles_size == 0) { - bench->cycles_size = 2; - bench->cycles[0] = KIT_BENCH_REPEATS_DEFAULT_1; - bench->cycles[1] = KIT_BENCH_REPEATS_DEFAULT_2; - } - - qsort(bench->cycles, bench->cycles_size, sizeof *bench->cycles, - kit_compare_32_); - - kit_benchs_list.v[i].ready = 1; - } - - /* Run cycles. - */ - - for (int cycle = 0; cycle < KIT_BENCH_MAX_CYCLES; cycle++) { - /* Prepare cycle. - */ - - int cycles_done = 1; - - for (int i = 0; - i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { - kit_benchmark_t *bench = kit_benchs_list.v + i; - - if (specific_bench != NULL && - strstr(bench->bench_name, specific_bench) == NULL) - continue; - if (cycle >= bench->cycles_size) - continue; - - bench->repeats = 0; - bench->cycle = cycle; - cycles_done = 0; - } - - if (cycles_done) - break; - - /* Run benchmarks. - */ - - for (int i = 0; - i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { - kit_benchmark_t *bench = kit_benchs_list.v + i; - - if (specific_bench != NULL && - strstr(bench->bench_name, specific_bench) == NULL) - continue; - if (cycle >= bench->cycles_size) - continue; - - if (file == NULL || strcmp(file, bench->bench_file) != 0) { - if (file != NULL) - printf("\n"); - file = bench->bench_file; - no_color || kit_print_color_(kit_blue_); - printf("* "); - no_color || kit_print_color_(kit_white_); - printf("%s\n", file + file_root); - } - - !carriage_return || no_color || kit_print_color_(kit_yellow_); - carriage_return || no_color || kit_print_color_(kit_light_); - printf("` %s ", bench->bench_name); - !carriage_return || printf("\r"); - fflush(stdout); - - int bench_status = kit_run_bench_(i); - - if (bench->repeats > KIT_BENCH_MAX_REPEATS) - bench_status = 0; - - !carriage_return || no_color || kit_print_color_(kit_light_); - !carriage_return || printf("` %s ", bench->bench_name); - - int l = (int) strlen(bench->bench_name); - printf("%*c", line_width - l, ' '); - - if (bench->repeats <= 0) { - no_color || kit_print_color_(kit_yellow_); - printf(" 0 runs\n"); - success_count++; - } else if (bench_status == 0) { - no_color || kit_print_color_(kit_red_); - printf(" FAIL\n"); - status = 1; - } else { - int repeats = bench->repeats; - - memcpy(bench->duration_sorted_nsec, bench->duration_nsec, - repeats * sizeof *bench->duration_sorted_nsec); - qsort(bench->duration_sorted_nsec, repeats, - sizeof *bench->duration_sorted_nsec, kit_compare_64_); - - int64_t average = bench->duration_sorted_nsec[repeats / 2]; - int64_t floor = bench->duration_sorted_nsec[repeats / 20]; - int64_t roof = - bench->duration_sorted_nsec[repeats - repeats / 20 - 1]; - - no_color || kit_print_color_(kit_white_); - printf("%-9g", (double) floor * 0.001); - no_color || kit_print_color_(kit_light_); - printf("| "); - no_color || kit_print_color_(kit_white_); - printf("%-9g", (double) average * 0.001); - no_color || kit_print_color_(kit_light_); - printf("| "); - no_color || kit_print_color_(kit_white_); - printf("%-9g", (double) roof * 0.001); - no_color || kit_print_color_(kit_light_); - printf(" %d runs\n", repeats); - success_count++; - } - } - } - - printf("\n"); - - if (status != 0) { - for (int i = 0; - i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { - kit_benchmark_t *bench = kit_benchs_list.v + i; - - if (specific_bench != NULL && - strstr(bench->bench_name, specific_bench) == NULL) - continue; - if (bench->signal != 0) { - int signum = bench->signal; - if (signum >= 0 && - signum < sizeof kit_signames_ / sizeof *kit_signames_ && - kit_signames_[signum] != NULL) { - no_color || kit_print_color_(kit_light_); - printf("Signal \"%s\" (%d) for \"", kit_signames_[signum], - signum); - no_color || kit_print_color_(kit_white_); - printf("%s", bench->bench_name); - no_color || kit_print_color_(kit_light_); - printf("\" in \""); - no_color || kit_print_color_(kit_white_); - printf("%s", bench->bench_file + file_root); - no_color || kit_print_color_(kit_light_); - printf("\"!.\n"); - } else { - no_color || kit_print_color_(kit_light_); - printf("Unknown signal (%d) for \"", signum); - no_color || kit_print_color_(kit_white_); - printf("%s", bench->bench_name); - no_color || kit_print_color_(kit_light_); - printf("\" in \""); - no_color || kit_print_color_(kit_white_); - printf("%s", bench->bench_file + file_root); - no_color || kit_print_color_(kit_light_); - printf("\"!.\n"); - } - } - } - - printf("\n"); - } - - if (kit_benchs_list.size > KIT_BENCHS_SIZE_LIMIT) { - no_color || kit_print_color_(kit_light_); - printf("Too many benchmarks!\n\n"); - status = 1; - } - - if (status == 0) { - no_color || kit_print_color_(kit_green_); - printf("DONE\n"); - } else { - no_color || kit_print_color_(kit_red_); - printf("DONE WITH ERRORS\n"); - } - - no_color || kit_print_color_(kit_light_); - printf("\n"); - return status; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/threads.h b/source/kit/threads.h deleted file mode 100644 index 8ff46ed..0000000 --- a/source/kit/threads.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef KIT_THREADS_H -#define KIT_THREADS_H -#ifndef KIT_DISABLE_SYSTEM_THREADS - -# include "time.h" - -# 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 diff --git a/source/kit/threads.posix.c b/source/kit/threads.posix.c deleted file mode 100644 index 44465a3..0000000 --- a/source/kit/threads.posix.c +++ /dev/null @@ -1,271 +0,0 @@ -#include "threads.h" - -#ifndef KIT_DISABLE_SYSTEM_THREADS -# include "allocator.h" - -# 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 diff --git a/source/kit/threads.win32.c b/source/kit/threads.win32.c deleted file mode 100644 index 72f0ba1..0000000 --- a/source/kit/threads.win32.c +++ /dev/null @@ -1,379 +0,0 @@ -#include "threads.h" - -#ifndef KIT_DISABLE_SYSTEM_THREADS -# include "allocator.h" - -# 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 diff --git a/source/kit/time.h b/source/kit/time.h deleted file mode 100644 index c14f8ff..0000000 --- a/source/kit/time.h +++ /dev/null @@ -1,54 +0,0 @@ -#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 diff --git a/source/kit/types.h b/source/kit/types.h deleted file mode 100644 index bbe8717..0000000 --- a/source/kit/types.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef KIT_TYPES_H -#define KIT_TYPES_H - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -// signed integers -// -typedef signed char i8; -typedef signed short i16; -typedef signed int i32; -typedef signed long long i64; - -// unsigned integers -// -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long long u64; - -// floats -// -typedef float f32; -typedef double f64; - -// chars -// -typedef char c8; -typedef int c32; - -typedef signed char b8; // 8-bit boolean -typedef signed int b32; // 32-bit boolean -typedef signed int s32; // 32-bit status - -#endif diff --git a/source/kit/unival.c b/source/kit/unival.c deleted file mode 100644 index 4fed179..0000000 --- a/source/kit/unival.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "unival.h" - -kit_uv_decode_result_t kit_uv_decode(kit_is_handle_t is, - kit_allocator_t *alloc) { - kit_uv_decode_result_t result; - memset(&result, 0, sizeof result); - - result.status = KIT_ERROR_NOT_IMPLEMENTED; - return result; -} - -kit_uv_encode_result_t kit_uv_encode(kit_unival_t *value, - kit_allocator_t *alloc, - i32 flags) { - kit_uv_encode_result_t result; - memset(&result, 0, sizeof result); - - result.status = KIT_ERROR_NOT_IMPLEMENTED; - return result; -} - -kit_uv_decode_result_t kit_uv_parse(kit_is_handle_t is, - kit_allocator_t *alloc) { - kit_uv_decode_result_t result; - memset(&result, 0, sizeof result); - - result.status = KIT_ERROR_NOT_IMPLEMENTED; - return result; -} - -kit_uv_decode_result_t kit_uv_parse_json(kit_is_handle_t is, - kit_allocator_t *alloc) { - kit_uv_decode_result_t result; - memset(&result, 0, sizeof result); - - result.status = KIT_ERROR_NOT_IMPLEMENTED; - return result; -} - -kit_uv_print_result_t kit_uv_print(kit_unival_t *value, - kit_allocator_t *alloc, - i32 flags) { - kit_uv_print_result_t result; - memset(&result, 0, sizeof result); - - result.status = KIT_ERROR_NOT_IMPLEMENTED; - return result; -} - -void kit_uv_destroy(kit_unival_t *value) { } - diff --git a/source/kit/unival.h b/source/kit/unival.h deleted file mode 100644 index e0362b1..0000000 --- a/source/kit/unival.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef KIT_UNIVAL_H -#define KIT_UNIVAL_H - -#include "string_builder.h" -#include "input_stream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - KIT_UV_NONE, - KIT_UV_BOOLEAN, - KIT_UV_INTEGER, - KIT_UV_FLOAT, - KIT_UV_STRING, - KIT_UV_BYTES, - KIT_UV_ARRAY, - KIT_UV_COMPOSITE, -}; - -enum { - KIT_UV_ENCODE_BZIP = 1, - KIT_UV_PRINT_PRETTY = 1, - KIT_UV_PRINT_JSON = 2, -}; - -typedef struct kit_unival_ kit_unival_t; - -typedef KIT_DA(kit_unival_t) kit_da_unival_t; -typedef KIT_DA(u8) kit_uv_bytes_t; - -struct kit_unival_ { - i8 type; - union { - i8 boolean; - i64 integer; - f64 float_; - kit_str_builder_t string; - kit_uv_bytes_t bytes; - kit_da_unival_t array; - struct { - kit_da_unival_t keys; - kit_da_unival_t values; - } composite; - }; -}; - -typedef struct { - s32 status; - kit_unival_t *value; -} kit_uv_decode_result_t; - -kit_uv_decode_result_t kit_uv_decode(kit_is_handle_t is, - kit_allocator_t *alloc); - -typedef struct { - s32 status; - kit_uv_bytes_t value; -} kit_uv_encode_result_t; - -kit_uv_encode_result_t kit_uv_encode(kit_unival_t *value, - kit_allocator_t *alloc, - i32 flags); - -kit_uv_decode_result_t kit_uv_parse(kit_is_handle_t is, - kit_allocator_t *alloc); - -kit_uv_decode_result_t kit_uv_parse_json(kit_is_handle_t is, - kit_allocator_t *alloc); - -typedef struct { - s32 status; - kit_str_builder_t value; -} kit_uv_print_result_t; - -kit_uv_print_result_t kit_uv_print(kit_unival_t *value, - kit_allocator_t *alloc, i32 flags); - -void kit_uv_destroy(kit_unival_t *value); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/utf8.h b/source/kit/utf8.h deleted file mode 100644 index 3dc6822..0000000 --- a/source/kit/utf8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef KIT_UTF8_H -#define KIT_UTF8_H - -#include "string_builder.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#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 s32 kit_utf8_count(kit_str_t s, i64 *count) { - return KIT_ERROR_NOT_IMPLEMENTED; -} - -static s32 kit_utf8_offset(kit_str_t s, i64 count, i64 *offset) { - return KIT_ERROR_NOT_IMPLEMENTED; -} - -static s32 kit_utf8_decode(kit_str_t s, i64 offset, i64 *size, - c32 *value) { - return KIT_ERROR_NOT_IMPLEMENTED; -} - -static s32 kit_utf8_encode(kit_str_builder_t *s, c32 value) { - return KIT_ERROR_NOT_IMPLEMENTED; -} - -#if defined(__GNUC__) || defined(__clang__) -# pragma GCC pop_options -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/kit/xml.c b/source/kit/xml.c deleted file mode 100644 index 0d8378c..0000000 --- a/source/kit/xml.c +++ /dev/null @@ -1,485 +0,0 @@ -#include "xml.h" - -#include "input_buffer.h" -#include <assert.h> - -typedef struct { - ib_token_t last; - str_builder_t text; - kit_da_xml_t tags; -} kit_xml_intermediate_t; - -static s32 kit_xml_alloc_and_unescape_(str_builder_t *dst, str_t str, - kit_allocator_t *alloc) { - assert(dst != NULL); - assert(str.size == 0 || str.values != NULL); - - if (dst == NULL) - return KIT_ERROR_INTERNAL; - if (str.size != 0 && str.values == NULL) - return KIT_ERROR_INTERNAL; - - DA_INIT(*dst, str.size, alloc); - - if (dst->size != str.size) - return KIT_ERROR_OUT_OF_MEMORY; - - dst->size = 0; - - for (i64 i = 0; i < str.size; i++) - if (str.values[i] != '&') - dst->values[dst->size++] = str.values[i]; - else { - i64 n = 1; - while (i + n < str.size && str.values[i + n] != ';') n++; - if (i + n >= str.size) { - DA_DESTROY(*dst); - return KIT_PARSING_FAILED; - } - if (n == 3 && memcmp(str.values + i, "<", 4) == 0) - dst->values[dst->size++] = '<'; - else if (n == 3 && memcmp(str.values + i, ">", 4) == 0) - dst->values[dst->size++] = '>'; - else if (n == 4 && memcmp(str.values + i, "&", 5) == 0) - dst->values[dst->size++] = '&'; - else if (n == 5 && memcmp(str.values + i, """, 6) == 0) - dst->values[dst->size++] = '"'; - else if (n == 5 && memcmp(str.values + i, "'", 6) == 0) - dst->values[dst->size++] = '\''; - else if (n - 2 <= 8 && str.values[i + 1] == '#' && - str.values[i + 2] == 'x') { - // hex encoding - // - - c8 buf[8]; - u64 x = 0; - - memcpy(buf, str.values + (i + 3), n - 2); - - for (i64 k = 0; k < n - 2; k++) { - c8 c = str.values[i + 3 + k]; - x <<= 8; - if (c >= '0' && c <= '9') - x |= (c - '0'); - else if (c >= 'a' && c <= 'f') - x |= 10 + (c - 'a'); - else if (c >= 'A' && c <= 'F') - x |= 10 + (c - 'A'); - else { - x = 0; - break; - } - } - - if (x == 0 || x > 255u) { - // TODO - // UTF-8 encoding - - DA_DESTROY(*dst); - return KIT_PARSING_FAILED; - } - - dst->values[dst->size++] = (c8) x; - } else if (n - 1 <= 20 && str.values[i + 1] == '#') { - // dec encoding - // - - c8 buf[20]; - u64 x = 0; - - memcpy(buf, str.values + (i + 2), n - 2); - - for (i64 k = 0; k < n - 1; k++) { - c8 c = str.values[i + 2 + k]; - x *= 10; - if (c >= '0' && c <= '9') - x += (c - '0'); - else { - x = 0; - break; - } - } - - if (x == 0 || x > 255u) { - // TODO - // UTF-8 encoding - - DA_DESTROY(*dst); - return KIT_PARSING_FAILED; - } - - dst->values[dst->size++] = (c8) x; - } else { - DA_DESTROY(*dst); - return KIT_PARSING_FAILED; - } - i += n; - } - - return KIT_OK; -} - -static ib_token_t kit_xml_parse_text_(ib_token_t begin, - str_builder_t *dst) { - ib_token_t last = ib_until(begin, SZ("<")); - - DA_RESIZE(*dst, last.size); - - assert(dst->size == last.size); - if (dst->size != last.size) - last.status |= KIT_ERROR_OUT_OF_MEMORY -; - else if (last.size > 0) - memcpy(dst->values, ib_str(last).values, last.size); - - for (;;) { - ib_token_t comment_open = ib_exact(last, SZ("<!--")); - - if (comment_open.status != KIT_OK) - break; - - ib_token_t comment_text = ib_until(comment_open, SZ("-->")); - ib_token_t comment_close = ib_exact(comment_text, SZ("-->")); - ib_token_t next_text = ib_until(comment_close, SZ("<")); - - if (next_text.status == KIT_OK && next_text.size > 0) { - i64 n = dst->size; - DA_RESIZE(*dst, n + next_text.size); - - assert(dst->size == n + next_text.size); - if (dst->size != n + next_text.size) - next_text.status |= KIT_ERROR_OUT_OF_MEMORY - ; - else - memcpy(dst->values + n, ib_str(next_text).values, - ib_str(next_text).size); - } - - last = next_text; - } - - return last; -} - -static ib_token_t kit_xml_parse_string_(ib_token_t begin, - ib_token_t *value) { - assert(value != NULL); - if (value == NULL) { - begin.status |= KIT_ERROR_INTERNAL; - return begin; - } - - ib_token_t quotes_open = ib_exact(begin, SZ("\"")); - ib_token_t apostr_open = ib_exact(begin, SZ("'")); - - ib_token_t open = quotes_open.status == KIT_OK ? quotes_open - : apostr_open; - - *value = ib_until(open, ib_str(open)); - ib_token_t close = ib_exact(*value, ib_str(open)); - - return close; -} - -static kit_xml_intermediate_t kit_xml_parse_buf_( - ib_token_t begin, kit_allocator_t *alloc) { - kit_xml_intermediate_t res; - memset(&res, 0, sizeof res); - - ib_token_t last, spaces; - memset(&last, 0, sizeof last); - memset(&spaces, 0, sizeof spaces); - - str_builder_t tag_text_string; - str_builder_t tag_tail_string; - DA_INIT(tag_text_string, 0, alloc); - DA_INIT(tag_tail_string, 0, alloc); - - ib_token_t tag_text = kit_xml_parse_text_(begin, &tag_text_string); - last = tag_text; - - DA_INIT(res.tags, 0, alloc); - - for (;;) { - ib_token_t tagend_open = ib_exact(last, SZ("</")); - if (tagend_open.status == KIT_OK) - break; - - ib_token_t tag_open = ib_exact(last, SZ("<")); - - if (tag_open.status != KIT_OK) - break; - - xml_t tag; - memset(&tag, 0, sizeof tag); - - ib_token_t decl_open = ib_exact(tag_open, SZ("?")); - - if (decl_open.status == KIT_OK) { - tag.is_declaration = 1; - last = decl_open; - } else - last = tag_open; - - spaces = ib_any(last, SZ(" \t\r\n")); - ib_token_t tag_name = ib_none(spaces, SZ(" \t\r\n/>")); - - DA_INIT(tag.properties, 0, alloc); - - last = tag_name; - - for (;;) { - spaces = ib_any(last, SZ(" \t\r\n")); - ib_token_t property = ib_none(spaces, SZ(" \t\r\n=?/>")); - - if (property.status != KIT_OK || property.size == 0) - break; - - spaces = ib_any(property, SZ(" \t\r\n")); - ib_token_t equals = ib_exact(spaces, SZ("=")); - spaces = ib_any(equals, SZ(" \t\r\n")); - - ib_token_t value; - last = kit_xml_parse_string_(spaces, &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_OUT_OF_MEMORY - ; - DA_DESTROY(tag.properties); - } else { - last.status |= kit_xml_alloc_and_unescape_( - &tag.properties.values[n].name, ib_str(property), - alloc); - last.status |= kit_xml_alloc_and_unescape_( - &tag.properties.values[n].value, ib_str(value), alloc); - } - } - } - - if (tag.is_declaration) { - ib_token_t tag_decl_close = ib_exact(spaces, SZ("?>")); - - last = tag_decl_close; - - DA_INIT(tag.text, 0, alloc); - DA_INIT(tag.children, 0, alloc); - } else { - ib_token_t tag_close = ib_exact(spaces, SZ(">")); - ib_token_t tag_close_empty = ib_exact(spaces, SZ("/>")); - - if (tag_close.status == KIT_OK) { - kit_xml_intermediate_t im = kit_xml_parse_buf_(tag_close, - alloc); - - tag.text = im.text; - tag.children = im.tags; - - tagend_open = ib_exact(im.last, SZ("</")); - spaces = ib_any(tagend_open, SZ(" \t\r\n")); - ib_token_t tagend_name = ib_exact(spaces, ib_str(tag_name)); - spaces = ib_any(tagend_name, SZ(" \t\r\n")); - ib_token_t tagend_close = ib_exact(spaces, SZ(">")); - - last = tagend_close; - - } else if (tag_close_empty.status == KIT_OK) { - last = tag_close_empty; - - DA_INIT(tag.text, 0, alloc); - DA_INIT(tag.children, 0, alloc); - } else - last.status |= KIT_PARSING_FAILED; - } - - ib_token_t tag_tail = kit_xml_parse_text_(last, &tag_tail_string); - - last = 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_OUT_OF_MEMORY - ; - xml_destroy(&tag); - } else { - last.status |= kit_xml_alloc_and_unescape_( - &tag.tag, ib_str(tag_name), alloc); - last.status |= kit_xml_alloc_and_unescape_( - &tag.tail, WRAP_STR(tag_tail_string), alloc); - - res.tags.values[n] = tag; - } - } else - xml_destroy(&tag); - } - - 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 - last.status |= kit_xml_alloc_and_unescape_( - &res.text, WRAP_STR(tag_text_string), alloc); - - DA_DESTROY(tag_text_string); - DA_DESTROY(tag_tail_string); - - res.last = last; - return res; -} - -kit_xml_parse_result_t kit_xml_parse(is_handle_t is, - kit_allocator_t *alloc) { - input_buffer_t ib = ib_wrap(is, alloc); - kit_xml_intermediate_t im = kit_xml_parse_buf_(ib_token(&ib), - alloc); - - kit_xml_parse_result_t res; - memset(&res, 0, sizeof res); - - res.status = im.last.status; - - if (res.status != KIT_OK) { - ib_destroy(&ib); - return res; - } - - if (im.text.size == 0 && im.tags.size == 1) { - res.xml = im.tags.values[0]; - DA_DESTROY(im.text); - DA_DESTROY(im.tags); - ib_destroy(&ib); - return res; - } - - 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; - - ib_destroy(&ib); - return res; -} - -kit_xml_text_t kit_xml_print(kit_xml_t *xml, kit_allocator_t *alloc) { - // TODO - // - - assert(xml != NULL); - - xml_text_t result; - memset(&result, 0, sizeof result); - - result.status = KIT_ERROR_NOT_IMPLEMENTED; - return result; -} - -static s32 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_OUT_OF_MEMORY; - - if (xml->text.size > 0) - memcpy(buf->values + n, xml->text.values, xml->text.size); - - for (i64 i = 0; i < xml->children.size; i++) { - s32 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_OUT_OF_MEMORY -; - - 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; -} - -b8 kit_xml_has_property(kit_xml_t *xml, kit_str_t name) { - assert(xml != NULL); - if (xml == NULL) - return 0; - - for (i64 i = 0; i < xml->properties.size; i++) - if (AR_EQUAL(xml->properties.values[i].name, name)) - return 1; - - return 0; -} - -str_t kit_xml_property(kit_xml_t *xml, str_t name) { - assert(xml != NULL); - if (xml == NULL) - return str(0, NULL); - - for (i64 i = 0; i < xml->properties.size; i++) - if (AR_EQUAL(xml->properties.values[i].name, name)) - return WRAP_STR(xml->properties.values[i].value); - - assert(0); - return str(0, NULL); -} - -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); -} diff --git a/source/kit/xml.h b/source/kit/xml.h deleted file mode 100644 index a4dd3d1..0000000 --- a/source/kit/xml.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef KIT_XML_H -#define KIT_XML_H - -#include "string_builder.h" -#include "input_stream.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 { - s32 status; - kit_xml_t xml; -} kit_xml_parse_result_t; - -typedef struct { - s32 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); -b8 kit_xml_has_property(kit_xml_t *xml, kit_str_t name); -kit_str_t kit_xml_property(kit_xml_t *xml, kit_str_t name); -void kit_xml_destroy(kit_xml_t *xml); - -#ifdef __cplusplus -} -#endif - -#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 -#define xml_parse kit_xml_parse -#define xml_print kit_xml_print -#define xml_full_text kit_xml_full_text -#define xml_has_property kit_xml_has_property -#define xml_property kit_xml_property -#define xml_destroy kit_xml_destroy - -#endif |