forked from rescript-lang/rescript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcaml_string.ml
145 lines (120 loc) · 4.07 KB
/
caml_string.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
(* BuckleScript compiler
* Copyright (C) 2015-2016 Bloomberg Finance L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)
(* Author: Hongbo Zhang *)
let string_of_char = Js.String.of_char
let add = Js.String.append
let caml_string_get s i=
if i >= String.length s || i < 0 then
raise (Invalid_argument "index out of bounds")
else String.unsafe_get s i
let caml_create_string len : bytes =
(* Node raise [RangeError] exception *)
if len < 0 then raise (Invalid_argument "String.create")
else Js.Bytes.new_uninitialized len
let caml_string_compare (s1 : string) (s2 : string) : int =
if s1 = s2 then 0
else if s1 < s2 then -1
else 1
let caml_fill_string (s : bytes) i l (c : char) =
if l > 0 then
for k = i to l + i - 1 do
Bytes.unsafe_set s k c
done
(**
TODO: [min] is not type specialized in OCaml
*)
let caml_blit_string s1 i1 s2 i2 (len : int ) =
if len > 0 then
let off1 = String.length s1 - i1 in
if len <= off1 then
for i = 0 to len - 1 do
Bytes.unsafe_set s2 (i2 + i) s1.[i1 + i]
done
else
begin
for i = 0 to off1 - 1 do
Bytes.unsafe_set s2 (i2 + i) s1.[i1 + i]
done;
for i = off1 to len - 1 do
Bytes.unsafe_set s2 (i2 + i) '\000'
done
end
(* TODO: when the compiler could optimize small function calls,
use high order functions instead
*)
let caml_blit_bytes s1 i1 s2 i2 len =
if len > 0 then
let off1 = Bytes.length s1 - i1 in
if len <= off1 then
for i = 0 to len - 1 do
Bytes.unsafe_set s2 (i2 + i) (Bytes.unsafe_get s1 (i1 + i))
done
else
begin
for i = 0 to off1 - 1 do
Bytes.unsafe_set s2 (i2 + i) (Bytes.unsafe_get s1 (i1 + i))
done;
for i = off1 to len - 1 do
Bytes.unsafe_set s2 (i2 + i) '\000'
done
end
(** checkout [Bytes.empty] -- to be inlined? *)
let bytes_of_string s =
let len = String.length s in
let res = Js.Bytes.new_uninitialized len in
for i = 0 to len - 1 do
Bytes.unsafe_set res i s.[i]
(* Note that when get a char and convert it to int immedately, should be optimized
should be [s.charCodeAt[i]]
*)
done;
res
let string_of_large_bytes bytes i len =
let s = ref "" in
let s_len = ref len in
let seg = 1024 in
if i = 0 && len <= 4 * seg && len = Bytes.length bytes then
Js.String.of_small_int_array (Js.Bytes.to_int_array bytes)
else
begin
let offset = ref 0 in
while !s_len > 0 do
let next = if !s_len < 1024 then !s_len else seg in
let tmp_bytes = Js.Bytes.new_uninitialized next in
let () = caml_blit_bytes bytes !offset tmp_bytes 0 next in
s := Js.String.append !s (Js.String.of_small_int_array (Js.Bytes.to_int_array tmp_bytes));
s_len := !s_len - next ;
offset := !offset + next;
done;
!s
end
let bytes_to_string a =
string_of_large_bytes a 0 (Bytes.length a)
(** TODO: performance could be improved, however,
this function is not in critical Path
*)
let caml_string_of_char_array chars =
let len = Array.length chars in
let bytes = Js.Bytes.new_uninitialized len in
for i = 0 to len - 1 do
Bytes.unsafe_set bytes i chars.(i)
done;
bytes_to_string bytes
let caml_is_printable c =
let code = Char.code c in
code > 31 && code < 127