summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2026-08-05 21:07:07 -0500
committerJohn Estabrook <jestabro@vyos.io>2026-08-05 21:07:43 -0500
commitbcc02a1ea3282438de6c7077b752cf0961201271 (patch)
treea019b4ece4376986fb1fd7bb2c744b2d3d6d7efd /src
parent65eeb4b40bb6366c6b99900f68d60cedfc512449 (diff)
downloadvyos1x-config-bcc02a1ea3282438de6c7077b752cf0961201271.tar.gz
vyos1x-config-bcc02a1ea3282438de6c7077b752cf0961201271.zip
T9169: move util subtree_from_partial to derived
The module derived should be the location for constructions involving both config_tree and reference_tree.
Diffstat (limited to 'src')
-rw-r--r--src/derived.ml66
-rw-r--r--src/derived.mli4
2 files changed, 70 insertions, 0 deletions
diff --git a/src/derived.ml b/src/derived.ml
new file mode 100644
index 0000000..b82226c
--- /dev/null
+++ b/src/derived.ml
@@ -0,0 +1,66 @@
+(* Convert from a path that may or may not include intervening tag_values,
+ returning a subtree of matches *)
+exception Malformed_path of string
+
+let subtree_from_partial reftree ctree result path =
+ if Util.is_empty path then result
+ else
+ let check_reftree p =
+ match p with
+ | [] -> false
+ | _ ->
+ let rpath =
+ Reference_tree.refpath_from_partial reftree p
+ in
+ match rpath with
+ | [] -> false
+ | _ -> true
+ in
+ let check_ctree p =
+ match p with
+ | [] -> false
+ | _ -> (Vytree.exists[@alert "-exn"]) ctree p
+ in
+ let clone_node ?(recurse=false) tree p =
+ if (Vytree.exists[@alert "-exn"]) tree p then
+ tree
+ else
+ if not ((Vytree.exists[@alert "-exn"]) ctree p) then
+ tree
+ else
+ (Config_tree.clone[@alert "-exn"]) ~recurse:recurse ctree tree p
+ in
+ let clone_children tree p =
+ let children = Vytree.list_children ((Vytree.get[@alert "-exn"]) ctree p) in
+ let paths = List.map (fun n -> p @ [n]) children in
+ List.fold_left (clone_node ~recurse:true) tree paths
+ in
+ let rec aux acc path_done p =
+ if not (check_reftree (path_done @ p)) then
+ raise (Malformed_path (Util.string_of_list (path_done @ p)))
+ else
+ match path_done, p with
+ | [], h :: tl ->
+ if check_reftree [h] then aux (clone_node acc [h]) [h] tl
+ else
+ raise (Malformed_path (Util.string_of_list p))
+ | _, h :: tl ->
+ let p' = path_done @ [h] in
+ if check_ctree p' then aux (clone_node acc p') p' tl
+ else
+ if (Config_tree.is_tag[@alert "-exn"]) ctree path_done then
+ let children =
+ Vytree.list_children ((Vytree.get[@alert "-exn"]) ctree path_done)
+ in
+ let func accum child =
+ let path = path_done @ [child] @ [h] in
+ if check_ctree path then
+ aux (clone_node accum path) path tl
+ else accum
+ in
+ List.fold_left func acc children
+ else
+ (* [h] is a tag_value not present in the config tree *)
+ raise (Malformed_path (Util.string_of_list p'))
+ | _, [] -> clone_children acc path_done
+ in aux result [] path
diff --git a/src/derived.mli b/src/derived.mli
new file mode 100644
index 0000000..39f255a
--- /dev/null
+++ b/src/derived.mli
@@ -0,0 +1,4 @@
+exception Malformed_path of string
+
+val subtree_from_partial : Reference_tree.t -> Config_tree.t -> Config_tree.t -> string list -> Config_tree.t
+[@@alert exn "Derived.Malformed_path"]