From 40c1e31fc03debb92f397dc0f029efdafdb777aa Mon Sep 17 00:00:00 2001 From: Alex Denes Date: Sun, 16 Jan 2022 14:16:35 +0000 Subject: [PATCH] Code refactorings and optimizations --- Makefile | 17 +- config.mk | 30 +-- src/dynarray/dynarray.c | 446 +++++++++++++++++++++++----------------- src/dynarray/dynarray.h | 2 +- 4 files changed, 278 insertions(+), 217 deletions(-) diff --git a/Makefile b/Makefile index 30c7aca..5076965 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,17 @@ +.SUFFIXES: include config.mk -OBJ = ${SRC:.c=.o} - -all: ${OBJ} ${OUT} +OBJ := $(SRC:.c=.o) +all: $(OBJ) $(OUT) %.o: %.c - ${CC} -o $@ -c ${CFLAGS} $< - + $(CC) -o $@ -c $(CFLAGS) $< clean: - rm -f ${OBJ} ${OUT} + rm -f $(OBJ) $(OUT) -ifneq (${OUT},) -${OUT}: ${OBJ} - ${CC} -o "$@" ${LDFLAGS} $^ +ifneq ($(OUT),) +$(OUT): $(OBJ) + $(CC) -o "$@" $(LDFLAGS) $^ endif .PHONY: all clean diff --git a/config.mk b/config.mk index 76a3719..afb81be 100644 --- a/config.mk +++ b/config.mk @@ -1,10 +1,10 @@ # Defaults -CC = clang -DEBUG = 1 -STATIC = 0 +CC := clang +DEBUG := 1 +STATIC := 0 -LDFLAGS = -CFLAGS =\ +LDFLAGS := +CFLAGS :=\ -std=c99 \ -Weverything \ -Wno-padded \ @@ -12,35 +12,35 @@ CFLAGS =\ -pedantic # Sources / Results -SRC =\ +SRC :=\ src/dynarray/dynarray.c \ src/llist/llist.c \ src/encoding/baseven/baseven.c \ src/types/error/error.c -LIBDIR = -LIB =\ +LIBDIR := +LIB :=\ c -INCDIR =\ +INCDIR :=\ src/ -OUT = +OUT := # Conditionals / Appends LDFLAGS +=\ - $(addprefix -L,${LIBDIR})\ - $(addprefix -l,${LIB}) + $(addprefix -L,$(LIBDIR))\ + $(addprefix -l,$(LIB)) CFLAGS +=\ - $(addprefix -I,${INCDIR}) + $(addprefix -I,$(INCDIR)) -ifeq (${DEBUG},1) +ifeq ($(DEBUG),1) CFLAGS += -g else CFLAGS += -O2 -Werror endif -ifeq (${STATIC},1) +ifeq ($(STATIC),1) LDFLAGS += -static endif diff --git a/src/dynarray/dynarray.c b/src/dynarray/dynarray.c index 99817bd..4fd0142 100644 --- a/src/dynarray/dynarray.c +++ b/src/dynarray/dynarray.c @@ -1,6 +1,6 @@ /* * This file is part of corelibs. (https://git.redxen.eu/corelibs) - * Copyright (c) 2021 Alex-David Denes + * Copyright (c) 2021-2022 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 @@ -43,7 +43,7 @@ corelibs_dynarray_export_slice (const cl_dynarray_t *, uintmax_t, uintmax_t, voi corelibs_dynarray_bcheck (const cl_dynarray_t *, uintmax_t, uintmax_t); struct cl_dynarray_t { - void * addr; // Location of element + uint8_t * addr; // Location of element uintmax_t len; // Element count struct { bool lock; // Is the capacity frozen? @@ -89,105 +89,130 @@ const struct corelibs_dynarray_interface cl_dynarray = { 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; - } + + if (ptr == NULL) { + err = cl_error.err.mem.null; + goto ret; } + + cl_dynarray_t *new = malloc (sizeof (*new)); + if (new == NULL) { + err = cl_error.err.mem.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 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); - } - } + if (save == NULL || arr == NULL) { + err = cl_error.err.mem.null; + goto ret; } + + if (cnt == 0) { + // Don't copy anything, just make new array + err = corelibs_dynarray_make_new (arr->es, save); + goto ret; + } + + // Can we slice these elements? + if ((err = corelibs_dynarray_bcheck (arr, pos, cnt))) goto ret; + + // Create new array + cl_dynarray_t *new; + if ((err = corelibs_dynarray_make_new (arr->es, &new))) goto ret; + + // Resize array to fit contents + if ((err = corelibs_dynarray_mod_arr_cap (new, cnt))) { + 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_free (new); + goto ret; + } + + new->len = cnt; + new->cap.lock = arr->cap.lock; // Inherit capacity lock + *save = new; +ret: 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); - } + + if (arr == NULL) { + err = cl_error.err.mem.null; + goto ret; } + + if ((err = corelibs_dynarray_mod_arr_cap (arr, 0))) goto ret; + free (arr); +ret: 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; - } + if (arr == NULL) { + err = cl_error.err.mem.null; + goto ret; } + + 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) { + err = cl_error.err.mem.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 + } else { + err = cl_error.err.data.immut; + goto ret; + } +ret: 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; + if (arr == NULL) { + err = cl_error.err.mem.null; + goto ret; } + arr->cap.lock = lock; +ret: return err; } @@ -199,182 +224,212 @@ corelibs_dynarray_mod_dat_app (cl_dynarray_t *arr, uintmax_t cnt, const void *el 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 - } + if (arr == NULL || elem == NULL) { + err = cl_error.err.mem.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))) 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; + + const uint8_t *src; + uint8_t * dest; + size_t bcnt; + + // If we are inserting and not appending + if (pos < clen) { + src = arr->addr + (pos * arr->es); + dest = arr->addr + ((pos + cnt) * arr->es); + bcnt = (clen - pos) * arr->es; + memmove (dest, src, bcnt); // Shift bytes to after insertion region + } + + src = elem; + dest = arr->addr + (pos * arr->es); + bcnt = cnt * arr->es; + memcpy (dest, src, bcnt); // No overlaps possible +ret: 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 - } + if (arr == NULL || elem == NULL) { + err = cl_error.err.mem.null; + goto ret; } + + if ((err = corelibs_dynarray_bcheck (arr, pos, cnt)) == cl_error.err.mem.oob) { + // Resize array to fit new elements + if ((err = corelibs_dynarray_mod_arr_cap (arr, pos + cnt))) 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) + + const uint8_t *src; + uint8_t * dest; + size_t bcnt; + + src = elem; + dest = arr->addr + (pos * arr->es); + bcnt = cnt * arr->es; + memcpy (dest, 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 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; - } - } + if (arr == NULL) { + err = cl_error.err.mem.null; + goto ret; } + // Are we removing elements we don't have? + if ((err = corelibs_dynarray_bcheck (arr, pos, cnt))) goto ret; + + // Allocate intermediate buffer + void *tbuf = malloc (arr->es * arr->len); + if (tbuf != NULL) { + err = cl_error.err.mem.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 + + const uint8_t *src; + uint8_t * dest; + size_t bcnt; + + src = arr->addr; + dest = tbuf; + bcnt = arr->len * arr->es; + memcpy (dest, 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 + src += (pos + cnt) * arr->es; + dest += pos * arr->es; + bcnt -= pos * arr->es; + memcpy (dest, src, bcnt); + } + + free (arr->addr); + arr->addr = tbuf; // Swap buffers and free previous one +ret: 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); - } + if (arr == NULL || save == NULL) { + err = cl_error.err.mem.null; + goto ret; } + if (cnt == 0) goto ret; // Skip exporting anything, nothing was requested + + // Do we have the requested slice? + if ((err = corelibs_dynarray_bcheck (arr, pos, cnt))) goto ret; + + const uint8_t *src; + uint8_t * dest; + size_t bcnt; + + src = arr->addr + (pos * arr->es); + dest = save; + bcnt = arr->es * cnt; + memcpy (dest, src, bcnt); +ret: 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; + + if (arr == NULL || save == NULL) { + err = cl_error.err.mem.null; + goto ret; } + *save = arr->len; +ret: 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; + + if (arr == NULL || save == NULL) { + err = cl_error.err.mem.null; + goto ret; } + *save = arr->cap.len; +ret: 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; + + if (arr == NULL || save == NULL) { + err = cl_error.err.mem.null; + goto ret; } + *save = arr->cap.lock; +ret: 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; + + if (arr == NULL || save == NULL) { + err = cl_error.err.mem.null; + goto ret; } + *save = arr->es; +ret: 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; - } + + if (a == NULL || b == NULL) { + err = cl_error.err.mem.null; + goto ret; } + if (a->es != b->es) { + err = cl_error.err.data.incompat; + goto ret; + } + + if (a->len != b->len) { + *eq = false; + } else { + *eq = (memcmp (a->addr, b->addr, a->len) != 0) ? false : true; + } +ret: return err; } @@ -382,7 +437,14 @@ corelibs_dynarray_cmp_data (const cl_dynarray_t *a, const cl_dynarray_t *b, bool 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; + if (arr == NULL) { + err = cl_error.err.mem.null; + goto ret; + } + if (arr->cap.len < pos + len) { + err = cl_error.err.mem.oob; + goto ret; + } +ret: return err; } diff --git a/src/dynarray/dynarray.h b/src/dynarray/dynarray.h index 3b214d0..3d9072f 100644 --- a/src/dynarray/dynarray.h +++ b/src/dynarray/dynarray.h @@ -1,6 +1,6 @@ /* * This file is part of corelibs. (https://git.redxen.eu/corelibs) - * Copyright (c) 2021 Alex-David Denes + * Copyright (c) 2021-2022 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