Compare commits

..

20 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
8bb8671fb0 rephrase the header a little, to not be confusing when a file is copy-pasted. 2025-11-13 22:29:41 +01:00
8d0e825157 rewrite copyright file header to provide more information about where the file is from. 2025-11-13 22:24:09 +01:00
5f909d1d65 rework the flow of the Makefile. 2025-10-23 15:28:42 +02:00
87541d5789 modify Makefile to be more in-line with the GNU standard.
Mainly so the makefile is a bit less esoteric to use, debugging flags
must be specified manually.

changed:
- `$RM` for calling `rm`
- removed unused `$ISWIN`
- renamed `test` to `check`
- added `install` and `install-strip` recipes, which for now remain
empty
- added `-g` to `$CFLAGS`, since it helps debugging, and in case of
failures makes bug report less of a headache.

I decided to not modify it further so "specialised tools" don't need to
store files in the git repo, which seemed to complicate logic.
This is the same reason to why I chose to not adapt clean in a way to
introduce `mostlyclean`.
2025-10-20 15:19:24 +02:00
316726a610 tmp: revert enabling a column limit 2025-10-16 23:35:30 +02:00
1aa34f7d3f enable a column limit. 2025-10-09 21:12:53 +02:00
00719b1933 refactor code with new formatting rules
Functions now break before their brace, mirroring the Linux kernel.
The reason for this is that breaking the parameter list otherwise makes
code unreadable.
2025-10-09 19:02:16 +02:00
eb45650178 fix: use uintptr over usize in locations where applicable 2025-10-09 18:35:39 +02:00
8ca49aa4fa fix: ssize got removed in rework of intdef.h/types.h. 2025-10-09 12:28:24 +02:00
d4fabf437c reformat the code by enabeling assignment- and declaration alignment. 2025-10-09 12:17:04 +02:00
cebe0df8a2 move /src/error.? to /src/util/error.? 2025-10-09 12:16:38 +02:00
aa58d931aa move /src/util/intdef.h to /src/util/types.h 2025-10-09 12:16:06 +02:00
27c862c215 rework intdef.h to not rely upon standard library headers by using predefined macros. 2025-10-09 12:05:05 +02:00
6eb7d126da create a custom definition for size_t and ssize_t, which is ssize and usize, for conveinience. 2025-09-18 10:39:57 +02:00
43 changed files with 436 additions and 677 deletions

View File

@@ -1,5 +1,6 @@
# Copyright (c) 2025 Quinn
# Licensed under the MIT Licence. See LICENSE for details
# Copyright (c) 2025 Quinn.
# This is a file from the project MCA-Selector-Lite and is
# licensed under the MIT Licence. See included LICENSE file for details.
#
---
# ---------------------------
@@ -24,9 +25,9 @@ AlignTrailingComments: true
AlignConsecutiveMacros: AcrossEmptyLines
AlignEscapedNewlines: Left
AlignArrayOfStructures: Left
AlignConsecutiveAssignments: None
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveBitFields: AcrossEmptyLines
AlignConsecutiveDeclarations: None
AlignConsecutiveDeclarations: Consecutive
AlignConsecutiveShortCaseStatements:
Enabled: true
@@ -34,9 +35,9 @@ AlignConsecutiveShortCaseStatements:
# short constructs on a single line
# ---------------------------
AllowShortBlocksOnASingleLine: Always
AllowShortFunctionsOnASingleLine: All
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortIfStatementsOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
@@ -61,7 +62,7 @@ BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterEnum: false
AfterFunction: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false

View File

@@ -1,5 +1,6 @@
# Copyright (c) 2025 Quinn
# Licensed under the MIT Licence. See LICENSE for details
# Copyright (c) 2025 Quinn.
# This is a file from the project MCA-Selector-Lite and is
# licensed under the MIT Licence. See included LICENSE file for details.
[*]
charset = utf-8

View File

@@ -54,4 +54,4 @@ jobs:
if: steps.cache-deps.outputs.cache-hit != 'true' && runner.os == 'Windows'
- run: make -j all
- run: make -j test
- run: make -j check

5
.gitignore vendored
View File

@@ -1,5 +1,6 @@
# Copyright (c) 2025 Quinn
# Licensed under the MIT Licence. See LICENSE for details
# Copyright (c) 2025 Quinn.
# This is a file from the project MCA-Selector-Lite and is
# licensed under the MIT Licence. See included LICENSE file for details.
# ignore all dotfiles by default
.*

5
.gitmodules vendored
View File

@@ -1,6 +1,11 @@
# Copyright (c) 2025 Quinn.
# This is a file from the project MCA-Selector-Lite and is
# licensed under the MIT Licence. See included LICENSE file for details.
[submodule "lib/glfw"]
path = lib/glfw
url = https://github.com/glfw/glfw
[submodule "lib/libarchive"]
path = lib/libarchive
url = https://github.com/libarchive/libarchive

View File

@@ -1,69 +1,71 @@
# Copyright (c) 2025 Quinn
# Licensed under the MIT Licence. See LICENSE for details
# Copyright (c) 2025 Quinn.
# This is a file from the project MCA-Selector-Lite and is
# licensed under the MIT Licence. See included LICENSE file for details.
SHELL = /bin/sh
.SUFFIXES:
# build configuration, information about the current build process
NAME = mcaselector-lite
DEBUG ?= 0
CC ?= cc
CMAKE ?= cmake -G 'Unix Makefiles'
# setting default compilation flags
# some of which are able to be overwritten, others are always appended
CPPFLAGS ?=
CFLAGS ?= -O2 -Wall -Wextra -Wpedantic -Wno-pointer-arith
CC ?= cc
RM ?= rm -vf
CMAKE ?= cmake -G 'Unix Makefiles'
CPPFLAGS ?= -DNDEBUG
CFLAGS ?= -O2
LDFLAGS ?= -flto
CPPFLAGS += -DGLFW_INCLUDE_NONE
CFLAGS += -std=gnu99
# add a few extra flags depending on whether
# we're debugging or not
ifeq ($(DEBUG),0)
CPPFLAGS += -DNDEBUG
else
CFLAGS += -fsanitize=address -ftrapv -g
LDFLAGS += -fsanitize=address -ftrapv
endif
CPPFLAGS += -DGLFW_INCLUDE_NONE
CPPFLAGS += -Iinclude -Ilib/glad/include -Ilib/glfw/include -Ilib/libarchive/libarchive
LDFLAGS += -Llib/obj/glfw/src -Llib/obj/libarchive/libarchive
LDLIBS += -lglfw3 -larchive -lm
CFLAGS += -std=gnu99 -g -MMD -MP
CFLAGS += -Wall -Wextra -Wpedantic -Wno-pointer-arith
# detect if we're compiling on Windows, meaning
# a lot of things considered "standard" are unavailable.
ifeq ($(OS),Windows_NT)
ISWIN = 1
NAME := $(NAME).exe
NAME := $(NAME).exe
LDLIBS += -lopengl32 -lgdi32
$(warning Detected Windows_NT, please refer to the documentation if you encounter issues.)
$(warning Detected Windows_NT, please refer to the documentation if you encounter issues.)
# in the case of Mac OS X
else ifeq ($(shell uname -s),Darwin)
LDLIBS += -framework Cocoa -framework OpenGL -framework IOKit
LDLIBS += -framework Coca -framework OpenGL -framework IOKit
$(info Mac OS X detected.)
endif
# TODO: find a better method to find all source files
# find all the source files using wildcards
# TODO: find a better method to find all source files
# NOTE: MS-DOS and MS-Windows uses backslash `\`, this might break.
RES := $(wildcard res/*)
SRC := $(wildcard src/*.c src/*/*.c src/*/*/*.c src/*/*/*/*.c src/*/*/*/*/*.c src/*/*/*/*/*/*.c src/*/*/*/*/*/*/*.c src/*/*/*/*/*/*/*/*.c) lib/glad/src/gl.c
OBJ := $(SRC:%.c=obj/%.o) $(RES:%=obj/%.o)
SRC := $(wildcard src/*.c src/*/*.c src/*/*/*.c src/*/*/*/*.c src/*/*/*/*/*.c src/*/*/*/*/*/*.c src/*/*/*/*/*/*/*.c src/*/*/*/*/*/*/*/*.c)
SRC += lib/glad/src/gl.c
TSRC := $(wildcard test/*.c test/*/*.c test/*/*/*.c test/*/*/*/*.c test/*/*/*/*/*.c test/*/*/*/*/*/*.c test/*/*/*/*/*/*/*.c test/*/*/*/*/*/*/*/*.c)
TOBJ := $(TSRC:%.c=obj/%.o)
OBJ := $(RES:%=obj/%.o) $(SRC:%.c=obj/%.o)
TOBJ := $(TSRC:%.c=obj/%.o)
# TODO: potentially automatically detect whether we should compile libs, or if we can just go ahead.
.PHONY: all libs test clean clean-libs
.PHONY: all libs check clean clean-libs
all: bin/$(NAME)
libs: lib/obj/glfw/ lib/obj/libarchive/
test: bin/TEST_$(NAME); bin/TEST_$(NAME)
clean:
ifneq ($(wildcard bin/),)
rm -vr bin/
endif
ifneq ($(wildcard obj/),)
rm -vr obj/
endif
clean-libs:
ifneq ($(wildcard lib/obj/),)
rm -vr lib/obj/
check: bin/TEST_$(NAME); ./$<
clean:; @-$(RM) -r bin/ obj/
clean-libs:; @-$(RM) -r lib/obj/
.PHONY:
install: all
ifneq ($(OS),Windows_NT)
# TODO: POSIX-compliant installation
else
# TODO: WINDOWS_NT installation
endif
.PHONY:
install-strip: install
# TODO: strip the produced installation
# compiles the libraries using cmake
lib/obj/%/: lib/%/
$(CMAKE) -S $< -B $@
@@ -86,17 +88,18 @@ obj/res/%.c: res/%
@mkdir -p $(@D)
@cd res/ && xxd -i $(patsubst res/%,%,$<) $(abspath $@)
obj/res/%.o: obj/res/%.c
obj/%.o: %.c
$(info [CC] $@)
@mkdir -p $(@D)
@$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
obj/%.o: %.c
obj/%.o: obj/%.c
$(info [CC] $@)
@mkdir -p $(@D)
@$(CC) -c $(CPPFLAGS) $(CFLAGS) -MMD -MP -o $@ $<
@$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
# Include the generated dependency files.
# Which creates rules for all dependencies,
# as a result updating an .o file when a .h is updated.
-include $(OBJ:%.o=%.d)
-include $(TOBJ:%.o=%.d)

View File

@@ -21,7 +21,7 @@ Where we have dependencies on:
| [openGL](https://www.opengl.org/) | hardware accelleration, for handling graphics. |
It is intended to be platform-agnostic, within reason. But the main focus is for [Linux](https://wikipedia.org/wiki/Linux) systems with [x86_64](https://wikipedia.org/wiki/X86-64) architecture.
Within [intdef.h](/src/util/intdef.h) there live definitions for fixed-width integer types.
Within [types.h](/src/types.h) there live definitions for fixed-width integer types.
### style guide
- Code must be written correctly, read [Correct C](./correct-c.md) if more information is required.

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "mcx.h"
#include <archive.h>
@@ -10,23 +11,24 @@
#include <string.h>
#include <time.h>
#include "../error.h"
#include "../util/intdef.h"
#include "../types.h"
#include "../util/error.h"
#define SECTOR 0x1000 // sector size
#define TABLE 0x800 // table (total) element count
#define CHUNKS 0x400 // amount of chunks in a file
enum mcx_compression {
MCX_COMPRESSION_GZIP = 0x01,
MCX_COMPRESSION_ZLIB = 0x02,
MCX_COMPRESSION_NONE = 0x03,
MCX_COMPRESSION_LZ4 = 0x04,
MCX_COMPRESSION_GZIP = 0x01,
MCX_COMPRESSION_ZLIB = 0x02,
MCX_COMPRESSION_NONE = 0x03,
MCX_COMPRESSION_LZ4 = 0x04,
MCX_COMPRESSION_CUSTOM = 0x7F,
};
/* first 4 bytes is an i32 indicating remaining bytes, the following byte defines the compression scheme */
static int mcx_loadchunk(const u8 *restrict buf, const i32 *restrict table, int idx) {
static int mcx_loadchunk(const u8 *restrict buf, const i32 *restrict table, int idx)
{
const u8 *chunk = buf + (be32toh(table[idx]) >> 8) * SECTOR;
i32 len;
@@ -56,7 +58,7 @@ static int mcx_loadchunk(const u8 *restrict buf, const i32 *restrict table, int
return 1;
}
ssize_t size = -1;
ssize size = -1;
for (;;) {
// TODO: handle buffer
// size = archive_read_data(archive, , );
@@ -64,7 +66,8 @@ static int mcx_loadchunk(const u8 *restrict buf, const i32 *restrict table, int
error("failed to decompress %i bytes of compression type %i", len, *chunk);
return 1;
}
if (size == 0) break;
if (size == 0)
break;
// TODO: handle data
}
@@ -72,13 +75,14 @@ static int mcx_loadchunk(const u8 *restrict buf, const i32 *restrict table, int
}
/* Moves chunks `src_s` to `src_e` (inclusive) from `src`, back onto `dst`. */
static void mvchunks(u8 *dst, u8 *src, u32 *restrict table, int src_s, int src_e) {
static void mvchunks(u8 *dst, u8 *src, u32 *restrict table, int src_s, int src_e)
{
assert(src > dst);
size_t len = src - dst; // acquire the amount of bytes that we shall move
uintptr len = src - dst; // acquire the amount of bytes that we shall move
assert(!(len % SECTOR));
// count how many bytes we need to move, whilst updating location data
size_t blen = 0;
usize blen = 0;
for (src_s++; src_s <= src_e; src_s++) {
blen += (be32toh(table[src_s]) & 0xFF) * SECTOR;
table[src_s] -= htobe32((len / SECTOR) << 8);
@@ -89,15 +93,16 @@ static void mvchunks(u8 *dst, u8 *src, u32 *restrict table, int src_s, int src_e
/* Deletes chunk `sidx` by moving chunks up to `eidx` back over `sidx` in `buf`.
* `rmb` is an optional additional offset that can be applied, and signifies bytes already removed.
* Returns the bytes removed by this function. */
static size_t delchunk(u8 *restrict buf, u32 *restrict table, size_t rmb, int sidx, int eidx) {
static usize delchunk(u8 *restrict buf, u32 *restrict table, usize rmb, int sidx, int eidx)
{
// load the table data
size_t slen, bidx, blen;
usize slen, bidx, blen;
slen = be32toh(table[sidx]) & 0xFF; // acquire the sector length of the chunk
bidx = (be32toh(table[sidx]) >> 8) * SECTOR; // acquire and compute the byte offset the chunk starts at
blen = slen * SECTOR; // compute the byte length of the chunk
// reset the table data
table[sidx] = 0;
table[sidx] = 0;
table[sidx + CHUNKS] = htobe32(time(NULL)); // assign the current time to the timestamp, for correctness NOTE: might need to zero-out instead
// move the succeeding chunks over the deleted chunk
@@ -110,15 +115,17 @@ static size_t delchunk(u8 *restrict buf, u32 *restrict table, size_t rmb, int si
/* Call `delchunk` with the parameters and some defaults. Ensuring the table is copied correctly as well.
* This is done instead of `delchunk` being globally linked, because
* `delchunk` requests more specific parameters, which is confusing outside this module. */
size_t mcx_delchunk(u8 *restrict buf, int chunk) {
usize mcx_delchunk(u8 *restrict buf, int chunk)
{
u32 table[TABLE];
memcpy(table, buf, sizeof(table));
size_t res = delchunk(buf, table, 0, chunk, CHUNKS);
usize res = delchunk(buf, table, 0, chunk, CHUNKS);
memcpy(buf, table, sizeof(table));
return res;
}
size_t mcx_delchunk_range(u8 *restrict buf, int start, int end) {
usize mcx_delchunk_range(u8 *restrict buf, int start, int end)
{
assert(start < end && end < CHUNKS);
u32 table[TABLE];
memcpy(table, buf, sizeof(table));
@@ -129,7 +136,7 @@ size_t mcx_delchunk_range(u8 *restrict buf, int start, int end) {
// zeroes-out the chunk data within this range. (and set the timestamp)
u32 ts = htobe32(time(NULL));
for (int i = start; i <= end; i++) {
table[i] = 0;
table[i] = 0;
table[i + CHUNKS] = ts;
}
@@ -141,7 +148,8 @@ size_t mcx_delchunk_range(u8 *restrict buf, int start, int end) {
}
/* comparer function for to be inputted into `qsort` to compare two */
static int cmp_chunkids(const void *restrict x, const void *restrict y) {
static int cmp_chunkids(const void *restrict x, const void *restrict y)
{
u16 x2 = *(u16 *)x;
u16 y2 = *(u16 *)y;
return (x2 > y2) - (x2 < y2);
@@ -149,7 +157,8 @@ static int cmp_chunkids(const void *restrict x, const void *restrict y) {
/* Sorts the chunks marked for deletion from smallest to greatest index.
* Then performs the deletion in this order. Making sure to only update the chunks up to the next. */
size_t mcx_delchunk_bulk(u8 *restrict buf, const u16 *restrict chunks, int chunkc) {
usize mcx_delchunk_bulk(u8 *restrict buf, const u16 *restrict chunks, int chunkc)
{
// ensure the chunks ids we're working on are sorted from least to greatest
u16 chunkids[chunkc + 1];
memcpy(chunkids, chunks, chunkc);
@@ -159,7 +168,7 @@ size_t mcx_delchunk_bulk(u8 *restrict buf, const u16 *restrict chunks, int chunk
u32 table[TABLE];
memcpy(table, buf, sizeof(table));
size_t rmb = 0;
usize rmb = 0;
for (int i = 0; i < chunkc; i++)
rmb += delchunk(buf, table, rmb, chunkids[i], chunkids[i + 1]);
@@ -169,8 +178,9 @@ size_t mcx_delchunk_bulk(u8 *restrict buf, const u16 *restrict chunks, int chunk
/* Sum together the 4th byte in each location integer to compute the sector size of all chunks.
* Multiplying by `SECTOR`, and adding the size of the table itself. */
size_t mcx_calcsize(const u8 *restrict buf) {
size_t size = 0;
usize mcx_calcsize(const u8 *restrict buf)
{
usize size = 0;
for (uint i = 0; i < CHUNKS; i++)
size += *(buf + (i * 4) + 3);
return (size * SECTOR) + (TABLE * 4);

View File

@@ -1,37 +1,38 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 <stdlib.h>
#include "../types.h"
#include "../util/atrb.h"
#include "../util/intdef.h"
/* contains chunk metadata */
struct mcx_chunk {
size_t idx; // byte offset for start of chunk data
u32 len; // byte length of chunk (+ padding)
u32 time; // modification time in epoch seconds
usize idx; // byte offset for start of chunk data
u32 len; // byte length of chunk (+ padding)
u32 time; // modification time in epoch seconds
};
/* Deletes a single chunk (`chunk`) out of `buf`.
* The chunk's location data shall become `0`, and timestamp data the current time.
* All succeeding chunks shall be moved back, freeing space.
* Returns the amount of bytes removed. */
size_t mcx_delchunk(u8 *restrict buf, int chunk) NONNULL((1));
usize mcx_delchunk(u8 *restrict buf, int chunk) NONNULL((1));
/* Deletes the range defined by `start`—`end` (inclusive) of chunks out of `buf`.
* The chunk's location data shall become `0`, and timestamp data the current time.
* All succeeding chunks shall be moved back, freeing space.
* Returns the amount of bytes removed */
size_t mcx_delchunk_range(u8 *restrict buf, int start, int end) NONNULL((1));
usize mcx_delchunk_range(u8 *restrict buf, int start, int end) NONNULL((1));
/* Deletes a `chunkc` chunks from `chunks` out of `buf`.
* If the `chunks` indices are known to be sequential, i.e. have a constant difference of `1`, `mcx_delchunk_range` should be preferred.
* The chunk's location data shall become `0`, and timestamp data the current time.
* All succeeding chunks shall be moved back, freeing space.
* Returns the amount of bytes removed */
size_t mcx_delchunk_bulk(u8 *restrict buf, const u16 *restrict chunks, int chunkc) NONNULL((1, 2));
usize mcx_delchunk_bulk(u8 *restrict buf, const u16 *restrict chunks, int chunkc) NONNULL((1, 2));
/* Computes the byte size of the `*.mcX` file in `buf` and returns it. */
size_t mcx_calcsize(const u8 *restrict buf) NONNULL((1)) PURE;
usize mcx_calcsize(const u8 *restrict buf) NONNULL((1)) PURE;

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "nbt.h"
#include <assert.h>
@@ -8,26 +9,29 @@
#include <stdlib.h>
#include <string.h>
#include "../util/intdef.h"
#include "../types.h"
#define MAX_DEPTH 512
/* Extracts a big endian 16 bit integer from address `buf`, converts it to host byte size if needed and returns. */
static inline u16 buftoh16(const void *restrict buf) {
static inline u16 buftoh16(const void *restrict buf)
{
u16 i;
memcpy(&i, buf, sizeof(i));
return be16toh(i);
}
/* Extracts a big endian 32 bit integer from address `buf`, converts it to host byte size if needed and returns. */
static inline u32 buftoh32(const void *restrict buf) {
static inline u32 buftoh32(const void *restrict buf)
{
u32 i;
memcpy(&i, buf, sizeof(i));
return be32toh(i);
}
/* Extracts a big endian 64 bit integer from address `buf`, converts it to host byte size if needed and returns. */
static inline u64 buftoh64(const void *restrict buf) {
static inline u64 buftoh64(const void *restrict buf)
{
u64 i;
memcpy(&i, buf, sizeof(i));
return be64toh(i);
@@ -36,12 +40,13 @@ static inline u64 buftoh64(const void *restrict buf) {
/* Processes the incoming array data in `buf`. Which contains `nmem` items of `size`.
* The data shall be converted to little-endian on little-endian systems
* Outputs the allocated data to `out`, returns where the next pointer would be. */
static const u8 *procarr(const u8 *restrict buf, i32 nmemb, uint size, struct nbt_array *restrict out) {
size_t len = nmemb * size;
*out = (struct nbt_array){
out->nmemb = nmemb,
out->dat = malloc(len),
};
static const u8 *procarr(const u8 *restrict buf, i32 nmemb, uint size, struct nbt_array *restrict out)
{
usize len = nmemb * size;
*out = (struct nbt_array){
out->nmemb = nmemb,
out->dat = malloc(len),
};
if (!out->dat)
return buf + len;
@@ -51,7 +56,8 @@ static const u8 *procarr(const u8 *restrict buf, i32 nmemb, uint size, struct nb
/* Only include this code for little-endian systems. Since only they require this logic.
* Producing optimised code for other platforms. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
if (size == 1) return buf;
if (size == 1)
return buf;
i32 i = 0;
while (i < nmemb) {
switch (size) {
@@ -67,7 +73,8 @@ static const u8 *procarr(const u8 *restrict buf, i32 nmemb, uint size, struct nb
}
/* calls `procarr` for the simple types available. */
static const u8 *proclist(const u8 *restrict buf, struct nbt_array *restrict out) {
static const u8 *proclist(const u8 *restrict buf, struct nbt_array *restrict out)
{
uint size;
switch (*(u8 *)buf) {
@@ -88,11 +95,12 @@ static const u8 *proclist(const u8 *restrict buf, struct nbt_array *restrict out
return procarr(buf, len, size, out);
}
const u8 *nbt_proctag(const u8 *restrict buf, u16 slen, void *restrict out) {
const u8 *nbt_proctag(const u8 *restrict buf, u16 slen, void *restrict out)
{
const u8 *ptr, *tmp;
ptr = buf + 3 + slen;
i32 nmem;
i32 nmem;
uint size;
switch (*buf) {
@@ -123,7 +131,8 @@ const u8 *nbt_proctag(const u8 *restrict buf, u16 slen, void *restrict out) {
* `ptr` is assumed to be the start of the `NBT_LIST` data, e.i. The list's ID, followed by the list's length.
* If `ID` is `NBT_I8`, `NBT_I16`, `NBT_I32`, `NBT_I64`, `NBT_F32`, or `NBT_F64`, the entire list length is computed and returned.
* For other types this won't be possible, and thus will add `1` to `dpt`, and write the list data to `lens` and `tags` at this new `dpt`. */
static const u8 *nexttag_list(const u8 *restrict ptr, uint *restrict const dpt, i32 *restrict const lens, u8 *restrict const tags) {
static const u8 *nexttag_list(const u8 *restrict ptr, uint *restrict const dpt, i32 *restrict const lens, u8 *restrict const tags)
{
const u8 *tag = ptr;
ptr++;
switch (*tag) {
@@ -151,8 +160,9 @@ static const u8 *nexttag_list(const u8 *restrict ptr, uint *restrict const dpt,
* - `lens` shall contain `MAX_DEPTH` of items representing the list length, if the current item is non-zero we shall assume we're in a list.
* Where the value is decremented until we reach `0`.
* - `tags` shall contain `MAX_DEPTH` of items representing the list's stored type. */
static const u8 *nexttag(const u8 *restrict tag, uint *restrict const dpt, i32 *restrict const lens, u8 *restrict const tags) {
u8 type;
static const u8 *nexttag(const u8 *restrict tag, uint *restrict const dpt, i32 *restrict const lens, u8 *restrict const tags)
{
u8 type;
const u8 *ptr = tag;
if (lens[*dpt]) {
type = tags[*dpt];
@@ -193,11 +203,12 @@ static const u8 *nexttag(const u8 *restrict tag, uint *restrict const dpt, i32 *
* - compound:list:int32
* - string
*/
const u8 *nbt_nexttag(const u8 *restrict buf) {
const u8 *nbt_nexttag(const u8 *restrict buf)
{
const u8 *tag;
u8 tags[MAX_DEPTH] = {0};
i32 lens[MAX_DEPTH] = {0};
uint dpt = 0;
u8 tags[MAX_DEPTH] = {0};
i32 lens[MAX_DEPTH] = {0};
uint dpt = 0;
tag = buf;
do {

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 <assert.h>
@@ -7,8 +8,8 @@
#include <stdbool.h>
#include <stdlib.h>
#include "../types.h"
#include "../util/atrb.h"
#include "../util/intdef.h"
/* NBT (named binary tag) is a tree data structure. Tags have a numeric type ID, name and a payload.
* NBT files are a compressed `compound` tag. GZip is the compression used in most cases,
@@ -21,23 +22,23 @@
/* specifies the NBT tag IDs.
* NOTE: every type is stored as BE (big-endian) in the file. */
enum nbt_tagid {
NBT_END = 0x00, // signifies the end of a compound tag
NBT_I8 = 0x01, // next byte is for an 8 bit signed integer.
NBT_I16 = 0x02, // next 2 bytes are for a 16 bit signed integer
NBT_I32 = 0x03, // next 4 bytes are for a 32 bit signed integer
NBT_I64 = 0x04, // next 8 bytes are for a 64 bit signed integer
NBT_F32 = 0x05, // next 4 bytes are for a single-precision floating-point
NBT_F64 = 0x06, // next 8 bytes are for a double-precision floating-point
NBT_ARR_I8 = 0x07, // starts with a i32, denoting size, followed by the i8 data
NBT_STR = 0x08, // starts with a u16, denoting size, followed by the UTF-8 data
NBT_LIST = 0x09, // starts with an ID, followed by a 32 bit signed integer denoting the size
NBT_END = 0x00, // signifies the end of a compound tag
NBT_I8 = 0x01, // next byte is for an 8 bit signed integer.
NBT_I16 = 0x02, // next 2 bytes are for a 16 bit signed integer
NBT_I32 = 0x03, // next 4 bytes are for a 32 bit signed integer
NBT_I64 = 0x04, // next 8 bytes are for a 64 bit signed integer
NBT_F32 = 0x05, // next 4 bytes are for a single-precision floating-point
NBT_F64 = 0x06, // next 8 bytes are for a double-precision floating-point
NBT_ARR_I8 = 0x07, // starts with a i32, denoting size, followed by the i8 data
NBT_STR = 0x08, // starts with a u16, denoting size, followed by the UTF-8 data
NBT_LIST = 0x09, // starts with an ID, followed by a 32 bit signed integer denoting the size
NBT_COMPOUND = 0x0A, // compound tag, contains tags and is delimited by `NBT_END`
NBT_ARR_I32 = 0x0B, // starts with a i32, denoting size, followed by the i32 data
NBT_ARR_I64 = 0x0C, // starts with a i32, denoting size, followed by the u32 data
NBT_ARR_I32 = 0x0B, // starts with a i32, denoting size, followed by the i32 data
NBT_ARR_I64 = 0x0C, // starts with a i32, denoting size, followed by the u32 data
};
struct nbt_array {
i32 nmemb;
i32 nmemb;
void *dat;
};

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,10 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
#pragma once
#include <GLFW/glfw3.h>
#include <glad/gl.h>
int render_init(void);
void render_update(GLFWwindow *win);
void render_free(void);

View File

@@ -1,70 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE 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,76 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE 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

@@ -1,10 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
#pragma once
#include <glad/gl.h>
#include <stddef.h>
#include <stdint.h>
/* Initialises the (embedded) shaders onto `pipe` */
int shader_init(GLuint pipe);

View File

@@ -1,10 +1,12 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "input.h"
#include <GLFW/glfw3.h>
void input_callback(GLFWwindow *win, int key, int scancode, int action, int mods) {
void input_callback(GLFWwindow *win, int key, int scancode, int action, int mods)
{
(void)win, (void)key, (void)scancode, (void)action, (void)mods; // make the compiler shut up as this is fine
#ifndef NDEBUG
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 <GLFW/glfw3.h>

View File

@@ -1,13 +1,14 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "render.h"
#include <GLFW/glfw3.h>
#include <glad/gl.h>
#include <stdint.h>
#include "../error.h"
#include "../util/intdef.h"
#include "../../types.h"
#include "../../util/error.h"
#include "shader.h"
#define VERTC 3
@@ -15,9 +16,10 @@ static GLuint pipe;
static GLuint vbo; // vertex buffer object
static GLuint vao; // vertex array object
static GLuint screen_loc; // location to where OpenGL sends to the shaders of the screen dimensions
static int win_w, win_h;
static int win_w, win_h;
static void screen_resize(int w, int h) {
static void screen_resize(int w, int h)
{
i32 verts[VERTC][4] = {
{0, 0, w, 20 },
{0, 20, w, h - 40},
@@ -31,7 +33,8 @@ static void screen_resize(int w, int h) {
win_h = h;
}
int render_init(void) {
int render_init(void)
{
pipe = glCreateProgram();
shader_init(pipe); // initialise and include the shaders
glLinkProgram(pipe); // link the application
@@ -63,7 +66,8 @@ int render_init(void) {
return 0;
}
void render_update(GLFWwindow *win) {
void render_update(GLFWwindow *win)
{
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
@@ -80,11 +84,12 @@ void render_update(GLFWwindow *win) {
glDrawArrays(GL_POINTS, 0, VERTC);
}
void render_free(void) {
void render_free(void)
{
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteProgram(pipe);
vbo = 0;
vao = 0;
vbo = 0;
vao = 0;
pipe = 0;
}

11
src/io/win/render.h Normal file
View File

@@ -0,0 +1,11 @@
/* 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 <GLFW/glfw3.h>
#include <glad/gl.h>
int render_init(void);
void render_update(GLFWwindow *win);
void render_free(void);

View File

@@ -1,12 +1,13 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "shader.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "../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.
@@ -19,8 +20,9 @@ extern const uint sh_geom_glsl_len;
/* Compiles a shader of `type` from `src` with `len` bytes.
* Returns the integer for the shader. */
static GLuint shader_compile(GLenum type, const char *src, size_t len) {
int ilen = len;
static GLuint shader_compile(GLenum type, const char *src, usize len)
{
int ilen = len;
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &src, &ilen);
glCompileShader(shader);
@@ -37,7 +39,8 @@ static GLuint shader_compile(GLenum type, const char *src, size_t len) {
return shader;
}
int shader_init(GLuint pipe) {
int shader_init(GLuint pipe)
{
GLuint vs = shader_compile(GL_VERTEX_SHADER, sh_vert_glsl, sh_vert_glsl_len);
GLuint fs = shader_compile(GL_FRAGMENT_SHADER, sh_frag_glsl, sh_frag_glsl_len);
GLuint gs = shader_compile(GL_GEOMETRY_SHADER, sh_geom_glsl, sh_geom_glsl_len);

11
src/io/win/shader.h Normal file
View File

@@ -0,0 +1,11 @@
/* 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 <glad/gl.h>
#include <stddef.h>
#include <stdint.h>
/* Initialises the (embedded) shaders onto `pipe` */
int shader_init(GLuint pipe);

View File

@@ -1,13 +1,14 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "window.h"
#include <GLFW/glfw3.h>
#include <assert.h>
#include <glad/gl.h>
#include "../error.h"
#include "../util/intdef.h"
#include "../../types.h"
#include "../../util/error.h"
#include "input.h"
#include "render.h"
@@ -15,7 +16,8 @@ static struct GLFWwindow *win = NULL;
/* Initialises the GLFW window with some defaults,
* then proceed to activate OpenGL on it. */
int window_init(void) {
int window_init(void)
{
// initialise the window
#ifndef NDEBUG
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
@@ -32,10 +34,12 @@ int window_init(void) {
/* NOTE: on my system; x86_64, GTX 1650 580.82.09-2, X11, i3, this causes one direct, 2 indirect memory leaks.
* This is not my fault, and can safely be ignored. */
win = glfwCreateWindow(640, 480, "MCA-Selector lite", NULL, NULL);
if (!win) return 1;
if (!win)
return 1;
glfwMakeContextCurrent(win);
if (!gladLoadGL(glfwGetProcAddress)) return 1;
if (!gladLoadGL(glfwGetProcAddress))
return 1;
glfwSwapInterval(1); // wait 1 screen update for a redraw a.k.a. "vsync". (not really applicable in this case but eh)
glfwSetKeyCallback(win, input_callback);
@@ -53,7 +57,8 @@ int window_init(void) {
return 0;
}
void window_loop(void) {
void window_loop(void)
{
assert(win);
render_init();
while (!glfwWindowShouldClose(win)) {
@@ -65,12 +70,14 @@ void window_loop(void) {
}
}
void window_close(void) {
void window_close(void)
{
assert(win);
glfwSetWindowShouldClose(win, 1);
}
void window_free(void) {
void window_free(void)
{
if (!win) {
debug("window has already been freed.");
return;

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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
/* Set up the window, enabling OpenGL, and

View File

@@ -1,19 +1,22 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 <GLFW/glfw3.h>
#include <glad/gl.h>
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
#include "io/window.h"
#include "io/win/window.h"
#include "util/error.h"
/* reroutes GLFW errors to our logging system. */
static void error_callback(int err, const char *const msg) {
static void error_callback(int err, const char *const msg)
{
error("glfw returned (%i); \"%s\"", err, msg);
}
static void quit(void) {
static void quit(void)
{
window_free();
/* terminates GLFW; destroying any
@@ -23,7 +26,8 @@ static void quit(void) {
/* Entry-point of the application. */
int main(int argc, char **argv) {
int main(int argc, char **argv)
{
(void)argc, (void)argv;
printf("debug: [DBG], info: [INF], warning: [WAR], error: [ERR], fatal: [FAT]\n");
atexit(quit);

36
src/types.h Normal file
View File

@@ -0,0 +1,36 @@
/* 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
typedef signed long long int llong;
typedef unsigned short int ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ullong;
typedef __INT8_TYPE__ i8;
typedef __INT16_TYPE__ i16;
typedef __INT32_TYPE__ i32;
typedef __INT64_TYPE__ i64;
typedef __UINT8_TYPE__ u8;
typedef __UINT16_TYPE__ u16;
typedef __UINT32_TYPE__ u32;
typedef __UINT64_TYPE__ u64;
typedef __SIZE_TYPE__ usize;
typedef __INTPTR_TYPE__ intptr;
typedef __UINTPTR_TYPE__ uintptr;
#if __SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__
typedef llong ssize;
#elif __SIZEOF_SIZE_T__ == __SIZEOF_LONG__
typedef long ssize;
#elif __SIZEOF_SIZE_T__ == __SIZEOF_INT__
typedef int ssize;
#endif
#if __SIZEOF_FLOAT__ == 4
typedef float f32;
#endif
#if __SIZEOF_DOUBLE__ == 8
typedef double f64;
#endif

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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
#if defined(__GNUC__)
@@ -56,4 +57,8 @@
#else
#define NONNULL(args)
#endif
#if __has_attribute(__assume__)
#define ASSUME(args) __attribute__((__assume__ args))
#endif
#endif

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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
#if defined __unix__
@@ -33,14 +34,16 @@ static inline int faccess(const char *restrict fname, int perms);
#define PATH_SEP '/' // contains the path separator as a character. Yes it is extremely annoying that this has to exist.
#define PATH_SEP_STR "/" // contains the path separator as a string, useful for concatenation. Yes it is extremely annoying that this has to exist.
int faccess(char const *restrict fname, int perms) {
int faccess(char const *restrict fname, int perms)
{
return access(fname, perms);
}
#elif defined(_WIN32)
#define PATH_SEP '\\' // contains the path separator as a character. Yes it is extremely annoying that this has to exist.
#define PATH_SEP_STR "\\" // contains the path separator as a string, useful for concatenation. Yes it is extremely annoying that this has to exist.
int faccess(char const *restrict fname, int perms) {
int faccess(char const *restrict fname, int perms)
{
return _access(fname, perms);
}
#else

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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
#if defined(__unix__)

View File

@@ -1,180 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE 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 "../error.h"
#include "atrb.h"
#include "intdef.h"
int conf_procbuf(const char *restrict buf, char *restrict kout, char *restrict vout, size_t 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 (size_t 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, size_t optc, const char *restrict key) {
// find a match for the current key
size_t 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, size_t s1len, size_t s2len, size_t 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;
size_t len;
size_t 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,70 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
#pragma once
#include <stddef.h>
#include <stdlib.h>
#include "atrb.h"
#include "intdef.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 {
size_t 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, size_t 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, size_t 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

@@ -1,21 +1,22 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "error.h"
#include <stdarg.h>
#include <stdio.h>
#include "util/intdef.h"
#include "../types.h"
static void error_log(FILE *restrict stream, const char *restrict pfx, uint ln, const char *restrict file, const char *restrict fmt, va_list ap) {
static void error_log(FILE *restrict stream, const char *restrict pfx, uint ln, const char *restrict file, const char *restrict fmt, va_list ap)
{
fprintf(stream, "(%s:%u) [%s] '", file, ln, pfx);
vfprintf(stream, fmt, ap);
fprintf(stream, "'\n");
}
void error_debug(uint ln, const char *restrict file, const char *restrict fmt, ...) {
void error_debug(uint ln, const char *restrict file, const char *restrict fmt, ...)
{
#ifndef NDEBUG
#else
char *env = getenv("DEBUG");
@@ -28,28 +29,32 @@ void error_debug(uint ln, const char *restrict file, const char *restrict fmt, .
va_end(ap);
}
void error_info(uint ln, const char *restrict file, const char *restrict fmt, ...) {
void error_info(uint ln, const char *restrict file, const char *restrict fmt, ...)
{
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[94mINF\033[0m", ln, file, fmt, ap);
va_end(ap);
}
void error_warn(uint ln, const char *restrict file, const char *restrict fmt, ...) {
void error_warn(uint ln, const char *restrict file, const char *restrict fmt, ...)
{
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[93mWAR\033[0m", ln, file, fmt, ap);
va_end(ap);
}
void error_error(uint ln, const char *restrict file, const char *restrict fmt, ...) {
void error_error(uint ln, const char *restrict file, const char *restrict fmt, ...)
{
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[91mERR\033[0m", ln, file, fmt, ap);
va_end(ap);
}
void error_fatal(uint ln, const char *restrict file, const char *restrict fmt, ...) {
void error_fatal(uint ln, const char *restrict file, const char *restrict fmt, ...)
{
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[101mFAT\033[0m", ln, file, fmt, ap);

View File

@@ -1,13 +1,13 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 <stdio.h>
#include <stdlib.h>
#include "util/atrb.h"
#include "util/intdef.h"
#include "util/macro.h"
#include "../types.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, ...);

View File

@@ -1,24 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
#pragma once
/* variable-width integer types */
typedef unsigned int uint; // ≥16 bit unsigned integer
typedef unsigned long ulong; // ≥32 bit unsigned integer
typedef signed long long llong; // ≥64 bit signed integer
typedef unsigned long long ullong; // ≥64 bit unsigned integer
/* fixed-width integer types */
#include <stdint.h>
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
/* floating point types */
typedef float f32; // single-precision floating-point
typedef double f64; // double-precision floating-point

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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
#define WIDTHOF(t) (sizeof(t) * 8) // gets the bit width of a type

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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
/* Acquires the next power of two of value `x`.

View File

@@ -1,8 +1,9 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "intdef.h"
#include "../types.h"
#if defined(__has_attribute) && __has_attribute(vector_size)
typedef float fvec2 __attribute__((vector_size(sizeof(float) * 2))); // SMID vector for 2 `float`

View File

@@ -1,11 +1,14 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 <stdint.h>
#include <stdio.h>
#include "test.h"
#include "test_conf.h"
int main(void) {
int main(void)
{
assert_true(-3 >> 5 == -1); // checking for arithmetic shift, rather than logical shift
assert_true(sizeof(u8) == 1);
assert_true(sizeof(u16) == 2);
@@ -13,6 +16,7 @@ int main(void) {
assert_true(sizeof(u64) == 8);
assert_true(sizeof(f32) == 4);
assert_true(sizeof(f64) == 8);
assert_true(sizeof(usize) == sizeof(size_t));
test_conf_procbuf("key=val", "key", "val", 0);
test_conf_procbuf("sometxt", "sometxt", "", CONF_ESYNTAX);
test_conf_procbuf("# comment", "", "", CONF_ENODAT);

View File

@@ -1,13 +1,15 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "test.h"
#include "../src/util/intdef.h"
#include "../src/types.h"
uint test_okay = 0;
uint test_fail = 0;
int test_process(int res, const char *restrict file, uint ln, const char *restrict function, const char *restrict expression) {
int test_process(int res, const char *restrict file, uint ln, const char *restrict function, const char *restrict expression)
{
const char *status = res ?
"[\033[32;1m OK \033[0m]" :
"[\033[31;1m FAIL \033[0m]";

View File

@@ -1,9 +1,10 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 <stdio.h>
#include "../src/util/intdef.h"
#include "../src/types.h"
extern uint test_okay;
extern uint test_fail;

View File

@@ -1,77 +1,89 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "test_conf.h"
#include <math.h>
#include <string.h>
#include "../src/types.h"
#include "../src/util/conf.h"
#include "test.h"
void test_conf_procbuf(const char *restrict buf, const char *restrict expect_key, const char *restrict expect_val, int expect_return) {
size_t len = strlen(buf) + 1;
char k[len], v[len];
void test_conf_procbuf(const char *restrict buf, const char *restrict expect_key, const char *restrict expect_val, int expect_return)
{
usize len = strlen(buf) + 1;
char k[len], v[len];
*k = '\0', *v = '\0';
(void)(assert_true(conf_procbuf(buf, k, v, len) == expect_return) &&
assert_true(!strcmp(k, expect_key)) &&
assert_true(!strcmp(v, expect_val)));
}
void test_conf_matchopt(struct conf_entry *opts, size_t optc, const char *restrict key, int expect_index) {
size_t idx = opts - conf_matchopt(opts, optc, key);
idx = (ssize_t)idx < 0 ? -idx : idx;
int i = idx < optc ? (int)idx : -1;
void test_conf_matchopt(struct conf_entry *opts, usize optc, const char *restrict key, int expect_index)
{
usize idx = opts - conf_matchopt(opts, optc, key);
idx = (ssize)idx < 0 ? -idx : idx;
int i = idx < optc ? (int)idx : -1;
assert_true(i == expect_index);
}
void test_conf_procval_int(const char *val, u64 expect_value, int type) {
void test_conf_procval_int(const char *val, u64 expect_value, int type)
{
u8 out[sizeof(u64)] = {0};
assert_true(!conf_procval(&(struct conf_entry){NULL, out, type}, val));
assert_true(memcmp(out, &expect_value, sizeof(u64)) == 0);
}
void test_conf_procval_f32(const char *val, f32 expect_value) {
u8 out[4];
void test_conf_procval_f32(const char *val, f32 expect_value)
{
u8 out[4];
f32 result;
conf_procval(&(struct conf_entry){NULL, out, CONF_F32}, val);
memcpy(&result, out, 4);
assert_true(fabsf(expect_value - result) < 1e-9f);
}
void test_procval_str(void) {
void test_procval_str(void)
{
char *out = NULL;
(void)(assert_true(!conf_procval(&(struct conf_entry){NULL, (void *)&out, CONF_STR}, "here comes the sowon")) &&
assert_false(strcmp("here comes the sowon", out)));
free(out);
}
void test_procval_str_predef(void) {
void test_procval_str_predef(void)
{
char *out = strdup("owo");
(void)(assert_true(!conf_procval(&(struct conf_entry){NULL, (void *)&out, CONF_STR}, "i leak if I don't free")) &&
assert_true(!strcmp("i leak if I don't free", out)));
free(out);
}
void test_procval_fstr(void) {
char buf[16];
void test_procval_fstr(void)
{
char buf[16];
struct conf_fstr str = {sizeof(buf), buf};
(void)(assert_true(!conf_procval(&(struct conf_entry){NULL, &str, CONF_FSTR}, "hewwoo wowld")) &&
assert_true(!strcmp(str.out, "hewwoo wowld")));
}
void test_procval_fstr_trunc(void) {
char buf[8];
void test_procval_fstr_trunc(void)
{
char buf[8];
struct conf_fstr str = {sizeof(buf), buf};
(void)(assert_true(!conf_procval(&(struct conf_entry){NULL, &str, CONF_FSTR}, "hewwooo wowld")) &&
assert_true(!strcmp(str.out, "hewwooo")));
}
void test_procval_eparse(void) {
void test_procval_eparse(void)
{
i32 out;
assert_true(conf_procval(&(struct conf_entry){NULL, &out, CONF_I32}, "owo") == CONF_EPARSE);
}
void test_conf_getpat(void) {
void test_conf_getpat(void)
{
char *path;
#if defined(__linux__)
/* test without setting environment variables. */

View File

@@ -1,12 +1,13 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
/* 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 "../src/types.h"
#include "../src/util/conf.h"
#include "../src/util/intdef.h"
void test_conf_procbuf(const char *restrict buf, const char *restrict expect_key, const char *restrict expect_val, int expect_return);
void test_conf_matchopt(struct conf_entry *restrict opts, size_t optc, const char *restrict key, int expect_index);
void test_conf_matchopt(struct conf_entry *restrict opts, usize optc, const char *restrict key, int expect_index);
void test_conf_procval_int(const char *val, u64 expect_value, int type);
void test_conf_procval_f32(const char *val, f32 expect_value);
void test_conf_procval_fstr(const char *val, u64 expect_value, int type);