diff --git a/common.c b/common.c index 4b7e6bf..10d4293 100644 --- a/common.c +++ b/common.c @@ -32,6 +32,7 @@ #include "liberty/liberty.c" #include +#include #include // --- Logging ----------------------------------------------------------------- @@ -639,10 +640,95 @@ config_item_get (struct config_item_ *self, const char *path) // TODO } -static void -config_item_write (struct config_item_ *root, struct str *output) +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +struct config_writer { - // TODO + struct str *output; + unsigned indent; +}; + +static void config_item_write_object_innards + (struct config_writer *self, struct config_item_ *object); + +static void +config_item_write_value (struct config_writer *self, struct config_item_ *value) +{ + switch (value->type) + { + case CONFIG_ITEM_NULL: + str_append (self->output, "null"); + break; + case CONFIG_ITEM_BOOLEAN: + str_append (self->output, value->value.boolean ? "on" : "off"); + break; + case CONFIG_ITEM_INTEGER: + str_append_printf (self->output, "%" PRIi64, value->value.integer); + break; + case CONFIG_ITEM_STRING: + case CONFIG_ITEM_STRING_ARRAY: + // TODO + break; + case CONFIG_ITEM_OBJECT: + { + char indent[self->indent + 1]; + memset (indent, '\t', self->indent); + indent[self->indent] = 0; + + str_append (self->output, "{\n"); + + self->indent++; + config_item_write_object_innards (self, value); + self->indent--; + + str_append_printf (self->output, "%s}", indent); + break; + } + default: + hard_assert (!"invalid item type"); + } +} + +static void +config_item_write_kv_pair (struct config_writer *self, + const char *key, struct config_item_ *value) +{ + char indent[self->indent + 1]; + memset (indent, '\t', self->indent); + indent[self->indent] = 0; + + if (value->schema && value->schema->comment) + str_append_printf (self->output, + "%s# %s\n", indent, value->schema->comment); + + str_append_printf (self->output, "%s%s = ", indent, key); + config_item_write_value (self, value); + str_append_c (self->output, '\n'); +} + +static void +config_item_write_object_innards + (struct config_writer *self, struct config_item_ *object) +{ + hard_assert (object->type == CONFIG_ITEM_OBJECT); + + struct str_map_iter iter; + str_map_iter_init (&iter, &object->value.object); + + struct config_item_ *value; + while ((value = str_map_iter_next (&iter))) + config_item_write_kv_pair (self, iter.link->key, value); +} + +static void +config_item_write (struct config_item_ *value, + bool object_innards, struct str *output) +{ + struct config_writer writer = { .output = output, .indent = 0 }; + if (object_innards) + config_item_write_object_innards (&writer, value); + else + config_item_write_value (&writer, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -