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,
private_vici_message_t *this, char *label, FILE *out)
{
.get_value = _get_value,
.vget_value = _vget_value,
.get_encoding = _get_encoding,
+ .parse = _parse,
.dump = _dump,
.destroy = _destroy,
},
#include <library.h>
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;
/**
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
*/
*/
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.
*