net-snmp 5.7
container_binary_array.c
00001 /*
00002  * container_binary_array.c
00003  * $Id$
00004  *
00005  * see comments in header file.
00006  *
00007  */
00008 
00009 #include <net-snmp/net-snmp-config.h>
00010 
00011 #if HAVE_IO_H
00012 #include <io.h>
00013 #endif
00014 #include <stdio.h>
00015 #if HAVE_STDLIB_H
00016 #include <stdlib.h>
00017 #endif
00018 #if HAVE_MALLOC_H
00019 #include <malloc.h>
00020 #endif
00021 #include <sys/types.h>
00022 #if HAVE_STRING_H
00023 #include <string.h>
00024 #else
00025 #include <strings.h>
00026 #endif
00027 
00028 #include <net-snmp/net-snmp-includes.h>
00029 #include <net-snmp/types.h>
00030 #include <net-snmp/library/snmp_api.h>
00031 #include <net-snmp/library/container.h>
00032 #include <net-snmp/library/container_binary_array.h>
00033 #include <net-snmp/library/tools.h>
00034 #include <net-snmp/library/snmp_assert.h>
00035 
00036 typedef struct binary_array_table_s {
00037     size_t                     max_size;   /* Size of the current data table */
00038     size_t                     count;      /* Index of the next free entry */
00039     int                        dirty;
00040     void                     **data;       /* The table itself */
00041 } binary_array_table;
00042 
00043 typedef struct binary_array_iterator_s {
00044     netsnmp_iterator base;
00045 
00046     size_t           pos;
00047 } binary_array_iterator;
00048 
00049 static netsnmp_iterator *_ba_iterator_get(netsnmp_container *c);
00050 
00051 /**********************************************************************
00052  *
00053  * 
00054  *
00055  */
00056 static void
00057 array_qsort(void **data, int first, int last, netsnmp_container_compare *f)
00058 {
00059     int i, j;
00060     void *mid, *tmp;
00061     
00062     i = first;
00063     j = last;
00064     mid = data[(first+last)/2];
00065     
00066     do {
00067         while (i < last && (*f)(data[i], mid) < 0)
00068             ++i;
00069         while (j > first && (*f)(mid, data[j]) < 0)
00070             --j;
00071 
00072         if(i < j) {
00073             tmp = data[i];
00074             data[i] = data[j];
00075             data[j] = tmp;
00076             ++i;
00077             --j;
00078         }
00079         else if (i == j) {
00080             ++i;
00081             --j;
00082             break;
00083         }
00084     } while(i <= j);
00085 
00086     if (j > first)
00087         array_qsort(data, first, j, f);
00088     
00089     if (i < last)
00090         array_qsort(data, i, last, f);
00091 }
00092 
00093 static int
00094 Sort_Array(netsnmp_container *c)
00095 {
00096     binary_array_table *t = (binary_array_table*)c->container_data;
00097     netsnmp_assert(t!=NULL);
00098     netsnmp_assert(c->compare!=NULL);
00099 
00100     if (c->flags & CONTAINER_KEY_UNSORTED)
00101         return 0;
00102 
00103     if (t->dirty) {
00104         /*
00105          * Sort the table 
00106          */
00107         if (t->count > 1)
00108             array_qsort(t->data, 0, t->count - 1, c->compare);
00109         t->dirty = 0;
00110 
00111         /*
00112          * no way to know if it actually changed... just assume so.
00113          */
00114         ++c->sync;
00115     }
00116 
00117     return 1;
00118 }
00119 
00120 static int
00121 linear_search(const void *val, netsnmp_container *c)
00122 {
00123     binary_array_table *t = (binary_array_table*)c->container_data;
00124     size_t             pos = 0;
00125 
00126     if (!t->count)
00127         return -1;
00128 
00129     if (! (c->flags & CONTAINER_KEY_UNSORTED)) {
00130         snmp_log(LOG_ERR, "linear search on sorted container %s?!?\n",
00131                  c->container_name);
00132         return -1;
00133     }
00134 
00135     for (; pos < t->count; ++pos) {
00136         if (c->compare(t->data[pos], val) == 0)
00137             break;
00138     }
00139 
00140     if (pos >= t->count)
00141         return -1;
00142 
00143     return pos;
00144 }
00145 
00146 static int
00147 binary_search(const void *val, netsnmp_container *c, int exact)
00148 {
00149     binary_array_table *t = (binary_array_table*)c->container_data;
00150     size_t             len = t->count;
00151     size_t             half;
00152     size_t             middle = 0;
00153     size_t             first = 0;
00154     int                result = 0;
00155 
00156     if (!len)
00157         return -1;
00158 
00159     if (c->flags & CONTAINER_KEY_UNSORTED) {
00160         if (!exact) {
00161             snmp_log(LOG_ERR, "non-exact search on unsorted container %s?!?\n",
00162                      c->container_name);
00163             return -1;
00164         }
00165         return linear_search(val, c);
00166     }
00167 
00168     if (t->dirty)
00169         Sort_Array(c);
00170 
00171     while (len > 0) {
00172         half = len >> 1;
00173         middle = first;
00174         middle += half;
00175         if ((result =
00176              c->compare(t->data[middle], val)) < 0) {
00177             first = middle;
00178             ++first;
00179             len = len - half - 1;
00180         } else {
00181             if(result == 0) {
00182                 first = middle;
00183                 break;
00184             }
00185             len = half;
00186         }
00187     }
00188 
00189     if (first >= t->count)
00190         return -1;
00191 
00192     if(first != middle) {
00193         /* last compare wasn't against first, so get actual result */
00194         result = c->compare(t->data[first], val);
00195     }
00196 
00197     if(result == 0) {
00198         if (!exact) {
00199             if (++first == t->count)
00200                first = -1;
00201         }
00202     }
00203     else {
00204         if(exact)
00205             first = -1;
00206     }
00207 
00208     return first;
00209 }
00210 
00211 NETSNMP_STATIC_INLINE binary_array_table *
00212 netsnmp_binary_array_initialize(void)
00213 {
00214     binary_array_table *t;
00215 
00216     t = SNMP_MALLOC_TYPEDEF(binary_array_table);
00217     if (t == NULL)
00218         return NULL;
00219 
00220     t->max_size = 0;
00221     t->count = 0;
00222     t->dirty = 0;
00223     t->data = NULL;
00224 
00225     return t;
00226 }
00227 
00228 void
00229 netsnmp_binary_array_release(netsnmp_container *c)
00230 {
00231     binary_array_table *t = (binary_array_table*)c->container_data;
00232     SNMP_FREE(t->data);
00233     SNMP_FREE(t);
00234     SNMP_FREE(c);
00235 }
00236 
00237 int
00238 netsnmp_binary_array_options_set(netsnmp_container *c, int set, u_int flags)
00239 {
00240 #define BA_FLAGS (CONTAINER_KEY_ALLOW_DUPLICATES|CONTAINER_KEY_UNSORTED)
00241 
00242     if (set) {
00243         if ((flags & BA_FLAGS) == flags)
00244             c->flags = flags;
00245         else
00246             flags = (u_int)-1; /* unsupported flag */
00247     }
00248     else
00249         return ((c->flags & flags) == flags);
00250     return flags;
00251 }
00252 
00253 NETSNMP_STATIC_INLINE size_t
00254 netsnmp_binary_array_count(netsnmp_container *c)
00255 {
00256     binary_array_table *t = (binary_array_table*)c->container_data;
00257     /*
00258      * return count
00259      */
00260     return t ? t->count : 0;
00261 }
00262 
00263 NETSNMP_STATIC_INLINE void           *
00264 netsnmp_binary_array_get(netsnmp_container *c, const void *key, int exact)
00265 {
00266     binary_array_table *t = (binary_array_table*)c->container_data;
00267     int             index = 0;
00268 
00269     /*
00270      * if there is no data, return NULL;
00271      */
00272     if (!t->count)
00273         return NULL;
00274 
00275     /*
00276      * if the table is dirty, sort it.
00277      */
00278     if (t->dirty)
00279         Sort_Array(c);
00280 
00281     /*
00282      * if there is a key, search. Otherwise default is 0;
00283      */
00284     if (key) {
00285         if ((index = binary_search(key, c, exact)) == -1)
00286             return NULL;
00287     }
00288 
00289     return t->data[index];
00290 }
00291 
00292 int
00293 netsnmp_binary_array_remove_at(netsnmp_container *c, size_t index, void **save)
00294 {
00295     binary_array_table *t = (binary_array_table*)c->container_data;
00296 
00297     if (save)
00298         *save = NULL;
00299     
00300     /*
00301      * if there is no data, return NULL;
00302      */
00303     if (!t->count)
00304         return 0;
00305 
00306     /*
00307      * find old data and save it, if ptr provided
00308      */
00309     if (save)
00310         *save = t->data[index];
00311 
00312     /*
00313      * if entry was last item, just decrement count
00314      */
00315     --t->count;
00316     if (index != t->count) {
00317         /*
00318          * otherwise, shift array down
00319          */
00320         memmove(&t->data[index], &t->data[index+1],
00321                 sizeof(void*) * (t->count - index));
00322 
00323         ++c->sync;
00324     }
00325 
00326     return 0;
00327 }
00328 int
00329 netsnmp_binary_array_remove(netsnmp_container *c, const void *key, void **save)
00330 {
00331     binary_array_table *t = (binary_array_table*)c->container_data;
00332     int                index = 0;
00333 
00334     if (save)
00335         *save = NULL;
00336     
00337     /*
00338      * if there is no data, return NULL;
00339      */
00340     if (!t->count)
00341         return 0;
00342 
00343     /*
00344      * if the table is dirty, sort it.
00345      */
00346     if (t->dirty)
00347         Sort_Array(c);
00348 
00349     /*
00350      * search
00351      */
00352     if ((index = binary_search(key, c, 1)) == -1)
00353         return -1;
00354 
00355     return netsnmp_binary_array_remove_at(c, (size_t)index, save);
00356 }
00357 
00358 NETSNMP_STATIC_INLINE void
00359 netsnmp_binary_array_for_each(netsnmp_container *c,
00360                               netsnmp_container_obj_func *fe,
00361                               void *context, int sort)
00362 {
00363     binary_array_table *t = (binary_array_table*)c->container_data;
00364     size_t             i;
00365 
00366     if (sort && t->dirty)
00367         Sort_Array(c);
00368 
00369     for (i = 0; i < t->count; ++i)
00370         (*fe) (t->data[i], context);
00371 }
00372 
00373 NETSNMP_STATIC_INLINE void
00374 netsnmp_binary_array_clear(netsnmp_container *c,
00375                            netsnmp_container_obj_func *fe,
00376                            void *context)
00377 {
00378     binary_array_table *t = (binary_array_table*)c->container_data;
00379 
00380     if( NULL != fe ) {
00381         size_t             i;
00382 
00383         for (i = 0; i < t->count; ++i)
00384             (*fe) (t->data[i], context);
00385     }
00386 
00387     t->count = 0;
00388     t->dirty = 0;
00389     ++c->sync;
00390 }
00391 
00392 NETSNMP_STATIC_INLINE int
00393 netsnmp_binary_array_insert(netsnmp_container *c, const void *entry)
00394 {
00395     binary_array_table *t = (binary_array_table*)c->container_data;
00396     int             was_dirty = 0;
00397     /*
00398      * check for duplicates
00399      */
00400     if (! (c->flags & CONTAINER_KEY_ALLOW_DUPLICATES)) {
00401         was_dirty = t->dirty;
00402         if (NULL != netsnmp_binary_array_get(c, entry, 1)) {
00403             DEBUGMSGTL(("container","not inserting duplicate key\n"));
00404             return -1;
00405         }
00406     }
00407     
00408     /*
00409      * check if we need to resize the array
00410      */
00411     if (t->max_size <= t->count) {
00412         /*
00413          * Table is full, so extend it to double the size, or use 10 elements
00414          * if it is empty.
00415          */
00416         size_t const new_max = t->max_size > 0 ? 2 * t->max_size : 10;
00417         void ** const new_data =
00418             (void**) realloc(t->data, new_max * sizeof(void*));
00419 
00420         if (new_data == NULL)
00421             return -1;
00422 
00423         memset(new_data + t->max_size, 0x0,
00424                (new_max - t->max_size) * sizeof(void*));
00425 
00426         t->data = new_data;
00427         t->max_size = new_max;
00428     }
00429 
00430     /*
00431      * Insert the new entry into the data array
00432      */
00433     t->data[t->count++] = NETSNMP_REMOVE_CONST(void *, entry);
00434     t->dirty = 1;
00435 
00436     /*
00437      * if array was dirty before we called get, sync was incremented when
00438      * get called SortArray. If we didn't call get or the array wasn't dirty,
00439      * bump sync now.
00440      */
00441     if (!was_dirty)
00442         ++c->sync;
00443 
00444     return 0;
00445 }
00446 
00447 /**********************************************************************
00448  *
00449  * Special case support for subsets
00450  *
00451  */
00452 static int
00453 binary_search_for_start(netsnmp_index *val, netsnmp_container *c)
00454 {
00455     binary_array_table *t = (binary_array_table*)c->container_data;
00456     size_t             len = t->count;
00457     size_t             half;
00458     size_t             middle;
00459     size_t             first = 0;
00460     int                result = 0;
00461 
00462     if (!len)
00463         return -1;
00464 
00465     if (t->dirty)
00466         Sort_Array(c);
00467 
00468     while (len > 0) {
00469         half = len >> 1;
00470         middle = first;
00471         middle += half;
00472         if ((result = c->ncompare(t->data[middle], val)) < 0) {
00473             first = middle;
00474             ++first;
00475             len = len - half - 1;
00476         } else
00477             len = half;
00478     }
00479 
00480     if ((first >= t->count) ||
00481         c->ncompare(t->data[first], val) != 0)
00482         return -1;
00483 
00484     return first;
00485 }
00486 
00487 void          **
00488 netsnmp_binary_array_get_subset(netsnmp_container *c, void *key, int *len)
00489 {
00490     binary_array_table *t = (binary_array_table*)c->container_data;
00491     void          **subset;
00492     int             start, end;
00493     size_t          i;
00494 
00495     /*
00496      * if there is no data, return NULL;
00497      */
00498     if (!c || !key)
00499         return NULL;
00500 
00501     t = (binary_array_table*)c->container_data;
00502     netsnmp_assert(c->ncompare);
00503     if (!t->count | !c->ncompare)
00504         return NULL;
00505 
00506     /*
00507      * if the table is dirty, sort it.
00508      */
00509     if (t->dirty)
00510         Sort_Array(c);
00511 
00512     /*
00513      * find matching items
00514      */
00515     start = end = binary_search_for_start((netsnmp_index *)key, c);
00516     if (start == -1)
00517         return NULL;
00518 
00519     for (i = start + 1; i < t->count; ++i) {
00520         if (0 != c->ncompare(t->data[i], key))
00521             break;
00522         ++end;
00523     }
00524 
00525     *len = end - start + 1;
00526     subset = (void **)malloc((*len) * sizeof(void*));
00527     if (subset)
00528         memcpy(subset, &t->data[start], sizeof(void*) * (*len));
00529 
00530     return subset;
00531 }
00532 
00533 /**********************************************************************
00534  *
00535  * container
00536  *
00537  */
00538 static void *
00539 _ba_find(netsnmp_container *container, const void *data)
00540 {
00541     return netsnmp_binary_array_get(container, data, 1);
00542 }
00543 
00544 static void *
00545 _ba_find_next(netsnmp_container *container, const void *data)
00546 {
00547     return netsnmp_binary_array_get(container, data, 0);
00548 }
00549 
00550 static int
00551 _ba_insert(netsnmp_container *container, const void *data)
00552 {
00553     return netsnmp_binary_array_insert(container, data);
00554 }
00555 
00556 static int
00557 _ba_remove(netsnmp_container *container, const void *data)
00558 {
00559     return netsnmp_binary_array_remove(container,data, NULL);
00560 }
00561 
00562 static int
00563 _ba_free(netsnmp_container *container)
00564 {
00565     netsnmp_binary_array_release(container);
00566     return 0;
00567 }
00568 
00569 static size_t
00570 _ba_size(netsnmp_container *container)
00571 {
00572     return netsnmp_binary_array_count(container);
00573 }
00574 
00575 static void
00576 _ba_for_each(netsnmp_container *container, netsnmp_container_obj_func *f,
00577              void *context)
00578 {
00579     netsnmp_binary_array_for_each(container, f, context, 1);
00580 }
00581 
00582 static void
00583 _ba_clear(netsnmp_container *container, netsnmp_container_obj_func *f,
00584              void *context)
00585 {
00586     netsnmp_binary_array_clear(container, f, context);
00587 }
00588 
00589 static netsnmp_void_array *
00590 _ba_get_subset(netsnmp_container *container, void *data)
00591 {
00592     netsnmp_void_array * va;
00593     void ** rtn;
00594     int len;
00595 
00596     rtn = netsnmp_binary_array_get_subset(container, data, &len);
00597     if ((NULL==rtn) || (len <=0))
00598         return NULL;
00599     
00600     va = SNMP_MALLOC_TYPEDEF(netsnmp_void_array);
00601     if (NULL==va)
00602     {
00603         free (rtn);
00604         return NULL;
00605     }
00606     
00607     va->size = len;
00608     va->array = rtn;
00609 
00610     return va;
00611 }
00612 
00613 static int _ba_options(netsnmp_container *c, int set, u_int flags)
00614 {
00615     return netsnmp_binary_array_options_set(c, set, flags);
00616 }
00617 
00618 static netsnmp_container *
00619 _ba_duplicate(netsnmp_container *c, void *ctx, u_int flags)
00620 {
00621     netsnmp_container *dup;
00622     binary_array_table *dupt, *t;
00623 
00624     if (flags) {
00625         snmp_log(LOG_ERR, "binary arry duplicate does not supprt flags yet\n");
00626         return NULL;
00627     }
00628 
00629     dup = netsnmp_container_get_binary_array();
00630     if (NULL == dup) {
00631         snmp_log(LOG_ERR," no memory for binary array duplicate\n");
00632         return NULL;
00633     }
00634     /*
00635      * deal with container stuff
00636      */
00637     if (netsnmp_container_data_dup(dup, c) != 0) {
00638         netsnmp_binary_array_release(dup);
00639         return NULL;
00640     }
00641 
00642     /*
00643      * deal with data
00644      */
00645     dupt = (binary_array_table*)dup->container_data;
00646     t = (binary_array_table*)c->container_data;
00647 
00648     dupt->max_size = t->max_size;
00649     dupt->count = t->count;
00650     dupt->dirty = t->dirty;
00651 
00652     /*
00653      * shallow copy
00654      */
00655     dupt->data = (void**) malloc(dupt->max_size * sizeof(void*));
00656     if (NULL == dupt->data) {
00657         snmp_log(LOG_ERR, "no memory for binary array duplicate\n");
00658         netsnmp_binary_array_release(dup);
00659         return NULL;
00660     }
00661 
00662     memcpy(dupt->data, t->data, dupt->max_size * sizeof(void*));
00663 
00664     return dup;
00665 }
00666 
00667 netsnmp_container *
00668 netsnmp_container_get_binary_array(void)
00669 {
00670     /*
00671      * allocate memory
00672      */
00673     netsnmp_container *c = SNMP_MALLOC_TYPEDEF(netsnmp_container);
00674     if (NULL==c) {
00675         snmp_log(LOG_ERR, "couldn't allocate memory\n");
00676         return NULL;
00677     }
00678 
00679     c->container_data = netsnmp_binary_array_initialize();
00680 
00681     /*
00682      * NOTE: CHANGES HERE MUST BE DUPLICATED IN duplicate AS WELL!!
00683      */
00684     netsnmp_init_container(c, NULL, _ba_free, _ba_size, NULL, _ba_insert,
00685                            _ba_remove, _ba_find);
00686     c->find_next = _ba_find_next;
00687     c->get_subset = _ba_get_subset;
00688     c->get_iterator = _ba_iterator_get;
00689     c->for_each = _ba_for_each;
00690     c->clear = _ba_clear;
00691     c->options = _ba_options;
00692     c->duplicate = _ba_duplicate;
00693         
00694     return c;
00695 }
00696 
00697 netsnmp_factory *
00698 netsnmp_container_get_binary_array_factory(void)
00699 {
00700     static netsnmp_factory f = { "binary_array",
00701                                  (netsnmp_factory_produce_f*)
00702                                  netsnmp_container_get_binary_array };
00703     
00704     return &f;
00705 }
00706 
00707 void
00708 netsnmp_container_binary_array_init(void)
00709 {
00710     netsnmp_container_register("binary_array",
00711                                netsnmp_container_get_binary_array_factory());
00712 }
00713 
00714 /**********************************************************************
00715  *
00716  * iterator
00717  *
00718  */
00719 NETSNMP_STATIC_INLINE binary_array_table *
00720 _ba_it2cont(binary_array_iterator *it)
00721 {
00722     if(NULL == it) {
00723         netsnmp_assert(NULL != it);
00724         return NULL;
00725     }
00726     if(NULL == it->base.container) {
00727         netsnmp_assert(NULL != it->base.container);
00728         return NULL;
00729     }
00730     if(NULL == it->base.container->container_data) {
00731         netsnmp_assert(NULL != it->base.container->container_data);
00732         return NULL;
00733     }
00734 
00735     return (binary_array_table*)(it->base.container->container_data);
00736 }
00737 
00738 NETSNMP_STATIC_INLINE void *
00739 _ba_iterator_position(binary_array_iterator *it, size_t pos)
00740 {
00741     binary_array_table *t = _ba_it2cont(it);
00742     if (NULL == t)
00743         return t; /* msg already logged */
00744 
00745     if(it->base.container->sync != it->base.sync) {
00746         DEBUGMSGTL(("container:iterator", "out of sync\n"));
00747         return NULL;
00748     }
00749     
00750     if(0 == t->count) {
00751         DEBUGMSGTL(("container:iterator", "empty\n"));
00752         return NULL;
00753     }
00754     else if(pos >= t->count) {
00755         DEBUGMSGTL(("container:iterator", "end of container\n"));
00756         return NULL;
00757     }
00758 
00759     return t->data[ pos ];
00760 }
00761 
00762 static void *
00763 _ba_iterator_curr(binary_array_iterator *it)
00764 {
00765     if(NULL == it) {
00766         netsnmp_assert(NULL != it);
00767         return NULL;
00768     }
00769 
00770     return _ba_iterator_position(it, it->pos);
00771 }
00772 
00773 static void *
00774 _ba_iterator_first(binary_array_iterator *it)
00775 {
00776     return _ba_iterator_position(it, 0);
00777 }
00778 
00779 static void *
00780 _ba_iterator_next(binary_array_iterator *it)
00781 {
00782     if(NULL == it) {
00783         netsnmp_assert(NULL != it);
00784         return NULL;
00785     }
00786 
00787     ++it->pos;
00788 
00789     return _ba_iterator_position(it, it->pos);
00790 }
00791 
00792 static void *
00793 _ba_iterator_last(binary_array_iterator *it)
00794 {
00795     binary_array_table* t = _ba_it2cont(it);
00796     if(NULL == t) {
00797         netsnmp_assert(NULL != t);
00798         return NULL;
00799     }
00800     
00801     return _ba_iterator_position(it, t->count - 1 );
00802 }
00803 
00804 static int
00805 _ba_iterator_remove(binary_array_iterator *it)
00806 {
00807     binary_array_table* t = _ba_it2cont(it);
00808     if(NULL == t) {
00809         netsnmp_assert(NULL != t);
00810         return -1;
00811     }
00812 
00813     /*
00814      * since this iterator was used for the remove, keep it in sync with
00815      * the container. Also, back up one so that next will be the position
00816      * that was just removed.
00817      */
00818     ++it->base.sync;
00819     return netsnmp_binary_array_remove_at(it->base.container, it->pos--, NULL);
00820 
00821 }
00822 
00823 static int
00824 _ba_iterator_reset(binary_array_iterator *it)
00825 {
00826     binary_array_table* t = _ba_it2cont(it);
00827     if(NULL == t) {
00828         netsnmp_assert(NULL != t);
00829         return -1;
00830     }
00831 
00832     if (t->dirty)
00833         Sort_Array(it->base.container);
00834 
00835     /*
00836      * save sync count, to make sure container doesn't change while
00837      * iterator is in use.
00838      */
00839     it->base.sync = it->base.container->sync;
00840 
00841     it->pos = 0;
00842 
00843     return 0;
00844 }
00845 
00846 static int
00847 _ba_iterator_release(netsnmp_iterator *it)
00848 {
00849     free(it);
00850 
00851     return 0;
00852 }
00853 
00854 static netsnmp_iterator *
00855 _ba_iterator_get(netsnmp_container *c)
00856 {
00857     binary_array_iterator* it;
00858 
00859     if(NULL == c)
00860         return NULL;
00861 
00862     it = SNMP_MALLOC_TYPEDEF(binary_array_iterator);
00863     if(NULL == it)
00864         return NULL;
00865 
00866     it->base.container = c;
00867     
00868     it->base.first = (netsnmp_iterator_rtn*)_ba_iterator_first;
00869     it->base.next = (netsnmp_iterator_rtn*)_ba_iterator_next;
00870     it->base.curr = (netsnmp_iterator_rtn*)_ba_iterator_curr;
00871     it->base.last = (netsnmp_iterator_rtn*)_ba_iterator_last;
00872     it->base.remove = (netsnmp_iterator_rc*)_ba_iterator_remove;
00873     it->base.reset = (netsnmp_iterator_rc*)_ba_iterator_reset;
00874     it->base.release = (netsnmp_iterator_rc*)_ba_iterator_release;
00875 
00876     (void)_ba_iterator_reset(it);
00877 
00878     return (netsnmp_iterator *)it;
00879 }