File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libpdel / structs / structs.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:25:53 2012 UTC (13 years, 1 month ago) by misho
Branches: libpdel, MAIN
CVS tags: v0_5_3, HEAD
libpdel

    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>