Skip to content

Commit

Permalink
Add apteryx_uniqify_tree
Browse files Browse the repository at this point in the history
Add a function to remove duplicate values from a tree - as a side effect
this will sort each level of the tree in alphabetic order.
  • Loading branch information
blairsteven authored and carlgsmith committed Oct 23, 2024
1 parent 4cd230b commit f7ca50c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
66 changes: 66 additions & 0 deletions apteryx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,72 @@ apteryx_sort_children (GNode *parent, int (*cmp) (const char *a, const char *b))
parent->children = merge_sort (parent->children, cmp);
}

void apteryx_uniqify_tree (GNode *root, GDestroyNotify destroyer)
{
if (!root)
{
return;
}

if (APTERYX_HAS_VALUE (root))
{
/* Throw away all but the first value (most recently added) */
for (GNode *value = root->children->next; value; value = root->children->next)
{
/* Free memory and node */
if (destroyer)
{
destroyer (value->data);
}
g_node_destroy (value);
}
return;
}

/* First sort children so we know duplicates are adjacent. */
apteryx_sort_children (root, g_strcmp0);

GNode *next;
for (GNode *iter = root->children; iter; iter = next)
{
/* We may remove and destroy iter before the end of the loop,
* so save the next pointer first.
*/
next = iter->next;

/* If this is the last node, or the next node has different name we
* don't need to do any more work on this node.
*/
if (!next || g_strcmp0 (APTERYX_NAME (iter), APTERYX_NAME (next)))
{
continue;
}

/* Found a collision, merge the lower trees and remove the duplicate */
/* Steal all the children from iter and give them to next node in
* the list.
*/
for (GNode *merged = iter->children; merged; merged = iter->children)
{
g_node_unlink (merged);
g_node_append (next, merged);
}

/* Free memory and node */
if (destroyer)
{
destroyer (iter->data);
}
g_node_destroy (iter);
}

/* Decend to the next level and uniq them too. */
for (GNode *iter = root->children; iter; iter = iter->next)
{
apteryx_uniqify_tree (iter, destroyer);
}
}

static char *
_node_to_path (GNode *node, char **buf)
{
Expand Down
7 changes: 7 additions & 0 deletions apteryx.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,13 @@ bool apteryx_query_to_node (GNode *parent, const char *query);
*/
GList *apteryx_find_tree (GNode *root);

/**
* Sort and merge duplicate nodes in a tree
* @param root pointer to the N-ary tree of nodes to sort
* @param destroyer function to call to free data from tree
*/
void apteryx_uniqify_tree (GNode *root, GDestroyNotify destroyer);

/**
* Find a list of paths that match this wildcard path + value
* @param path Path to match (with one or more * wildcard)
Expand Down
3 changes: 3 additions & 0 deletions apteryxd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,9 @@ handle_set (rpc_message msg, bool ack)
ts = rpc_msg_decode_uint64 (msg);
root = rpc_msg_decode_tree (msg);

/* Remove any duplicate nodes */
apteryx_uniqify_tree (root, g_free);

if (!root)
{
ERROR ("SET: Failed to decode message\n");
Expand Down

0 comments on commit f7ca50c

Please sign in to comment.