forked from rescript-lang/rescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcaml_string.ml
More file actions
155 lines (125 loc) · 4.41 KB
/
Copy pathcaml_string.ml
File metadata and controls
155 lines (125 loc) · 4.41 KB
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
144
145
146
147
148
149
150
151
152
153
(* 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 *)
external append : string -> string -> string = "js_string_append"
external array_append : 'a array -> 'a array -> 'a array = "js_array_append"
external string_of_small_int_array : int array -> string = "js_string_of_small_int_array"
external bytes_to_int_array : bytes -> int array = "%identity"
external bytes_of_int_array : int array -> bytes = "%identity"
external new_uninitialized_bytes : int -> bytes = "js_create_array"
let add = 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 new_uninitialized_bytes 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 = new_uninitialized_bytes 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
string_of_small_int_array (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 = new_uninitialized_bytes next in
let () = caml_blit_bytes bytes !offset tmp_bytes 0 next in
s := append !s (string_of_small_int_array (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 = new_uninitialized_bytes 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