New upstream version 0.12.0
Stephane Glondu
4 years ago
0 | ## git version | |
1 | ||
2 | - Added function `Out_channel.print_s`. | |
3 | ||
4 | ## v0.10 | |
5 | ||
6 | - Enabled `-safe-string`. | |
7 | ||
8 | - Added functions `Out_channel.output_bytes`, `Out_channel.output_substring`. | |
9 | ||
10 | - Added functions `In_channel.equal` and `Out_channel.equal`, implemented as `phys_equal`. | |
11 | ||
12 | ## v0.9 | |
13 | ||
14 | Initial release. |
0 | This repository contains open source software that is developed and | |
1 | maintained by [Jane Street][js]. | |
2 | ||
3 | Contributions to this project are welcome and should be submitted via | |
4 | GitHub pull requests. | |
5 | ||
6 | Signing contributions | |
7 | --------------------- | |
8 | ||
9 | We require that you sign your contributions. Your signature certifies | |
10 | that you wrote the patch or otherwise have the right to pass it on as | |
11 | an open-source patch. The rules are pretty simple: if you can certify | |
12 | the below (from [developercertificate.org][dco]): | |
13 | ||
14 | ``` | |
15 | Developer Certificate of Origin | |
16 | Version 1.1 | |
17 | ||
18 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. | |
19 | 1 Letterman Drive | |
20 | Suite D4700 | |
21 | San Francisco, CA, 94129 | |
22 | ||
23 | Everyone is permitted to copy and distribute verbatim copies of this | |
24 | license document, but changing it is not allowed. | |
25 | ||
26 | ||
27 | Developer's Certificate of Origin 1.1 | |
28 | ||
29 | By making a contribution to this project, I certify that: | |
30 | ||
31 | (a) The contribution was created in whole or in part by me and I | |
32 | have the right to submit it under the open source license | |
33 | indicated in the file; or | |
34 | ||
35 | (b) The contribution is based upon previous work that, to the best | |
36 | of my knowledge, is covered under an appropriate open source | |
37 | license and I have the right under that license to submit that | |
38 | work with modifications, whether created in whole or in part | |
39 | by me, under the same open source license (unless I am | |
40 | permitted to submit under a different license), as indicated | |
41 | in the file; or | |
42 | ||
43 | (c) The contribution was provided directly to me by some other | |
44 | person who certified (a), (b) or (c) and I have not modified | |
45 | it. | |
46 | ||
47 | (d) I understand and agree that this project and the contribution | |
48 | are public and that a record of the contribution (including all | |
49 | personal information I submit with it, including my sign-off) is | |
50 | maintained indefinitely and may be redistributed consistent with | |
51 | this project or the open source license(s) involved. | |
52 | ``` | |
53 | ||
54 | Then you just add a line to every git commit message: | |
55 | ||
56 | ``` | |
57 | Signed-off-by: Joe Smith <joe.smith@email.com> | |
58 | ``` | |
59 | ||
60 | Use your real name (sorry, no pseudonyms or anonymous contributions.) | |
61 | ||
62 | If you set your `user.name` and `user.email` git configs, you can sign | |
63 | your commit automatically with git commit -s. | |
64 | ||
65 | [dco]: http://developercertificate.org/ | |
66 | [js]: https://opensource.janestreet.com/ |
0 | The MIT License | |
1 | ||
2 | Copyright (c) 2016--2019 Jane Street Group, LLC <opensource@janestreet.com> | |
3 | ||
4 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 | of this software and associated documentation files (the "Software"), to deal | |
6 | in the Software without restriction, including without limitation the rights | |
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 | copies of the Software, and to permit persons to whom the Software is | |
9 | furnished to do so, subject to the following conditions: | |
10 | ||
11 | The above copyright notice and this permission notice shall be included in all | |
12 | copies or substantial portions of the Software. | |
13 | ||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
20 | SOFTWARE. |
0 | INSTALL_ARGS := $(if $(PREFIX),--prefix $(PREFIX),) | |
1 | ||
2 | default: | |
3 | dune build | |
4 | ||
5 | install: | |
6 | dune install $(INSTALL_ARGS) | |
7 | ||
8 | uninstall: | |
9 | dune uninstall $(INSTALL_ARGS) | |
10 | ||
11 | reinstall: uninstall install | |
12 | ||
13 | clean: | |
14 | dune clean | |
15 | ||
16 | .PHONY: default install uninstall reinstall clean |
0 | * Standard IO Library for OCaml | |
1 | ||
2 | Stdio provides input/output functions for OCaml. It re-exports the | |
3 | buffered channels of the stdlib distributed with OCaml but with some | |
4 | improvements. |
0 | (lang dune 1.5)⏎ |
0 | (library (name stdio) (public_name stdio) (libraries base base.caml) | |
1 | (preprocess no_preprocessing) | |
2 | (lint | |
3 | (pps ppx_base -check-doc-comments -type-conv-keep-w32=impl | |
4 | -apply=js_style,type_conv)))⏎ |
0 | open! Base | |
1 | ||
2 | module Sexplib = Base.Exported_for_specific_uses.Sexplib | |
3 | module Ppx_sexp_conv_lib = Base.Exported_for_specific_uses.Ppx_sexp_conv_lib |
0 | open! Base | |
1 | open! Import | |
2 | ||
3 | type t = Caml.in_channel | |
4 | ||
5 | let equal (t1 : t) t2 = phys_equal t1 t2 | |
6 | ||
7 | let seek = Caml.LargeFile.seek_in | |
8 | let pos = Caml.LargeFile.pos_in | |
9 | let length = Caml.LargeFile.in_channel_length | |
10 | ||
11 | let stdin = Caml.stdin | |
12 | ||
13 | let create ?(binary = true) file = | |
14 | let flags = [Open_rdonly] in | |
15 | let flags = if binary then Open_binary :: flags else flags in | |
16 | Caml.open_in_gen flags 0o000 file | |
17 | ;; | |
18 | ||
19 | let close = Caml.close_in | |
20 | ||
21 | let with_file ?binary file ~f = Exn.protectx (create ?binary file) ~f ~finally:close | |
22 | ||
23 | let may_eof f = try Some (f ()) with End_of_file -> None | |
24 | ||
25 | let input t ~buf ~pos ~len = Caml.input t buf pos len | |
26 | let really_input t ~buf ~pos ~len = | |
27 | may_eof (fun () -> Caml.really_input t buf pos len) | |
28 | let really_input_exn t ~buf ~pos ~len = | |
29 | Caml.really_input t buf pos len | |
30 | let input_byte t = may_eof (fun () -> Caml.input_byte t) | |
31 | let input_char t = may_eof (fun () -> Caml.input_char t) | |
32 | let input_binary_int t = may_eof (fun () -> Caml.input_binary_int t) | |
33 | let unsafe_input_value t = may_eof (fun () -> Caml.input_value t) | |
34 | let input_buffer t buf ~len = may_eof (fun () -> Caml.Buffer.add_channel buf t len) | |
35 | ||
36 | let set_binary_mode = Caml.set_binary_mode_in | |
37 | ||
38 | let input_all t = | |
39 | (* We use 65536 because that is the size of OCaml's IO buffers. *) | |
40 | let buf_size = 65536 in | |
41 | let buf = Bytes.create buf_size in | |
42 | let buffer = Buffer.create buf_size in | |
43 | let rec loop () = | |
44 | let len = input t ~buf ~pos:0 ~len:(Bytes.length buf) in | |
45 | if len > 0 then begin | |
46 | Buffer.add_subbytes buffer buf ~pos:0 ~len; | |
47 | loop (); | |
48 | end | |
49 | in | |
50 | loop (); | |
51 | Buffer.contents buffer; | |
52 | ;; | |
53 | ||
54 | let trim ~fix_win_eol line = | |
55 | if fix_win_eol then begin | |
56 | let len = String.length line in | |
57 | if len > 0 | |
58 | && Char.equal (String.get line (len - 1)) '\r' | |
59 | then String.sub line ~pos:0 ~len:(len - 1) | |
60 | else line | |
61 | end | |
62 | else line | |
63 | ||
64 | let input_line ?(fix_win_eol = true) t = | |
65 | match may_eof (fun () -> Caml.input_line t) with | |
66 | | None -> None | |
67 | | Some line -> Some (trim ~fix_win_eol line) | |
68 | ;; | |
69 | ||
70 | let input_line_exn ?(fix_win_eol = true) t = | |
71 | let line = Caml.input_line t in | |
72 | trim ~fix_win_eol line | |
73 | ||
74 | let fold_lines ?fix_win_eol t ~init ~f = | |
75 | let rec loop ac = | |
76 | match input_line ?fix_win_eol t with | |
77 | | None -> ac | |
78 | | Some line -> loop (f ac line) | |
79 | in | |
80 | loop init | |
81 | ;; | |
82 | ||
83 | let input_lines ?fix_win_eol t = | |
84 | List.rev | |
85 | (fold_lines ?fix_win_eol t ~init:[] ~f:(fun lines line -> line :: lines)) | |
86 | ;; | |
87 | ||
88 | let iter_lines ?fix_win_eol t ~f = | |
89 | fold_lines ?fix_win_eol t ~init:() ~f:(fun () line -> f line) | |
90 | ;; | |
91 | ||
92 | let read_lines fname = with_file fname ~f:input_lines | |
93 | ||
94 | let read_all fname = with_file fname ~f:input_all |
0 | (** An input channel for doing blocking reads from input sources like files and sockets. | |
1 | ||
2 | Note that an [In_channel.t] is a custom block with a finalizer, and so is allocated | |
3 | directly to the major heap. Creating a lot of in_channels can result in many major | |
4 | collections and poor performance. | |
5 | ||
6 | Note that this is simply another interface on the [in_channel] type in the OCaml | |
7 | standard library. | |
8 | *) | |
9 | ||
10 | open! Base | |
11 | open! Import | |
12 | ||
13 | type t = Caml.in_channel | |
14 | ||
15 | include Equal.S with type t := t | |
16 | ||
17 | val stdin : t | |
18 | ||
19 | (** Channels are opened in binary mode iff [binary] is true. This only has an effect on | |
20 | Windows. | |
21 | *) | |
22 | ||
23 | val create : ?binary:bool (** defaults to [true] *) -> string -> t | |
24 | ||
25 | (** [with_file ~f fname] executes [~f] on the open channel from | |
26 | [fname], and closes it afterwards. *) | |
27 | val with_file : ?binary:bool (** defaults to [true] *) -> string -> f:(t -> 'a) -> 'a | |
28 | ||
29 | (** [close t] closes [t], or does nothing if [t] is already closed, and may raise an | |
30 | exception. *) | |
31 | val close : t -> unit | |
32 | ||
33 | val input : t -> buf:bytes -> pos:int -> len:int -> int | |
34 | val really_input : t -> buf:bytes -> pos:int -> len:int -> unit option | |
35 | ||
36 | (** Same as [Pervasives.really_input], for backwards compatibility *) | |
37 | val really_input_exn : t -> buf:bytes -> pos:int -> len:int -> unit | |
38 | ||
39 | (** Read one character from the given input channel. Return [None] if there are no more | |
40 | characters to read. *) | |
41 | val input_char : t -> char option | |
42 | ||
43 | (** Same as [input_char], but return the 8-bit integer representing the character. Return | |
44 | [None] if an end of file was reached. *) | |
45 | val input_byte : t -> int option | |
46 | ||
47 | (** Read an integer encoded in binary format (4 bytes, big-endian) from the given input | |
48 | channel. See {!Pervasives.output_binary_int}. Return [None] if an end of file was | |
49 | reached while reading the integer. *) | |
50 | val input_binary_int : t -> int option | |
51 | ||
52 | (** Ocaml's built-in marshal format *) | |
53 | val unsafe_input_value : t -> _ option | |
54 | ||
55 | (** [input_buffer t buf ~len] reads at most [len] characters from the input channel [t] | |
56 | and stores them at the end of buffer [buf]. Return [None] if the channel contains | |
57 | fewer than [len] characters. In this case, the characters are still added to the | |
58 | buffer, so as to avoid loss of data. *) | |
59 | val input_buffer : t -> Buffer.t -> len:int -> unit option | |
60 | ||
61 | val input_all : t -> string | |
62 | ||
63 | (** [input_line ?fix_win_eol t] reads a line from [t] and returns it, without | |
64 | the newline ("\n") character at the end, and, if [fix_win_eol] the trailing | |
65 | "\r\n" is dropped. | |
66 | *) | |
67 | val input_line : ?fix_win_eol:bool (** defaults to [true] *) -> t -> string option | |
68 | val input_line_exn : ?fix_win_eol:bool (** defaults to [true] *) -> t -> string | |
69 | ||
70 | (** [fold_lines ?fix_win_eol t ~init ~f] folds over the lines read from [t] | |
71 | using [input_line]. Lines are provided to [f] in the order they are | |
72 | found in the file. *) | |
73 | val fold_lines | |
74 | : ?fix_win_eol:bool (** defaults to [true] *) | |
75 | -> t | |
76 | -> init:'a | |
77 | -> f:('a -> string -> 'a) | |
78 | -> 'a | |
79 | ||
80 | (** Completely reads an input channel and returns the results as a list of | |
81 | strings. Each line in one string. *) | |
82 | val input_lines : ?fix_win_eol:bool (** defaults to [true] *) -> t -> string list | |
83 | ||
84 | (** [iter_lines ?fix_win_eol t ~f] applies [f] to each line read from [t] using | |
85 | [input_line]. *) | |
86 | val iter_lines | |
87 | : ?fix_win_eol:bool (** defaults to [true] *) | |
88 | -> t | |
89 | -> f:(string -> unit) | |
90 | -> unit | |
91 | ||
92 | (** This works only for regular files. On files of other kinds, the behavior is | |
93 | unspecified. *) | |
94 | val seek : t -> int64 -> unit | |
95 | ||
96 | val pos : t -> int64 | |
97 | ||
98 | (** Return the size (number of characters) of the regular file on which the given channel | |
99 | is opened. If the channel is opened on a file that is not a regular file, the result | |
100 | is meaningless. The returned size does not take into account the end-of-line | |
101 | translations that can be performed when reading from a channel opened in text mode. *) | |
102 | val length : t -> int64 | |
103 | ||
104 | (** same as [Pervasives.set_binary_mode_in], only applicable for Windows or Cygwin, no-op | |
105 | otherwise *) | |
106 | val set_binary_mode : t -> bool -> unit | |
107 | ||
108 | ||
109 | (** [read_lines filename] reads the full contents of file and returns it as a list of | |
110 | lines, closing the file when it's done. It's the equivalent of [with_file fname | |
111 | ~f:input_lines] *) | |
112 | val read_lines : string -> string list | |
113 | ||
114 | (** [read_all filename] reads the full contents of file and returns it as a single | |
115 | string, closing the file when it's done. It's the equivalent of [with_file fname | |
116 | ~f:input_all] *) | |
117 | val read_all : string -> string |
0 | open! Base | |
1 | open! Import | |
2 | ||
3 | type t = Caml.out_channel | |
4 | ||
5 | let equal (t1 : t) t2 = phys_equal t1 t2 | |
6 | ||
7 | let seek = Caml.LargeFile.seek_out | |
8 | let pos = Caml.LargeFile.pos_out | |
9 | let length = Caml.LargeFile.out_channel_length | |
10 | ||
11 | let stdout = Caml.stdout | |
12 | let stderr = Caml.stderr | |
13 | ||
14 | let sexp_of_t t = | |
15 | if phys_equal t stderr | |
16 | then Sexp.Atom "<stderr>" | |
17 | else if phys_equal t stdout | |
18 | then Sexp.Atom "<stdout>" | |
19 | else Sexp.Atom "<Out_channel.t>" | |
20 | ;; | |
21 | ||
22 | type 'a with_create_args = | |
23 | ?binary:bool | |
24 | -> ?append:bool | |
25 | -> ?fail_if_exists:bool | |
26 | -> ?perm:int | |
27 | -> 'a | |
28 | ||
29 | let create ?(binary = true) ?(append = false) ?(fail_if_exists = false) ?(perm = 0o666) file = | |
30 | let flags = [Open_wronly; Open_creat] in | |
31 | let flags = (if binary then Open_binary else Open_text) :: flags in | |
32 | let flags = (if append then Open_append else Open_trunc) :: flags in | |
33 | let flags = (if fail_if_exists then Open_excl :: flags else flags) in | |
34 | Caml.open_out_gen flags perm file | |
35 | ;; | |
36 | ||
37 | let set_binary_mode = Caml.set_binary_mode_out | |
38 | ||
39 | let flush = Caml.flush | |
40 | ||
41 | let close = Caml.close_out | |
42 | let close_no_err = Caml.close_out_noerr | |
43 | ||
44 | let output t ~buf ~pos ~len = Caml.output t buf pos len | |
45 | let output_substring t ~buf ~pos ~len = Caml.output_substring t buf pos len | |
46 | let output_string = Caml.output_string | |
47 | let output_bytes = Caml.output_bytes | |
48 | let output_char = Caml.output_char | |
49 | let output_byte = Caml.output_byte | |
50 | let output_binary_int = Caml.output_binary_int | |
51 | let output_buffer = Caml.Buffer.output_buffer | |
52 | let output_value = Caml.output_value | |
53 | ||
54 | let newline t = output_string t "\n" | |
55 | ||
56 | let output_lines t lines = | |
57 | List.iter lines ~f:(fun line -> output_string t line; newline t) | |
58 | ;; | |
59 | ||
60 | let printf = Caml.Printf.printf | |
61 | let eprintf = Caml.Printf.eprintf | |
62 | let fprintf = Caml.Printf.fprintf | |
63 | let kfprintf = Caml.Printf.kfprintf | |
64 | ||
65 | let print_string = Caml.print_string | |
66 | let print_endline = Caml.print_endline | |
67 | let prerr_endline = Caml.prerr_endline | |
68 | ||
69 | let print_s ?mach sexp = | |
70 | print_endline | |
71 | (match mach with | |
72 | | Some () -> Sexp.to_string_mach sexp | |
73 | | None -> Sexp.to_string_hum sexp) | |
74 | ;; | |
75 | ||
76 | let with_file ?binary ?append ?fail_if_exists ?perm file ~f = | |
77 | Exn.protectx (create ?binary ?append ?fail_if_exists ?perm file) ~f ~finally:close | |
78 | ;; | |
79 | ||
80 | let write_lines file lines = with_file file ~f:(fun t -> output_lines t lines) | |
81 | ||
82 | let write_all file ~data = with_file file ~f:(fun t -> output_string t data) |
0 | (** An output channel for doing blocking writes to destinations like files and sockets. | |
1 | ||
2 | Note that an [Out_channel.t] is a custom block with a finalizer, and so is allocated | |
3 | directly to the major heap. Creating a lot of out_channels can result in many major | |
4 | collections and poor performance. | |
5 | ||
6 | Note that this is simply another interface on the [out_channel] type in the OCaml | |
7 | standard library. | |
8 | ||
9 | As for the output functions in the standard library, all the functions in this module, | |
10 | unless otherwise specified, can raise [Sys_error] when the system calls they invoke | |
11 | fail. | |
12 | *) | |
13 | ||
14 | open! Base | |
15 | open! Import | |
16 | ||
17 | type t = Caml.out_channel [@@deriving_inline sexp_of] | |
18 | include | |
19 | sig [@@@ocaml.warning "-32"] val sexp_of_t : t -> Ppx_sexp_conv_lib.Sexp.t | |
20 | end[@@ocaml.doc "@inline"] | |
21 | [@@@end] | |
22 | ||
23 | include Equal.S with type t := t | |
24 | ||
25 | val stdout : t | |
26 | val stderr : t | |
27 | ||
28 | type 'a with_create_args = | |
29 | ?binary:bool (** defaults to [true] *) | |
30 | -> ?append:bool (** defaults to [false] *) | |
31 | -> ?fail_if_exists:bool (** defaults to [false] *) | |
32 | -> ?perm:int | |
33 | -> 'a | |
34 | ||
35 | ||
36 | val create : (string -> t) with_create_args | |
37 | val with_file : (string -> f:(t -> 'a) -> 'a) with_create_args | |
38 | ||
39 | ||
40 | (** [close t] flushes and closes [t], and may raise an exception. [close] returns () and | |
41 | does not raise if [t] is already closed. [close] raises an exception if the close() | |
42 | system call on the underlying file descriptor fails (i.e. returns -1), which would | |
43 | happen in the following cases: | |
44 | ||
45 | EBADF -- this would happen if someone else did close() system call on the underlying | |
46 | fd, which I would think a rare event. | |
47 | ||
48 | EINTR -- would happen if the system call was interrupted by a signal, which would be | |
49 | rare. Also, I think we should probably just catch EINTR and re-attempt the close. | |
50 | Unfortunately, we can't do that in OCaml because the OCaml library marks the | |
51 | out_channel as closed even if the close syscall fails, so a subsequent call | |
52 | [close_out_channel] will be a no-op. This should really be fixed in the OCaml library | |
53 | C code, having it restart the close() syscall on EINTR. I put a couple CRs in | |
54 | [fixed_close_channel], our rework of OCaml's [caml_ml_close_channel], | |
55 | ||
56 | EIO -- I don't recall seeing this. I think it's rare. | |
57 | ||
58 | See "man 2 close" for details. | |
59 | *) | |
60 | val close : t -> unit | |
61 | ||
62 | (** [close_no_err] tries to flush and close [t]. It does not raise.*) | |
63 | val close_no_err : t -> unit | |
64 | ||
65 | val set_binary_mode : t -> bool -> unit | |
66 | ||
67 | val flush : t -> unit | |
68 | ||
69 | val output : t -> buf:bytes -> pos:int -> len:int -> unit | |
70 | val output_string : t -> string -> unit | |
71 | val output_substring : t -> buf:string -> pos:int -> len:int -> unit | |
72 | val output_bytes : t -> Bytes.t -> unit | |
73 | val output_char : t -> char -> unit | |
74 | val output_byte : t -> int -> unit | |
75 | val output_binary_int : t -> int -> unit | |
76 | val output_buffer : t -> Buffer.t -> unit | |
77 | val output_value : t -> _ -> unit (** OCaml's internal Marshal format *) | |
78 | ||
79 | val newline : t -> unit | |
80 | ||
81 | (** Outputs a list of lines, each terminated by a newline character *) | |
82 | val output_lines : t -> string list -> unit | |
83 | ||
84 | (** Formatted printing to an out channel. This is the same as [Printf.sprintf] except | |
85 | that it outputs to [t] instead of returning a string. Similarly, the function | |
86 | arguments corresponding to conversions specifications such as [%a] or [%t] takes [t] | |
87 | as argument and must print to it instead of returning a string. *) | |
88 | val fprintf : t -> ('a, t, unit) format -> 'a | |
89 | ||
90 | (** [printf fmt] is the same as [fprintf stdout fmt] *) | |
91 | val printf : ('a, t, unit) format -> 'a | |
92 | ||
93 | (** [print_s sexp] outputs [sexp] on [stdout], by default using [Sexp.to_string_hum], | |
94 | or, with [~mach:()], [Sexp.to_string_mach]. *) | |
95 | val print_s : ?mach : unit -> Sexp.t -> unit | |
96 | ||
97 | (** [printf fmt] is the same as [fprintf stderr fmt] *) | |
98 | val eprintf : ('a, t, unit) format -> 'a | |
99 | ||
100 | (** [kfprintf k t fmt] is the same as [fprintf t fmt], but instead of returning | |
101 | immediately, passes the out channel to [k] at the end of printing. *) | |
102 | val kfprintf : (t -> 'a) -> t -> ('b, t, unit, 'a) format4 -> 'b | |
103 | ||
104 | (** [print_string s] = [output_string stdout s] *) | |
105 | val print_string : string -> unit | |
106 | ||
107 | (** [print_endline str] outputs [str] to [stdout] followed by a newline then flushes | |
108 | [stdout] *) | |
109 | val print_endline : string -> unit | |
110 | ||
111 | (** [prerr_endline str] outputs [str] to [stderr] followed by a newline then flushes | |
112 | [stderr] *) | |
113 | val prerr_endline : string -> unit | |
114 | ||
115 | val seek : t -> int64 -> unit | |
116 | val pos : t -> int64 | |
117 | val length : t -> int64 | |
118 | ||
119 | (** The first argument of these is the file name to write to. *) | |
120 | val write_lines : string -> string list -> unit | |
121 | val write_all : string -> data:string -> unit | |
122 | ||
123 | ||
124 |
0 | open! Base | |
1 | open! Import | |
2 | ||
3 | module In_channel = In_channel | |
4 | module Out_channel = Out_channel | |
5 | ||
6 | let stdin = In_channel.stdin | |
7 | let stdout = Out_channel.stdout | |
8 | let stderr = Out_channel.stderr | |
9 | ||
10 | let eprintf = Out_channel.eprintf | |
11 | let printf = Out_channel.printf | |
12 | let print_s = Out_channel.print_s | |
13 | let print_string = Out_channel.print_string | |
14 | let print_endline = Out_channel.print_endline | |
15 | let prerr_endline = Out_channel.prerr_endline |
0 | {1 Stdio: Standard IO Library for OCaml} | |
1 | ||
2 | Stdio provides input/output functions for OCaml. It re-exports the | |
3 | buffered channels of the stdlib distributed with OCaml but with some | |
4 | improvements. | |
5 | ||
6 | The full API is browsable {{!Stdio}{b here}}. |
0 | open! Base | |
1 | open! Import | |
2 | ||
3 | module In_channel = In_channel | |
4 | module Out_channel = Out_channel | |
5 | ||
6 | (** Same as {!In_channel.stdin} *) | |
7 | val stdin : In_channel.t | |
8 | ||
9 | (** Same as {!Out_channel.stdout} *) | |
10 | val stdout : Out_channel.t | |
11 | ||
12 | (** Same as {!Out_channel.stderr} *) | |
13 | val stderr : Out_channel.t | |
14 | ||
15 | (** Same as {!Out_channel.printf} *) | |
16 | val printf : ('a, Out_channel.t, unit) format -> 'a | |
17 | ||
18 | (** Same as {!Out_channel.print_s} *) | |
19 | val print_s : ?mach : unit -> Sexp.t -> unit | |
20 | ||
21 | (** Same as {!Out_channel.eprintf} *) | |
22 | val eprintf : ('a, Out_channel.t, unit) format -> 'a | |
23 | ||
24 | (** Same as {!Out_channel.print_string} *) | |
25 | val print_string : string -> unit | |
26 | ||
27 | (** Same as {!Out_channel.print_endline} *) | |
28 | val print_endline : string -> unit | |
29 | ||
30 | (** Same as {!Out_channel.prerr_endline} *) | |
31 | val prerr_endline : string -> unit |
0 | opam-version: "2.0" | |
1 | version: "v0.12.0" | |
2 | maintainer: "opensource@janestreet.com" | |
3 | authors: ["Jane Street Group, LLC <opensource@janestreet.com>"] | |
4 | homepage: "https://github.com/janestreet/stdio" | |
5 | bug-reports: "https://github.com/janestreet/stdio/issues" | |
6 | dev-repo: "git+https://github.com/janestreet/stdio.git" | |
7 | doc: "https://ocaml.janestreet.com/ocaml-core/latest/doc/stdio/index.html" | |
8 | license: "MIT" | |
9 | build: [ | |
10 | ["dune" "build" "-p" name "-j" jobs] | |
11 | ] | |
12 | depends: [ | |
13 | "ocaml" {>= "4.04.2"} | |
14 | "base" {>= "v0.12" & < "v0.13"} | |
15 | "dune" {build & >= "1.5.1"} | |
16 | ] | |
17 | synopsis: "Standard IO library for OCaml" | |
18 | description: " | |
19 | Stdio implements simple input/output functionalities for OCaml. | |
20 | ||
21 | It re-exports the input/output functions of the OCaml standard | |
22 | libraries using a more consistent API. | |
23 | " |