diff options
-rw-r--r-- | ctrl/libhicnctrl/src/util/map.h | 234 | ||||
-rw-r--r-- | ctrl/libhicnctrl/src/util/set.h | 213 |
2 files changed, 447 insertions, 0 deletions
diff --git a/ctrl/libhicnctrl/src/util/map.h b/ctrl/libhicnctrl/src/util/map.h new file mode 100644 index 000000000..334f12cc1 --- /dev/null +++ b/ctrl/libhicnctrl/src/util/map.h @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UTIL_MAP_H +#define UTIL_MAP_H + +#include <stdlib.h> + +#include "set.h" + +#define ERR_MAP_EXISTS -2 +#define ERR_MAP_NOT_FOUND -3 + +#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T) \ + \ +typedef struct { \ + KEY_T key; \ + VAL_T value; \ +} NAME ## _pair_t; \ + \ +NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value); \ + \ +void NAME ## _pair_free(NAME ## _pair_t * pair); \ + \ +int NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2); \ + \ +TYPEDEF_SET_H(NAME ## _pair_set, NAME ## _pair_t *) \ + \ +typedef struct NAME ## _s { \ + NAME ## _pair_set_t pair_set; \ +} NAME ## _t; \ + \ +int NAME ## _initialize(NAME ## _t * map); \ + \ +int NAME ## _finalize(NAME ## _t * map); \ + \ +NAME ## _t * NAME ## _create(); \ + \ +void NAME ## _free(NAME ## _t * map); \ + \ +int NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value); \ + \ +int NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value); \ + \ +int NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value); \ + \ +void NAME ## _dump(NAME ## _t * map); + + + + +#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF) \ + \ +NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value) \ +{ \ + /* Create pair */ \ + NAME ## _pair_t * pair = malloc(sizeof(NAME ## _pair_t)); \ + if (!pair) \ + return NULL; \ + \ + pair->key = key; \ + pair->value = value; \ + \ + return pair; \ +} \ + \ +void NAME ## _pair_free(NAME ## _pair_t * pair) \ +{ \ + free(pair); \ +} \ + \ +int \ +NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2) \ +{ \ + return (CMP(p1->key, p2->key)); \ +} \ + \ +int \ +NAME ## _pair_snprintf(char * buf, size_t size, const NAME ## _pair_t * pair) { \ + int rc; \ + rc = KEY_SNPRINTF(buf, BUFSIZE/2, (KEY_T)pair->key); \ + if (rc < 0) \ + return rc; \ + rc = VALUE_SNPRINTF(buf+rc, BUFSIZE/2, (VAL_T)pair->value); \ + return rc; \ +} \ + \ +TYPEDEF_SET(NAME ## _pair_set, NAME ## _pair_t *, NAME ## _pair_cmp, NAME ## _pair_snprintf); \ + \ +int \ +NAME ## _initialize(NAME ## _t * map) \ +{ \ + return NAME ## _pair_set_initialize(&map->pair_set); \ +} \ + \ +int \ +NAME ## _finalize(NAME ## _t * map) \ +{ \ + return NAME ## _pair_set_finalize(&map->pair_set); \ +} \ + \ +NAME ## _t * \ +NAME ## _create() \ +{ \ + NAME ## _t * map = malloc(sizeof(NAME ## _t)); \ + if (!map) \ + goto ERR_MALLOC; \ + \ + if (NAME ## _initialize(map) < 0) \ + goto ERR_INITIALIZE; \ + \ + return map; \ + \ +ERR_INITIALIZE: \ + free(map); \ +ERR_MALLOC: \ + return NULL; \ +} \ + \ +void \ +NAME ## _free(NAME ## _t * map) \ +{ \ + NAME ## _finalize(map); \ + free(map); \ +} \ + \ +int \ +NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value) \ +{ \ + int rc; \ + NAME ## _pair_t * found = NULL; \ + \ + NAME ## _pair_t * pair = NAME ## _pair_create(key, value); \ + if (!pair) \ + return -1; \ + \ + rc = NAME ## _pair_set_get(&map->pair_set, pair, &found); \ + if (rc < 0) \ + return -1; \ + if (found) { \ + NAME ## _pair_free(pair); \ + return ERR_MAP_EXISTS; \ + } \ + \ + rc = NAME ## _pair_set_add(&map->pair_set, pair); \ + if (rc < 0) { \ + NAME ## _pair_free(pair); \ + return -1; \ + } \ + return 0; \ +} \ + \ +int \ +NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value) \ +{ \ + NAME ## _pair_t * found = NULL; \ + NAME ## _pair_t search = { .key = key }; \ + int rc = NAME ## _pair_set_remove(&map->pair_set, &search, &found); \ + if (rc < 0) \ + return ERR_MAP_NOT_FOUND; \ + if (value) \ + *value = found->value; \ + NAME ## _pair_free(found); \ + return 0; \ +} \ + \ +int \ +NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value) \ +{ \ + NAME ## _pair_t * found = NULL, search = { .key = key }; \ + int rc = NAME ## _pair_set_get(&map->pair_set, &search, &found); \ + if (rc < 0) \ + return -1; \ + if (found) \ + *value = found->value; \ + return 0; \ +} \ + \ +void \ +NAME ## _dump(NAME ## _t * map) { \ + NAME ## _pair_set_dump(&map->pair_set); \ +} \ + \ +int \ +NAME ## _get_key_array(NAME ## _t * map, KEY_T **array) { \ + NAME ## _pair_t ** pair_array; \ + int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \ + if (n < 0) \ + return -1; \ + /* Allocate result array */ \ + *array = malloc(n * sizeof(KEY_T)); \ + if (!array) { \ + free(pair_array); \ + return -1; \ + } \ + /* Copy keys */ \ + for (int i = 0; i < n; i++) \ + (*array)[i] = pair_array[i]->key; \ + free(pair_array); \ + return 0; \ +} \ + \ +int \ +NAME ## _get_value_array(NAME ## _t * map, VAL_T **array) { \ + NAME ## _pair_t ** pair_array; \ + int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \ + if (n < 0) \ + return -1; \ + /* Allocate result array */ \ + *array = malloc(n * sizeof(VAL_T)); \ + if (!*array) { \ + free(pair_array); \ + return -1; \ + } \ + /* Copy values */ \ + for (int i = 0; i < n; i++) \ + (*array)[i] = pair_array[i]->value; \ + free(pair_array); \ + return 0; \ +} + +#endif /* UTIL_MAP_H */ diff --git a/ctrl/libhicnctrl/src/util/set.h b/ctrl/libhicnctrl/src/util/set.h new file mode 100644 index 000000000..3706e36f4 --- /dev/null +++ b/ctrl/libhicnctrl/src/util/set.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UTIL_SET_H +#define UTIL_SET_H + +#include <search.h> +#include <string.h> +//#if !defined(__ANDROID__) && !defined(__APPLE__) +//#include <threads.h> +//#else +#define thread_local _Thread_local +//#endif /* ! __ANDROID__ */ +#include "util/log.h" + +#define ERR_SET_EXISTS -2 +#define ERR_SET_NOT_FOUND -3 + +/* FIXME: buffer overflow when this is too small... investigate */ +#define BUFSIZE 1024 + +static inline +int +int_cmp(const int x, const int y) +{ + return x - y; +} + +static inline +int +int_snprintf(char * buf, size_t size, int value) { + return snprintf(buf, size, "%d", value); +} + +static inline +int +string_snprintf(char * buf, size_t size, const char * s) { + return snprintf(buf, size, "%s", s); +} + +static inline +int +generic_snprintf(char * buf, size_t size, const void * value) { + return snprintf(buf, BUFSIZE, "%p", value); +} + +typedef int(*cmp_t)(const void * x, const void * y); + +#define TYPEDEF_SET_H(NAME, T) \ + \ +typedef struct { \ + size_t size; \ + void * root; \ +} NAME ## _t; \ + \ +int NAME ## _initialize(NAME ## _t * set); \ + \ +int NAME ## _finalize(NAME ## _t * set); \ + \ +NAME ## _t * NAME ## _create(); \ + \ +void NAME ## _free(NAME ## _t * set); \ + \ +int NAME ## _add(NAME ## _t * set, const T element); \ + \ +int NAME ## _remove(NAME ## _t * set, const T search, T * element); \ + \ +int NAME ## _get(const NAME ## _t * set, const T search, T * element); \ + \ +int NAME ## _get_array(const NAME ## _t * set, T ** element); \ + \ +void NAME ## _dump(NAME ## _t * set); + + + + +#define TYPEDEF_SET(NAME, T, CMP, SNPRINTF) \ +int \ +NAME ## _initialize(NAME ## _t * set) \ +{ \ + set->root = NULL; \ + set->size = 0; \ + return 0; \ +} \ + \ +int \ +NAME ## _finalize(NAME ## _t * set) { return 0; } \ + \ +NAME ## _t * \ +NAME ## _create() \ +{ \ + NAME ## _t * set = malloc(sizeof(NAME ## _t)); \ + if (!set) \ + goto ERR_MALLOC; \ + \ + if (NAME ## _initialize(set) < 0) \ + goto ERR_INITIALIZE; \ + \ + return set; \ + \ +ERR_INITIALIZE: \ + free(set); \ +ERR_MALLOC: \ + return NULL; \ +} \ + \ +void \ +NAME ## _free(NAME ## _t * set) \ +{ \ + NAME ## _finalize(set); \ + free(set); \ +} \ + \ +int \ +NAME ## _add(NAME ## _t * set, const T element) \ +{ \ + void * ptr = tsearch(element, &set->root, (cmp_t)CMP); \ + if (!ptr) \ + return -1; \ + set->size++; \ + return 0; \ +} \ + \ +int \ +NAME ## _remove(NAME ## _t * set, const T search, T * element) \ +{ \ + T * found = tfind(search, &set->root, (cmp_t)CMP); \ + if (!found) \ + return ERR_SET_NOT_FOUND; \ + if (element) \ + *element = *found; \ + tdelete(search, &set->root, (cmp_t)CMP); \ + set->size--; \ + return 0; \ +} \ + \ +int \ +NAME ## _get(const NAME ## _t * set, const T search, T * element) \ +{ \ + T * found = tfind(search, &set->root, (cmp_t)CMP); \ + if (element) \ + *element = found ? *found : NULL; \ + return 0; \ +} \ + \ +static void \ +NAME ## _dump_node(const void *nodep, const VISIT which, \ + const int depth) \ +{ \ + char buf[BUFSIZE]; \ + switch (which) { \ + case preorder: \ + case endorder: \ + break; \ + case postorder: \ + case leaf: \ + SNPRINTF(buf, BUFSIZE, *(T*)nodep); \ + INFO("%s", buf); \ + break; \ + } \ +} \ + \ +void \ +NAME ## _dump(NAME ## _t * set) { \ + twalk(set->root, NAME ## _dump_node); \ +} \ + \ +thread_local \ +T * NAME ## _array_pos = NULL; \ + \ +static void \ +NAME ## _add_node_to_array(const void *nodep, const VISIT which, \ + const int depth) \ +{ \ + if (!NAME ## _array_pos) \ + return; \ + switch (which) { \ + case preorder: \ + case endorder: \ + break; \ + case postorder: \ + case leaf: \ + *NAME ## _array_pos = *(T*)nodep; \ + NAME ## _array_pos++; \ + break; \ + } \ +} \ + \ +int \ +NAME ## _get_array(const NAME ## _t * set, T ** element) \ +{ \ + *element = malloc(set->size * sizeof(T)); \ + if (!*element) \ + return -1; \ + NAME ## _array_pos = *element; \ + twalk(set->root, NAME ## _add_node_to_array); \ + NAME ## _array_pos = NULL; \ + return set->size; \ +} + +#endif /* UTIL_SET_H */ |