owO?
This commit is contained in:
parent
d090b6bfe1
commit
0165e7d682
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/build
|
||||
/.cache
|
||||
compile_commands.json
|
||||
/test
|
33
Makefile
Normal file
33
Makefile
Normal 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
56
src/collect/gen_vec.c
Normal 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
93
src/collect/hash_map.c
Normal 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
102
src/collect/str.c
Normal 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
171
src/hash/md5.c
Normal 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);
|
||||
}
|
21
src/include/collect/gen_vec.h
Normal file
21
src/include/collect/gen_vec.h
Normal 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
|
33
src/include/collect/hash_map.h
Normal file
33
src/include/collect/hash_map.h
Normal 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
42
src/include/collect/str.h
Normal 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
22
src/include/hash/md5.h
Normal 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
32
src/include/iter.h
Normal 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
|
||||
|
|
@ -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
29
src/include/mcutil.h
Normal 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
34
src/include/result.h
Normal 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
|
Loading…
Reference in New Issue
Block a user