--- /dev/null
+(* virt-similarity
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Printf
+
+type t =
+ | Leaf of int (* A single disk image (index of). *)
+ | Node of t list (* An interior node in the tree. *)
+
+let rec images_in_subtree = function
+ | Leaf i -> [i]
+ | Node xs -> List.concat (List.map images_in_subtree xs)
+
+let max_list = List.fold_left max min_int
+
+let mapi f xs =
+ let rec loop i = function
+ | [] -> []
+ | x :: xs -> let r = f i x in r :: loop (i+1) xs
+ in
+ loop 0 xs
+
+let format_cladogram ?format_leaf t =
+ let format_leaf = match format_leaf with
+ | None -> string_of_int
+ | Some f -> f
+ in
+ let rec format = function
+ | Leaf i ->
+ let s = "--- " ^ format_leaf i in
+ [s; ""], String.length s
+ | Node xs ->
+ let xs = List.map format xs in
+ let n = List.length xs in
+ let w = 7 + max_list (List.map snd xs) in
+ let xs = mapi (
+ fun row (ss, _) ->
+ let s, ss = match ss with
+ | s :: ss -> s, ss
+ | [] -> assert false in
+ if row = 0 then (
+ ("---+---" ^ s) ::
+ List.map (fun s -> " | " ^ s) ss
+ ) else if row < n-1 then (
+ (" +---" ^ s) ::
+ List.map (fun s -> " | " ^ s) ss
+ ) else (
+ (" +---" ^ s) ::
+ List.map (fun s -> " " ^ s) ss
+ )
+ ) xs in
+ List.concat xs, w
+ in
+ let strs, _ = format t in
+ strs