Merge modules into one Makefile due to cross-dependencies
This commit is contained in:
parent
405818ad0d
commit
7b6ee47d8e
|
@ -1,9 +0,0 @@
|
||||||
[submodule "encoding/baseven"]
|
|
||||||
path = encoding/baseven
|
|
||||||
url = https://git.redxen.eu/corelibs/baseven
|
|
||||||
[submodule "llist"]
|
|
||||||
path = llist
|
|
||||||
url = https://git.redxen.eu/corelibs/llist
|
|
||||||
[submodule "dynarray"]
|
|
||||||
path = dynarray
|
|
||||||
url = https://git.redxen.eu/corelibs/dynarray
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
include config.mk
|
||||||
|
|
||||||
|
OBJ = ${SRC:.c=.o}
|
||||||
|
|
||||||
|
all: ${OBJ} ${OUT}
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
${CC} -o $@ -c ${CFLAGS} $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${OBJ} ${OUT}
|
||||||
|
|
||||||
|
ifneq (${OUT},)
|
||||||
|
${OUT}: ${OBJ}
|
||||||
|
${CC} -o "$@" ${LDFLAGS} $^
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: all clean
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Defaults
|
||||||
|
CC = clang
|
||||||
|
DEBUG = 1
|
||||||
|
STATIC = 0
|
||||||
|
|
||||||
|
LDFLAGS =
|
||||||
|
CFLAGS =\
|
||||||
|
-std=c99 \
|
||||||
|
-Weverything \
|
||||||
|
-Wno-padded \
|
||||||
|
-Wno-disabled-macro-expansion \
|
||||||
|
-pedantic
|
||||||
|
|
||||||
|
# Sources / Results
|
||||||
|
SRC =\
|
||||||
|
src/dynarray/dynarray.c \
|
||||||
|
src/llist/llist.c \
|
||||||
|
src/encoding/baseven/baseven.c \
|
||||||
|
src/types/error/error.c
|
||||||
|
|
||||||
|
LIBDIR =
|
||||||
|
LIB =\
|
||||||
|
c
|
||||||
|
|
||||||
|
INCDIR =\
|
||||||
|
src/
|
||||||
|
|
||||||
|
OUT =
|
||||||
|
|
||||||
|
# Conditionals / Appends
|
||||||
|
LDFLAGS +=\
|
||||||
|
$(addprefix -L,${LIBDIR})\
|
||||||
|
$(addprefix -l,${LIB})
|
||||||
|
|
||||||
|
CFLAGS +=\
|
||||||
|
$(addprefix -I,${INCDIR})
|
||||||
|
|
||||||
|
ifeq (${DEBUG},1)
|
||||||
|
CFLAGS += -g
|
||||||
|
else
|
||||||
|
CFLAGS += -O2 -Werror
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq (${STATIC},1)
|
||||||
|
LDFLAGS += -static
|
||||||
|
endif
|
1
dynarray
1
dynarray
|
@ -1 +0,0 @@
|
||||||
Subproject commit 12b6867f4684913b36962d0abda3ac6c7cfbc9c4
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit cc742932a2d665c0fc5b1c7d0909aee308c23988
|
|
1
llist
1
llist
|
@ -1 +0,0 @@
|
||||||
Subproject commit 2d89d5f40cde60bf5c87206268dcb810b7175740
|
|
|
@ -0,0 +1,388 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarray/dynarray.h"
|
||||||
|
|
||||||
|
#include "types/error/error.h"
|
||||||
|
|
||||||
|
#include <stdbool.h> // bool
|
||||||
|
#include <stdlib.h> // malloc() free()
|
||||||
|
#include <string.h> // memcpy()
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_export_slice (const cl_dynarray_t *, uintmax_t, uintmax_t, void *),
|
||||||
|
corelibs_dynarray_make_new (size_t, cl_dynarray_t **),
|
||||||
|
corelibs_dynarray_make_slice (const cl_dynarray_t *, uintmax_t, uintmax_t, cl_dynarray_t **),
|
||||||
|
corelibs_dynarray_free (cl_dynarray_t *),
|
||||||
|
corelibs_dynarray_mod_arr_cap (cl_dynarray_t *, uintmax_t),
|
||||||
|
corelibs_dynarray_mod_arr_lock (cl_dynarray_t *, bool),
|
||||||
|
corelibs_dynarray_mod_dat_app (cl_dynarray_t *, uintmax_t, const void *),
|
||||||
|
corelibs_dynarray_mod_dat_ins (cl_dynarray_t *, uintmax_t, uintmax_t, const void *),
|
||||||
|
corelibs_dynarray_mod_dat_rep (cl_dynarray_t *, uintmax_t, uintmax_t, const void *),
|
||||||
|
corelibs_dynarray_mod_dat_rm (cl_dynarray_t *, uintmax_t, uintmax_t),
|
||||||
|
corelibs_dynarray_get_len (const cl_dynarray_t *, uintmax_t *),
|
||||||
|
corelibs_dynarray_get_size (const cl_dynarray_t *, size_t *),
|
||||||
|
corelibs_dynarray_get_cap_len (const cl_dynarray_t *, uintmax_t *),
|
||||||
|
corelibs_dynarray_get_cap_lock (const cl_dynarray_t *, bool *),
|
||||||
|
corelibs_dynarray_cmp_data (const cl_dynarray_t *a, const cl_dynarray_t *b, bool *eq),
|
||||||
|
corelibs_dynarray_bcheck (const cl_dynarray_t *, uintmax_t, uintmax_t);
|
||||||
|
|
||||||
|
struct cl_dynarray_t {
|
||||||
|
void * addr; // Location of element
|
||||||
|
uintmax_t len; // Element count
|
||||||
|
struct {
|
||||||
|
bool lock; // Is the capacity frozen?
|
||||||
|
uintmax_t len; // Capacity
|
||||||
|
} cap;
|
||||||
|
size_t es; // Size of element
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct corelibs_dynarray_interface cl_dynarray = {
|
||||||
|
.make = {
|
||||||
|
.new = corelibs_dynarray_make_new,
|
||||||
|
.slice = corelibs_dynarray_make_slice,
|
||||||
|
},
|
||||||
|
.free = corelibs_dynarray_free,
|
||||||
|
.mod = {
|
||||||
|
.arr = {
|
||||||
|
.cap = corelibs_dynarray_mod_arr_cap,
|
||||||
|
.lock = corelibs_dynarray_mod_arr_lock,
|
||||||
|
},
|
||||||
|
.dat = {
|
||||||
|
.app = corelibs_dynarray_mod_dat_app,
|
||||||
|
.ins = corelibs_dynarray_mod_dat_ins,
|
||||||
|
.rep = corelibs_dynarray_mod_dat_rep,
|
||||||
|
.rm = corelibs_dynarray_mod_dat_rm,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.cmp = {
|
||||||
|
.data = corelibs_dynarray_cmp_data,
|
||||||
|
},
|
||||||
|
.export = {
|
||||||
|
.slice = corelibs_dynarray_export_slice,
|
||||||
|
},
|
||||||
|
.get = {
|
||||||
|
.len = corelibs_dynarray_get_len,
|
||||||
|
.size = corelibs_dynarray_get_size,
|
||||||
|
.cap = {
|
||||||
|
.len = corelibs_dynarray_get_cap_len,
|
||||||
|
.lock = corelibs_dynarray_get_cap_lock,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_make_new (size_t sbyte, cl_dynarray_t **ptr) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (ptr == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
cl_dynarray_t *new = malloc (sizeof (*new));
|
||||||
|
if (new != NULL) {
|
||||||
|
new->addr = NULL;
|
||||||
|
new->es = sbyte;
|
||||||
|
new->len = 0;
|
||||||
|
new->cap.len = 0;
|
||||||
|
new->cap.lock = false;
|
||||||
|
*ptr = new;
|
||||||
|
} else {
|
||||||
|
err = cl_error.err.mem.alloc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_make_slice (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, cl_dynarray_t **save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (save == NULL || arr == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
if (cnt == 0) {
|
||||||
|
// Don't copy anything, just make new array
|
||||||
|
return corelibs_dynarray_make_new (arr->es, save);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we slice these elements?
|
||||||
|
if (!(err = corelibs_dynarray_bcheck (arr, pos, cnt))) {
|
||||||
|
// Create new array
|
||||||
|
cl_dynarray_t *new;
|
||||||
|
if (!(err = corelibs_dynarray_make_new (arr->es, &new))) {
|
||||||
|
// Resize array to fit contents
|
||||||
|
if (!(err = corelibs_dynarray_mod_arr_cap (new, cnt))) {
|
||||||
|
// Copy contents from old array to new one
|
||||||
|
if (!(err = corelibs_dynarray_export_slice (arr, pos, cnt, new->addr))) {
|
||||||
|
new->len = cnt;
|
||||||
|
new->cap.lock = arr->cap.lock; // Inherit capacity lock
|
||||||
|
*save = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (err) corelibs_dynarray_free (new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_free (cl_dynarray_t *arr) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
if (!(err = corelibs_dynarray_mod_arr_cap (arr, 0))) {
|
||||||
|
free (arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_mod_arr_cap (cl_dynarray_t *arr, uintmax_t len) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
if (len == 0) {
|
||||||
|
free (arr->addr);
|
||||||
|
arr->cap.len = 0;
|
||||||
|
} else if (!arr->cap.lock) {
|
||||||
|
void * reg = NULL;
|
||||||
|
const size_t nl = len * arr->es;
|
||||||
|
|
||||||
|
if (arr->addr == NULL) {
|
||||||
|
reg = malloc (nl);
|
||||||
|
} else if (arr->cap.len != len) {
|
||||||
|
reg = realloc (arr->addr, nl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg != NULL) {
|
||||||
|
arr->cap.len = len;
|
||||||
|
arr->addr = reg;
|
||||||
|
if (arr->cap.len < arr->len) arr->len = arr->cap.len; // Cut out discarded elements if resized to shorter size
|
||||||
|
} else {
|
||||||
|
err = cl_error.err.mem.alloc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = cl_error.err.data.immut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_mod_arr_lock (cl_dynarray_t *arr, bool lock) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
arr->cap.lock = lock;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_mod_dat_app (cl_dynarray_t *arr, uintmax_t cnt, const void *elem) {
|
||||||
|
return corelibs_dynarray_mod_dat_ins (arr, arr->len, cnt, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_mod_dat_ins (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, const void *elem) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL || elem == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
// Resize array to fit inserted objects
|
||||||
|
if (!(err = corelibs_dynarray_mod_arr_cap (arr, ((arr->cap.len < pos) ? pos : arr->cap.len) + cnt))) {
|
||||||
|
// CHECKPOINT: From here it is safe to commit changes as required conditions are met
|
||||||
|
// and no errors should be possible (unless you have some special hardware)
|
||||||
|
|
||||||
|
uintmax_t clen = arr->len; // Lenght pre-resize
|
||||||
|
|
||||||
|
if (arr->len < pos) arr->len = pos;
|
||||||
|
arr->len += cnt;
|
||||||
|
|
||||||
|
uintptr_t src, // Source of copy address without pointer aritmethic
|
||||||
|
dest; // Destination to copy to
|
||||||
|
size_t bcnt; // Amount of bytes to copy
|
||||||
|
|
||||||
|
// If we are inserting and not appending
|
||||||
|
if (pos < clen) {
|
||||||
|
src = (uintptr_t) arr->addr + (pos * arr->es);
|
||||||
|
dest = src + (cnt * arr->es);
|
||||||
|
bcnt = (clen - pos) * arr->es;
|
||||||
|
memmove ((void *) dest, (void *) src, bcnt); // Shift bytes to after insertion region
|
||||||
|
}
|
||||||
|
|
||||||
|
src = (uintptr_t) elem;
|
||||||
|
dest = (uintptr_t) arr->addr + (pos * arr->es);
|
||||||
|
bcnt = cnt * arr->es;
|
||||||
|
memcpy ((void *) dest, (void *) src, bcnt); // No overlaps possible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_mod_dat_rep (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, const void *elem) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL || elem == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
if (corelibs_dynarray_bcheck (arr, pos, cnt) == cl_error.err.mem.oob) {
|
||||||
|
// Resize array to fit new elements
|
||||||
|
err = corelibs_dynarray_mod_arr_cap (arr, pos + cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
// CHECKPOINT: From here it is safe to commit changes as required conditions are met
|
||||||
|
// and no errors should be possible (unless you have some special hardware)
|
||||||
|
|
||||||
|
uintptr_t src, // Source of copy address without pointer aritmethic
|
||||||
|
dest; // Destination to copy to
|
||||||
|
size_t bcnt; // Amount of bytes to copy
|
||||||
|
|
||||||
|
src = (uintptr_t) elem;
|
||||||
|
dest = (uintptr_t) arr->addr + (pos * arr->es);
|
||||||
|
bcnt = cnt * arr->es;
|
||||||
|
memcpy ((void *) dest, (void *) src, bcnt);
|
||||||
|
if (arr->len < pos + cnt) arr->len = pos + cnt; // Set length at end of replacement if not already same or longer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_mod_dat_rm (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
// Are we removing elements we don't have?
|
||||||
|
if (!(err = corelibs_dynarray_bcheck (arr, pos, cnt))) {
|
||||||
|
// Allocate intermediate buffer
|
||||||
|
void *tbuf = malloc (arr->es * arr->len);
|
||||||
|
if (tbuf != NULL) {
|
||||||
|
// CHECKPOINT: From here it is safe to commit changes as required conditions are met
|
||||||
|
// and no errors should be possible (unless you have some special hardware)
|
||||||
|
|
||||||
|
arr->len -= cnt; // We remove cnt elements from array
|
||||||
|
|
||||||
|
uintptr_t src, // Source of copy address without pointer aritmethic
|
||||||
|
dest; // Destination to copy to
|
||||||
|
size_t bcnt; // Amount of bytes to copy
|
||||||
|
|
||||||
|
dest = (uintptr_t) tbuf;
|
||||||
|
src = (uintptr_t) arr->addr;
|
||||||
|
bcnt = arr->len * arr->es;
|
||||||
|
memcpy ((void *) dest, (void *) src, bcnt); // Copy current contents up to arr->len to intermediate buffer
|
||||||
|
|
||||||
|
// If tail is the only thing removed, don't copy back
|
||||||
|
if (pos + cnt != arr->len) {
|
||||||
|
// Copy back slice and overwrite region removed
|
||||||
|
dest += pos * arr->es;
|
||||||
|
src += (pos + cnt) * arr->es;
|
||||||
|
bcnt -= pos * arr->es;
|
||||||
|
memcpy ((void *) dest, (void *) src, bcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (arr->addr);
|
||||||
|
arr->addr = tbuf; // Swap buffers and free previous one
|
||||||
|
} else {
|
||||||
|
err = cl_error.err.mem.alloc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_export_slice (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, void *save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err || cnt != 0) {
|
||||||
|
// Do we have the requested slice?
|
||||||
|
if (!(err = corelibs_dynarray_bcheck (arr, pos, cnt))) {
|
||||||
|
uintptr_t src, // Source of copy address without pointer aritmethic
|
||||||
|
dest; // Destination to copy to
|
||||||
|
size_t bcnt; // Amount of bytes to copy
|
||||||
|
|
||||||
|
src = (uintptr_t) arr->addr + (arr->es * pos);
|
||||||
|
dest = (uintptr_t) save;
|
||||||
|
bcnt = arr->es * cnt;
|
||||||
|
memcpy ((void *) dest, (void *) src, bcnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_get_len (const cl_dynarray_t *arr, uintmax_t *save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
*save = arr->len;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_get_cap_len (const cl_dynarray_t *arr, uintmax_t *save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
*save = arr->cap.len;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_get_cap_lock (const cl_dynarray_t *arr, bool *save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
*save = arr->cap.lock;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_get_size (const cl_dynarray_t *arr, size_t *save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
*save = arr->es;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_cmp_data (const cl_dynarray_t *a, const cl_dynarray_t *b, bool *eq) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (a == NULL || b == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (a->es != b->es) err = cl_error.err.data.incompat;
|
||||||
|
if (!err) {
|
||||||
|
if (a->len != b->len) {
|
||||||
|
*eq = false;
|
||||||
|
} else {
|
||||||
|
*eq = (memcmp (a->addr, b->addr, a->len) != 0) ? false : true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private functions
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_dynarray_bcheck (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t len) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (arr == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (arr->cap.len < pos + len) err = cl_error.err.mem.oob;
|
||||||
|
return err;
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "types/error/error.h"
|
||||||
|
|
||||||
|
#include <stdbool.h> // bool
|
||||||
|
#include <stddef.h> // size_t
|
||||||
|
#include <stdint.h> // uintmax_t
|
||||||
|
|
||||||
|
#ifndef CORELIBS_GUARD_DYNARRAY
|
||||||
|
#define CORELIBS_GUARD_DYNARRAY
|
||||||
|
|
||||||
|
typedef struct cl_dynarray_t cl_dynarray_t;
|
||||||
|
|
||||||
|
struct corelibs_dynarray_interface {
|
||||||
|
|
||||||
|
// Makers
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const new) (size_t sbyte, cl_dynarray_t **ptr), // New - allocate new array
|
||||||
|
(*const slice) (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t len, cl_dynarray_t **ssave); // Slicer - gets a slice of a array
|
||||||
|
} make;
|
||||||
|
|
||||||
|
// Free
|
||||||
|
cl_error_t (*const free) (cl_dynarray_t *arr);
|
||||||
|
|
||||||
|
// Modifiers
|
||||||
|
const struct {
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const app) (cl_dynarray_t *arr, uintmax_t cnt, const void *elem), // Appender - Adds element at end of array
|
||||||
|
(*const ins) (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, const void *elem), // Inserter - Adds element at position, pushing next element 1 position further
|
||||||
|
(*const rep) (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, const void *elem), // Replacer - Replaces array item or creates it if not existent
|
||||||
|
(*const rm) (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt); // Remover - removes element from array
|
||||||
|
} dat;
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const cap) (cl_dynarray_t *ptr, uintmax_t len), // Capacity
|
||||||
|
(*const lock) (cl_dynarray_t *ptr, bool cap); // Capacity lock (dynamic / static capacity)
|
||||||
|
} arr;
|
||||||
|
|
||||||
|
} mod;
|
||||||
|
|
||||||
|
// Fetchers
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const len) (const cl_dynarray_t *arr, uintmax_t *save),
|
||||||
|
(*const size) (const cl_dynarray_t *arr, size_t *save);
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const len) (const cl_dynarray_t *arr, uintmax_t *save),
|
||||||
|
(*const lock) (const cl_dynarray_t *arr, bool *save);
|
||||||
|
} cap;
|
||||||
|
} get;
|
||||||
|
|
||||||
|
// Comparers
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const data) (const cl_dynarray_t *a, const cl_dynarray_t *b, bool *eq);
|
||||||
|
} cmp;
|
||||||
|
|
||||||
|
// Exporter
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const slice) (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, void *save);
|
||||||
|
} export;
|
||||||
|
};
|
||||||
|
extern const struct corelibs_dynarray_interface cl_dynarray;
|
||||||
|
|
||||||
|
#endif /* CORELIBS_GUARD_DYNARRAY */
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "encoding/baseven/baseven.h"
|
||||||
|
|
||||||
|
#include <assert.h> // assert()
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h> // bool
|
||||||
|
#include <stdio.h> // putchar()
|
||||||
|
#include <stdlib.h> // malloc() free()
|
||||||
|
|
||||||
|
#define ENCODED 8
|
||||||
|
#define DECODED 7
|
||||||
|
#define RESERVED (ENCODED - DECODED)
|
||||||
|
#define RESERVEDBIT (1 << 7)
|
||||||
|
|
||||||
|
static cl_error_t corelibs_baseven_encode (const uint8_t *, size_t, uint8_t *, size_t),
|
||||||
|
corelibs_baseven_decode (const uint8_t *, size_t, uint8_t *, size_t);
|
||||||
|
|
||||||
|
static uintmax_t corelibs_baseven_size_encoded (uintmax_t),
|
||||||
|
corelibs_baseven_size_decoded (uintmax_t);
|
||||||
|
|
||||||
|
static uint8_t corelibs_baseven_bits_first (uint8_t, uint8_t),
|
||||||
|
corelibs_baseven_bits_last (uint8_t, uint8_t);
|
||||||
|
|
||||||
|
static bool corelibs_baseven_bits_nth (uint8_t, uint8_t);
|
||||||
|
|
||||||
|
const struct corelibs_baseven_interface cl_baseven = {
|
||||||
|
.encode = corelibs_baseven_encode,
|
||||||
|
.decode = corelibs_baseven_decode,
|
||||||
|
.size = {
|
||||||
|
.decoded = corelibs_baseven_size_decoded,
|
||||||
|
.encoded = corelibs_baseven_size_encoded,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_baseven_encode (const uint8_t *src, size_t len, uint8_t *dest, size_t max) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
|
||||||
|
if (src == NULL || dest == NULL) err = cl_error.err.data.inval;
|
||||||
|
if (corelibs_baseven_size_encoded (len) > max) err = cl_error.err.mem.oob;
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
const uint8_t *const end = src + len;
|
||||||
|
|
||||||
|
uint8_t bits = 0,
|
||||||
|
last = 0;
|
||||||
|
|
||||||
|
while (src < end) {
|
||||||
|
const uint8_t rev = RESERVED, keep = DECODED;
|
||||||
|
|
||||||
|
last |= corelibs_baseven_bits_first (*src, rev) >> (bits + rev); // Save first bit into the last byte to append to byte series
|
||||||
|
*dest = corelibs_baseven_bits_last (*src, keep) | RESERVEDBIT; // Write the kept bytes in the output buffer
|
||||||
|
|
||||||
|
src++;
|
||||||
|
dest++;
|
||||||
|
bits++;
|
||||||
|
|
||||||
|
if (bits == DECODED || src == end) {
|
||||||
|
*(dest++) = last | RESERVEDBIT;
|
||||||
|
|
||||||
|
bits = 0;
|
||||||
|
last = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_baseven_decode (const uint8_t *src, size_t len, uint8_t *dest, size_t max) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
|
||||||
|
if (src == NULL || dest == NULL) err = cl_error.err.data.inval;
|
||||||
|
if (corelibs_baseven_size_decoded (len) > max) err = cl_error.err.mem.oob;
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
while (1) {
|
||||||
|
const uint8_t con = ((ENCODED - 1) < len) ? (ENCODED - 1) : (uint8_t) len - 1; // Count of bytes to the extra post-encoding byte as OFFSET (8 -> 7)
|
||||||
|
|
||||||
|
for (uint8_t p = 0; p < con; p++) {
|
||||||
|
dest[p] = (uint8_t) ((corelibs_baseven_bits_nth (src[con], p + 1) << (ENCODED - 1)) // Get n-th bit from last byte and shift it to the beginning
|
||||||
|
| (src[p] ^ RESERVEDBIT) // Discard reserved bit and merge it with bit from last
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ((ENCODED - 1) < len) {
|
||||||
|
dest += con;
|
||||||
|
len -= con;
|
||||||
|
src += ENCODED;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintmax_t
|
||||||
|
corelibs_baseven_size_encoded (uintmax_t b) {
|
||||||
|
return b + ((b / DECODED) + (bool) (b % DECODED));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintmax_t
|
||||||
|
corelibs_baseven_size_decoded (uintmax_t b) {
|
||||||
|
return b - ((b / ENCODED) + (bool) (b % ENCODED));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
corelibs_baseven_bits_first (const uint8_t byte, const uint8_t cnt) {
|
||||||
|
assert (cnt < ENCODED);
|
||||||
|
const uint8_t fb = (uint8_t) ~0;
|
||||||
|
return byte & ((fb >> cnt) ^ fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
corelibs_baseven_bits_last (const uint8_t byte, const uint8_t cnt) {
|
||||||
|
assert (cnt < ENCODED);
|
||||||
|
const uint8_t fb = (uint8_t) ~0;
|
||||||
|
return byte & ((fb << cnt) ^ fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
corelibs_baseven_bits_nth (const uint8_t byte, const uint8_t index) {
|
||||||
|
assert (index < ENCODED);
|
||||||
|
uint8_t off = (ENCODED - 1) - index;
|
||||||
|
/*
|
||||||
|
* 00100000
|
||||||
|
*
|
||||||
|
* 00000001 << ((8 - 1) - 2)
|
||||||
|
* * 10000000 << (7)
|
||||||
|
* * 00100000 >> (2)
|
||||||
|
*
|
||||||
|
* 00100000 >> ((8 - 1) - 2)
|
||||||
|
* * 00000001 >> (5)
|
||||||
|
*/
|
||||||
|
return (byte & (1 << off)) >> off;
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "types/error/error.h"
|
||||||
|
|
||||||
|
#include <stdbool.h> // bool
|
||||||
|
#include <stddef.h> // size_t
|
||||||
|
#include <stdint.h> // uintmax_t
|
||||||
|
|
||||||
|
#ifndef CORELIBS_GUARD_BASEVEN
|
||||||
|
#define CORELIBS_GUARD_BASEVEN
|
||||||
|
|
||||||
|
typedef struct cl_baseven_t cl_baseven_t;
|
||||||
|
|
||||||
|
struct corelibs_baseven_interface {
|
||||||
|
cl_error_t (*const encode) (const uint8_t *src, size_t len, uint8_t *dest, size_t cap),
|
||||||
|
(*const decode) (const uint8_t *src, size_t len, uint8_t *dest, size_t cap);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
uintmax_t (*const decoded) (uintmax_t enc_size),
|
||||||
|
(*const encoded) (uintmax_t dec_size);
|
||||||
|
} size;
|
||||||
|
};
|
||||||
|
extern const struct corelibs_baseven_interface cl_baseven;
|
||||||
|
|
||||||
|
#endif /* CORELIBS_GUARD_BASEVEN */
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "llist/llist.h"
|
||||||
|
|
||||||
|
#include <stdarg.h> // va_args
|
||||||
|
#include <stdint.h> // uintmax_t
|
||||||
|
#include <stdlib.h> // malloc() free()
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_create (void *, void (*) (void *), cl_llist_t **),
|
||||||
|
corelibs_llist_link (uintmax_t, ...),
|
||||||
|
corelibs_llist_rep (cl_llist_t *, cl_llist_t *),
|
||||||
|
corelibs_llist_free_list (cl_llist_t *),
|
||||||
|
corelibs_llist_free_elem (cl_llist_t *),
|
||||||
|
corelibs_llist_free_cont (cl_llist_t *),
|
||||||
|
corelibs_llist_set_cont (cl_llist_t *, void *),
|
||||||
|
corelibs_llist_set_free (cl_llist_t *, void (*) (void *)),
|
||||||
|
corelibs_llist_get_next (const cl_llist_t *, cl_llist_t **),
|
||||||
|
corelibs_llist_get_prev (const cl_llist_t *, cl_llist_t **),
|
||||||
|
corelibs_llist_get_cont (const cl_llist_t *, void **);
|
||||||
|
|
||||||
|
static void corelibs_llist_remove (cl_llist_t *);
|
||||||
|
|
||||||
|
struct cl_llist_t {
|
||||||
|
struct cl_llist_t *next, *prev;
|
||||||
|
void * cont;
|
||||||
|
void (*free) (void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct corelibs_llist_interface const cl_llist = {
|
||||||
|
.create = corelibs_llist_create,
|
||||||
|
.link = corelibs_llist_link,
|
||||||
|
.rep = corelibs_llist_rep,
|
||||||
|
.free = {
|
||||||
|
.list = corelibs_llist_free_list,
|
||||||
|
.elem = corelibs_llist_free_elem,
|
||||||
|
.cont = corelibs_llist_free_cont,
|
||||||
|
},
|
||||||
|
.set = {
|
||||||
|
.cont = corelibs_llist_set_cont,
|
||||||
|
.free = corelibs_llist_set_free,
|
||||||
|
},
|
||||||
|
.get = {
|
||||||
|
.prev = corelibs_llist_get_prev,
|
||||||
|
.cont = corelibs_llist_get_cont,
|
||||||
|
.next = corelibs_llist_get_next,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_create (void *c, void (*const f) (void *), cl_llist_t **s) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (s == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
cl_llist_t *cur = malloc (sizeof (*cur));
|
||||||
|
if (cur != NULL) {
|
||||||
|
cur->prev = NULL;
|
||||||
|
cur->next = NULL;
|
||||||
|
cur->cont = c;
|
||||||
|
cur->free = f;
|
||||||
|
*s = cur;
|
||||||
|
} else {
|
||||||
|
err = cl_error.err.mem.alloc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_free_list (cl_llist_t *l) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (l == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
// Free previous elements if we have any
|
||||||
|
if (l->prev != NULL) {
|
||||||
|
for (cl_llist_t *p = l->prev; p != NULL;) {
|
||||||
|
cl_llist_t *c = p;
|
||||||
|
p = p->prev;
|
||||||
|
corelibs_llist_remove (c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free current and next elements
|
||||||
|
for (cl_llist_t *p = l; p != NULL;) {
|
||||||
|
cl_llist_t *c = p;
|
||||||
|
p = p->next;
|
||||||
|
corelibs_llist_remove (c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_free_elem (cl_llist_t *l) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (l == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
corelibs_llist_remove (l);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_free_cont (cl_llist_t *l) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (l == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
if (l->free != NULL) l->free (l->cont);
|
||||||
|
l->free = NULL;
|
||||||
|
l->cont = NULL;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_link (uintmax_t cnt, ...) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (cnt <= 1) err = cl_error.err.args.mis;
|
||||||
|
if (!err) {
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, cnt);
|
||||||
|
|
||||||
|
uintmax_t ccnt = 0;
|
||||||
|
cl_llist_t *a = NULL, *b = NULL;
|
||||||
|
while (ccnt < cnt) {
|
||||||
|
a = b;
|
||||||
|
b = va_arg (ap, cl_llist_t *);
|
||||||
|
if (ccnt < 1) continue; // Fill at least first 2 slots
|
||||||
|
|
||||||
|
if (a != NULL) a->next = b;
|
||||||
|
if (b != NULL) b->prev = a;
|
||||||
|
|
||||||
|
ccnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_rep (cl_llist_t *dest, cl_llist_t *src) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (src == NULL || dest == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
if (dest->prev != NULL) dest->prev->next = src;
|
||||||
|
if (dest->next != NULL) dest->next->prev = src;
|
||||||
|
corelibs_llist_free_elem (dest);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_get_next (const cl_llist_t *e, cl_llist_t **save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (e == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (e->next == NULL) err = cl_error.err.undef;
|
||||||
|
if (!err) {
|
||||||
|
*save = e->next;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_get_prev (const cl_llist_t *e, cl_llist_t **save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (e == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (e->prev == NULL) err = cl_error.err.undef;
|
||||||
|
if (!err) {
|
||||||
|
*save = e->prev;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_get_cont (const cl_llist_t *e, void **save) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (e == NULL || save == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
*save = e->cont;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_set_cont (cl_llist_t *e, void *i) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (e == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
e->cont = i;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl_error_t
|
||||||
|
corelibs_llist_set_free (cl_llist_t *e, void (*const f) (void *)) {
|
||||||
|
cl_error_t err = cl_error.err.ok;
|
||||||
|
if (e == NULL) err = cl_error.err.mem.null;
|
||||||
|
if (!err) {
|
||||||
|
e->free = f;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private function
|
||||||
|
static void
|
||||||
|
corelibs_llist_remove (cl_llist_t *e) {
|
||||||
|
corelibs_llist_link (2, e->prev, e->next);
|
||||||
|
if (e->free != NULL) e->free (e->cont);
|
||||||
|
free (e);
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "types/error/error.h"
|
||||||
|
|
||||||
|
#include <stdint.h> // uintmax_t
|
||||||
|
|
||||||
|
#ifndef CORELIBS_GUARD_LLIST
|
||||||
|
#define CORELIBS_GUARD_LLIST
|
||||||
|
|
||||||
|
typedef struct cl_llist_t cl_llist_t;
|
||||||
|
|
||||||
|
struct corelibs_llist_interface {
|
||||||
|
cl_error_t (*const create) (void *content, void (*const free_function) (void *), cl_llist_t **save);
|
||||||
|
cl_error_t (*const link) (uintmax_t elements, ...);
|
||||||
|
cl_error_t (*const rep) (cl_llist_t *dest, cl_llist_t *src);
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const list) (cl_llist_t *element);
|
||||||
|
cl_error_t (*const elem) (cl_llist_t *element);
|
||||||
|
cl_error_t (*const cont) (cl_llist_t *element);
|
||||||
|
} free;
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const cont) (cl_llist_t *element, void *content);
|
||||||
|
cl_error_t (*const free) (cl_llist_t *element, void (*const free_function) (void *));
|
||||||
|
} set;
|
||||||
|
const struct {
|
||||||
|
cl_error_t (*const prev) (const cl_llist_t *element, cl_llist_t **save);
|
||||||
|
cl_error_t (*const next) (const cl_llist_t *element, cl_llist_t **save);
|
||||||
|
cl_error_t (*const cont) (const cl_llist_t *element, void **save);
|
||||||
|
} get;
|
||||||
|
};
|
||||||
|
extern const struct corelibs_llist_interface cl_llist;
|
||||||
|
|
||||||
|
#endif /* CORELIBS_GUARD_LLIST */
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "types/error/error.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static const char *corelibs_error_string (cl_error_lang, cl_error_t);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CORELIBS_ERROR_LANG_EN = 0,
|
||||||
|
CORELIBS_ERROR_LANG_COUNT, // Must be last
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CORELIBS_ERROR_ERR_OK = 0,
|
||||||
|
CORELIBS_ERROR_ERR_UNK,
|
||||||
|
CORELIBS_ERROR_ERR_UNDEF,
|
||||||
|
CORELIBS_ERROR_ERR_INVAL,
|
||||||
|
CORELIBS_ERROR_ERR_MEM_ALLOC,
|
||||||
|
CORELIBS_ERROR_ERR_MEM_NULL,
|
||||||
|
CORELIBS_ERROR_ERR_MEM_OOB,
|
||||||
|
CORELIBS_ERROR_ERR_DATA_IMMUT,
|
||||||
|
CORELIBS_ERROR_ERR_DATA_INVAL,
|
||||||
|
CORELIBS_ERROR_ERR_DATA_INCOMPAT,
|
||||||
|
CORELIBS_ERROR_ERR_ARGS_MIS,
|
||||||
|
CORELIBS_ERROR_ERR_COUNT, // Must be last
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const cl_error_strings[CORELIBS_ERROR_LANG_COUNT][CORELIBS_ERROR_ERR_COUNT] = {
|
||||||
|
[CORELIBS_ERROR_LANG_EN] = {
|
||||||
|
// General
|
||||||
|
[CORELIBS_ERROR_ERR_OK] = "OK",
|
||||||
|
[CORELIBS_ERROR_ERR_UNK] = "Unknown error",
|
||||||
|
[CORELIBS_ERROR_ERR_UNDEF] = "Undefined or missing variable",
|
||||||
|
[CORELIBS_ERROR_ERR_INVAL] = "Invalid action",
|
||||||
|
// Memory
|
||||||
|
[CORELIBS_ERROR_ERR_MEM_ALLOC] = "Allocation failed",
|
||||||
|
[CORELIBS_ERROR_ERR_MEM_NULL] = "NULL address",
|
||||||
|
[CORELIBS_ERROR_ERR_MEM_OOB] = "Out of bounds",
|
||||||
|
// Data
|
||||||
|
[CORELIBS_ERROR_ERR_DATA_IMMUT] = "Immutable data",
|
||||||
|
[CORELIBS_ERROR_ERR_DATA_INCOMPAT] = "Incompatible data",
|
||||||
|
[CORELIBS_ERROR_ERR_DATA_INVAL] = "Invalid data",
|
||||||
|
// Arguments
|
||||||
|
[CORELIBS_ERROR_ERR_ARGS_MIS] = "Missing argument(s)",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct corelibs_error_tree const cl_error = {
|
||||||
|
.string = corelibs_error_string,
|
||||||
|
.err = {
|
||||||
|
.ok = CORELIBS_ERROR_ERR_OK,
|
||||||
|
.unk = CORELIBS_ERROR_ERR_UNK,
|
||||||
|
.undef = CORELIBS_ERROR_ERR_UNDEF,
|
||||||
|
.mem = {
|
||||||
|
.null = CORELIBS_ERROR_ERR_MEM_NULL,
|
||||||
|
.alloc = CORELIBS_ERROR_ERR_MEM_ALLOC,
|
||||||
|
.oob = CORELIBS_ERROR_ERR_MEM_OOB,
|
||||||
|
},
|
||||||
|
.data = {
|
||||||
|
.immut = CORELIBS_ERROR_ERR_DATA_IMMUT,
|
||||||
|
.incompat = CORELIBS_ERROR_ERR_DATA_INCOMPAT,
|
||||||
|
.inval = CORELIBS_ERROR_ERR_DATA_INVAL,
|
||||||
|
},
|
||||||
|
.args = {
|
||||||
|
.mis = CORELIBS_ERROR_ERR_ARGS_MIS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
corelibs_error_string (const cl_error_lang lang, const cl_error_t err) {
|
||||||
|
if (lang >= CORELIBS_ERROR_LANG_COUNT || err < 0 || err >= CORELIBS_ERROR_ERR_COUNT) return NULL;
|
||||||
|
return cl_error_strings[lang][err];
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* This file is part of corelibs. (https://git.redxen.eu/corelibs)
|
||||||
|
* Copyright (c) 2021 Alex-David Denes
|
||||||
|
*
|
||||||
|
* corelibs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* corelibs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h> // int_least16_t
|
||||||
|
|
||||||
|
#ifndef CORELIBS_GUARD_ERROR
|
||||||
|
#define CORELIBS_GUARD_ERROR
|
||||||
|
|
||||||
|
typedef int_least16_t cl_error_t;
|
||||||
|
typedef uint_least8_t cl_error_lang;
|
||||||
|
|
||||||
|
struct corelibs_error_tree {
|
||||||
|
const char *(*const string) (cl_error_lang language, cl_error_t errno);
|
||||||
|
const struct {
|
||||||
|
const cl_error_t ok,
|
||||||
|
unk,
|
||||||
|
undef;
|
||||||
|
const struct {
|
||||||
|
const cl_error_t null,
|
||||||
|
alloc,
|
||||||
|
oob;
|
||||||
|
} mem;
|
||||||
|
const struct {
|
||||||
|
const cl_error_t immut,
|
||||||
|
incompat,
|
||||||
|
inval;
|
||||||
|
} data;
|
||||||
|
const struct {
|
||||||
|
const cl_error_t mis;
|
||||||
|
} args;
|
||||||
|
} err;
|
||||||
|
};
|
||||||
|
extern const struct corelibs_error_tree cl_error;
|
||||||
|
|
||||||
|
#endif /* CORELIBS_GUARD_ERROR */
|
||||||
|
|
Reference in New Issue