diff options
-rw-r--r-- | src/vytree.ml | 16 | ||||
-rw-r--r-- | src/vytree.mli | 4 | ||||
-rw-r--r-- | test/vytree_test.ml | 13 |
3 files changed, 23 insertions, 10 deletions
diff --git a/src/vytree.ml b/src/vytree.ml index ed5efd2..93d3d71 100644 --- a/src/vytree.ml +++ b/src/vytree.ml @@ -4,7 +4,7 @@ type 'a t = { children: 'a t list } -type position = Before of string | After of string | Default +type position = Before of string | After of string | End | Default type node_type = Leaf | Tag | Other @@ -21,10 +21,14 @@ let name_of_node node = node.name let data_of_node node = node.data let children_of_node node = node.children -let insert_immediate node name data = +let insert_immediate ?(position=Default) node name data = let new_node = make data name in - let children' = new_node :: node.children in - { node with children = children' } + let children' = + match position with + | Default -> new_node :: node.children + | End -> node.children @ [new_node] + | _ -> assert false + in { node with children = children' } let delete_immediate node name = let children' = Vylist.remove (fun x -> x.name = name) node.children in @@ -60,13 +64,13 @@ let rec do_with_child fn node path = let new_node = do_with_child fn next_child names in replace node new_node -let rec insert node path data = +let rec insert ?(position=Default) node path data = match path with | [] -> raise Empty_path | [name] -> (let last_child = find node name in match last_child with - | None -> insert_immediate node name data + | None -> insert_immediate ~position:position node name data | (Some _) -> raise Duplicate_child) | name :: names -> let next_child = find node name in diff --git a/src/vytree.mli b/src/vytree.mli index 4b52727..e912922 100644 --- a/src/vytree.mli +++ b/src/vytree.mli @@ -5,7 +5,7 @@ exception Duplicate_child exception Nonexistent_path exception Insert_error of string -type position = Before of string | After of string | Default +type position = Before of string | After of string | End | Default type node_type = Leaf | Tag | Other @@ -19,7 +19,7 @@ val children_of_node : 'a t -> 'a t list val find : 'a t -> string -> 'a t option val find_or_fail : 'a t -> string -> 'a t -val insert : 'a t -> string list -> 'a -> 'a t +val insert : ?position:position -> 'a t -> string list -> 'a -> 'a t val delete : 'a t -> string list -> 'a t diff --git a/test/vytree_test.ml b/test/vytree_test.ml index 24a6d1e..86a6269 100644 --- a/test/vytree_test.ml +++ b/test/vytree_test.ml @@ -21,8 +21,8 @@ let test_insert_immediate_child test_ctxt = assert_equal (children_of_node node') [make () "foo"] -(* Inserting one child after another adds it to the - end of the children list *) +(* Inserting one child after another works. + The default behaviour is to insert new items at the beginning. *) let test_insert_multiple_children test_ctxt = let node = make () "root" in let node' = insert node ["foo"] () in @@ -47,6 +47,14 @@ let test_insert_duplicate_child test_ctxt = let node = insert node ["foo"] () in assert_raises Duplicate_child (fun () -> insert node ["foo"] ()) +(* Inserting a child at the end works *) +let test_insert_multiple_children_end test_ctxt = + let node = make () "root" in + let node = insert node ["foo"] () in + let node = insert ~position:End node ["bar"] () in + assert_equal (children_of_node node) + [make () "foo"; make () "bar"] + (* list_children correctly returns a list of children names *) let test_list_children test_ctxt = let node = make () "root" in @@ -126,6 +134,7 @@ let suite = "test_insert_multiple_children" >:: test_insert_multiple_children; "test_insert_multi_level" >:: test_insert_multi_level; "test_insert_duplicate_child" >:: test_insert_duplicate_child; + "test_insert_multiple_children_end" >:: test_insert_multiple_children_end; "test_list_children" >:: test_list_children; "test_delete_immediate_child" >:: test_delete_immediate_child; "test_delete_multi_level" >:: test_delete_multi_level; |