Initial commit after repository separation
This commit is contained in:
commit
062056f660
60
Makefile
Normal file
60
Makefile
Normal file
@ -0,0 +1,60 @@
|
||||
include config.mk
|
||||
|
||||
ifeq (${CC},clang)
|
||||
|
||||
CFLAGS :=\
|
||||
-std=c99\
|
||||
-Weverything\
|
||||
-Wno-padded\
|
||||
-Wno-disabled-macro-expansion\
|
||||
-pedantic\
|
||||
${CFLAGS}
|
||||
|
||||
else ifeq (${CC},gcc)
|
||||
|
||||
CFLAGS :=\
|
||||
-std=c99\
|
||||
-Wall\
|
||||
-Wextra\
|
||||
-Wformat-overflow=2\
|
||||
-Wformat-security\
|
||||
-Winit-self\
|
||||
-Wstrict-overflow=2\
|
||||
-Wstringop-overflow=2\
|
||||
-Walloc-zero\
|
||||
-Wduplicated-branches\
|
||||
-Wduplicated-cond\
|
||||
-Wtrampolines\
|
||||
-Wfloat-equal\
|
||||
-Wshadow\
|
||||
-Wunsafe-loop-optimizations\
|
||||
-Wparentheses\
|
||||
-pedantic\
|
||||
${CFLAGS}
|
||||
|
||||
endif
|
||||
|
||||
SRC = dynarray.c
|
||||
HDR = dynarray.h
|
||||
LIB = dynarray.a
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
all: ${LIB}
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $<
|
||||
|
||||
${LIB}: ${OBJ}
|
||||
${AR} rc $@ $?
|
||||
${RANLIB} $@
|
||||
|
||||
clean:
|
||||
rm -f ${LIB} ${OBJ}
|
||||
|
||||
install: all
|
||||
mkdir -p "${DESTDIR}${PREFIX}/lib/corelibs"
|
||||
cp -f ${LIB} "${DESTDIR}${PREFIX}/lib/corelibs"
|
||||
mkdir -p "${DESTDIR}${PREFIX}/include/corelibs"
|
||||
cp -f ${HDR} "${DESTDIR}${PREFIX}/include/corelibs"
|
||||
|
||||
.PHONY: all clean install
|
7
config.mk
Normal file
7
config.mk
Normal file
@ -0,0 +1,7 @@
|
||||
VERSION = 1.1
|
||||
|
||||
PREFIX = /usr/local
|
||||
|
||||
CC = clang
|
||||
AR = llvm-ar
|
||||
RANLIB = llvm-ranlib
|
526
dynarray.c
Normal file
526
dynarray.c
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* This file is part of corelibs. (https://git.redxen.eu/caskd/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.h"
|
||||
|
||||
#include <stdbool.h> // bool
|
||||
#include <stdlib.h> // malloc() free()
|
||||
#include <string.h> // memcpy()
|
||||
|
||||
// Exporter
|
||||
static dynarray_err corelibs_dynarray_export_slice(const dynarray_t*, uintmax_t, uintmax_t, void*);
|
||||
|
||||
// Lifetime
|
||||
static dynarray_err corelibs_dynarray_make_new(size_t, dynarray_t**);
|
||||
static dynarray_err corelibs_dynarray_make_slice(const dynarray_t*, uintmax_t, uintmax_t, dynarray_t**);
|
||||
static dynarray_err corelibs_dynarray_free(dynarray_t*);
|
||||
|
||||
// Array storage
|
||||
static dynarray_err corelibs_dynarray_mod_arr_cap(dynarray_t*, uintmax_t);
|
||||
static dynarray_err corelibs_dynarray_mod_arr_lock(dynarray_t*, bool);
|
||||
|
||||
// Array contents
|
||||
static dynarray_err corelibs_dynarray_mod_ct_app(dynarray_t*, uintmax_t, const void*);
|
||||
static dynarray_err corelibs_dynarray_mod_ct_ins(dynarray_t*, uintmax_t, uintmax_t, const void*);
|
||||
static dynarray_err corelibs_dynarray_mod_ct_rep(dynarray_t*, uintmax_t, uintmax_t, const void*);
|
||||
static dynarray_err corelibs_dynarray_mod_ct_rm(dynarray_t*, uintmax_t, uintmax_t);
|
||||
|
||||
// Get array properties
|
||||
static dynarray_err corelibs_dynarray_get_len(const dynarray_t*, uintmax_t*);
|
||||
static dynarray_err corelibs_dynarray_get_size(const dynarray_t*, size_t*);
|
||||
static dynarray_err corelibs_dynarray_get_cap_len(const dynarray_t*, uintmax_t*);
|
||||
static dynarray_err corelibs_dynarray_get_cap_lock(const dynarray_t*, bool*);
|
||||
|
||||
// Compare arrays
|
||||
static dynarray_err corelibs_dynarray_cmp_data(const dynarray_t* a, const dynarray_t* b, bool* eq);
|
||||
|
||||
// Private functions
|
||||
static dynarray_err corelibs_dynarray_bcheck(const dynarray_t*, uintmax_t, uintmax_t);
|
||||
|
||||
struct 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
|
||||
};
|
||||
|
||||
enum { // Avoid collision in error numbers
|
||||
CORELIBS_DYNARRAY_ERR_NCOMPAT = -7,
|
||||
CORELIBS_DYNARRAY_ERR_INVAL,
|
||||
CORELIBS_DYNARRAY_ERR_IMMUT,
|
||||
CORELIBS_DYNARRAY_ERR_UNDEF,
|
||||
CORELIBS_DYNARRAY_ERR_OOB,
|
||||
CORELIBS_DYNARRAY_ERR_NULL,
|
||||
CORELIBS_DYNARRAY_ERR_ALLOC,
|
||||
CORELIBS_DYNARRAY_ERR_UNK = 0,
|
||||
CORELIBS_DYNARRAY_ERR_OK = 1,
|
||||
};
|
||||
|
||||
// Present a unified structure that may receive changes, deprecations and renames without hassle for external users
|
||||
const struct corelibs_dynarray_interface 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,
|
||||
},
|
||||
.ct = {
|
||||
.app = corelibs_dynarray_mod_ct_app,
|
||||
.ins = corelibs_dynarray_mod_ct_ins,
|
||||
.rep = corelibs_dynarray_mod_ct_rep,
|
||||
.rm = corelibs_dynarray_mod_ct_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,
|
||||
},
|
||||
},
|
||||
.err = {
|
||||
.ok = CORELIBS_DYNARRAY_ERR_OK,
|
||||
.unknown = CORELIBS_DYNARRAY_ERR_UNK,
|
||||
.mem = {
|
||||
.alloc = CORELIBS_DYNARRAY_ERR_ALLOC,
|
||||
.null = CORELIBS_DYNARRAY_ERR_NULL,
|
||||
.oob = CORELIBS_DYNARRAY_ERR_OOB,
|
||||
},
|
||||
.var = {
|
||||
.undef = CORELIBS_DYNARRAY_ERR_UNDEF,
|
||||
.immut = CORELIBS_DYNARRAY_ERR_IMMUT,
|
||||
.inval = CORELIBS_DYNARRAY_ERR_INVAL,
|
||||
.ncompat = CORELIBS_DYNARRAY_ERR_NCOMPAT,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_make_new(size_t sbyte, dynarray_t** ptr)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (ptr == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
dynarray_t* new = malloc(sizeof(*new));
|
||||
if (new == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_ALLOC;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
new->addr = NULL;
|
||||
new->es = sbyte;
|
||||
new->len = 0;
|
||||
new->cap.len = 0;
|
||||
new->cap.lock = false;
|
||||
|
||||
*ptr = new;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_make_slice(const dynarray_t* arr, uintmax_t pos, uintmax_t cnt, dynarray_t** save)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (save == NULL || arr == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (cnt == 0) {
|
||||
// Don't copy anything, just make new array
|
||||
err = corelibs_dynarray_make_new(arr->es, save);
|
||||
goto ret; // Return even if no error is met, nothing more to do
|
||||
}
|
||||
|
||||
// Can we slice these elements?
|
||||
if ((err = corelibs_dynarray_bcheck(arr, pos, cnt)) != CORELIBS_DYNARRAY_ERR_OK) goto ret;
|
||||
|
||||
dynarray_t* new;
|
||||
// Create new array
|
||||
if ((err = corelibs_dynarray_make_new(arr->es, &new)) != CORELIBS_DYNARRAY_ERR_OK) goto ret;
|
||||
|
||||
// Resize array to fit contents
|
||||
if ((err = corelibs_dynarray_mod_arr_cap(new, cnt)) != CORELIBS_DYNARRAY_ERR_OK) {
|
||||
corelibs_dynarray_free(new);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// Copy contents from old array to new one
|
||||
if ((err = corelibs_dynarray_export_slice(arr, pos, cnt, new->addr)) != CORELIBS_DYNARRAY_ERR_OK) {
|
||||
corelibs_dynarray_free(new);
|
||||
goto ret;
|
||||
}
|
||||
new->len = cnt;
|
||||
new->cap.lock = arr->cap.lock; // Inherit capacity lock
|
||||
|
||||
*save = new;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_free(dynarray_t* arr)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if ((err = corelibs_dynarray_mod_arr_cap(arr, 0)) != CORELIBS_DYNARRAY_ERR_OK) goto ret;
|
||||
|
||||
free(arr);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_mod_arr_cap(dynarray_t* arr, uintmax_t len)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
free(arr->addr);
|
||||
arr->cap.len = 0;
|
||||
goto ret; // Return success (default)
|
||||
}
|
||||
|
||||
if (arr->cap.lock) {
|
||||
err = CORELIBS_DYNARRAY_ERR_IMMUT;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
void* reg = NULL;
|
||||
const size_t nl = len * arr->es;
|
||||
|
||||
if (arr->addr == NULL) {
|
||||
if ((reg = malloc(nl)) == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_ALLOC;
|
||||
goto ret;
|
||||
}
|
||||
} else if (arr->cap.len != len) {
|
||||
if ((reg = realloc(arr->addr, nl)) == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_ALLOC;
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_mod_arr_lock(dynarray_t* arr, bool lock)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
arr->cap.lock = lock;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_mod_ct_app(dynarray_t* arr, uintmax_t cnt, const void* elem)
|
||||
{
|
||||
return corelibs_dynarray_mod_ct_ins(arr, arr->len, cnt, elem);
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_mod_ct_ins(dynarray_t* arr, uintmax_t pos, uintmax_t cnt, const void* elem)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL || elem == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// Resize array to fit inserted objects
|
||||
if ((err = corelibs_dynarray_mod_arr_cap(arr, ((arr->cap.len < pos) ? pos : arr->cap.len) + cnt)) != CORELIBS_DYNARRAY_ERR_OK) goto ret;
|
||||
|
||||
// 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
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_mod_ct_rep(dynarray_t* arr, uintmax_t pos, uintmax_t cnt, const void* elem)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL || elem == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (corelibs_dynarray_bcheck(arr, pos, cnt) == dynarray.err.mem.oob) {
|
||||
// Resize array to fit new elements
|
||||
if ((err = corelibs_dynarray_mod_arr_cap(arr, pos + cnt)) != CORELIBS_DYNARRAY_ERR_OK) goto ret;
|
||||
}
|
||||
|
||||
// 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
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_mod_ct_rm(dynarray_t* arr, uintmax_t pos, uintmax_t cnt)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// Are we removing elements we don't have?
|
||||
if ((err = corelibs_dynarray_bcheck(arr, pos, cnt)) != CORELIBS_DYNARRAY_ERR_OK) goto ret;
|
||||
|
||||
// Allocate intermediate buffer
|
||||
void* tbuf = malloc(arr->es * arr->len);
|
||||
if (tbuf == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_ALLOC;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// 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
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_export_slice(const dynarray_t* arr, uintmax_t pos, uintmax_t cnt, void* save)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL || save == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
if (cnt == 0) goto ret;
|
||||
|
||||
// Do we have the requested slice?
|
||||
if ((err = corelibs_dynarray_bcheck(arr, pos, cnt)) != CORELIBS_DYNARRAY_ERR_OK) goto ret;
|
||||
|
||||
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);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_get_len(const dynarray_t* arr, uintmax_t* save)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL || save == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
*save = arr->len;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_get_cap_len(const dynarray_t* arr, uintmax_t* save)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL || save == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
*save = arr->cap.len;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_get_cap_lock(const dynarray_t* arr, bool* save)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL || save == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
*save = arr->cap.lock;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_get_size(const dynarray_t* arr, size_t* save)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL || save == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
*save = arr->es;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static dynarray_err
|
||||
corelibs_dynarray_cmp_data(const dynarray_t* a, const dynarray_t* b, bool* eq)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (a == NULL || b == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (a->es != b->es) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NCOMPAT;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (a->len != b->len) {
|
||||
*eq = false;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
*eq = (memcmp(a->addr, b->addr, a->len) != 0) ? false : true;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
// Private functions
|
||||
static dynarray_err
|
||||
corelibs_dynarray_bcheck(const dynarray_t* arr, uintmax_t pos, uintmax_t len)
|
||||
{
|
||||
dynarray_err err = CORELIBS_DYNARRAY_ERR_OK;
|
||||
|
||||
if (arr == NULL) {
|
||||
err = CORELIBS_DYNARRAY_ERR_NULL;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (arr->cap.len < pos + len) {
|
||||
err = CORELIBS_DYNARRAY_ERR_OOB;
|
||||
goto ret;
|
||||
}
|
||||
ret:
|
||||
return err;
|
||||
}
|
109
dynarray.h
Normal file
109
dynarray.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This file is part of corelibs. (https://git.redxen.eu/caskd/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 <stdbool.h> // bool
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdint.h> // uintmax_t
|
||||
|
||||
#ifndef CORELIBS_GUARD_DYNARRAY
|
||||
#define CORELIBS_GUARD_DYNARRAY
|
||||
|
||||
typedef signed short int dynarray_err;
|
||||
typedef struct dynarray_t dynarray_t;
|
||||
|
||||
struct corelibs_dynarray_interface {
|
||||
|
||||
// Makers
|
||||
const struct {
|
||||
// New - allocate new array
|
||||
dynarray_err (*const new)(size_t sbyte, dynarray_t** ptr);
|
||||
// Slicer - gets a slice of a array
|
||||
dynarray_err (*const slice)(const dynarray_t* arr, uintmax_t pos, uintmax_t len, dynarray_t** ssave);
|
||||
} make;
|
||||
|
||||
// Free
|
||||
dynarray_err (*const free)(dynarray_t* arr);
|
||||
|
||||
// Modifiers
|
||||
const struct {
|
||||
|
||||
const struct {
|
||||
// Capacity
|
||||
dynarray_err (*const cap)(dynarray_t* ptr, uintmax_t len);
|
||||
// Capacity lock (dynamic / static capacity)
|
||||
dynarray_err (*const lock)(dynarray_t* ptr, bool cap);
|
||||
} arr;
|
||||
|
||||
const struct {
|
||||
// Appender - Adds element at end of array
|
||||
dynarray_err (*const app)(dynarray_t* arr, uintmax_t cnt, const void* elem);
|
||||
// Inserter - Adds element at position, pushing next element 1 position further
|
||||
dynarray_err (*const ins)(dynarray_t* arr, uintmax_t pos, uintmax_t cnt, const void* elem);
|
||||
// Replacer - Replaces array item or creates it if not existent
|
||||
dynarray_err (*const rep)(dynarray_t* arr, uintmax_t pos, uintmax_t cnt, const void* elem);
|
||||
// Remover - removes element from array
|
||||
dynarray_err (*const rm)(dynarray_t* arr, uintmax_t pos, uintmax_t cnt);
|
||||
} ct;
|
||||
|
||||
} mod;
|
||||
|
||||
// Fetchers
|
||||
const struct {
|
||||
dynarray_err (*const len)(const dynarray_t* arr, uintmax_t* save);
|
||||
dynarray_err (*const size)(const dynarray_t* arr, size_t* save);
|
||||
const struct {
|
||||
dynarray_err (*const len)(const dynarray_t* arr, uintmax_t* save);
|
||||
dynarray_err (*const lock)(const dynarray_t* arr, bool* save);
|
||||
} cap;
|
||||
} get;
|
||||
|
||||
// Comparers
|
||||
const struct {
|
||||
dynarray_err (*const data)(const dynarray_t* a, const dynarray_t* b, bool* eq);
|
||||
} cmp;
|
||||
|
||||
// Exporter
|
||||
const struct {
|
||||
dynarray_err (*const slice)(const dynarray_t* arr, uintmax_t pos, uintmax_t cnt, void* save);
|
||||
} export;
|
||||
|
||||
// Errors - functions return them on run-time problems
|
||||
const struct {
|
||||
|
||||
const dynarray_err ok, // No error
|
||||
unknown; // Unknown error
|
||||
|
||||
const struct {
|
||||
const dynarray_err alloc, // Memory allocation failed
|
||||
null, // Passed a null pointer
|
||||
oob; // Out of bounds modification or fetch
|
||||
} mem;
|
||||
|
||||
const struct {
|
||||
const dynarray_err undef, // Undefined variable
|
||||
immut, // Immutable (constant) variable
|
||||
inval, // Invalid value passed
|
||||
ncompat; // Incompatible comparasion
|
||||
} var;
|
||||
|
||||
} err;
|
||||
};
|
||||
extern const struct corelibs_dynarray_interface dynarray;
|
||||
|
||||
#endif /* CORELIBS_GUARD_DYNARRAY */
|
||||
|
Reference in New Issue
Block a user