(* 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.9 2006-02-23 15:24:25 rich Exp $
*)
(* The format of CSV files:
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)
(** csv.mli - comma separated values parser
*
- * $Id: csv.mli,v 1.7 2005-11-25 14:08:46 rich Exp $
+ * $Id: csv.mli,v 1.8 2006-02-23 15:24:25 rich Exp $
*)
type t = string list list
* The returned CSV will be square.
*)
+val compare : t -> t -> int
+(** Compare two CSV files for equality, ignoring blank cells at the end
+ * of a row, and empty rows appended to one or the other. This is
+ * "semantic" equality - roughly speaking, the two CSV files would
+ * look the same if opened in a spreadsheet program.
+ *)
+
val to_array : t -> string array array
val of_array : string array array -> t
(** Convenience functions to convert to and from a matrix representation.
-(* $Id: test.ml,v 1.1 2003-12-17 16:05:08 rich Exp $ *)
+(* $Id: test.ml,v 1.2 2006-02-23 15:24:25 rich Exp $ *)
open Printf
open Csv
print expected;
failwith "failed"
)
+ else ()
-let testcsv1 =
+let () =
do_testcsv
"testcsv1.csv"
[ [ "This is a test\nwith commas,,,,,\n\nand carriage returns." ] ]
-let testcsv2 =
+let () =
do_testcsv
"testcsv2.csv"
[ [ "Normal field"; "Quoted field"; "Quoted field with \"\" quotes" ] ]
-let testcsv3 =
+let () =
do_testcsv
"testcsv3.csv"
[ [ "" ];
[ ""; ""; "" ];
[ ""; ""; ""; "" ];
[ ""; ""; ""; ""; "" ] ]
-let testcsv4 =
+let () =
do_testcsv
"testcsv4.csv"
[]
-let testcsv5 =
+let () =
do_testcsv
"testcsv5.csv"
[ [ "This is a test\nwith commas,,,,,\n\nand carriage returns.";
"a second field"; "a third field" ];
[ "a fourth field on a new line" ] ]
-let testcsv6 =
+let () =
do_testcsv
"testcsv6.csv"
[ [ "This is a test\nwith commas,,,,,\n\nand carriage returns\nand \000";
"a second field"; "a third field" ];
[ "a fourth field on a new line" ] ]
+let () =
+ let csv1 = [ [ "a"; "b"; "c"; ""; "" ];
+ [ "f"; "g"; "h"; "i"; "" ];
+ [ "" ];
+ [ ] ] in
+ let csv2 = trim ~top:false ~left:false ~right:true ~bottom:true csv1 in
+ assert (compare csv1 csv2 = 0)
+let () =
+ let csv1 = [ [ "a"; "b"; "c"; ""; "" ];
+ [ "f"; "g"; "h"; "i"; "" ];
+ [ "" ];
+ [ ] ] in
+ let csv2 = [ [ "a"; "b"; "c"; "d"; "" ];
+ [ "f"; "g"; "h"; "i"; "" ];
+ [ "" ];
+ [ ] ] in
+ assert (compare csv1 csv2 < 0)
+
+
;;
print_endline "All tests succeeded."