mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
No functional change, just an optimization. Signed-off-by: Edwin Török <edvin.torok@citrix.com> Acked-by: Christian Lindig <christian.lindig@citrix.com>
178 lines
4.3 KiB
OCaml
178 lines
4.3 KiB
OCaml
(*
|
|
* Copyright (C) 2008-2009 Citrix Ltd.
|
|
* Author Thomas Gazagnaire <thomas.gazagnaire@eu.citrix.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; version 2.1 only. with the special
|
|
* exception on linking described in file LICENSE.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*)
|
|
|
|
open Stdext
|
|
|
|
module StringMap = Map.Make(String)
|
|
|
|
module Node =
|
|
struct
|
|
type 'a t = {
|
|
key: string;
|
|
value: 'a option;
|
|
children: 'a t StringMap.t;
|
|
}
|
|
|
|
let _create key value = {
|
|
key = key;
|
|
value = Some value;
|
|
children = StringMap.empty;
|
|
}
|
|
|
|
let empty key = {
|
|
key = key;
|
|
value = None;
|
|
children = StringMap.empty;
|
|
}
|
|
|
|
let _get_key node = node.key
|
|
let get_value node =
|
|
match node.value with
|
|
| None -> raise Not_found
|
|
| Some value -> value
|
|
|
|
let _get_children node = node.children
|
|
|
|
let set_value node value =
|
|
{ node with value = Some value }
|
|
let set_children node children =
|
|
{ node with children = children }
|
|
|
|
let _add_child node child =
|
|
{ node with children = StringMap.add child.key child node.children }
|
|
end
|
|
|
|
type 'a t = 'a Node.t StringMap.t
|
|
|
|
let mem_node nodes key =
|
|
StringMap.mem key nodes
|
|
|
|
let find_node nodes key =
|
|
StringMap.find key nodes
|
|
|
|
let replace_node nodes key node =
|
|
StringMap.update key (function None -> None | Some _ -> Some node) nodes
|
|
|
|
let remove_node nodes key =
|
|
StringMap.update key (function None -> raise Not_found | Some _ -> None) nodes
|
|
|
|
let create () = StringMap.empty
|
|
|
|
let rec iter f tree =
|
|
let aux key node =
|
|
f key node.Node.value;
|
|
iter f node.Node.children
|
|
in
|
|
StringMap.iter aux tree
|
|
|
|
let rec map f tree =
|
|
let aux node =
|
|
let value =
|
|
match node.Node.value with
|
|
| None -> None
|
|
| Some value -> f value
|
|
in
|
|
{ node with Node.value = value; Node.children = map f node.Node.children }
|
|
in
|
|
tree |> StringMap.map aux
|
|
|> StringMap.filter (fun _ n -> n.Node.value <> None || not (StringMap.is_empty n.Node.children))
|
|
|
|
let rec fold f tree acc =
|
|
let aux key node accu =
|
|
fold f node.Node.children (f key node.Node.value accu)
|
|
in
|
|
StringMap.fold aux tree acc
|
|
|
|
(* return a sub-trie *)
|
|
let rec sub_node tree = function
|
|
| [] -> raise Not_found
|
|
| h::t ->
|
|
if mem_node tree h
|
|
then begin
|
|
let node = find_node tree h in
|
|
if t = []
|
|
then node
|
|
else sub_node node.Node.children t
|
|
end else
|
|
raise Not_found
|
|
|
|
let sub tree path =
|
|
try (sub_node tree path).Node.children
|
|
with Not_found -> StringMap.empty
|
|
|
|
let find tree path =
|
|
Node.get_value (sub_node tree path)
|
|
|
|
(* return false if the node doesn't exists or if it is not associated to any value *)
|
|
let rec mem tree = function
|
|
| [] -> false
|
|
| h::t ->
|
|
mem_node tree h
|
|
&& (let node = find_node tree h in
|
|
if t = []
|
|
then node.Node.value <> None
|
|
else mem node.Node.children t)
|
|
|
|
(* Iterate over the longest valid prefix *)
|
|
let rec iter_path f tree = function
|
|
| [] -> ()
|
|
| h::l ->
|
|
if mem_node tree h
|
|
then begin
|
|
let node = find_node tree h in
|
|
f node.Node.key node.Node.value;
|
|
iter_path f node.Node.children l
|
|
end
|
|
|
|
let rec set_node node path value =
|
|
if path = []
|
|
then Node.set_value node value
|
|
else begin
|
|
let children = set node.Node.children path value in
|
|
Node.set_children node children
|
|
end
|
|
|
|
and set tree path value =
|
|
match path with
|
|
| [] -> raise Not_found
|
|
| h::t ->
|
|
if mem_node tree h
|
|
then begin
|
|
let node = find_node tree h in
|
|
replace_node tree h (set_node node t value)
|
|
end else begin
|
|
let node = Node.empty h in
|
|
StringMap.add node.Node.key (set_node node t value) tree
|
|
end
|
|
|
|
let rec unset tree = function
|
|
| [] -> tree
|
|
| h::t ->
|
|
if mem_node tree h
|
|
then begin
|
|
let node = find_node tree h in
|
|
let children = unset node.Node.children t in
|
|
let new_node =
|
|
if t = []
|
|
then Node.set_children (Node.empty h) children
|
|
else Node.set_children node children
|
|
in
|
|
if StringMap.is_empty children && new_node.Node.value = None
|
|
then remove_node tree h
|
|
else replace_node tree h new_node
|
|
end else
|
|
raise Not_found
|
|
|