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 | 
