diff options
Diffstat (limited to 'snmplib/container_list_ssll.c')
-rw-r--r-- | snmplib/container_list_ssll.c | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/snmplib/container_list_ssll.c b/snmplib/container_list_ssll.c new file mode 100644 index 0000000..39b0709 --- /dev/null +++ b/snmplib/container_list_ssll.c @@ -0,0 +1,393 @@ +/* + * container_list_sl.c + * $Id: container_list_ssll.c 11048 2004-09-09 10:43:40Z slif $ + * + */ +#include <net-snmp/net-snmp-config.h> + +#include <stdio.h> +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif +#if HAVE_MALLOC_H +#include <malloc.h> +#endif +#include <sys/types.h> +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/types.h> +#include <net-snmp/library/snmp_api.h> +#include <net-snmp/library/container.h> +#include <net-snmp/library/tools.h> +#include <net-snmp/library/snmp_assert.h> + +#include <net-snmp/library/container_list_ssll.h> + +typedef struct sl_node { + void *data; + struct sl_node *next; +} sl_node; + +typedef struct sl_container_s { + netsnmp_container c; + + size_t count; /* Index of the next free entry */ + sl_node *head; /* head of list */ + + int unsorted; /* unsorted list? */ + int fifo; /* lifo or fifo? */ + +} sl_container; + + +static void * +_get(netsnmp_container *c, const void *key, int exact) +{ + sl_container *sl = (sl_container*)c; + sl_node *curr = sl->head; + int rc = 0; + + /* + * note: get-next on unsorted list is meaningless. we + * don't try to search whole array, looking for the next highest. + */ + if( (NULL != curr) && (NULL != key)) { + while (curr) { + rc = sl->c.compare(curr->data, key); + if (rc == 0) + break; + else if (rc > 0) { + if (0 == sl->unsorted) { + /* + * if sorted, we can stop. + */ + break; + } + } + curr = curr->next; + } + + if((curr) && (!exact) && (rc == 0)) { + curr = curr->next; + } + } + + return curr ? curr->data : NULL; +} + +/********************************************************************** + * + * + * + **********************************************************************/ +static void +_ssll_free(netsnmp_container *c) +{ + if(c) { + free(c); + } +} + +static void * +_ssll_find(netsnmp_container *c, const void *data) +{ + if((NULL == c) || (NULL == data)) + return NULL; + + return _get(c, data, 1); +} + +static void * +_ssll_find_next(netsnmp_container *c, const void *data) +{ + if(NULL == c) + return NULL; + + return _get(c, data, 0); +} + +static int +_ssll_insert(netsnmp_container *c, const void *data) +{ + sl_container *sl = (sl_container*)c; + sl_node *new_node, *curr = sl->head; + + if(NULL == c) + return -1; + + new_node = SNMP_MALLOC_TYPEDEF(sl_node); + if(NULL == new_node) + return -1; + new_node->data = (void *)data; + ++sl->count; + + /* + * first node? + */ + if(NULL == sl->head) { + sl->head = new_node; + return 0; + } + + /* + * sorted or unsorted insert? + */ + if (1 == sl->unsorted) { + /* + * unsorted: fifo, or lifo? + */ + if (1 == sl->fifo) { + /* + * fifo: insert at tail + */ + while(NULL != curr->next) + curr = curr->next; + curr->next = new_node; + } + else { + /* + * lifo: insert at head + */ + new_node->next = sl->head; + sl->head = new_node; + } + } + else { + /* + * sorted + */ + sl_node *last = NULL; + for( ; curr; last = curr, curr = curr->next) { + if(sl->c.compare(curr->data, data) > 0) + break; + } + if(NULL == last) { + new_node->next = sl->head; + sl->head = new_node; + } + else { + new_node->next = last->next; + last->next = new_node; + } + } + + return 0; +} + +static int +_ssll_remove(netsnmp_container *c, const void *data) +{ + sl_container *sl = (sl_container*)c; + sl_node *curr = sl->head; + + if((NULL == c) || (NULL == curr)) + return -1; + + /* + * special case for NULL data, act like stack + */ + if ((NULL == data) || + (sl->c.compare(sl->head->data, data) == 0)) { + curr = sl->head; + sl->head = sl->head->next; + } + else { + sl_node *last = sl->head; + int rc; + for(curr = sl->head->next ; curr; last = curr, curr = curr->next) { + rc = sl->c.compare(curr->data, data); + if (rc == 0) { + last->next = curr->next; + break; + } + else if ((rc > 0) && (0 == sl->unsorted)) { + /* + * if sorted and rc > 0, didn't find entry + */ + curr = NULL; + break; + } + } + } + + if(NULL == curr) + return -2; + + /* + * free our node structure, but not the data + */ + free(curr); + --sl->count; + + return 0; +} + +static size_t +_ssll_size(netsnmp_container *c) +{ + sl_container *sl = (sl_container*)c; + + if(NULL == c) + return 0; + + return sl->count; +} + +static void +_ssll_for_each(netsnmp_container *c, netsnmp_container_obj_func *f, + void *context) +{ + sl_container *sl = (sl_container*)c; + sl_node *curr; + + if(NULL == c) + return; + + for(curr = sl->head; curr; curr = curr->next) + (*f) ((void *)curr->data, context); +} + +static void +_ssll_clear(netsnmp_container *c, netsnmp_container_obj_func *f, + void *context) +{ + sl_container *sl = (sl_container*)c; + sl_node *curr, *next; + + if(NULL == c) + return; + + for(curr = sl->head; curr; curr = next) { + + next = curr->next; + + if( NULL != f ) { + curr->next = NULL; + (*f) ((void *)curr->data, context); + } + + /* + * free our node structure, but not the data + */ + free(curr); + } + sl->head = NULL; + sl->count = 0; +} + +/********************************************************************** + * + * + * + **********************************************************************/ +netsnmp_container * +netsnmp_container_get_ssll(void) +{ + /* + * allocate memory + */ + sl_container *sl = SNMP_MALLOC_TYPEDEF(sl_container); + if (NULL==sl) { + snmp_log(LOG_ERR, "couldn't allocate memory\n"); + return NULL; + } + + sl->c.cfree = (netsnmp_container_rc*)_ssll_free; + + sl->c.get_size = _ssll_size; + sl->c.init = NULL; + sl->c.insert = _ssll_insert; + sl->c.remove = _ssll_remove; + sl->c.find = _ssll_find; + sl->c.find_next = _ssll_find_next; + sl->c.get_subset = NULL; + sl->c.get_iterator = NULL; + sl->c.for_each = _ssll_for_each; + sl->c.clear = _ssll_clear; + + + return (netsnmp_container*)sl; +} + +netsnmp_factory * +netsnmp_container_get_ssll_factory(void) +{ + static netsnmp_factory f = {"sorted_singly_linked_list", + (netsnmp_factory_produce_f*) + netsnmp_container_get_ssll }; + + return &f; +} + + +netsnmp_container * +netsnmp_container_get_usll(void) +{ + /* + * allocate memory + */ + sl_container *sl = (sl_container *)netsnmp_container_get_ssll(); + if (NULL==sl) + return NULL; /* msg already logged */ + + sl->unsorted = 1; + + return (netsnmp_container*)sl; +} + +netsnmp_container * +netsnmp_container_get_singly_linked_list(int fifo) +{ + sl_container *sl = (sl_container *)netsnmp_container_get_usll(); + if (NULL == sl) + return NULL; /* error already logged */ + + sl->fifo = fifo; + + return (netsnmp_container *)sl; +} + +netsnmp_container * +netsnmp_container_get_fifo(void) +{ + return netsnmp_container_get_singly_linked_list(1); +} + +netsnmp_factory * +netsnmp_container_get_usll_factory(void) +{ + static netsnmp_factory f = {"unsorted_singly_linked_list-lifo", + (netsnmp_factory_produce_f*) + netsnmp_container_get_usll }; + + return &f; +} + +netsnmp_factory * +netsnmp_container_get_fifo_factory(void) +{ + static netsnmp_factory f = {"unsorted_singly_linked_list-fifo", + (netsnmp_factory_produce_f*) + netsnmp_container_get_fifo }; + + return &f; +} + +void +netsnmp_container_ssll_init(void) +{ + netsnmp_container_register("sorted_singly_linked_list", + netsnmp_container_get_ssll_factory()); + netsnmp_container_register("unsorted_singly_linked_list", + netsnmp_container_get_usll_factory()); + netsnmp_container_register("lifo", + netsnmp_container_get_usll_factory()); + netsnmp_container_register("fifo", + netsnmp_container_get_fifo_factory()); +} + |