@shd101wyy/yo 0.1.26 → 0.1.27
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.
- package/.github/skills/yo-async-effects/SKILL.md +4 -4
- package/.github/skills/yo-async-effects/async-effects-recipes.md +34 -34
- package/.github/skills/yo-core-patterns/SKILL.md +1 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +26 -26
- package/.github/skills/yo-project-workflow/SKILL.md +6 -3
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
- package/.github/skills/yo-syntax/SKILL.md +7 -6
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +73 -60
- package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
- package/README.md +10 -8
- package/out/cjs/index.cjs +456 -438
- package/out/cjs/yo-cli.cjs +576 -543
- package/out/cjs/yo-lsp.cjs +559 -532
- package/out/esm/index.mjs +281 -263
- package/out/types/src/formatter.d.ts +11 -0
- package/out/types/src/lsp/formatting.d.ts +2 -0
- package/out/types/src/tests/formatter.test.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/alg/hash.yo +13 -21
- package/std/allocator.yo +25 -40
- package/std/async.yo +3 -7
- package/std/build.yo +105 -151
- package/std/cli/arg_parser.yo +184 -169
- package/std/collections/array_list.yo +350 -314
- package/std/collections/btree_map.yo +142 -131
- package/std/collections/deque.yo +132 -128
- package/std/collections/hash_map.yo +542 -566
- package/std/collections/hash_set.yo +623 -687
- package/std/collections/linked_list.yo +275 -293
- package/std/collections/ordered_map.yo +113 -85
- package/std/collections/priority_queue.yo +73 -73
- package/std/crypto/md5.yo +191 -95
- package/std/crypto/random.yo +56 -64
- package/std/crypto/sha256.yo +151 -107
- package/std/encoding/base64.yo +87 -81
- package/std/encoding/hex.yo +43 -50
- package/std/encoding/html.yo +56 -81
- package/std/encoding/html_char_utils.yo +7 -13
- package/std/encoding/html_entities.yo +2248 -2253
- package/std/encoding/json.yo +316 -224
- package/std/encoding/punycode.yo +86 -116
- package/std/encoding/toml.yo +67 -66
- package/std/encoding/utf16.yo +37 -44
- package/std/env.yo +62 -91
- package/std/error.yo +7 -15
- package/std/fmt/display.yo +5 -9
- package/std/fmt/index.yo +8 -14
- package/std/fmt/to_string.yo +330 -315
- package/std/fmt/writer.yo +58 -87
- package/std/fs/dir.yo +83 -102
- package/std/fs/file.yo +147 -180
- package/std/fs/metadata.yo +45 -78
- package/std/fs/temp.yo +55 -65
- package/std/fs/types.yo +27 -40
- package/std/fs/walker.yo +53 -68
- package/std/gc.yo +5 -8
- package/std/glob.yo +30 -43
- package/std/http/client.yo +107 -120
- package/std/http/http.yo +106 -96
- package/std/http/index.yo +4 -6
- package/std/imm/list.yo +88 -93
- package/std/imm/map.yo +528 -464
- package/std/imm/set.yo +52 -57
- package/std/imm/sorted_map.yo +340 -286
- package/std/imm/sorted_set.yo +57 -63
- package/std/imm/string.yo +404 -345
- package/std/imm/vec.yo +173 -181
- package/std/io/reader.yo +3 -6
- package/std/io/writer.yo +4 -8
- package/std/libc/assert.yo +5 -9
- package/std/libc/ctype.yo +32 -22
- package/std/libc/dirent.yo +26 -25
- package/std/libc/errno.yo +164 -90
- package/std/libc/fcntl.yo +52 -45
- package/std/libc/float.yo +66 -44
- package/std/libc/limits.yo +42 -33
- package/std/libc/math.yo +53 -82
- package/std/libc/signal.yo +72 -47
- package/std/libc/stdatomic.yo +217 -188
- package/std/libc/stdint.yo +5 -29
- package/std/libc/stdio.yo +5 -29
- package/std/libc/stdlib.yo +32 -39
- package/std/libc/string.yo +5 -23
- package/std/libc/sys/stat.yo +58 -56
- package/std/libc/time.yo +5 -19
- package/std/libc/unistd.yo +5 -20
- package/std/libc/wctype.yo +6 -9
- package/std/libc/windows.yo +26 -30
- package/std/log.yo +41 -55
- package/std/net/addr.yo +102 -97
- package/std/net/dns.yo +27 -28
- package/std/net/errors.yo +50 -49
- package/std/net/tcp.yo +113 -124
- package/std/net/udp.yo +55 -66
- package/std/os/env.yo +35 -33
- package/std/os/signal.yo +15 -25
- package/std/path.yo +276 -311
- package/std/prelude.yo +6304 -4315
- package/std/process/command.yo +87 -103
- package/std/process/index.yo +12 -31
- package/std/regex/compiler.yo +196 -95
- package/std/regex/flags.yo +58 -39
- package/std/regex/index.yo +157 -173
- package/std/regex/match.yo +20 -31
- package/std/regex/node.yo +134 -152
- package/std/regex/parser.yo +283 -259
- package/std/regex/unicode.yo +172 -202
- package/std/regex/vm.yo +155 -171
- package/std/string/index.yo +5 -7
- package/std/string/rune.yo +45 -55
- package/std/string/string.yo +937 -964
- package/std/string/string_builder.yo +94 -104
- package/std/string/unicode.yo +46 -64
- package/std/sync/channel.yo +72 -73
- package/std/sync/cond.yo +31 -36
- package/std/sync/mutex.yo +30 -32
- package/std/sync/once.yo +13 -16
- package/std/sync/rwlock.yo +26 -31
- package/std/sync/waitgroup.yo +20 -25
- package/std/sys/advise.yo +16 -24
- package/std/sys/bufio/buf_reader.yo +77 -93
- package/std/sys/bufio/buf_writer.yo +52 -65
- package/std/sys/clock.yo +4 -9
- package/std/sys/constants.yo +77 -61
- package/std/sys/copy.yo +4 -10
- package/std/sys/dir.yo +26 -43
- package/std/sys/dns.yo +41 -61
- package/std/sys/errors.yo +95 -103
- package/std/sys/events.yo +45 -57
- package/std/sys/externs.yo +319 -267
- package/std/sys/fallocate.yo +7 -11
- package/std/sys/fcntl.yo +14 -22
- package/std/sys/file.yo +26 -40
- package/std/sys/future.yo +5 -8
- package/std/sys/iov.yo +12 -25
- package/std/sys/lock.yo +12 -13
- package/std/sys/mmap.yo +38 -43
- package/std/sys/path.yo +3 -8
- package/std/sys/perm.yo +7 -21
- package/std/sys/pipe.yo +5 -12
- package/std/sys/process.yo +23 -29
- package/std/sys/seek.yo +10 -12
- package/std/sys/signal.yo +7 -13
- package/std/sys/signals.yo +52 -35
- package/std/sys/socket.yo +63 -58
- package/std/sys/socketpair.yo +3 -6
- package/std/sys/sockinfo.yo +11 -20
- package/std/sys/statfs.yo +11 -34
- package/std/sys/statx.yo +25 -52
- package/std/sys/sysinfo.yo +15 -20
- package/std/sys/tcp.yo +62 -92
- package/std/sys/temp.yo +5 -9
- package/std/sys/time.yo +5 -15
- package/std/sys/timer.yo +6 -11
- package/std/sys/tty.yo +10 -18
- package/std/sys/udp.yo +22 -39
- package/std/sys/umask.yo +3 -6
- package/std/sys/unix.yo +33 -52
- package/std/testing/bench.yo +49 -52
- package/std/thread.yo +10 -15
- package/std/time/datetime.yo +105 -89
- package/std/time/duration.yo +43 -56
- package/std/time/instant.yo +13 -18
- package/std/time/sleep.yo +5 -9
- package/std/url/index.yo +184 -209
- package/std/worker.yo +6 -10
package/std/imm/string.yo
CHANGED
|
@@ -2,450 +2,491 @@
|
|
|
2
2
|
//!
|
|
3
3
|
//! Uses atomic reference counting for safe sharing across threads.
|
|
4
4
|
//! All "modification" operations return a new string; the original is unchanged.
|
|
5
|
-
|
|
6
|
-
{ GlobalAllocator } :: import "../allocator.yo";
|
|
5
|
+
{ GlobalAllocator } :: import("../allocator.yo");
|
|
7
6
|
{ malloc, free } :: GlobalAllocator;
|
|
8
|
-
{ memcpy, memcmp } :: import
|
|
9
|
-
{ rune } :: import
|
|
10
|
-
std_string :: import
|
|
11
|
-
{ ToString } :: import
|
|
12
|
-
imm_list :: import
|
|
13
|
-
|
|
14
|
-
_min :: (fn(a: usize, b: usize) -> usize)(
|
|
7
|
+
{ memcpy, memcmp } :: import("../libc/string.yo");
|
|
8
|
+
{ rune } :: import("../string/rune.yo");
|
|
9
|
+
std_string :: import("../string");
|
|
10
|
+
{ ToString } :: import("../fmt/to_string.yo");
|
|
11
|
+
imm_list :: import("./list.yo");
|
|
12
|
+
_min :: (fn(a : usize, b : usize) -> usize)(
|
|
15
13
|
cond((a < b) => a, true => b)
|
|
16
14
|
);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
_alloc_bytes :: (fn(n : usize) -> *(u8))(
|
|
16
|
+
match(
|
|
17
|
+
malloc(n),
|
|
20
18
|
.Some(p) => *(u8)(p),
|
|
21
19
|
.None => panic("imm.String: allocation failed")
|
|
22
20
|
)
|
|
23
21
|
);
|
|
24
|
-
|
|
25
22
|
/// Immutable, thread-safe UTF-8 string.
|
|
26
23
|
///
|
|
27
24
|
/// Uses atomic RC — cheap to clone, safe to share across threads.
|
|
28
25
|
/// No mutable operations. All "modification" methods return a new String.
|
|
29
26
|
///
|
|
30
27
|
/// Empty strings are zero-allocation (null pointer, zero length).
|
|
31
|
-
String :: atomic
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
String :: atomic(
|
|
29
|
+
object(
|
|
30
|
+
_ptr : ?*(u8),
|
|
31
|
+
_len : usize,
|
|
32
|
+
_capacity : usize
|
|
33
|
+
)
|
|
35
34
|
);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
impl(
|
|
36
|
+
String,
|
|
37
|
+
Dispose(
|
|
38
|
+
dispose : (fn(self : Self) -> unit)({
|
|
39
|
+
match(
|
|
40
|
+
self._ptr,
|
|
41
|
+
.Some(p) => free(.Some(*(void)(p))),
|
|
42
|
+
.None => ()
|
|
43
|
+
);
|
|
44
|
+
})
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
impl(
|
|
48
|
+
String,
|
|
47
49
|
/// Create a new empty string (zero allocation).
|
|
48
50
|
new : (fn() -> Self)(
|
|
49
|
-
Self(_ptr
|
|
51
|
+
Self(_ptr :.None, _len : usize(0), _capacity : usize(0))
|
|
50
52
|
),
|
|
51
|
-
|
|
52
53
|
/// Create a string from a `str` slice (copies the bytes).
|
|
53
|
-
from : (fn(s: str) -> Self)({
|
|
54
|
+
from : (fn(s : str) -> Self)({
|
|
54
55
|
slen := s.len();
|
|
55
|
-
if(
|
|
56
|
-
return
|
|
56
|
+
if(slen == usize(0), {
|
|
57
|
+
return(Self(_ptr :.None, _len : usize(0), _capacity : usize(0)));
|
|
57
58
|
});
|
|
58
59
|
ptr := _alloc_bytes(slen);
|
|
59
60
|
memcpy(*(void)(ptr), *(void)(s.ptr()), slen);
|
|
60
|
-
return
|
|
61
|
+
return(Self(_ptr :.Some(ptr), _len : slen, _capacity : slen));
|
|
61
62
|
}),
|
|
62
|
-
|
|
63
63
|
/// Create a string from a standard (mutable) String by copying its bytes.
|
|
64
|
-
from_string : (fn(s: std_string.String) -> Self)({
|
|
64
|
+
from_string : (fn(s : std_string.String) -> Self)({
|
|
65
65
|
slen := s.bytes_len();
|
|
66
|
-
if(
|
|
67
|
-
return
|
|
66
|
+
if(slen == usize(0), {
|
|
67
|
+
return(Self(_ptr :.None, _len : usize(0), _capacity : usize(0)));
|
|
68
68
|
});
|
|
69
69
|
ptr := _alloc_bytes(slen);
|
|
70
70
|
(as_str : str) = s.as_str();
|
|
71
71
|
memcpy(*(void)(ptr), *(void)(as_str.ptr()), slen);
|
|
72
|
-
return
|
|
72
|
+
return(Self(_ptr :.Some(ptr), _len : slen, _capacity : slen));
|
|
73
73
|
}),
|
|
74
|
-
|
|
75
74
|
/// Byte length of the string.
|
|
76
|
-
bytes_len : (fn(self: Self) -> usize)(
|
|
75
|
+
bytes_len : (fn(self : Self) -> usize)(
|
|
77
76
|
self._len
|
|
78
77
|
),
|
|
79
|
-
|
|
80
78
|
/// Number of Unicode characters (runes) in the string.
|
|
81
|
-
len : (fn(self: Self) -> usize)({
|
|
82
|
-
if(
|
|
83
|
-
return
|
|
79
|
+
len : (fn(self : Self) -> usize)({
|
|
80
|
+
if(self._len == usize(0), {
|
|
81
|
+
return(usize(0));
|
|
84
82
|
});
|
|
85
83
|
count := usize(0);
|
|
86
84
|
i := usize(0);
|
|
87
|
-
match(
|
|
85
|
+
match(
|
|
86
|
+
self._ptr,
|
|
88
87
|
.None => (),
|
|
89
88
|
.Some(p) => {
|
|
90
|
-
while
|
|
89
|
+
while(i < self._len, i = (i + usize(1)), {
|
|
91
90
|
(b : u8) = (p &+ i).*;
|
|
92
|
-
if((
|
|
91
|
+
if((b & u8(0xC0)) != u8(0x80), {
|
|
93
92
|
count = (count + usize(1));
|
|
94
93
|
});
|
|
95
|
-
};
|
|
94
|
+
});
|
|
96
95
|
}
|
|
97
96
|
);
|
|
98
97
|
count
|
|
99
98
|
}),
|
|
100
|
-
|
|
101
99
|
/// Check if the string is empty.
|
|
102
|
-
is_empty : (fn(self: Self) -> bool)(
|
|
103
|
-
|
|
100
|
+
is_empty : (fn(self : Self) -> bool)(
|
|
101
|
+
self._len == usize(0)
|
|
104
102
|
),
|
|
105
|
-
|
|
106
103
|
/// Get a `str` view of the string's bytes (zero-copy borrow).
|
|
107
|
-
as_str : (fn(self: Self) -> str)(
|
|
108
|
-
match(
|
|
104
|
+
as_str : (fn(self : Self) -> str)(
|
|
105
|
+
match(
|
|
106
|
+
self._ptr,
|
|
109
107
|
.Some(p) => str.from_raw_parts(p, self._len),
|
|
110
108
|
.None => str.from_raw_parts(*(u8)(""), usize(0))
|
|
111
109
|
)
|
|
112
110
|
),
|
|
113
|
-
|
|
114
111
|
/// Get the byte at a given index, or `.None` if out of bounds.
|
|
115
|
-
byte_at : (fn(self: Self, index: usize) -> Option(u8))(
|
|
112
|
+
byte_at : (fn(self : Self, index : usize) -> Option(u8))(
|
|
116
113
|
cond(
|
|
117
|
-
(index >= self._len)
|
|
118
|
-
true => match(
|
|
119
|
-
.
|
|
120
|
-
.
|
|
114
|
+
(index >= self._len) =>.None,
|
|
115
|
+
true => match(
|
|
116
|
+
self._ptr,
|
|
117
|
+
.Some(p) =>.Some((p &+ index).*),
|
|
118
|
+
.None =>.None
|
|
121
119
|
)
|
|
122
120
|
)
|
|
123
121
|
),
|
|
124
|
-
|
|
125
122
|
/// Concatenate two strings, returning a new string.
|
|
126
123
|
/// Uses COW: if this string has a unique reference and enough capacity,
|
|
127
124
|
/// appends in-place.
|
|
128
|
-
concat : (fn(own(self): Self, other: Self) -> Self)({
|
|
129
|
-
if(
|
|
125
|
+
concat : (fn(own(self) : Self, other : Self) -> Self)({
|
|
126
|
+
if(self._len == usize(0), {
|
|
130
127
|
unsafe.drop(self);
|
|
131
|
-
return
|
|
128
|
+
return(other);
|
|
132
129
|
});
|
|
133
|
-
if(
|
|
134
|
-
return
|
|
130
|
+
if(other._len == usize(0), {
|
|
131
|
+
return(self);
|
|
135
132
|
});
|
|
136
133
|
new_len := (self._len + other._len);
|
|
137
|
-
if(
|
|
138
|
-
if(
|
|
139
|
-
match(
|
|
140
|
-
.
|
|
141
|
-
|
|
134
|
+
if(rc(self) == usize(1), {
|
|
135
|
+
if(new_len <= self._capacity, {
|
|
136
|
+
match(
|
|
137
|
+
other._ptr,
|
|
138
|
+
.Some(op) => match(
|
|
139
|
+
self._ptr,
|
|
140
|
+
.Some(sp) => {
|
|
141
|
+
memcpy(*(void)(sp &+ self._len), *(void)(op), other._len);
|
|
142
|
+
},
|
|
142
143
|
.None => ()
|
|
143
144
|
),
|
|
144
145
|
.None => ()
|
|
145
146
|
);
|
|
146
147
|
self._len = new_len;
|
|
147
|
-
return
|
|
148
|
+
return(self);
|
|
148
149
|
});
|
|
149
150
|
new_cap := cond(
|
|
150
151
|
(new_len > (self._capacity * usize(2))) => new_len,
|
|
151
152
|
true => (self._capacity * usize(2))
|
|
152
153
|
);
|
|
153
154
|
ptr := _alloc_bytes(new_cap);
|
|
154
|
-
match(
|
|
155
|
-
|
|
155
|
+
match(
|
|
156
|
+
self._ptr,
|
|
157
|
+
.Some(sp) => {
|
|
158
|
+
memcpy(*(void)(ptr), *(void)(sp), self._len);
|
|
159
|
+
free(.Some(*(void)(sp)));
|
|
160
|
+
},
|
|
156
161
|
.None => ()
|
|
157
162
|
);
|
|
158
|
-
match(
|
|
159
|
-
|
|
163
|
+
match(
|
|
164
|
+
other._ptr,
|
|
165
|
+
.Some(op) => {
|
|
166
|
+
memcpy(*(void)(ptr &+ self._len), *(void)(op), other._len);
|
|
167
|
+
},
|
|
160
168
|
.None => ()
|
|
161
169
|
);
|
|
162
|
-
self._ptr
|
|
170
|
+
self._ptr =.Some(ptr);
|
|
163
171
|
self._len = new_len;
|
|
164
172
|
self._capacity = new_cap;
|
|
165
|
-
return
|
|
173
|
+
return(self);
|
|
166
174
|
});
|
|
167
175
|
ptr := _alloc_bytes(new_len);
|
|
168
|
-
match(
|
|
169
|
-
|
|
176
|
+
match(
|
|
177
|
+
self._ptr,
|
|
178
|
+
.Some(sp) => {
|
|
179
|
+
memcpy(*(void)(ptr), *(void)(sp), self._len);
|
|
180
|
+
},
|
|
170
181
|
.None => ()
|
|
171
182
|
);
|
|
172
|
-
match(
|
|
173
|
-
|
|
183
|
+
match(
|
|
184
|
+
other._ptr,
|
|
185
|
+
.Some(op) => {
|
|
186
|
+
memcpy(*(void)(ptr &+ self._len), *(void)(op), other._len);
|
|
187
|
+
},
|
|
174
188
|
.None => ()
|
|
175
189
|
);
|
|
176
190
|
unsafe.drop(self);
|
|
177
|
-
return
|
|
191
|
+
return(Self(_ptr :.Some(ptr), _len : new_len, _capacity : new_len));
|
|
178
192
|
}),
|
|
179
|
-
|
|
180
193
|
/// Extract a byte-range substring [start, end). Returns a new string.
|
|
181
194
|
/// If indices are out of bounds, clamps to valid range.
|
|
182
|
-
slice : (fn(self: Self, start: usize, end: usize) -> Self)({
|
|
195
|
+
slice : (fn(self : Self, start : usize, end : usize) -> Self)({
|
|
183
196
|
(clamped_start : usize) = _min(start, self._len);
|
|
184
197
|
(clamped_end : usize) = _min(end, self._len);
|
|
185
|
-
if(
|
|
186
|
-
return
|
|
198
|
+
if(clamped_start >= clamped_end, {
|
|
199
|
+
return(Self.new());
|
|
187
200
|
});
|
|
188
201
|
new_len := (clamped_end - clamped_start);
|
|
189
202
|
ptr := _alloc_bytes(new_len);
|
|
190
|
-
match(
|
|
191
|
-
.
|
|
203
|
+
match(
|
|
204
|
+
self._ptr,
|
|
205
|
+
.Some(sp) => {
|
|
206
|
+
memcpy(*(void)(ptr), *(void)(sp &+ clamped_start), new_len);
|
|
207
|
+
},
|
|
192
208
|
.None => ()
|
|
193
209
|
);
|
|
194
|
-
return
|
|
210
|
+
return(Self(_ptr :.Some(ptr), _len : new_len, _capacity : new_len));
|
|
195
211
|
}),
|
|
196
|
-
|
|
197
212
|
/// Check if the string starts with a given prefix.
|
|
198
|
-
starts_with : (fn(self: Self, prefix: Self) -> bool)({
|
|
199
|
-
if(
|
|
200
|
-
return
|
|
213
|
+
starts_with : (fn(self : Self, prefix : Self) -> bool)({
|
|
214
|
+
if(prefix._len > self._len, {
|
|
215
|
+
return(false);
|
|
201
216
|
});
|
|
202
|
-
if(
|
|
203
|
-
return
|
|
217
|
+
if(prefix._len == usize(0), {
|
|
218
|
+
return(true);
|
|
204
219
|
});
|
|
205
|
-
match(
|
|
206
|
-
.
|
|
220
|
+
match(
|
|
221
|
+
self._ptr,
|
|
222
|
+
.Some(sp) => match(
|
|
223
|
+
prefix._ptr,
|
|
207
224
|
.Some(pp) => (memcmp(*(void)(sp), *(void)(pp), prefix._len) == int(0)),
|
|
208
225
|
.None => true
|
|
209
226
|
),
|
|
210
227
|
.None => (prefix._len == usize(0))
|
|
211
228
|
)
|
|
212
229
|
}),
|
|
213
|
-
|
|
214
230
|
/// Check if the string ends with a given suffix.
|
|
215
|
-
ends_with : (fn(self: Self, suffix: Self) -> bool)({
|
|
216
|
-
if(
|
|
217
|
-
return
|
|
231
|
+
ends_with : (fn(self : Self, suffix : Self) -> bool)({
|
|
232
|
+
if(suffix._len > self._len, {
|
|
233
|
+
return(false);
|
|
218
234
|
});
|
|
219
|
-
if(
|
|
220
|
-
return
|
|
235
|
+
if(suffix._len == usize(0), {
|
|
236
|
+
return(true);
|
|
221
237
|
});
|
|
222
238
|
offset := (self._len - suffix._len);
|
|
223
|
-
match(
|
|
224
|
-
.
|
|
225
|
-
|
|
239
|
+
match(
|
|
240
|
+
self._ptr,
|
|
241
|
+
.Some(sp) => match(
|
|
242
|
+
suffix._ptr,
|
|
243
|
+
.Some(xp) => (memcmp(*(void)(sp &+ offset), *(void)(xp), suffix._len) == int(0)),
|
|
226
244
|
.None => true
|
|
227
245
|
),
|
|
228
246
|
.None => (suffix._len == usize(0))
|
|
229
247
|
)
|
|
230
248
|
}),
|
|
231
|
-
|
|
232
249
|
/// Find the first occurrence of `needle` starting at `from_index`.
|
|
233
250
|
/// Returns byte index or `.None`.
|
|
234
|
-
index_of : (fn(self: Self, needle: Self, from_index: usize) -> Option(usize))({
|
|
235
|
-
if(
|
|
236
|
-
return
|
|
251
|
+
index_of : (fn(self : Self, needle : Self, from_index : usize) -> Option(usize))({
|
|
252
|
+
if(needle._len == usize(0), {
|
|
253
|
+
return(.Some(from_index));
|
|
237
254
|
});
|
|
238
|
-
if((
|
|
239
|
-
return
|
|
255
|
+
if((from_index + needle._len) > self._len, {
|
|
256
|
+
return(.None);
|
|
240
257
|
});
|
|
241
|
-
match(
|
|
242
|
-
.
|
|
243
|
-
.
|
|
244
|
-
.None
|
|
258
|
+
match(
|
|
259
|
+
self._ptr,
|
|
260
|
+
.None => {
|
|
261
|
+
return(.None);
|
|
262
|
+
},
|
|
263
|
+
.Some(sp) => match(
|
|
264
|
+
needle._ptr,
|
|
265
|
+
.None => {
|
|
266
|
+
return(.Some(from_index));
|
|
267
|
+
},
|
|
245
268
|
.Some(np) => {
|
|
246
269
|
i := from_index;
|
|
247
270
|
limit := ((self._len - needle._len) + usize(1));
|
|
248
|
-
while
|
|
249
|
-
if(
|
|
250
|
-
return
|
|
271
|
+
while(i < limit, i = (i + usize(1)), {
|
|
272
|
+
if(memcmp(*(void)(sp &+ i), *(void)(np), needle._len) == int(0), {
|
|
273
|
+
return(.Some(i));
|
|
251
274
|
});
|
|
252
|
-
};
|
|
253
|
-
return
|
|
275
|
+
});
|
|
276
|
+
return(.None);
|
|
254
277
|
}
|
|
255
278
|
)
|
|
256
279
|
)
|
|
257
280
|
}),
|
|
258
|
-
|
|
259
281
|
/// Check if the string contains a given substring.
|
|
260
|
-
contains : (fn(self: Self, needle: Self) -> bool)(
|
|
282
|
+
contains : (fn(self : Self, needle : Self) -> bool)(
|
|
261
283
|
self.index_of(needle, usize(0)).is_some()
|
|
262
284
|
),
|
|
263
|
-
|
|
264
285
|
/// Split the string by a separator, returning an immutable List of Strings.
|
|
265
|
-
split : (fn(self: Self, sep: Self) -> imm_list.List(String))({
|
|
286
|
+
split : (fn(self : Self, sep : Self) -> imm_list.List(String))({
|
|
266
287
|
result := imm_list.List(String).new();
|
|
267
|
-
if(
|
|
268
|
-
return
|
|
288
|
+
if(sep._len == usize(0), {
|
|
289
|
+
return(result.prepend(self));
|
|
269
290
|
});
|
|
270
291
|
pos := usize(0);
|
|
271
292
|
segments := imm_list.List(String).new();
|
|
272
|
-
while
|
|
273
|
-
match(
|
|
293
|
+
while(runtime(true), {
|
|
294
|
+
match(
|
|
295
|
+
self.index_of(sep, pos),
|
|
274
296
|
.Some(idx) => {
|
|
275
297
|
segments = segments.prepend(self.slice(pos, idx));
|
|
276
298
|
pos = (idx + sep._len);
|
|
277
299
|
},
|
|
278
300
|
.None => {
|
|
279
301
|
segments = segments.prepend(self.slice(pos, self._len));
|
|
280
|
-
return
|
|
302
|
+
return(segments.reverse());
|
|
281
303
|
}
|
|
282
304
|
);
|
|
283
|
-
};
|
|
305
|
+
});
|
|
284
306
|
segments.reverse()
|
|
285
307
|
}),
|
|
286
|
-
|
|
287
308
|
/// Check if a byte is ASCII whitespace.
|
|
288
|
-
_is_whitespace : (fn(b: u8) -> bool)(
|
|
289
|
-
(((
|
|
309
|
+
_is_whitespace : (fn(b : u8) -> bool)(
|
|
310
|
+
(((b == u8(0x20)) || (b == u8(0x09))) || (b == u8(0x0A))) || ((b == u8(0x0D)) || (b == u8(0x0C)))
|
|
290
311
|
),
|
|
291
|
-
|
|
292
312
|
/// Trim leading and trailing ASCII whitespace.
|
|
293
|
-
trim : (fn(self: Self) -> Self)({
|
|
294
|
-
if(
|
|
295
|
-
return
|
|
313
|
+
trim : (fn(self : Self) -> Self)({
|
|
314
|
+
if(self._len == usize(0), {
|
|
315
|
+
return(self);
|
|
296
316
|
});
|
|
297
|
-
match(
|
|
298
|
-
.
|
|
317
|
+
match(
|
|
318
|
+
self._ptr,
|
|
319
|
+
.None => {
|
|
320
|
+
return(self);
|
|
321
|
+
},
|
|
299
322
|
.Some(p) => {
|
|
300
323
|
start := usize(0);
|
|
301
|
-
while
|
|
302
|
-
|
|
303
|
-
|
|
324
|
+
while(
|
|
325
|
+
(start < self._len) && (Self._is_whitespace((p &+ start).*)),
|
|
326
|
+
start = (start + usize(1)),
|
|
327
|
+
()
|
|
328
|
+
);
|
|
304
329
|
end := self._len;
|
|
305
|
-
while
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
330
|
+
while(
|
|
331
|
+
(end > start) && (Self._is_whitespace((p &+ (end - usize(1))).*)),
|
|
332
|
+
end = (end - usize(1)),
|
|
333
|
+
()
|
|
334
|
+
);
|
|
335
|
+
if((start == usize(0)) && (end == self._len), {
|
|
336
|
+
return(self);
|
|
310
337
|
});
|
|
311
|
-
return
|
|
338
|
+
return(self.slice(start, end));
|
|
312
339
|
}
|
|
313
340
|
)
|
|
314
341
|
}),
|
|
315
|
-
|
|
316
342
|
/// Trim leading ASCII whitespace.
|
|
317
|
-
trim_start : (fn(self: Self) -> Self)({
|
|
318
|
-
if(
|
|
319
|
-
return
|
|
343
|
+
trim_start : (fn(self : Self) -> Self)({
|
|
344
|
+
if(self._len == usize(0), {
|
|
345
|
+
return(self);
|
|
320
346
|
});
|
|
321
|
-
match(
|
|
322
|
-
.
|
|
347
|
+
match(
|
|
348
|
+
self._ptr,
|
|
349
|
+
.None => {
|
|
350
|
+
return(self);
|
|
351
|
+
},
|
|
323
352
|
.Some(p) => {
|
|
324
353
|
start := usize(0);
|
|
325
|
-
while
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
354
|
+
while(
|
|
355
|
+
(start < self._len) && (Self._is_whitespace((p &+ start).*)),
|
|
356
|
+
start = (start + usize(1)),
|
|
357
|
+
()
|
|
358
|
+
);
|
|
359
|
+
if(start == usize(0), {
|
|
360
|
+
return(self);
|
|
330
361
|
});
|
|
331
|
-
return
|
|
362
|
+
return(self.slice(start, self._len));
|
|
332
363
|
}
|
|
333
364
|
)
|
|
334
365
|
}),
|
|
335
|
-
|
|
336
366
|
/// Trim trailing ASCII whitespace.
|
|
337
|
-
trim_end : (fn(self: Self) -> Self)({
|
|
338
|
-
if(
|
|
339
|
-
return
|
|
367
|
+
trim_end : (fn(self : Self) -> Self)({
|
|
368
|
+
if(self._len == usize(0), {
|
|
369
|
+
return(self);
|
|
340
370
|
});
|
|
341
|
-
match(
|
|
342
|
-
.
|
|
371
|
+
match(
|
|
372
|
+
self._ptr,
|
|
373
|
+
.None => {
|
|
374
|
+
return(self);
|
|
375
|
+
},
|
|
343
376
|
.Some(p) => {
|
|
344
377
|
end := self._len;
|
|
345
|
-
while
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
378
|
+
while(
|
|
379
|
+
(end > usize(0)) && (Self._is_whitespace((p &+ (end - usize(1))).*)),
|
|
380
|
+
end = (end - usize(1)),
|
|
381
|
+
()
|
|
382
|
+
);
|
|
383
|
+
if(end == self._len, {
|
|
384
|
+
return(self);
|
|
350
385
|
});
|
|
351
|
-
return
|
|
386
|
+
return(self.slice(usize(0), end));
|
|
352
387
|
}
|
|
353
388
|
)
|
|
354
389
|
}),
|
|
355
|
-
|
|
356
390
|
/// Convert all ASCII uppercase letters to lowercase.
|
|
357
391
|
/// Uses COW: if this string has a unique reference, modifies bytes in-place.
|
|
358
|
-
to_lowercase : (fn(own(self): Self) -> Self)({
|
|
359
|
-
if(
|
|
360
|
-
return
|
|
392
|
+
to_lowercase : (fn(own(self) : Self) -> Self)({
|
|
393
|
+
if(self._len == usize(0), {
|
|
394
|
+
return(self);
|
|
361
395
|
});
|
|
362
|
-
match(
|
|
363
|
-
.
|
|
396
|
+
match(
|
|
397
|
+
self._ptr,
|
|
398
|
+
.None => {
|
|
399
|
+
return(self);
|
|
400
|
+
},
|
|
364
401
|
.Some(sp) => {
|
|
365
|
-
if(
|
|
402
|
+
if(rc(self) == usize(1), {
|
|
366
403
|
i := usize(0);
|
|
367
|
-
while
|
|
404
|
+
while(i < self._len, i = (i + usize(1)), {
|
|
368
405
|
(b : u8) = (sp &+ i).*;
|
|
369
|
-
if((
|
|
406
|
+
if((b >= u8(0x41)) && (b <= u8(0x5A)), {
|
|
370
407
|
(sp &+ i).* = (b + u8(32));
|
|
371
408
|
});
|
|
372
|
-
};
|
|
373
|
-
return
|
|
409
|
+
});
|
|
410
|
+
return(self);
|
|
374
411
|
});
|
|
375
412
|
ptr := _alloc_bytes(self._len);
|
|
376
413
|
memcpy(*(void)(ptr), *(void)(sp), self._len);
|
|
377
414
|
i := usize(0);
|
|
378
|
-
while
|
|
415
|
+
while(i < self._len, i = (i + usize(1)), {
|
|
379
416
|
(b : u8) = (ptr &+ i).*;
|
|
380
|
-
if((
|
|
417
|
+
if((b >= u8(0x41)) && (b <= u8(0x5A)), {
|
|
381
418
|
(ptr &+ i).* = (b + u8(32));
|
|
382
419
|
});
|
|
383
|
-
};
|
|
420
|
+
});
|
|
384
421
|
saved_len := self._len;
|
|
385
422
|
unsafe.drop(self);
|
|
386
|
-
return
|
|
423
|
+
return(Self(_ptr :.Some(ptr), _len : saved_len, _capacity : saved_len));
|
|
387
424
|
}
|
|
388
425
|
)
|
|
389
426
|
}),
|
|
390
|
-
|
|
391
427
|
/// Convert all ASCII lowercase letters to uppercase.
|
|
392
428
|
/// Uses COW: if this string has a unique reference, modifies bytes in-place.
|
|
393
|
-
to_uppercase : (fn(own(self): Self) -> Self)({
|
|
394
|
-
if(
|
|
395
|
-
return
|
|
429
|
+
to_uppercase : (fn(own(self) : Self) -> Self)({
|
|
430
|
+
if(self._len == usize(0), {
|
|
431
|
+
return(self);
|
|
396
432
|
});
|
|
397
|
-
match(
|
|
398
|
-
.
|
|
433
|
+
match(
|
|
434
|
+
self._ptr,
|
|
435
|
+
.None => {
|
|
436
|
+
return(self);
|
|
437
|
+
},
|
|
399
438
|
.Some(sp) => {
|
|
400
|
-
if(
|
|
439
|
+
if(rc(self) == usize(1), {
|
|
401
440
|
i := usize(0);
|
|
402
|
-
while
|
|
441
|
+
while(i < self._len, i = (i + usize(1)), {
|
|
403
442
|
(b : u8) = (sp &+ i).*;
|
|
404
|
-
if((
|
|
443
|
+
if((b >= u8(0x61)) && (b <= u8(0x7A)), {
|
|
405
444
|
(sp &+ i).* = (b - u8(32));
|
|
406
445
|
});
|
|
407
|
-
};
|
|
408
|
-
return
|
|
446
|
+
});
|
|
447
|
+
return(self);
|
|
409
448
|
});
|
|
410
449
|
ptr := _alloc_bytes(self._len);
|
|
411
450
|
memcpy(*(void)(ptr), *(void)(sp), self._len);
|
|
412
451
|
i := usize(0);
|
|
413
|
-
while
|
|
452
|
+
while(i < self._len, i = (i + usize(1)), {
|
|
414
453
|
(b : u8) = (ptr &+ i).*;
|
|
415
|
-
if((
|
|
454
|
+
if((b >= u8(0x61)) && (b <= u8(0x7A)), {
|
|
416
455
|
(ptr &+ i).* = (b - u8(32));
|
|
417
456
|
});
|
|
418
|
-
};
|
|
457
|
+
});
|
|
419
458
|
saved_len := self._len;
|
|
420
459
|
unsafe.drop(self);
|
|
421
|
-
return
|
|
460
|
+
return(Self(_ptr :.Some(ptr), _len : saved_len, _capacity : saved_len));
|
|
422
461
|
}
|
|
423
462
|
)
|
|
424
463
|
}),
|
|
425
|
-
|
|
426
464
|
/// Replace the first occurrence of `search` with `replacement`.
|
|
427
|
-
replace : (fn(self: Self, search: Self, replacement: Self) -> Self)(
|
|
428
|
-
match(
|
|
429
|
-
.
|
|
465
|
+
replace : (fn(self : Self, search : Self, replacement : Self) -> Self)(
|
|
466
|
+
match(
|
|
467
|
+
self.index_of(search, usize(0)),
|
|
468
|
+
.None => {
|
|
469
|
+
return(self);
|
|
470
|
+
},
|
|
430
471
|
.Some(idx) => {
|
|
431
472
|
before := self.slice(usize(0), idx);
|
|
432
|
-
after := self.slice(
|
|
473
|
+
after := self.slice(idx + search._len, self._len);
|
|
433
474
|
tmp := before.concat(replacement);
|
|
434
|
-
return
|
|
475
|
+
return(tmp.concat(after));
|
|
435
476
|
}
|
|
436
477
|
)
|
|
437
478
|
),
|
|
438
|
-
|
|
439
479
|
/// Replace all occurrences of `search` with `replacement`.
|
|
440
|
-
replace_all : (fn(self: Self, search: Self, replacement: Self) -> Self)({
|
|
441
|
-
if(
|
|
442
|
-
return
|
|
480
|
+
replace_all : (fn(self : Self, search : Self, replacement : Self) -> Self)({
|
|
481
|
+
if(search._len == usize(0), {
|
|
482
|
+
return(self);
|
|
443
483
|
});
|
|
444
484
|
result := Self.new();
|
|
445
485
|
pos := usize(0);
|
|
446
486
|
done := false;
|
|
447
|
-
while
|
|
448
|
-
match(
|
|
487
|
+
while(!(done), {
|
|
488
|
+
match(
|
|
489
|
+
self.index_of(search, pos),
|
|
449
490
|
.Some(idx) => {
|
|
450
491
|
segment := self.slice(pos, idx);
|
|
451
492
|
result = result.concat(segment);
|
|
@@ -457,89 +498,93 @@ impl(String,
|
|
|
457
498
|
done = true;
|
|
458
499
|
}
|
|
459
500
|
);
|
|
460
|
-
};
|
|
501
|
+
});
|
|
461
502
|
result
|
|
462
503
|
}),
|
|
463
|
-
|
|
464
504
|
/// Repeat the string `n` times.
|
|
465
|
-
repeat : (fn(self: Self, n: usize) -> Self)({
|
|
466
|
-
if((
|
|
467
|
-
return
|
|
505
|
+
repeat : (fn(self : Self, n : usize) -> Self)({
|
|
506
|
+
if((n == usize(0)) || (self._len == usize(0)), {
|
|
507
|
+
return(Self.new());
|
|
468
508
|
});
|
|
469
|
-
if(
|
|
470
|
-
return
|
|
509
|
+
if(n == usize(1), {
|
|
510
|
+
return(self);
|
|
471
511
|
});
|
|
472
512
|
new_len := (self._len * n);
|
|
473
513
|
ptr := _alloc_bytes(new_len);
|
|
474
|
-
match(
|
|
514
|
+
match(
|
|
515
|
+
self._ptr,
|
|
475
516
|
.Some(sp) => {
|
|
476
517
|
i := usize(0);
|
|
477
|
-
while
|
|
478
|
-
memcpy(*(void)(
|
|
479
|
-
};
|
|
518
|
+
while(i < n, i = (i + usize(1)), {
|
|
519
|
+
memcpy(*(void)(ptr &+ (i * self._len)), *(void)(sp), self._len);
|
|
520
|
+
});
|
|
480
521
|
},
|
|
481
522
|
.None => ()
|
|
482
523
|
);
|
|
483
|
-
return
|
|
524
|
+
return(Self(_ptr :.Some(ptr), _len : new_len, _capacity : new_len));
|
|
484
525
|
}),
|
|
485
|
-
|
|
486
526
|
/// Decode a single UTF-8 rune starting at byte index.
|
|
487
|
-
_decode_rune_at : (fn(self: Self, byte_index: usize) -> Option(rune))({
|
|
488
|
-
if(
|
|
489
|
-
return
|
|
527
|
+
_decode_rune_at : (fn(self : Self, byte_index : usize) -> Option(rune))({
|
|
528
|
+
if(byte_index >= self._len, {
|
|
529
|
+
return(.None);
|
|
490
530
|
});
|
|
491
|
-
match(
|
|
492
|
-
.
|
|
531
|
+
match(
|
|
532
|
+
self._ptr,
|
|
533
|
+
.None => {
|
|
534
|
+
return(.None);
|
|
535
|
+
},
|
|
493
536
|
.Some(p) => {
|
|
494
537
|
(b0 : u8) = (p &+ byte_index).*;
|
|
495
|
-
if((
|
|
496
|
-
return
|
|
538
|
+
if((b0 & u8(0x80)) == u8(0), {
|
|
539
|
+
return(.Some(rune(char : u32(b0))));
|
|
497
540
|
});
|
|
498
|
-
if((
|
|
499
|
-
if((
|
|
500
|
-
return
|
|
541
|
+
if((b0 & u8(0xE0)) == u8(0xC0), {
|
|
542
|
+
if((byte_index + usize(1)) >= self._len, {
|
|
543
|
+
return(.None);
|
|
501
544
|
});
|
|
502
545
|
(b1 : u8) = (p &+ (byte_index + usize(1))).*;
|
|
503
546
|
(code : u32) = (((u32(b0) & u32(0x1F)) << u32(6)) | (u32(b1) & u32(0x3F)));
|
|
504
|
-
return
|
|
547
|
+
return(.Some(rune(char : code)));
|
|
505
548
|
});
|
|
506
|
-
if((
|
|
507
|
-
if((
|
|
508
|
-
return
|
|
549
|
+
if((b0 & u8(0xF0)) == u8(0xE0), {
|
|
550
|
+
if((byte_index + usize(2)) >= self._len, {
|
|
551
|
+
return(.None);
|
|
509
552
|
});
|
|
510
553
|
(b1 : u8) = (p &+ (byte_index + usize(1))).*;
|
|
511
554
|
(b2 : u8) = (p &+ (byte_index + usize(2))).*;
|
|
512
555
|
(code : u32) = ((((u32(b0) & u32(0x0F)) << u32(12)) | ((u32(b1) & u32(0x3F)) << u32(6))) | (u32(b2) & u32(0x3F)));
|
|
513
|
-
return
|
|
556
|
+
return(.Some(rune(char : code)));
|
|
514
557
|
});
|
|
515
|
-
if((
|
|
516
|
-
if((
|
|
517
|
-
return
|
|
558
|
+
if((b0 & u8(0xF8)) == u8(0xF0), {
|
|
559
|
+
if((byte_index + usize(3)) >= self._len, {
|
|
560
|
+
return(.None);
|
|
518
561
|
});
|
|
519
562
|
(b1 : u8) = (p &+ (byte_index + usize(1))).*;
|
|
520
563
|
(b2 : u8) = (p &+ (byte_index + usize(2))).*;
|
|
521
564
|
(b3 : u8) = (p &+ (byte_index + usize(3))).*;
|
|
522
565
|
(code : u32) = (((((u32(b0) & u32(0x07)) << u32(18)) | ((u32(b1) & u32(0x3F)) << u32(12))) | ((u32(b2) & u32(0x3F)) << u32(6))) | (u32(b3) & u32(0x3F)));
|
|
523
|
-
return
|
|
566
|
+
return(.Some(rune(char : code)));
|
|
524
567
|
});
|
|
525
|
-
return
|
|
568
|
+
return(.None);
|
|
526
569
|
}
|
|
527
570
|
)
|
|
528
571
|
}),
|
|
529
|
-
|
|
530
572
|
/// Get the Unicode character (rune) at a given character index.
|
|
531
|
-
at : (fn(self: Self, index: usize) -> Option(rune))({
|
|
532
|
-
if(
|
|
533
|
-
return
|
|
573
|
+
at : (fn(self : Self, index : usize) -> Option(rune))({
|
|
574
|
+
if(self._len == usize(0), {
|
|
575
|
+
return(.None);
|
|
534
576
|
});
|
|
535
|
-
match(
|
|
536
|
-
.
|
|
577
|
+
match(
|
|
578
|
+
self._ptr,
|
|
579
|
+
.None => {
|
|
580
|
+
return(.None);
|
|
581
|
+
},
|
|
537
582
|
.Some(p) => {
|
|
538
583
|
char_count := usize(0);
|
|
539
584
|
byte_index := usize(0);
|
|
540
|
-
while
|
|
541
|
-
if(
|
|
542
|
-
return
|
|
585
|
+
while(byte_index < self._len, (), {
|
|
586
|
+
if(char_count == index, {
|
|
587
|
+
return(self._decode_rune_at(byte_index));
|
|
543
588
|
});
|
|
544
589
|
(b : u8) = (p &+ byte_index).*;
|
|
545
590
|
cond(
|
|
@@ -557,111 +602,125 @@ impl(String,
|
|
|
557
602
|
}
|
|
558
603
|
);
|
|
559
604
|
char_count = (char_count + usize(1));
|
|
560
|
-
};
|
|
561
|
-
return
|
|
605
|
+
});
|
|
606
|
+
return(.None);
|
|
562
607
|
}
|
|
563
608
|
)
|
|
564
609
|
})
|
|
565
610
|
);
|
|
566
|
-
|
|
567
611
|
/// Equality by byte content.
|
|
568
|
-
impl(
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
.
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
612
|
+
impl(
|
|
613
|
+
String,
|
|
614
|
+
Eq(String)(
|
|
615
|
+
(==) : (fn(self : Self, other : Self) -> bool)({
|
|
616
|
+
if(self._len != other._len, {
|
|
617
|
+
return(false);
|
|
618
|
+
});
|
|
619
|
+
if(self._len == usize(0), {
|
|
620
|
+
return(true);
|
|
621
|
+
});
|
|
622
|
+
match(
|
|
623
|
+
self._ptr,
|
|
624
|
+
.Some(sp) => match(
|
|
625
|
+
other._ptr,
|
|
626
|
+
.Some(op) => (memcmp(*(void)(sp), *(void)(op), self._len) == int(0)),
|
|
627
|
+
.None => false
|
|
628
|
+
),
|
|
629
|
+
.None => match(
|
|
630
|
+
other._ptr,
|
|
631
|
+
.Some(_) => false,
|
|
632
|
+
.None => true
|
|
633
|
+
)
|
|
584
634
|
)
|
|
585
|
-
)
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
)
|
|
591
|
-
|
|
635
|
+
}),
|
|
636
|
+
(!=) : (fn(self : Self, other : Self) -> bool)({
|
|
637
|
+
return(!(Self.(==)(self, other)));
|
|
638
|
+
})
|
|
639
|
+
)
|
|
640
|
+
);
|
|
592
641
|
// TODO: Eq(str) impl — "Variable str not found" inside impl blocks for atomic object types.
|
|
593
642
|
// Provide eq_str method instead.
|
|
594
|
-
impl(
|
|
643
|
+
impl(
|
|
644
|
+
String,
|
|
595
645
|
/// Compare with a `str` for equality.
|
|
596
|
-
eq_str : (fn(self: Self, other: str) -> bool)({
|
|
646
|
+
eq_str : (fn(self : Self, other : str) -> bool)({
|
|
597
647
|
other_len := other.len();
|
|
598
|
-
if(
|
|
599
|
-
return
|
|
648
|
+
if(self._len != other_len, {
|
|
649
|
+
return(false);
|
|
600
650
|
});
|
|
601
|
-
if(
|
|
602
|
-
return
|
|
651
|
+
if(self._len == usize(0), {
|
|
652
|
+
return(true);
|
|
603
653
|
});
|
|
604
|
-
match(
|
|
654
|
+
match(
|
|
655
|
+
self._ptr,
|
|
605
656
|
.Some(sp) => (memcmp(*(void)(sp), *(void)(other.ptr()), self._len) == int(0)),
|
|
606
657
|
.None => (other_len == usize(0))
|
|
607
658
|
)
|
|
608
659
|
})
|
|
609
660
|
);
|
|
610
|
-
|
|
611
661
|
/// Lexicographic ordering.
|
|
612
|
-
impl(
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
662
|
+
impl(
|
|
663
|
+
String,
|
|
664
|
+
Ord(String)(
|
|
665
|
+
(<) : (fn(self : Self, other : Self) -> bool)({
|
|
666
|
+
min_len := _min(self._len, other._len);
|
|
667
|
+
if(min_len > usize(0), {
|
|
668
|
+
match(
|
|
669
|
+
self._ptr,
|
|
670
|
+
.Some(sp) => match(
|
|
671
|
+
other._ptr,
|
|
672
|
+
.Some(op) => {
|
|
673
|
+
(cmp_result : int) = memcmp(*(void)(sp), *(void)(op), min_len);
|
|
674
|
+
if(cmp_result != int(0), {
|
|
675
|
+
return(cmp_result < int(0));
|
|
676
|
+
});
|
|
677
|
+
},
|
|
678
|
+
.None => ()
|
|
679
|
+
),
|
|
624
680
|
.None => ()
|
|
625
|
-
)
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
})
|
|
629
|
-
(self
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
(other
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
));
|
|
641
|
-
|
|
681
|
+
);
|
|
682
|
+
});
|
|
683
|
+
self._len < other._len
|
|
684
|
+
}),
|
|
685
|
+
(<=) : (fn(self : Self, other : Self) -> bool)({
|
|
686
|
+
return(!(other < self));
|
|
687
|
+
}),
|
|
688
|
+
(>) : (fn(self : Self, other : Self) -> bool)(
|
|
689
|
+
other < self
|
|
690
|
+
),
|
|
691
|
+
(>=) : (fn(self : Self, other : Self) -> bool)({
|
|
692
|
+
return(!(self < other));
|
|
693
|
+
})
|
|
694
|
+
)
|
|
695
|
+
);
|
|
642
696
|
/// FNV-1a hash over the string's bytes.
|
|
643
|
-
impl(
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
)
|
|
659
|
-
|
|
697
|
+
impl(
|
|
698
|
+
String,
|
|
699
|
+
Hash(
|
|
700
|
+
(hash) : (fn(self : *(Self)) -> u64)({
|
|
701
|
+
h := u64(14695981039346656037);
|
|
702
|
+
match(
|
|
703
|
+
self.*._ptr,
|
|
704
|
+
.None => (),
|
|
705
|
+
.Some(p) => {
|
|
706
|
+
i := usize(0);
|
|
707
|
+
while(i < self.*._len, i = (i + usize(1)), {
|
|
708
|
+
h = (h ^ u64((p &+ i).*));
|
|
709
|
+
h = (h * u64(1099511628211));
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
h
|
|
714
|
+
})
|
|
715
|
+
)
|
|
716
|
+
);
|
|
660
717
|
/// ToString returns a std.String for compatibility with println/print.
|
|
661
|
-
impl(
|
|
662
|
-
|
|
663
|
-
|
|
718
|
+
impl(
|
|
719
|
+
String,
|
|
720
|
+
ToString(
|
|
721
|
+
to_string : (fn(self : *(Self)) -> std_string.String)(
|
|
722
|
+
std_string.String.from(self.*.as_str())
|
|
723
|
+
)
|
|
664
724
|
)
|
|
665
|
-
)
|
|
666
|
-
|
|
667
|
-
export String;
|
|
725
|
+
);
|
|
726
|
+
export(String);
|