Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
STRUCTS_TYPE_UNION(3)  FreeBSD Library Functions Manual	 STRUCTS_TYPE_UNION(3)

     structs_type_union	-- structs types for C unions

     PDEL Library (libpdel, -lpdel)

     #include <sys/types.h>
     #include <stddef.h>
     #include <pdel/structs/structs.h>
     #include <pdel/structs/type/union.h>

     DEFINE_STRUCTS_UNION(struct_name, union_name);

     STRUCTS_UNION_TYPE(union_name, field_list);

     STRUCTS_UNION_FIELD(field_name, field_type);

     structs_union_set(const struct structs_type *type,	const char *name,
	 void *data, const char	*field_name);

     The STRUCTS_UNION_TYPE() macro defines a structs(3) type (i.e., a struct
     structs_type) for describing a struct structs_union, which	is an interme-
     diate structure describing	a union	union_name.

	struct structs_union {
	    const char	*const field_name; /* name of field currently in use */
	    void	*un;		   /* pointer to the union itself */

     The field_name always indicates which of the union	fields is currently in
     use.  It should never be modified directly; instead, use the function
     structs_union_set() (see below).  un points to the	actual union, which is
     stored in a separately allocated buffer typed_mem(3) type union
     union_name.  This buffer is only large enough to hold the specific	field
     currently in use.

     To	define a structure equivalent to a struct structs_union	that declares
     un	to have	the correct C type for the union used (instead of void *), use
     the DEFINE_STRUCTS_UNION()	macro, where struct_name is the	name of	the
     structure (or empty if no name is desired)	and union_name is the name of
     the represented union.  Then the un field will be declared	to have	type
     union union_name *.

     The union's fields	are accessible by name.	 Of course, only one field may
     be	accessed at a time, and	changing the current union field causes	the
     previous field contents to	be lost.

     As	a special case,	the field named	"field_name" is	also read-only acces-
     sible and always returns the name of the union field currently in use.
     The union itself must not contain a field named "field_name," or else it
     will not be accessible.  The "field_name" field does not appear in	the
     output of structs_xml_output(3) or	structs_traverse(3).

     STRUCTS_UNION_TYPE() defines a structs(3) type for	a C union.  The
     field_list	parameter must point to	an array of struct structs_ufield
     structures	describing each	union field:

	/* This	structure describes one	field in a union */
	struct structs_ufield {
	    const char			*name;	     /*	field name */
	    const struct structs_type	*type;	     /*	field type */

     The STRUCTS_UNION_FIELD() macro should be used to define an entry in the
     field array: field_name is	the name of the	field and field_type is	a
     pointer to	the structs(3) type describing the field.

     The fields	need not be listed in the array	in the same order as they are
     declared in the C union.  However,	the array must be terminated with
     STRUCTS_UNION_FIELD_END, which is defined as follows:


     The first field in	the list is the	"default field"	and it is chosen as
     the current field when a union data type is initialized.  When a union
     data type is read in as XML by structs_xml_input(3), if the innermost XML
     tag is omitted (i.e., the one that	specifies the field name) and the de-
     fault field has primitive type, then the default field is assumed.

     structs_union_set() should	be used	to change the union field currently in
     use, to guarantee that the	old field's contents are properly deallocated
     and the new field's contents are properly initialized.  The new field
     will be initialized to its	default	value.	The sub-field name of the ob-
     ject pointed to by	data must correspond to	a struct structs_union (or
     equivalent	structure), and	field_name must	match one of the union's field
     names.  The structs_find(3) function may also be used to change the cur-
     rent union	field.

     structs_union_set() returns zero if successful, otherwise -1 with errno
     set appropriately.

     libpdel(3), structs(3), structs_type(3), structs_type_struct(3),

     The program below sets a union field using	the field name and value spec-
     ified on the command line:

	#include <sys/types.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>

	#include <stdio.h>
	#include <stdlib.h>
	#include <stdarg.h>
	#include <err.h>

	#include <pdel/structs/structs.h>
	#include <pdel/structs/type/union.h>
	#include <pdel/structs/type/string.h>
	#include <pdel/structs/type/ip4.h>
	#include <pdel/structs/type/int.h>
	#include <pdel/util/typed_mem.h>

	/* My union */
	union foobar {
		char		*name;
		u_int16_t	index;
		struct in_addr	ipaddr;

	/* My structs_union structure */
	DEFINE_STRUCTS_UNION(foobar_union, foobar);

	/* Structs type	for a 'struct foobar_union' */
	static const struct structs_ufield foobar_fields[] = {
		STRUCTS_UNION_FIELD(name, &structs_type_string),
		STRUCTS_UNION_FIELD(index, &structs_type_uint16),
		STRUCTS_UNION_FIELD(ipaddr, &structs_type_ip4),
	static const struct structs_type foobar_type =
		STRUCTS_UNION_TYPE(foobar, &foobar_fields);

	static void
	show_union(struct foobar_union *un)
		/* Show	the result */
		if (strcmp(un->field_name, "name") == 0)
			printf("name=\"%s\"\n",	un->un->name);
		else if	(strcmp(un->field_name,	"index") == 0)
			printf("index=%u\n", un->un->index);
		else if	(strcmp(un->field_name,	"ipaddr") == 0)
			printf("ipaddr=%s\n", inet_ntoa(un->un->ipaddr));
			printf("unknown	field \"%s\"\n", un->field_name);

	main(int argc, char **argv)
		struct foobar_union un;
		const char *name;
		char *value;
		char ebuf[64];

		/* Initialize union */
		if (structs_init(&foobar_type, NULL, &un) == -1)
			err(1, "structs_init");
		printf("Default	value: ");

		/* Get the requested field's name and value from command line */
		if (argc != 3)
			errx(1,	"usage:	setfield <name>	<value>");
		name = argv[1];
		value =	argv[2];

		/* Set the requested field's value */
		if (structs_set_string(&foobar_type, name,
		    value, &un,	ebuf, sizeof(ebuf)) == -1)
			errx(1,	"%s: %s", name,	ebuf);

		/* Show	the result */
		printf("New value: ");

		/* Done, clean up */
		structs_free(&foobar_type, NULL, &un);
		return (0);

     The PDEL library was developed at Packet Design, LLC.

     Archie Cobbs <>

FreeBSD	13.0			April 22, 2002			  FreeBSD 13.0


Want to link to this manual page? Use this URL:

home | help