vici: Add generic callback based vici message parsing
This commit is contained in:
@@ -412,6 +412,100 @@ METHOD(vici_message_t, get_encoding, chunk_t,
|
|||||||
return this->encoding;
|
return this->encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private parse context data
|
||||||
|
*/
|
||||||
|
struct vici_parse_context_t {
|
||||||
|
/** current section nesting level */
|
||||||
|
int level;
|
||||||
|
/** parse enumerator */
|
||||||
|
enumerator_t *e;
|
||||||
|
};
|
||||||
|
|
||||||
|
METHOD(vici_message_t, parse, bool,
|
||||||
|
private_vici_message_t *this, vici_parse_context_t *ctx,
|
||||||
|
vici_section_cb_t section, vici_value_cb_t kv, vici_value_cb_t li,
|
||||||
|
void *user)
|
||||||
|
{
|
||||||
|
vici_parse_context_t root = {};
|
||||||
|
char *name, *list = NULL;
|
||||||
|
vici_type_t type;
|
||||||
|
chunk_t value;
|
||||||
|
int base;
|
||||||
|
bool ok = TRUE;
|
||||||
|
|
||||||
|
if (!ctx)
|
||||||
|
{
|
||||||
|
ctx = &root;
|
||||||
|
root.e = create_enumerator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
base = ctx->level;
|
||||||
|
|
||||||
|
while (ok)
|
||||||
|
{
|
||||||
|
ok = ctx->e->enumerate(ctx->e, &type, &name, &value);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case VICI_KEY_VALUE:
|
||||||
|
if (ctx->level == base && kv)
|
||||||
|
{
|
||||||
|
name = strdup(name);
|
||||||
|
this->strings->insert_last(this->strings, name);
|
||||||
|
ok = kv(user, &this->public, name, value);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case VICI_LIST_START:
|
||||||
|
if (ctx->level == base)
|
||||||
|
{
|
||||||
|
list = strdup(name);
|
||||||
|
this->strings->insert_last(this->strings, list);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case VICI_LIST_ITEM:
|
||||||
|
if (list && li)
|
||||||
|
{
|
||||||
|
name = strdup(name);
|
||||||
|
this->strings->insert_last(this->strings, name);
|
||||||
|
ok = li(user, &this->public, list, value);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case VICI_LIST_END:
|
||||||
|
if (ctx->level == base)
|
||||||
|
{
|
||||||
|
list = NULL;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case VICI_SECTION_START:
|
||||||
|
if (ctx->level++ == base && section)
|
||||||
|
{
|
||||||
|
name = strdup(name);
|
||||||
|
this->strings->insert_last(this->strings, name);
|
||||||
|
ok = section(user, &this->public, ctx, name);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case VICI_SECTION_END:
|
||||||
|
if (ctx->level-- == base)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case VICI_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx == &root)
|
||||||
|
{
|
||||||
|
root.e->destroy(root.e);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(vici_message_t, dump, bool,
|
METHOD(vici_message_t, dump, bool,
|
||||||
private_vici_message_t *this, char *label, FILE *out)
|
private_vici_message_t *this, char *label, FILE *out)
|
||||||
{
|
{
|
||||||
@@ -506,6 +600,7 @@ vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup)
|
|||||||
.get_value = _get_value,
|
.get_value = _get_value,
|
||||||
.vget_value = _vget_value,
|
.vget_value = _vget_value,
|
||||||
.get_encoding = _get_encoding,
|
.get_encoding = _get_encoding,
|
||||||
|
.parse = _parse,
|
||||||
.dump = _dump,
|
.dump = _dump,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
|
||||||
typedef struct vici_message_t vici_message_t;
|
typedef struct vici_message_t vici_message_t;
|
||||||
|
typedef struct vici_parse_context_t vici_parse_context_t;
|
||||||
typedef enum vici_type_t vici_type_t;
|
typedef enum vici_type_t vici_type_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,6 +48,30 @@ enum vici_type_t {
|
|||||||
VICI_END
|
VICI_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function for key/value and list items, invoked by parse().
|
||||||
|
*
|
||||||
|
* @param user user data, as passed to parse()
|
||||||
|
* @param message message currently parsing
|
||||||
|
* @param name name of key or list
|
||||||
|
* @param value parsed value
|
||||||
|
* @return TRUE if parsed successfully
|
||||||
|
*/
|
||||||
|
typedef bool (*vici_value_cb_t)(void *user, vici_message_t *message,
|
||||||
|
char *name, chunk_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function for sections, invoked by parse().
|
||||||
|
*
|
||||||
|
* @param user user data, as passed to parse()
|
||||||
|
* @param message message currently parsing
|
||||||
|
* @param ctx parse context, to pass to recursive parse() invocations.
|
||||||
|
* @param name name of the section
|
||||||
|
* @return TRUE if parsed successfully
|
||||||
|
*/
|
||||||
|
typedef bool (*vici_section_cb_t)(void *user, vici_message_t *message,
|
||||||
|
vici_parse_context_t *ctx, char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Names for vici encoding types
|
* Names for vici encoding types
|
||||||
*/
|
*/
|
||||||
@@ -137,6 +162,25 @@ struct vici_message_t {
|
|||||||
*/
|
*/
|
||||||
chunk_t (*get_encoding)(vici_message_t *this);
|
chunk_t (*get_encoding)(vici_message_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a message using callback functions.
|
||||||
|
*
|
||||||
|
* Any of the callbacks may be NULL to skip this kind of item. Callbacks are
|
||||||
|
* invoked for the current section level only. To descent into sections,
|
||||||
|
* call parse() from within a section callback using the provided parse
|
||||||
|
* context.
|
||||||
|
*
|
||||||
|
* @param ctx parse context, NULL for root level
|
||||||
|
* @param section callback invoked for each section
|
||||||
|
* @param kv callback invoked for key/value pairs
|
||||||
|
* @param li callback invoked for list items
|
||||||
|
* @param user user data to pass to callbacks
|
||||||
|
* @return TRUE if parsed successfully
|
||||||
|
*/
|
||||||
|
bool (*parse)(vici_message_t *this, vici_parse_context_t *ctx,
|
||||||
|
vici_section_cb_t section, vici_value_cb_t kv,
|
||||||
|
vici_value_cb_t li, void *user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dump a message text representation to a FILE stream.
|
* Dump a message text representation to a FILE stream.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user