OSSP CVS Repository

ossp - ossp-pkg/lmtp2nntp/lmtp2nntp_val.c 1.1
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

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;
}


CVSTrac 2.0.1