summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2015-06-03 13:51:25 +0600
committerDaniil Baturin <daniil@baturin.org>2015-06-03 13:51:25 +0600
commit74132f616269e0de282354dec602d494455da4dc (patch)
treeb7584be9eaef6b5c275ac81dafe3ac7e079a577a
parentcfb1d2c4385554325e9e23ab43745d5d8fc4e7e9 (diff)
downloadvyconf-74132f616269e0de282354dec602d494455da4dc.tar.gz
vyconf-74132f616269e0de282354dec602d494455da4dc.zip
Make tree insert position-aware.
Make insertion at the beginning default behaviour. Implement insertion at the end.
-rw-r--r--src/vytree.ml16
-rw-r--r--src/vytree.mli4
-rw-r--r--test/vytree_test.ml13
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;