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

  
 
  

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

NAME
     structs_type_union -- structs types for C unions

LIBRARY
     PDEL Library (libpdel, -lpdel)

SYNOPSIS
     #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);

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

DESCRIPTION
     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 intermedi-
     ate 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 struc-
     ture (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 pre-
     vious field contents to be lost.

     As  a special case, the field named "field_name" is also read-only accessi-
     ble 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 struc-
     tures 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:

	   #define STRUCTS_UNION_FIELD_END { NULL, NULL }

     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 default 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  object
     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  current  union
     field.

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

SEE ALSO
     libpdel(3),     structs(3),     structs_type(3),	 structs_type_struct(3),
     structs_xml_input

EXAMPLES
     The program below sets a union field using the field name and value  speci-
     fied 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),
		STRUCTS_UNION_FIELD_END
	};
	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));
		else
			printf("unknown field \"%s\"\n", un->field_name);
	}

	int
	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: ");
		show_union(&un);

		/* 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: ");
		show_union(&un);

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

HISTORY
     The    PDEL    library    was    developed    at	 Packet   Design,   LLC.
     http://www.packetdesign.com/

AUTHORS
     Archie Cobbs <archie@freebsd.org>

FreeBSD ports 15.quarterly	 April 22, 2002 	   STRUCTS_TYPE_UNION(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=STRUCTS_UNION_FIELD&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help