This commit is contained in:
Gvidas Juknevičius 2025-01-28 23:42:26 +02:00
parent d090b6bfe1
commit 0165e7d682
Signed by: MCorange
GPG Key ID: 12B1346D720B7FBB
15 changed files with 688 additions and 2 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/build
/.cache
compile_commands.json
/test

33
Makefile Normal file
View File

@ -0,0 +1,33 @@
# Literaly only need thos so i can get a compile_commands.json so my clangd lsp stops yelling at me
OUTD ?= ./build
CC = gcc
LD = gcc
AR = ar
# -fblocks
CCARGS = -fpic -Wall -O3 -Wall -Isrc/include
LDARGS =
# -lBlocksRuntime
srcs = $(wildcard src/**/*.c) $(wildcard src/*.c)
objs = $(patsubst src/%.c,$(OUTD)/obj/%.o,$(srcs))
# $(OUTD)/libmcutil.so
all: $(objs) $(OUTD)/libmcutil.a
compiledb -n make
$(OUTD)/libmcutil.so: $(objs)
$(LD) -o $@ $^ -shared $(LDARGS)
$(OUTD)/libmcutil.a: $(objs)
$(AR) rcs $@ $^
build/obj/%.o: src/%.c
mkdir -p $(dir $@)
$(CC) -c -o $@ $< $(CCARGS)

56
src/collect/gen_vec.c Normal file
View File

@ -0,0 +1,56 @@
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "mcutil.h"
#include "collect/gen_vec.h"
MCU_API void mcu_gen_vec_init(gen_vec_t* gv) {
gv->inner = MCU_ALLOC(sizeof(void*)*MCU_GEN_VEC_INITIAL_SIZE);
gv->capacity = MCU_GEN_VEC_INITIAL_SIZE;
}
MCU_API void mcu_gen_vec_insert_front(gen_vec_t* gv, void* data) {
assert(gv && "Null ptr passed as gen_vec_t");
if (!gv->inner) mcu_gen_vec_init(gv);
if (gv->count == gv->capacity) {
gv->inner = MCU_REALLOC(gv->inner, (gv->capacity * sizeof(void*)) * 2);
gv->capacity *= 2;
}
size_t count = sizeof(void*)*gv->count;
void* tmp = MCU_ALLOC(count);
memcpy(tmp, gv->inner, count);
memcpy(gv->inner + sizeof(void*), tmp, count);
gv->inner[0] = data;
MCU_FREE(tmp);
}
MCU_API void mcu_gen_vec_insert_back(gen_vec_t* gv, void* data) {
assert(gv && "Null ptr passed as gen_vec_t");
if (!gv->inner) mcu_gen_vec_init(gv);
if (gv->count == gv->capacity) {
gv->inner = MCU_REALLOC(gv->inner, (gv->capacity * sizeof(void*)) * 2);
gv->capacity *= 2;
}
gv->inner[gv->count++] = data;
}
MCU_API void* mcu_gen_vec_remove_back(gen_vec_t *gv) {
assert(gv && "Null ptr passed as gen_vec_t");
if (gv->count == 0) return NULL;
return gv->inner[gv->count--];
}
MCU_API void* mcu_gen_vec_remove_front(gen_vec_t *gv) {
assert(gv && "Null ptr passed as gen_vec_t");
if (gv->count == 0) return NULL;
void* data = gv->inner[0];
size_t count = sizeof(void*)*gv->count;
void* tmp = MCU_ALLOC(count);
memcpy(tmp, gv->inner, count);
memcpy(gv->inner - sizeof(void*), tmp, count);
MCU_FREE(tmp);
gv->count--;
return data;
}

93
src/collect/hash_map.c Normal file
View File

@ -0,0 +1,93 @@
#include "collect/hash_map.h"
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "mcutil.h"
#include "hash/md5.h"
MCU_API mcu_hash_map_t mcu_hm_new() {
return (mcu_hash_map_t){
.nodes = MCU_ALLOC(sizeof(mcu_hash_map_node_t)),
};
}
MCU_API void _mcu_hm_insert(mcu_hash_map_t* hm, const void* key, const size_t key_len, const void* value) {
mcu_md5_context ctx = {0};
mcu_md5_init(&ctx);
mcu_md5_digest(&ctx, (void*)key, key_len);
uint8_t key_res[16];
mcu_md5_output(&ctx, key_res);
mcu_hash_map_node_t* node = hm->nodes;
while (true) {
if (!node->next) {
node->next = MCU_ALLOC(sizeof(mcu_hash_map_node_t));
node->next->next = NULL;
memcpy(node->next->key, key_res, 16);
node->next->value = (void*)value;
return;
}
node = node->next;
}
}
MCU_API void* _mcu_hm_get(mcu_hash_map_t* hm, const void* key, const size_t key_len) {
mcu_md5_context ctx = {0};
mcu_md5_init(&ctx);
mcu_md5_digest(&ctx, (void*)key, key_len);
uint8_t key_res[16];
mcu_md5_output(&ctx, key_res);
mcu_hash_map_node_t* node = hm->nodes;
while (true) {
if (memcmp(node->key, key_res, 16) == 0) {
return node->value;
} else {
if (!node->next) return NULL;
node = node->next;
}
}
}
MCU_API void* _mcu_hm_remove(mcu_hash_map_t* hm, const void* key, const size_t key_len) {
mcu_md5_context ctx = {0};
mcu_md5_init(&ctx);
mcu_md5_digest(&ctx, (void*)key, key_len);
uint8_t key_res[16];
mcu_md5_output(&ctx, key_res);
mcu_hash_map_node_t* node = hm->nodes;
mcu_hash_map_node_t* prev = hm->nodes;
while (true) {
if (memcmp(node->key, key_res, 16) == 0) {
void* val = node->value;
prev->next = node->next;
return val;
} else {
if (!node->next) return NULL;
prev = node;
node = node->next;
}
}
}
MCU_API void mcu_free(mcu_hash_map_t* hm) {
mcu_hash_map_node_t* node = hm->nodes;
while (true) {
if (node->next) return;
MCU_FREE(node);
node = node->next;
}
}
MCU_API void mcu_free_all(mcu_hash_map_t* hm) {
mcu_hash_map_node_t* node = hm->nodes;
while (true) {
if (node->next) return;
MCU_FREE(node);
MCU_FREE(node->value);
node = node->next;
}
}

102
src/collect/str.c Normal file
View File

@ -0,0 +1,102 @@
#include "str.h"
#include "mcutil.h"
MCU_API mcu_str_t mcu_str_new(const char* str) {
size_t len = strlen(str);
char* buf = MCU_ALLOC(len*sizeof(char)*2);
memcpy(buf, str, len*sizeof(char));
return (mcu_str_t){
.inner = buf,
._null = 0,
.cap = len * 2,
.len = len,
};
}
MCU_API void mcu_str_append(mcu_str_t* to, const mcu_str_t* from) {
if (to->len + from->len >= to->cap) {
to->inner = MCU_REALLOC(to->inner, (to->len + from->len) * 2);
}
memcpy(to->inner + (to->len * sizeof(char)), from->inner, from->len);
}
/// Strip the whitespace from the front of the string
MCU_API void mcu_str_trim_front(mcu_str_t* str) {
size_t removed_count = 0;
for (size_t i = 0; i < str->len; i++) {
if (
str->inner[i] == ' ' |
str->inner[i] == '\t' |
str->inner[i] == '\r' |
str->inner[i] == '\n'
) {
removed_count += 1;
} else {
break;
}
}
memcpy(
str->inner,
str->inner + (sizeof(char) * removed_count),
str->len - removed_count
);
str->len -= removed_count;
}
/// Strip the whitespace from the front of the string
MCU_API void mcu_str_trim_end(mcu_str_t* str) {
for (size_t i = str->len - 1; i >= 0; i--) {
if (
str->inner[i] == ' ' |
str->inner[i] == '\t' |
str->inner[i] == '\r' |
str->inner[i] == '\n'
) {
str->len -= 1;
str->inner[i] = '\0';
} else {
break;
}
}
}
/// Strip the whitespace from the front and end of the string
MCU_API void mcu_str_trim(mcu_str_t* str) {
mcu_str_trim_front(str);
mcu_str_trim_end(str);
}
MCU_API void mcu_str_replace(mcu_str_t* str, const mcu_str_t* from, const mcu_str_t* to) {
for (size_t i = 0; i < str->len; i++) {
if (str->inner[i] == from->inner[0]) continue;
for (size_t ii = 0; ii < from->len; ii++) {
if (i + ii > str->len) break;
if (str->inner[i + ii] == from->inner[ii]) {
if (ii != from->len - 1) continue;
str->inner = MCU_REALLOC(str->inner,
str->len + (
(to->len - from->len) > 0 ?
(to->len - from->len) :
0
));
memcpy(
str->inner + ((i + to->len) * sizeof(char)),
str->inner + ((i + from->len) * sizeof(char)),
(str->len - i - from->len)
);
memcpy(
str->inner + i,
from->inner,
from->len
);
return;
} else {
break;
}
}
}
}

171
src/hash/md5.c Normal file
View File

@ -0,0 +1,171 @@
// Taken from https://breder.org/md5-implementation
// Author header continues below
// MD5 (Message-Digest Algorithm 5)
// Copyright Victor Breder 2024
// SPDX-License-Identifier: MIT
// Implemented from reference RFC 1321 available at
// <https://www.ietf.org/rfc/rfc1321.txt>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "hash/md5.h"
// from RFC 1321, Section 3.4:
#define F(X, Y, Z) (((X) & (Y)) | ((~(X)) & (Z)))
#define G(X, Y, Z) (((X) & (Z)) | (Y & (~(Z))))
#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
#define I(X, Y, Z) ((Y) ^ ((X) | (~(Z))))
static
uint32_t rotl(uint32_t x, int s) { return (x << s) | (x >> (32 - s)); }
#define STEP(OP, a, b, c, d, k, s, i) do{ \
a = b + rotl(a + OP(b, c, d) + X[k] + i, s); \
}while(0)
#define TO_I32(x,i) ((x[i]) | (x[i+1]<<8) | (x[i+2]<<16) | (x[i+3]<<24))
static
void mcu_md5_block(mcu_md5_context* ctx, const uint8_t m[64]) {
assert(ctx != NULL);
uint32_t X[16] = {
TO_I32(m,0), TO_I32(m,4), TO_I32(m,8), TO_I32(m,12),
TO_I32(m,16), TO_I32(m,20), TO_I32(m,24), TO_I32(m,28),
TO_I32(m,32), TO_I32(m,36), TO_I32(m,40), TO_I32(m,44),
TO_I32(m,48), TO_I32(m,52), TO_I32(m,56), TO_I32(m,60)
};
uint32_t a = ctx->a;
uint32_t b = ctx->b;
uint32_t c = ctx->c;
uint32_t d = ctx->d;
STEP(F, a, b, c, d, 0, 7, 0xd76aa478);
STEP(F, d, a, b, c, 1, 12, 0xe8c7b756);
STEP(F, c, d, a, b, 2, 17, 0x242070db);
STEP(F, b, c, d, a, 3, 22, 0xc1bdceee);
STEP(F, a, b, c, d, 4, 7, 0xf57c0faf);
STEP(F, d, a, b, c, 5, 12, 0x4787c62a);
STEP(F, c, d, a, b, 6, 17, 0xa8304613);
STEP(F, b, c, d, a, 7, 22, 0xfd469501);
STEP(F, a, b, c, d, 8, 7, 0x698098d8);
STEP(F, d, a, b, c, 9, 12, 0x8b44f7af);
STEP(F, c, d, a, b, 10, 17, 0xffff5bb1);
STEP(F, b, c, d, a, 11, 22, 0x895cd7be);
STEP(F, a, b, c, d, 12, 7, 0x6b901122);
STEP(F, d, a, b, c, 13, 12, 0xfd987193);
STEP(F, c, d, a, b, 14, 17, 0xa679438e);
STEP(F, b, c, d, a, 15, 22, 0x49b40821);
STEP(G, a, b, c, d, 1, 5, 0xf61e2562);
STEP(G, d, a, b, c, 6, 9, 0xc040b340);
STEP(G, c, d, a, b, 11, 14, 0x265e5a51);
STEP(G, b, c, d, a, 0, 20, 0xe9b6c7aa);
STEP(G, a, b, c, d, 5, 5, 0xd62f105d);
STEP(G, d, a, b, c, 10, 9, 0x02441453);
STEP(G, c, d, a, b, 15, 14, 0xd8a1e681);
STEP(G, b, c, d, a, 4, 20, 0xe7d3fbc8);
STEP(G, a, b, c, d, 9, 5, 0x21e1cde6);
STEP(G, d, a, b, c, 14, 9, 0xc33707d6);
STEP(G, c, d, a, b, 3, 14, 0xf4d50d87);
STEP(G, b, c, d, a, 8, 20, 0x455a14ed);
STEP(G, a, b, c, d, 13, 5, 0xa9e3e905);
STEP(G, d, a, b, c, 2, 9, 0xfcefa3f8);
STEP(G, c, d, a, b, 7, 14, 0x676f02d9);
STEP(G, b, c, d, a, 12, 20, 0x8d2a4c8a);
STEP(H, a, b, c, d, 5, 4, 0xfffa3942);
STEP(H, d, a, b, c, 8, 11, 0x8771f681);
STEP(H, c, d, a, b, 11, 16, 0x6d9d6122);
STEP(H, b, c, d, a, 14, 23, 0xfde5380c);
STEP(H, a, b, c, d, 1, 4, 0xa4beea44);
STEP(H, d, a, b, c, 4, 11, 0x4bdecfa9);
STEP(H, c, d, a, b, 7, 16, 0xf6bb4b60);
STEP(H, b, c, d, a, 10, 23, 0xbebfbc70);
STEP(H, a, b, c, d, 13, 4, 0x289b7ec6);
STEP(H, d, a, b, c, 0, 11, 0xeaa127fa);
STEP(H, c, d, a, b, 3, 16, 0xd4ef3085);
STEP(H, b, c, d, a, 6, 23, 0x04881d05);
STEP(H, a, b, c, d, 9, 4, 0xd9d4d039);
STEP(H, d, a, b, c, 12, 11, 0xe6db99e5);
STEP(H, c, d, a, b, 15, 16, 0x1fa27cf8);
STEP(H, b, c, d, a, 2, 23, 0xc4ac5665);
STEP(I, a, b, c, d, 0, 6, 0xf4292244);
STEP(I, d, a, b, c, 7, 10, 0x432aff97);
STEP(I, c, d, a, b, 14, 15, 0xab9423a7);
STEP(I, b, c, d, a, 5, 21, 0xfc93a039);
STEP(I, a, b, c, d, 12, 6, 0x655b59c3);
STEP(I, d, a, b, c, 3, 10, 0x8f0ccc92);
STEP(I, c, d, a, b, 10, 15, 0xffeff47d);
STEP(I, b, c, d, a, 1, 21, 0x85845dd1);
STEP(I, a, b, c, d, 8, 6, 0x6fa87e4f);
STEP(I, d, a, b, c, 15, 10, 0xfe2ce6e0);
STEP(I, c, d, a, b, 6, 15, 0xa3014314);
STEP(I, b, c, d, a, 13, 21, 0x4e0811a1);
STEP(I, a, b, c, d, 4, 6, 0xf7537e82);
STEP(I, d, a, b, c, 11, 10, 0xbd3af235);
STEP(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
STEP(I, b, c, d, a, 9, 21, 0xeb86d391);
ctx->a += a;
ctx->b += b;
ctx->c += c;
ctx->d += d;
memset(X, 0, sizeof(X));
}
void mcu_md5_init(mcu_md5_context* ctx) {
assert(ctx != NULL);
memset(ctx, 0, sizeof(mcu_md5_context));
// initialization values from RFC 1321, Section 3.3:
ctx->a = 0x67452301;
ctx->b = 0xEFCDAB89;
ctx->c = 0x98BADCFE;
ctx->d = 0x10325476;
}
#define TO_U8(x,o,i) do{ \
o[i] = (x) & 0xFF; \
o[i+1] = ((x) >> 8) & 0xFF; \
o[i+2] = ((x) >> 16) & 0xFF; \
o[i+3] = ((x) >> 24) & 0xFF; }while(0)
void mcu_md5_digest(mcu_md5_context* ctx, void* buffer, size_t size) {
uint8_t* bytes = (uint8_t*)buffer;
uint64_t message_bits = size * 8;
ssize_t rem_size = size;
while (rem_size > 64) {
mcu_md5_block(ctx, bytes);
bytes += 64;
rem_size -= 64;
}
uint8_t scratch[64];
memset(scratch, 0, 64);
memcpy(scratch, bytes, rem_size);
if (rem_size == 64) {
mcu_md5_block(ctx, scratch);
memset(scratch, 0, 64);
scratch[0] = 0x80;
} else {
scratch[rem_size] = 0x80;
if (64 - (rem_size + 1) < 8) {
mcu_md5_block(ctx, scratch);
memset(scratch, 0, 64);
}
}
TO_U8(message_bits, scratch, 56);
TO_U8(message_bits>>32, scratch, 60);
mcu_md5_block(ctx, scratch);
memset(scratch, 0x00, 64);
}
void mcu_md5_output(mcu_md5_context* ctx, uint8_t out[16]) {
TO_U8(ctx->a, out, 0);
TO_U8(ctx->b, out, 4);
TO_U8(ctx->c, out, 8);
TO_U8(ctx->d, out, 12);
}

View File

@ -0,0 +1,21 @@
#ifndef _H_MCUTIL_COLLEC_GEN_VEC
#define _H_MCUTIL_COLLEC_GEN_VEC
#include "mcutil.h"
#include <stddef.h>
#define MCU_GEN_VEC_INITIAL_SIZE 32
typedef struct gen_vec_s {
void** inner;
size_t count;
size_t capacity;
} gen_vec_t;
MCU_API void mcu_gen_vec_insert_front(gen_vec_t* gv, void* data);
MCU_API void mcu_gen_vec_insert_back(gen_vec_t* gv, void* data);
MCU_API void* mcu_gen_vec_remove_back(gen_vec_t *gv);
MCU_API void* mcu_gen_vec_remove_front(gen_vec_t *gv);
#endif

View File

@ -0,0 +1,33 @@
#ifndef _H_MCU_COLLECT_HASH_MAP
#define _H_MCU_COLLECT_HASH_MAP
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "mcutil.h"
typedef struct mcu_hash_map_node_s {
uint8_t key[16];
void* value;
struct mcu_hash_map_node_s* next;
} mcu_hash_map_node_t;
typedef struct mcu_hash_map_s {
mcu_hash_map_node_t* nodes;
} mcu_hash_map_t;
#define mcu_hm_insert(hm, key, value) _mcu_hm_insert((hm), (key), (const size_t)sizeof(key), (value));
#define mcu_hm_get(hm, key) _mcu_hm_insert((hm), (key), (const size_t)sizeof(key));
#define mcu_hm_remove(hm, key) _mcu_hm_insert((hm), (key), (const size_t)sizeof(key));
MCU_API mcu_hash_map_t mcu_hm_new();
MCU_API void _mcu_hm_insert(mcu_hash_map_t* hm, const void* key, const size_t key_len, const void* value);
MCU_API void* _mcu_hm_get (mcu_hash_map_t* hm, const void* key, const size_t key_len);
MCU_API void* _mcu_hm_remove(mcu_hash_map_t* hm, const void* key, const size_t key_len);
/// Frees the hashmap but not the pointers inside the values
MCU_API void mcu_free(mcu_hash_map_t* hm);
/// Frees the hashmap and the pointers inside the values
MCU_API void mcu_free_all(mcu_hash_map_t* hm);
#endif // _H_MCU_COLLECT_HASH_MAP

42
src/include/collect/str.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef _H_MCU_STR
#define _H_MCU_STR
#include "mcutil.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define mcu_str_append_cstr(to, from) mc_str_append((to), mc_str_new(from))
#define mcu_str_free(str) MCU_FREE((str)->inner)
typedef struct mcu_str_s {
char* inner;
uint8_t _null;
size_t len;
size_t cap;
} mcu_str_t;
/// Creates a new owned string
/// You can just use printf as normal with this cause you can safely cast this into char*
MCU_API mcu_str_t mcu_str_new(const char* str);
/// Append the string 'from' onto string 'to'
MCU_API void mcu_str_append(mcu_str_t* to, const mcu_str_t* from);
/// Strip the whitespace from the front of the string
MCU_API void mcu_str_trim_front(mcu_str_t* str);
/// Strip the whitespace from the front of the string
MCU_API void mcu_str_trim_end(mcu_str_t* str);
/// Strip the whitespace from the front and end of the string
MCU_API void mcu_str_trim(mcu_str_t* str);
/// Replace string 'from' to string 'to'
/// Hopefully this works, i hope
MCU_API void mcu_str_replace(mcu_str_t* str, const mcu_str_t* from, const mcu_str_t* to);
#endif // _H_MCU_STR

22
src/include/hash/md5.h Normal file
View File

@ -0,0 +1,22 @@
// Taken from https://breder.org/md5-implementation
// Author header continues below
// MD5 (Message-Digest Algorithm 5)
// Copyright Victor Breder 2024
// SPDX-License-Identifier: MIT
#ifndef _H_MCU_HASH_MD5
#define _H_MCU_HASH_MD5
#include <stddef.h>
#include <stdint.h>
typedef struct {
uint32_t a, b, c, d;
} mcu_md5_context;
void mcu_md5_init(mcu_md5_context* ctx);
void mcu_md5_digest(mcu_md5_context* ctx, void* buffer, size_t size);
void mcu_md5_output(mcu_md5_context* ctx, uint8_t out[16]);
#endif // _H_MCU_HASH_MD5

32
src/include/iter.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef _H_MCU_ITER
#define _H_MCU_ITER
#define mcu_for_char_in_str(str, var_name, body) for (int __mcu_i; __mcu_i < (str)->len; __mcu_i++) { \
char var_name = (str)->inner[__mcu_i]; \
{body} \
}
/// The cast will always have an appended pointer
#define mcu_for_item_in_vec(vec, var_name, cast, body) for (int __mcu_il __mcu_i < (vec)->count; __mcu_i++) { \
cast* var_name = (cast*)(vec)-inner[__mcu_i]; \
{body} \
}
/// If we want to have the keys actual value too we would have to store it in the collection, this is not needed, usually?
/// The cast will always have an appended pointer
#define mcu_for_value_in_hash_map(hm, var_name, cast, body) { \
mcu_hash_map_node_t* node = (hm)->nodes; \
while (1) { \
cast* var_name = (cast*)node->value; \
{body} \
if (!node->next) break; \
node = node->next; \
} \
}
#endif // _H_MCU_ITER

View File

@ -1,5 +1,5 @@
#ifndef _H_MCORANGE_LAMBDA
#define _H_MCORANGE_LAMBDA
#ifndef _H_MCUTIL_LAMBDA
#define _H_MCUTIL_LAMBDA
#if defined(_MSC_VER) && !defined(__MC_LMBD_DEF)
#define __MC_LMBD_DEF

29
src/include/mcutil.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef _H_MCUTIL
#define _H_MCUTIL
// https://fdiv.net/2015/10/08/emulating-defer-c-clang-or-gccblocks
#ifndef MCU_ALLOC
#define MCU_ALLOC malloc
#endif
#ifndef MCU_REALLOC
#define MCU_REALLOC realloc
#endif
#ifndef MCU_FREE
#define MCU_FREE free
#endif
#if defined(_MSC_VER)
#define MCU_API __declspec(dllexport)
#elif defined(__GNUC__)
#define MCU_API __attribute__((visibility("default")))
#else
#define MCU_API
#pragma warning Unknown dynamic link import/export semantics.
#endif
#endif

34
src/include/result.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _H_MCU_RESULT
#define _H_MCU_RESULT
#include "str.h"
#include <stdbool.h>
typedef struct mcu_error_s {
mcu_str_t reason;
const char* file;
int line;
} mcu_error_t;
typedef struct mcu_result_s {
union {
void* res;
mcu_error_t err;
};
bool is_err;
} mcu_result_t;
#define Ok(val) (mcu_result_t){ .is_err=false, .res = val }
#define Err(_reason) (mcu_result_t){ .is_err=true, .err = (mcu_error_t){ .reason=mcu_str_new(_reason), .file=__FILE__, .line=__LINE__ }}
#define mcu_result_unwrap(result) ({ \
if ((result).is_err) { \
printf("%s:%d: PANIC: Unwrapped on error value%s\n", \
(result).err.file, (result).err.line, \
(result).err.reason.inner); \
exit(1); \
}; \
(result).res; \
})
#endif // _H_MCU_RESULT

14
test.c Normal file
View File

@ -0,0 +1,14 @@
// #include "collec/gen_vec.h"
#include "result.h"
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a = 1;
mcu_result_t good = Ok(&a);
mcu_result_t bad = Err("Owo?");
mcu_result_unwrap(good);
mcu_result_unwrap(bad);
return 0;
}