summaryrefslogtreecommitdiffstats
path: root/src/ucl_emitter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ucl_emitter.c')
-rw-r--r--src/ucl_emitter.c136
1 files changed, 134 insertions, 2 deletions
diff --git a/src/ucl_emitter.c b/src/ucl_emitter.c
index 9ddf358..8bfbf09 100644
--- a/src/ucl_emitter.c
+++ b/src/ucl_emitter.c
@@ -62,6 +62,7 @@ UCL_EMIT_TYPE_OPS(json);
UCL_EMIT_TYPE_OPS(json_compact);
UCL_EMIT_TYPE_OPS(config);
UCL_EMIT_TYPE_OPS(yaml);
+UCL_EMIT_TYPE_OPS(msgpack);
#define UCL_EMIT_TYPE_CONTENT(type) { \
.ucl_emitter_write_elt = ucl_emit_ ## type ## _elt, \
@@ -71,12 +72,12 @@ UCL_EMIT_TYPE_OPS(yaml);
.ucl_emitter_end_array = ucl_emit_ ## type ##_end_array \
}
-
const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = {
[UCL_EMIT_JSON] = UCL_EMIT_TYPE_CONTENT(json),
[UCL_EMIT_JSON_COMPACT] = UCL_EMIT_TYPE_CONTENT(json_compact),
[UCL_EMIT_CONFIG] = UCL_EMIT_TYPE_CONTENT(config),
- [UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml)
+ [UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml),
+ [UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack)
};
/*
@@ -469,19 +470,150 @@ UCL_EMIT_TYPE_IMPL(json_compact, true)
UCL_EMIT_TYPE_IMPL(config, false)
UCL_EMIT_TYPE_IMPL(yaml, false)
+static void
+ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
+ const ucl_object_t *obj, bool first, bool print_key)
+{
+ ucl_object_iter_t it;
+ struct ucl_object_userdata *ud;
+ const char *ud_out;
+ const ucl_object_t *cur, *celt;
+
+ switch (obj->type) {
+ case UCL_INT:
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+ ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj));
+ break;
+
+ case UCL_FLOAT:
+ case UCL_TIME:
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+ ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj));
+ break;
+
+ case UCL_BOOLEAN:
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+ ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj));
+ break;
+
+ case UCL_STRING:
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
+ if (obj->flags & UCL_OBJECT_BINARY) {
+ ucl_emitter_print_binary_string_msgpack (ctx, obj->value.sv,
+ obj->len);
+ }
+ else {
+ ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
+ }
+ break;
+
+ case UCL_NULL:
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+ ucl_emitter_print_null_msgpack (ctx);
+ break;
+
+ case UCL_OBJECT:
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+ ucl_emit_msgpack_start_obj (ctx, obj, print_key);
+ it = NULL;
+
+ while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) {
+ LL_FOREACH (cur, celt) {
+ ucl_emit_msgpack_elt (ctx, celt, false, true);
+ /* XXX:
+ * in msgpack the length of objects is encoded within a single elt
+ * so in case of multi-value keys we are using merely the first
+ * element ignoring others
+ */
+ break;
+ }
+ }
+
+ break;
+
+ case UCL_ARRAY:
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+ ucl_emit_msgpack_start_array (ctx, obj, print_key);
+ it = NULL;
+
+ while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) {
+ ucl_emit_msgpack_elt (ctx, cur, false, false);
+ }
+
+ break;
+
+ case UCL_USERDATA:
+ ud = (struct ucl_object_userdata *)obj;
+ ucl_emitter_print_key_msgpack (print_key, ctx, obj);
+
+ if (ud->emitter) {
+ ud_out = ud->emitter (obj->value.ud);
+ if (ud_out == NULL) {
+ ud_out = "null";
+ }
+ }
+ ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
+ break;
+ }
+}
+
+static void
+ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx,
+ const ucl_object_t *obj, bool print_key)
+{
+ ucl_emitter_print_object_msgpack (ctx, obj->len);
+}
+
+static void
+ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx,
+ const ucl_object_t *obj, bool print_key)
+{
+ ucl_emitter_print_array_msgpack (ctx, obj->len);
+}
+
+static void
+ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx,
+ const ucl_object_t *obj)
+{
+
+}
+
+static void
+ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx,
+ const ucl_object_t *obj)
+{
+
+}
+
unsigned char *
ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
{
+ return ucl_object_emit_len (obj, emit_type, NULL);
+}
+
+unsigned char *
+ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type,
+ size_t *outlen)
+{
unsigned char *res = NULL;
struct ucl_emitter_functions *func;
+ UT_string *s;
+
if (obj == NULL) {
return NULL;
}
func = ucl_object_emit_memory_funcs ((void **)&res);
+ s = func->ud;
if (func != NULL) {
ucl_object_emit_full (obj, emit_type, func);
+
+ if (outlen != NULL) {
+ *outlen = s->i;
+ }
+
ucl_object_emit_funcs_free (func);
}
OpenPOWER on IntegriCloud