Annotation of embedaddon/mpd/src/contrib/libpdel/structs/structs.h, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #ifndef _PDEL_STRUCTS_STRUCTS_H_
! 42: #define _PDEL_STRUCTS_STRUCTS_H_
! 43:
! 44: /*********************************************************************
! 45:
! 46: STRUCTS TYPES
! 47: -------------
! 48:
! 49: A "structs type" is a descriptor for a C data structure that
! 50: allows access to the data structure in an automated fashion.
! 51: For example, once a data structure is described by a associated
! 52: structs type, the following operations can be performed
! 53: automatically on any instance of the data structure:
! 54:
! 55: o Initialization to default value
! 56: o Comparison of two instances for equality
! 57: o "Deep" copying (aka. "cloning")
! 58: o Access to arbitrary sub-fields by name (aka. "introspection")
! 59: o Conversion to/from ASCII (primitive types)
! 60: o Import/export from/to XML, with precise input validation,
! 61: automating conversion between internal and external formats
! 62: o Conversion into XML-RPC request or reply
! 63: o Import/export from/to a machine independent binary encoding
! 64: o Inserting, deleting, and extending elements in arrays
! 65:
! 66: In addition, any required dynamic memory allocation and free'ing
! 67: is handled automatically.
! 68:
! 69: Supported data structures include the normal primitive C types,
! 70: plus arrays, structures, unions, and pointers to supported types,
! 71: as well as some other useful types such as opaque binary data,
! 72: IP address, regular expression, etc. User-defined types may be
! 73: added as well.
! 74:
! 75: Put simply, a structs type describes how to interpret a region
! 76: of memory so that the operations listed above may be peformed
! 77: in an automated fashion.
! 78:
! 79: Arrays must be defined using the "structs_array" structure.
! 80: Unions must be defined using the "structs_union" structure.
! 81:
! 82: Nested items in a data structure can be identified by names,
! 83: where each name component is either the name of a structure or
! 84: union field, or an array index. Name components are separated
! 85: by dots. For example, "foo.list.12" (see below).
! 86:
! 87: EXAMPLE
! 88: -------
! 89:
! 90: Consider the C data structure defined by "struct janfu":
! 91:
! 92: struct fubar {
! 93: struct structs_array list; // array of strings
! 94: };
! 95:
! 96: struct janfu {
! 97: u_int16_t value; // 16 bit hex value
! 98: struct fubar *foo; // fubar structure
! 99: };
! 100:
! 101: A memory region containing a 'struct janfu' would be described
! 102: in C code like so:
! 103:
! 104: // Descriptor for field 'list' in 'struct fubar': array of strings
! 105: static const struct structs_type list_array_type =
! 106: STRUCTS_ARRAY_TYPE(&structs_type_string, "list_elem", "list_elem");
! 107:
! 108: // Descriptor for 'struct fubar'
! 109: static const struct structs_field fubar_fields[] = {
! 110: STRUCTS_STRUCT_FIELD(fubar, list, &list_array_type),
! 111: STRUCTS_STRUCT_FIELD_END
! 112: };
! 113: static const struct structs_type fubar_type =
! 114: STRUCTS_STRUCT_TYPE(fubar, &fubar_fields);
! 115:
! 116: // Descriptor for a variable of type 'struct fubar *'
! 117: static const struct structs_type foo_ptr_type =
! 118: STRUCTS_POINTER_TYPE(&fubar_type, "struct fubar");
! 119:
! 120: // Descriptor for 'struct janfu'
! 121: static const struct structs_field janfu_fields[] = {
! 122: STRUCTS_STRUCT_FIELD(janfu, value, &structs_type_uint16),
! 123: STRUCTS_STRUCT_FIELD(janfu, foo, &foo_ptr_type),
! 124: STRUCTS_STRUCT_FIELD_END
! 125: };
! 126: static const struct structs_type janfu_type =
! 127: STRUCTS_STRUCT_TYPE(janfu, &janfu_fields);
! 128:
! 129: The type "janfu_type" describes a 'struct janfu' data structure.
! 130:
! 131: Then "foo.list.12" refers to the 12th item in the "list" array
! 132: (assuming it actually exists), counting from zero. It's value
! 133: could be accessed like this:
! 134:
! 135: void
! 136: print_list_12(const struct janfu *j)
! 137: {
! 138: char *s;
! 139:
! 140: s = structs_get_string(&janfu_type, "foo.list.12", j, NULL);
! 141: if (s == NULL) {
! 142: fprintf(stderr, "structs_get_string: %s: %s",
! 143: "foo.list.12", strerror(errno));
! 144: exit(1);
! 145: }
! 146: printf("foo.list.12 = %s\n", s);
! 147: free(s);
! 148: }
! 149:
! 150: An instance of a "struct janfu", if output as XML, might look
! 151: like this:
! 152:
! 153: <?xml version="1.0" standalone="yes"?>
! 154: <janfu>
! 155: <value>0x1234</value>
! 156: <list>
! 157: <list_elem>first list element</list_elem>
! 158: <list_elem>second list element</list_elem>
! 159: <list_elem>third list element</list_elem>
! 160: </list>
! 161: </janfu>
! 162:
! 163: A function call that would produce the above output is:
! 164:
! 165: void
! 166: dump_janfu(struct janfu *j)
! 167: {
! 168: structs_xml_output(&janfu_type, "janfu", NULL, j, stdout, NULL, 0);
! 169: }
! 170:
! 171: *********************************************************************/
! 172:
! 173: /* Name component separator */
! 174: #define STRUCTS_SEPARATOR '.'
! 175:
! 176: struct structs_type;
! 177:
! 178: /* For representing arbitrary binary data */
! 179: struct structs_data {
! 180: u_int length; /* number of bytes */
! 181: u_char *data; /* bytes */
! 182: };
! 183:
! 184: /*********************************************************************
! 185: STRUCTS TYPE METHODS
! 186: *********************************************************************/
! 187:
! 188: /*
! 189: * The structs type "init" method.
! 190: *
! 191: * The region of memory pointed to by "data" must be at least
! 192: * type->size bytes and should be uninitialized (i.e., it should
! 193: * not contain a valid instance of the type).
! 194: *
! 195: * This method should initialize the memory with a valid instance
! 196: * of the type, setting this new instance to be equal to the default
! 197: * value for the type, and allocating any resources required for the
! 198: * instance in the process.
! 199: *
! 200: * Returns 0 if successful, or -1 (and sets errno) if there was an error.
! 201: */
! 202: typedef int structs_init_t(const struct structs_type *type, void *data);
! 203:
! 204: /*
! 205: * The structs type "copy" method.
! 206: *
! 207: * The region of memory pointed to by "from" contains a valid instance
! 208: * of the type described by "type".
! 209: *
! 210: * The region of memory pointed to by "to" is uninitialized.
! 211: *
! 212: * This method should initialize "to" with a "deep" copy of the
! 213: * data structure pointed to by "from". The copy must be equal
! 214: * (according to the "equal" method) to the original.
! 215: *
! 216: * Returns 0 if successful, or -1 (and sets errno) if there was an error.
! 217: */
! 218: typedef int structs_copy_t(const struct structs_type *type,
! 219: const void *from, void *to);
! 220:
! 221: /*
! 222: * The structs type "equal" method.
! 223: *
! 224: * The regions of memory pointed to by "data1" and "data2" contain valid
! 225: * instances of the type described by "type".
! 226: *
! 227: * Returns 1 if "data1" and "data2" are equal (by a "deep" comparison), or
! 228: * 0 if not, or -1 (and sets errno) if there was an error.
! 229: */
! 230: typedef int structs_equal_t(const struct structs_type *type,
! 231: const void *data1, const void *data2);
! 232:
! 233: /*
! 234: * The structs type "ascify" method.
! 235: *
! 236: * The region of memory pointed to by "data" contains a valid instance
! 237: * of the type described by "type".
! 238: *
! 239: * The method should convert this instance into a NUL-terminated
! 240: * ASCII string stored in a dynamically allocated buffer that is
! 241: * allocated with the memory type described by "mtype".
! 242: *
! 243: * The ASCII string must be unique, in that it can be used as input
! 244: * to the "binify" method to create an instance equal (according to the
! 245: * "equal" method) to the original.
! 246: *
! 247: * Returns the ASCII string buffer if successful, or NULL
! 248: * (and sets errno) if error.
! 249: */
! 250: typedef char *structs_ascify_t(const struct structs_type *type,
! 251: const char *mtype, const void *data);
! 252:
! 253: /*
! 254: * The structs type "binify" method.
! 255: *
! 256: * The region of memory pointed to by "data" is uninitialized.
! 257: *
! 258: * The variable "ascii" points to a NUL-terminated string. This method
! 259: * should use the contents of the string to create a new instace of
! 260: * the type in the memory pointed to by "data".
! 261: *
! 262: * Returns 0 if successful, or -1 if there was an error. In the latter
! 263: * case, either errno should be set, or a more informative error string
! 264: * may be printed (including NUL) into "ebuf", which has total size "emax"
! 265: * (see snprintf(3)).
! 266: *
! 267: * This method must be robust in the face of bogus data in "ascii";
! 268: * it must return an error if "ascii" is invalid.
! 269: */
! 270: typedef int structs_binify_t(const struct structs_type *type,
! 271: const char *ascii, void *data, char *ebuf, size_t emax);
! 272:
! 273: /*
! 274: * The structs type "encode" method.
! 275: *
! 276: * The region of memory pointed to by "data" contains a valid instance
! 277: * of the type described by "type".
! 278: *
! 279: * This method should encode the data structure into a host order
! 280: * independent, self-delimiting sequence of bytes. The sequence must be
! 281: * stored in a dynamically allocated buffer allocated with the memory type
! 282: * described by "mtype", and "code" must be filled in with the buffer's
! 283: * pointer and length.
! 284: *
! 285: * The binary sequence must be unique, in that it can be used as input
! 286: * to the "decode" method to create an instance equal (according to the
! 287: * "equal" method) to the original.
! 288: *
! 289: * Returns 0 if successful, or -1 (and sets errno) if there was an error.
! 290: */
! 291: typedef int structs_encode_t(const struct structs_type *type,
! 292: const char *mtype, struct structs_data *code,
! 293: const void *data);
! 294:
! 295: /*
! 296: * The structs type "decode" method.
! 297: *
! 298: * The region of memory pointed to by "data" is uninitialized.
! 299: *
! 300: * The "code" parameter points to a sequence of "cmax" binary data bytes.
! 301: * This method should decode the binary data and use it to reconstruct
! 302: * an instance of "type" in the memory region pointed to by "data".
! 303: *
! 304: * Returns the number of bytes consumed in the decoding process if
! 305: * successful, or -1 (and sets errno) if there was an error. In the
! 306: * latter case, either errno should be set, or a more informative error
! 307: * string may be printed (including NUL) into "ebuf", which has total
! 308: * size "emax" (see snprintf(3)).
! 309: */
! 310: typedef int structs_decode_t(const struct structs_type *type,
! 311: const u_char *code, size_t cmax, void *data,
! 312: char *ebuf, size_t emax);
! 313:
! 314: /*
! 315: * The structs type "uninit" method.
! 316: *
! 317: * The region of memory pointed to by "data" contains a valid instance
! 318: * of the type described by "type".
! 319: *
! 320: * This method should free any resources associated with the instance
! 321: * pointed to by "data". Upon return, the memory pointed to by "data"
! 322: * may be no longer used or referenced.
! 323: */
! 324: typedef void structs_uninit_t(const struct structs_type *type, void *data);
! 325:
! 326: /*********************************************************************
! 327: STRUCTS TYPE DEFINITION
! 328: *********************************************************************/
! 329:
! 330: /*
! 331: * This structure defines a structs type.
! 332: */
! 333: struct structs_type {
! 334: size_t size; /* size of an instance */
! 335: const char *name; /* human informative name */
! 336: int tclass; /* see classes listed below */
! 337: structs_init_t *init; /* type "init" method */
! 338: structs_copy_t *copy; /* type "copy" method */
! 339: structs_equal_t *equal; /* type "equal" method */
! 340: structs_ascify_t *ascify; /* type "ascify" method */
! 341: structs_binify_t *binify; /* type "binify" method */
! 342: structs_encode_t *encode; /* type "encode" method */
! 343: structs_decode_t *decode; /* type "decode" method */
! 344: structs_uninit_t *uninit; /* type "uninit" method */
! 345: union { /* type specific arguments */
! 346: const void *v;
! 347: const char *s;
! 348: int i;
! 349: } args[3];
! 350: };
! 351:
! 352: /* Classes of types */
! 353: #define STRUCTS_TYPE_PRIMITIVE 0
! 354: #define STRUCTS_TYPE_POINTER 1
! 355: #define STRUCTS_TYPE_ARRAY 2
! 356: #define STRUCTS_TYPE_FIXEDARRAY 3
! 357: #define STRUCTS_TYPE_STRUCTURE 4
! 358: #define STRUCTS_TYPE_UNION 5
! 359:
! 360: /*********************************************************************
! 361: GENERIC TYPE METHODS
! 362: *********************************************************************/
! 363:
! 364: __BEGIN_DECLS
! 365:
! 366: /* These operate on simple block regions of memory */
! 367: extern structs_init_t structs_region_init;
! 368: extern structs_copy_t structs_region_copy;
! 369: extern structs_equal_t structs_region_equal;
! 370:
! 371: extern structs_encode_t structs_region_encode;
! 372: extern structs_decode_t structs_region_decode;
! 373: extern structs_encode_t structs_region_encode_netorder;
! 374: extern structs_decode_t structs_region_decode_netorder;
! 375:
! 376: /* These always return an error with errno set to EOPNOTSUPP */
! 377: extern structs_init_t structs_notsupp_init;
! 378: extern structs_copy_t structs_notsupp_copy;
! 379: extern structs_equal_t structs_notsupp_equal;
! 380: extern structs_ascify_t structs_notsupp_ascify;
! 381: extern structs_binify_t structs_notsupp_binify;
! 382: extern structs_encode_t structs_notsupp_encode;
! 383: extern structs_decode_t structs_notsupp_decode;
! 384:
! 385: /* This copies any type that is ascifyable by converting to ASCII and back */
! 386: extern structs_copy_t structs_ascii_copy;
! 387:
! 388: /* This does nothing */
! 389: extern structs_uninit_t structs_nothing_free;
! 390:
! 391: __END_DECLS
! 392:
! 393: /*********************************************************************
! 394: BASIC STRUCTS FUNCTIONS
! 395: *********************************************************************/
! 396:
! 397: __BEGIN_DECLS
! 398:
! 399: /*
! 400: * Initialize an item in a data structure to its default value.
! 401: * This assumes the item is not already initialized.
! 402: *
! 403: * If "name" is NULL or empty string, the entire structure is initialied.
! 404: *
! 405: * Returns 0 if successful, otherwise -1 and sets errno.
! 406: */
! 407: extern int structs_init(const struct structs_type *type,
! 408: const char *name, void *data);
! 409:
! 410: /*
! 411: * Reset an item in a data structure to its default value.
! 412: * This assumes the item is already initialized.
! 413: *
! 414: * If "name" is NULL or empty string, the entire structure is reset.
! 415: *
! 416: * Returns 0 if successful, otherwise -1 and sets errno.
! 417: */
! 418: extern int structs_reset(const struct structs_type *type,
! 419: const char *name, void *data);
! 420:
! 421: /*
! 422: * Free an item in a data structure, returning it to its uninitialized state.
! 423: * This function can be thought of as the opposite of structs_init().
! 424: *
! 425: * If "name" is NULL or empty string, the entire structure is free'd.
! 426: *
! 427: * Returns 0 if successful, otherwise -1 and sets errno.
! 428: */
! 429: extern int structs_free(const struct structs_type *type,
! 430: const char *name, void *data);
! 431:
! 432: /*
! 433: * Compare two data structures of the same type for equality.
! 434: *
! 435: * If "name" is NULL or empty string, the entire structures are compared.
! 436: * Otherwise, the "name" sub-elements of both structures are compared.
! 437: *
! 438: * Returns zero or one (for not equal or equal, respectively),
! 439: * or -1 (and sets errno) if there was an error.
! 440: */
! 441: extern int structs_equal(const struct structs_type *type,
! 442: const char *name, const void *data1, const void *data2);
! 443:
! 444: /*
! 445: * Find an item in a data structure structure.
! 446: *
! 447: * If "name" is NULL or empty string, "type" is returned and "datap"
! 448: * is unmodified.
! 449: *
! 450: * If "set_union" is true, then any unions in the path will be reset
! 451: * so that their fields agree with "name" in the case that "name" contains
! 452: * a different field name than is currently set for that union. However,
! 453: * these changes will only occur if "name" is actually found.
! 454: *
! 455: * Returns the type of the item and points *datap at it, or NULL
! 456: * (and sets errno) if there was an error.
! 457: */
! 458: extern const struct structs_type *structs_find(
! 459: const struct structs_type *type, const char *name,
! 460: void **datap, int set_union);
! 461:
! 462: /*
! 463: * Get a copy of an item from a data structure.
! 464: *
! 465: * If "name" is NULL or empty string, the entire structure is copied.
! 466: *
! 467: * It is assumed that "to" points to a region big enough to hold
! 468: * the copy of the item. "to" will not be free'd first, so it should
! 469: * not already be initialized.
! 470: *
! 471: * Note: "name" is only applied to "from". The structs types of
! 472: * "from.<name>" and "to" must be the same.
! 473: *
! 474: * Returns 0 if successful, otherwise -1 and sets errno.
! 475: */
! 476: extern int structs_get(const struct structs_type *type,
! 477: const char *name, const void *from, void *to);
! 478:
! 479: /*
! 480: * Set an item in a data structure.
! 481: *
! 482: * If "name" is NULL or empty string, the entire structure is copied.
! 483: *
! 484: * It is assumed that "to" is already initialized.
! 485: *
! 486: * Note: "name" is only applied to "to". The structs types of
! 487: * "from" and "to.<name>" must be the same.
! 488: *
! 489: * Returns 0 if successful, otherwise -1 and sets errno.
! 490: */
! 491: extern int structs_set(const struct structs_type *type,
! 492: const void *from, const char *name, void *to);
! 493:
! 494: /*
! 495: * Get the ASCII form of an item, in a string allocated with the
! 496: * memory type described by "mtype".
! 497: *
! 498: * The caller is reponsible for freeing the returned string.
! 499: *
! 500: * Returns the ASCII string if successful, otherwise NULL and sets errno.
! 501: */
! 502: extern char *structs_get_string(const struct structs_type *type,
! 503: const char *name, const void *data, const char *mtype);
! 504:
! 505: /*
! 506: * Set the value of an item in a data structure from an ASCII string.
! 507: *
! 508: * The referred to item must be of a type that supports ASCII encoding,
! 509: * and is assumed to be already initialized.
! 510: *
! 511: * Returns 0 if successful, otherwise -1 and sets errno.
! 512: */
! 513: extern int structs_set_string(const struct structs_type *type,
! 514: const char *name, const char *ascii,
! 515: void *data, char *ebuf, size_t emax);
! 516:
! 517: /*
! 518: * Get the binary encoded form of an item, put into a buffer
! 519: * allocated with memory type "mtype" and described by "code".
! 520: *
! 521: * The caller is reponsible for freeing the allocated bytes.
! 522: *
! 523: * Returns 0 if successful, otherwise -1 and sets errno.
! 524: */
! 525: extern int structs_get_binary(const struct structs_type *type,
! 526: const char *name, const void *data,
! 527: const char *mtype, struct structs_data *code);
! 528:
! 529: /*
! 530: * Set an item's value from its binary encoded value.
! 531: *
! 532: * The referred to item is assumed to be already initialized.
! 533: *
! 534: * Returns 0 if successful, otherwise -1 and sets errno.
! 535: */
! 536: extern int structs_set_binary(const struct structs_type *type,
! 537: const char *name, const struct structs_data *code,
! 538: void *data, char *ebuf, size_t emax);
! 539:
! 540: /*
! 541: * Traverse a structure, returning the names of all primitive fields
! 542: * (i.e., the "leaves" of the data structure).
! 543: *
! 544: * The number of items is returned, or -1 and errno if there was an error.
! 545: * The caller must free the list by freeing each string in the array,
! 546: * and then the array itself; all memory is allocated using memory type
! 547: * "mtype".
! 548: *
! 549: * If "type" is a primitive type, a list of length one is returned
! 550: * containing an empty string.
! 551: */
! 552: extern int structs_traverse(const struct structs_type *type,
! 553: const void *data, char ***listp, const char *mtype);
! 554:
! 555: __END_DECLS
! 556:
! 557: #endif /* _PDEL_STRUCTS_STRUCTS_H_ */
! 558:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>