1 #if BRCM_CONTAINER_SUPPORT
3 * container_binary_array.c
4 * $Id: container_binary_array.c,v 1.6.2.2 2003/01/21 04:21:08 rstory Exp $
6 * see comments in header file.
10 #include <net-snmp/net-snmp-config.h>
22 #include <sys/types.h>
29 #include <net-snmp/net-snmp-includes.h>
30 #include <net-snmp/types.h>
31 #include <net-snmp/library/snmp_api.h>
32 #include <net-snmp/library/container.h>
33 #include <net-snmp/library/container_binary_array.h>
34 #include <net-snmp/library/tools.h>
35 #include <net-snmp/library/snmp_assert.h>
37 typedef struct binary_array_table_s {
38 size_t max_size; /* Size of the current data table */
39 size_t count; /* Index of the next free entry */
41 int data_size; /* Size of an individual entry */
42 void **data; /* The table itself */
46 array_qsort(void **data, int first, int last, netsnmp_container_compare *f)
53 mid = data[(first+last)/2];
56 while ( ((*f)(data[i], mid) < 0) && (i < last))
58 while ( ((*f)(mid, data[j]) < 0) && (j > first))
76 array_qsort(data, first, j, f);
79 array_qsort(data, i, last, f);
83 Sort_Array(netsnmp_container *c)
85 binary_array_table *t = (binary_array_table*)c->private;
86 netsnmp_assert(t!=NULL);
87 netsnmp_assert(c->compare!=NULL);
94 array_qsort(t->data, 0, t->count - 1, c->compare);
102 binary_search(const void *val, netsnmp_container *c, int exact)
104 binary_array_table *t = (binary_array_table*)c->private;
105 size_t len = t->count;
122 c->compare(t->data[middle], val)) < 0) {
125 len = len - half - 1;
135 if (first >= t->count)
138 if(first != middle) {
139 /* last compare wasn't against first, so get actual result */
140 result = c->compare(t->data[first], val);
145 if (++first == t->count)
158 netsnmp_binary_array_initialize(void)
160 binary_array_table *t;
162 t = SNMP_MALLOC_TYPEDEF(binary_array_table);
176 netsnmp_binary_array_release(netsnmp_container *c)
178 binary_array_table *t = (binary_array_table*)c->private;
183 netsnmp_binary_array_count(netsnmp_container *c)
185 binary_array_table *t = (binary_array_table*)c->private;
189 return t ? t->count : 0;
193 netsnmp_binary_array_get(netsnmp_container *c, const void *key, int exact)
195 binary_array_table *t = (binary_array_table*)c->private;
199 * if there is no data, return NULL;
205 * if the table is dirty, sort it.
211 * if there is a key, search. Otherwise default is 0;
214 if ((index = binary_search(key, c, exact)) == -1)
218 return t->data[index];
222 netsnmp_binary_array_replace(netsnmp_container *c, void *entry)
224 binary_array_table *t = (binary_array_table*)c->private;
228 * if there is no data, return NULL;
234 * if the table is dirty, sort it.
242 if ((index = binary_search(entry, c, 1)) == -1)
245 t->data[index] = entry;
251 netsnmp_binary_array_remove(netsnmp_container *c, const void *key, void **save)
253 binary_array_table *t = (binary_array_table*)c->private;
260 * if there is no data, return NULL;
266 * if the table is dirty, sort it.
274 if ((index = binary_search(key, c, 1)) == -1)
278 * find old data and save it, if ptr provided
281 *save = t->data[index];
284 * if entry was last item, just decrement count
287 if (index != t->count) {
289 * otherwise, shift array down
291 memmove(&t->data[index], &t->data[index+1], t->data_size * (t->count - index));
298 netsnmp_binary_array_for_each(netsnmp_container *c,
299 netsnmp_container_obj_func *fe,
300 void *context, int sort)
302 binary_array_table *t = (binary_array_table*)c->private;
305 if (sort && t->dirty)
308 for (i = 0; i < t->count; ++i)
309 (*fe) (t->data[i], context);
313 netsnmp_binary_array_insert(netsnmp_container *c, const void *entry)
315 binary_array_table *t = (binary_array_table*)c->private;
317 void *new_data; /* Used for * a) extending the data table
318 * * b) the next entry to use */
320 if (t->max_size <= t->count) {
322 * Table is full, so extend it to double the size
324 new_max = 2 * t->max_size;
326 new_max = 10; /* Start with 10 entries */
328 new_data = (void *) calloc(new_max, t->data_size);
329 if (new_data == NULL)
333 memcpy(new_data, t->data, t->max_size * t->data_size);
337 t->max_size = new_max;
341 * Insert the new entry into the data array
343 t->data[t->count++] = (void*)entry;
349 netsnmp_binary_array_retrieve(netsnmp_container *c, int *max_oids, int sort)
351 binary_array_table *t = (binary_array_table*)c->private;
352 if (sort && t->dirty)
355 *max_oids = t->count;
359 /**********************************************************************
361 * Special case support for subsets
365 binary_search_for_start(netsnmp_index *val, netsnmp_container *c)
367 binary_array_table *t = (binary_array_table*)c->private;
368 size_t len = t->count;
384 if ((result = c->ncompare(t->data[middle], val)) < 0) {
387 len = len - half - 1;
392 if ((first >= t->count) ||
393 c->ncompare(t->data[first], val) != 0)
400 netsnmp_binary_array_get_subset(netsnmp_container *c, void *key, int *len)
402 binary_array_table *t = (binary_array_table*)c->private;
408 * if there is no data, return NULL;
410 if (!t->count || !key)
414 * if the table is dirty, sort it.
420 * find matching items
422 start = end = binary_search_for_start(key, c);
426 for (i = start + 1; i < t->count; ++i) {
427 if (0 != c->ncompare(t->data[i], key))
432 *len = end - start + 1;
433 subset = malloc((*len) * t->data_size);
434 memcpy(subset, &t->data[start], t->data_size * (*len));
439 /**********************************************************************
445 _ba_find(netsnmp_container *container, const void *data)
447 return netsnmp_binary_array_get(container, data, 1);
451 _ba_find_next(netsnmp_container *container, const void *data)
453 return netsnmp_binary_array_get(container, data, 0);
457 _ba_insert(netsnmp_container *container, const void *data)
459 return netsnmp_binary_array_insert(container, data);
463 _ba_remove(netsnmp_container *container, const void *data)
465 return netsnmp_binary_array_remove(container,data, NULL);
469 _ba_free(netsnmp_container *container)
471 netsnmp_binary_array_release(container);
476 _ba_size(netsnmp_container *container)
478 return netsnmp_binary_array_count(container);
482 _ba_for_each(netsnmp_container *container, netsnmp_container_obj_func *f,
485 netsnmp_binary_array_for_each(container, f, context, 0);
488 static netsnmp_void_array *
489 _ba_get_subset(netsnmp_container *container, void *data)
491 netsnmp_void_array * va;
495 rtn = netsnmp_binary_array_get_subset(container, data, &len);
496 if ((NULL==rtn) || (len <=0))
499 va = SNMP_MALLOC_TYPEDEF(netsnmp_void_array);
510 netsnmp_container_get_binary_array_noalloc(netsnmp_container *c)
515 c->private = netsnmp_binary_array_initialize();
517 c->get_size = _ba_size;
520 c->insert = _ba_insert;
521 c->remove = _ba_remove;
523 c->find_next = _ba_find_next;
524 c->get_subset = _ba_get_subset;
525 c->get_iterator = NULL;
526 c->for_each = _ba_for_each;
532 netsnmp_container_get_binary_array(void)
537 netsnmp_container *c = SNMP_MALLOC_TYPEDEF(netsnmp_container);
539 snmp_log(LOG_ERR, "couldn't allocate memory\n");
543 if (0 != netsnmp_container_get_binary_array_noalloc(c)) {
552 netsnmp_container_get_binary_array_factory(void)
554 static netsnmp_factory f = { "binary_array",
555 (netsnmp_factory_produce_f*)
556 netsnmp_container_get_binary_array,
557 (netsnmp_factory_produce_noalloc_f*)
558 netsnmp_container_get_binary_array_noalloc };
565 netsnmp_binary_array_iterator_first(netsnmp_iterator *it)
567 binary_array_table *t;
570 netsnmp_assert(NULL != it);
573 if(NULL == it->container) {
574 netsnmp_assert(NULL != it->container);
577 if(NULL == it->container->private) {
578 netsnmp_assert(NULL != it->container->private);
581 t = (binary_array_table*)(it->container->private);
583 (int)(it->context) = 0;
585 if((int)(it->context) <= t->count)
588 return t->data[ (int)(it->context) ];
591 netsnmp_binary_array_iterator_next(netsnmp_iterator *it)
594 netsnmp_assert(NULL != it);
597 if(NULL == it->container) {
598 netsnmp_assert(NULL != it->container);
601 if(NULL == it->container->private) {
602 netsnmp_assert(NULL != it->container->private);
605 t = (binary_array_table*)(it->container->private);
607 ++(int)(it->context);
609 if((int)(it->context) <= t->count)
612 return t->data[ (int)(it->context) ];
617 netsnmp_binary_array_iterator_last(netsnmp_iterator *it)
620 netsnmp_assert(NULL != it);
623 if(NULL == it->container) {
624 netsnmp_assert(NULL != it->container);
627 if(NULL == it->container->private) {
628 netsnmp_assert(NULL != it->container->private);
631 t = (binary_array_table*)(it->container->private);
633 return t->data[ t->count - 1 ];
637 /* netsnmp_binary_array_iterator_position(netsnmp_iterator *it) */
639 /* if(NULL == it) { */
640 /* netsnmp_assert(NULL != it); */
643 /* if(NULL == it->container) { */
644 /* netsnmp_assert(NULL != it->container); */
647 /* if(NULL == it->container->private) { */
648 /* netsnmp_assert(NULL != it->container->private); */
651 /* t = (binary_array_table*)(it->container->private); */
656 netsnmp_binary_array_get_iterator(netsnmp_container *c)
658 netsnmp_iterator* it;
663 it = SNMP_MALLOC_TYPEDEF(netsnmp_iterator);
668 (int)(it->context) = 0;
670 it->first = netsnmp_binary_array_iterator_first;
671 it->next = netsnmp_binary_array_iterator_next;
672 it->last = netsnmp_binary_array_iterator_last;
673 it->position = NULL;/*netsnmp_binary_array_iterator_position;*/
677 #endif /* BRCM_CONTAINER_SUPPORT */