vici: Add a callback based recursive parser function
This commit is contained in:
parent
d9ae1c68e5
commit
993bfe95fb
|
@ -94,6 +94,8 @@ struct vici_res_t {
|
|||
char *name;
|
||||
/** currently enumerating value */
|
||||
chunk_t value;
|
||||
/** section nesting level of callback parser */
|
||||
int level;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -495,6 +497,7 @@ void* vici_parse_value(vici_res_t *res, int *len)
|
|||
*len = res->value.len;
|
||||
return res->value.ptr;
|
||||
default:
|
||||
*len = 0;
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -522,6 +525,98 @@ char* vici_parse_value_str(vici_res_t *res)
|
|||
}
|
||||
}
|
||||
|
||||
int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
|
||||
vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
|
||||
void *user)
|
||||
{
|
||||
char *name, *list = NULL;
|
||||
void *value;
|
||||
int base, len, ret;
|
||||
|
||||
base = res->level;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (vici_parse(res))
|
||||
{
|
||||
case VICI_PARSE_KEY_VALUE:
|
||||
if (res->level == base)
|
||||
{
|
||||
if (kv)
|
||||
{
|
||||
name = vici_parse_name(res);
|
||||
value = vici_parse_value(res, &len);
|
||||
if (name && value)
|
||||
{
|
||||
ret = kv(user, res, name, value, len);
|
||||
if (ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VICI_PARSE_BEGIN_SECTION:
|
||||
if (res->level++ == base)
|
||||
{
|
||||
if (section)
|
||||
{
|
||||
name = vici_parse_name(res);
|
||||
if (name)
|
||||
{
|
||||
ret = section(user, res, name);
|
||||
if (ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VICI_PARSE_END_SECTION:
|
||||
if (res->level-- == base)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case VICI_PARSE_END:
|
||||
res->level = 0;
|
||||
return 0;
|
||||
case VICI_PARSE_BEGIN_LIST:
|
||||
if (res->level == base)
|
||||
{
|
||||
list = vici_parse_name(res);
|
||||
}
|
||||
break;
|
||||
case VICI_PARSE_LIST_ITEM:
|
||||
if (list && li)
|
||||
{
|
||||
value = vici_parse_value(res, &len);
|
||||
if (value)
|
||||
{
|
||||
ret = li(user, res, list, value, len);
|
||||
if (ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VICI_PARSE_END_LIST:
|
||||
if (res->level == base)
|
||||
{
|
||||
list = NULL;
|
||||
}
|
||||
break;
|
||||
case VICI_PARSE_ERROR:
|
||||
res->level = 0;
|
||||
errno = EBADMSG;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* vici_find(vici_res_t *res, int *len, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
|
|
@ -123,6 +123,29 @@ typedef enum {
|
|||
*/
|
||||
typedef void (*vici_event_cb_t)(void *user, char *name, vici_res_t *msg);
|
||||
|
||||
/**
|
||||
* Callback function for key/value and list items, invoked by vici_parse_cb().
|
||||
*
|
||||
* @param user user data, as passed to vici_parse_cb()
|
||||
* @param res message currently parsing
|
||||
* @param name name of key or list
|
||||
* @param value value buffer
|
||||
* @param len length of value buffer
|
||||
* @return 0 if parsed successfully
|
||||
*/
|
||||
typedef int (*vici_parse_value_cb_t)(void *user, vici_res_t *res, char *name,
|
||||
void *value, int len);
|
||||
|
||||
/**
|
||||
* Callback function for sections, invoked by vici_parse_cb().
|
||||
*
|
||||
* @param user user data, as passed to vici_parse_cb()
|
||||
* @param res message currently parsing
|
||||
* @param name name of the section
|
||||
* @return 0 if parsed successfully
|
||||
*/
|
||||
typedef int (*vici_parse_section_cb_t)(void *user, vici_res_t *res, char *name);
|
||||
|
||||
/**
|
||||
* Open a new vici connection.
|
||||
*
|
||||
|
@ -309,6 +332,24 @@ void* vici_parse_value(vici_res_t *res, int *len);
|
|||
char* vici_parse_value_str(vici_res_t *res);
|
||||
|
||||
/**
|
||||
* Parse a complete message with callbacks.
|
||||
*
|
||||
* 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
|
||||
* vici_parse_cb() from within a section callback.
|
||||
*
|
||||
* @param res message to parse
|
||||
* @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 0 if parsing successful
|
||||
*/
|
||||
int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
|
||||
vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
|
||||
void *user);
|
||||
|
||||
/*
|
||||
* Find a blob value in a message for a given key.
|
||||
*
|
||||
* Sections can be selected by prefixing them separated by dots.
|
||||
|
|
Loading…
Reference in New Issue