-let fold f init = Hashtbl.fold (fun k v acc -> f acc k v) registry init
-let iter f = fold (fun _ k v -> f k v) ()
-let to_list () = fold (fun acc k v -> (k, v) :: acc) []
+let fold ?prefix f init =
+ match prefix with
+ | None -> Hashtbl.fold (fun k v acc -> f acc k v) registry init
+ | Some s ->
+ let key_matches = starts_with (s ^ ".") in
+ let rec fold_filter acc = function
+ | [] -> acc
+ | (k,v) :: tl when key_matches k -> fold_filter (f acc k v) tl
+ | _ :: tl -> fold_filter acc tl
+ in
+ fold_filter init (hashtbl_pairs registry)
+
+let iter ?prefix f = fold ?prefix (fun _ k v -> f k v) ()
+let to_list ?prefix () = fold ?prefix (fun acc k v -> (k, v) :: acc) []
+
+let ls prefix =
+ let prefix = prefix ^ "." in
+ let prefix_len = String.length prefix in
+ let key_matches = starts_with prefix in
+ let matching_keys = (* collect matching keys' _postfixes_ *)
+ fold
+ (fun acc key _ ->
+ if key_matches key then
+ String.sub key prefix_len (String.length key - prefix_len) :: acc
+ else
+ acc)
+ []
+ in
+ let (sections, keys) =
+ List.fold_left
+ (fun (sections, keys) postfix ->
+ match Str.split dot_rex postfix with
+ | [key] -> (sections, key :: keys)
+ | hd_key :: _ -> (* length > 1 => nested section found *)
+ (hd_key :: sections, keys)
+ | _ -> assert false)
+ ([], []) matching_keys
+ in
+ (list_uniq (List.sort Pervasives.compare sections), keys)