container.h

00001 #ifndef NETSNMP_CONTAINER_H
00002 #define NETSNMP_CONTAINER_H
00003 
00004 /*
00005  * $Id: container.h 13803 2005-12-04 18:43:04Z rstory $
00006  *
00007  * WARNING: This is a recently created file, and all of it's contents are
00008  *          subject to change at any time.
00009  *
00010  * A basic container template. A generic way for code to store and
00011  * retrieve data. Allows for interchangable storage algorithms.
00012  */
00013 #ifndef NET_SNMP_CONFIG_H
00014 #error "Please include <net-snmp/net-snmp-config.h> before this file"
00015 #endif
00016 
00017 #include <net-snmp/types.h>
00018 #include <net-snmp/library/factory.h>
00019 #include <net-snmp/library/snmp_logging.h>
00020 
00021 #ifdef  __cplusplus
00022 extern "C" {
00023 #endif
00024 
00025     /*************************************************************************
00026      *
00027      * function pointer definitions
00028      *
00029      *************************************************************************/
00030     struct netsnmp_iterator_s; 
00031     struct netsnmp_container_s; 
00033     /*
00034      * function returning an int for an operation on a container
00035      */
00036     typedef int (netsnmp_container_option)(struct netsnmp_container_s *,
00037                                            int set, u_int flags);
00038 
00039     /*
00040      * function returning an int for an operation on a container
00041      */
00042     typedef int (netsnmp_container_rc)(struct netsnmp_container_s *);
00043 
00044     /*
00045      * function returning an iterator for a container
00046      */
00047     typedef struct netsnmp_iterator_s * (netsnmp_container_it)
00048         (struct netsnmp_container_s *);
00049 
00050     /*
00051      * function returning a size_t for an operation on a container
00052      */
00053     typedef size_t (netsnmp_container_size)(struct netsnmp_container_s *);
00054 
00055     /*
00056      * function returning an int for an operation on an object and
00057      * a container
00058      */
00059     typedef int (netsnmp_container_op)(struct netsnmp_container_s *,
00060                                        const void *data);
00061 
00062     /*
00063      * function returning an oject for an operation on an object and a
00064      * container
00065      */
00066     typedef void * (netsnmp_container_rtn)(struct netsnmp_container_s *,
00067                                            const void *data);
00068 
00069     /*
00070      * function with no return which acts on an object
00071      */
00072     typedef void (netsnmp_container_obj_func)(void *data, void *context);
00073 
00074     /*
00075      * function with no return which calls a function on an object
00076      */
00077     typedef void (netsnmp_container_func)(struct netsnmp_container_s *,
00078                                           netsnmp_container_obj_func *,
00079                                           void *context);
00080 
00081     /*
00082      * function returning an array of objects for an operation on an
00083      * ojbect and a container
00084      */
00085     typedef netsnmp_void_array * (netsnmp_container_set)
00086         (struct netsnmp_container_s *, void *data);
00087 
00088     /*
00089      * function returning an int for a comparison between two objects
00090      */
00091     typedef int (netsnmp_container_compare)(const void *lhs,
00092                                             const void *rhs);
00093 
00094     /*************************************************************************
00095      *
00096      * Basic container
00097      *
00098      *************************************************************************/
00099     typedef struct netsnmp_container_s {
00100        
00101        /*
00102         * pointer for container implementation
00103         */
00104        void *         container_data;
00105 
00106        /*
00107         * returns the number of items in a container
00108         */
00109        netsnmp_container_size  *get_size;
00110        
00111        /*
00112         * initialize a container
00113         */
00114        netsnmp_container_rc    *init;
00115 
00116        /*
00117         * release memory used by a container.
00118         *
00119         * Note: if your data structures contained allocated
00120         * memory, you are responsible for releasing that
00121         * memory before calling this function!
00122         */
00123        netsnmp_container_rc    *cfree;
00124 
00125        /*
00126         * add an entry to the container
00127         */
00128        netsnmp_container_op    *insert;
00129 
00130        /*
00131         * remove an entry from the container
00132         */
00133        netsnmp_container_op    *remove;
00134 
00135        /*
00136         * release memory for an entry from the container
00137         */
00138        netsnmp_container_op    *release;
00139 
00140        /*
00141         * Note: do not change the key!  If you need to
00142         * change a key, remove the entry, change the key,
00143         * and the re-add the entry.
00144         */
00145 
00146        /*
00147         * find the entry in the container with the same key
00148         *
00149         */
00150        netsnmp_container_rtn   *find;
00151 
00152        /*
00153         * find the entry in the container with the next highest key
00154         *
00155         * If the key is NULL, return the first item in the container.
00156         */
00157        netsnmp_container_rtn   *find_next;
00158 
00159        /*
00160         * find all entries in the container which match the partial key
00161         * returns allocated memory (netsnmp_void_array). User is responsible
00162         * for releasing this memory (free(array->array), free(array)).
00163         * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers
00164         * stored in the container.
00165         */
00166        netsnmp_container_set            *get_subset;
00167 
00168        /*
00169         * function to return an iterator for the container
00170         */
00171        netsnmp_container_it           *get_iterator;
00172 
00173        /*
00174         * function to call another function for each object in the container
00175         */
00176        netsnmp_container_func         *for_each;
00177 
00178        /*
00179         * specialized version of for_each used to optimize cleanup.
00180         * clear the container, optionally calling a function for each item.
00181         */
00182        netsnmp_container_func         *clear;
00183 
00184        /*
00185         * OPTIONAL function to filter inserts to the container
00186         *  (intended for a secondary container, which only wants
00187         *   a sub-set of the objects in the primary/parent container)
00188         * Returns:
00189         *   1 : filter matched (don't insert)
00190         *   0 : no match (insert)
00191         */
00192        netsnmp_container_op    *insert_filter;
00193 
00194        /*
00195         * function to compare two object stored in the container.
00196         *
00197         * Returns:
00198         *
00199         *   -1  LHS < RHS
00200         *    0  LHS = RHS
00201         *    1  LHS > RHS
00202         */
00203        netsnmp_container_compare        *compare;
00204 
00205        /*
00206         * same as compare, but RHS will be a partial key
00207         */
00208        netsnmp_container_compare        *ncompare;
00209 
00210        /*
00211         * function to set container options
00212         */
00213        netsnmp_container_option         *options;
00214 
00215        /*
00216         * unique name for finding a particular container in a list
00217         */
00218        char *container_name;
00219 
00220        /*
00221         * sort count, for iterators to track (insert/delete
00222         * bumps coutner, invalidates iterator
00223         */
00224        u_long                          sync;
00225 
00226        /*
00227         * containers can contain other containers (additional indexes)
00228         */
00229        struct netsnmp_container_s *next, *prev;
00230 
00231     } netsnmp_container;
00232 
00233     /*
00234      * initialize/free a container of container factories. used by
00235      * netsnmp_container_find* functions.
00236      */
00237     void netsnmp_container_init_list(void);
00238     void netsnmp_container_free_list(void);
00239 
00240     /*
00241      * register a new container factory
00242      */
00243     int netsnmp_container_register_with_compare(const char* name,
00244                                                 netsnmp_factory *f,
00245                                                 netsnmp_container_compare *c);
00246     int netsnmp_container_register(const char* name, netsnmp_factory *f);
00247 
00248     /*
00249      * search for and create a container from a list of types or a
00250      * specific type.
00251      */
00252     netsnmp_container * netsnmp_container_find(const char *type_list);
00253     netsnmp_container * netsnmp_container_get(const char *type);
00254 
00255     /*
00256      * utility routines
00257      */
00258     void netsnmp_container_add_index(netsnmp_container *primary,
00259                                      netsnmp_container *new_index);
00260 
00261 
00262     netsnmp_factory *netsnmp_container_get_factory(const char *type);
00263 
00264     /*
00265      * common comparison routines
00266      */
00268     int netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs);
00269     int netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs);
00270 
00272     int netsnmp_compare_cstring(const void * lhs, const void * rhs);
00273     int netsnmp_ncompare_cstring(const void * lhs, const void * rhs);
00274 
00276     int netsnmp_compare_mem(const char * lhs, size_t lhs_len,
00277                             const char * rhs, size_t rhs_len);
00278 
00280     void  netsnmp_container_simple_free(void *data, void *context);
00281 
00282 /*
00283  * container optionflags
00284  */
00285 #define CONTAINER_KEY_ALLOW_DUPLICATES             0x00000001
00286 #define CONTAINER_KEY_UNSORTED                     0x00000002
00287 
00288 #define CONTAINER_SET_OPTIONS(x,o,rc)  do {                             \
00289         if (NULL==(x)->options)                                         \
00290             rc = -1;                                                    \
00291         else                                                            \
00292             rc = (x)->options(x, 1, o);                                 \
00293     } while(0)
00294 
00295 #define CONTAINER_CHECK_OPTION(x,o,rc)    do {                          \
00296         if (NULL==(x)->options)                                         \
00297             rc = -1;                                                    \
00298         else                                                            \
00299             rc = (x)->options(x,0, o);                                  \
00300     } while(0)
00301 
00302 
00303     /*
00304      * useful macros (x = container; k = key; c = user context)
00305      */
00306 #define CONTAINER_FIRST(x)          (x)->find_next(x,NULL)
00307 #define CONTAINER_FIND(x,k)         (x)->find(x,k)
00308 #define CONTAINER_NEXT(x,k)         (x)->find_next(x,k)
00309 /*
00310  * GET_SUBSET returns allocated memory (netsnmp_void_array). User is responsible
00311  * for releasing this memory (free(array->array), free(array)).
00312  * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers
00313  * stored in the container.
00314  */
00315 #define CONTAINER_GET_SUBSET(x,k)   (x)->get_subset(x,k)
00316 #define CONTAINER_SIZE(x)           (x)->get_size(x)
00317 #define CONTAINER_ITERATOR(x)       (x)->get_iterator(x)
00318 #define CONTAINER_COMPARE(x,l,r)    (x)->compare(l,r)
00319 #define CONTAINER_FOR_EACH(x,f,c)   (x)->for_each(x,f,c)
00320 
00321     /*
00322      * if you are getting multiple definitions of these three
00323      * inline functions, you most likely have optimizations turned off.
00324      * Either turn them back on, or define NETSNMP_NO_INLINE
00325      */
00326 #ifndef NETSNMP_USE_INLINE /* default is to inline */
00327     /*
00328      * insert k into all containers
00329      */
00330     int CONTAINER_INSERT(netsnmp_container *x, const void *k);
00331 
00332     /*
00333      * check if k is in any container and insert it into all if not
00334      */
00335     int CONTAINER_TRY_INSERT(netsnmp_container *x, const void *k);
00336     
00337     /*
00338      * remove k from all containers
00339      */
00340     int CONTAINER_REMOVE(netsnmp_container *x, const void *k);
00341 
00342     /*
00343      * clear all containers. When clearing the *first* container, and
00344      * *only* the first container, call the function f for each item.
00345      * After calling this function, all containers should be empty.
00346      */
00347     void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
00348                         void *c);
00349     /*
00350      * free all containers
00351      */
00352     int CONTAINER_FREE(netsnmp_container *x);
00353 #else
00354     /*------------------------------------------------------------------
00355      * These functions should EXACTLY match the function version in
00356      * container.c. If you change one, change them both.
00357      */
00358     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00359     int CONTAINER_INSERT(netsnmp_container *x, const void *k)
00360     {
00361         int rc2, rc = 0;
00362         
00364         while(x->prev)
00365             x = x->prev;
00366         for(; x; x = x->next) {
00367             if ((NULL != x->insert_filter) &&
00368                 (x->insert_filter(x,k) == 1))
00369                 continue;
00370             rc2 = x->insert(x,k);
00371             if (rc2) {
00372                 snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n",
00373                          x->container_name ? x->container_name : "", rc2);
00374                 rc = rc2;
00375             }
00376         }
00377         return rc;
00378     }    
00379     
00380     
00381     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00382     int CONTAINER_TRY_INSERT(netsnmp_container *x, const void *k)
00383     {
00384         const void *res = NULL;
00385 
00386         netsnmp_container *start;
00388         while(x->prev)
00389             x = x->prev;
00390 
00391        start = x;
00392 
00393        for(; x; x = x->next) {
00394             if ((NULL != x->insert_filter) &&
00395                (x->insert_filter(x,k) == 1))
00396                 continue;
00397             res = x->find(x,k);
00398             if (res) {
00399                return -1;
00400             }
00401         }
00402         return CONTAINER_INSERT(start, k);
00403     }
00404 
00405     /*------------------------------------------------------------------
00406      * These functions should EXACTLY match the function version in
00407      * container.c. If you change one, change them both.
00408      */
00409     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00410     int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
00411     {
00412         int rc2, rc = 0;
00413         
00415         while(x->next)
00416             x = x->next;
00417         while(x) {
00418             rc2 = x->remove(x,k);
00420             if ((rc2) && (NULL == x->insert_filter)) {
00421                 snmp_log(LOG_ERR,"error on subcontainer remove (%d)\n", rc2);
00422                 rc = rc2;
00423             }
00424             x = x->prev;
00425             
00426         }
00427         return rc;
00428     }
00429     
00430     /*------------------------------------------------------------------
00431      * These functions should EXACTLY match the function version in
00432      * container.c. If you change one, change them both.
00433      */
00434     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00435     int CONTAINER_FREE(netsnmp_container *x)
00436     {
00437         int  rc2, rc = 0;
00438         
00440         while(x->next)
00441             x = x->next;
00442         while(x) {
00443             netsnmp_container *tmp;
00444             tmp = x->prev;
00445             if (NULL != x->container_name)
00446                 SNMP_FREE(x->container_name);
00447             rc2 = x->cfree(x);
00448             if (rc2) {
00449                 snmp_log(LOG_ERR,"error on subcontainer cfree (%d)\n", rc2);
00450                 rc = rc2;
00451             }
00452             x = tmp;
00453         }
00454         return rc;
00455     }
00456 
00457     /*------------------------------------------------------------------
00458      * These functions should EXACTLY match the function version in
00459      * container.c. If you change one, change them both.
00460      */
00461     /*
00462      * clear all containers. When clearing the *first* container, and
00463      * *only* the first container, call the function f for each item.
00464      * After calling this function, all containers should be empty.
00465      */
00466     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00467     void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
00468                         void *c)
00469     {
00471         while(x->next)
00472             x = x->next;
00473         while(x->prev) {
00474             x->clear(x, NULL, c);
00475             x = x->prev;
00476         }
00477         x->clear(x, f, c);
00478     }
00479 
00480     /*------------------------------------------------------------------
00481      * These functions should EXACTLY match the function version in
00482      * container.c. If you change one, change them both.
00483      */
00484     /*
00485      * Find a sub-container with the given name
00486      */
00487     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00488     netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
00489                                          const char* name)
00490     {
00491         if ((NULL == x) || (NULL == name))
00492             return NULL;
00493 
00495         while(x->prev)
00496             x = x->prev;
00497         while(x) {
00498             if ((NULL != x->container_name) &&
00499                 (0 == strcmp(name,x->container_name)))
00500                 break;
00501             x = x->next;
00502         }
00503         return x;
00504     }
00505 
00506 #endif
00507     
00508     /*************************************************************************
00509      *
00510      * container iterator
00511      *
00512      *************************************************************************/
00513     /*
00514      * function returning an int for an operation on an iterator
00515      */
00516     typedef int (netsnmp_iterator_rc)(struct netsnmp_iterator_s *);
00517 
00518     /*
00519      * function returning an oject for an operation on an iterator
00520      */
00521     typedef void * (netsnmp_iterator_rtn)(struct netsnmp_iterator_s *);
00522 
00523 
00524     /*
00525      * iterator structure
00526      */
00527     typedef struct netsnmp_iterator_s {
00528 
00529        netsnmp_container              *container;
00530 
00531         /*
00532          * sync from container when iterator created. used to invalidate
00533          * the iterator when the container changes.
00534          */
00535        u_long                          sync;
00536 
00537         /*
00538          * reset iterator position to beginning of container.
00539          */
00540        netsnmp_iterator_rc           *reset;
00541 
00542         /*
00543          * release iterator and memory it uses
00544          */
00545        netsnmp_iterator_rc           *release;
00546 
00547         /*
00548          * first, last and current DO NOT advance the iterator
00549          */
00550        netsnmp_iterator_rtn          *first;
00551        netsnmp_iterator_rtn          *curr;
00552        netsnmp_iterator_rtn          *last;
00553 
00554        netsnmp_iterator_rtn          *next;
00555 
00556     } netsnmp_iterator;
00557 
00558 
00559 #define ITERATOR_FIRST(x)  x->first(x)
00560 #define ITERATOR_NEXT(x)   x->next(x)
00561 #define ITERATOR_LAST(x)   x->last(x)
00562 #define ITERATOR_RELEASE(x) do { x->release(x); x = NULL; } while(0)
00563     
00564 #ifdef  __cplusplus
00565 }
00566 #endif
00567 
00568 #endif 

net-snmpに対してSat Sep 5 13:14:20 2009に生成されました。  doxygen 1.4.7