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>