git: 7af6dde54995 - main - textproc/ocaml-csv: the port had been improved (+)

Alexey Dokuchaev danfe at FreeBSD.org
Fri Sep 10 05:00:20 UTC 2021


The branch main has been updated by danfe:

URL: https://cgit.FreeBSD.org/ports/commit/?id=7af6dde54995fa1784440b52be51499b7dff070b

commit 7af6dde54995fa1784440b52be51499b7dff070b
Author:     Alexey Dokuchaev <danfe at FreeBSD.org>
AuthorDate: 2021-09-10 04:58:16 +0000
Commit:     Alexey Dokuchaev <danfe at FreeBSD.org>
CommitDate: 2021-09-10 04:58:18 +0000

    textproc/ocaml-csv: the port had been improved (+)
    
    - Unbreak against immutable strings in OCaml 4.06+
    - Define LICENSE (GNU LGPL version 2.1 or later)
    - Drop unused dependency on `devel/ocaml-extlib'
    - Hook the provided test target to our framework
    - Fix wording and grammar of the port description
---
 textproc/ocaml-csv/Makefile                |   3 +-
 textproc/ocaml-csv/files/patch-src_csv.ml  | 235 +++++++++++++++++++++++++++++
 textproc/ocaml-csv/files/patch-src_csv.mli |  20 +++
 textproc/ocaml-csv/pkg-descr               |   4 +-
 4 files changed, 259 insertions(+), 3 deletions(-)

diff --git a/textproc/ocaml-csv/Makefile b/textproc/ocaml-csv/Makefile
index 4a9841f25bc7..bdc0c1a94232 100644
--- a/textproc/ocaml-csv/Makefile
+++ b/textproc/ocaml-csv/Makefile
@@ -9,7 +9,7 @@ MASTER_SITES=	https://forge.ocamlcore.org/frs/download.php/420/
 MAINTAINER=	tcrimi at gmail.com
 COMMENT=	OCaml library to read and write CSV files
 
-BUILD_DEPENDS=	${LOCALBASE}/${OCAML_SITELIBDIR}/extlib:devel/ocaml-extlib
+LICENSE=	LGPL21+
 
 WRKSRC=		${WRKDIR}/csv-${PORTVERSION}
 USES=		gmake
@@ -17,6 +17,7 @@ MAKE_ARGS=	byte native
 USE_OCAML=	yes
 USE_OCAML_FINDLIB=	yes
 OCAML_PKGDIRS=	csv
+TEST_TARGET=	tests
 
 MAKE_JOBS_UNSAFE=	yes
 
diff --git a/textproc/ocaml-csv/files/patch-src_csv.ml b/textproc/ocaml-csv/files/patch-src_csv.ml
new file mode 100644
index 000000000000..dbbc419be7dc
--- /dev/null
+++ b/textproc/ocaml-csv/files/patch-src_csv.ml
@@ -0,0 +1,235 @@
+--- src/csv.ml.orig	2010-06-14 11:17:06 UTC
++++ src/csv.ml
+@@ -50,13 +50,13 @@ let max i j = if (i:int) < j then j else i
+ 
+ class type in_obj_channel =
+ object
+-  method input : string -> int -> int -> int
++  method input : bytes -> int -> int -> int
+   method close_in : unit -> unit
+ end
+ 
+ class type out_obj_channel =
+ object
+-  method output : string -> int -> int -> int
++  method output : bytes -> int -> int -> int
+   method close_out : unit -> unit
+ end
+ 
+@@ -81,7 +81,7 @@ let buffer_len = 0x1FFF
+    FIXME: This is not made for non-blocking channels.  Can we fix it? *)
+ type in_channel = {
+   in_chan : in_obj_channel;
+-  in_buf : string;
++  in_buf : bytes;
+   (* The data in the in_buf is at indexes i s.t. in0 <= i < in1.
+      Invariant: 0 <= in0 ; in1 <= buffer_len in1 < 0 indicates a
+      closed channel. *)
+@@ -156,12 +156,12 @@ object
+   val ic = ic
+ 
+   method input buf ofs len =
+-    if ofs < 0 || len < 0 || ofs + len > String.length buf
++    if ofs < 0 || len < 0 || ofs + len > Bytes.length buf
+     then invalid_arg "Csv.to_in_obj#input";
+     if ic.in1 < 0 then raise(Sys_error "Bad file descriptor");
+     fill_in_buf ic;
+     let r = min len (ic.in1 - ic.in0) in
+-    String.blit ic.in_buf ic.in0 buf ofs r;
++    Bytes.blit ic.in_buf ic.in0 buf ofs r;
+     ic.in0 <- ic.in0 + r;
+     r
+ 
+@@ -185,8 +185,8 @@ let strip_contents buf =
+    assumed the substring parameters are valid. *)
+ let strip_substring buf ofs len =
+   let n = ref(ofs + len - 1) in
+-  while !n >= ofs && is_space(String.unsafe_get buf !n) do decr n done;
+-  String.sub buf ofs (!n - ofs + 1)
++  while !n >= ofs && is_space(Bytes.unsafe_get buf !n) do decr n done;
++  Bytes.sub_string buf ofs (!n - ofs + 1)
+ 
+ 
+ (* Skip the possible '\n' following a '\r'.  Reaching End_of_file is
+@@ -194,7 +194,7 @@ let strip_substring buf ofs len =
+ let skip_CR ic =
+   try
+     fill_in_buf ic;
+-    if String.unsafe_get ic.in_buf ic.in0 = '\n' then ic.in0 <- ic.in0 + 1
++    if Bytes.unsafe_get ic.in_buf ic.in0 = '\n' then ic.in0 <- ic.in0 + 1
+   with End_of_file -> ()
+ 
+ 
+@@ -205,19 +205,19 @@ let skip_CR ic =
+ let rec seek_unquoted_separator ic i =
+   if i >= ic.in1 then (
+     (* End not found, need to look at the next chunk *)
+-    Buffer.add_substring ic.current_field ic.in_buf ic.in0 (i - ic.in0);
++    Buffer.add_subbytes ic.current_field ic.in_buf ic.in0 (i - ic.in0);
+     ic.in0 <- i;
+     fill_in_buf ic; (* or raise End_of_file *)
+     seek_unquoted_separator ic 0
+   )
+   else
+-    let c = String.unsafe_get ic.in_buf i in
++    let c = Bytes.unsafe_get ic.in_buf i in
+     if c = ic.separator || c = '\n' || c = '\r' then (
+       if Buffer.length ic.current_field = 0 then
+         (* Avoid copying the string to the buffer if unnecessary *)
+         ic.record <- strip_substring ic.in_buf ic.in0 (i - ic.in0) :: ic.record
+       else (
+-        Buffer.add_substring ic.current_field ic.in_buf ic.in0 (i - ic.in0);
++        Buffer.add_subbytes ic.current_field ic.in_buf ic.in0 (i - ic.in0);
+         ic.record <- strip_contents ic.current_field :: ic.record;
+       );
+       ic.in0 <- i + 1;
+@@ -236,7 +236,7 @@ let add_unquoted_field ic =
+    follow, [false] if the record is complete. *)
+ let rec seek_quoted_separator ic field_no =
+   fill_in_buf ic; (* or raise End_of_file *)
+-  let c = String.unsafe_get ic.in_buf ic.in0 in
++  let c = Bytes.unsafe_get ic.in_buf ic.in0 in
+   ic.in0 <- ic.in0 + 1;
+   if c = ic.separator || c = '\n' || c = '\r' then (
+     ic.record <- Buffer.contents ic.current_field :: ic.record;
+@@ -249,13 +249,13 @@ let rec seek_quoted_separator ic field_no =
+ let rec examine_quoted_field ic field_no after_quote i =
+   if i >= ic.in1 then (
+     (* End of field not found, need to look at the next chunk *)
+-    Buffer.add_substring ic.current_field ic.in_buf ic.in0 (i - ic.in0);
++    Buffer.add_subbytes ic.current_field ic.in_buf ic.in0 (i - ic.in0);
+     ic.in0 <- i;
+     fill_in_buf ic; (* or raise End_of_file *)
+     examine_quoted_field ic field_no after_quote 0
+   )
+   else
+-    let c = String.unsafe_get ic.in_buf i in
++    let c = Bytes.unsafe_get ic.in_buf i in
+     if !after_quote then (
+       if c = '\"' then (
+         after_quote := false;
+@@ -278,7 +278,7 @@ let rec examine_quoted_field ic field_no after_quote i
+     else if c = '\"' then (
+       after_quote := true;
+       (* Save the field so far, without the quote *)
+-      Buffer.add_substring ic.current_field ic.in_buf ic.in0 (i - ic.in0);
++      Buffer.add_subbytes ic.current_field ic.in_buf ic.in0 (i - ic.in0);
+       ic.in0 <- i + 1; (* skip the quote *)
+       examine_quoted_field ic field_no after_quote ic.in0
+     )
+@@ -298,12 +298,12 @@ let add_quoted_field ic field_no =
+ let skip_spaces ic =
+   let is_space = if ic.separator = '\t' then is_real_space else is_space in
+   (* Skip spaces: after this [in0] is a non-space char. *)
+-  while ic.in0 < ic.in1 && is_space(String.unsafe_get ic.in_buf ic.in0) do
++  while ic.in0 < ic.in1 && is_space(Bytes.unsafe_get ic.in_buf ic.in0) do
+     ic.in0 <- ic.in0 + 1
+   done;
+   while ic.in0 >= ic.in1 do
+     fill_in_buf ic;
+-    while ic.in0 < ic.in1 && is_space(String.unsafe_get ic.in_buf ic.in0) do
++    while ic.in0 < ic.in1 && is_space(Bytes.unsafe_get ic.in_buf ic.in0) do
+       ic.in0 <- ic.in0 + 1
+     done;
+   done
+@@ -320,7 +320,7 @@ let add_next_field ic field_no =
+   try
+     skip_spaces ic;
+     (* Now, in0 < in1 or End_of_file was raised *)
+-    let c = String.unsafe_get ic.in_buf ic.in0 in
++    let c = Bytes.unsafe_get ic.in_buf ic.in0 in
+     if c = '\"' then (
+       ic.in0 <- ic.in0 + 1;
+       add_quoted_field ic field_no
+@@ -329,7 +329,7 @@ let add_next_field ic field_no =
+       ic.in0 <- ic.in0 + 1; (* mark '=' as read *)
+       try
+         fill_in_buf ic;
+-        if String.unsafe_get ic.in_buf ic.in0 = '\"' then (
++        if Bytes.unsafe_get ic.in_buf ic.in0 = '\"' then (
+           (* Excel trick ="..." to prevent spaces around the field
+              to be removed. *)
+           ic.in0 <- ic.in0 + 1; (* skip '"' *)
+@@ -414,14 +414,14 @@ let load_rows ?separator ?excel_tricks f ch =
+ type out_channel = {
+   out_chan : out_obj_channel;
+   out_separator : char;
+-  out_separator_string : string;
++  out_separator_bytes : bytes;
+   out_excel_tricks : bool;
+ }
+ 
+ let to_out_obj ?(separator=',') ?(excel_tricks=false) out_chan = {
+   out_chan = out_chan;
+   out_separator = separator;
+-  out_separator_string = String.make 1 separator;
++  out_separator_bytes = Bytes.make 1 separator;
+   out_excel_tricks = excel_tricks;
+ }
+ 
+@@ -437,6 +437,16 @@ let rec really_output oc s ofs len =
+   let w = oc.out_chan#output s ofs len in
+   if w < len then really_output oc s (ofs+w) (len-w)
+ 
++let quote_bytes = Bytes.make 1 '\"'
++let output_quote oc = really_output oc quote_bytes 0 1
++
++let equal_quote_bytes = Bytes.make 2 '='
++let () = Bytes.unsafe_set equal_quote_bytes 1 '\"'
++let output_equal_quote oc = really_output oc equal_quote_bytes 0 2
++
++let newline_bytes = Bytes.make 1 '\n'
++let output_newline oc = really_output oc newline_bytes 0 1
++
+ (* Determine whether the string s must be quoted and how many chars it
+    must be extended to contain the escaped values.  Return -1 if there
+    is no need to quote.  It is assumed that the string length [len]
+@@ -466,10 +476,11 @@ let write_escaped oc field =
+     let use_excel_trick = oc.out_excel_tricks && need_excel_trick field len
+     and n = must_quote oc.out_separator oc.out_excel_tricks field len in
+     if n < 0 && not use_excel_trick then
+-      really_output oc field 0 len
++      (* [really_output] does not mutate the [bytes] argument. *)
++      really_output oc (Bytes.unsafe_of_string field) 0 len
+     else (
+       let field =
+-        if n = 0 then field
++        if n = 0 then Bytes.unsafe_of_string field
+         else (* There are some quotes to escape *)
+           let s = String.create (len + n) in
+           let j = ref 0 in
+@@ -487,26 +498,26 @@ let write_escaped oc field =
+           done;
+           s
+       in
+-      if use_excel_trick then really_output oc "=\"" 0 2
+-      else really_output oc "\"" 0 1;
+-      really_output oc field 0 (String.length field);
+-      really_output oc "\"" 0 1
++      if use_excel_trick then output_equal_quote oc
++      else output_quote oc;
++      really_output oc field 0 (Bytes.length field);
++      output_quote oc
+     )
+   end
+ 
+ let output_record oc = function
+   | [] ->
+-      really_output oc "\n" 0 1
++      output_newline oc
+   | [f] ->
+       write_escaped oc f;
+-      really_output oc "\n" 0 1
++      output_newline oc
+   | f :: tl ->
+       write_escaped oc f;
+       List.iter (fun f ->
+-                   really_output oc oc.out_separator_string 0 1;
++                   really_output oc oc.out_separator_bytes 0 1;
+                    write_escaped oc f;
+                 ) tl;
+-      really_output oc "\n" 0 1
++      output_newline oc
+ 
+ let output_all oc t =
+   List.iter (fun r -> output_record oc r) t
diff --git a/textproc/ocaml-csv/files/patch-src_csv.mli b/textproc/ocaml-csv/files/patch-src_csv.mli
new file mode 100644
index 000000000000..ecccf681add9
--- /dev/null
+++ b/textproc/ocaml-csv/files/patch-src_csv.mli
@@ -0,0 +1,20 @@
+--- src/csv.mli.orig	2010-06-14 11:17:06 UTC
++++ src/csv.mli
+@@ -37,7 +37,7 @@ type t = string list list
+ (** The most basic input object for best interoperability. *)
+ class type in_obj_channel =
+ object
+-  method input : string -> int -> int -> int
++  method input : bytes -> int -> int -> int
+     (** [input buf ofs len] reads up to [len] octets from the channel
+         and puts them in the substring [buf.[ofs .. ofs+len-1]].
+         Returns the number of octets actually read (and stored).  When
+@@ -52,7 +52,7 @@ end
+ (** The most basic output object for best interoperability. *)
+ class type out_obj_channel =
+ object
+-  method output : string -> int -> int -> int
++  method output : bytes -> int -> int -> int
+     (** [output s ofs len] writes up to [len] bytes of the substring
+         [s.[ofs .. ofs+len-1]].  Return the number of bytes actually
+         written.  When the channel is non-blocking, and there are
diff --git a/textproc/ocaml-csv/pkg-descr b/textproc/ocaml-csv/pkg-descr
index 846a4ce73995..8fdd50978cbd 100644
--- a/textproc/ocaml-csv/pkg-descr
+++ b/textproc/ocaml-csv/pkg-descr
@@ -1,4 +1,4 @@
-This library can read and write CSV files, including all extensions used by
-Excel - eg. quotes, newlines, 8 bit characters in fields, "0 etc.
+This library can read and write CSV files, including all extensions used
+Microsoft Excel, e.g. quotes, newlines, 8-bit field characters, "0, etc.
 
 WWW: http://forge.ocamlcore.org/projects/csv/


More information about the dev-commits-ports-main mailing list