From 5cf0292ebe3df06e0739c7006eada868ccaeda6d Mon Sep 17 00:00:00 2001 From: Quinn Date: Mon, 15 Dec 2025 09:54:57 +0100 Subject: [PATCH] delete configuration logic The configuration logic was violating alignment rules, and will be rewritten. --- src/util/conf.c | 192 ------------------------------------------------ src/util/conf.h | 71 ------------------ 2 files changed, 263 deletions(-) delete mode 100644 src/util/conf.c delete mode 100644 src/util/conf.h diff --git a/src/util/conf.c b/src/util/conf.c deleted file mode 100644 index 68bd5ae..0000000 --- a/src/util/conf.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (c) 2025 Quinn. - * This is a file from the project MCA-Selector-Lite and is - * licensed under the MIT Licence. See the project's LICENSE file for details. */ -#include "conf.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "../types.h" -#include "../util/error.h" -#include "atrb.h" - -int conf_procbuf(const char *restrict buf, char *restrict kout, char *restrict vout, usize len) -{ - bool feq = false; // whether we've found the equal sign - - // data traversal - char *pos = kout; // will point to the next point in the buffer, where we'll write data - - // acquire data - for (usize i = 0; i < len; i++) { - // handling of termination tokens - bool brk = false; // whether we broke out of the loop, and are done reading - switch (buf[i]) { - case '\n': - case '\r': - case '\0': - case '#': - brk = true; - break; - } - if (brk) - break; - - // everything after `=` is interpreted as a value - if (!feq && buf[i] == '=') { - feq = true; - *pos = '\0'; // terminate string - pos = vout; // move pointer to start of value data - continue; - } - *pos = buf[i]; // copy over the buffer's data - pos++; // increment the position pointer - } - // null-terminate what we've got now (yes, there should be enough space for this since \0 isn't stored) - // this also ensures the value is valid, even if none is given - *pos = '\0'; - - // no data if we didn't move from the key position - // syntax error if we couldn't find the equal sign - return (pos == kout) ? CONF_ENODAT : (!feq ? CONF_ESYNTAX : 0); -} - -struct conf_entry const *conf_matchopt(struct conf_entry const *opts, usize optc, const char *restrict key) -{ - // find a match for the current key - usize i = 0; - for (; i < optc; i++) { - if (strcmp(opts[i].key, key) == 0) - return opts + i; - } - return NULL; -} - -int conf_procval(struct conf_entry const *opt, const char *restrict val) -{ - // parse the data - errno = 0; - char *end; - u8 dat[sizeof(u64)]; - - switch (opt->type) { - // signed integer data parsing - case CONF_I8: - case CONF_I16: - case CONF_I32: - case CONF_I64: - *(i64 *)dat = strtoll(val, &end, 10); // for signed integer types - break; - // unsigned integer data parsing - case CONF_U8: - case CONF_U16: - case CONF_U32: - case CONF_U64: - *(u64 *)dat = strtoull(val, &end, 10); // for unsigned integer types - break; - - // floating-point data parsing - case CONF_F32: *(f32 *)dat = strtof(val, &end); break; - case CONF_F64: *(f64 *)dat = strtod(val, &end); break; - - // string data parsing - case CONF_STR: - if (*(char **)opt->out) { - free(*(char **)opt->out); // if the same key is given multiple times, free the memory so we don't leak. - warn("encountered a dynamic string multiple times, this is sub-optimal."); - } - *(char **)opt->out = strdup(val); - return 0; - case CONF_FSTR: { - struct conf_fstr *s = opt->out; - strncpy(s->out, val, s->len); - s->out[s->len - 1] = '\0'; // ensure the string is null-terminated - return 0; - } - default: return CONF_EINVALIDTYPE; // return error code indicating function not implemented - } - - if (errno || end == val || *end != '\0') { - error("failed to parse '%s' as a numeric value", val); - return CONF_EPARSE; - } - - switch (opt->type) { - case CONF_U8: *(u8 *)opt->out = *(u64 *)dat >= UINT8_MAX ? UINT8_MAX : *(u64 *)dat; return 0; - case CONF_U16: *(u16 *)opt->out = *(u64 *)dat >= UINT16_MAX ? UINT16_MAX : *(u64 *)dat; return 0; - case CONF_U32: *(u32 *)opt->out = *(u64 *)dat >= UINT32_MAX ? UINT32_MAX : *(u64 *)dat; return 0; - case CONF_U64: *(u64 *)opt->out = *(u64 *)dat >= UINT64_MAX ? UINT64_MAX : *(u64 *)dat; return 0; - case CONF_I8: *(i8 *)opt->out = *(i64 *)dat >= INT8_MAX ? INT8_MAX : (*(i64 *)dat <= INT8_MIN ? INT8_MIN : *(i64 *)dat); return 0; - case CONF_I16: *(i16 *)opt->out = *(i64 *)dat >= INT16_MAX ? INT16_MAX : (*(i64 *)dat <= INT16_MIN ? INT16_MIN : *(i64 *)dat); return 0; - case CONF_I32: *(i32 *)opt->out = *(i64 *)dat >= INT32_MAX ? INT32_MAX : (*(i64 *)dat <= INT32_MIN ? INT32_MIN : *(i64 *)dat); return 0; - case CONF_I64: *(i64 *)opt->out = *(i64 *)dat >= INT64_MAX ? INT64_MAX : (*(i64 *)dat <= INT64_MIN ? INT64_MIN : *(i64 *)dat); return 0; - case CONF_F32: *(f32 *)opt->out = *(f32 *)dat; return 0; - case CONF_F64: *(f64 *)opt->out = *(f64 *)dat; return 0; - default: fatal("invalid switch state, all cases should be handled already"); // abort; this shouldn't be possible, so I blame the programmer - } -} - -/* utility function for conf_getpat to concatenate 3 strings, where we already know the size */ -NONNULL((1, 3)) -static char *conf_getpat_concat(const char *restrict s1, const char *restrict s2, const char *restrict s3, usize s1len, usize s2len, usize s3len) -{ - assert(s2 || (!s2 && !s2len)); // ensuring the programmer passes both s2 and s2len as 0, if they intend to - char *buf, *ptr; - - // allocate enough data for all three to the buffer - ptr = malloc(s1len + s2len + s3len + 1); - if (!ptr) - return NULL; - buf = ptr; // store the head pointer into buf - - // copy data to the buffer - ptr = memcpy(ptr, s1, s1len) + s1len; // copy s1 data to the buffer - if (s2len) - ptr = memcpy(ptr, s2, s2len) + s2len; // copy s2 data to the buffer (excluding null-terminator) - (void)strcpy(ptr, s3); // copy s3 as a string, thus including null-terminator - - // return the buffer - return buf; -} - -/* appends str to the config directory string we acquire from environment variables. */ -char *conf_getpat(const char *restrict str) -{ - char *buf = NULL; - usize len; - usize str_len = strlen(str); -#if defined(__linux__) - buf = getenv("XDG_CONFIG_HOME"); - if (!buf) { - buf = getenv("HOME"); - if (!buf) - return NULL; - len = strlen(buf); - return conf_getpat_concat(buf, "/.config", str, len, 8, str_len); - } - return conf_getpat_concat(buf, NULL, str, strlen(buf), 0, str_len); -#elif defined(__APPLE__) - buf = getenv("HOME"); - if (!buf) - return NULL; - len = strlen(buf); - return conf_getpat_concat(buf, "/Library/Application Support", str, len, 28, str_len); -#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) - buf = getenv("APPDATA"); - if (!buf) { - buf = getenv("USERPROFILE"); - if (!buf) - return NULL; - len = strlen(buf); - return conf_getpat_concat(buf, "\\AppData\\Roaming", str, len, 16, str_len); - } - return conf_getpat_concat(buf, NULL, str, strlen(buf), 0, str_len); -#else -#error platform unsupported! -#endif -} diff --git a/src/util/conf.h b/src/util/conf.h deleted file mode 100644 index 0df2f1a..0000000 --- a/src/util/conf.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2025 Quinn. - * This is a file from the project MCA-Selector-Lite and is - * licensed under the MIT Licence. See the project's LICENSE file for details. */ -#pragma once - -#include -#include - -#include "../types.h" -#include "atrb.h" - -/* error codes */ -enum conf_err { - CONF_ENODAT = -1, // no data was found - CONF_ESYNTAX = 1, // couldn't extract clear key/val data - CONF_ENOMATCH = 2, // couldn't find a match for the inputted key - CONF_EINVALIDTYPE = 3, // the type inputted in conf_entry was invalid - CONF_EPARSE = 4, // something went wrong whilst parsing -}; - -/* defines the primitive types available in the config file */ -enum conf_primitive { - CONF_STR = 0, // expects: `char**`, will output malloc'd data !!must be freed!! - CONF_I8 = 1, // expects: `int8_t*`, will point to a location in memory where an i8 is stored. - CONF_I16 = 2, // expects: `int16_t*`, will point to a location in memory where an i16 is stored. - CONF_I32 = 4, // expects: `int32_t*`, will point to a location in memory where an i32 is stored. - CONF_I64 = 8, // expects: `int64_t*`, will point to a location in memory where an i64 is stored. - CONF_U8 = CONF_I8 | 0x80, // expects: `uint8_t*`, will point to a location in memory where an u8 is stored. - CONF_U16 = CONF_I16 | 0x80, // expects: `uint16_t*`, will point to a location in memory where an u16 is stored. - CONF_U32 = CONF_I32 | 0x80, // expects: `uint32_t*`, will point to a location in memory where an u32 is stored. - CONF_U64 = CONF_I64 | 0x80, // expects: `uint64_t*`, will point to a location in memory where an u64 is stored. - CONF_F32 = CONF_I32 | 0x40, // expects: `float*`, will point to a location in memory where an f32 is stored. - CONF_F64 = CONF_I64 | 0x40, // expects: `double*`, will point to a location in memory where an f64 is stored. - CONF_FSTR = 0x40, // expects: `struct conf_fstr*`, which contains the data for a fixed-width string -}; - -/* for outputting a fixed string as this config field */ -struct conf_fstr { - usize len; // length in BYTES of the output data - char *out; // where we will output the data -}; - -/* defines the structure of a config file entry */ -struct conf_entry { - const char *key; // the key of this entry - void *out; // the pointer to which the data is written value is read if the given option is incorrect or missing - u8 type; // the primitive type which we are querying for -}; - -/* processes an incoming buffer. - * `buf`, `kout` and `vout` mustn't overlap, and must be (at least) `len` bytes long! - * `kout` and `vout` will contain a null-terminated string if the function returned successfully. - * returns `0` on success, `<0` when no data was found. `>0` when data was invalid but something went wrong. - * see `CONF_E*` or `enum conf_err` */ -int conf_procbuf(const char *restrict buf, char *restrict kout, char *restrict vout, usize len); - -/* matches the key with one of the options and returns the pointer. Returns NULL if none could be found. */ -struct conf_entry const *conf_matchopt(struct conf_entry const *opts, usize optc, const char *restrict key); - -/* processes the value belonging to the key and outputs the result to opts. - * - `val` points to a null-terminated string which contains the key and value. - * returns `0` upon success, non-zero upon failure. For information about specific error codes, see `enum conf_err` */ -int conf_procval(struct conf_entry const *opts, const char *restrict val); - -/* acquires the config file path, appending str to the end (you need to handle path separators yourself) - * expecting str to be null-terminated - * - linux: reads $XDG_CONFIG_HOME, if empty $HOME/.config is used, if $HOME is empty NULL is returned. - * - windows: reads %APPDATA%, if empty %USERPROFILE%\AppData\Roaming is used, if both are empty NULL is returned. - * - osx: reads $HOME, uses $HOME/Library/Application Support, if $HOME is empty NULL is returned. - * !! A malloc'd null-terminated string is returned !! */ -char *conf_getpat(const char *) MALLOC NONNULL((1));