diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:55:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:55:11 +0000 |
commit | cd07912073c951b4bbb871ed2653af1be2cfc714 (patch) | |
tree | 1073c2308492e6aea4c66cb7436ee92db2abfd42 /src/set.c | |
parent | Initial commit. (diff) | |
download | libyang2-upstream.tar.xz libyang2-upstream.zip |
Adding upstream version 2.1.30.upstream/2.1.30upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/set.c')
-rw-r--r-- | src/set.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/src/set.c b/src/set.c new file mode 100644 index 0000000..1b8bfa5 --- /dev/null +++ b/src/set.c @@ -0,0 +1,247 @@ +/** + * @file set.c + * @author Radek Krejci <rkrejci@cesnet.cz> + * @brief Generic set routines implementations + * + * Copyright (c) 2015 - 2018 CESNET, z.s.p.o. + * + * This source code is licensed under BSD 3-Clause License (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + */ + +#include "common.h" + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "log.h" +#include "set.h" + +LIBYANG_API_DEF LY_ERR +ly_set_new(struct ly_set **set_p) +{ + LY_CHECK_ARG_RET(NULL, set_p, LY_EINVAL); + + *set_p = calloc(1, sizeof **set_p); + LY_CHECK_ERR_RET(!(*set_p), LOGMEM(NULL), LY_EMEM); + + return LY_SUCCESS; +} + +LIBYANG_API_DEF void +ly_set_clean(struct ly_set *set, void (*destructor)(void *obj)) +{ + uint32_t u; + + if (!set) { + return; + } + + if (destructor) { + for (u = 0; u < set->count; ++u) { + destructor(set->objs[u]); + } + } + set->count = 0; +} + +LIBYANG_API_DEF void +ly_set_erase(struct ly_set *set, void (*destructor)(void *obj)) +{ + if (!set) { + return; + } + + ly_set_clean(set, destructor); + + free(set->objs); + set->size = 0; + set->objs = NULL; +} + +LIBYANG_API_DEF void +ly_set_free(struct ly_set *set, void (*destructor)(void *obj)) +{ + if (!set) { + return; + } + + ly_set_erase(set, destructor); + + free(set); +} + +LIBYANG_API_DEF ly_bool +ly_set_contains(const struct ly_set *set, const void *object, uint32_t *index_p) +{ + LY_CHECK_ARG_RET(NULL, set, 0); + + for (uint32_t i = 0; i < set->count; i++) { + if (set->objs[i] == object) { + /* object found */ + if (index_p) { + *index_p = i; + } + return 1; + } + } + + /* object not found */ + return 0; +} + +LIBYANG_API_DEF LY_ERR +ly_set_dup(const struct ly_set *set, void *(*duplicator)(const void *obj), struct ly_set **newset_p) +{ + struct ly_set *newset; + uint32_t u; + + LY_CHECK_ARG_RET(NULL, set, newset_p, LY_EINVAL); + + newset = calloc(1, sizeof *newset); + LY_CHECK_ERR_RET(!newset, LOGMEM(NULL), LY_EMEM); + if (!set->count) { + *newset_p = newset; + return LY_SUCCESS; + } + + newset->count = set->count; + newset->size = set->count; /* optimize the size */ + newset->objs = malloc(newset->size * sizeof *(newset->objs)); + LY_CHECK_ERR_RET(!newset->objs, LOGMEM(NULL); free(newset), LY_EMEM); + if (duplicator) { + for (u = 0; u < set->count; ++u) { + newset->objs[u] = duplicator(set->objs[u]); + } + } else { + memcpy(newset->objs, set->objs, newset->size * sizeof *(newset->objs)); + } + + *newset_p = newset; + return LY_SUCCESS; +} + +LIBYANG_API_DEF LY_ERR +ly_set_add(struct ly_set *set, const void *object, ly_bool list, uint32_t *index_p) +{ + void **new; + + LY_CHECK_ARG_RET(NULL, set, LY_EINVAL); + + if (!list) { + /* search for duplication */ + for (uint32_t i = 0; i < set->count; i++) { + if (set->objs[i] == object) { + /* already in set */ + if (index_p) { + *index_p = i; + } + return LY_SUCCESS; + } + } + } + + if (set->size == set->count) { +#define SET_SIZE_STEP 8 + new = realloc(set->objs, (set->size + SET_SIZE_STEP) * sizeof *(set->objs)); + LY_CHECK_ERR_RET(!new, LOGMEM(NULL), LY_EMEM); + set->size += SET_SIZE_STEP; + set->objs = new; +#undef SET_SIZE_STEP + } + + if (index_p) { + *index_p = set->count; + } + set->objs[set->count++] = (void *)object; + + return LY_SUCCESS; +} + +LIBYANG_API_DEF LY_ERR +ly_set_merge(struct ly_set *trg, const struct ly_set *src, ly_bool list, void *(*duplicator)(const void *obj)) +{ + uint32_t u; + void *obj; + + LY_CHECK_ARG_RET(NULL, trg, LY_EINVAL); + + if (!src) { + /* nothing to do */ + return LY_SUCCESS; + } + + for (u = 0; u < src->count; ++u) { + if (duplicator) { + obj = duplicator(src->objs[u]); + } else { + obj = src->objs[u]; + } + LY_CHECK_RET(ly_set_add(trg, obj, list, NULL)); + } + + return LY_SUCCESS; +} + +LIBYANG_API_DEF LY_ERR +ly_set_rm_index(struct ly_set *set, uint32_t index, void (*destructor)(void *obj)) +{ + LY_CHECK_ARG_RET(NULL, set, LY_EINVAL); + LY_CHECK_ERR_RET(index >= set->count, LOGARG(NULL, index), LY_EINVAL); + + if (destructor) { + destructor(set->objs[index]); + } + if (index == set->count - 1) { + /* removing last item in set */ + set->objs[index] = NULL; + } else { + /* removing item somewhere in a middle, so put there the last item */ + set->objs[index] = set->objs[set->count - 1]; + set->objs[set->count - 1] = NULL; + } + set->count--; + + return LY_SUCCESS; +} + +LIBYANG_API_DEF LY_ERR +ly_set_rm(struct ly_set *set, void *object, void (*destructor)(void *obj)) +{ + uint32_t i; + + LY_CHECK_ARG_RET(NULL, set, object, LY_EINVAL); + + /* get index */ + for (i = 0; i < set->count; i++) { + if (set->objs[i] == object) { + break; + } + } + LY_CHECK_ERR_RET((i == set->count), LOGARG(NULL, object), LY_EINVAL); /* object is not in set */ + + return ly_set_rm_index(set, i, destructor); +} + +LY_ERR +ly_set_rm_index_ordered(struct ly_set *set, uint32_t index, void (*destructor)(void *obj)) +{ + if (destructor) { + destructor(set->objs[index]); + } + set->count--; + if (index == set->count) { + /* removing last item in set */ + set->objs[index] = NULL; + } else { + /* removing item somewhere in a middle, move following items */ + memmove(set->objs + index, set->objs + index + 1, (set->count - index) * sizeof *set->objs); + set->objs[set->count] = NULL; + } + + return LY_SUCCESS; +} |