X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=csv.ml;h=6ca424b09ee1faa34556da43a40389dbc156712f;hb=680fc80e414200998978f834a83bb8200b2a6609;hp=2a22bf983eef6e3e372b825de554e0e08eee65fe;hpb=ae6f56ba8e80a1c05aa076404dd14145b306780a;p=ocaml-csv.git diff --git a/csv.ml b/csv.ml index 2a22bf9..6ca424b 100644 --- a/csv.ml +++ b/csv.ml @@ -1,6 +1,6 @@ (* csv.ml - comma separated values parser * - * $Id: csv.ml,v 1.8 2006-02-15 13:25:58 rich Exp $ + * $Id: csv.ml,v 1.11 2006-07-19 09:41:58 rich Exp $ *) (* The format of CSV files: @@ -40,6 +40,8 @@ * subset of it into a matrix. *) +open Printf + type t = string list list exception Bad_CSV_file of string @@ -265,6 +267,38 @@ let sub r c rows cols csv = let csv = set_columns cols csv in csv +(* Compare two rows for semantic equality - ignoring any blank cells + * at the end of each row. + *) +let rec compare_row (row1 : string list) row2 = + match row1, row2 with + | [], [] -> 0 + | x :: xs, y :: ys -> + let c = compare x y in + if c <> 0 then c else compare_row xs ys + | "" :: xs , [] -> + compare_row xs [] + | x :: xs, [] -> + 1 + | [], "" :: ys -> + compare_row [] ys + | [], y :: ys -> + -1 + +(* Semantic equality for CSV files. *) +let rec compare (csv1 : t) csv2 = + match csv1, csv2 with + | [], [] -> 0 + | x :: xs, y :: ys -> + let c = compare_row x y in + if c <> 0 then c else compare xs ys + | x :: xs, [] -> + let c = compare_row x [] in + if c <> 0 then c else compare xs [] + | [], y :: ys -> + let c = compare_row [] y in + if c <> 0 then c else compare [] ys + let to_array csv = Array.of_list (List.map Array.of_list csv) @@ -337,18 +371,18 @@ let save_out_readable chan csv = match csv with | [] -> [] - | r :: _ -> - let n = List.length r in - let lengths = List.map (List.map String.length) csv in + | row1 :: rest -> + let lengths_row1 = List.map String.length row1 in + let lengths_rest = List.map (List.map String.length) rest in let max2rows r1 r2 = - let rp = List.combine r1 r2 in + let rp = + try List.combine r1 r2 + with + Invalid_argument "List.combine" -> + failwith (sprintf "Csv.save_out_readable: internal error: length r1 = %d, length r2 = %d" (List.length r1) (List.length r2)) in List.map (fun ((a : int), (b : int)) -> max a b) rp in - let rec repeat x = function - | 0 -> [] - | i -> x :: repeat x (i-1) - in - List.fold_left max2rows (repeat 0 n) lengths in + List.fold_left max2rows lengths_row1 lengths_rest in (* Print out each cell at the correct width. *) let rec repeat f = function @@ -361,9 +395,17 @@ let save_out_readable chan csv = output_string chan cell; output_char chan '\n' | row -> (* Other. *) - let row = List.combine widths row in + (* Pair up each cell with its max width. *) + let row = + let rec loop = function + | ([], _) -> [] + | (_, []) -> failwith "Csv.save_out_readable: internal error" + | (cell :: cells, width :: widths) -> + (cell, width) :: loop (cells, widths) + in + loop (row, widths) in List.iter ( - fun (width, cell) -> + fun (cell, width) -> output_string chan cell; let n = String.length cell in repeat (fun () -> output_char chan ' ') (width - n + 1)