/* * container_list_sl.c * $Id: container_list_ssll.c,v 1.7 2004/09/09 10:43:40 slif Exp $ * */ #include #include #if HAVE_STDLIB_H #include #endif #if HAVE_MALLOC_H #include #endif #include #if HAVE_STRING_H #include #else #include #endif #include #include #include #include #include #include #include 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()); }