dlib

Unnamed repository; edit this file 'description' to name the repository.
git clone https://git.deepztream.com/dlib
Log | Files | Refs

commit 17ea5a41be7a78531e1919b84399d09fe36bdfcf
Author: William Djupström <william@deepztream.com>
Date:   Sun, 20 Sep 2026 11:07:25 +0200

Initial commit

Diffstat:
Adlib.h | 580+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 580 insertions(+), 0 deletions(-)

diff --git a/dlib.h b/dlib.h @@ -0,0 +1,580 @@ +#ifndef DLIB_H +#define DLIB_H 1 + +#include <assert.h> +#include <ctype.h> +#include <fcntl.h> +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#define todo_p(msg) \ + do { \ + fprintf(stderr, "%s:%i:1: Error: TODO: %s\n", __FILE__, __LINE__, (msg)); \ + abort(); \ + } while (0) + +#define todo(msg) \ + do { \ + fprintf(stderr, "%s:%i:1: Error: TODO: %s\n", __FILE__, __LINE__, (msg)); \ + return false; \ + } while (0) + +#define unimplemented() \ + do { \ + fprintf(stderr, "%s:%i:1: Error: not implemented %s\n", __FILE__, __LINE__, __func__); \ + abort(); \ + } while (0) + +#define unreachable(msg) \ + do { \ + fprintf(stderr, "%s:%i:1: Error: Unreachable: %s\n", __FILE__, __LINE__, (msg)); \ + abort(); \ + } while (0) + +#define pop_arg(argc, argv) ((argc)--, *(argv)++) + +#define da_append(da, new)\ + do {\ + if ((da)->capacity <= (da)->count) {\ + (da)->capacity = (da)->capacity ? (da)->capacity * 2 : 16;\ + (da)->items = realloc((da)->items, sizeof(*(da)->items) * (da)->capacity);\ + }\ + (da)->items[(da)->count++] = (new);\ + } while(0) + +#define da_prepend(da, new)\ + do {\ + if ((da)->capacity <= (da)->count) {\ + (da)->capacity = (da)->capacity ? (da)->capacity * 2 : 16;\ + (da)->items = realloc((da)->items, sizeof(*(da)->items) * (da)->capacity);\ + }\ + memmove((da)->items + 1, (da)->items, sizeof(*(da)->items) * ((da)->count++));\ + (da)->items[0] = (new);\ + } while(0) + +#define da_reserve(da, len)\ + do {\ + if ((da)->capacity >= (len)) break;\ + (da)->capacity = (len);\ + (da)->items = realloc((da)->items, sizeof(*(da)->items) * (len));\ + } while(0) + +#define da_expand(da, size)\ + do {\ + if ((da)->count >= (size)) break;\ + da_reserve(da, size);\ + (da)->count = (size);\ + } while(0) + +#define da_delete(da, index)\ + do {\ + assert(index >= 0 && index < (da)->count);\ + (da)->items[index] = (da)->items[--(da)->count];\ + } while (0) + +#define da_delete_ordered(da, index)\ + do {\ + assert(index < (da)->count);\ + memmove(&(da)->items[(index)], &(da)->items[(index) + 1], sizeof(*(da)->items) * ((da)->count-- - (index) - 1));\ + } while (0) + +typedef struct { + union { + char *items; + const char *data; + }; + union { + ssize_t count; + ssize_t length; + }; + ssize_t capacity; +} Sb; +#define String_builder Sb + +typedef struct { + union { + const char *items; + const char *data; + }; + union { + ssize_t count; + ssize_t length; + }; +} Sv; +#define String_view Sv + +typedef struct { + void *base; + void *head; + void *end; +} Temp_allocator; + +#define TA_DEFAULT_SIZE (1024*1024) + +void ta_init(Temp_allocator *ta, size_t size); +void *ta_alloc(Temp_allocator *ta, size_t size); + +#define sb_append_char da_append +int sb_printf(Sb *sb, const char *fmt, ...); +void sb_append_cstr(Sb *sb, const char *cstr); +void sb_append_sv(Sb *sb, Sv sv); +bool sb_append_and_unescape_sv(Sb *sb, Sv sv); + +bool sb_read(Sb *sb, int fd); +bool sb_read_file(Sb *sb, const char *file_name); +void sb_write(int fd, Sb sb); + +void sb_release(Sb *sb); + +#define sv_literal(str) ((Sv){.items = (str), .count = (sizeof (str) - 1)}) + +Sv sv_from_sb(Sb sb); +Sv sv_from_cstr(const char *cstr); +const char *sv_to_cstr(Sv sv); +long int sv_to_number(Sv sv, int base); +ssize_t sv_find_char(Sv sv, char c); + +Sv sv_chop(Sv sv, ssize_t count, Sv *rest); +Sv sv_chop_delim(Sv sv, char c, Sv *rest); + +Sv sv_getline(Sv *sv); + +Sv sv_trim_left(Sv sv); +Sv sv_trim_right(Sv sv); +Sv sv_trim(Sv sv); + +Sv sv_substring(Sv sv, ssize_t start, ssize_t req_count); + +int sv_compare(Sv sv1, Sv sv2); +bool sv_equal(Sv sv1, Sv sv2); +bool sv_starts_with_cstr(Sv sv, const char *cstr); +bool sv_starts_with(Sv sv, Sv prefix); + +void sv_write(int fd, Sv sv); + +/* Adding missing libc functions */ +int ctoi(int c); +#define isddigit isdigit +int isbdigit(int c); +int isodigit(int c); + +int is_digit_base(int c, int base); + +#ifdef DLIB_IMPLEMENTATION + +void +ta_init(Temp_allocator *ta, size_t size) +{ + ta->base = malloc(size); + ta->head = ta->base; + ta->end = ta->base + size; +} + +void * +ta_alloc(Temp_allocator *ta, size_t size) +{ + if (!ta->base) { + ta->base = malloc(TA_DEFAULT_SIZE); + ta->head = ta->base; + ta->end = ta->base + TA_DEFAULT_SIZE; + } + void *result = ta->head; + ta->head += (size + 0xF) & ~0xFul; + if (ta->head >= ta->end) { + fprintf(stderr, "Error: Temp allocator out of memory\n"); + exit(1); + } + return result; +} + +int +sb_printf(Sb *sb, const char *fmt, ...) { + va_list args, args_copy; + va_start(args, fmt); + va_copy(args_copy, args); + int len = vsnprintf(NULL, 0, fmt, args_copy) + 1; + ssize_t new_size = sb->count + len; + da_reserve(sb, new_size); + va_end(args_copy); + vsnprintf(sb->items + sb->count, len, fmt, args); + va_end(args); + sb->count = new_size - 1; + return len - 1; +} + +void +sb_append_cstr(Sb *sb, const char *cstr) +{ + ssize_t len = strlen(cstr); + da_reserve(sb, sb->count + len); + strcpy(sb->items + sb->count, cstr); + sb->count += len; +} + +void +sb_append_sv(Sb *sb, Sv sv) +{ + da_reserve(sb, sb->count + sv.count); + memcpy(sb->items + sb->count, sv.items, sv.count); + sb->count += sv.count; +} + +/* Returns `false` if it encounters an invalid escape character */ + +bool +sb_append_and_unescape_sv(Sb *sb, Sv sv) +{ + bool success = true; + ssize_t i; + char c; + for (i = 0; i < sv.count; i++) { + c = sv.data[i]; + if (c == '\\') { + if (++i >= sv.count) { + success = false; + } else { + c = sv.data[i]; + if (c == 'n') { + c = '\n'; + } else if (c == 't') { + c = '\t'; + } else if (c == 'r') { + c = '\r'; + } else if (c == '0') { + c = '\0'; + } else { + if (c >= 32 && c < 127) { + fprintf(stderr, "Info: escape character '%c' unsupported\n", c); + } else { + fprintf(stderr, "Info: escape character 0x%x02 unsupported\n", c); + } + success = false; + } + } + } + sb_append_char(sb, c); + } + return success; +} + +bool +sb_read(Sb *sb, int fd) +{ + ssize_t read_count; + ssize_t buf_size = 4096; + char *buf = malloc(buf_size); + do { + read_count = read(fd, buf, buf_size); + if (read_count < 0) { + if (errno == EINTR) { + continue; + } + perror("sb_read()"); + return false; + } + if (read_count == 0) { + break; + } + sb_append_sv(sb, ((Sv) {.items = buf, .length = read_count})); + if (read_count < buf_size) { + break; + } + } while (1); + free(buf); + return true; +} + +bool +sb_read_file(Sb *sb, const char *file_name) +{ + int fd = open(file_name, O_RDONLY); + if (fd < 0) { + perror("sb_read()"); + return false; + } + ssize_t read_count; + ssize_t buf_size = 4096; + char *buf = malloc(buf_size); + do { + read_count = read(fd, buf, buf_size); + if (read_count < 0) { + if (errno == EINTR) { + continue; + } + perror("sb_read_file()"); + return false; + } + if (read_count == 0) { + break; + } + sb_append_sv(sb, ((Sv) {.items = buf, .length = read_count})); + } while (1); + free(buf); + return true; +} + +void +sb_write(int fd, Sb sb) +{ + write(fd, sb.items, sb.length); +} + +void +sb_release(Sb *sb) +{ + if (sb->capacity) { + free(sb->items); + sb->items = NULL; + sb->count = 0; + sb->capacity = 0; + } +} + +/* String view functions */ + +void +sv_write(int fd, Sv sv) +{ + write(fd, sv.items, sv.count); +} + +Sv +sv_from_sb(Sb sb) +{ + return (Sv) {.items = sb.items, .count = sb.count}; +} + +Sv +sv_from_cstr(const char *cstr) +{ + return (Sv) {.items = cstr, .count = strlen(cstr)}; +} + +const char * +sv_to_cstr(Sv sv) +{ + char *cstr = malloc(sv.count + 1); + memcpy(cstr, sv.data, sv.count); + cstr[sv.count] = '\0'; + return cstr; +} + +long int +sv_to_number(Sv sv, int base) +{ + assert(sv.count > 0 && sv.items); + long int result = 0; + bool negative = false; + if (*sv.items == '-') { + negative = true; + sv.items++; + sv.count--; + } + if (sv_starts_with_cstr(sv, "0b") || + sv_starts_with_cstr(sv, "0o") || + sv_starts_with_cstr(sv, "0d") || + sv_starts_with_cstr(sv, "0x")) { + sv.items += 2; + sv.count -= 2; + } + do { + if (!is_digit_base(*sv.items, base)) { + fprintf(stderr, "Error: sv_to_number: Not a valid base%i digit '%c'\n", base, *sv.items); + } + result *= base; + result += ctoi(*sv.items); + sv.items++; + sv.count--; + } while (sv.count); + return negative ? -result : result; +} + +ssize_t +sv_find_char(Sv sv, char c) +{ + ssize_t pos = 0; + while (sv.count > pos && sv.items[pos] != c) + pos++; + for (pos = 0; pos < sv.count && sv.items[pos] != c; pos++); + return pos < sv.count ? pos : -1; +} + +Sv +sv_chop_delim(Sv sv, char c, Sv *rest) +{ + ssize_t pos = sv_find_char(sv, c); + Sv res = sv; + if (pos > 0) { + res.count = pos; + + rest->count -= pos + 1; + rest->items += pos + 1; + } + return res; +} + +Sv +sv_chop(Sv sv, ssize_t count, Sv *rest) +{ + Sv left = {0}; + ssize_t lcount, rcount; + if (count > sv.count) { + lcount = sv.count; + rcount = 0; + } else if (-count > sv.count) { + lcount = 0; + rcount = sv.count; + } else if (count < 0) { + lcount = sv.count + count; + rcount = -count; + } else { + lcount = count; + rcount = sv.count - count; + } + left.items = sv.items; + left.count = lcount; + if (rest) { + rest->items = sv.items + lcount; + rest->count = rcount; + } + return left; +} + +Sv +sv_trim_left(Sv sv) +{ + while (sv.count && isspace(sv.items[0])) { + sv.count--; + sv.items++; + } + return sv; +} + +Sv +sv_trim_right(Sv sv) +{ + while (sv.count && isspace(sv.items[sv.count - 1])) { + sv.count--; + } + return sv; +} + +Sv +sv_trim(Sv sv) +{ + return sv_trim_right(sv_trim_left(sv)); +} + +Sv +sv_substring(Sv sv, ssize_t start, ssize_t req_count) +{ + Sv ss = {0}; + if (start >= sv.count) return ss; + ss.count = (req_count < sv.count - start) ? req_count : sv.count - start; + ss.items = sv.items + start; + return ss; +} + +int +sv_compare(Sv sv1, Sv sv2) +{ + if (sv1.items == sv2.items && sv1.count == sv2.count) return 0; + signed char diff; + ssize_t pos; + for (pos = 0; pos < sv1.count; pos++) { + if (pos == sv2.count) return 1; + if ((diff = sv1.items[pos] - sv2.items[pos])) return diff; + } + return pos < sv2.count ? -1 : 0; +} + +bool +sv_equal(Sv sv1, Sv sv2) +{ + if (sv1.count != sv2.count) return false; + if (sv1.items == sv2.items) return true; + ssize_t pos; + for (pos = 0; pos < sv1.count && sv1.items[pos] == sv2.items[pos]; pos++); + return pos == sv1.count; +} + +bool +sv_starts_with_cstr(Sv sv, const char *cstr) +{ + size_t cstr_len = strlen(cstr); + assert(cstr_len <= SSIZE_MAX); + if (sv.count < (ssize_t) cstr_len) return false; + ssize_t pos; + for (pos = 0; pos < (ssize_t) cstr_len && sv.items[pos] == cstr[pos]; pos++); + return pos == (ssize_t) cstr_len; +} + +bool +sv_starts_with(Sv sv, Sv prefix) +{ + if (sv.count < prefix.count) return false; + ssize_t pos; + for (pos = 0; pos < prefix.count && sv.items[pos] == prefix.items[pos]; pos++); + return pos == prefix.count; +} + +Sv +sv_getline(Sv *sv) +{ + Sv line = sv_chop_delim(*sv, '\n', sv); + if (line.count && line.items[line.count - 1] == '\r') { + line.count--; + } + return line; +} + +int +isbdigit(int c) +{ + if (c > 127) { + todo_p("unicode support"); + } + return c == '0' || c == '1'; +} + +int +isodigit(int c) +{ + if (c > 127) { + todo_p("unicode support"); + } + return c == '0' || c == '1' || c == '2' || c == '3' || + c == '4' || c == '5' || c == '6' || c == '7'; +} + +int +is_digit_base(int c, int base) +{ + if (base == 2) return isbdigit(c); + if (base == 8) return isodigit(c); + if (base == 10) return isddigit(c); + if (base == 16) return isxdigit(c); + fprintf(stderr, "Error: is_digit_base: invalid base %i\n", base); + return 0; +} + +int +ctoi(int c) +{ + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'Z') return c - 'A' + 10; + if (c >= 'a' && c <= 'z') return c - 'a' + 10; + fprintf(stderr, "Error: ctoi: invalid digit '%c'\n", c); + return 0; +} + +#endif // DLIB_IMPLEMENTATION + +#endif // DLIB_H