summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stdlib/scanf.ml28
-rw-r--r--stdlib/scanf.mli43
2 files changed, 45 insertions, 26 deletions
diff --git a/stdlib/scanf.ml b/stdlib/scanf.ml
index 92d3d667d..aef85182a 100644
--- a/stdlib/scanf.ml
+++ b/stdlib/scanf.ml
@@ -306,10 +306,13 @@ end;;
(* Formatted input functions. *)
+type ('a, 'b, 'c, 'd) tscanf =
+ ('a, Scanning.scanbuf, 'b, 'c, 'a -> 'd, 'd) format6 -> 'c;;
+
module Sformat = Printf.Sformat;;
external string_to_format :
- string -> ('a, 'b, 'c, 'd) format4 = "%identity";;
+ string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity";;
(* Reporting errors. *)
exception Scan_failure of string;;
@@ -962,7 +965,7 @@ let rec skip_whites ib =
If the scanning or some conversion fails, the main scanning function
aborts and applies the scanning buffer and a string that explains
the error to the error handling function [ef] (the error continuation). *)
-let kscanf ib ef fmt f =
+let kscanf ib ef fmt = Obj.magic (fun f ->
let lim = Sformat.length fmt - 1 in
@@ -997,7 +1000,7 @@ let kscanf ib ef fmt f =
| 'S' ->
let _x = scan_String max ib in
scan_fmt (stack f (token_string ib)) (succ i)
- | '[' ->
+ | '[' (* ']' *) ->
let i, char_set = read_char_set fmt (succ i) in
let i, stp = scan_fmt_stoppers (succ i) in
let _x = scan_chars_in_char_set stp char_set max ib in
@@ -1061,7 +1064,7 @@ let kscanf ib ef fmt f =
let p, i = read_width 0 (succ i) in
scan_conversion skip (succ (max + p)) f i
| _ -> scan_conversion skip max f i end
- | '(' | '{' as conv ->
+ | '(' | '{' as conv (* ')' '}' *) ->
let i = succ i in
let j =
Printf.sub_format
@@ -1070,7 +1073,7 @@ let kscanf ib ef fmt f =
let _x = scan_String max ib in
let rf = token_string ib in
if not (compatible_format_type rf mf) then format_mismatch rf mf ib else
- if conv = '{' then scan_fmt (stack f rf) j else
+ if conv = '{' (* '}' *) then scan_fmt (stack f rf) j else
let nf = scan_fmt (Obj.magic rf) 0 in
scan_fmt (stack f nf) j
| c -> bad_conversion fmt i c
@@ -1088,7 +1091,7 @@ let kscanf ib ef fmt f =
try scan_fmt (fun () -> f) 0 with
| (Scan_failure _ | Failure _ | End_of_file) as exc ->
stack (delay ef ib) exc in
- return v;;
+ return v);;
let bscanf ib = kscanf ib scanf_bad_input;;
@@ -1103,9 +1106,16 @@ let bscanf_format ib fmt f =
let fmt1 = ignore (scan_String max_int ib); token_string ib in
if not (compatible_format_type fmt1 fmt) then
format_mismatch fmt1 fmt ib else
- let fresh_fmt1 = String.copy fmt1 in
- f (string_to_format fresh_fmt1);;
+ f (string_to_format fmt1);;
let sscanf_format s fmt f = bscanf_format (Scanning.from_string s) fmt f;;
-let format_from_string s fmt = sscanf_format s fmt (fun x -> x);;
+let quote_string s =
+ let b = Buffer.create (String.length s + 2) in
+ Buffer.add_char b '\"';
+ Buffer.add_string b s;
+ Buffer.add_char b '\"';
+ Buffer.contents b;;
+
+let format_from_string s fmt =
+ sscanf_format (quote_string s) fmt (fun x -> x);;
diff --git a/stdlib/scanf.mli b/stdlib/scanf.mli
index 37fe47dda..aaa447de8 100644
--- a/stdlib/scanf.mli
+++ b/stdlib/scanf.mli
@@ -85,9 +85,12 @@ exception Scan_failure of string;;
(** The exception that formatted input functions raise when the input
cannot be read according to the given format. *)
-val bscanf :
- Scanning.scanbuf -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;;
-(** [bscanf ib fmt f] reads tokens from the scanning buffer [ib] according
+type ('a, 'b, 'c, 'd) tscanf =
+ ('a, Scanning.scanbuf, 'b, 'c, 'a -> 'd, 'd) format6 -> 'c;;
+
+val bscanf : Scanning.scanbuf -> ('a, 'b, 'c, 'd) tscanf;;
+(**
+ [bscanf ib fmt f] reads tokens from the scanning buffer [ib] according
to the format string [fmt], converts these tokens to values, and
applies the function [f] to these values.
The result of this application of [f] is the result of the whole construct.
@@ -160,6 +163,9 @@ val bscanf :
first character of the range (or just after the [^] in case of
range negation); hence [\[\]\]] matches a [\]] character and
[\[^\]\]] matches any character that is not [\]].
+ - [r]: user-defined reader. Takes a reader function [rdr] as argument and
+ applies it to [ib]. The argument [rdr] must therefore have type
+ [Scanf.Scanning.scanbuf -> 't] and the argument read has type ['t].
- [\{ fmt %\}]: reads a format string argument to the format
specified by the internal format [fmt]. The format string to be
read must have the same type as the internal format [fmt].
@@ -232,7 +238,7 @@ val bscanf :
[ocamlyacc]-generated parsers.
*)
-val fscanf : in_channel -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;;
+val fscanf : in_channel -> ('a, 'b, 'c, 'd) tscanf;;
(** Same as {!Scanf.bscanf}, but inputs from the given channel.
Warning: since all scanning functions operate from a scanning
@@ -251,16 +257,16 @@ val fscanf : in_channel -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;;
This method is not only clearer it is also faster, since scanning
buffers to files are optimized for fast bufferized reading. *)
-val sscanf : string -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;;
+val sscanf : string -> ('a, 'b, 'c, 'd) tscanf;;
(** Same as {!Scanf.bscanf}, but inputs from the given string. *)
-val scanf : ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;;
+val scanf : ('a, 'b, 'c, 'd) tscanf;;
(** Same as {!Scanf.bscanf}, but reads from the predefined scanning
buffer {!Scanf.Scanning.stdib} that is connected to [stdin]. *)
val kscanf :
- Scanning.scanbuf -> (Scanning.scanbuf -> exn -> 'a) ->
- ('b, Scanning.scanbuf, 'a) format -> 'b -> 'a;;
+ Scanning.scanbuf -> (Scanning.scanbuf -> exn -> 'd) ->
+ ('a, 'b, 'c, 'd) tscanf;;
(** Same as {!Scanf.bscanf}, but takes an additional function argument
[ef] that is called in case of error: if the scanning process or
some conversion fails, the scanning function aborts and applies the
@@ -268,20 +274,23 @@ val kscanf :
exception that aborted the scanning process. *)
val bscanf_format :
- Scanning.scanbuf -> ('a, 'b, 'c, 'd) format4 ->
- (('a, 'b, 'c, 'd) format4 -> 'e) -> 'e;;
+ Scanning.scanbuf -> ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
+ (('a, 'b, 'c, 'd, 'e, 'f) format6 -> 'g) -> 'g;;
(** [bscanf_format ib fmt f] reads a format string token from scannning buffer
- [ib], according to the format string [fmt], and applies the function [f] to
- the resulting format string value.
+ [ib], according to the given format string [fmt], and applies
+ the function [f] to the resulting format string value.
Raises [Scan_failure] if the format string value read has not the same type
as [fmt]. *)
val sscanf_format :
- string -> ('a, 'b, 'c, 'd) format4 ->
- (('a, 'b, 'c, 'd) format4 -> 'e) -> 'e;;
+ string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
+ (('a, 'b, 'c, 'd, 'e, 'f) format6 -> 'g) -> 'g;;
(** Same as {!Scanf.bscanf_format}, but inputs from the given string. *)
val format_from_string :
- string -> ('a, 'b, 'c, 'd) format4 -> ('a, 'b, 'c, 'd) format4;;
-(** Same as {!Scanf.sscanf_format}, but converts the given string to a format
- string. *)
+ string ->
+ ('a, 'b, 'c, 'd, 'e, 'f) format6 -> ('a, 'b, 'c, 'd, 'e, 'f) format6;;
+(** [format_from_string s fmt] converts a string argument to a format string,
+ according to the given format string [fmt].
+ Raises [Scan_failure] if [s], considered as a format string, has not the same
+ type as [fmt]. *)