ossp-pkg/lmtp2nntp/lmtp2nntp_val.c
1.1
#include "lmtp2nntp_val.h"
#include "lmtp2nntp_lh.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
/* usually val_object_t.data is a pointer val_object_t.data.p, but VAL_INLINE
* signals val_object_t.data is actual data val_object_t.data.[csilfd]
*/
enum {
VAL_INLINE = 1<<31
};
typedef struct {
char *name;
int type;
union {
void *p;
char c;
short s;
int i;
long l;
float f;
double d;
} data;
} val_object_t;
struct val_s {
lh_t *lh;
};
static void *val_unionptr(val_object_t *obj)
{
void *storage;
switch (obj->type & ~VAL_INLINE) {
case VAL_TYPE_PTR:
storage = &obj->data.p;
break;
case VAL_TYPE_CHAR:
storage = (void *)&obj->data.c;
break;
case VAL_TYPE_SHORT:
storage = (void *)&obj->data.s;
break;
case VAL_TYPE_INT:
storage = (void *)&obj->data.i;
break;
case VAL_TYPE_LONG:
storage = (void *)&obj->data.l;
break;
case VAL_TYPE_FLOAT:
storage = (void *)&obj->data.f;
break;
case VAL_TYPE_DOUBLE:
storage = (void *)&obj->data.d;
break;
default:
storage = NULL;
}
return storage;
}
val_rc_t val_create(val_t **valp)
{
val_t *val;
if ((val = (val_t *)malloc(sizeof(val_t))) == NULL)
return VAL_MEMORY;
if ((val->lh = lh_create()) == NULL)
return VAL_LH;
*valp = val;
return VAL_OK;
}
val_rc_t val_destroy(val_t *val)
{
if (val == NULL)
return VAL_MEMORY;
lh_destroy(val->lh);
free(val);
return VAL_OK;
}
val_rc_t val_reg(val_t *val, const char *name, int type, void *storage)
{
val_object_t obj;
if ((obj.name = strdup(name)) == NULL)
return VAL_MEMORY;
obj.type = type;
if (storage == NULL) {
obj.type |= VAL_INLINE;
obj.data.l = 0;
}
else
obj.data.p = storage;
if (! lh_insert(val->lh, name, strlen(name), &obj, sizeof(obj), 1))
return VAL_LH;
return VAL_OK;
}
val_rc_t val_vset(val_t *val, const char *name, va_list ap)
{
val_object_t *obj;
void *storage;
const char *cp;
if ((cp = strchr(name, '.')) != NULL) {
if (! lh_lookup(val->lh, name, cp-name, (void **)&obj, NULL))
return VAL_LH;
return val_vset((val_t *)obj->data.p, cp+1, ap);
}
if (! lh_lookup(val->lh, name, strlen(name), (void **)&obj, NULL))
return VAL_LH;
if (obj->type & VAL_INLINE)
storage = val_unionptr(obj);
else
storage = obj->data.p;
switch(obj->type & ~VAL_INLINE) {
case VAL_TYPE_PTR:
*(char **)storage = (char *)va_arg(ap, void *);
break;
case VAL_TYPE_CHAR:
*(char *)storage = (char)va_arg(ap, int);
break;
case VAL_TYPE_SHORT:
*(short *)storage = (short)va_arg(ap, int);
break;
case VAL_TYPE_INT:
*(int *)storage = (int)va_arg(ap, int);
break;
case VAL_TYPE_LONG:
*(long *)storage = (long)va_arg(ap, long);
break;
case VAL_TYPE_FLOAT:
*(float *)storage = (float)va_arg(ap, double);
break;
case VAL_TYPE_DOUBLE:
*(double *)storage = (double)va_arg(ap, double);
break;
}
return VAL_OK;
}
val_rc_t val_set(val_t *val, const char *name, ...)
{
val_rc_t rc;
va_list ap;
va_start(ap, name);
rc = val_vset(val, name, ap);
va_end(ap);
return rc;
}
val_rc_t val_vget(val_t *val, const char *name, va_list ap)
{
val_object_t *obj;
void *storage;
const char *cp;
if ((cp = strchr(name, '.')) != NULL) {
if (! lh_lookup(val->lh, name, cp-name, (void **)&obj, NULL))
return VAL_LH;
return val_vget((val_t *)obj->data.p, cp+1, ap);
}
if (! lh_lookup(val->lh, name, strlen(name), (void **)&obj, NULL))
return VAL_LH;
if (obj->type & VAL_INLINE)
storage = val_unionptr(obj);
else
storage = obj->data.p;
switch (obj->type & ~VAL_INLINE) {
case VAL_TYPE_PTR:
*((char **)va_arg(ap, void *)) = *(char **)storage;
break;
case VAL_TYPE_CHAR:
*((char *)va_arg(ap, int *)) = *(char *)storage;
break;
case VAL_TYPE_SHORT:
*((short *)va_arg(ap, int *)) = *(short *)storage;
break;
case VAL_TYPE_INT:
*((int *)va_arg(ap, int *)) = *(int *)storage;
break;
case VAL_TYPE_LONG:
*((long *)va_arg(ap, long *)) = *(long *)storage;
break;
case VAL_TYPE_FLOAT:
*((float *)va_arg(ap, double *)) = *(float *)storage;
break;
case VAL_TYPE_DOUBLE:
*((double *)va_arg(ap, double *)) = *(double *)storage;
break;
}
return VAL_OK;
}
val_rc_t val_get(val_t *val, const char *name, ...)
{
val_rc_t rc;
va_list ap;
va_start(ap, name);
rc = val_vget(val, name, ap);
va_end(ap);
return rc;
}