Skip to content

Commit b02767f

Browse files
committed
Add missing Stdlib functions for older OCaml versions
1 parent 08b118c commit b02767f

File tree

2 files changed

+117
-1
lines changed

2 files changed

+117
-1
lines changed

compiler/lib/link_js.ml

+8-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@ end = struct
5656

5757
let open_ fname =
5858
let lines =
59-
In_channel.input_all (open_in_bin fname) |> String.split_on_char ~sep:'\n'
59+
(* If we are not on 32-bit hardware (where the max string length is too
60+
small), read the entire file and split it in lines. This is faster
61+
than reading it line by line. On 32 bits, we fall back to a
62+
line-by-line read. *)
63+
if Sys.word_size >= 64 then
64+
In_channel.input_all (open_in_bin fname) |> String.split_on_char ~sep:'\n'
65+
else
66+
In_channel.input_lines (open_in_bin fname)
6067
in
6168
{ lines; lnum = 0; fname; current = lines }
6269

compiler/lib/stdlib.ml

+109
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,115 @@ module Fun = struct
12261226
r
12271227
end
12281228

1229+
module In_channel = struct
1230+
include In_channel
1231+
[@@if ocaml_version >= (4, 14, 0)]
1232+
1233+
(* Read up to [len] bytes into [buf], starting at [ofs]. Return total bytes
1234+
read. *)
1235+
let read_upto ic buf ofs len =
1236+
let rec loop ofs len =
1237+
if len = 0 then ofs
1238+
else begin
1239+
let r = input ic buf ofs len in
1240+
if r = 0 then
1241+
ofs
1242+
else
1243+
loop (ofs + r) (len - r)
1244+
end
1245+
in
1246+
loop ofs len - ofs
1247+
[@@if ocaml_version < (4, 14, 0)]
1248+
1249+
(* Best effort attempt to return a buffer with >= (ofs + n) bytes of storage,
1250+
and such that it coincides with [buf] at indices < [ofs].
1251+
1252+
The returned buffer is equal to [buf] itself if it already has sufficient
1253+
free space.
1254+
1255+
The returned buffer may have *fewer* than [ofs + n] bytes of storage if this
1256+
number is > [Sys.max_string_length]. However the returned buffer will
1257+
*always* have > [ofs] bytes of storage. In the limiting case when [ofs = len
1258+
= Sys.max_string_length] (so that it is not possible to resize the buffer at
1259+
all), an exception is raised. *)
1260+
1261+
let ensure buf ofs n =
1262+
let len = Bytes.length buf in
1263+
if len >= ofs + n then buf
1264+
else begin
1265+
let new_len = ref len in
1266+
while !new_len < ofs + n do
1267+
new_len := 2 * !new_len + 1
1268+
done;
1269+
let new_len = !new_len in
1270+
let new_len =
1271+
if new_len <= Sys.max_string_length then
1272+
new_len
1273+
else if ofs < Sys.max_string_length then
1274+
Sys.max_string_length
1275+
else
1276+
failwith "In_channel.input_all: channel content \
1277+
is larger than maximum string length"
1278+
in
1279+
let new_buf = Bytes.create new_len in
1280+
Bytes.blit ~src:buf ~src_pos:0 ~dst:new_buf ~dst_pos:0 ~len:ofs;
1281+
new_buf
1282+
end
1283+
[@@if ocaml_version < (4, 14, 0)]
1284+
1285+
let input_all ic =
1286+
let chunk_size = 65536 in (* IO_BUFFER_SIZE *)
1287+
let initial_size =
1288+
try
1289+
in_channel_length ic - pos_in ic
1290+
with Sys_error _ ->
1291+
-1
1292+
in
1293+
let initial_size = if initial_size < 0 then chunk_size else initial_size in
1294+
let initial_size =
1295+
if initial_size <= Sys.max_string_length then
1296+
initial_size
1297+
else
1298+
Sys.max_string_length
1299+
in
1300+
let buf = Bytes.create initial_size in
1301+
let nread = read_upto ic buf 0 initial_size in
1302+
if nread < initial_size then (* EOF reached, buffer partially filled *)
1303+
Bytes.sub_string buf ~pos:0 ~len:nread
1304+
else begin (* nread = initial_size, maybe EOF reached *)
1305+
match input_char ic with
1306+
| exception End_of_file ->
1307+
(* EOF reached, buffer is completely filled *)
1308+
Bytes.unsafe_to_string buf
1309+
| c ->
1310+
(* EOF not reached *)
1311+
let rec loop buf ofs =
1312+
let buf = ensure buf ofs chunk_size in
1313+
let rem = Bytes.length buf - ofs in
1314+
(* [rem] can be < [chunk_size] if buffer size close to
1315+
[Sys.max_string_length] *)
1316+
let r = read_upto ic buf ofs rem in
1317+
if r < rem then (* EOF reached *)
1318+
Bytes.sub_string buf ~pos:0 ~len:(ofs + r)
1319+
else (* r = rem *)
1320+
loop buf (ofs + rem)
1321+
in
1322+
let buf = ensure buf nread (chunk_size + 1) in
1323+
Bytes.set buf nread c;
1324+
loop buf (nread + 1)
1325+
end
1326+
[@@if ocaml_version < (4, 14, 0)]
1327+
1328+
let input_lines ic =
1329+
let rec aux acc =
1330+
match input_line ic with
1331+
| line -> aux (line :: acc)
1332+
| exception End_of_file -> acc
1333+
in
1334+
List.rev (aux [])
1335+
[@@if ocaml_version < (4, 14, 0)]
1336+
end
1337+
12291338
let generated_name = function
12301339
| "param" | "match" | "switcher" -> true
12311340
| s -> String.is_prefix ~prefix:"cst_" s

0 commit comments

Comments
 (0)