--- lmtp2nntp_val.c 2002/01/15 13:02:20 1.1
+++ lmtp2nntp_val.c 2002/01/16 09:46:52 1.2
@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-
+#include <stdio.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]
@@ -14,9 +14,9 @@
};
typedef struct {
- char *name;
int type;
union {
+ val_t *v;
void *p;
char c;
short s;
@@ -25,41 +25,49 @@
float f;
double d;
} data;
+ char *desc;
} val_object_t;
struct val_s {
lh_t *lh;
};
-static void *val_unionptr(val_object_t *obj)
+static void *val_storage(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;
+ if (obj->type & VAL_INLINE) {
+ switch (obj->type & ~VAL_INLINE) {
+ case VAL_TYPE_VAL:
+ storage = &obj->data.v;
+ break;
+ case VAL_TYPE_PTR:
+ storage = &obj->data.p;
+ break;
+ case VAL_TYPE_CHAR:
+ storage = &obj->data.c;
+ break;
+ case VAL_TYPE_SHORT:
+ storage = &obj->data.s;
+ break;
+ case VAL_TYPE_INT:
+ storage = &obj->data.i;
+ break;
+ case VAL_TYPE_LONG:
+ storage = &obj->data.l;
+ break;
+ case VAL_TYPE_FLOAT:
+ storage = &obj->data.f;
+ break;
+ case VAL_TYPE_DOUBLE:
+ storage = &obj->data.d;
+ break;
+ default:
+ storage = NULL;
+ }
}
+ else
+ storage = obj->data.p;
return storage;
}
@@ -67,40 +75,77 @@
{
val_t *val;
+ if (valp == NULL)
+ return VAL_ERR_ARG;
if ((val = (val_t *)malloc(sizeof(val_t))) == NULL)
- return VAL_MEMORY;
- if ((val->lh = lh_create()) == NULL)
- return VAL_LH;
+ return VAL_ERR_SYS;
+ if ((val->lh = lh_create()) == NULL) {
+ free(val);
+ return VAL_ERR_SYS;
+ }
*valp = val;
return VAL_OK;
}
+static int (val_destroy_cb)(void *_ctx, const void *keyptr, int keylen, const void *datptr, int datlen)
+{
+ val_object_t *obj;
+
+ obj = (val_object_t *)datptr;
+ if (obj->desc != NULL)
+ free(obj->desc);
+ return TRUE;
+}
+
val_rc_t val_destroy(val_t *val)
{
if (val == NULL)
- return VAL_MEMORY;
- lh_destroy(val->lh);
+ return VAL_ERR_ARG;
+ lh_apply(val->lh, val_destroy_cb, NULL);
+ if (!lh_destroy(val->lh))
+ return VAL_ERR_SYS;
free(val);
return VAL_OK;
}
-val_rc_t val_reg(val_t *val, const char *name, int type, void *storage)
+val_rc_t val_reg(val_t *val, const char *name, int type, const char *desc, void *storage)
{
- val_object_t obj;
+ val_object_t *obj;
+ val_object_t newobj;
+ const char *cp;
+ val_t *child;
+
+ if (val == NULL || name == NULL || type == 0)
+ return VAL_ERR_ARG;
+
+
- if ((obj.name = strdup(name)) == NULL)
- return VAL_MEMORY;
- obj.type = type;
- if (storage == NULL) {
- obj.type |= VAL_INLINE;
- obj.data.l = 0;
+ if ((cp = strchr(name, '.')) != NULL) {
+ if (!lh_lookup(val->lh, name, cp-name, (void **)&obj, NULL))
+ return VAL_ERR_ARG;
+ if (!(obj->type & VAL_TYPE_VAL))
+ return VAL_ERR_USE;
+ child = *(val_t **)(val_storage(obj));
+ return val_reg(child, cp+1, type, desc, storage);
}
+
+
+
+ if (desc != NULL)
+ newobj.desc = strdup(desc);
else
- obj.data.p = storage;
+ newobj.desc = NULL;
+ if (storage == NULL) {
+ newobj.type = (type | VAL_INLINE);
+ newobj.data.l = 0;
+ }
+ else {
+ newobj.type = (type & ~VAL_INLINE);
+ newobj.data.p = storage;
+ }
+ if (!lh_insert(val->lh, name, strlen(name), &newobj, sizeof(newobj), 1))
+ return VAL_ERR_SYS;
- if (! lh_insert(val->lh, name, strlen(name), &obj, sizeof(obj), 1))
- return VAL_LH;
-
return VAL_OK;
}
@@ -109,19 +154,25 @@
val_object_t *obj;
void *storage;
const char *cp;
+ val_t *child;
+ if (val == NULL || name == NULL || ap == NULL)
+ return VAL_ERR_ARG;
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) {
+ if (!lh_lookup(val->lh, name, cp-name, (void **)&obj, NULL))
+ return VAL_ERR_ARG;
+ if (!(obj->type & VAL_TYPE_VAL))
+ return VAL_ERR_USE;
+ child = *(val_t **)(val_storage(obj));
+ return val_vset(child, cp+1, ap);
+ }
+ if (!lh_lookup(val->lh, name, strlen(name), (void **)&obj, NULL))
+ return VAL_ERR_ARG;
+ storage = val_storage(obj);
+ switch (obj->type & ~VAL_INLINE) {
+ case VAL_TYPE_VAL:
+ *(val_t **)storage = (val_t *)va_arg(ap, void *);
+ break;
case VAL_TYPE_PTR:
*(char **)storage = (char *)va_arg(ap, void *);
break;
@@ -152,6 +203,8 @@
val_rc_t rc;
va_list ap;
+ if (val == NULL || name == NULL)
+ return VAL_ERR_ARG;
va_start(ap, name);
rc = val_vset(val, name, ap);
va_end(ap);
@@ -163,19 +216,25 @@
val_object_t *obj;
void *storage;
const char *cp;
+ val_t *child;
+ if (val == NULL || name == NULL || ap == NULL)
+ return VAL_ERR_ARG;
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;
+ if (!lh_lookup(val->lh, name, cp-name, (void **)&obj, NULL))
+ return VAL_ERR_ARG;
+ if (!(obj->type & VAL_TYPE_VAL))
+ return VAL_ERR_USE;
+ child = *(val_t **)(val_storage(obj));
+ return val_vget(child, cp+1, ap);
+ }
+ if (!lh_lookup(val->lh, name, strlen(name), (void **)&obj, NULL))
+ return VAL_ERR_ARG;
+ storage = val_storage(obj);
switch (obj->type & ~VAL_INLINE) {
+ case VAL_TYPE_VAL:
+ *((val_t **)va_arg(ap, void *)) = *(val_t **)storage;
+ break;
case VAL_TYPE_PTR:
*((char **)va_arg(ap, void *)) = *(char **)storage;
break;
@@ -206,9 +265,61 @@
val_rc_t rc;
va_list ap;
+ if (val == NULL || name == NULL)
+ return VAL_ERR_ARG;
va_start(ap, name);
rc = val_vget(val, name, ap);
va_end(ap);
return rc;
}
+#define VAL_MAXNAME 1024
+
+typedef struct {
+ val_cb_t cb;
+ void *ctx;
+ val_rc_t rc;
+} val_apply_ctx_t;
+
+static int (val_apply_cb)(void *_ctx, const void *keyptr, int keylen, const void *datptr, int datlen)
+{
+ val_apply_ctx_t *ctx = (val_apply_ctx_t *)_ctx;
+ val_object_t *obj;
+ char name[VAL_MAXNAME+1];
+
+ /* on-the-fly create NUL-terminated name string */
+ if (keylen > VAL_MAXNAME) {
+ ctx->rc = VAL_ERR_MEM;
+ return FALSE;
+ }
+ strncpy(name, (char *)keyptr, keylen);
+ *((char *)name+keylen) = '\0';
+
+ /* take object */
+ if (datlen != sizeof(val_object_t)) {
+ ctx->rc = VAL_ERR_ARG;
+ return FALSE;
+ }
+ obj = (val_object_t *)datptr;
+
+ /* execute VAL callback */
+ if ((ctx->rc = ctx->cb(ctx->ctx, name, (obj->type & ~VAL_INLINE), obj->desc, val_storage(obj))) != VAL_OK)
+ return FALSE;
+
+ return TRUE;
+}
+
+val_rc_t val_apply(val_t *val, val_cb_t cb, void *ctx)
+{
+ val_apply_ctx_t val_ctx;
+
+ if (val == NULL || cb == NULL)
+ return VAL_ERR_ARG;
+ val_ctx.cb = cb;
+ val_ctx.ctx = ctx;
+ val_ctx.rc = VAL_OK;
+ if (!lh_apply(val->lh, val_apply_cb, &val_ctx))
+ return VAL_ERR_SYS;
+ return val_ctx.rc;
+}
+
|