1 /* Portions of this file are subject to the following copyright(s). See 2 * the Net-SNMP's COPYING file for more details and other copyrights 3 * that may apply: 4 */ 5 /* 6 * Portions of this file are copyrighted by: 7 * Copyright (C) 2007 Apple, Inc. All rights reserved. 8 * Use is subject to license terms specified in the COPYING file 9 * distributed with the Net-SNMP package. 10 * 11 * Portions of this file are copyrighted by: 12 * Copyright (c) 2016 VMware, Inc. All rights reserved. 13 * Use is subject to license terms specified in the COPYING file 14 * distributed with the Net-SNMP package. 15 */ 16 #ifndef NETSNMP_CONTAINER_H 17 #define NETSNMP_CONTAINER_H 18 19 /* 20 * $Id$ 21 * 22 * WARNING: This is a recently created file, and all of it's contents are 23 * subject to change at any time. 24 * 25 * A basic container template. A generic way for code to store and 26 * retrieve data. Allows for interchangable storage algorithms. 27 */ 28 #ifndef NET_SNMP_CONFIG_H 29 #error "Please include <net-snmp/net-snmp-config.h> before this file" 30 #endif 31 32 #include <stdlib.h> /* free() */ 33 #include <net-snmp/types.h> 34 #include <net-snmp/library/factory.h> 35 #include <net-snmp/library/snmp_logging.h> 36 #include <net-snmp/library/tools.h> 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 /************************************************************************* 43 * 44 * function pointer definitions 45 * 46 *************************************************************************/ 47 struct netsnmp_iterator_s; /** forward declare */ 48 struct netsnmp_container_s; /** forward declare */ 49 50 /* 51 * function for performing an operation on a container which 52 * returns (maybe the same) container. 53 */ 54 typedef struct netsnmp_container_s* (netsnmp_container_mod_op) 55 (struct netsnmp_container_s *, void *context, u_int flags); 56 57 /* 58 * function for setting an option on a container 59 */ 60 typedef int (netsnmp_container_option)(struct netsnmp_container_s *, 61 int set, u_int flags); 62 63 /* 64 * function returning an int for an operation on a container 65 */ 66 typedef int (netsnmp_container_rc)(struct netsnmp_container_s *); 67 68 /* 69 * function returning an iterator for a container 70 */ 71 typedef struct netsnmp_iterator_s * (netsnmp_container_it) 72 (struct netsnmp_container_s *); 73 74 /* 75 * function returning a size_t for an operation on a container 76 */ 77 typedef size_t (netsnmp_container_size)(struct netsnmp_container_s *); 78 79 /* 80 * function returning an int for an operation on an object and 81 * a container 82 */ 83 typedef int (netsnmp_container_op)(struct netsnmp_container_s *, 84 const void *data); 85 86 /* 87 * function returning an int for an operation on an object at a given 88 * position in a container (for containers supporting direct access) 89 */ 90 typedef int (netsnmp_container_da_op)(struct netsnmp_container_s *, 91 size_t pos, void *data); 92 93 /* 94 * function returning an int and an object at a given position in a 95 * container (for containers supporting direct access) 96 */ 97 typedef int (netsnmp_container_da_op_rtn)(struct netsnmp_container_s *, 98 size_t pos, 99 void **data); 100 101 /* 102 * function returning an oject for an operation on an object and a 103 * container 104 */ 105 typedef void * (netsnmp_container_rtn)(struct netsnmp_container_s *, 106 const void *data); 107 108 /* 109 * function with no return which acts on an object 110 */ 111 typedef void (netsnmp_container_obj_func)(void *data, void *context); 112 113 /* 114 * function with no return which calls a function on an object 115 */ 116 typedef void (netsnmp_container_func)(struct netsnmp_container_s *, 117 netsnmp_container_obj_func *, 118 void *context); 119 120 /* 121 * function returning an array of objects for an operation on an 122 * ojbect and a container 123 */ 124 typedef netsnmp_void_array * (netsnmp_container_set) 125 (struct netsnmp_container_s *, void *data); 126 127 /* 128 * function returning an int for a comparison between two objects 129 */ 130 typedef int (netsnmp_container_compare)(const void *lhs, 131 const void *rhs); 132 133 /************************************************************************* 134 * 135 * Basic container 136 * 137 *************************************************************************/ 138 typedef struct netsnmp_container_s { 139 140 /* 141 * pointer for container implementation 142 */ 143 void * container_data; 144 145 /* 146 * returns the number of items in a container 147 */ 148 netsnmp_container_size *get_size; 149 150 /* 151 * initialize a container 152 */ 153 netsnmp_container_rc *init; 154 155 /* 156 * release memory used by a container. 157 * 158 * Note: if your data structures contained allocated 159 * memory, you are responsible for releasing that 160 * memory before calling this function! 161 */ 162 netsnmp_container_rc *cfree; 163 164 /* 165 * add an entry to the container 166 */ 167 netsnmp_container_op *insert; 168 169 /* 170 * add an entry to the container at a given position 171 */ 172 netsnmp_container_da_op *insert_before; 173 netsnmp_container_da_op *insert_after; 174 175 /* 176 * remove an entry from the container 177 */ 178 netsnmp_container_op *remove; 179 180 /* 181 * remove an entry from the container at a given position 182 */ 183 netsnmp_container_da_op_rtn *remove_at; 184 185 /* 186 * release memory for an entry from the container 187 */ 188 netsnmp_container_op *release; /* NOTE: deprecated. Use free_item */ 189 netsnmp_container_obj_func *free_item; 190 191 /* 192 * find the entry in the container with the same key 193 * 194 * Note: do not change the key! If you need to 195 * change a key, remove the entry, change the key, 196 * and the re-add the entry. 197 */ 198 netsnmp_container_rtn *find; 199 200 /* 201 * find the entry in the container with the next highest key 202 * 203 * If the key is NULL, return the first item in the container. 204 */ 205 netsnmp_container_rtn *find_next; 206 207 /* 208 * get entry at the given index (for containers supporting direct access 209 */ 210 netsnmp_container_da_op_rtn *get_at; 211 212 /* 213 * find all entries in the container which match the partial key 214 * returns allocated memory (netsnmp_void_array). User is responsible 215 * for releasing this memory (free(array->array), free(array)). 216 * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers 217 * stored in the container. 218 */ 219 netsnmp_container_set *get_subset; 220 221 /* 222 * function to return an iterator for the container 223 */ 224 netsnmp_container_it *get_iterator; 225 226 /* 227 * function to call another function for each object in the container 228 */ 229 netsnmp_container_func *for_each; 230 231 /* 232 * specialized version of for_each used to optimize cleanup. 233 * clear the container, optionally calling a function for each item. 234 */ 235 netsnmp_container_func *clear; 236 237 /* 238 * OPTIONAL function to filter inserts to the container 239 * (intended for a secondary container, which only wants 240 * a sub-set of the objects in the primary/parent container) 241 * Returns: 242 * 1 : filter matched (don't insert) 243 * 0 : no match (insert) 244 */ 245 netsnmp_container_op *insert_filter; 246 247 /* 248 * OPTIONAL function to duplicate a container. Defaults to a shallow 249 * copy. Only the specified container is copied (i.e. sub-containers 250 * not included). 251 */ 252 netsnmp_container_mod_op *duplicate; 253 254 255 /* 256 * function to compare two object stored in the container. 257 * 258 * Returns: 259 * 260 * -1 LHS < RHS 261 * 0 LHS = RHS 262 * 1 LHS > RHS 263 */ 264 netsnmp_container_compare *compare; 265 266 /* 267 * same as compare, but RHS will be a partial key 268 */ 269 netsnmp_container_compare *ncompare; 270 271 /* 272 * function to set container options 273 */ 274 netsnmp_container_option *options; 275 276 /* 277 * unique name for finding a particular container in a list 278 */ 279 char *container_name; 280 281 /* 282 * sort count, for iterators to track (insert/delete 283 * bumps counter, invalidates iterator) 284 */ 285 u_long sync; 286 287 /* 288 * flags 289 */ 290 u_int flags; 291 292 /* 293 * containers can contain other containers (additional indexes) 294 */ 295 struct netsnmp_container_s *next, *prev; 296 297 } netsnmp_container; 298 299 /* 300 * initialize/free a container of container factories. used by 301 * netsnmp_container_find* functions. 302 */ 303 NETSNMP_IMPORT 304 void netsnmp_container_init_list(void); 305 NETSNMP_IMPORT 306 void netsnmp_container_free_list(void); 307 308 /* 309 * register a new container factory 310 */ 311 int netsnmp_container_register_with_compare(const char* name, 312 netsnmp_factory *f, 313 netsnmp_container_compare *c); 314 int netsnmp_container_register(const char* name, netsnmp_factory *f); 315 316 /* 317 * search for and create a container from a list of types or a 318 * specific type. 319 */ 320 NETSNMP_IMPORT 321 netsnmp_container * netsnmp_container_find(const char *type_list); 322 netsnmp_container * netsnmp_container_get(const char *type); 323 324 /* 325 * utility routines 326 */ 327 NETSNMP_IMPORT 328 void netsnmp_container_add_index(netsnmp_container *primary, 329 netsnmp_container *new_index); 330 331 332 netsnmp_factory *netsnmp_container_get_factory(const char *type); 333 334 /* 335 * common comparison routines 336 */ 337 /** first data element is a 'netsnmp_index' */ 338 NETSNMP_IMPORT 339 int netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs); 340 NETSNMP_IMPORT 341 int netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs); 342 343 /** first data element is a 'char *' */ 344 int netsnmp_compare_cstring(const void * lhs, const void * rhs); 345 int netsnmp_ncompare_cstring(const void * lhs, const void * rhs); 346 347 /** useful for octet strings */ 348 NETSNMP_IMPORT 349 int netsnmp_compare_mem(const char * lhs, size_t lhs_len, 350 const char * rhs, size_t rhs_len); 351 352 /** no structure, just 'char *' pointers */ 353 int netsnmp_compare_direct_cstring(const void * lhs, const void * rhs); 354 355 int netsnmp_compare_long(const void * lhs, const void * rhs); 356 int netsnmp_compare_ulong(const void * lhs, const void * rhs); 357 int netsnmp_compare_int32(const void * lhs, const void * rhs); 358 int netsnmp_compare_uint32(const void * lhs, const void * rhs); 359 360 /** for_each callback to call free on data item */ 361 NETSNMP_IMPORT 362 void netsnmp_container_simple_free(void *data, void *context); 363 364 /* 365 * container optionflags 366 */ 367 #define CONTAINER_KEY_ALLOW_DUPLICATES 0x00000001 368 #define CONTAINER_KEY_UNSORTED 0x00000002 369 /* ... */ 370 #define CONTAINER_FLAG_INTERNAL_1 0x80000000 371 372 #define CONTAINER_SET_OPTIONS(x,o,rc) do { \ 373 if (NULL==(x)->options) \ 374 rc = -1; \ 375 else { \ 376 rc = (x)->options(x, 1, o); \ 377 if (rc != -1 ) \ 378 (x)->flags |= o; \ 379 } \ 380 } while(0) 381 382 #define CONTAINER_CHECK_OPTION(x,o,rc) do { \ 383 rc = x->flags & 0; \ 384 } while(0) 385 386 387 /* 388 * useful macros (x = container; k = key; c = user context) 389 */ 390 #define CONTAINER_FIRST(x) (x)->find_next(x,NULL) 391 #define CONTAINER_FIND(x,k) (x)->find(x,k) 392 #define CONTAINER_NEXT(x,k) (x)->find_next(x,k) 393 /* 394 * GET_SUBSET returns allocated memory (netsnmp_void_array). User is responsible 395 * for releasing this memory (free(array->array), free(array)). 396 * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers 397 * stored in the container. 398 */ 399 #define CONTAINER_GET_SUBSET(x,k) (x)->get_subset(x,k) 400 #define CONTAINER_SIZE(x) (x)->get_size(x) 401 #define CONTAINER_ITERATOR(x) (x)->get_iterator(x) 402 #define CONTAINER_COMPARE(x,l,r) (x)->compare(l,r) 403 #define CONTAINER_FOR_EACH(x,f,c) (x)->for_each(x,f,c) 404 405 /* 406 * if you are getting multiple definitions of these three 407 * inline functions, you most likely have optimizations turned off. 408 * Either turn them back on, or define NETSNMP_NO_INLINE 409 */ 410 /* 411 * insert k into all containers 412 */ 413 NETSNMP_IMPORT 414 int CONTAINER_INSERT(netsnmp_container *x, const void *k); 415 416 /* 417 * insert item before given position 418 */ 419 NETSNMP_IMPORT 420 int CONTAINER_INSERT_BEFORE(netsnmp_container *x, size_t pos, void *k); 421 422 /* 423 * remove k from all containers 424 */ 425 NETSNMP_IMPORT 426 int CONTAINER_REMOVE(netsnmp_container *x, const void *k); 427 428 /* 429 * remove item at given position 430 */ 431 NETSNMP_IMPORT 432 int CONTAINER_REMOVE_AT(netsnmp_container *x, size_t pos, void **k); 433 434 /* 435 * get item at given position 436 */ 437 NETSNMP_IMPORT 438 int CONTAINER_GET_AT(netsnmp_container *x, size_t pos, void **k); 439 440 /* 441 * duplicate container 442 */ 443 NETSNMP_IMPORT 444 netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx, 445 u_int flags); 446 447 /* 448 * clear all containers. When clearing the *first* container, and 449 * *only* the first container, call the function f for each item. 450 * After calling this function, all containers should be empty. 451 */ 452 NETSNMP_IMPORT 453 void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f, 454 void *c); 455 456 /* 457 * clear all containers. When clearing the *first* container, and 458 * *only* the first container, call the free_item function for each item. 459 * After calling this function, all containers should be empty. 460 */ 461 NETSNMP_IMPORT 462 void CONTAINER_FREE_ALL(netsnmp_container *x, void *c); 463 464 /* 465 * free all containers 466 */ 467 NETSNMP_IMPORT 468 int CONTAINER_FREE(netsnmp_container *x); 469 470 NETSNMP_IMPORT 471 netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x, 472 const char* name); 473 474 /* 475 * INTERNAL utility routines for container implementations 476 */ 477 void netsnmp_init_container(netsnmp_container *c, 478 netsnmp_container_rc *init, 479 netsnmp_container_rc *cfree, 480 netsnmp_container_size *size, 481 netsnmp_container_compare *cmp, 482 netsnmp_container_op *ins, 483 netsnmp_container_op *rem, 484 netsnmp_container_rtn *fnd); 485 /** Duplicate container meta-data. */ 486 int netsnmp_container_data_dup(netsnmp_container *dup, 487 netsnmp_container *c); 488 489 490 /************************************************************************* 491 * 492 * container iterator 493 * 494 *************************************************************************/ 495 /* 496 * function returning an int for an operation on an iterator 497 */ 498 typedef int (netsnmp_iterator_rc)(struct netsnmp_iterator_s *); 499 500 /* 501 * function returning an oject for an operation on an iterator 502 */ 503 typedef void * (netsnmp_iterator_rtn)(struct netsnmp_iterator_s *); 504 505 506 /* 507 * iterator structure 508 */ 509 typedef struct netsnmp_iterator_s { 510 511 netsnmp_container *container; 512 513 /* 514 * sync from container when iterator created. used to invalidate 515 * the iterator when the container changes. 516 */ 517 u_long sync; 518 519 /* 520 * reset iterator position to beginning of container. 521 */ 522 netsnmp_iterator_rc *reset; 523 524 /* 525 * release iterator and memory it uses 526 */ 527 netsnmp_iterator_rc *release; 528 529 /* 530 * first, last and current DO NOT advance the iterator 531 */ 532 netsnmp_iterator_rtn *first; 533 netsnmp_iterator_rtn *curr; 534 netsnmp_iterator_rtn *last; 535 536 netsnmp_iterator_rtn *next; 537 538 /* 539 * remove will remove the item at the current position, then back up 540 * the iterator to the previous item. That way next will move to the 541 * item (the one that replaced the removed item. 542 */ 543 netsnmp_iterator_rc *remove; 544 545 } netsnmp_iterator; 546 547 548 #define ITERATOR_FIRST(x) x->first(x) 549 #define ITERATOR_NEXT(x) x->next(x) 550 #define ITERATOR_LAST(x) x->last(x) 551 #define ITERATOR_REMOVE(x) x->remove(x) 552 #define ITERATOR_RELEASE(x) do { x->release(x); x = NULL; } while(0) 553 554 #ifdef __cplusplus 555 } 556 #endif 557 558 #endif /** NETSNMP_CONTAINER_H */ 559