diff options
author | Daniil Baturin <daniil@baturin.org> | 2015-04-23 05:29:31 +0600 |
---|---|---|
committer | Daniil Baturin <daniil@baturin.org> | 2015-04-23 05:29:31 +0600 |
commit | ccab6d041c7ca307486bb344dd2a4e669e9bb9fe (patch) | |
tree | 2c2409dec310ef02af2847badc891d1acc1a30bb | |
parent | 3b2b0d009ba7962da8b12c62f119fa4b1178e858 (diff) | |
download | vyconf-ccab6d041c7ca307486bb344dd2a4e669e9bb9fe.tar.gz vyconf-ccab6d041c7ca307486bb344dd2a4e669e9bb9fe.zip |
Make insert require all but the last elements in the path to exist in the tree.
Making it linear time at cost of knowing the data for all path elements
was probably a bad idea.
-rw-r--r-- | src/vytree.ml | 26 | ||||
-rw-r--r-- | src/vytree.mli | 2 | ||||
-rw-r--r-- | test/vyconf_tree_test.ml | 45 |
3 files changed, 35 insertions, 38 deletions
diff --git a/src/vytree.ml b/src/vytree.ml index 728e26d..10ccf0e 100644 --- a/src/vytree.ml +++ b/src/vytree.ml @@ -60,28 +60,22 @@ 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_list = - match (path, data_list) with - | ([], _) -> raise Empty_path - | (_ :: _, []) -> raise (Insert_error "No data found") - | ([name], [datum]) -> - begin - (* Check for duplicate item *) - let last_child = find node name in - match last_child with - | None -> insert_immediate node name datum - | (Some _) -> raise Duplicate_child - end - | (name :: names, datum :: data) -> +let rec insert 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 + | (Some _) -> raise Duplicate_child) + | name :: names -> let next_child = find node name in match next_child with | Some next_child' -> let new_node = insert next_child' names data in replace node new_node | None -> - let next_child' = make datum name in - let new_node = insert next_child' names data in - adopt node new_node + raise (Insert_error "Path does not exist") let delete node path = do_with_child delete_immediate node path diff --git a/src/vytree.mli b/src/vytree.mli index cebbcde..8224fdd 100644 --- a/src/vytree.mli +++ b/src/vytree.mli @@ -16,7 +16,7 @@ val name_of_node : 'a t -> string val data_of_node : 'a t -> 'a val children_of_node : 'a t -> 'a t list -val insert : 'a t -> string list -> 'a list -> 'a t +val insert : 'a t -> string list -> 'a -> 'a t val delete : 'a t -> string list -> 'a t diff --git a/test/vyconf_tree_test.ml b/test/vyconf_tree_test.ml index 26d350b..edafb78 100644 --- a/test/vyconf_tree_test.ml +++ b/test/vyconf_tree_test.ml @@ -17,7 +17,7 @@ let test_make_node test_ctxt = children list *) let test_insert_immediate_child test_ctxt = let node = make () "root" in - let node' = insert node ["foo"] [()] in + let node' = insert node ["foo"] () in assert_equal (children_of_node node') [make () "foo"] @@ -25,8 +25,8 @@ let test_insert_immediate_child test_ctxt = end of the children list *) let test_insert_multiple_children test_ctxt = let node = make () "root" in - let node' = insert node ["foo"] [()] in - let node'' = insert node' ["bar"] [()] in + let node' = insert node ["foo"] () in + let node'' = insert node' ["bar"] () in assert_equal (children_of_node node'') [make () "bar"; make () "foo"] @@ -34,39 +34,41 @@ let test_insert_multiple_children test_ctxt = two levels deep *) let test_insert_multi_level test_ctxt = let node = make () "root" in - let node' = insert node ["foo"; "bar"] [(); ()] in + let node = insert node ["foo"] () in + let node = insert node ["foo"; "bar"] () in let bar = make () "bar" in let foo = make_full () "foo" [bar] in let root = make_full () "root" [foo] in - assert_equal root node' + assert_equal root node (* Inserting duplicate child fails *) let test_insert_duplicate_child test_ctxt = let node = make () "root" in - let node' = insert node ["foo"] [()] in - assert_raises Duplicate_child (fun () -> insert node' ["foo"] [()]) + let node = insert node ["foo"] () in + assert_raises Duplicate_child (fun () -> insert node ["foo"] ()) (* list_children correctly returns a list of children names *) let test_list_children test_ctxt = let node = make () "root" in - let node' = insert node ["foo"] [()] in - let node'' = insert node' ["bar"] [()] in - assert_equal (list_children node'') ["bar"; "foo"] + let node = insert node ["foo"] () in + let node = insert node ["bar"] () in + assert_equal (list_children node) ["bar"; "foo"] (* Deleting a child, well, deletes it *) let test_delete_immediate_child test_ctxt = let node = make () "root" in - let node' = insert node ["foo"] [()] in - let node'' = delete node' ["foo"] in - assert_equal node node'' + let node' = insert node ["foo"] () in + let node' = delete node' ["foo"] in + assert_equal node node' (* Deleting a child at multi-level path works *) let test_delete_multi_level test_ctxt = let node = make () "root" in - let node' = insert node ["foo"; "bar"] [(); ()] in - let foo_node = insert node ["foo"] [()] in - let node'' = delete node' ["foo"; "bar"] in - assert_equal node'' foo_node + let node' = insert node ["foo"] () in + let node' = insert node' ["foo"; "bar"] () in + let foo_node = insert node ["foo"] () in + let node' = delete node' ["foo"; "bar"] in + assert_equal node' foo_node (* Attempt to delete a node at non-existent path raises an exception *) let test_delete_nonexistent test_ctxt = @@ -76,14 +78,15 @@ let test_delete_nonexistent test_ctxt = (* get_child works with immediate children *) let test_get_immediate_child test_ctxt = let node = make () "root" in - let node' = insert node ["foo"] [()] in + let node' = insert node ["foo"] () in assert_equal (name_of_node (get node' ["foo"])) "foo" (* get_child works with multi-level paths *) let test_get_child_multilevel test_ctxt = let node = make () "root" in - let node' = insert node ["foo"; "bar"] [(); ()] in - assert_equal (name_of_node (get node' ["foo"; "bar"])) "bar" + let node = insert node ["foo"] () in + let node = insert node ["foo"; "bar"] () in + assert_equal (name_of_node (get node ["foo"; "bar"])) "bar" (* get_child raises Nonexistent_path for non-existent paths *) let test_get_child_nonexistent test_ctxt = @@ -93,7 +96,7 @@ let test_get_child_nonexistent test_ctxt = (* update works *) let test_update test_ctxt = let node = make 0 "root" in - let node = insert node ["foo"] [1] in + let node = insert node ["foo"] 1 in assert_equal (data_of_node (get (update node ["foo"] 9) ["foo"])) 9 let suite = |