From 4e8ae2e0d7d40a4ec5779047c9f2c8fbef1aa638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Krzy=C5=BCanowski?= Date: Sun, 16 Feb 2025 16:00:58 +0100 Subject: [PATCH] Initial commit --- main.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 main.c diff --git a/main.c b/main.c new file mode 100644 index 0000000..66acd7c --- /dev/null +++ b/main.c @@ -0,0 +1,230 @@ +#include +#include +#include + +#define max(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) + +#define min(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) + +typedef struct { + void *elem_storage; + size_t elem_count; + size_t elem_size; + size_t elem_count_cap; +} cvec; + +int cvec_new(cvec *dest, size_t elem_size) +{ + size_t init_count_cap = 1; + cvec result = { + .elem_storage = malloc(init_count_cap * elem_size), + .elem_count = 0, + .elem_size = elem_size, + .elem_count_cap = init_count_cap, + }; + + if (!result.elem_storage) + return -1; + + *dest = result; + return 0; +} + +int cvec_extend(cvec *dest) +{ + dest->elem_count_cap *= 2; + dest->elem_storage = realloc(dest->elem_storage, dest->elem_count_cap * dest->elem_size); + if (!dest->elem_storage) + return -1; + + return 0; +} + +int cvec_append(cvec *dest, void *elem) +{ + if (dest->elem_count == dest->elem_count_cap) + { + if (cvec_extend(dest)) + return -1; + } + + memcpy(dest->elem_storage + dest->elem_size * dest->elem_count, elem, dest->elem_size); + + dest->elem_count++; + + return 0; +} + +int cvec_shrink(cvec *dest) +{ + dest->elem_count_cap /= 2; + dest->elem_storage = realloc(dest->elem_storage, dest->elem_count_cap * dest->elem_size); + if (dest->elem_storage) + return -1; + + return 0; +} + +int cvec_pop(cvec *dest) +{ + dest->elem_count--; + + if (dest->elem_count < dest->elem_count_cap / 2) + { + if (cvec_shrink(dest)) + return -1; + } + + return 0; +} + +void cvec_free(cvec vec); +int cvec_erase(cvec *dest) +{ + size_t elem_size = dest->elem_size; + cvec_free(*dest); + return cvec_new(dest, elem_size); +} + +typedef enum { + CVEC_PRINT_FLAG_NONE = 0, + CVEC_PRINT_FLAG_ELLIPSIS = 1, + CVEC_PRINT_FLAG_MULTILINE = 2, +} cvec_print_flag; + +typedef void (*cvec_print_func)(void *elem); +void cvec_print(cvec vec, cvec_print_func print_func, cvec_print_flag flags) +{ + size_t print_left = min(vec.elem_count, 3); + size_t print_center = max((long int)vec.elem_count - 6, 0); + size_t print_right = min(max((long int)vec.elem_count - 3, 0), 3); + size_t elems_printed = 0; + char sep = flags & CVEC_PRINT_FLAG_MULTILINE ? '\n' : ';'; + + printf("["); + + if (flags & CVEC_PRINT_FLAG_MULTILINE) + printf("\n"); + + for (size_t i = 0; i < print_left; i++) + { + print_func(vec.elem_storage + elems_printed * vec.elem_size); + printf("%c ", sep); + elems_printed++; + } + + if (flags & CVEC_PRINT_FLAG_ELLIPSIS) + { + printf("... %lu elements in between ... ", print_center); + + if (flags & CVEC_PRINT_FLAG_MULTILINE) + printf("\n"); + + elems_printed += print_center; + } + else + { + for (size_t i = 0; i < print_center; i++) + { + print_func(vec.elem_storage + elems_printed * vec.elem_size); + + if (elems_printed != vec.elem_count - 1) + printf("%c ", sep); + + elems_printed++; + } + } + + for (size_t i = 0; i < print_right; i++) + { + print_func(vec.elem_storage + elems_printed * vec.elem_size); + + if (elems_printed != vec.elem_count - 1) + printf("%c ", sep); + + elems_printed++; + } + + if (flags & CVEC_PRINT_FLAG_MULTILINE) + printf("\n"); + + printf("]\n"); +} + +void cvec_free(cvec vec) +{ + free(vec.elem_storage); +} + +#define CVEC_PRIMITIVE_PRINT_FUNC(type, type_name, format_flag) \ + void cvec_##type_name##_print_func(void *elem) \ + { \ + type _elem = *(type*)elem; \ + printf(format_flag, _elem); \ + } + +CVEC_PRIMITIVE_PRINT_FUNC(int, int, "%d") +CVEC_PRIMITIVE_PRINT_FUNC(unsigned int, uint, "%u") +CVEC_PRIMITIVE_PRINT_FUNC(float, float, "%f") +CVEC_PRIMITIVE_PRINT_FUNC(double, double, "%f") + +#define CVEC_APPEND(dest, elem) \ + ({ typeof(elem) _elem = (elem); \ + cvec_append(dest, &_elem); }) + +int main() +{ + int ret = 0; + cvec vec = {0}; + cvec uint_vec = {0}; + + ret = cvec_new(&vec, sizeof(int)); + if (ret < 0) + return ret; + + ret = cvec_append(&vec, &(int){1}); + if (ret < 0) + return ret; + + ret = cvec_append(&vec, &(int){2}); + if (ret < 0) + return ret; + + ret = cvec_append(&vec, &(int){3}); + if (ret < 0) + return ret; + + ret = CVEC_APPEND(&vec, 4); + if (ret < 0) + return ret; + + ret = cvec_append(&vec, &(int){5}); + if (ret < 0) + return ret; + + cvec_print(vec, cvec_int_print_func, CVEC_PRINT_FLAG_NONE); + + for (int i = 0; i < 100; i++) + { + ret = cvec_append(&vec, &(int){5 + i}); + if (ret < 0) + return ret; + } + + cvec_print(vec, cvec_int_print_func, CVEC_PRINT_FLAG_ELLIPSIS | CVEC_PRINT_FLAG_MULTILINE); + cvec_pop(&vec); + cvec_print(vec, cvec_int_print_func, CVEC_PRINT_FLAG_NONE); + cvec_erase(&vec); + cvec_print(vec, cvec_int_print_func, CVEC_PRINT_FLAG_NONE); + cvec_free(vec); +}