vici: Add a callback based recursive parser function
This commit is contained in:
@@ -94,6 +94,8 @@ struct vici_res_t {
|
|||||||
char *name;
|
char *name;
|
||||||
/** currently enumerating value */
|
/** currently enumerating value */
|
||||||
chunk_t 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;
|
*len = res->value.len;
|
||||||
return res->value.ptr;
|
return res->value.ptr;
|
||||||
default:
|
default:
|
||||||
|
*len = 0;
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
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, ...)
|
void* vici_find(vici_res_t *res, int *len, char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|||||||
@@ -123,6 +123,29 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
typedef void (*vici_event_cb_t)(void *user, char *name, vici_res_t *msg);
|
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.
|
* 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);
|
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.
|
* Find a blob value in a message for a given key.
|
||||||
*
|
*
|
||||||
* Sections can be selected by prefixing them separated by dots.
|
* Sections can be selected by prefixing them separated by dots.
|
||||||
|
|||||||
Reference in New Issue
Block a user