diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vytree.ml | 36 | ||||
-rw-r--r-- | src/vytree.mli | 2 |
2 files changed, 38 insertions, 0 deletions
diff --git a/src/vytree.ml b/src/vytree.ml index 0e379ee..b27aea6 100644 --- a/src/vytree.ml +++ b/src/vytree.ml @@ -81,6 +81,42 @@ let rec insert ?(position=Default) node path data = | None -> raise (Insert_error "Path does not exist") +(** Given a node N check if it has children with duplicate names, + and merge subsequent children's children into the first child by + that name. + + While all insert functions maintain the "every child has unique name" + invariant, for nodes constructed manually with make/make_full and adopt + it may not hold, and constructing nodes this way is a sensible approach + for config parsing. Depending on the config format, duplicate node names + may be normal and even expected, such as "ethernet eth0" and "ethernet eth1" + in the "curly" format. + *) +let merge_children node = + (* Given a node N and a list of nodes NS, find all nodes in NS that + have the same name as N and merge their children into N *) + let rec merge_into n ns = + match ns with + | [] -> n + | n' :: ns' -> + if n.name = n'.name then + let children = List.append n.children n'.children in + let n = {n with children=children} in + merge_into n ns' + else merge_into n ns' + in + (* Given a list of nodes, for every node, find subsequent children with + the same name and merge them into the first node, then delete remaining + nodes from the list *) + let rec aux ns = + match ns with + | [] -> [] + | n :: ns -> + let n = merge_into n ns in + let ns = List.filter (fun x -> x.name <> n.name) ns in + n :: (aux ns) + in {node with children=(aux node.children)} + (* When inserting at a path that, entirely or partially, does not exist yet, create missing nodes on the way with default data *) let rec insert_multi_level default_data node path_done path_remaining data = diff --git a/src/vytree.mli b/src/vytree.mli index 6de65c5..d00d3ff 100644 --- a/src/vytree.mli +++ b/src/vytree.mli @@ -23,6 +23,8 @@ val insert : ?position:position -> 'a t -> string list -> 'a -> 'a t val insert_multi_level : 'a -> 'a t -> string list -> string list -> 'a -> 'a t +val merge_children : 'a t -> 'a t + val delete : 'a t -> string list -> 'a t val update : 'a t -> string list -> 'a -> 'a t |