summaryrefslogtreecommitdiff
path: root/src/kontoml.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/kontoml.h')
-rw-r--r--src/kontoml.h649
1 files changed, 0 insertions, 649 deletions
diff --git a/src/kontoml.h b/src/kontoml.h
deleted file mode 100644
index 88a7e68..0000000
--- a/src/kontoml.h
+++ /dev/null
@@ -1,649 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * kontoml.h
- *
- * Copyright (c) 2026 KonAki
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef KONTOML_H
-#define KONTOML_H
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-typedef enum kon_tomlType {
- konTomlString,
- konTomlInt,
- konTomlFloat,
- konTomlBool,
- konTomlArray
-} kon_tomlType_t;
-
-typedef struct kon_tomlEntry {
- char *section;
- char *key;
- kon_tomlType_t type;
- char *str_value;
- long long int_value;
- double float_value;
- bool bool_value;
-
- kon_tomlType_t array_type;
- int array_count;
- char **array_str;
- long long *array_int;
- double *array_float;
- bool *array_bool;
-} kon_tomlEntry_t;
-
-typedef struct kon_toml {
- kon_tomlEntry_t *entries;
- int count;
- int capacity;
-} kon_toml_t;
-
-kon_toml_t *kon_parseToml(const char *text);
-kon_toml_t *kon_parseTomlFile(const char *path);
-void kon_freeToml(kon_toml_t *toml);
-
-const char *kon_tomlGetString(kon_toml_t *toml, const char *section, const char *key, const char *def);
-long long kon_tomlGetInt(kon_toml_t *toml, const char *section, const char *key, long long def);
-double kon_tomlGetFloat(kon_toml_t *toml, const char *section, const char *key, double def);
-bool kon_tomlGetBool(kon_toml_t *toml, const char *section, const char *key, bool def);
-
-const char *const *kon_tomlGetStringArray(kon_toml_t *toml, const char *section, const char *key, int *out_count);
-const long long *kon_tomlGetIntArray(kon_toml_t *toml, const char *section, const char *key, int *out_count);
-const double *kon_tomlGetFloatArray(kon_toml_t *toml, const char *section, const char *key, int *out_count);
-const bool *kon_tomlGetBoolArray(kon_toml_t *toml, const char *section, const char *key, int *out_count);
-
-/*** implementation ***/
-
-#ifdef KONTOML_IMPLEMENTATION
-
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-
-static char *kon__tomlStrdup(const char *s) {
- size_t len = strlen(s) + 1;
- char *out = malloc(len);
- if (!out) return NULL;
- memcpy(out, s, len);
- return out;
-}
-
-static char *kon__tomlStrndup(const char *s, size_t n) {
- char *out = malloc(n + 1);
- if (!out) return NULL;
- memcpy(out, s, n);
- out[n] = '\0';
- return out;
-}
-
-static char *kon__tomlTrim(char *s) {
- char *end;
-
- while (*s == ' ' || *s == '\t') s++;
- if (*s == '\0') return s;
-
- end = s + strlen(s) - 1;
- while (end > s && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) {
- *end = '\0';
- end--;
- }
-
- return s;
-}
-
-static kon_tomlEntry_t *kon__tomlPushEntry(kon_toml_t *toml) {
- if (toml->count == toml->capacity) {
- int newCap = toml->capacity ? toml->capacity * 2 : 16;
- kon_tomlEntry_t *tmp = realloc(toml->entries, (size_t)newCap * sizeof(kon_tomlEntry_t));
- if (!tmp) return NULL;
-
- toml->entries = tmp;
- toml->capacity = newCap;
- }
-
- kon_tomlEntry_t *entry = &toml->entries[toml->count];
- memset(entry, 0, sizeof(kon_tomlEntry_t));
- toml->count++;
-
- return entry;
-}
-
-static int kon__tomlParseString(const char **p, char **out) {
- const char *s = *p;
- char quote = *s;
- int literal = (quote == '\'');
- s++;
-
- char *buf = malloc(strlen(s) + 1);
- if (!buf) return -1;
-
- size_t bi = 0;
-
- while (*s && *s != quote) {
- if (!literal && *s == '\\') {
- s++;
- switch (*s) {
- case 'n':
- buf[bi++] = '\n';
- break;
- case 't':
- buf[bi++] = '\t';
- break;
- case 'r':
- buf[bi++] = '\r';
- break;
- case '"':
- buf[bi++] = '"';
- break;
- case '\\':
- buf[bi++] = '\\';
- break;
- case '\0':
- free(buf);
- return -1;
- default:
- buf[bi++] = *s;
- break;
- }
- s++;
- } else {
- buf[bi++] = *s;
- s++;
- }
- }
-
- if (*s != quote) {
- free(buf);
- return -1;
- }
- s++;
-
- buf[bi] = '\0';
- *out = buf;
- *p = s;
-
- return 0;
-}
-
-static char *kon__tomlStripUnderscores(const char *s) {
- char *out = malloc(strlen(s) + 1);
- if (!out) return NULL;
-
- size_t oi = 0;
- for (size_t i = 0; s[i]; i++) {
- if (s[i] != '_') out[oi++] = s[i];
- }
- out[oi] = '\0';
-
- return out;
-}
-
-static char **kon__tomlSplitArrayElements(const char *content, int *outCount) {
- int cap = 8;
- int count = 0;
- char **elems = malloc((size_t)cap * sizeof(char *));
- if (!elems) return NULL;
-
- const char *start = content;
- const char *p = content;
- char inQuote = 0;
-
- while (*p) {
- if (inQuote) {
- if (inQuote == '"' && *p == '\\' && *(p + 1) != '\0') {
- p += 2;
- continue;
- }
- if (*p == inQuote) inQuote = 0;
- p++;
- continue;
- }
-
- if (*p == '"' || *p == '\'') {
- inQuote = *p;
- p++;
- continue;
- }
-
- if (*p == ',') {
- if (count == cap) {
- cap *= 2;
- char **tmp = realloc(elems, (size_t)cap * sizeof(char *));
- if (!tmp) { free(elems); return NULL; }
- elems = tmp;
- }
- elems[count++] = kon__tomlStrndup(start, (size_t)(p - start));
- p++;
- start = p;
- continue;
- }
-
- p++;
- }
-
- {
- char *raw = kon__tomlStrndup(start, (size_t)(p - start));
- char *checkTrim = raw ? kon__tomlTrim(raw) : NULL;
-
- if (raw && *checkTrim != '\0') {
- if (count == cap) {
- cap += 1;
- char **tmp = realloc(elems, (size_t)cap * sizeof(char *));
- if (!tmp) { free(raw); free(elems); return NULL; }
- elems = tmp;
- }
- elems[count++] = raw;
- } else {
- free(raw);
- }
- }
-
- *outCount = count;
- return elems;
-}
-
-static int kon__tomlParseArrayValue(kon_tomlEntry_t *entry, const char *valueStr) {
- const char *open = strchr(valueStr, '[');
- const char *close = strchr(valueStr, ']');
- if (!open || !close || close <= open) return -1;
-
- char *content = kon__tomlStrndup(open + 1, (size_t)(close - open - 1));
- if (!content) return -1;
-
- int rawCount = 0;
- char **rawElems = kon__tomlSplitArrayElements(content, &rawCount);
- free(content);
- if (!rawElems) return -1;
-
- if (rawCount == 0) {
- free(rawElems);
- entry->type = konTomlArray;
- entry->array_type = konTomlInt;
- entry->array_count = 0;
- return 0;
- }
-
- kon_tomlType_t elemType = konTomlInt;
- char **strArr = NULL;
- long long *intArr = NULL;
- double *floatArr = NULL;
- bool *boolArr = NULL;
- int ok = 1;
-
- for (int i = 0; i < rawCount && ok; i++) {
- char *trimmed = kon__tomlTrim(rawElems[i]);
-
- kon_tomlType_t thisType;
- char *decodedStr = NULL;
- long long thisInt = 0;
- double thisFloat = 0.0;
- bool thisBool = false;
-
- if (*trimmed == '"' || *trimmed == '\'') {
- const char *vp = trimmed;
- thisType = konTomlString;
- if (kon__tomlParseString(&vp, &decodedStr) != 0) { ok = 0; break; }
- } else if (strcmp(trimmed, "true") == 0) {
- thisType = konTomlBool;
- thisBool = true;
- } else if (strcmp(trimmed, "false") == 0) {
- thisType = konTomlBool;
- thisBool = false;
- } else {
- char *clean = kon__tomlStripUnderscores(trimmed);
- if (!clean) { ok = 0; break; }
-
- int isFloat = (strchr(clean, '.') || strchr(clean, 'e') || strchr(clean, 'E'));
- if (isFloat) {
- thisType = konTomlFloat;
- thisFloat = strtod(clean, NULL);
- } else {
- thisType = konTomlInt;
- thisInt = strtoll(clean, NULL, 10);
- }
- free(clean);
- }
-
- if (i == 0) {
- elemType = thisType;
- switch (elemType) {
- case konTomlString:
- strArr = malloc((size_t)rawCount * sizeof(char *));
- break;
- case konTomlInt:
- intArr = malloc((size_t)rawCount * sizeof(long long));
- break;
- case konTomlFloat:
- floatArr = malloc((size_t)rawCount * sizeof(double));
- break;
- case konTomlBool:
- boolArr = malloc((size_t)rawCount * sizeof(bool));
- break;
- default:
- break;
- }
- } else if (thisType != elemType) {
- free(decodedStr);
- ok = 0;
- break;
- }
-
- switch (elemType) {
- case konTomlString:
- strArr[i] = decodedStr;
- break;
- case konTomlInt:
- intArr[i] = thisInt;
- break;
- case konTomlFloat:
- floatArr[i] = thisFloat;
- break;
- case konTomlBool:
- boolArr[i] = thisBool;
- break;
- default:
- break;
- }
- }
-
- for (int i = 0; i < rawCount; i++) free(rawElems[i]);
- free(rawElems);
-
- if (!ok) {
- if (strArr) {
- for (int i = 0; i < rawCount; i++)
- free(strArr[i]);
-
- free(strArr);
- }
- free(intArr);
- free(floatArr);
- free(boolArr);
- return -1;
- }
-
- entry->type = konTomlArray;
- entry->array_type = elemType;
- entry->array_count = rawCount;
- entry->array_str = strArr;
- entry->array_int = intArr;
- entry->array_float = floatArr;
- entry->array_bool = boolArr;
-
- return 0;
-}
-
-static int kon__tomlParseLine(kon_toml_t *toml, char *line, char **currentSection) {
- char *trimmed = kon__tomlTrim(line);
-
- if (*trimmed == '\0' || *trimmed == '#') return 0;
-
- if (*trimmed == '[') {
- char *close = strchr(trimmed, ']');
- if (!close) return -1;
-
- free(*currentSection);
- *currentSection = kon__tomlStrndup(trimmed + 1, (size_t)(close - trimmed - 1));
-
- return 0;
- }
-
- char *eq = strchr(trimmed, '=');
- if (!eq) return -1;
-
- *eq = '\0';
- char *key = kon__tomlTrim(trimmed);
- char *valueStr = kon__tomlTrim(eq + 1);
-
- if (*valueStr != '"' && *valueStr != '\'') {
- char *hash = strchr(valueStr, '#');
- if (hash) {
- *hash = '\0';
- valueStr = kon__tomlTrim(valueStr);
- }
- }
-
- if (*key == '\0' || *valueStr == '\0') return -1;
-
- kon_tomlEntry_t *entry = kon__tomlPushEntry(toml);
- if (!entry) return -1;
-
- entry->section = *currentSection ? kon__tomlStrdup(*currentSection) : kon__tomlStrdup("");
- entry->key = kon__tomlStrdup(key);
-
- if (*valueStr == '[') {
- if (kon__tomlParseArrayValue(entry, valueStr) != 0) return -1;
- } else if (*valueStr == '"' || *valueStr == '\'') {
- const char *vp = valueStr;
- char *decoded = NULL;
-
- if (kon__tomlParseString(&vp, &decoded) != 0) return -1;
-
- entry->type = konTomlString;
- entry->str_value = decoded;
- } else if (strcmp(valueStr, "true") == 0) {
- entry->type = konTomlBool;
- entry->bool_value = true;
- } else if (strcmp(valueStr, "false") == 0) {
- entry->type = konTomlBool;
- entry->bool_value = false;
- } else {
- char *clean = kon__tomlStripUnderscores(valueStr);
- if (!clean) return -1;
-
- int isFloat = (strchr(clean, '.') || strchr(clean, 'e') || strchr(clean, 'E'));
-
- if (isFloat) {
- entry->type = konTomlFloat;
- entry->float_value = strtod(clean, NULL);
- } else {
- entry->type = konTomlInt;
- entry->int_value = strtoll(clean, NULL, 10);
- }
-
- free(clean);
- }
-
- return 0;
-}
-
-kon_toml_t *kon_parseToml(const char *text) {
- if (!text) return NULL;
-
- kon_toml_t *toml = malloc(sizeof(kon_toml_t));
- if (!toml) return NULL;
-
- toml->entries = NULL;
- toml->count = 0;
- toml->capacity = 0;
-
- char *currentSection = NULL;
-
- const char *lineStart = text;
- while (*lineStart) {
- const char *lineEnd = strchr(lineStart, '\n');
- size_t len = lineEnd ? (size_t)(lineEnd - lineStart) : strlen(lineStart);
-
- char *line = kon__tomlStrndup(lineStart, len);
- if (line) {
- kon__tomlParseLine(toml, line, &currentSection);
- free(line);
- }
-
- if (!lineEnd) break;
- lineStart = lineEnd + 1;
- }
-
- free(currentSection);
-
- return toml;
-}
-
-kon_toml_t *kon_parseTomlFile(const char *path) {
- FILE *f = fopen(path, "rb");
- if (!f) return NULL;
-
- fseek(f, 0, SEEK_END);
- long size = ftell(f);
- fseek(f, 0, SEEK_SET);
-
- if (size < 0) {
- fclose(f);
- return NULL;
- }
-
- char *buf = malloc((size_t)size + 1);
- if (!buf) {
- fclose(f);
- return NULL;
- }
-
- size_t read = fread(buf, 1, (size_t)size, f);
- buf[read] = '\0';
- fclose(f);
-
- kon_toml_t *toml = kon_parseToml(buf);
- free(buf);
-
- return toml;
-}
-
-void kon_freeToml(kon_toml_t *toml) {
- if (!toml) return;
-
- for (int i = 0; i < toml->count; i++) {
- kon_tomlEntry_t *e = &toml->entries[i];
-
- free(e->section);
- free(e->key);
-
- if (e->type == konTomlString) {
- free(e->str_value);
- } else if (e->type == konTomlArray) {
- if (e->array_str) {
- for (int j = 0; j < e->array_count; j++) free(e->array_str[j]);
- free(e->array_str);
- }
- free(e->array_int);
- free(e->array_float);
- free(e->array_bool);
- }
- }
-
- free(toml->entries);
- free(toml);
-}
-
-static kon_tomlEntry_t *kon__tomlFind(kon_toml_t *toml, const char *section, const char *key) {
- if (!toml) return NULL;
-
- const char *sec = section ? section : "";
-
- for (int i = 0; i < toml->count; i++) {
- kon_tomlEntry_t *e = &toml->entries[i];
- if (strcmp(e->section, sec) == 0 && strcmp(e->key, key) == 0) {
- return e;
- }
- }
-
- return NULL;
-}
-
-const char *kon_tomlGetString(kon_toml_t *toml, const char *section, const char *key, const char *def) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e || e->type != konTomlString) return def;
- return e->str_value;
-}
-
-long long kon_tomlGetInt(kon_toml_t *toml, const char *section, const char *key, long long def) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e) return def;
-
- if (e->type == konTomlInt) return e->int_value;
- if (e->type == konTomlFloat) return (long long)e->float_value;
-
- return def;
-}
-
-double kon_tomlGetFloat(kon_toml_t *toml, const char *section, const char *key, double def) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e) return def;
-
- if (e->type == konTomlFloat) return e->float_value;
- if (e->type == konTomlInt) return (double)e->int_value;
-
- return def;
-}
-
-bool kon_tomlGetBool(kon_toml_t *toml, const char *section, const char *key, bool def) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e || e->type != konTomlBool) return def;
- return e->bool_value;
-}
-
-const char *const *kon_tomlGetStringArray(kon_toml_t *toml, const char *section, const char *key, int *out_count) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e || e->type != konTomlArray || e->array_type != konTomlString) {
- if (out_count) *out_count = 0;
- return NULL;
- }
- if (out_count) *out_count = e->array_count;
- return (const char *const *)e->array_str;
-}
-
-const long long *kon_tomlGetIntArray(kon_toml_t *toml, const char *section, const char *key, int *out_count) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e || e->type != konTomlArray || e->array_type != konTomlInt) {
- if (out_count) *out_count = 0;
- return NULL;
- }
- if (out_count) *out_count = e->array_count;
- return e->array_int;
-}
-
-const double *kon_tomlGetFloatArray(kon_toml_t *toml, const char *section, const char *key, int *out_count) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e || e->type != konTomlArray || e->array_type != konTomlFloat) {
- if (out_count) *out_count = 0;
- return NULL;
- }
- if (out_count) *out_count = e->array_count;
- return e->array_float;
-}
-
-const bool *kon_tomlGetBoolArray(kon_toml_t *toml, const char *section, const char *key, int *out_count) {
- kon_tomlEntry_t *e = kon__tomlFind(toml, section, key);
- if (!e || e->type != konTomlArray || e->array_type != konTomlBool) {
- if (out_count) *out_count = 0;
- return NULL;
- }
- if (out_count) *out_count = e->array_count;
- return e->array_bool;
-}
-
-#endif /* END of KONTOML_IMPLEMENTATION */
-
-#endif