/* netio/fget_netio_options.c.  Generated from netio_options.c.in by configure. */

/*
**  Copyright 2000-2004 University of Illinois Board of Trustees
**  Copyright 2000-2004 Mark D. Roth
**  All rights reserved.
**
**  fget_netio_options.c - netio option code
**
**  Mark D. Roth <roth@feep.net>
*/

#include <fget_netio_internal.h>

#include <stdio.h>

#ifdef STDC_HEADERS
# include <stdarg.h>
# include <string.h>
#endif


/******************************************************************************
***  value type information
******************************************************************************/

/*
** value types for options
*/
enum value_types {
	VAL_TYPE_UNSIGNED_SHORT = 1,
	VAL_TYPE_TIME_T,
	VAL_TYPE_LONG,
	VAL_TYPE_NETIO_HOOKFUNC_T,
	VAL_TYPE_CHAR_P,
	VAL_TYPE_VOID_P
};


/*
** size for each type
*/
struct type_size
{
	enum value_types ts_type;
	size_t ts_size;
};
typedef struct type_size type_size_t;


/*
** table of sizes for each value type
*/
static const type_size_t type_sizes[] = {
  { VAL_TYPE_UNSIGNED_SHORT,		sizeof(unsigned short) },
  { VAL_TYPE_TIME_T,			sizeof(time_t) },
  { VAL_TYPE_LONG,			sizeof(long) },
  { VAL_TYPE_NETIO_HOOKFUNC_T,		sizeof(netio_hookfunc_t) },
  { VAL_TYPE_CHAR_P,			sizeof(char *) },
  { VAL_TYPE_VOID_P,			sizeof(void *) },
  { 0,					0 }
};


/*
** utility function for finding the size for a given type
*/
static size_t
_type_sizeof(enum value_types value_type)
{
	int i;

	for (i = 0; type_sizes[i].ts_type != 0; i++)
	{
		if (type_sizes[i].ts_type == value_type)
			return type_sizes[i].ts_size;
	}

	return (size_t)0;
}


/******************************************************************************
***  option description information
******************************************************************************/

/*
** finds the offset within the NETIO handle of a given field
*/
#define netio_field_offset(field) \
	((unsigned int) (((char *) (&(((NETIO *)NULL)->field))) - ((char *)NULL)))


/*
** description of an option
*/
struct netio_option_description
{
	int o_option;			/* option number */
	size_t o_offset;		/* offset of field into NETIO struct */
	enum value_types o_type;	/* value type */
};
typedef struct netio_option_description netio_option_description_t;


/*
** here's the actual table of option descriptions
*/
static const netio_option_description_t netio_option_descriptions[] = {
	{
		NETIO_OPT_DEFAULT_SERVICE,
		netio_field_offset(n_default_service),
		VAL_TYPE_CHAR_P
	},
	{
		NETIO_OPT_DEFAULT_PORT,
		netio_field_offset(n_default_port),
		VAL_TYPE_UNSIGNED_SHORT
	},
	{
		NETIO_OPT_SEND_HOOK,
		netio_field_offset(n_sendhook),
		VAL_TYPE_NETIO_HOOKFUNC_T
	},
	{
		NETIO_OPT_RECV_HOOK,
		netio_field_offset(n_recvhook),
		VAL_TYPE_NETIO_HOOKFUNC_T
	},
	{
		NETIO_OPT_HOOK_HANDLE,
		netio_field_offset(n_hook_handle),
		VAL_TYPE_VOID_P
	},
	{
		NETIO_OPT_HOOK_DATA,
		netio_field_offset(n_hook_data),
		VAL_TYPE_VOID_P
	},
	{
		0,
		0,
		0
	}
};


/*
** utility function for finding the right option description in the table
*/
static const netio_option_description_t *
_find_option_description(int option)
{
	int i;

	for (i = 0; netio_option_descriptions[i].o_option != 0; i++)
	{
		if (netio_option_descriptions[i].o_option == option)
			return &(netio_option_descriptions[i]);
	}

	return NULL;
}


/*
** set option defaults
*/
void
fget_netio_init_options(NETIO *netio)
{
	/*
	** netio_connect() uses calloc(3) to create the NETIO handle,
	** so we only need to set those options that have a non-zero
	** default value
	*/
#if 0
	netio_set_options(
		netio,
		NETIO_OPT_PASSIVE,	(unsigned short)1,
		NETIO_OPT_CACHE_MAXSIZE,	(long)-1,
		NETIO_OPT_CACHE_EXPIRE,	(long)-1,
		0
	);
#endif
}


/******************************************************************************
***  code for setting options
******************************************************************************/

void
fget_netio_vset_options(NETIO *netio, va_list args)
{
	const netio_option_description_t *netio_option_description;
	int option;
	void *ptr;
	unsigned short val_unsigned_short;
	unsigned short *ptr_unsigned_short;
	time_t val_time_t;
	time_t *ptr_time_t;
	long val_long;
	long *ptr_long;
	netio_hookfunc_t val_netio_hookfunc_t;
	netio_hookfunc_t *ptr_netio_hookfunc_t;
	void *val_void_p;
	void **ptr_void_p;
	char **ptr_char_p;
	char *cp;

	while ((option = va_arg(args, int)) != 0)
	{
#ifdef DEBUG
		printf("    _vnetio_set_options(): option=%d\n", option);
#endif
		netio_option_description = _find_option_description(option);
		if (netio_option_description == NULL)
			continue;

		ptr = ((char *)netio + netio_option_description->o_offset);

		switch (netio_option_description->o_type)
		{
		case VAL_TYPE_UNSIGNED_SHORT:
			ptr_unsigned_short = (unsigned short *)ptr;
			/*
			** NOTE: we use int instead of short when
			** calling va_arg() because short will be
			** promoted to int when passed to a
			** varags function
			*/
			*ptr_unsigned_short = va_arg(args, unsigned int);
#ifdef DEBUG
			printf("    _vnetio_set_options(): value=%hu\n",
			       *ptr_unsigned_short);
#endif
			break;

		case VAL_TYPE_TIME_T:
			ptr_time_t = (time_t *)ptr;
			*ptr_time_t = va_arg(args, time_t);
#ifdef DEBUG
			printf("    _vnetio_set_options(): value=%lu\n",
			       (unsigned long)*ptr_time_t);
#endif
			break;

		case VAL_TYPE_LONG:
			ptr_long = (long *)ptr;
			*ptr_long = va_arg(args, long);
#ifdef DEBUG
			printf("    _vnetio_set_options(): value=%ld\n",
			       *ptr_long);
#endif
			break;

		case VAL_TYPE_NETIO_HOOKFUNC_T:
			ptr_netio_hookfunc_t = (netio_hookfunc_t *)ptr;
			*ptr_netio_hookfunc_t = va_arg(args, netio_hookfunc_t);
#ifdef DEBUG
			printf("    _vnetio_set_options(): value=0x%lx\n",
			       *ptr_netio_hookfunc_t);
#endif
			break;

		case VAL_TYPE_CHAR_P:
			ptr_char_p = (char **)ptr;
			cp = va_arg(args, char *);
			if (cp == NULL)
				*ptr_char_p = cp;
			else
			{
				if (*ptr_char_p != NULL)
					free(*ptr_char_p);
				*ptr_char_p = strdup(cp);
			}
#ifdef DEBUG
			printf("    _vnetio_set_options(): value=\"%s\"\n",
			       *ptr_char_p);
#endif
			break;

		case VAL_TYPE_VOID_P:
			ptr_void_p = (void **)ptr;
			*ptr_void_p = va_arg(args, void *);
#ifdef DEBUG
			printf("    _vnetio_set_options(): value=0x%lx\n",
			       *ptr_void_p);
#endif
			break;

		default:
			/* can't happen */
			break;
		}
	}
}


/*
** set options
*/
void
fget_netio_set_options(NETIO *netio, ...)
{
	va_list args;

	va_start(args, netio);
	fget_netio_vset_options(netio, args);
	va_end(args);
}


/******************************************************************************
***  code for getting options
******************************************************************************/

static void
fget_netio_vget_options(NETIO *netio, va_list args)
{
	const netio_option_description_t *netio_option_description;
	int option;
	void *opt_ptr, *arg_ptr;
	size_t sz;

	while ((option = va_arg(args, int)) != 0)
	{
		netio_option_description = _find_option_description(option);
		if (netio_option_description == NULL)
			return;

		opt_ptr = ((char *)netio + netio_option_description->o_offset);
		sz = _type_sizeof(netio_option_description->o_type);

		arg_ptr = va_arg(args, void *);

#ifdef DEBUG
		printf("    _vnetio_get_options(): option=%d sz=%lu\n",
		       option, (unsigned long)sz);
#endif

		memcpy(arg_ptr, opt_ptr, sz);
	}
}


/*
** get options
*/
void
fget_netio_get_options(NETIO *netio, ...)
{
	va_list args;

	va_start(args, netio);
	fget_netio_vget_options(netio, args);
	va_end(args);
}




syntax highlighted by Code2HTML, v. 0.9.1