container_binary_array.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:15k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * container_binary_array.c
  3.  * $Id: container_binary_array.c,v 1.17.2.1 2005/06/13 16:16:31 dts12 Exp $
  4.  *
  5.  * see comments in header file.
  6.  *
  7.  */
  8. #include <net-snmp/net-snmp-config.h>
  9. #if HAVE_IO_H
  10. #include <io.h>
  11. #endif
  12. #include <stdio.h>
  13. #if HAVE_STDLIB_H
  14. #include <stdlib.h>
  15. #endif
  16. #if HAVE_MALLOC_H
  17. #include <malloc.h>
  18. #endif
  19. #include <sys/types.h>
  20. #if HAVE_STRING_H
  21. #include <string.h>
  22. #else
  23. #include <strings.h>
  24. #endif
  25. #include <net-snmp/net-snmp-includes.h>
  26. #include <net-snmp/types.h>
  27. #include <net-snmp/library/snmp_api.h>
  28. #include <net-snmp/library/container.h>
  29. #include <net-snmp/library/container_binary_array.h>
  30. #include <net-snmp/library/tools.h>
  31. #include <net-snmp/library/snmp_assert.h>
  32. typedef struct binary_array_table_s {
  33.     size_t                     max_size;   /* Size of the current data table */
  34.     size_t                     count;      /* Index of the next free entry */
  35.     int                        dirty;
  36.     int                        data_size;  /* Size of an individual entry */
  37.     void                     **data;       /* The table itself */
  38. } binary_array_table;
  39. static void
  40. array_qsort(void **data, int first, int last, netsnmp_container_compare *f)
  41. {
  42.     int i, j;
  43.     void *mid, *tmp;
  44.     
  45.     i = first;
  46.     j = last;
  47.     mid = data[(first+last)/2];
  48.     
  49.     do {
  50.         while ( ((*f)(data[i], mid) < 0) && (i < last))
  51.             ++i;
  52.         while ( ((*f)(mid, data[j]) < 0) && (j > first))
  53.             --j;
  54.         if(i < j) {
  55.             tmp = data[i];
  56.             data[i] = data[j];
  57.             data[j] = tmp;
  58.             ++i;
  59.             --j;
  60.         }
  61.         else if (i == j) {
  62.             ++i;
  63.             --j;
  64.             break;
  65.         }
  66.     } while(i <= j);
  67.     if (j > first)
  68.         array_qsort(data, first, j, f);
  69.     
  70.     if (i < last)
  71.         array_qsort(data, i, last, f);
  72. }
  73. static int
  74. Sort_Array(netsnmp_container *c)
  75. {
  76.     binary_array_table *t = (binary_array_table*)c->container_data;
  77.     netsnmp_assert(t!=NULL);
  78.     netsnmp_assert(c->compare!=NULL);
  79.     
  80.     if (t->dirty) {
  81.         /*
  82.          * Sort the table 
  83.          */
  84.         if (t->count > 1)
  85.             array_qsort(t->data, 0, t->count - 1, c->compare);
  86.         t->dirty = 0;
  87.     }
  88.     return 1;
  89. }
  90. static int
  91. binary_search(const void *val, netsnmp_container *c, int exact)
  92. {
  93.     binary_array_table *t = (binary_array_table*)c->container_data;
  94.     size_t             len = t->count;
  95.     size_t             half;
  96.     size_t             middle = 0;
  97.     size_t             first = 0;
  98.     int                result = 0;
  99.     if (!len)
  100.         return -1;
  101.     if (t->dirty)
  102.         Sort_Array(c);
  103.     while (len > 0) {
  104.         half = len >> 1;
  105.         middle = first;
  106.         middle += half;
  107.         if ((result =
  108.              c->compare(t->data[middle], val)) < 0) {
  109.             first = middle;
  110.             ++first;
  111.             len = len - half - 1;
  112.         } else {
  113.             if(result == 0) {
  114.                 first = middle;
  115.                 break;
  116.             }
  117.             len = half;
  118.         }
  119.     }
  120.     if (first >= t->count)
  121.         return -1;
  122.     if(first != middle) {
  123.         /* last compare wasn't against first, so get actual result */
  124.         result = c->compare(t->data[first], val);
  125.     }
  126.     if(result == 0) {
  127.         if (!exact) {
  128.             if (++first == t->count)
  129.                first = -1;
  130.         }
  131.     }
  132.     else {
  133.         if(exact)
  134.             first = -1;
  135.     }
  136.     return first;
  137. }
  138. NETSNMP_STATIC_INLINE binary_array_table *
  139. netsnmp_binary_array_initialize(void)
  140. {
  141.     binary_array_table *t;
  142.     t = SNMP_MALLOC_TYPEDEF(binary_array_table);
  143.     if (t == NULL)
  144.         return NULL;
  145.     t->max_size = 0;
  146.     t->count = 0;
  147.     t->dirty = 0;
  148.     t->data_size = sizeof(void*);
  149.     t->data = NULL;
  150.     return t;
  151. }
  152. void
  153. netsnmp_binary_array_release(netsnmp_container *c)
  154. {
  155.     binary_array_table *t = (binary_array_table*)c->container_data;
  156.     if (t->data != NULL) {
  157. SNMP_FREE(t->data);
  158.     }
  159.     SNMP_FREE(t);
  160.     SNMP_FREE(c);
  161. }
  162. NETSNMP_STATIC_INLINE size_t
  163. netsnmp_binary_array_count(netsnmp_container *c)
  164. {
  165.     binary_array_table *t = (binary_array_table*)c->container_data;
  166.     /*
  167.      * return count
  168.      */
  169.     return t ? t->count : 0;
  170. }
  171. NETSNMP_STATIC_INLINE void           *
  172. netsnmp_binary_array_get(netsnmp_container *c, const void *key, int exact)
  173. {
  174.     binary_array_table *t = (binary_array_table*)c->container_data;
  175.     int             index = 0;
  176.     /*
  177.      * if there is no data, return NULL;
  178.      */
  179.     if (!t->count)
  180.         return 0;
  181.     /*
  182.      * if the table is dirty, sort it.
  183.      */
  184.     if (t->dirty)
  185.         Sort_Array(c);
  186.     /*
  187.      * if there is a key, search. Otherwise default is 0;
  188.      */
  189.     if (key) {
  190.         if ((index = binary_search(key, c, exact)) == -1)
  191.             return 0;
  192.     }
  193.     return t->data[index];
  194. }
  195. NETSNMP_STATIC_INLINE int
  196. netsnmp_binary_array_replace(netsnmp_container *c, void *entry)
  197. {
  198.     binary_array_table *t = (binary_array_table*)c->container_data;
  199.     int             index = 0;
  200.     /*
  201.      * if there is no data, return NULL;
  202.      */
  203.     if (!t->count)
  204.         return 0;
  205.     /*
  206.      * if the table is dirty, sort it.
  207.      */
  208.     if (t->dirty)
  209.         Sort_Array(c);
  210.     /*
  211.      * search
  212.      */
  213.     if ((index = binary_search(entry, c, 1)) == -1)
  214.         return 0;
  215.     t->data[index] = entry;
  216.     return 0;
  217. }
  218. int
  219. netsnmp_binary_array_remove(netsnmp_container *c, const void *key, void **save)
  220. {
  221.     binary_array_table *t = (binary_array_table*)c->container_data;
  222.     int             index = 0;
  223.     if (save)
  224.         *save = NULL;
  225.     
  226.     /*
  227.      * if there is no data, return NULL;
  228.      */
  229.     if (!t->count)
  230.         return 0;
  231.     /*
  232.      * if the table is dirty, sort it.
  233.      */
  234.     if (t->dirty)
  235.         Sort_Array(c);
  236.     /*
  237.      * search
  238.      */
  239.     if ((index = binary_search(key, c, 1)) == -1)
  240.         return -1;
  241.     /*
  242.      * find old data and save it, if ptr provided
  243.      */
  244.     if (save)
  245.         *save = t->data[index];
  246.     /*
  247.      * if entry was last item, just decrement count
  248.      */
  249.     --t->count;
  250.     if (index != (int)t->count) {
  251.         /*
  252.          * otherwise, shift array down
  253.          */
  254.         memmove(&t->data[index], &t->data[index+1], t->data_size * (t->count - index));
  255.     }
  256.     return 0;
  257. }
  258. NETSNMP_STATIC_INLINE void
  259. netsnmp_binary_array_for_each(netsnmp_container *c,
  260.                               netsnmp_container_obj_func *fe,
  261.                               void *context, int sort)
  262. {
  263.     binary_array_table *t = (binary_array_table*)c->container_data;
  264.     size_t             i;
  265.     if (sort && t->dirty)
  266.         Sort_Array(c);
  267.     for (i = 0; i < t->count; ++i)
  268.         (*fe) (t->data[i], context);
  269. }
  270. NETSNMP_STATIC_INLINE void
  271. netsnmp_binary_array_clear(netsnmp_container *c,
  272.                            netsnmp_container_obj_func *fe,
  273.                            void *context)
  274. {
  275.     binary_array_table *t = (binary_array_table*)c->container_data;
  276.     if( NULL != fe ) {
  277.         size_t             i;
  278.         for (i = 0; i < t->count; ++i)
  279.             (*fe) (t->data[i], context);
  280.     }
  281.     t->count = 0;
  282.     t->dirty = 0;
  283. }
  284. NETSNMP_STATIC_INLINE int
  285. netsnmp_binary_array_insert(netsnmp_container *c, const void *entry)
  286. {
  287.     binary_array_table *t = (binary_array_table*)c->container_data;
  288.     int             new_max;
  289.     void           *new_data;   /* Used for * a) extending the data table
  290.                                  * * b) the next entry to use */
  291.     if (t->max_size <= t->count) {
  292.         /*
  293.          * Table is full, so extend it to double the size
  294.          */
  295.         new_max = 2 * t->max_size;
  296.         if (new_max == 0)
  297.             new_max = 10;       /* Start with 10 entries */
  298.         new_data = (void *) calloc(new_max, t->data_size);
  299.         if (new_data == NULL)
  300.             return -1;
  301.         if (t->data) {
  302.             memcpy(new_data, t->data, t->max_size * t->data_size);
  303.             SNMP_FREE(t->data);
  304.         }
  305.         t->data = new_data;
  306.         t->max_size = new_max;
  307.     }
  308.     /*
  309.      * Insert the new entry into the data array
  310.      */
  311.     t->data[t->count++] = (void*)entry;
  312.     t->dirty = 1;
  313.     return 0;
  314. }
  315. NETSNMP_STATIC_INLINE void           *
  316. netsnmp_binary_array_retrieve(netsnmp_container *c, int *max_oids, int sort)
  317. {
  318.     binary_array_table *t = (binary_array_table*)c->container_data;
  319.     if (sort && t->dirty)
  320.         Sort_Array(c);
  321.     *max_oids = t->count;
  322.     return t->data;
  323. }
  324. /**********************************************************************
  325.  *
  326.  * Special case support for subsets
  327.  *
  328.  */
  329. static int
  330. binary_search_for_start(netsnmp_index *val, netsnmp_container *c)
  331. {
  332.     binary_array_table *t = (binary_array_table*)c->container_data;
  333.     size_t             len = t->count;
  334.     size_t             half;
  335.     size_t             middle;
  336.     size_t             first = 0;
  337.     int                result = 0;
  338.     if (!len)
  339.         return -1;
  340.     if (t->dirty)
  341.         Sort_Array(c);
  342.     while (len > 0) {
  343.         half = len >> 1;
  344.         middle = first;
  345.         middle += half;
  346.         if ((result = c->ncompare(t->data[middle], val)) < 0) {
  347.             first = middle;
  348.             ++first;
  349.             len = len - half - 1;
  350.         } else
  351.             len = half;
  352.     }
  353.     if ((first >= t->count) ||
  354.         c->ncompare(t->data[first], val) != 0)
  355.         return -1;
  356.     return first;
  357. }
  358. void          **
  359. netsnmp_binary_array_get_subset(netsnmp_container *c, void *key, int *len)
  360. {
  361.     binary_array_table *t = (binary_array_table*)c->container_data;
  362.     void          **subset;
  363.     int             start, end;
  364.     size_t          i;
  365.     /*
  366.      * if there is no data, return NULL;
  367.      */
  368.     if (!t->count || !key)
  369.         return 0;
  370.     /*
  371.      * if the table is dirty, sort it.
  372.      */
  373.     if (t->dirty)
  374.         Sort_Array(c);
  375.     /*
  376.      * find matching items
  377.      */
  378.     start = end = binary_search_for_start(key, c);
  379.     if (start == -1)
  380.         return 0;
  381.     for (i = start + 1; i < t->count; ++i) {
  382.         if (0 != c->ncompare(t->data[i], key))
  383.             break;
  384.         ++end;
  385.     }
  386.     *len = end - start + 1;
  387.     subset = malloc((*len) * t->data_size);
  388.     if (subset)
  389.         memcpy(subset, &t->data[start], t->data_size * (*len));
  390.     return subset;
  391. }
  392. /**********************************************************************
  393.  *
  394.  * container
  395.  *
  396.  */
  397. static void *
  398. _ba_find(netsnmp_container *container, const void *data)
  399. {
  400.     return netsnmp_binary_array_get(container, data, 1);
  401. }
  402. static void *
  403. _ba_find_next(netsnmp_container *container, const void *data)
  404. {
  405.     return netsnmp_binary_array_get(container, data, 0);
  406. }
  407. static int
  408. _ba_insert(netsnmp_container *container, const void *data)
  409. {
  410.     return netsnmp_binary_array_insert(container, data);
  411. }
  412. static int
  413. _ba_remove(netsnmp_container *container, const void *data)
  414. {
  415.     return netsnmp_binary_array_remove(container,data, NULL);
  416. }
  417. static int
  418. _ba_free(netsnmp_container *container)
  419. {
  420.     netsnmp_binary_array_release(container);
  421.     return 0;
  422. }
  423. static size_t
  424. _ba_size(netsnmp_container *container)
  425. {
  426.     return netsnmp_binary_array_count(container);
  427. }
  428. static void
  429. _ba_for_each(netsnmp_container *container, netsnmp_container_obj_func *f,
  430.              void *context)
  431. {
  432.     netsnmp_binary_array_for_each(container, f, context, 1);
  433. }
  434. static void
  435. _ba_clear(netsnmp_container *container, netsnmp_container_obj_func *f,
  436.              void *context)
  437. {
  438.     netsnmp_binary_array_clear(container, f, context);
  439. }
  440. static netsnmp_void_array *
  441. _ba_get_subset(netsnmp_container *container, void *data)
  442. {
  443.     netsnmp_void_array * va;
  444.     void ** rtn;
  445.     int len;
  446.     rtn = netsnmp_binary_array_get_subset(container, data, &len);
  447.     if ((NULL==rtn) || (len <=0))
  448.         return NULL;
  449.     
  450.     va = SNMP_MALLOC_TYPEDEF(netsnmp_void_array);
  451.     if (NULL==va)
  452.         return NULL;
  453.     va->size = len;
  454.     va->array = rtn;
  455.     return va;
  456. }
  457. netsnmp_container *
  458. netsnmp_container_get_binary_array(void)
  459. {
  460.     /*
  461.      * allocate memory
  462.      */
  463.     netsnmp_container *c = SNMP_MALLOC_TYPEDEF(netsnmp_container);
  464.     if (NULL==c) {
  465.         snmp_log(LOG_ERR, "couldn't allocate memoryn");
  466.         return NULL;
  467.     }
  468.     c->container_data = netsnmp_binary_array_initialize();
  469.         
  470.     c->get_size = _ba_size;
  471.     c->init = NULL;
  472.     c->cfree = _ba_free;
  473.     c->insert = _ba_insert;
  474.     c->remove = _ba_remove;
  475.     c->find = _ba_find;
  476.     c->find_next = _ba_find_next;
  477.     c->get_subset = _ba_get_subset;
  478.     c->get_iterator = NULL;
  479.     c->for_each = _ba_for_each;
  480.     c->clear = _ba_clear;
  481.         
  482.     return c;
  483. }
  484. netsnmp_factory *
  485. netsnmp_container_get_binary_array_factory(void)
  486. {
  487.     static netsnmp_factory f = { "binary_array",
  488.                                  (netsnmp_factory_produce_f*)
  489.                                  netsnmp_container_get_binary_array };
  490.     
  491.     return &f;
  492. }
  493. void
  494. netsnmp_container_binary_array_init(void)
  495. {
  496.     netsnmp_container_register("binary_array",
  497.                                netsnmp_container_get_binary_array_factory());
  498. }
  499. #ifdef NOT_YET
  500. void *
  501. netsnmp_binary_array_iterator_first(netsnmp_iterator *it)
  502. {
  503.     binary_array_table *t;
  504.     if(NULL == it) {
  505.         netsnmp_assert(NULL != it);
  506.         return NULL;
  507.     }
  508.     if(NULL == it->container) {
  509.         netsnmp_assert(NULL != it->container);
  510.         return NULL;
  511.     }
  512.     if(NULL == it->container->container_data) {
  513.         netsnmp_assert(NULL != it->container->container_data);
  514.         return NULL;
  515.     }
  516.     t = (binary_array_table*)(it->container->container_data);
  517.     
  518.     (int)(it->context) = 0;
  519.     if((int)(it->context) <= t->count)
  520.         return NULL;
  521.     return t->data[ (int)(it->context) ];
  522. }
  523. netsnmp_binary_array_iterator_next(netsnmp_iterator *it)
  524. {
  525.     if(NULL == it) {
  526.         netsnmp_assert(NULL != it);
  527.         return NULL;
  528.     }
  529.     if(NULL == it->container) {
  530.         netsnmp_assert(NULL != it->container);
  531.         return NULL;
  532.     }
  533.     if(NULL == it->container->container_data) {
  534.         netsnmp_assert(NULL != it->container->container_data);
  535.         return NULL;
  536.     }
  537.     t = (binary_array_table*)(it->container->container_data);
  538.     ++(int)(it->context);
  539.     if((int)(it->context) <= t->count)
  540.         return NULL;
  541.     return t->data[ (int)(it->context) ];
  542.    
  543. }
  544. void *
  545. netsnmp_binary_array_iterator_last(netsnmp_iterator *it)
  546. {
  547.     if(NULL == it) {
  548.         netsnmp_assert(NULL != it);
  549.         return NULL;
  550.     }
  551.     if(NULL == it->container) {
  552.         netsnmp_assert(NULL != it->container);
  553.         return NULL;
  554.     }
  555.     if(NULL == it->container->container_data) {
  556.         netsnmp_assert(NULL != it->container->container_data);
  557.         return NULL;
  558.     }
  559.     t = (binary_array_table*)(it->container->container_data);
  560.     
  561.     return t->data[ t->count - 1 ];
  562. }
  563. /*  void * */
  564. /*  netsnmp_binary_array_iterator_position(netsnmp_iterator *it) */
  565. /*  { */
  566. /*      if(NULL == it) { */
  567. /*          netsnmp_assert(NULL != it); */
  568. /*          return NULL; */
  569. /*      } */
  570. /*      if(NULL == it->container) { */
  571. /*          netsnmp_assert(NULL != it->container); */
  572. /*          return NULL; */
  573. /*      } */
  574. /*      if(NULL == it->container->container_data) { */
  575. /*          netsnmp_assert(NULL != it->container->container_data); */
  576. /*          return NULL; */
  577. /*      } */
  578. /*      t = (binary_array_table*)(it->container->container_data); */
  579.     
  580. /*  } */
  581. netsnmp_iterator *
  582. netsnmp_binary_array_iterator_get(netsnmp_container *c)
  583. {
  584.     netsnmp_iterator* it;
  585.     if(NULL == c)
  586.         return NULL;
  587.     it = SNMP_MALLOC_TYPEDEF(netsnmp_iterator);
  588.     if(NULL == it)
  589.         return NULL;
  590.     it->container = c;
  591.     (int)(it->context) = 0;
  592.     it->first = netsnmp_binary_array_iterator_first;
  593.     it->next = netsnmp_binary_array_iterator_next;
  594.     it->last = netsnmp_binary_array_iterator_last;
  595.     it->position = NULL;/*netsnmp_binary_array_iterator_position;*/
  596. }
  597. #endif