mt-lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
data/std/str.mt
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import std.mem.arena as arena
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
public function cstr_len(text: cstr) -> ptr_uint:
|
|
5
|
+
var count: ptr_uint = 0
|
|
6
|
+
unsafe:
|
|
7
|
+
let data = ptr[char]<-text
|
|
8
|
+
while read(data + count) != zero[char]:
|
|
9
|
+
count += 1
|
|
10
|
+
return count
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
public function cstr_as_str(text: cstr) -> str:
|
|
14
|
+
return unsafe: str(data = ptr[char]<-text, len = cstr_len(text))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
public function chars_as_str(text: ptr[char]) -> str:
|
|
18
|
+
return unsafe: str(data = text, len = cstr_len(cstr<-text))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
public function nullable_cstr_as_str(text: cstr?) -> Option[str]:
|
|
22
|
+
if text == null:
|
|
23
|
+
return Option[str].none
|
|
24
|
+
|
|
25
|
+
return Option[str].some(value= cstr_as_str(text))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
public function as_byte_span(text: str) -> span[ubyte]:
|
|
29
|
+
return unsafe: span[ubyte](data = ptr[ubyte]<-text.data, len = text.len)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
public function utf8_byte_span_as_str(bytes: span[ubyte]) -> Option[str]:
|
|
33
|
+
unsafe:
|
|
34
|
+
let borrowed = str(data = ptr[char]<-bytes.data, len = bytes.len)
|
|
35
|
+
if not borrowed.is_valid_utf8():
|
|
36
|
+
return Option[str].none
|
|
37
|
+
|
|
38
|
+
return Option[str].some(value= borrowed)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
public function utf8_continuation_byte(value: ubyte) -> bool:
|
|
42
|
+
return (value & 0xC0) == 0x80
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
function utf8_boundary(text: str, index: ptr_uint) -> bool:
|
|
46
|
+
if index == 0 or index == text.len:
|
|
47
|
+
return true
|
|
48
|
+
|
|
49
|
+
unsafe:
|
|
50
|
+
let value = ubyte<-read(text.data + index)
|
|
51
|
+
return not utf8_continuation_byte(value)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
function is_ascii_space(value: ubyte) -> bool:
|
|
55
|
+
return value == 32 or value == 9 or value == 10 or value == 13 or value == 12
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
extending str:
|
|
59
|
+
public function byte_at(index: ptr_uint) -> ubyte:
|
|
60
|
+
if index >= this.len:
|
|
61
|
+
fatal(c"str.byte_at index out of bounds")
|
|
62
|
+
|
|
63
|
+
return unsafe: ubyte<-read(this.data + index)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
public function equal(right: str) -> bool:
|
|
67
|
+
if this.len != right.len:
|
|
68
|
+
return false
|
|
69
|
+
|
|
70
|
+
var index: ptr_uint = 0
|
|
71
|
+
while index < this.len:
|
|
72
|
+
if this.byte_at(index) != right.byte_at(index):
|
|
73
|
+
return false
|
|
74
|
+
index += 1
|
|
75
|
+
return true
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
public function starts_with(prefix: str) -> bool:
|
|
79
|
+
if prefix.len > this.len:
|
|
80
|
+
return false
|
|
81
|
+
|
|
82
|
+
var index: ptr_uint = 0
|
|
83
|
+
while index < prefix.len:
|
|
84
|
+
if this.byte_at(index) != prefix.byte_at(index):
|
|
85
|
+
return false
|
|
86
|
+
index += 1
|
|
87
|
+
return true
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
public function ends_with(suffix: str) -> bool:
|
|
91
|
+
if suffix.len > this.len:
|
|
92
|
+
return false
|
|
93
|
+
|
|
94
|
+
let offset = this.len - suffix.len
|
|
95
|
+
var index: ptr_uint = 0
|
|
96
|
+
while index < suffix.len:
|
|
97
|
+
if this.byte_at(offset + index) != suffix.byte_at(index):
|
|
98
|
+
return false
|
|
99
|
+
index += 1
|
|
100
|
+
return true
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
public function find_byte(value: ubyte) -> Option[ptr_uint]:
|
|
104
|
+
var index: ptr_uint = 0
|
|
105
|
+
while index < this.len:
|
|
106
|
+
if this.byte_at(index) == value:
|
|
107
|
+
return Option[ptr_uint].some(value= index)
|
|
108
|
+
index += 1
|
|
109
|
+
return Option[ptr_uint].none
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
public function trim_ascii_whitespace() -> str:
|
|
113
|
+
var start: ptr_uint = 0
|
|
114
|
+
while start < this.len and is_ascii_space(this.byte_at(start)):
|
|
115
|
+
start += 1
|
|
116
|
+
|
|
117
|
+
var stop = this.len
|
|
118
|
+
while stop > start and is_ascii_space(this.byte_at(stop - 1)):
|
|
119
|
+
stop -= 1
|
|
120
|
+
|
|
121
|
+
return unsafe: str(data = this.data + start, len = stop - start)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
public function is_valid_utf8() -> bool:
|
|
125
|
+
var index: ptr_uint = 0
|
|
126
|
+
while index < this.len:
|
|
127
|
+
let first = this.byte_at(index)
|
|
128
|
+
if first < 0x80:
|
|
129
|
+
index += 1
|
|
130
|
+
else if first >= 0xC2 and first <= 0xDF:
|
|
131
|
+
if index + 1 >= this.len or not utf8_continuation_byte(this.byte_at(index + 1)):
|
|
132
|
+
return false
|
|
133
|
+
index += 2
|
|
134
|
+
else if first == 0xE0:
|
|
135
|
+
if index + 2 >= this.len:
|
|
136
|
+
return false
|
|
137
|
+
let second = this.byte_at(index + 1)
|
|
138
|
+
if second < 0xA0 or second > 0xBF or not utf8_continuation_byte(this.byte_at(index + 2)):
|
|
139
|
+
return false
|
|
140
|
+
index += 3
|
|
141
|
+
else if first >= 0xE1 and first <= 0xEC:
|
|
142
|
+
if (
|
|
143
|
+
index + 2 >= this.len
|
|
144
|
+
or not utf8_continuation_byte(this.byte_at(index + 1))
|
|
145
|
+
or not utf8_continuation_byte(this.byte_at(index + 2))
|
|
146
|
+
):
|
|
147
|
+
return false
|
|
148
|
+
index += 3
|
|
149
|
+
else if first == 0xED:
|
|
150
|
+
if index + 2 >= this.len:
|
|
151
|
+
return false
|
|
152
|
+
let second = this.byte_at(index + 1)
|
|
153
|
+
if second < 0x80 or second > 0x9F or not utf8_continuation_byte(this.byte_at(index + 2)):
|
|
154
|
+
return false
|
|
155
|
+
index += 3
|
|
156
|
+
else if first >= 0xEE and first <= 0xEF:
|
|
157
|
+
if (
|
|
158
|
+
index + 2 >= this.len
|
|
159
|
+
or not utf8_continuation_byte(this.byte_at(index + 1))
|
|
160
|
+
or not utf8_continuation_byte(this.byte_at(index + 2))
|
|
161
|
+
):
|
|
162
|
+
return false
|
|
163
|
+
index += 3
|
|
164
|
+
else if first == 0xF0:
|
|
165
|
+
if index + 3 >= this.len:
|
|
166
|
+
return false
|
|
167
|
+
let second = this.byte_at(index + 1)
|
|
168
|
+
if (
|
|
169
|
+
second < 0x90
|
|
170
|
+
or second > 0xBF
|
|
171
|
+
or not utf8_continuation_byte(this.byte_at(index + 2))
|
|
172
|
+
or not utf8_continuation_byte(this.byte_at(index + 3))
|
|
173
|
+
):
|
|
174
|
+
return false
|
|
175
|
+
index += 4
|
|
176
|
+
else if first >= 0xF1 and first <= 0xF3:
|
|
177
|
+
if (
|
|
178
|
+
index + 3 >= this.len
|
|
179
|
+
or not utf8_continuation_byte(this.byte_at(index + 1))
|
|
180
|
+
or not utf8_continuation_byte(this.byte_at(index + 2))
|
|
181
|
+
or not utf8_continuation_byte(this.byte_at(index + 3))
|
|
182
|
+
):
|
|
183
|
+
return false
|
|
184
|
+
index += 4
|
|
185
|
+
else if first == 0xF4:
|
|
186
|
+
if index + 3 >= this.len:
|
|
187
|
+
return false
|
|
188
|
+
let second = this.byte_at(index + 1)
|
|
189
|
+
if (
|
|
190
|
+
second < 0x80
|
|
191
|
+
or second > 0x8F
|
|
192
|
+
or not utf8_continuation_byte(this.byte_at(index + 2))
|
|
193
|
+
or not utf8_continuation_byte(this.byte_at(index + 3))
|
|
194
|
+
):
|
|
195
|
+
return false
|
|
196
|
+
index += 4
|
|
197
|
+
else:
|
|
198
|
+
return false
|
|
199
|
+
|
|
200
|
+
return true
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
public function slice(start: ptr_uint, len: ptr_uint) -> str:
|
|
204
|
+
if start > this.len:
|
|
205
|
+
fatal(c"str slice start out of bounds")
|
|
206
|
+
if len > this.len - start:
|
|
207
|
+
fatal(c"str slice length out of bounds")
|
|
208
|
+
|
|
209
|
+
if not utf8_boundary(this, start):
|
|
210
|
+
fatal(c"str slice start must be a UTF-8 boundary")
|
|
211
|
+
var actual_stop = start + len
|
|
212
|
+
if not utf8_boundary(this, actual_stop):
|
|
213
|
+
fatal(c"str slice end must be a UTF-8 boundary")
|
|
214
|
+
|
|
215
|
+
return unsafe: str(data = this.data + start, len = actual_stop - start)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
public function find_substring(needle: str) -> Option[ptr_uint]:
|
|
219
|
+
if needle.len == 0:
|
|
220
|
+
return Option[ptr_uint].some(value= 0)
|
|
221
|
+
if needle.len > this.len:
|
|
222
|
+
return Option[ptr_uint].none
|
|
223
|
+
|
|
224
|
+
let limit = this.len - needle.len
|
|
225
|
+
var offset: ptr_uint = 0
|
|
226
|
+
while offset <= limit:
|
|
227
|
+
var matched = true
|
|
228
|
+
var index: ptr_uint = 0
|
|
229
|
+
while index < needle.len:
|
|
230
|
+
if this.byte_at(offset + index) != needle.byte_at(index):
|
|
231
|
+
matched = false
|
|
232
|
+
break
|
|
233
|
+
index += 1
|
|
234
|
+
if matched:
|
|
235
|
+
return Option[ptr_uint].some(value= offset)
|
|
236
|
+
offset += 1
|
|
237
|
+
|
|
238
|
+
return Option[ptr_uint].none
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
public function contains_substring(needle: str) -> bool:
|
|
242
|
+
return this.find_substring(needle).is_some()
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
public static function hash(value: const_ptr[str]) -> uint:
|
|
246
|
+
let fnv_offset: uint = 0x811C9DC5
|
|
247
|
+
let fnv_prime: uint = 0x01000193
|
|
248
|
+
|
|
249
|
+
var result = fnv_offset
|
|
250
|
+
unsafe:
|
|
251
|
+
let view = read(value)
|
|
252
|
+
var index: ptr_uint = 0
|
|
253
|
+
while index < view.len:
|
|
254
|
+
let byte_value = uint<-view.byte_at(index)
|
|
255
|
+
result = (result ^ byte_value) * fnv_prime
|
|
256
|
+
index += 1
|
|
257
|
+
return result
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
public static function equal(left: const_ptr[str], right: const_ptr[str]) -> bool:
|
|
261
|
+
unsafe:
|
|
262
|
+
return read(left).equal(read(right))
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
public static function order(left: const_ptr[str], right: const_ptr[str]) -> int:
|
|
266
|
+
unsafe:
|
|
267
|
+
let left_view = read(left)
|
|
268
|
+
let right_view = read(right)
|
|
269
|
+
var min_len = left_view.len
|
|
270
|
+
if right_view.len < min_len:
|
|
271
|
+
min_len = right_view.len
|
|
272
|
+
|
|
273
|
+
var index: ptr_uint = 0
|
|
274
|
+
while index < min_len:
|
|
275
|
+
let lb = int<-left_view.byte_at(index)
|
|
276
|
+
let rb = int<-right_view.byte_at(index)
|
|
277
|
+
if lb != rb:
|
|
278
|
+
return lb - rb
|
|
279
|
+
index += 1
|
|
280
|
+
|
|
281
|
+
let left_len = int<-left_view.len
|
|
282
|
+
let right_len = int<-right_view.len
|
|
283
|
+
return left_len - right_len
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
public function compare(right: str) -> int:
|
|
287
|
+
var left_copy: str = this
|
|
288
|
+
var right_copy: str = right
|
|
289
|
+
return str.order(ptr_of(left_copy), ptr_of(right_copy))
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
public function to_cstr(space: ref[arena.Arena]) -> cstr:
|
|
293
|
+
return space.to_cstr(this)
|
data/std/string.mt
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import std.str as text_ops
|
|
2
|
+
import std.mem.arena as arena
|
|
3
|
+
import std.mem.heap as heap
|
|
4
|
+
import std.vec as vec
|
|
5
|
+
|
|
6
|
+
public struct String:
|
|
7
|
+
data: ptr[ubyte]?
|
|
8
|
+
len: ptr_uint
|
|
9
|
+
capacity: ptr_uint
|
|
10
|
+
owns_storage: bool
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
extending String:
|
|
14
|
+
public static function create() -> String:
|
|
15
|
+
return String(data = null, len = 0, capacity = 0, owns_storage = true)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
public static function with_capacity(capacity: ptr_uint) -> String:
|
|
19
|
+
var result = String.create()
|
|
20
|
+
result.reserve(capacity)
|
|
21
|
+
return result
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
public static function from_str(text: str) -> String:
|
|
25
|
+
var result = String.with_capacity(text.len)
|
|
26
|
+
result.append(text)
|
|
27
|
+
return result
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
public function len() -> ptr_uint:
|
|
31
|
+
return this.len
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
public function capacity() -> ptr_uint:
|
|
35
|
+
return this.capacity
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
public function is_empty() -> bool:
|
|
39
|
+
return this.len == 0
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
public function equal(other: String) -> bool:
|
|
43
|
+
return this.as_str().equal(other.as_str())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
public editable function clear() -> void:
|
|
47
|
+
this.len = 0
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
public editable function truncate(new_len: ptr_uint) -> void:
|
|
51
|
+
if new_len > this.len:
|
|
52
|
+
fatal(c"string.truncate new length exceeds current length")
|
|
53
|
+
this.len = new_len
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
public editable function release() -> void:
|
|
57
|
+
if this.owns_storage:
|
|
58
|
+
heap.release(this.data)
|
|
59
|
+
|
|
60
|
+
this.data = null
|
|
61
|
+
this.len = 0
|
|
62
|
+
this.capacity = 0
|
|
63
|
+
this.owns_storage = true
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
public static function hash(value: const_ptr[String]) -> uint:
|
|
67
|
+
let fnv_offset: uint = 0x811C9DC5
|
|
68
|
+
let fnv_prime: uint = 0x01000193
|
|
69
|
+
|
|
70
|
+
unsafe:
|
|
71
|
+
let view = read(value)
|
|
72
|
+
var result = fnv_offset
|
|
73
|
+
let raw = view.as_str()
|
|
74
|
+
var index: ptr_uint = 0
|
|
75
|
+
while index < raw.len:
|
|
76
|
+
let byte_value = uint<-raw.byte_at(index)
|
|
77
|
+
result = (result ^ byte_value) * fnv_prime
|
|
78
|
+
index += 1
|
|
79
|
+
return result
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
public static function equal(left: const_ptr[String], right: const_ptr[String]) -> bool:
|
|
83
|
+
unsafe:
|
|
84
|
+
let left_view = read(left)
|
|
85
|
+
let right_view = read(right)
|
|
86
|
+
return left_view.as_str().equal(right_view.as_str())
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
public static function order(left: const_ptr[String], right: const_ptr[String]) -> int:
|
|
90
|
+
unsafe:
|
|
91
|
+
let left_view = read(left)
|
|
92
|
+
let right_view = read(right)
|
|
93
|
+
return left_view.as_str().compare(right_view.as_str())
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
public function starts_with(prefix: str) -> bool:
|
|
97
|
+
return this.as_str().starts_with(prefix)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
public function ends_with(suffix: str) -> bool:
|
|
101
|
+
return this.as_str().ends_with(suffix)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
public function find_substring(needle: str) -> Option[ptr_uint]:
|
|
105
|
+
return this.as_str().find_substring(needle)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
public function contains_substring(needle: str) -> bool:
|
|
109
|
+
return this.as_str().contains_substring(needle)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
public editable function reserve(min_capacity: ptr_uint) -> void:
|
|
113
|
+
if min_capacity <= this.capacity:
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
if not this.owns_storage:
|
|
117
|
+
fatal(c"string.reserve cannot grow borrowed storage")
|
|
118
|
+
|
|
119
|
+
var new_capacity = this.capacity
|
|
120
|
+
if new_capacity == 0:
|
|
121
|
+
new_capacity = 4
|
|
122
|
+
|
|
123
|
+
while new_capacity < min_capacity:
|
|
124
|
+
if new_capacity > heap.ptr_uint_max / 2:
|
|
125
|
+
new_capacity = min_capacity
|
|
126
|
+
else:
|
|
127
|
+
new_capacity *= 2
|
|
128
|
+
|
|
129
|
+
let resized = heap.resize[ubyte](this.data, new_capacity) else:
|
|
130
|
+
fatal(c"string.reserve out of memory")
|
|
131
|
+
|
|
132
|
+
this.data = resized
|
|
133
|
+
this.capacity = new_capacity
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
public editable function push_byte(value: ubyte) -> void:
|
|
137
|
+
if this.len == this.capacity:
|
|
138
|
+
this.reserve(this.len + 1)
|
|
139
|
+
|
|
140
|
+
let data = this.data else:
|
|
141
|
+
fatal(c"string.push_byte missing storage")
|
|
142
|
+
|
|
143
|
+
unsafe:
|
|
144
|
+
let data_ptr = data
|
|
145
|
+
read(data_ptr + this.len) = value
|
|
146
|
+
this.len += 1
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
public editable function append(suffix: str) -> void:
|
|
150
|
+
if suffix.len == 0:
|
|
151
|
+
return
|
|
152
|
+
|
|
153
|
+
let current_len = this.len
|
|
154
|
+
if suffix.len > heap.ptr_uint_max - current_len:
|
|
155
|
+
fatal(c"string.append size overflow")
|
|
156
|
+
|
|
157
|
+
let new_len = current_len + suffix.len
|
|
158
|
+
let needs_growth = new_len > this.capacity
|
|
159
|
+
|
|
160
|
+
var copied: ptr[ubyte]? = null
|
|
161
|
+
if needs_growth:
|
|
162
|
+
copied = heap.must_alloc[ubyte](suffix.len)
|
|
163
|
+
unsafe: heap.copy_bytes(copied, ptr[ubyte]<-suffix.data, suffix.len)
|
|
164
|
+
|
|
165
|
+
this.reserve(new_len)
|
|
166
|
+
|
|
167
|
+
let data = this.data else:
|
|
168
|
+
fatal(c"string.append missing storage")
|
|
169
|
+
|
|
170
|
+
unsafe:
|
|
171
|
+
let destination = data + current_len
|
|
172
|
+
if copied != null:
|
|
173
|
+
heap.copy_bytes(destination, copied, suffix.len)
|
|
174
|
+
heap.release(copied)
|
|
175
|
+
else:
|
|
176
|
+
heap.copy_bytes(destination, ptr[ubyte]<-suffix.data, suffix.len)
|
|
177
|
+
|
|
178
|
+
this.len = new_len
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
public editable function append_format(text: str) -> void:
|
|
182
|
+
this.append(text)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
public editable function assign(value_text: str) -> void:
|
|
186
|
+
this.clear()
|
|
187
|
+
this.append(value_text)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
public editable function assign_format(text: str) -> void:
|
|
191
|
+
this.assign(text)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
public function as_str() -> str:
|
|
195
|
+
let data = this.data
|
|
196
|
+
if data == null and this.len != 0:
|
|
197
|
+
fatal(c"string.as_str requires storage when len > 0")
|
|
198
|
+
|
|
199
|
+
let borrowed = unsafe: str(data = ptr[char]<-data, len = this.len)
|
|
200
|
+
if not borrowed.is_valid_utf8():
|
|
201
|
+
fatal(c"string.as_str text must be valid UTF-8")
|
|
202
|
+
|
|
203
|
+
return borrowed
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
public function to_cstr(space: ref[arena.Arena]) -> cstr:
|
|
207
|
+
return space.to_cstr(this.as_str())
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
public function split(separator: str) -> vec.Vec[String]:
|
|
211
|
+
var result = vec.Vec[String].create()
|
|
212
|
+
var remaining = this.as_str()
|
|
213
|
+
while true:
|
|
214
|
+
let found = remaining.find_substring(separator)
|
|
215
|
+
let idx = found else:
|
|
216
|
+
break
|
|
217
|
+
result.push(String.from_str(remaining.slice(0, idx)))
|
|
218
|
+
remaining = remaining.slice(idx + separator.len, remaining.len - idx - separator.len)
|
|
219
|
+
result.push(String.from_str(remaining))
|
|
220
|
+
return result
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
public function replace(old_substr: str, new_substr: str) -> String:
|
|
224
|
+
var result = String.create()
|
|
225
|
+
var remaining = this.as_str()
|
|
226
|
+
while true:
|
|
227
|
+
let found = remaining.find_substring(old_substr)
|
|
228
|
+
let idx = found else:
|
|
229
|
+
break
|
|
230
|
+
result.append(remaining.slice(0, idx))
|
|
231
|
+
result.append(new_substr)
|
|
232
|
+
remaining = remaining.slice(idx + old_substr.len, remaining.len - idx - old_substr.len)
|
|
233
|
+
result.append(remaining)
|
|
234
|
+
return result
|