Compare commits

..

6 Commits

Author SHA1 Message Date
9e8f5958c7 write conf scripts 2025-12-15 18:52:47 +01:00
bc0743a72b add __assume__ macro definition in atrb.h 2025-12-15 12:32:34 +01:00
81b21ff7ce move windowing code into io/win 2025-12-15 10:02:54 +01:00
7df20e9aa1 remove mapcolour files, since we don't use them 2025-12-15 09:56:45 +01:00
5cf0292ebe delete configuration logic
The configuration logic was violating alignment rules, and will be
rewritten.
2025-12-15 09:54:57 +01:00
64b06d88c8 fix: error headers were needlessly backing out of util/ 2025-12-15 09:54:17 +01:00
17 changed files with 58 additions and 419 deletions

35
src/io/conf.c Normal file
View File

@@ -0,0 +1,35 @@
#include "conf.h"
#include <string.h>
#include "../types.h"
#include "../util/atrb.h"
/* Matches s1 with s2, returns a pointer to s1 where the match stopped. */
static const char *strmat(const char *s1, const char *s2) PURE NONNULL((1, 2));
static const char *strmat(const char *s1, const char *s2)
{
while ((*s1 == *s2) & !!*s1)
s1++, s2++;
return s1;
}
int conf_getkeyval(const char *restrict buf, const char *const restrict *restrict keys, int klen, const char *restrict *restrict out)
{
const char *tmp = NULL;
ASSUME((klen > 0));
int i = 0;
for (; i < klen && !tmp; i++) {
tmp = strmat(buf, keys[i]);
tmp = keys[i][buf - tmp] ? tmp : 0;
}
if (!tmp || *tmp != '=')
return -1;
*out = tmp + 1;
return i;
}
int conf_val(int);

12
src/io/conf.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include "../types.h"
#include "../util/atrb.h"
/* Gets the key and value, if present. Writes the pointer for the value to `out`.
* Returns the key index, or <0 upon failure. */
int conf_getkeyval(const char *restrict buf, const char *const restrict *restrict keys, int klen,
const char *restrict *restrict out) NONNULL((1, 2, 4));
/* Processes the value of `type` in `val`. Outputs to `out`.
* Returns non-zero on failure. */
int conf_procval(u8 type, const char *restrict val, void *restrict out) NONNULL((2, 3));

View File

@@ -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. */
#include "mapcolour.h"
#include "../../util/vec.h"
u8vec4 map_colours[MAP_COLOUR_COUNT] = {
{0, 0, 0, 0 },
{127, 178, 56, 255},
{247, 233, 163, 255},
{199, 199, 199, 255},
{255, 0, 0, 255},
{160, 160, 255, 255},
{167, 167, 167, 255},
{0, 124, 0, 255},
{255, 255, 255, 255},
{164, 168, 184, 255},
{151, 109, 77, 255},
{112, 112, 112, 255},
{64, 64, 255, 255},
{143, 119, 72, 255},
{255, 252, 245, 255},
{216, 127, 51, 255},
{178, 76, 216, 255},
{102, 153, 216, 255},
{229, 229, 51, 255},
{127, 204, 25, 255},
{242, 127, 165, 255},
{76, 76, 76, 255},
{153, 153, 153, 255},
{76, 127, 153, 255},
{127, 63, 178, 255},
{51, 76, 178, 255},
{102, 76, 51, 255},
{102, 127, 51, 255},
{153, 51, 51, 255},
{25, 25, 25, 255},
{250, 238, 77, 255},
{92, 219, 213, 255},
{74, 128, 255, 255},
{0, 217, 58, 255},
{129, 86, 49, 255},
{112, 2, 0, 255},
{209, 177, 161, 255},
{159, 82, 36, 255},
{149, 87, 108, 255},
{112, 108, 138, 255},
{186, 133, 36, 255},
{103, 117, 53, 255},
{160, 77, 78, 255},
{57, 41, 35, 255},
{135, 107, 98, 255},
{87, 92, 92, 255},
{122, 73, 88, 255},
{76, 62, 92, 255},
{76, 50, 35, 255},
{76, 82, 42, 255},
{142, 60, 46, 255},
{37, 22, 16, 255},
{189, 48, 49, 255},
{148, 63, 97, 255},
{92, 25, 29, 255},
{22, 126, 134, 255},
{58, 142, 140, 255},
{86, 44, 62, 255},
{20, 180, 133, 255},
{100, 100, 100, 255},
{216, 175, 147, 255},
{127, 167, 150, 255},
};

View File

@@ -1,77 +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 "../../util/vec.h"
enum map_colour_id {
MAP_COLOUR_NONE,
MAP_COLOUR_GRASS,
MAP_COLOUR_SAND,
MAP_COLOUR_WOOL,
MAP_COLOUR_FIRE,
MAP_COLOUR_ICE,
MAP_COLOUR_METAL,
MAP_COLOUR_PLANT,
MAP_COLOUR_SNOW,
MAP_COLOUR_CLAY,
MAP_COLOUR_DIRT,
MAP_COLOUR_STONE,
MAP_COLOUR_WATER,
MAP_COLOUR_WOOD,
MAP_COLOUR_QUARTZ,
MAP_COLOUR_ORANGE,
MAP_COLOUR_MAGENTA,
MAP_COLOUR_LIGHT_BLUE,
MAP_COLOUR_YELLOW,
MAP_COLOUR_LIGHT_GREEN,
MAP_COLOUR_PINK,
MAP_COLOUR_GREY,
MAP_COLOUR_LIGHT_GREY,
MAP_COLOUR_CYAN,
MAP_COLOUR_PURPLE,
MAP_COLOUR_BLUE,
MAP_COLOUR_BROWN,
MAP_COLOUR_GREEN,
MAP_COLOUR_RED,
MAP_COLOUR_BLACK,
MAP_COLOUR_GOLD,
MAP_COLOUR_DIAMOND,
MAP_COLOUR_LAPIS,
MAP_COLOUR_EMERALD,
MAP_COLOUR_PODZOL,
MAP_COLOUR_NETHER,
MAP_COLOUR_TERRACOTTA_WHITE,
MAP_COLOUR_TERRACOTTA_ORANGE,
MAP_COLOUR_TERRACOTTA_MAGENTA,
MAP_COLOUR_TERRACOTTA_LIGHT_BLUE,
MAP_COLOUR_TERRACOTTA_YELLOW,
MAP_COLOUR_TERRACOTTA_LIGHT_GREEN,
MAP_COLOUR_TERRACOTTA_PINK,
MAP_COLOUR_TERRACOTTA_GREY,
MAP_COLOUR_TERRACOTTA_LIGHT_GREY,
MAP_COLOUR_TERRACOTTA_CYAN,
MAP_COLOUR_TERRACOTTA_PURPLE,
MAP_COLOUR_TERRACOTTA_BLUE,
MAP_COLOUR_TERRACOTTA_BROWN,
MAP_COLOUR_TERRACOTTA_GREEN,
MAP_COLOUR_TERRACOTTA_RED,
MAP_COLOUR_TERRACOTTA_BLACK,
MAP_COLOUR_CRIMSON_NYLIUM,
MAP_COLOUR_CRIMSON_STEM,
MAP_COLOUR_CRIMSON_HYPHAE,
MAP_COLOUR_WARPED_NYLIUM,
MAP_COLOUR_WARPED_STEM,
MAP_COLOUR_WARPED_HYPHAE,
MAP_COLOUR_WARPED_WART_BLOCK,
MAP_COLOUR_DEEPSLATE,
MAP_COLOUR_RAW_IRON,
MAP_COLOUR_GLOW_LICHEN,
// contains count, leave last
MAP_COLOUR_COUNT,
};
/* contains the colours of the map on their' respective index - 1. (NONE should be handled separately) */
extern u8vec4 map_colours[MAP_COLOUR_COUNT];

View File

@@ -7,8 +7,8 @@
#include <glad/gl.h>
#include <stdint.h>
#include "../types.h"
#include "../util/error.h"
#include "../../types.h"
#include "../../util/error.h"
#include "shader.h"
#define VERTC 3

View File

@@ -7,7 +7,7 @@
#include <stdint.h>
#include <stdio.h>
#include "../util/error.h"
#include "../../util/error.h"
// NOTE: we are currently just sucking up the memory costs for ease. We can either include the source files themselves. Or use compression, where I'd prefer the latter for ease of installation.

View File

@@ -7,8 +7,8 @@
#include <assert.h>
#include <glad/gl.h>
#include "../types.h"
#include "../util/error.h"
#include "../../types.h"
#include "../../util/error.h"
#include "input.h"
#include "render.h"

View File

@@ -6,7 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "io/window.h"
#include "io/win/window.h"
#include "util/error.h"
/* reroutes GLFW errors to our logging system. */

View File

@@ -57,4 +57,8 @@
#else
#define NONNULL(args)
#endif
#if __has_attribute(__assume__)
#define ASSUME(args) __attribute__((__assume__ args))
#endif
#endif

View File

@@ -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 <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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
}

View File

@@ -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 <stddef.h>
#include <stdlib.h>
#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));

View File

@@ -7,8 +7,7 @@
#include <stdlib.h>
#include "../types.h"
#include "../util/atrb.h"
#include "../util/macro.h"
#include "atrb.h"
void error_debug(uint ln, const char *restrict file, const char *restrict fmt, ...);
void error_info(uint ln, const char *restrict file, const char *restrict fmt, ...);