Skip to content

Commit

Permalink
emit: strip empty kv take #2
Browse files Browse the repository at this point in the history
The original feature did not work well for flow/json outputs and
produced invalid yaml/json. This new take works.

Signed-off-by: Pantelis Antoniou <[email protected]>
  • Loading branch information
pantoniou committed Jan 13, 2022
1 parent b4c5591 commit f62fffd
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 20 deletions.
29 changes: 20 additions & 9 deletions src/lib/fy-doc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,9 +1265,11 @@ bool fy_node_compare_user(struct fy_node *fyn1, struct fy_node *fyn2,
}

fynpp1 = alloca(sizeof(*fynpp1) * (count1 + 1));
fynpp2 = alloca(sizeof(*fynpp2) * (count2 + 1));

fy_node_mapping_fill_array(fyn1, fynpp1, count1);
fy_node_mapping_perform_sort(fyn1, sort_fn, sort_fn_arg, fynpp1, count1);

fynpp2 = alloca(sizeof(*fynpp2) * (count2 + 1));
fy_node_mapping_fill_array(fyn2, fynpp2, count2);
fy_node_mapping_perform_sort(fyn2, sort_fn, sort_fn_arg, fynpp2, count2);

for (i = 0; i < count1; i++) {
Expand Down Expand Up @@ -5725,14 +5727,11 @@ static int fy_node_mapping_sort_cmp_default(const struct fy_node_pair *fynp_a,
return idx_a > idx_b ? 1 : (idx_a < idx_b ? -1 : 0);
}

void fy_node_mapping_perform_sort(struct fy_node *fyn_map,
fy_node_mapping_sort_fn key_cmp, void *arg,
void fy_node_mapping_fill_array(struct fy_node *fyn_map,
struct fy_node_pair **fynpp, int count)
{
int i;
struct fy_node_pair *fynpi;
struct fy_node_mapping_sort_ctx ctx;
struct fy_node_cmp_arg def_arg;
int i;

for (i = 0, fynpi = fy_node_pair_list_head(&fyn_map->mapping); i < count && fynpi;
fynpi = fy_node_pair_next(&fyn_map->mapping, fynpi), i++)
Expand All @@ -5743,6 +5742,15 @@ void fy_node_mapping_perform_sort(struct fy_node *fyn_map,
fynpp[i++] = NULL;
assert(i == count);

}

void fy_node_mapping_perform_sort(struct fy_node *fyn_map,
fy_node_mapping_sort_fn key_cmp, void *arg,
struct fy_node_pair **fynpp, int count)
{
struct fy_node_mapping_sort_ctx ctx;
struct fy_node_cmp_arg def_arg;

if (!key_cmp) {
def_arg.cmp_fn = fy_node_scalar_cmp_default;
def_arg.arg = arg;
Expand Down Expand Up @@ -5784,6 +5792,7 @@ struct fy_node_pair **fy_node_mapping_sort_array(struct fy_node *fyn_map,

memset(fynpp, 0, (count + 1) * sizeof(*fynpp));

fy_node_mapping_fill_array(fyn_map, fynpp, count);
fy_node_mapping_perform_sort(fyn_map, key_cmp, arg, fynpp, count);

if (countp)
Expand All @@ -5792,7 +5801,7 @@ struct fy_node_pair **fy_node_mapping_sort_array(struct fy_node *fyn_map,
return fynpp;
}

void fy_node_mapping_sort_release_array(struct fy_node *fyn_map, struct fy_node_pair **fynpp)
void fy_node_mapping_release_array(struct fy_node *fyn_map, struct fy_node_pair **fynpp)
{
if (!fyn_map || !fynpp)
return;
Expand All @@ -5817,7 +5826,7 @@ int fy_node_mapping_sort(struct fy_node *fyn_map,
fy_node_pair_list_add_tail(&fyn_map->mapping, fynpi);
}

fy_node_mapping_sort_release_array(fyn_map, fynpp);
fy_node_mapping_release_array(fyn_map, fynpp);

return 0;
}
Expand Down Expand Up @@ -6437,6 +6446,8 @@ fy_node_hash_internal(struct fy_node *fyn, fy_hash_update_fn update_fn, void *st
count = fy_node_mapping_item_count(fyn);

fynpp = alloca(sizeof(*fynpp) * (count + 1));

fy_node_mapping_fill_array(fyn, fynpp, count);
fy_node_mapping_perform_sort(fyn, NULL, NULL, fynpp, count);

/* MAPPING */
Expand Down
5 changes: 4 additions & 1 deletion src/lib/fy-doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,14 @@ void fy_node_mapping_perform_sort(struct fy_node *fyn_map,
fy_node_mapping_sort_fn key_cmp, void *arg,
struct fy_node_pair **fynpp, int count);

void fy_node_mapping_fill_array(struct fy_node *fyn_map,
struct fy_node_pair **fynpp, int count);

struct fy_node_pair **fy_node_mapping_sort_array(struct fy_node *fyn_map,
fy_node_mapping_sort_fn key_cmp,
void *arg, int *countp);

void fy_node_mapping_sort_release_array(struct fy_node *fyn_map, struct fy_node_pair **fynpp);
void fy_node_mapping_release_array(struct fy_node *fyn_map, struct fy_node_pair **fynpp);

struct fy_node_walk_ctx {
unsigned int max_depth;
Expand Down
44 changes: 34 additions & 10 deletions src/lib/fy-emit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1631,8 +1631,8 @@ void fy_emit_mapping(struct fy_emitter *emit, struct fy_node *fyn, int flags, in
{
struct fy_node_pair *fynp, *fynpn, **fynpp = NULL;
struct fy_token *fyt_key, *fyt_value;
bool last, simple_key;
int aflags, i;
bool last, simple_key, used_malloc = false;
int aflags, i, count;
struct fy_emit_save_ctx sct, *sc = &sct;

memset(sc, 0, sizeof(*sc));
Expand All @@ -1646,11 +1646,39 @@ void fy_emit_mapping(struct fy_emitter *emit, struct fy_node *fyn, int flags, in

fy_emit_mapping_prolog(emit, sc);

if (!(emit->cfg.flags & FYECF_SORT_KEYS)) {
if (!(emit->cfg.flags & (FYECF_SORT_KEYS | FYECF_STRIP_EMPTY_KV))) {
fynp = fy_node_pair_list_head(&fyn->mapping);
fynpp = NULL;
} else {
fynpp = fy_node_mapping_sort_array(fyn, NULL, NULL, NULL);
count = fy_node_mapping_item_count(fyn);

/* heuristic, avoid allocation for small maps */
if (count > 64) {
fynpp = malloc((count + 1) * sizeof(*fynpp));
fyd_error_check(fyn->fyd, fynpp, err_out,
"malloc() failed");
used_malloc = true;
} else
fynpp = alloca((count + 1) * sizeof(*fynpp));

/* fill (removing empty KVs) */
i = 0;
for (fynp = fy_node_pair_list_head(&fyn->mapping); fynp;
fynp = fy_node_pair_next(&fyn->mapping, fynp)) {

/* strip key/value pair from the output if it's empty */
if ((emit->cfg.flags & FYECF_STRIP_EMPTY_KV) && fy_node_is_empty(fynp->value))
continue;

fynpp[i++] = fynp;
}
count = i;
fynpp[count] = NULL;

/* sort the keys */
if (emit->cfg.flags & FYECF_SORT_KEYS)
fy_node_mapping_perform_sort(fyn, NULL, NULL, fynpp, count);

i = 0;
fynp = fynpp[i];
}
Expand All @@ -1671,10 +1699,6 @@ void fy_emit_mapping(struct fy_emitter *emit, struct fy_node *fyn, int flags, in
(fynp->key && fynp->key->type == FYNT_SCALAR),
err_out, "Non scalar keys are not allowed in JSON emit mode");

/* strip key/value pair from the output if it's empty */
if ((emit->cfg.flags & FYECF_STRIP_EMPTY_KV) && fy_node_is_empty(fynp->value))
continue;

simple_key = false;
if (fynp->key) {
switch (fynp->key->type) {
Expand Down Expand Up @@ -1703,8 +1727,8 @@ void fy_emit_mapping(struct fy_emitter *emit, struct fy_node *fyn, int flags, in
fy_emit_mapping_value_epilog(emit, sc, last, fyt_value);
}

if (fynpp)
fy_node_mapping_sort_release_array(fyn, fynpp);
if (fynpp && used_malloc)
free(fynpp);

fy_emit_mapping_epilog(emit, sc);

Expand Down

0 comments on commit f62fffd

Please sign in to comment.