diff --git a/include/array.h b/include/array.h index 05042f0..397f5a6 100644 --- a/include/array.h +++ b/include/array.h @@ -11,8 +11,8 @@ extern void array_init(vtype_array* x, vtype type) LIBCDSB_nt__ LIBCDSB_nn1__; -extern void* array_at(const vtype_array* s, ssize_t index) LIBCDSB_nt__ LIBCDSB_nn1__; -extern _Bool array_slice(vtype_array* x, vtype_array* src, ssize_t index, size_t count, _Bool cut) LIBCDSB_nt__ LIBCDSB_nn1__; +extern void* array_at(const vtype_array* s, ssize_t index) LIBCDSB_nt__ LIBCDSB_nn1__; +extern size_t array_slice(vtype_array* x, vtype_array* src, ssize_t index, size_t count, _Bool cut) LIBCDSB_nt__ LIBCDSB_nn1__; extern void array_sort (vtype_array* x) LIBCDSB_nt__ LIBCDSB_nn1__; extern void array_reverse(vtype_array* x) LIBCDSB_nt__ LIBCDSB_nn1__; diff --git a/include/list.h b/include/list.h index eda1488..a88fc19 100644 --- a/include/list.h +++ b/include/list.h @@ -12,6 +12,8 @@ extern void list_init(vtype_list* x); extern void list_extend(vtype_list* x, const vtype_list* s); +extern size_t list_slice(vtype_list* x, vtype_list* src, ssize_t index, size_t count, _Bool cut) LIBCDSB_nt__ LIBCDSB_nn12__; + extern void list_sort(vtype_list* x); extern void list_reverse(vtype_list* x); diff --git a/src/array/base-copy.c b/src/array/base-copy.c index fe4dbcf..967e74e 100644 --- a/src/array/base-copy.c +++ b/src/array/base-copy.c @@ -4,12 +4,11 @@ #include "include.h" #include "../__internal/assert.h" + arr_t array_copy(const arr_t* s) { arr_t x = { .mem = 0, .size = 0, .type = 0 }; if (s->size > 0) { - assert(!is_null(s->mem)); - x.type = s->type; x.size = s->size; @@ -41,12 +40,11 @@ arr_t array_copy(const arr_t* s) { return x; } + arr_t* array_duplicate(const arr_t* s) { arr_t* x = malloc(sizeof(*x)); if (s->size > 0) { - assert(!is_null(s->mem)); - x->type = s->type; x->size = s->size; @@ -78,10 +76,9 @@ arr_t* array_duplicate(const arr_t* s) { return x; } + void array_copy_init(arr_t* x, const arr_t* s) { if (s->size > 0) { - assert(!is_null(s->mem)); - x->type = s->type; x->size = s->size; @@ -110,3 +107,46 @@ void array_copy_init(arr_t* x, const arr_t* s) { } else x->mem = memndup(s->mem, x->size*vtype_size(x->type)); } else memset(x, 0, sizeof(*x)); } + + +size_t array_slice(arr_t* x, arr_t* s, ssize_t i, size_t n, _Bool cut) { + + if (!n || !s->size) { + memset(x, 0, sizeof(*x)); + return 0; + } + + if (i < 0 && (i += s->size) < 0) i = 0; + if (i + n > s->size) n = s->size - (i + 1); + + x->type = s->type; + x->size = n; + x->mem = malloc(x->size*vtype_size(x->type)); + + if (!cut && s->type >= VTYPE_STRING) { + void *p, *v, *e; + void (*init)(void*, const void*); + + p = x->mem; + v = array_internal_at(s, i); + e = array_internal_at(x, n); + + switch (s->type) { default: abort(); + case VTYPE_STRING: init = (void*)string_copy_init; break; + case VTYPE_ARRAY: init = (void*) array_copy_init; break; + case VTYPE_LIST: init = (void*) list_copy_init; break; + case VTYPE_MAP: init = (void*) map_copy_init; break; + case VTYPE_SET: init = (void*) vset_copy_init; break; + } + + do { + init(p, v); + p += vtype_size(x->type); + v += vtype_size(x->type); + } while (p < e); + } else memcpy(x->mem, array_internal_at(s, i), n*vtype_size(x->type)); + + if (cut) array_cut(s, i, n); + + return n; +} diff --git a/src/array/slice.c b/src/array/slice.c deleted file mode 100644 index 00c9549..0000000 --- a/src/array/slice.c +++ /dev/null @@ -1,54 +0,0 @@ -/* This software is licensed by the MIT License, see LICENSE file */ -/* Copyright © 2022 Gregory Lirent */ - -#include "include.h" -#include "../__internal/assert.h" -#include "../__internal/vnode.h" - -_Bool array_slice(arr_t* x, arr_t* s, ssize_t i, size_t n, _Bool cut) { - if (n && s->size) { - assert(!is_null(s->mem)); - - if (i < 0 && (i += s->size) < 0) i = 0; - - if (i + n > s->size) { - memset(x, 0, sizeof(*x)); - return false; - } - - x->type = s->type; - x->size = n; - x->mem = malloc(x->size*vtype_size(x->type)); - - if (!cut && s->type >= VTYPE_STRING) { - void *p, *v, *e; - void (*init)(void*, const void*); - - p = x->mem; - v = array_internal_at(s, i); - e = array_internal_at(x, n); - - switch (s->type) { default: abort(); - case VTYPE_STRING: init = (void*)string_copy_init; break; - case VTYPE_ARRAY: init = (void*) array_copy_init; break; - case VTYPE_LIST: init = (void*) list_copy_init; break; - case VTYPE_MAP: init = (void*) map_copy_init; break; - case VTYPE_SET: init = (void*) vset_copy_init; break; - } - - do { - init(p, v); - p += vtype_size(x->type); - v += vtype_size(x->type); - } while (p < e); - } else memcpy(x->mem, array_internal_at(s, i), n*vtype_size(x->type)); - - if (cut) array_cut(s, i, n); - } else { - memset(x, 0, sizeof(*x)); - - if (n && !s->size) return false; - } - - return true; -} diff --git a/src/list/copy.c b/src/list/copy.c index fb714ae..c9839c6 100644 --- a/src/list/copy.c +++ b/src/list/copy.c @@ -107,3 +107,80 @@ void list_extend(list_t* x, const list_t* s) { push_next(x, vnode_duplicate(&c->node, c->type), c->type); } while (!is_null(c = c->next)); } + + + +size_t list_slice(list_t* x, list_t* s, ssize_t i, size_t n, _Bool cut) { + + ldir_t dir; + lnode_t* c; + lnode_t* e; + size_t r; + + r = n; + + if (!n || is_null(s->first)) { + memset(x, 0, sizeof(*x)); + return 0; + } + + if (i < 0) { + c = s->last; + e = s->last; + i = ~i; + + while (i && !is_null(c)) { + c = c->prev; + --i; + if (!n) { e = e->prev; } + else --n; + } + + if (is_null(c)) c = x->first; + } else { + c = s->first; + + while (i && !is_null(c)) { + c = c->next; + --i; + } + + e = c; + + while (n && !is_null(e)) { + e = e->next; + --n; + } + + if (is_null(e)) e = x->last; + } + + if (is_null(c)) return 0; + else r -= n; + + if (!cut) { + init_first(x, vnode_duplicate(&c->node, c->type), c->type); + + while ((c = c->next) != e) { + push_next(x, vnode_duplicate(&c->node, c->type), c->type); + } + + push_next(x, vnode_duplicate(&e->node, e->type), e->type); + } else { + if (c->prev) { + c->prev->next = e->next; + } else x->first = e->next; + + if (e->next) { + e->next->prev = c->prev; + } else s->last = c->prev; + + e->next = nullptr; + c->prev = nullptr; + + x->first = c; + x->last = e; + } + + return r; +} diff --git a/src/list/extra.c b/src/list/extra.c index b51ee54..8b578c7 100644 --- a/src/list/extra.c +++ b/src/list/extra.c @@ -59,14 +59,15 @@ ssize_t libcdsb_list_get(val_t* x, list_t* s, ssize_t i, _Bool cut) { /*#####################################################################################################################*/ ssize_t libcdsb_list_find(val_t* x, list_t* s, const void* v, vtype t, _Bool r, _Bool cut) { - ldir_t dir = r ? LD_PREV : LD_NEXT; + ldir_t dir; lnode_t* c; ssize_t i; int cmp; - c = ldir_dir((lnode_t*)s, dir); - i = 0; + dir = r ? LD_PREV : LD_NEXT; + c = ldir_dir((lnode_t*)s, dir); + i = 0; if (!is_null(x)) memset(x, 0, sizeof(*x)); @@ -178,7 +179,7 @@ int libcdsb_list_foreach(vtype_list* x, void* data, list_foreach_callback callba break; n = c->next; - + if (flush) { vnode_free(&c->node, c->type); free(c);