commit f1b29d1c3f0d62ea69804e618c9e7c8619bb0b26 Author: Abdelrahman Date: Sat Jan 20 21:37:22 2024 +0000 INITIAL COMMIT diff --git a/README.md b/README.md new file mode 100644 index 0000000..8025b0d --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Wizard Apprentice Standard Library + +A collection of useful C/C++ utilities for my projects diff --git a/aliases/aliases.h b/aliases/aliases.h new file mode 100644 index 0000000..1a8e776 --- /dev/null +++ b/aliases/aliases.h @@ -0,0 +1,27 @@ +#ifndef ALIASES_H +#define ALIASES_H + +#include + +#define u8 uint8_t +#define u16 uint16_t +#define u32 uint32_t +#define u64 uint64_t + +#define i8 int8_t +#define i16 int16_t +#define i32 int32_t +#define i64 int64_t + +#define f32 float +#define f64 double +#define f128 long double + +#define INTERNAL static +#define PERSISTENT static + +#ifdef __cplusplus +#define CLASS_MEMBER static +#endif // __cplusplus + +#endif // !ALIASES_H diff --git a/cpath/include/cpath.h b/cpath/include/cpath.h new file mode 100644 index 0000000..06f7018 --- /dev/null +++ b/cpath/include/cpath.h @@ -0,0 +1,18 @@ +#ifndef PATH_UTILS_H +#define PATH_UTILS_H + +#include "aliases.h" + +#define NUMPARTS(...) \ + (sizeof((const char *[]){"", __VA_ARGS__}) / sizeof(const char *) - 1) + +#define JOIN_PATH(DST, ...) join_path(DST, NUMPARTS(__VA_ARGS__), __VA_ARGS__) + +void join_path(char *dst, u64 count, ...); + +#define DIRNAME(DST, PATH) dirup(DST, 1, PATH) +#define DIRUP(DST, COUNT, PATH) dirup(DST, COUNT, PATH) + +void dirup(char *dst, u64 levels, const char *path); + +#endif // !PATH_UTILS_H diff --git a/cpath/src/cpath.c b/cpath/src/cpath.c new file mode 100644 index 0000000..50531f6 --- /dev/null +++ b/cpath/src/cpath.c @@ -0,0 +1,78 @@ +#include "cpath.h" +#include "aliases.h" +#include +#include +#include + +#if defined(__unix__) || defined(__APPLE__) || defined(__ANDROID__) +INTERNAL char path_sep = '/'; +#elif defined(_WIN32) || defined(_WIN64) +INTERNAL char path_sep = '\\'; +#endif + +void join_root_and_leaf(const char *root, const char *leaf, char *dst); + +void join_path(char *dst, u64 count, ...) { + va_list args; + + va_start(args, count); + + for (u64 i = 0; i < count; ++i) { + join_root_and_leaf(dst, va_arg(args, const char *), dst); + } + + va_end(args); +} + +void dirup(char *dst, u64 levels, const char *path) { + if (levels < 1) { + return; + } + + u64 end_index = 0; + u64 sep_count = 0; + + u64 length = strlen(path); + if (path[length - 1] == path_sep) { + --length; + } + + for (u64 i = length - 1; i >= 0; --i) { + if (path[i] == path_sep) { + ++sep_count; + end_index = i; + + if (sep_count == levels) { + break; + } + } + } + + if (sep_count < levels) { + end_index = 0; + } + + strncpy(dst, path, end_index); +} + +void join_root_and_leaf(const char *root, const char *leaf, char *dst) { + u64 root_length = strlen(root); + u64 root_end = root_length - 1; + + u64 leaf_length = strlen(leaf); + u64 leaf_start = 0; + + if (root[root_end] == path_sep) { + --root_end; + } + + if (leaf[leaf_start] == path_sep) { + ++leaf_start; + } + + memcpy(dst, root, ++root_end); + + dst[root_end] = path_sep; + + memcpy(&(dst[++root_end]), &(leaf[leaf_start]), leaf_length - leaf_start); +} diff --git a/dstr/include/dstr.h b/dstr/include/dstr.h new file mode 100644 index 0000000..9000462 --- /dev/null +++ b/dstr/include/dstr.h @@ -0,0 +1,22 @@ +#ifndef DSTR_H +#define DSTR_H + +#include "aliases.h" + +typedef struct dstring dstr_t; + +dstr_t *dstr_with_capacity(u64 capacity); +dstr_t *dstr_from_string(const char *str); +void dstr_update(dstr_t **dst, const char *src); +void dstr_free(dstr_t **str); +void dstr_concat(dstr_t **dst, const char *src); +void dstr_append(dstr_t **dst, char c); +void dstr_resize(dstr_t **str); +void dstr_clear(dstr_t *str); +void dstr_print(const dstr_t *str); +i64 dstr_find(const dstr_t *str, const char *substr); +u64 dstr_length(const dstr_t *str); +u64 dstr_capacity(const dstr_t *str); +const char *dstr_to_cstr(const dstr_t *str); + +#endif // !DSTR_H diff --git a/dstr/src/dstr.c b/dstr/src/dstr.c new file mode 100644 index 0000000..bc4601d --- /dev/null +++ b/dstr/src/dstr.c @@ -0,0 +1,219 @@ +#include "dstr.h" +#include "aliases.h" +#include +#include +#include + +// Use this scalar to allocate extra memory in order to avoid having to +// constantly reallocate +#define CAPACITY_SCALAR 8 + +struct dstring { + u64 capacity; + u64 size; + char buf[]; +}; + +dstr_t *dstr_with_capacity(u64 capacity) { + dstr_t *out = (dstr_t *)malloc(sizeof(dstr_t) + capacity + 1); + + if (!out) { + return NULL; + } + + out->capacity = capacity; + out->size = 0; + memset(out->buf, 0, capacity + 1); + + return out; +} + +dstr_t *dstr_from_string(const char *str) { + if (!str) { + return NULL; + } + + u64 length = strlen(str); + + u64 capacity = length * CAPACITY_SCALAR; + + dstr_t *out = dstr_with_capacity(capacity); + + if (!out) { + return NULL; + } + + out->size = length; + strncpy(out->buf, str, length); + + return out; +} + +void dstr_update(dstr_t **dst, const char *src) { + if (!dst || !(*dst)) { + return; + } + + u64 length = strlen(src); + + dstr_t *str = *dst; + + if (length <= str->capacity) { + memset(str->buf, 0, str->capacity); + + str->size = length; + + strncpy(str->buf, src, length); + } else { + u64 capacity = length * CAPACITY_SCALAR; + + dstr_t *tmp = (dstr_t *)realloc(*dst, sizeof(dstr_t) + capacity + 1); + + if (!tmp) { + return; + } + + tmp->capacity = capacity; + tmp->size = length; + strncpy(tmp->buf, src, length); + + *dst = tmp; + } +} + +void dstr_free(dstr_t **str) { + if (!str || !(*str)) { + return; + } + + free(*str); + *str = NULL; +} + +void dstr_concat(dstr_t **dst, const char *src) { + if (!dst || !(*dst)) { + return; + } + + u64 src_length = strlen(src); + + if (src_length == 0) { + return; + } + + u64 new_length = (*dst)->size + src_length; + + char str[new_length + 1]; + memset(str, 0, new_length + 1); + + strncpy(str, (*dst)->buf, (*dst)->size); + strncat(str, src, src_length); + + dstr_update(dst, str); +} + +void dstr_append(dstr_t **dst, char c) { + if (!dst || !(*dst)) { + return; + } + + u64 new_length = (*dst)->size + 1; + + char str[new_length + 1]; + memset(str, 0, new_length + 1); + + strncpy(str, (*dst)->buf, (*dst)->size); + str[(*dst)->size] = c; + + dstr_update(dst, str); +} + +void dstr_resize(dstr_t **str) { + if (!str || !(*str)) { + return; + } + + u64 capacity = (*str)->size; + + dstr_t *tmp = (dstr_t *)realloc(*str, sizeof(dstr_t) + capacity + 1); + + if (!tmp) { + return; + } + + tmp->capacity = capacity; + + *str = tmp; +} + +void dstr_clear(dstr_t *str) { + if (!str || str->size == 0) { + return; + } + + memset(str->buf, 0, str->capacity); + str->size = 0; +} + +void dstr_print(const dstr_t *str) { + if (!str) { + return; + } + + printf("%s\n", str->buf); +} + +i64 dstr_find(const dstr_t *str, const char *substr) { + if (!str || !substr) { + return -1; + } + + u64 substr_length = strlen(substr); + + if (substr_length == 0 || substr_length > str->size) { + return -1; + } + + char buf[substr_length + 1]; + memset(buf, 0, substr_length + 1); + + for (u64 i = 0; i < str->size; ++i) { + if (i + substr_length >= str->size) { + break; + } + + for (u64 j = 0; j < substr_length; ++j) { + buf[j] = str->buf[i + j]; + } + + if (strcmp(buf, substr) == 0) { + return i; + } + } + + return -1; +} + +u64 dstr_length(const dstr_t *str) { + if (!str) { + return 0; + } + + return str->size; +} + +u64 dstr_capacity(const dstr_t *str) { + if (!str) { + return 0; + } + + return str->capacity; +} + +const char *dstr_to_cstr(const dstr_t *str) { + if (!str) { + return ""; + } + + return str->buf; +} diff --git a/example_build b/example_build new file mode 100755 index 0000000..86bdd0c --- /dev/null +++ b/example_build @@ -0,0 +1,12 @@ +#!/bin/bash + +INCLUDE=" \ + -Ialiases \ + -Icpath/include \ + -Idstr/include \ +" + +SRC=" \ + cpath/src/*.c \ + dstr/src/*.c \ +"