yml: support multiple merge values

This adds support for merging multiple values, using a list of
dictionaries:

    foo:
      <<: [*foo, *bar]
This commit is contained in:
Daniel Eklöf 2018-12-29 16:06:04 +01:00
parent 36e3bdd9fd
commit b2082e38ed

56
yml.c
View file

@ -161,23 +161,53 @@ post_process(struct yml_node *node)
if (strcmp(it->item.key->scalar.value, "<<") != 0) if (strcmp(it->item.key->scalar.value, "<<") != 0)
continue; continue;
assert(it->item.value->type == DICT); if (it->item.value->type == LIST) {
tll_foreach(it->item.value->dict.pairs, v_it) { /*
struct dict_pair p = { * Merge value is a list (of dictionaries)
.key = v_it->item.key, * e.g. <<: [*foo, *bar]
.value = v_it->item.value, */
}; tll_foreach(it->item.value->list.values, v_it) {
tll_push_back(node->dict.pairs, p); assert(v_it->item->type == DICT);
} tll_foreach(v_it->item->dict.pairs, vv_it) {
struct dict_pair p = {
.key = vv_it->item.key,
.value = vv_it->item.value,
};
tll_push_back(node->dict.pairs, p);
}
/* Destroy list here, *without* freeing nodes (since nodes /* Destroy lits, but don't free (since its nodes
* have been moved to this node), *before* destroying the * have been moved to this node), *before*
* key/value nodes. This ensures the dict nodes aren't * destroying the key/value nodes. This ensures
* free:d in the yml_destroy() below */ * the dict nodes aren't free:d in the
tll_free(it->item.value->dict.pairs); * yml_destroy() below). */
tll_free(v_it->item->dict.pairs);
}
} else {
/*
* Merge value is a dictionary only
* e.g. <<: *foo
*/
assert(it->item.value->type == DICT);
tll_foreach(it->item.value->dict.pairs, v_it) {
struct dict_pair p = {
.key = v_it->item.key,
.value = v_it->item.value,
};
tll_push_back(node->dict.pairs, p);
}
/* Destroy list here, *without* freeing nodes (since
* nodes have been moved to this node), *before*
* destroying the key/value nodes. This ensures the
* dict nodes aren't free:d in the yml_destroy()
* below */
tll_free(it->item.value->dict.pairs);
}
yml_destroy(it->item.key); yml_destroy(it->item.key);
yml_destroy(it->item.value); yml_destroy(it->item.value);
tll_remove(node->dict.pairs, it); tll_remove(node->dict.pairs, it);
} }
break; break;