module Person = struct type name_t = string type address_t = string type t = { name: name_t; addresses: address_t list } let empty = { name = ""; addresses = [] } let compare = Stdlib.compare let name_to_string p = p.name let to_string p = List.fold_left (fun a e -> Printf.sprintf "%s <%s>" a e) p.name p.addresses let of_string s = match String.trim s with "" -> empty | s -> match Str.(split (regexp " *< *") s) with | [] -> empty | [n] -> let name = String.trim n in { empty with name } | n::adds -> let name = String.trim n in let addresses = List.map (fun f -> String.(sub f 0 (length f -1))) adds in { name; addresses } end include Person module Set = struct include Set.Make(Person) let to_string ?(names_only=false) ?(pre="") ?(sep=", ") s = let str = if names_only then Person.name_to_string else Person.to_string in let j x a = match a, x with "",_ -> str x | _,x when x = Person.empty -> a | _ -> a^sep^str x in fold j s pre let of_string s = of_list (List.map Person.of_string (String_set.list_of_csv s)) let of_stringset s = String_set.fold (fun e a -> union (of_string e) a) s empty let of_query q = of_stringset (fst q), of_stringset (snd q) let predicate (inc, exl) set = not (disjoint inc set) && disjoint exl set end