advent-of-code

Solutions for Advent of Code.
git clone git://git.amin.space/advent-of-code.git
Log | Files | Refs | LICENSE

commit 493efe528d1e6f5bab55426e6304ec7173d13c9f
parent d21bdd13f2579276c34e70f187971edecda3d62a
Author: amin <dev@aminmesbah.com>
Date:   Sun,  9 Jul 2023 06:40:11 +0000

Merge in the last remaining library copies

FossilOrigin-Name: 260b55b4949b90fe83b4bb79fb63f1b4ea87bcb4937b7a7eb510667830eb0e10
Diffstat:
D2021/am_base.h | 118-------------------------------------------------------------------------------
D2021/am_list.h | 233-------------------------------------------------------------------------------
D2021/am_memory.h | 178-------------------------------------------------------------------------------
D2021/am_string.h | 257-------------------------------------------------------------------------------
M2021/day01_01.c | 2+-
M2021/day01_02.c | 2+-
M2021/day02_01.c | 2+-
M2021/day02_02.c | 2+-
M2021/day03_01.c | 2+-
M2021/day03_02.c | 2+-
M2021/day04_01.c | 3++-
M2021/day04_02.c | 3++-
D2022/am_base.h | 118-------------------------------------------------------------------------------
D2022/am_list.h | 233-------------------------------------------------------------------------------
D2022/am_memory.h | 185-------------------------------------------------------------------------------
D2022/am_string.h | 381-------------------------------------------------------------------------------
M2022/day01.c | 2+-
M2022/day02.c | 2+-
18 files changed, 12 insertions(+), 1713 deletions(-)

diff --git a/2021/am_base.h b/2021/am_base.h @@ -1,118 +0,0 @@ -#ifndef AM_BASE_H -#define AM_BASE_H - -#if __STDC_VERSION__ < 201112L -# error "C11 or greater required." -#endif - -// context -// https://sourceforge.net/p/predef/wiki/Home/ -#if defined(__clang__) -# define COMPILER_CLANG 1 -#elif defined (__GNUC__) -# define COMPILER_GCC 1 -#else -# error "Unsupported compiler." -#endif - -#if !defined(COMPILER_CLANG) -# define COMPILER_CLANG 0 -#endif -#if !defined(COMPILER_GCC) -# define COMPILER_GCC 0 -#endif - -#if defined (__linux__) -# define OPERATING_SYSTEM_LINUX 1 -#elif defined(_WIN32) -# define OPERATING_SYSTEM_WINDOWS 1 -#else -# error "Unsupported OS." -#endif - -#if !defined(OPERATING_SYSTEM_LINUX) -# define OPERATING_SYSTEM_LINUX 0 -#endif -#if !defined(OPERATING_SYSTEM_WINDOWS) -# define OPERATING_SYSTEM_WINDOWS 0 -#endif - -// compiler builtins -#if COMPILER_CLANG || COMPILER_GCC -# ifndef __has_builtin -# define __has_builtin(x) 0 -# endif -#endif - -#define IMPLEMENTATION_UNSIGNED_CHAR (CHAR_MIN == 0) - -// freestanding headers -#include <float.h> -#include <limits.h> -#include <stdalign.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include <stdnoreturn.h> - -// preprocessor improvement -#define AM__STRINGIFY(S) #S -#define AM__GLUE(A, B) A##B -#define AM_STRINGIFY(S) AM__STRINGIFY(S) -#define AM_GLUE(A, B) AM__GLUE((A), (B)) - -// assert -#define static_assert(expr) _Static_assert((expr), "") - -#if !defined(AM_ENABLE_ASSERT) -# define AM_ENABLE_ASSERT 0 -#endif - -#if AM_ENABLE_ASSERT -# if !defined(AM_ASSERT_FAIL) -# if __has_builtin(__builtin_trap) -# define AM_ASSERT_FAIL(expr, file, line, func) __builtin_trap() -# else -# error "Must define implementation of AM_ASSERT_FAIL(expr, file, line, func)." -# endif -# endif -# define assert(x) ((void)((x) || (AM_ASSERT_FAIL(AM_STRINGIFY(x), __FILE__, __LINE__, __func__),0))) -#else -# define assert(c) ((void)0) -#endif - -#define AM_UNREACHABLE assert(false && "Unreachable code reached") - -// utility macros -#define ALIGN_UP_POW_2(x, p) (((x) + (p) - 1) & ~((p) - (1))) -#define ALIGN_DOWN_POW_2(x, p) ((x) & ~((p) - 1)) -#define ARRAY_COUNT(a) (sizeof(a)/sizeof(*(a))) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define CLAMP(a, x, b) (((x) < (a)) ? (a) : (((b) < (x)) ? (b) : (x))) -#define CLAMP_TOP(a, b) MIN((a), (b)) -#define CLAMP_BOT(a, b) MAX((a), (b)) -#define UNUSED(p) (void)(p) - -// basic types -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef size_t usz; -typedef float f32; -typedef double f64; - -#define global static -#define local_persist static -#define internal static - -// sanity checks -static_assert(CHAR_BIT == 8); - -#endif // AM_BASE_H diff --git a/2021/am_list.h b/2021/am_list.h @@ -1,233 +0,0 @@ -#ifndef AM_LIST_H -#define AM_LIST_H - -#define DLL_APPEND_NP(f, l, n, next, prev) \ - ((f) == NULL \ - ? ((f) = (l) = (n) \ - , (f)->prev = (n)->next = NULL) \ - : ((n)->prev = (l) \ - , (l)->next = (n) \ - , (l) = (n) \ - , (n)->next = NULL)) - -#define DLL_REMOVE_NP(f, l, n, next, prev) \ - ((f) == (l) && (f) == (n) \ - ? ((f) = (l) = NULL) \ - : ((f) == (n) \ - ? ((f) = (f)->next \ - , (f)->prev = NULL) \ - : ((l) == (n) \ - ? ((l) = (l)->prev \ - , (l)->next = NULL) \ - : ((n)->prev->next = (n)->next \ - , (n)->next->prev = (n)->prev)))) - -#define SLL_QUEUE_PUSH_N(f, l, n, next) \ - ((f) == NULL \ - ? ((f) = (l) = (n)) \ - : ((l)->next = (n) \ - , (l) = (n) \ - , (n)->next = NULL)) - -#define SLL_QUEUE_PUSH_FRONT_N(f, l, n, next) \ - ((f) == NULL \ - ? ((f) = (l) = (n) \ - , (n)->next = NULL) \ - : ((n)->next = (f) \ - , (f) = (n))) - -// TODO: It's maybe somewhat surprising to the user that these pop functions -// don't return the popped node. -#define SLL_QUEUE_POP_N(f, l, next) \ - ((f) == (l) \ - ? ((f) = (l) = NULL) \ - : ((f) = (f)->next)) - - -#define SLL_STACK_PUSH_N(f, n, next) ((n)->next = (f), (f) = (n)) - -#define SLL_STACK_POP_N(f, next) \ - ((f) == NULL \ - ? 0 \ - : ((f) = (f)->next)) - -#define DLL_APPEND(f, l, n) DLL_APPEND_NP((f), (l), (n), next, prev) -#define DLL_PREPEND(f, l, n) DLL_APPEND_NP((l), (f), (n), prev, next) -#define DLL_REMOVE(f, l, n) DLL_REMOVE_NP((f), (l), (n), next, prev) - -#define SLL_QUEUE_PUSH(f, l, n) SLL_QUEUE_PUSH_N((f), (l), (n), next) -#define SLL_QUEUE_PUSH_FRONT(f, l, n) SLL_QUEUE_PUSH_FRONT_N((f), (l), (n), next) -#define SLL_QUEUE_POP(f, l) SLL_QUEUE_POP_N((f), (l), next) - -#define SLL_STACK_PUSH(f, n) SLL_STACK_PUSH_N((f), (n), next) -#define SLL_STACK_POP(f) SLL_STACK_POP_N((f), next) - -#if defined(AM_INCLUDE_TESTS) -typedef struct TestNode TestNode; -struct TestNode { - TestNode *next; - TestNode *prev; - s32 val; -}; - -internal void am_list_test(void) { - TestNode nodes[10] = {0}; - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - nodes[i].val = i; - } - - { - TestNode *first = NULL; - TestNode *last = NULL; - - printf("dll append and remove from front\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_APPEND(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_REMOVE(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - printf("dll prepend and remove from back\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_PREPEND(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_REMOVE(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - printf("dll append and remove from middle\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_APPEND(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_REMOVE(first, last, &nodes[(i + (ARRAY_COUNT(nodes) / 2)) % ARRAY_COUNT(nodes)]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - } - - { - TestNode *first = NULL; - TestNode *last = NULL; - - printf("sll queue push and pop\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - SLL_QUEUE_PUSH(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - while (first) { - SLL_QUEUE_POP(first, last); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - printf("sll queue push front and pop\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - SLL_QUEUE_PUSH_FRONT(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - while (first) { - SLL_QUEUE_POP(first, last); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - } - - { - TestNode *first = NULL; - - printf("sll stack push and pop\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - SLL_STACK_PUSH(first, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - while (first) { - SLL_STACK_POP(first); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - } -} -#endif // defined(AM_INCLUDE_TESTS) - -#endif // AM_LIST_H diff --git a/2021/am_memory.h b/2021/am_memory.h @@ -1,178 +0,0 @@ -#ifndef AM_MEMORY_H -#define AM_MEMORY_H - -#define MEM_KIB(b) ((u64)(b) << 10) -#define MEM_MIB(b) ((u64)(b) << 20) -#define MEM_GIB(b) ((u64)(b) << 30) - -#define AM_MEM_RESERVE_FN(name) void *(name)(void *ctx, u64 size) -typedef AM_MEM_RESERVE_FN(am_mem_reserve_fn); - -#define AM_MEM_CHANGE_FN(name) void (name)(void *ctx, void *ptr, u64 size) -typedef AM_MEM_CHANGE_FN(am_mem_change_fn); - -typedef struct { - am_mem_reserve_fn* reserve; - am_mem_change_fn* commit; - am_mem_change_fn* decommit; - am_mem_change_fn* release; - void *ctx; -} BaseAllocator; - -#define AM_MEM_ARENA_COMMIT_BLOCK_SIZE MEM_MIB(64) -#define AM_MEM_ARENA_DEFAULT_RESERVE_SIZE MEM_GIB(1) - -typedef struct { - BaseAllocator *base; - u8 *mem; - u64 cap; - u64 pos; - u64 commit_pos; -} MemArena; - -internal AM_MEM_CHANGE_FN(am_mem_change_noop) { - UNUSED(ctx); - UNUSED(ptr); - UNUSED(size); -} - -internal AM_MEM_RESERVE_FN(am_mem_reserve_malloc) { - UNUSED(ctx); - return malloc(size); -} - -internal AM_MEM_CHANGE_FN(am_mem_release_malloc) { - UNUSED(ctx); - UNUSED(size); - free(ptr); -} - -internal BaseAllocator *am_mem_base_allocator_malloc(void) { - local_persist BaseAllocator b; - if (!b.reserve) { - b = (BaseAllocator) { - .reserve = am_mem_reserve_malloc, - .commit = am_mem_change_noop, - .decommit = am_mem_change_noop, - .release = am_mem_release_malloc, - }; - } - return &b; -} - -internal MemArena am_mem_arena_create_reserve(BaseAllocator *base, u64 reserve_size) { - MemArena a = { - .base = base, - }; - a.mem = a.base->reserve(a.base->ctx, reserve_size); - a.cap = reserve_size; - return a; -} - -internal MemArena am_mem_arena_create(BaseAllocator *base) { - return am_mem_arena_create_reserve(base, AM_MEM_ARENA_DEFAULT_RESERVE_SIZE); -} - -internal void *am_mem_arena_push(MemArena *a, u64 size) { - void *result = NULL; - if (a->mem + size <= a->mem + a->cap) { - result = a->mem + a->pos; - a->pos += size; - - if (a->pos > a->commit_pos) { - u64 aligned = ALIGN_UP_POW_2(a->pos, AM_MEM_ARENA_COMMIT_BLOCK_SIZE); - u64 next_commit_pos = CLAMP_TOP(aligned, a->cap); - u64 commit_size = next_commit_pos - a->commit_pos; - a->base->commit(a->base->ctx, a->mem + a->commit_pos, commit_size); - a->commit_pos = next_commit_pos; - } - } - return result; -} - -#define AM_MEM_ARENA_PUSH_ARRAY(arena, T, count) (am_mem_arena_push((arena), sizeof(T) * (count))) - -internal void am_mem_arena_pop_to(MemArena *a, u64 pos) { - if (pos < a->pos) { - a->pos = pos; - - u64 aligned = ALIGN_UP_POW_2(a->pos, AM_MEM_ARENA_COMMIT_BLOCK_SIZE); - u64 next_commit_pos = CLAMP_TOP(aligned, a->cap); - if (next_commit_pos < a->commit_pos) { - u64 decommit_size = a->commit_pos - next_commit_pos; - a->base->decommit(a->base->ctx, a->mem + a->commit_pos, decommit_size); - a->commit_pos = next_commit_pos; - } - } -} - -internal void am_mem_arena_release(MemArena *a) { - a->base->release(a->base->ctx, a->mem, a->cap); - *a = (MemArena){0}; -} - -// TODO: SIMD -internal void am_mem_copy(void *dst, void *src, u64 size) { - for (u64 i = 0; i < size; i++) { - ((u8 *)dst)[i] = ((u8 *)src)[i]; - } -} - -internal bool am_mem_equal(void *dst, void *src, u64 size) { - for (u64 i = 0; i < size; i++) { - if (((u8 *)dst)[i] != ((u8 *)src)[i]) { - return false; - } - } - return true; -} - -#if defined(AM_INCLUDE_TESTS) -internal void am_memory_test(void) { - assert(MEM_KIB(10) == 10240); - assert(MEM_MIB(10) == 10485760); - assert(MEM_GIB(10) == 10737418240); - - { - BaseAllocator *a = am_mem_base_allocator_malloc(); - u64 num_test_ints = 10; - s32 *int_buf = a->reserve(NULL, num_test_ints * sizeof(s32)); - assert(int_buf); - a->release(NULL, int_buf, 0); - } - - { - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - am_mem_arena_push(&a, 1020); - assert(a.pos == 1020); - u64 p = a.pos; - u64 cp = a.commit_pos; - - AM_MEM_ARENA_PUSH_ARRAY(&a, u8, a.cap - a.pos); - assert(a.pos == a.cap); - assert(a.commit_pos == a.cap); - - am_mem_arena_pop_to(&a, p); - assert(a.pos == p); - assert(a.commit_pos == cp); - - am_mem_arena_release(&a); - assert(a.pos == 0); - assert(a.commit_pos == 0); - assert(a.mem == NULL); - } - - { - u8 src[10] = {0}; - u8 dst[10] = {0}; - for (u64 i = 0; i < ARRAY_COUNT(src); i++) { - src[i] = i; - } - - am_mem_copy(dst, src, ARRAY_COUNT(dst)); - assert(am_mem_equal(dst, src, ARRAY_COUNT(dst))); - } -} -#endif // defined(AM_INCLUDE_TESTS) - -#endif // AM_MEMORY_H diff --git a/2021/am_string.h b/2021/am_string.h @@ -1,257 +0,0 @@ -#ifndef AM_STRING_H -#define AM_STRING_H - -#ifndef AM_MEMORY_H - #error "am_memory.h is required" -#endif -#ifndef AM_LIST_H - #error "am_list.h is required" -#endif - -typedef struct { - usz size; - u8 *str; -} Str; - -typedef struct StrListNode StrListNode; -struct StrListNode { - StrListNode *next; - Str s; -}; - -typedef struct { - StrListNode *first; - StrListNode *last; - u64 node_count; - u64 total_size; -} StrList; - -#define AM_STR_LIT(s) (Str) { .str = (u8 *)(s), .size = sizeof(s) - 1, } -#define AM_STR_EXPAND(s) (s32)((s).size), ((s).str) - -internal usz am_cstr_len(char *cstr) { - usz len = 0; - while (cstr && *cstr != '\0') { - len++; - cstr++; - } - return len; -} - -internal Str am_str(u8 *str, usz size) { - return (Str) { .size = size, .str = str, }; -} - -internal Str am_str_from_range(u8 *start, u8 *opl) { - assert(start < opl); - return am_str(start, opl - start); -} - -internal Str am_str_from_cstr(char *cstr, usz len) { - return am_str((u8 *)cstr, len); -} - -// TODO: Use string interning -internal bool am_str_eq(Str s1, Str s2) { - if (s1.size != s2.size) { - return false; - } - - for (usz i = 0; i < s1.size; i++) { - if (s1.str[i] != s2.str[i]) { - return false; - } - } - - return true; -} - -internal bool am_cstr_eq(char *cstr1, char *cstr2) { - usz len1 = am_cstr_len(cstr1); - usz len2 = am_cstr_len(cstr2); - return am_str_eq(am_str_from_cstr(cstr1, len1), am_str_from_cstr(cstr2, len2)); -} - -internal Str am_str_line(Str s, u8 *cursor) { - u8 *opl = s.str + s.size; - - assert(cursor >= s.str && cursor < opl); - - u8 *end = cursor; - while (end < opl) { - if (*end == '\n') { - break; - } - end++; - } - - u8 *beginning = cursor - (*cursor == '\n'); - while (beginning >= s.str) { - if (*beginning == '\n') { - beginning++; - break; - } - beginning--; - } - - return am_str_from_range(beginning, end); -} - -internal bool am_str_contains(Str s, char c) { - for (usz i = 0; i < s.size; i++) { - if (s.str[i] == c) { - return true; - } - } - return false; -} - -internal bool am_cstr_contains(char *s, usz len, char c) { - return am_str_contains(am_str_from_cstr(s, len), c); -} - -internal bool am_str_cstr_eq(Str s, char *cstr) { - return am_str_eq(s, am_str_from_cstr(cstr, am_cstr_len(cstr))); -} - -internal void am_str_list_append(MemArena *arena, StrList *list, Str s) { - StrListNode *node = am_mem_arena_push(arena, sizeof(StrListNode)); - *node = (StrListNode) { - .s = s, - }; - SLL_QUEUE_PUSH(list->first, list->last, node); - list->node_count += 1; - list->total_size += s.size; -} - -typedef struct { - Str pre; - Str mid; - Str post; -} StringJoinOptions; - -internal Str am_str_join(MemArena *arena, StrList *list, StringJoinOptions *options) { - StringJoinOptions join; - if (options) { - join = *options; - } else { - join = (StringJoinOptions){0}; - } - - u64 total_size = list->total_size - + join.pre.size - + (join.mid.size * (list->node_count - 1)) - + join.post.size; - - Str s= { - .str = AM_MEM_ARENA_PUSH_ARRAY(arena, u8, total_size), - .size = total_size, - }; - - u8 *p = s.str; - am_mem_copy(p, join.pre.str, join.pre.size); - p += join.pre.size; - - bool is_mid = false; - for (StrListNode *n = list->first; n; n = n->next) { - if (is_mid) { - am_mem_copy(p, join.mid.str, join.mid.size); - p += join.mid.size; - } - - am_mem_copy(p, n->s.str, n->s.size); - p += n->s.size; - - is_mid = true; - } - - am_mem_copy(p, join.post.str, join.post.size); - p += join.post.size; - - return s; -} - -internal StrList am_str_split(MemArena *arena, Str s, u8 *split_chars, u64 split_char_count) { - StrList list = {0}; - - u8 *cursor = s.str; - u8 *split_beginning = cursor; - u8 *opl = s.str + s.size; - while (cursor < opl) { - bool split_byte = false; - for (u64 i = 0; i < split_char_count; i++) { - if (split_chars[i] == *cursor) { - split_byte = true; - break; - } - } - - if (split_byte) { - if (split_beginning < cursor) { - am_str_list_append(arena, &list, am_str_from_range(split_beginning, cursor)); - } - split_beginning = cursor + 1; - } - cursor++; - } - - if (split_beginning < cursor) { - am_str_list_append(arena, &list, am_str_from_range(split_beginning, cursor)); - } - - return list; -} - -#if defined(AM_INCLUDE_TESTS) -internal void am_string_test(void) { - assert(am_cstr_len("abcdefg") == 7); - assert(am_cstr_len("") == 0); - assert(am_cstr_len("\0") == 0); - assert(am_cstr_eq("", "")); - assert(am_cstr_eq("\0", "\0")); - assert(am_cstr_eq("abc", "abc")); - assert(!am_cstr_eq("ABC", "abc")); - assert(!am_cstr_eq("", " ")); - assert(!am_cstr_eq("abc", "abcde")); - assert(!am_str_cstr_eq(AM_STR_LIT("abcd"), "abc")); - assert(am_str_cstr_eq(AM_STR_LIT("abc"), "abc")); - assert(am_cstr_contains("abc", 3, 'c')); - assert(am_cstr_contains("a c", 3, ' ')); - assert(am_cstr_contains("", 1, '\0')); - assert(!am_cstr_contains("abc", 3, 'z')); - assert(!am_cstr_contains("", 0, 'z')); - assert(!am_cstr_contains("", 0, '\0')); - assert(am_cstr_contains("https://www.example.com", 23, '/')); - - { - StrList l = {0}; - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - Str strings[] = { - AM_STR_LIT("one"), - AM_STR_LIT("two"), - AM_STR_LIT("three"), - }; - - for (u64 i = 0; i < ARRAY_COUNT(strings); i++) { - am_str_list_append(&a, &l, strings[i]); - } - - Str joined = am_str_join(&a, &l, &(StringJoinOptions){ - .pre = AM_STR_LIT("Joined: '"), - .mid = AM_STR_LIT(", "), - .post = AM_STR_LIT("'."), - }); - - printf("%.*s\n", AM_STR_EXPAND(joined)); - - StrList split = am_str_split(&a, AM_STR_LIT(", one, two, three, "), (u8 *)", ", 2); - - for (StrListNode *n = split.first; n; n = n->next) { - printf("split: '%.*s'\n", AM_STR_EXPAND(n->s)); - } - am_mem_arena_release(&a); - } -} -#endif // defined(AM_INCLUDE_TESTS) - -#endif // AM_STRING_H diff --git a/2021/day01_01.c b/2021/day01_01.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then diff --git a/2021/day01_02.c b/2021/day01_02.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then diff --git a/2021/day02_01.c b/2021/day02_01.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then diff --git a/2021/day02_02.c b/2021/day02_02.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then diff --git a/2021/day03_01.c b/2021/day03_01.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then diff --git a/2021/day03_02.c b/2021/day03_02.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then diff --git a/2021/day04_01.c b/2021/day04_01.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then @@ -82,6 +82,7 @@ int main(void) { Str input = open_file(&a, "day04_input.txt"); StrList split_data = am_str_split(&a, input, (u8 *)"\n ", 2); + am_str_list_discard_empty(&split_data); StrList split_first_line = am_str_split(&a, split_data.first->s, (u8 *)",", 1); u64 drawn_number_count = split_first_line.node_count; diff --git a/2021/day04_02.c b/2021/day04_02.c @@ -7,7 +7,7 @@ if [ "$input" -nt "$output" ]; then mkdir --parents "$outdir" || exit echo "Building ${output}." || exit - clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit fi if [ "$1" = "-r" ]; then @@ -82,6 +82,7 @@ int main(void) { Str input = open_file(&a, "day04_input.txt"); StrList split_data = am_str_split(&a, input, (u8 *)"\n ", 2); + am_str_list_discard_empty(&split_data); StrList split_first_line = am_str_split(&a, split_data.first->s, (u8 *)",", 1); u64 drawn_number_count = split_first_line.node_count; diff --git a/2022/am_base.h b/2022/am_base.h @@ -1,118 +0,0 @@ -#ifndef AM_BASE_H -#define AM_BASE_H - -#if __STDC_VERSION__ < 201112L -# error "C11 or greater required." -#endif - -// context -// https://sourceforge.net/p/predef/wiki/Home/ -#if defined(__clang__) -# define COMPILER_CLANG 1 -#elif defined (__GNUC__) -# define COMPILER_GCC 1 -#else -# error "Unsupported compiler." -#endif - -#if !defined(COMPILER_CLANG) -# define COMPILER_CLANG 0 -#endif -#if !defined(COMPILER_GCC) -# define COMPILER_GCC 0 -#endif - -#if defined (__linux__) -# define OPERATING_SYSTEM_LINUX 1 -#elif defined(_WIN32) -# define OPERATING_SYSTEM_WINDOWS 1 -#else -# error "Unsupported OS." -#endif - -#if !defined(OPERATING_SYSTEM_LINUX) -# define OPERATING_SYSTEM_LINUX 0 -#endif -#if !defined(OPERATING_SYSTEM_WINDOWS) -# define OPERATING_SYSTEM_WINDOWS 0 -#endif - -// compiler builtins -#if COMPILER_CLANG || COMPILER_GCC -# ifndef __has_builtin -# define __has_builtin(x) 0 -# endif -#endif - -#define IMPLEMENTATION_UNSIGNED_CHAR (CHAR_MIN == 0) - -// freestanding headers -#include <float.h> -#include <limits.h> -#include <stdalign.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include <stdnoreturn.h> - -// preprocessor improvement -#define AM__STRINGIFY(S) #S -#define AM__GLUE(A, B) A##B -#define AM_STRINGIFY(S) AM__STRINGIFY(S) -#define AM_GLUE(A, B) AM__GLUE((A), (B)) - -// assert -#define static_assert(expr) _Static_assert((expr), "") - -#if !defined(AM_ENABLE_ASSERT) -# define AM_ENABLE_ASSERT 0 -#endif - -#if AM_ENABLE_ASSERT -# if !defined(AM_ASSERT_FAIL) -# if __has_builtin(__builtin_trap) -# define AM_ASSERT_FAIL(expr, file, line, func) __builtin_trap() -# else -# error "Must define implementation of AM_ASSERT_FAIL(expr, file, line, func)." -# endif -# endif -# define assert(x) ((void)((x) || (AM_ASSERT_FAIL(AM_STRINGIFY(x), __FILE__, __LINE__, __func__),0))) -#else -# define assert(c) ((void)0) -#endif - -#define AM_UNREACHABLE assert(false && "Unreachable code reached") - -// utility macros -#define ALIGN_UP_POW_2(x, p) (((x) + (p) - 1) & ~((p) - (1))) -#define ALIGN_DOWN_POW_2(x, p) ((x) & ~((p) - 1)) -#define ARRAY_COUNT(a) (sizeof(a)/sizeof(*(a))) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define CLAMP(a, x, b) (((x) < (a)) ? (a) : (((b) < (x)) ? (b) : (x))) -#define CLAMP_TOP(a, b) MIN((a), (b)) -#define CLAMP_BOT(a, b) MAX((a), (b)) -#define UNUSED(p) (void)(p) - -// basic types -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef size_t usz; -typedef float f32; -typedef double f64; - -#define global static -#define local_persist static -#define internal static - -// sanity checks -static_assert(CHAR_BIT == 8); - -#endif // AM_BASE_H diff --git a/2022/am_list.h b/2022/am_list.h @@ -1,233 +0,0 @@ -#ifndef AM_LIST_H -#define AM_LIST_H - -#define DLL_APPEND_NP(f, l, n, next, prev) \ - ((f) == NULL \ - ? ((f) = (l) = (n) \ - , (f)->prev = (n)->next = NULL) \ - : ((n)->prev = (l) \ - , (l)->next = (n) \ - , (l) = (n) \ - , (n)->next = NULL)) - -#define DLL_REMOVE_NP(f, l, n, next, prev) \ - ((f) == (l) && (f) == (n) \ - ? ((f) = (l) = NULL) \ - : ((f) == (n) \ - ? ((f) = (f)->next \ - , (f)->prev = NULL) \ - : ((l) == (n) \ - ? ((l) = (l)->prev \ - , (l)->next = NULL) \ - : ((n)->prev->next = (n)->next \ - , (n)->next->prev = (n)->prev)))) - -#define SLL_QUEUE_PUSH_N(f, l, n, next) \ - ((f) == NULL \ - ? ((f) = (l) = (n)) \ - : ((l)->next = (n) \ - , (l) = (n) \ - , (n)->next = NULL)) - -#define SLL_QUEUE_PUSH_FRONT_N(f, l, n, next) \ - ((f) == NULL \ - ? ((f) = (l) = (n) \ - , (n)->next = NULL) \ - : ((n)->next = (f) \ - , (f) = (n))) - -// TODO: It's maybe somewhat surprising to the user that these pop functions -// don't return the popped node. -#define SLL_QUEUE_POP_N(f, l, next) \ - ((f) == (l) \ - ? ((f) = (l) = NULL) \ - : ((f) = (f)->next)) - - -#define SLL_STACK_PUSH_N(f, n, next) ((n)->next = (f), (f) = (n)) - -#define SLL_STACK_POP_N(f, next) \ - ((f) == NULL \ - ? 0 \ - : ((f) = (f)->next)) - -#define DLL_APPEND(f, l, n) DLL_APPEND_NP((f), (l), (n), next, prev) -#define DLL_PREPEND(f, l, n) DLL_APPEND_NP((l), (f), (n), prev, next) -#define DLL_REMOVE(f, l, n) DLL_REMOVE_NP((f), (l), (n), next, prev) - -#define SLL_QUEUE_PUSH(f, l, n) SLL_QUEUE_PUSH_N((f), (l), (n), next) -#define SLL_QUEUE_PUSH_FRONT(f, l, n) SLL_QUEUE_PUSH_FRONT_N((f), (l), (n), next) -#define SLL_QUEUE_POP(f, l) SLL_QUEUE_POP_N((f), (l), next) - -#define SLL_STACK_PUSH(f, n) SLL_STACK_PUSH_N((f), (n), next) -#define SLL_STACK_POP(f) SLL_STACK_POP_N((f), next) - -#ifdef AM_LIST_TESTS -typedef struct TestNode TestNode; -struct TestNode { - TestNode *next; - TestNode *prev; - s32 val; -}; - -internal void am_list_test(void) { - TestNode nodes[10] = {0}; - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - nodes[i].val = i; - } - - { - TestNode *first = NULL; - TestNode *last = NULL; - - printf("dll append and remove from front\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_APPEND(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_REMOVE(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - printf("dll prepend and remove from back\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_PREPEND(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_REMOVE(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - printf("dll append and remove from middle\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_APPEND(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - DLL_REMOVE(first, last, &nodes[(i + (ARRAY_COUNT(nodes) / 2)) % ARRAY_COUNT(nodes)]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf(" <|> "); - for (TestNode *n = last; n; n = n->prev) { - printf(" %i ", n->val); - } - printf("]\n"); - } - } - - { - TestNode *first = NULL; - TestNode *last = NULL; - - printf("sll queue push and pop\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - SLL_QUEUE_PUSH(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - while (first) { - SLL_QUEUE_POP(first, last); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - printf("sll queue push front and pop\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - SLL_QUEUE_PUSH_FRONT(first, last, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - while (first) { - SLL_QUEUE_POP(first, last); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - } - - { - TestNode *first = NULL; - - printf("sll stack push and pop\n"); - for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) { - SLL_STACK_PUSH(first, &nodes[i]); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - - while (first) { - SLL_STACK_POP(first); - printf("["); - for (TestNode *n = first; n; n = n->next) { - printf(" %i ", n->val); - } - printf("]\n"); - } - } -} -#endif // AM_LIST_TESTS - -#endif // AM_LIST_H diff --git a/2022/am_memory.h b/2022/am_memory.h @@ -1,185 +0,0 @@ -#ifndef AM_MEMORY_H -#define AM_MEMORY_H - -#define MEM_KIB(b) ((u64)(b) << 10) -#define MEM_MIB(b) ((u64)(b) << 20) -#define MEM_GIB(b) ((u64)(b) << 30) - -#define AM_MEM_RESERVE_FN(name) void *(name)(void *ctx, u64 size) -typedef AM_MEM_RESERVE_FN(am_mem_reserve_fn); - -#define AM_MEM_CHANGE_FN(name) void (name)(void *ctx, void *ptr, u64 size) -typedef AM_MEM_CHANGE_FN(am_mem_change_fn); - -typedef struct { - am_mem_reserve_fn* reserve; - am_mem_change_fn* commit; - am_mem_change_fn* decommit; - am_mem_change_fn* release; - void *ctx; -} BaseAllocator; - -#define AM_MEM_ARENA_COMMIT_BLOCK_SIZE MEM_MIB(64) -#define AM_MEM_ARENA_DEFAULT_RESERVE_SIZE MEM_GIB(1) - -typedef struct { - BaseAllocator *base; - u8 *mem; - u64 cap; - u64 pos; - u64 commit_pos; -} MemArena; - -internal AM_MEM_CHANGE_FN(am_mem_change_noop) { - UNUSED(ctx); - UNUSED(ptr); - UNUSED(size); -} - -internal AM_MEM_RESERVE_FN(am_mem_reserve_malloc) { - UNUSED(ctx); - return malloc(size); -} - -internal AM_MEM_CHANGE_FN(am_mem_release_malloc) { - UNUSED(ctx); - UNUSED(size); - free(ptr); -} - -internal BaseAllocator *am_mem_base_allocator_malloc(void) { - local_persist BaseAllocator b; - if (!b.reserve) { - b = (BaseAllocator) { - .reserve = am_mem_reserve_malloc, - .commit = am_mem_change_noop, - .decommit = am_mem_change_noop, - .release = am_mem_release_malloc, - }; - } - return &b; -} - -internal MemArena am_mem_arena_create_reserve(BaseAllocator *base, u64 reserve_size) { - MemArena a = { - .base = base, - }; - a.mem = a.base->reserve(a.base->ctx, reserve_size); - a.cap = reserve_size; - return a; -} - -internal MemArena am_mem_arena_create(BaseAllocator *base) { - return am_mem_arena_create_reserve(base, AM_MEM_ARENA_DEFAULT_RESERVE_SIZE); -} - -internal void *am_mem_arena_push(MemArena *a, u64 size) { - void *result = NULL; - if (a->mem + size <= a->mem + a->cap) { - result = a->mem + a->pos; - a->pos += size; - - if (a->pos > a->commit_pos) { - u64 aligned = ALIGN_UP_POW_2(a->pos, AM_MEM_ARENA_COMMIT_BLOCK_SIZE); - u64 next_commit_pos = CLAMP_TOP(aligned, a->cap); - u64 commit_size = next_commit_pos - a->commit_pos; - a->base->commit(a->base->ctx, a->mem + a->commit_pos, commit_size); - a->commit_pos = next_commit_pos; - } - } - return result; -} - -#define AM_MEM_ARENA_PUSH_ARRAY(arena, T, count) (am_mem_arena_push((arena), sizeof(T) * (count))) - -internal void am_mem_arena_pop_to(MemArena *a, u64 pos) { - if (pos < a->pos) { - a->pos = pos; - - u64 aligned = ALIGN_UP_POW_2(a->pos, AM_MEM_ARENA_COMMIT_BLOCK_SIZE); - u64 next_commit_pos = CLAMP_TOP(aligned, a->cap); - if (next_commit_pos < a->commit_pos) { - u64 decommit_size = a->commit_pos - next_commit_pos; - a->base->decommit(a->base->ctx, a->mem + a->commit_pos, decommit_size); - a->commit_pos = next_commit_pos; - } - } -} - -internal void am_mem_arena_release(MemArena *a) { - a->base->release(a->base->ctx, a->mem, a->cap); - *a = (MemArena){0}; -} - -// TODO: SIMD -internal void am_mem_copy(void *dst, void *src, u64 size) { - assert(dst); - for (u64 i = 0; i < size; i++) { - ((u8 *)dst)[i] = ((u8 *)src)[i]; - } -} - -internal void am_mem_set(u64 size, void *dst, u8 byte) { - assert(dst); - for (u64 i = 0; i < size; i++) { - ((u8 *)dst)[i] = byte; - } -} - -internal bool am_mem_equal(void *dst, void *src, u64 size) { - for (u64 i = 0; i < size; i++) { - if (((u8 *)dst)[i] != ((u8 *)src)[i]) { - return false; - } - } - return true; -} - -internal void am_memory_test(void) { - assert(MEM_KIB(10) == 10240); - assert(MEM_MIB(10) == 10485760); - assert(MEM_GIB(10) == 10737418240); - - { - BaseAllocator *a = am_mem_base_allocator_malloc(); - u64 num_test_ints = 10; - s32 *int_buf = a->reserve(NULL, num_test_ints * sizeof(s32)); - assert(int_buf); - a->release(NULL, int_buf, 0); - } - - { - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - am_mem_arena_push(&a, 1020); - assert(a.pos == 1020); - u64 p = a.pos; - u64 cp = a.commit_pos; - - AM_MEM_ARENA_PUSH_ARRAY(&a, u8, a.cap - a.pos); - assert(a.pos == a.cap); - assert(a.commit_pos == a.cap); - - am_mem_arena_pop_to(&a, p); - assert(a.pos == p); - assert(a.commit_pos == cp); - - am_mem_arena_release(&a); - assert(a.pos == 0); - assert(a.commit_pos == 0); - assert(a.mem == NULL); - } - - { - u8 src[10] = {0}; - u8 dst[10] = {0}; - for (u64 i = 0; i < ARRAY_COUNT(src); i++) { - assert(i < UINT8_MAX); - src[i] = (u8)i; - } - - am_mem_copy(dst, src, ARRAY_COUNT(dst)); - assert(am_mem_equal(dst, src, ARRAY_COUNT(dst))); - } -} - -#endif // AM_MEMORY_H diff --git a/2022/am_string.h b/2022/am_string.h @@ -1,381 +0,0 @@ -#ifndef AM_STRING_H -#define AM_STRING_H - -#ifndef AM_MEMORY_H - #error "am_memory.h is required" -#endif -#ifndef AM_LIST_H - #error "am_list.h is required" -#endif - -typedef struct { - usz size; - u8 *str; -} Str; - -typedef struct StrListNode StrListNode; -struct StrListNode { - StrListNode *next; - Str s; -}; - -typedef struct { - StrListNode *first; - StrListNode *last; - u64 node_count; - u64 total_size; -} StrList; - -#define AM_STR_LIT(s) (Str) { .str = (u8 *)(s), .size = sizeof(s) - 1, } -#define AM_STR_EXPAND(s) (s32)((s).size), ((s).str) - -internal usz am_cstr_len(char *cstr) { - usz len = 0; - while (cstr && *cstr != '\0') { - len++; - cstr++; - } - return len; -} - -internal Str am_str(u8 *str, usz size) { - return (Str) { .size = size, .str = str, }; -} - -internal Str am_str_from_range(u8 *start, u8 *opl) { - assert(start < opl); - return am_str(start, (usz)(opl - start)); -} - -internal Str am_str_from_cstr(char *cstr, usz len) { - return am_str((u8 *)cstr, len); -} - -// TODO: Use string interning -internal bool am_str_eq(Str s1, Str s2) { - if (s1.size != s2.size) { - return false; - } - - for (usz i = 0; i < s1.size; i++) { - if (s1.str[i] != s2.str[i]) { - return false; - } - } - - return true; -} - -internal bool am_cstr_eq(char *cstr1, char *cstr2) { - usz len1 = am_cstr_len(cstr1); - usz len2 = am_cstr_len(cstr2); - return am_str_eq(am_str_from_cstr(cstr1, len1), am_str_from_cstr(cstr2, len2)); -} - -internal Str am_str_line(Str s, u8 *cursor) { - u8 *opl = s.str + s.size; - - assert(cursor >= s.str && cursor < opl); - - u8 *end = cursor; - while (end < opl) { - if (*end == '\n') { - break; - } - end++; - } - - u8 *beginning = cursor - (*cursor == '\n'); - while (beginning > s.str) { - if (*beginning == '\n') { - beginning++; - break; - } - beginning--; - } - - return am_str_from_range(beginning, end); -} - -internal bool am_str_contains(Str s, char c) { - for (usz i = 0; i < s.size; i++) { - if (s.str[i] == c) { - return true; - } - } - return false; -} - -internal bool am_cstr_contains(char *s, usz len, char c) { - return am_str_contains(am_str_from_cstr(s, len), c); -} - -internal bool am_str_cstr_eq(Str s, char *cstr) { - return am_str_eq(s, am_str_from_cstr(cstr, am_cstr_len(cstr))); -} - -internal void am_str_list_append(MemArena *arena, StrList *list, Str s) { - StrListNode *node = am_mem_arena_push(arena, sizeof(StrListNode)); - *node = (StrListNode) { - .s = s, - }; - SLL_QUEUE_PUSH(list->first, list->last, node); - list->node_count += 1; - list->total_size += s.size; -} - -internal void am_str_list_discard_empty(StrList *list) { - assert(list); - if (list->node_count) { - StrListNode *previous = NULL; - - for (StrListNode *n = list->first; n; n = n->next) { - if (n->s.size == 0) { - assert(list->node_count > 0); - list->node_count--; - if (previous) { - previous->next = n->next; - } else { - list->first = n->next; - } - } else { - previous = n; - } - } - } -} - -typedef struct { - Str pre; - Str mid; - Str post; -} StringJoinOptions; - -internal Str am_str_join(MemArena *arena, StrList *list, StringJoinOptions *options) { - StringJoinOptions join; - if (options) { - join = *options; - } else { - join = (StringJoinOptions){0}; - } - - Str s = {0}; - - if (list->node_count) { - assert(list->node_count > 0); - - u64 total_size = list->total_size - + join.pre.size - + (join.mid.size * (list->node_count - 1)) - + join.post.size; - - s = (Str) { - .str = AM_MEM_ARENA_PUSH_ARRAY(arena, u8, total_size), - .size = total_size, - }; - - u8 *p = s.str; - am_mem_copy(p, join.pre.str, join.pre.size); - p += join.pre.size; - - bool is_mid = false; - for (StrListNode *n = list->first; n; n = n->next) { - if (is_mid) { - am_mem_copy(p, join.mid.str, join.mid.size); - p += join.mid.size; - } - - am_mem_copy(p, n->s.str, n->s.size); - p += n->s.size; - - is_mid = true; - } - - am_mem_copy(p, join.post.str, join.post.size); - p += join.post.size; - } - - return s; -} - -internal StrList am_str_split(MemArena *arena, Str s, u8 *split_chars, u64 split_char_count) { - StrList list = {0}; - - u8 *cursor = s.str; - u8 *split_beginning = cursor; - u8 *opl = s.str + s.size; - while (cursor <= opl) { - bool split_byte = false; - for (u64 i = 0; i < split_char_count; i++) { - if (split_chars[i] == *cursor) { - split_byte = true; - break; - } - } - - if (split_byte) { - if (cursor == split_beginning) { - am_str_list_append(arena, &list, AM_STR_LIT("")); - } else { - am_str_list_append(arena, &list, am_str_from_range(split_beginning, cursor)); - } - split_beginning = cursor + 1; - } - cursor++; - } - - return list; -} - -internal void am_string_test(void) { - assert(am_cstr_len("abcdefg") == 7); - assert(am_cstr_len("") == 0); - assert(am_cstr_len("\0") == 0); - assert(am_cstr_eq("", "")); - assert(am_cstr_eq("\0", "\0")); - assert(am_cstr_eq("abc", "abc")); - assert(!am_cstr_eq("ABC", "abc")); - assert(!am_cstr_eq("", " ")); - assert(!am_cstr_eq("abc", "abcde")); - assert(!am_str_cstr_eq(AM_STR_LIT("abcd"), "abc")); - assert(am_str_cstr_eq(AM_STR_LIT("abc"), "abc")); - assert(am_cstr_contains("abc", 3, 'c')); - assert(am_cstr_contains("a c", 3, ' ')); - assert(am_cstr_contains("", 1, '\0')); - assert(!am_cstr_contains("abc", 3, 'z')); - assert(!am_cstr_contains("", 0, 'z')); - assert(!am_cstr_contains("", 0, '\0')); - assert(am_cstr_contains("https://www.example.com", 23, '/')); - - { - StrList l = {0}; - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - Str strings[] = { - AM_STR_LIT("one"), - AM_STR_LIT("two"), - AM_STR_LIT("three"), - }; - - for (u64 i = 0; i < ARRAY_COUNT(strings); i++) { - am_str_list_append(&a, &l, strings[i]); - } - - Str joined = am_str_join(&a, &l, &(StringJoinOptions){ - .pre = AM_STR_LIT("Joined: '"), - .mid = AM_STR_LIT(", "), - .post = AM_STR_LIT("'."), - }); - - printf("%.*s\n", AM_STR_EXPAND(joined)); - - StrList split = am_str_split(&a, AM_STR_LIT(", one, two, three, four, "), (u8 *)", ", 2); - - for (StrListNode *n = split.first; n; n = n->next) { - printf("split: '%.*s'\n", AM_STR_EXPAND(n->s)); - } - - am_mem_arena_release(&a); - } - - { - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - StrList lines = am_str_split(&a, AM_STR_LIT("one|two|three|four"), (u8 *)"|", 1); - - Str expected[] = { - AM_STR_LIT("one"), - AM_STR_LIT("two"), - AM_STR_LIT("three"), - AM_STR_LIT("four"), - }; - - size_t i = 0; - for (StrListNode *line = lines.first; line; line = line->next) { - printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); - assert(i < ARRAY_COUNT(expected)); - assert(am_str_eq(line->s, expected[i])); - i++; - } - - assert(i + 1 == ARRAY_COUNT(expected)); - am_mem_arena_release(&a); - } - - { - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - StrList lines = am_str_split(&a, AM_STR_LIT("|one|two||three|four|"), (u8 *)"|", 1); - - Str expected[] = { - AM_STR_LIT(""), - AM_STR_LIT("one"), - AM_STR_LIT("two"), - AM_STR_LIT(""), - AM_STR_LIT("three"), - AM_STR_LIT("four"), - AM_STR_LIT(""), - }; - - size_t i = 0; - for (StrListNode *line = lines.first; line; line = line->next) { - printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); - assert(i < ARRAY_COUNT(expected)); - assert(am_str_eq(line->s, expected[i])); - i++; - } - - assert(i + 1 == ARRAY_COUNT(expected)); - am_mem_arena_release(&a); - } - - { - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - StrList lines = am_str_split(&a, AM_STR_LIT("|||"), (u8 *)"|", 1); - - Str expected[] = { - AM_STR_LIT(""), - AM_STR_LIT(""), - AM_STR_LIT(""), - AM_STR_LIT(""), - }; - - size_t i = 0; - for (StrListNode *line = lines.first; line; line = line->next) { - printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); - assert(i < ARRAY_COUNT(expected)); - assert(am_str_eq(line->s, expected[i])); - i++; - } - - assert(i + 1 == ARRAY_COUNT(expected)); - am_mem_arena_release(&a); - } - - { - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - StrList lines = am_str_split(&a, AM_STR_LIT(""), (u8 *)"|", 1); - - assert(lines.node_count == 0); - am_mem_arena_release(&a); - } - - { - MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); - StrList lines = am_str_split(&a, AM_STR_LIT("one two three four"), (u8 *)"|", 1); - - Str expected[] = { - AM_STR_LIT("one two three four"), - }; - - size_t i = 0; - for (StrListNode *line = lines.first; line; line = line->next) { - printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); - assert(i < ARRAY_COUNT(expected)); - assert(am_str_eq(line->s, expected[i])); - i++; - } - - assert(i + 1 == ARRAY_COUNT(expected)); - am_mem_arena_release(&a); - } -} - -#endif // AM_STRING_H diff --git a/2022/day01.c b/2022/day01.c @@ -5,7 +5,7 @@ input=$(basename "$0") output="$outdir"/$(basename "$0" .c) mkdir --parents "$outdir" || exit echo "Building ${output}." || exit -clang -std=c11 -O0 -g -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit +clang -std=c11 -O0 -g -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit if [ "$1" = "-r" ]; then ./"$output" "$@" diff --git a/2022/day02.c b/2022/day02.c @@ -5,7 +5,7 @@ input=$(basename "$0") output="$outdir"/$(basename "$0" .c) mkdir --parents "$outdir" || exit echo "Building ${output}." || exit -clang -std=c11 -O0 -g -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit +clang -std=c11 -O0 -g -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit if [ "$1" = "-r" ]; then ./"$output" "$@"