blob: b0fcb000f7e071a1edd0baf8e9e5591086706279 [file] [log] [blame]
/*
* container_list_sl.c
* $Id$
*
*/
#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 {
const 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 */
} sl_container;
static void *
_get(netsnmp_container *c, const void *key, int exact)
{
sl_container *sl = (sl_container*)c;
sl_node *curr = sl->head;
if( (NULL != curr) && (NULL != key)) {
while (curr) {
if (sl->c.compare(curr->data, key) == 0)
break;
curr = curr->next;
}
if((curr) && (!exact)) {
curr = curr->next;
}
}
return curr ? (void *)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;
if(NULL == c)
return -1;
new_node = SNMP_MALLOC_TYPEDEF(sl_node);
if(NULL == new_node)
return -1;
new_node->data = data;
if(NULL == sl->head) {
sl->head = new_node;
}
else {
sl_node *curr = sl->head, *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;
}
}
++sl->count;
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;
if(sl->c.compare(sl->head->data, data) == 0) {
curr = sl->head;
sl->head = sl->head->next;
}
else {
sl_node *last = sl->head;
for(curr = sl->head->next ; curr; last = curr, curr = curr->next)
if(sl->c.compare(curr->data, data) == 0) {
last->next = curr->next;
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);
}
/**********************************************************************
*
*
*
**********************************************************************/
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;
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;
}
void
netsnmp_container_ssll_init(void)
{
netsnmp_container_register("sorted_singly_linked_list",
netsnmp_container_get_ssll_factory());
}