From d5e21f6b8e6eca9ac112af1c585d67f0a71740ab Mon Sep 17 00:00:00 2001 From: Alex Denes Date: Sat, 11 Sep 2021 19:42:38 +0000 Subject: [PATCH] Cleanup code and update clang-format --- .clang-format | 92 ++++--- dynarray.c | 670 +++++++++++++++++++++----------------------------- 2 files changed, 341 insertions(+), 421 deletions(-) diff --git a/.clang-format b/.clang-format index 07327a4..4e18d0e 100644 --- a/.clang-format +++ b/.clang-format @@ -1,41 +1,61 @@ --- -BasedOnStyle: LLVM -AlignConsecutiveMacros: 'true' -AlignConsecutiveAssignments: 'true' -AlignConsecutiveDeclarations: 'true' -AlignEscapedNewlines: Left -AllowShortBlocksOnASingleLine: 'true' -AllowShortCaseLabelsOnASingleLine: 'true' -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Always -AllowShortLoopsOnASingleLine: 'true' -AlwaysBreakAfterDefinitionReturnType: TopLevel -AlwaysBreakAfterReturnType: AllDefinitions -AlwaysBreakBeforeMultilineStrings: 'false' -BinPackArguments: 'false' -BinPackParameters: 'false' -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Linux -BreakStringLiterals: 'false' -ColumnLimit: '150' -ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' -Cpp11BracedListStyle: 'false' -IncludeBlocks: Regroup -IndentCaseLabels: 'true' -IndentPPDirectives: None -IndentWidth: '8' +Standard: Auto Language: Cpp -PointerAlignment: Left -ReflowComments: 'true' -SortIncludes: 'true' -SpaceAfterCStyleCast: 'true' -SpaceAfterLogicalNot: 'false' -SpaceBeforeAssignmentOperators: 'true' -SpaceBeforeCpp11BracedList: 'true' -SpaceBeforeParens: ControlStatements -SpacesInCStyleCastParentheses: 'false' -Standard: Cpp11 -TabWidth: '8' +BasedOnStyle: LLVM +ColumnLimit: 0 +IndentWidth: 8 +TabWidth: 8 UseTab: ForIndentation +AlignConsecutiveAssignments: true +AlignConsecutiveBitFields: true +AlignConsecutiveDeclarations: true +AlignConsecutiveMacros: true +AlignEscapedNewlines: Left +AlignOperands: AlignAfterOperator +AlignTrailingComments: true + +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLoopsOnASingleLine: true + +AlwaysBreakAfterDefinitionReturnType: TopLevel +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakBeforeMultilineStrings: false + +BinPackArguments: false +BinPackParameters: false + +BreakBeforeBinaryOperators: All +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true + +BreakStringLiterals: false +BreakConstructorInitializers: AfterColon + +IndentCaseLabels: true +IndentPPDirectives: None +IndentGotoLabels: true + +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +IncludeBlocks: Regroup +InsertTrailingCommas: Wrapped +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: true +SpaceBeforeParens: Always +SpacesInConditionalStatement: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false + ... diff --git a/dynarray.c b/dynarray.c index f892af0..259ef28 100644 --- a/dynarray.c +++ b/dynarray.c @@ -23,37 +23,37 @@ #include // memcpy() // Exporter -static cl_dynarray_err corelibs_dynarray_export_slice(const cl_dynarray_t*, uintmax_t, uintmax_t, void*); +static cl_dynarray_err corelibs_dynarray_export_slice (const cl_dynarray_t *, uintmax_t, uintmax_t, void *); // Lifetime -static cl_dynarray_err corelibs_dynarray_make_new(size_t, cl_dynarray_t**); -static cl_dynarray_err corelibs_dynarray_make_slice(const cl_dynarray_t*, uintmax_t, uintmax_t, cl_dynarray_t**); -static cl_dynarray_err corelibs_dynarray_free(cl_dynarray_t*); +static cl_dynarray_err corelibs_dynarray_make_new (size_t, cl_dynarray_t **); +static cl_dynarray_err corelibs_dynarray_make_slice (const cl_dynarray_t *, uintmax_t, uintmax_t, cl_dynarray_t **); +static cl_dynarray_err corelibs_dynarray_free (cl_dynarray_t *); // Array storage -static cl_dynarray_err corelibs_dynarray_mod_arr_cap(cl_dynarray_t*, uintmax_t); -static cl_dynarray_err corelibs_dynarray_mod_arr_lock(cl_dynarray_t*, bool); +static cl_dynarray_err corelibs_dynarray_mod_arr_cap (cl_dynarray_t *, uintmax_t); +static cl_dynarray_err corelibs_dynarray_mod_arr_lock (cl_dynarray_t *, bool); // Array contents -static cl_dynarray_err corelibs_dynarray_mod_ct_app(cl_dynarray_t*, uintmax_t, const void*); -static cl_dynarray_err corelibs_dynarray_mod_ct_ins(cl_dynarray_t*, uintmax_t, uintmax_t, const void*); -static cl_dynarray_err corelibs_dynarray_mod_ct_rep(cl_dynarray_t*, uintmax_t, uintmax_t, const void*); -static cl_dynarray_err corelibs_dynarray_mod_ct_rm(cl_dynarray_t*, uintmax_t, uintmax_t); +static cl_dynarray_err corelibs_dynarray_mod_ct_app (cl_dynarray_t *, uintmax_t, const void *); +static cl_dynarray_err corelibs_dynarray_mod_ct_ins (cl_dynarray_t *, uintmax_t, uintmax_t, const void *); +static cl_dynarray_err corelibs_dynarray_mod_ct_rep (cl_dynarray_t *, uintmax_t, uintmax_t, const void *); +static cl_dynarray_err corelibs_dynarray_mod_ct_rm (cl_dynarray_t *, uintmax_t, uintmax_t); // Get array properties -static cl_dynarray_err corelibs_dynarray_get_len(const cl_dynarray_t*, uintmax_t*); -static cl_dynarray_err corelibs_dynarray_get_size(const cl_dynarray_t*, size_t*); -static cl_dynarray_err corelibs_dynarray_get_cap_len(const cl_dynarray_t*, uintmax_t*); -static cl_dynarray_err corelibs_dynarray_get_cap_lock(const cl_dynarray_t*, bool*); +static cl_dynarray_err corelibs_dynarray_get_len (const cl_dynarray_t *, uintmax_t *); +static cl_dynarray_err corelibs_dynarray_get_size (const cl_dynarray_t *, size_t *); +static cl_dynarray_err corelibs_dynarray_get_cap_len (const cl_dynarray_t *, uintmax_t *); +static cl_dynarray_err corelibs_dynarray_get_cap_lock (const cl_dynarray_t *, bool *); // Compare arrays -static cl_dynarray_err corelibs_dynarray_cmp_data(const cl_dynarray_t* a, const cl_dynarray_t* b, bool* eq); +static cl_dynarray_err corelibs_dynarray_cmp_data (const cl_dynarray_t *a, const cl_dynarray_t *b, bool *eq); // Private functions -static cl_dynarray_err corelibs_dynarray_bcheck(const cl_dynarray_t*, uintmax_t, uintmax_t); +static cl_dynarray_err corelibs_dynarray_bcheck (const cl_dynarray_t *, uintmax_t, uintmax_t); struct cl_dynarray_t { - void* addr; // Location of element + void * addr; // Location of element uintmax_t len; // Element count struct { bool lock; // Is the capacity frozen? @@ -63,464 +63,364 @@ struct cl_dynarray_t { }; enum { // Avoid collision in error numbers - CORELIBS_DYNARRAY_ERR_VAR_NCOMPAT = -7, - CORELIBS_DYNARRAY_ERR_VAR_INVAL, - CORELIBS_DYNARRAY_ERR_VAR_IMMUT, - CORELIBS_DYNARRAY_ERR_VAR_UNDEF, + CORELIBS_DYNARRAY_ERR_OK = 0, + CORELIBS_DYNARRAY_ERR_UNKOWN, CORELIBS_DYNARRAY_ERR_MEM_OOB, CORELIBS_DYNARRAY_ERR_MEM_NULL, CORELIBS_DYNARRAY_ERR_MEM_ALLOC, - CORELIBS_DYNARRAY_ERR_UNKOWN = 0, - CORELIBS_DYNARRAY_ERR_OK = 1, + CORELIBS_DYNARRAY_ERR_VAR_NCOMPAT, + CORELIBS_DYNARRAY_ERR_VAR_INVAL, + CORELIBS_DYNARRAY_ERR_VAR_IMMUT, + CORELIBS_DYNARRAY_ERR_VAR_UNDEF, }; // Present a unified structure that may receive changes, deprecations and renames without hassle for external users 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, - }, - .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_UNKOWN, - .mem = { - .alloc = CORELIBS_DYNARRAY_ERR_MEM_ALLOC, - .null = CORELIBS_DYNARRAY_ERR_MEM_NULL, - .oob = CORELIBS_DYNARRAY_ERR_MEM_OOB, - }, - .var = { - .undef = CORELIBS_DYNARRAY_ERR_VAR_UNDEF, - .immut = CORELIBS_DYNARRAY_ERR_VAR_IMMUT, - .inval = CORELIBS_DYNARRAY_ERR_VAR_INVAL, - .ncompat = CORELIBS_DYNARRAY_ERR_VAR_NCOMPAT, - }, - }, + .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_UNKOWN, + .mem = { + .alloc = CORELIBS_DYNARRAY_ERR_MEM_ALLOC, + .null = CORELIBS_DYNARRAY_ERR_MEM_NULL, + .oob = CORELIBS_DYNARRAY_ERR_MEM_OOB, + }, + .var = { + .undef = CORELIBS_DYNARRAY_ERR_VAR_UNDEF, + .immut = CORELIBS_DYNARRAY_ERR_VAR_IMMUT, + .inval = CORELIBS_DYNARRAY_ERR_VAR_INVAL, + .ncompat = CORELIBS_DYNARRAY_ERR_VAR_NCOMPAT, + }, + }, }; static cl_dynarray_err -corelibs_dynarray_make_new(size_t sbyte, cl_dynarray_t** ptr) -{ +corelibs_dynarray_make_new (size_t sbyte, cl_dynarray_t **ptr) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (ptr == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; - } - - cl_dynarray_t* new = malloc(sizeof(*new)); - if (new == NULL) { - err = CORELIBS_DYNARRAY_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_dynarray_err -corelibs_dynarray_make_slice(const cl_dynarray_t* arr, uintmax_t pos, uintmax_t cnt, cl_dynarray_t** save) -{ - cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (save == NULL || arr == NULL) { - err = CORELIBS_DYNARRAY_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; // 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; - - cl_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 cl_dynarray_err -corelibs_dynarray_free(cl_dynarray_t* arr) -{ - cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (arr == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; - } - - if ((err = corelibs_dynarray_mod_arr_cap(arr, 0)) != CORELIBS_DYNARRAY_ERR_OK) goto ret; - - free(arr); -ret: - return err; -} - -static cl_dynarray_err -corelibs_dynarray_mod_arr_cap(cl_dynarray_t* arr, uintmax_t len) -{ - cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (arr == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_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_VAR_IMMUT; - goto ret; - } - - void* reg = NULL; - const size_t nl = len * arr->es; - - if (arr->addr == NULL) { - if ((reg = malloc(nl)) == NULL) { + if (ptr == NULL) err = CORELIBS_DYNARRAY_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 = CORELIBS_DYNARRAY_ERR_MEM_ALLOC; - goto ret; - } - } else if (arr->cap.len != len) { - if ((reg = realloc(arr->addr, nl)) == NULL) { - err = CORELIBS_DYNARRAY_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 -ret: return err; } static cl_dynarray_err -corelibs_dynarray_mod_arr_lock(cl_dynarray_t* arr, bool lock) -{ +corelibs_dynarray_make_slice (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, cl_dynarray_t **save) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (save == NULL || arr == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + if (cnt == 0) { + // Don't copy anything, just make new array + return corelibs_dynarray_make_new (arr->es, save); + } - if (arr == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + // 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); + } + } } - - arr->cap.lock = lock; -ret: return err; } static cl_dynarray_err -corelibs_dynarray_mod_ct_app(cl_dynarray_t* arr, uintmax_t cnt, const void* elem) -{ - return corelibs_dynarray_mod_ct_ins(arr, arr->len, cnt, elem); -} - -static cl_dynarray_err -corelibs_dynarray_mod_ct_ins(cl_dynarray_t* arr, uintmax_t pos, uintmax_t cnt, const void* elem) -{ +corelibs_dynarray_free (cl_dynarray_t *arr) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (arr == NULL || elem == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + if (arr == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + if (!(err = corelibs_dynarray_mod_arr_cap (arr, 0))) { + free (arr); + } } - - // 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 cl_dynarray_err -corelibs_dynarray_mod_ct_rep(cl_dynarray_t* arr, uintmax_t pos, uintmax_t cnt, const void* elem) -{ +corelibs_dynarray_mod_arr_cap (cl_dynarray_t *arr, uintmax_t len) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (arr == NULL) err = CORELIBS_DYNARRAY_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 == NULL || elem == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + 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 = CORELIBS_DYNARRAY_ERR_MEM_ALLOC; + } + } else { + err = CORELIBS_DYNARRAY_ERR_VAR_IMMUT; + } } - - if (corelibs_dynarray_bcheck(arr, pos, cnt) == CORELIBS_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 cl_dynarray_err -corelibs_dynarray_mod_ct_rm(cl_dynarray_t* arr, uintmax_t pos, uintmax_t cnt) -{ +corelibs_dynarray_mod_arr_lock (cl_dynarray_t *arr, bool lock) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (arr == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + if (arr == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + arr->cap.lock = lock; } - - // 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_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 - - 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 cl_dynarray_err -corelibs_dynarray_export_slice(const cl_dynarray_t* arr, uintmax_t pos, uintmax_t cnt, void* save) -{ +corelibs_dynarray_mod_ct_app (cl_dynarray_t *arr, uintmax_t cnt, const void *elem) { + return corelibs_dynarray_mod_ct_ins (arr, arr->len, cnt, elem); +} + +static cl_dynarray_err +corelibs_dynarray_mod_ct_ins (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, const void *elem) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (arr == NULL || elem == NULL) err = CORELIBS_DYNARRAY_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) - if (arr == NULL || save == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + 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 (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 cl_dynarray_err -corelibs_dynarray_get_len(const cl_dynarray_t* arr, uintmax_t* save) -{ +corelibs_dynarray_mod_ct_rep (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, const void *elem) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (arr == NULL || elem == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + if (corelibs_dynarray_bcheck (arr, pos, cnt) == CORELIBS_DYNARRAY_ERR_MEM_OOB) { + // Resize array to fit new elements + err = corelibs_dynarray_mod_arr_cap (arr, pos + cnt); + } - if (arr == NULL || save == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + 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 + } } - - *save = arr->len; -ret: return err; } static cl_dynarray_err -corelibs_dynarray_get_cap_len(const cl_dynarray_t* arr, uintmax_t* save) -{ +corelibs_dynarray_mod_ct_rm (cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (arr == NULL) err = CORELIBS_DYNARRAY_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) - if (arr == NULL || save == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + 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 = CORELIBS_DYNARRAY_ERR_MEM_ALLOC; + } + } } - - *save = arr->cap.len; -ret: return err; } static cl_dynarray_err -corelibs_dynarray_get_cap_lock(const cl_dynarray_t* arr, bool* save) -{ +corelibs_dynarray_export_slice (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t cnt, void *save) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (arr == NULL || save == NULL) err = CORELIBS_DYNARRAY_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 - if (arr == NULL || save == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + src = (uintptr_t) arr->addr + (arr->es * pos); + dest = (uintptr_t) save; + bcnt = arr->es * cnt; + memcpy ((void *) dest, (void *) src, bcnt); + } } - - *save = arr->cap.lock; -ret: return err; } static cl_dynarray_err -corelibs_dynarray_get_size(const cl_dynarray_t* arr, size_t* save) -{ +corelibs_dynarray_get_len (const cl_dynarray_t *arr, uintmax_t *save) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (arr == NULL || save == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + if (arr == NULL || save == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + *save = arr->len; } - - *save = arr->es; -ret: return err; } static cl_dynarray_err -corelibs_dynarray_cmp_data(const cl_dynarray_t* a, const cl_dynarray_t* b, bool* eq) -{ +corelibs_dynarray_get_cap_len (const cl_dynarray_t *arr, uintmax_t *save) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (a == NULL || b == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; + if (arr == NULL || save == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + *save = arr->cap.len; } + return err; +} - if (a->es != b->es) { - err = CORELIBS_DYNARRAY_ERR_VAR_NCOMPAT; - goto ret; +static cl_dynarray_err +corelibs_dynarray_get_cap_lock (const cl_dynarray_t *arr, bool *save) { + cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (arr == NULL || save == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + *save = arr->cap.lock; } + return err; +} - if (a->len != b->len) { - *eq = false; - goto ret; +static cl_dynarray_err +corelibs_dynarray_get_size (const cl_dynarray_t *arr, size_t *save) { + cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (arr == NULL || save == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (!err) { + *save = arr->es; } + return err; +} - *eq = (memcmp(a->addr, b->addr, a->len) != 0) ? false : true; -ret: +static cl_dynarray_err +corelibs_dynarray_cmp_data (const cl_dynarray_t *a, const cl_dynarray_t *b, bool *eq) { + cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; + if (a == NULL || b == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (a->es != b->es) err = CORELIBS_DYNARRAY_ERR_VAR_NCOMPAT; + 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_dynarray_err -corelibs_dynarray_bcheck(const cl_dynarray_t* arr, uintmax_t pos, uintmax_t len) -{ +corelibs_dynarray_bcheck (const cl_dynarray_t *arr, uintmax_t pos, uintmax_t len) { cl_dynarray_err err = CORELIBS_DYNARRAY_ERR_OK; - - if (arr == NULL) { - err = CORELIBS_DYNARRAY_ERR_MEM_NULL; - goto ret; - } - - if (arr->cap.len < pos + len) { - err = CORELIBS_DYNARRAY_ERR_MEM_OOB; - goto ret; - } -ret: + if (arr == NULL) err = CORELIBS_DYNARRAY_ERR_MEM_NULL; + if (arr->cap.len < pos + len) err = CORELIBS_DYNARRAY_ERR_MEM_OOB; return err; }