GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
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);

int
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 intermediate 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 accessible 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:

#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.

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

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

The program below sets a union field using the field name and value specified 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);
}

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

Archie Cobbs ⟨archie@freebsd.org⟩
April 22, 2002 FreeBSD 13.1-RELEASE

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.