*** /dev/null Sat Nov 23 01:26:37 2024
--- - Sat Nov 23 01:26:56 2024
***************
*** 0 ****
--- 1,214 ----
+
+ #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;
+ }
+
|