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