ic-mops 0.8.5 → 0.8.7
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/package.json +3 -1
- package/.mops/base@0.7.4/LICENSE +0 -208
- package/.mops/base@0.7.4/README.md +0 -64
- package/.mops/base@0.7.4/mops.toml +0 -5
- package/.mops/base@0.7.4/src/Array.mo +0 -686
- package/.mops/base@0.7.4/src/AssocList.mo +0 -203
- package/.mops/base@0.7.4/src/Blob.mo +0 -55
- package/.mops/base@0.7.4/src/Bool.mo +0 -44
- package/.mops/base@0.7.4/src/Buffer.mo +0 -1937
- package/.mops/base@0.7.4/src/CertifiedData.mo +0 -29
- package/.mops/base@0.7.4/src/Char.mo +0 -67
- package/.mops/base@0.7.4/src/Debug.mo +0 -15
- package/.mops/base@0.7.4/src/Deque.mo +0 -75
- package/.mops/base@0.7.4/src/Error.mo +0 -41
- package/.mops/base@0.7.4/src/ExperimentalCycles.mo +0 -51
- package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +0 -36
- package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +0 -121
- package/.mops/base@0.7.4/src/Float.mo +0 -150
- package/.mops/base@0.7.4/src/Func.mo +0 -38
- package/.mops/base@0.7.4/src/Hash.mo +0 -83
- package/.mops/base@0.7.4/src/HashMap.mo +0 -229
- package/.mops/base@0.7.4/src/Heap.mo +0 -113
- package/.mops/base@0.7.4/src/Int.mo +0 -150
- package/.mops/base@0.7.4/src/Int16.mo +0 -159
- package/.mops/base@0.7.4/src/Int32.mo +0 -160
- package/.mops/base@0.7.4/src/Int64.mo +0 -161
- package/.mops/base@0.7.4/src/Int8.mo +0 -160
- package/.mops/base@0.7.4/src/Iter.mo +0 -220
- package/.mops/base@0.7.4/src/IterType.mo +0 -7
- package/.mops/base@0.7.4/src/List.mo +0 -433
- package/.mops/base@0.7.4/src/Nat.mo +0 -75
- package/.mops/base@0.7.4/src/Nat16.mo +0 -146
- package/.mops/base@0.7.4/src/Nat32.mo +0 -146
- package/.mops/base@0.7.4/src/Nat64.mo +0 -146
- package/.mops/base@0.7.4/src/Nat8.mo +0 -146
- package/.mops/base@0.7.4/src/None.mo +0 -19
- package/.mops/base@0.7.4/src/Option.mo +0 -160
- package/.mops/base@0.7.4/src/Order.mo +0 -46
- package/.mops/base@0.7.4/src/Prelude.mo +0 -33
- package/.mops/base@0.7.4/src/Principal.mo +0 -58
- package/.mops/base@0.7.4/src/RBTree.mo +0 -218
- package/.mops/base@0.7.4/src/Random.mo +0 -188
- package/.mops/base@0.7.4/src/Result.mo +0 -210
- package/.mops/base@0.7.4/src/Stack.mo +0 -40
- package/.mops/base@0.7.4/src/Text.mo +0 -615
- package/.mops/base@0.7.4/src/Time.mo +0 -37
- package/.mops/base@0.7.4/src/Trie.mo +0 -1200
- package/.mops/base@0.7.4/src/TrieMap.mo +0 -180
- package/.mops/base@0.7.4/src/TrieSet.mo +0 -97
- package/.mops/base@0.8.3/LICENSE +0 -208
- package/.mops/base@0.8.3/README.md +0 -64
- package/.mops/base@0.8.3/mops.toml +0 -6
- package/.mops/base@0.8.3/src/Array.mo +0 -717
- package/.mops/base@0.8.3/src/AssocList.mo +0 -404
- package/.mops/base@0.8.3/src/Blob.mo +0 -212
- package/.mops/base@0.8.3/src/Bool.mo +0 -44
- package/.mops/base@0.8.3/src/Buffer.mo +0 -2660
- package/.mops/base@0.8.3/src/CertifiedData.mo +0 -53
- package/.mops/base@0.8.3/src/Char.mo +0 -65
- package/.mops/base@0.8.3/src/Debug.mo +0 -56
- package/.mops/base@0.8.3/src/Deque.mo +0 -243
- package/.mops/base@0.8.3/src/Error.mo +0 -68
- package/.mops/base@0.8.3/src/ExperimentalCycles.mo +0 -151
- package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +0 -60
- package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +0 -348
- package/.mops/base@0.8.3/src/Float.mo +0 -843
- package/.mops/base@0.8.3/src/Func.mo +0 -46
- package/.mops/base@0.8.3/src/Hash.mo +0 -82
- package/.mops/base@0.8.3/src/HashMap.mo +0 -457
- package/.mops/base@0.8.3/src/Heap.mo +0 -233
- package/.mops/base@0.8.3/src/Int.mo +0 -365
- package/.mops/base@0.8.3/src/Int16.mo +0 -521
- package/.mops/base@0.8.3/src/Int32.mo +0 -522
- package/.mops/base@0.8.3/src/Int64.mo +0 -522
- package/.mops/base@0.8.3/src/Int8.mo +0 -522
- package/.mops/base@0.8.3/src/Iter.mo +0 -227
- package/.mops/base@0.8.3/src/IterType.mo +0 -7
- package/.mops/base@0.8.3/src/List.mo +0 -930
- package/.mops/base@0.8.3/src/Nat.mo +0 -305
- package/.mops/base@0.8.3/src/Nat16.mo +0 -144
- package/.mops/base@0.8.3/src/Nat32.mo +0 -144
- package/.mops/base@0.8.3/src/Nat64.mo +0 -144
- package/.mops/base@0.8.3/src/Nat8.mo +0 -144
- package/.mops/base@0.8.3/src/None.mo +0 -19
- package/.mops/base@0.8.3/src/Option.mo +0 -154
- package/.mops/base@0.8.3/src/Order.mo +0 -46
- package/.mops/base@0.8.3/src/Prelude.mo +0 -33
- package/.mops/base@0.8.3/src/Principal.mo +0 -249
- package/.mops/base@0.8.3/src/RBTree.mo +0 -681
- package/.mops/base@0.8.3/src/Random.mo +0 -270
- package/.mops/base@0.8.3/src/Result.mo +0 -209
- package/.mops/base@0.8.3/src/Stack.mo +0 -93
- package/.mops/base@0.8.3/src/Text.mo +0 -761
- package/.mops/base@0.8.3/src/Time.mo +0 -36
- package/.mops/base@0.8.3/src/Timer.mo +0 -62
- package/.mops/base@0.8.3/src/Trie.mo +0 -1603
- package/.mops/base@0.8.3/src/TrieMap.mo +0 -392
- package/.mops/base@0.8.3/src/TrieSet.mo +0 -148
- package/network.txt +0 -1
|
@@ -1,761 +0,0 @@
|
|
|
1
|
-
/// Utility functions for `Text` values.
|
|
2
|
-
///
|
|
3
|
-
/// A `Text` value represents human-readable text as a sequence of characters of type `Char`.
|
|
4
|
-
///
|
|
5
|
-
/// ```motoko
|
|
6
|
-
/// let text = "Hello!";
|
|
7
|
-
/// let size = text.size(); // 6
|
|
8
|
-
/// let iter = text.chars(); // iterator ('H', 'e', 'l', 'l', 'o', '!')
|
|
9
|
-
/// let concat = text # " 👋"; // "Hello! 👋"
|
|
10
|
-
/// ```
|
|
11
|
-
///
|
|
12
|
-
/// The `"mo:base/Text"` module defines additional operations on `Text` values.
|
|
13
|
-
///
|
|
14
|
-
/// Import the module from the base library:
|
|
15
|
-
///
|
|
16
|
-
/// ```motoko name=import
|
|
17
|
-
/// import Text "mo:base/Text";
|
|
18
|
-
/// ```
|
|
19
|
-
///
|
|
20
|
-
/// Note: `Text` values are represented as ropes of UTF-8 character sequences with O(1) concatenation.
|
|
21
|
-
///
|
|
22
|
-
|
|
23
|
-
import Char "Char";
|
|
24
|
-
import Iter "Iter";
|
|
25
|
-
import Hash "Hash";
|
|
26
|
-
import Stack "Stack";
|
|
27
|
-
import Prim "mo:⛔";
|
|
28
|
-
|
|
29
|
-
module {
|
|
30
|
-
|
|
31
|
-
/// The type corresponding to primitive `Text` values.
|
|
32
|
-
///
|
|
33
|
-
/// ```motoko
|
|
34
|
-
/// let hello = "Hello!";
|
|
35
|
-
/// let emoji = "👋";
|
|
36
|
-
/// let concat = hello # " " # emoji; // "Hello! 👋"
|
|
37
|
-
/// ```
|
|
38
|
-
public type Text = Prim.Types.Text;
|
|
39
|
-
|
|
40
|
-
/// Converts the given `Char` to a `Text` value.
|
|
41
|
-
///
|
|
42
|
-
/// ```motoko include=import
|
|
43
|
-
/// let text = Text.fromChar('A'); // "A"
|
|
44
|
-
/// ```
|
|
45
|
-
public let fromChar : (c : Char) -> Text = Prim.charToText;
|
|
46
|
-
|
|
47
|
-
/// Iterates over each `Char` value in the given `Text`.
|
|
48
|
-
///
|
|
49
|
-
/// Equivalent to calling the `t.chars()` method where `t` is a `Text` value.
|
|
50
|
-
///
|
|
51
|
-
/// ```motoko include=import
|
|
52
|
-
/// import { print } "mo:base/Debug";
|
|
53
|
-
///
|
|
54
|
-
/// for (c in Text.toIter("abc")) {
|
|
55
|
-
/// print(debug_show c);
|
|
56
|
-
/// }
|
|
57
|
-
/// ```
|
|
58
|
-
public func toIter(t : Text) : Iter.Iter<Char> = t.chars();
|
|
59
|
-
|
|
60
|
-
/// Creates a `Text` value from a `Char` iterator.
|
|
61
|
-
///
|
|
62
|
-
/// ```motoko include=import
|
|
63
|
-
/// let text = Text.fromIter(['a', 'b', 'c'].vals()); // "abc"
|
|
64
|
-
/// ```
|
|
65
|
-
public func fromIter(cs : Iter.Iter<Char>) : Text {
|
|
66
|
-
var r = "";
|
|
67
|
-
for (c in cs) {
|
|
68
|
-
r #= Prim.charToText(c)
|
|
69
|
-
};
|
|
70
|
-
return r
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/// Returns the number of characters in the given `Text`.
|
|
74
|
-
///
|
|
75
|
-
/// Equivalent to calling `t.size()` where `t` is a `Text` value.
|
|
76
|
-
///
|
|
77
|
-
/// ```motoko include=import
|
|
78
|
-
/// let size = Text.size("abc"); // 3
|
|
79
|
-
/// ```
|
|
80
|
-
public func size(t : Text) : Nat { t.size() };
|
|
81
|
-
|
|
82
|
-
/// Returns a hash obtained by using the `djb2` algorithm ([more details](http://www.cse.yorku.ca/~oz/hash.html)).
|
|
83
|
-
///
|
|
84
|
-
/// ```motoko include=import
|
|
85
|
-
/// let hash = Text.hash("abc");
|
|
86
|
-
/// ```
|
|
87
|
-
///
|
|
88
|
-
/// Note: this algorithm is intended for use in data structures rather than as a cryptographic hash function.
|
|
89
|
-
public func hash(t : Text) : Hash.Hash {
|
|
90
|
-
var x : Nat32 = 5381;
|
|
91
|
-
for (char in t.chars()) {
|
|
92
|
-
let c : Nat32 = Prim.charToNat32(char);
|
|
93
|
-
x := ((x << 5) +% x) +% c
|
|
94
|
-
};
|
|
95
|
-
return x
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/// Returns `t1 # t2`, where `#` is the `Text` concatenation operator.
|
|
99
|
-
///
|
|
100
|
-
/// ```motoko include=import
|
|
101
|
-
/// let a = "Hello";
|
|
102
|
-
/// let b = "There";
|
|
103
|
-
/// let together = a # b; // "HelloThere"
|
|
104
|
-
/// let withSpace = a # " " # b; // "Hello There"
|
|
105
|
-
/// let togetherAgain = Text.concat(a, b); // "HelloThere"
|
|
106
|
-
/// ```
|
|
107
|
-
public func concat(t1 : Text, t2 : Text) : Text = t1 # t2;
|
|
108
|
-
|
|
109
|
-
/// Returns `t1 == t2`.
|
|
110
|
-
public func equal(t1 : Text, t2 : Text) : Bool { t1 == t2 };
|
|
111
|
-
|
|
112
|
-
/// Returns `t1 != t2`.
|
|
113
|
-
public func notEqual(t1 : Text, t2 : Text) : Bool { t1 != t2 };
|
|
114
|
-
|
|
115
|
-
/// Returns `t1 < t2`.
|
|
116
|
-
public func less(t1 : Text, t2 : Text) : Bool { t1 < t2 };
|
|
117
|
-
|
|
118
|
-
/// Returns `t1 <= t2`.
|
|
119
|
-
public func lessOrEqual(t1 : Text, t2 : Text) : Bool { t1 <= t2 };
|
|
120
|
-
|
|
121
|
-
/// Returns `t1 > t2`.
|
|
122
|
-
public func greater(t1 : Text, t2 : Text) : Bool { t1 > t2 };
|
|
123
|
-
|
|
124
|
-
/// Returns `t1 >= t2`.
|
|
125
|
-
public func greaterOrEqual(t1 : Text, t2 : Text) : Bool { t1 >= t2 };
|
|
126
|
-
|
|
127
|
-
/// Compares `t1` and `t2` lexicographically.
|
|
128
|
-
///
|
|
129
|
-
/// ```motoko include=import
|
|
130
|
-
/// import { print } "mo:base/Debug";
|
|
131
|
-
///
|
|
132
|
-
/// print(debug_show Text.compare("abc", "abc")); // #equal
|
|
133
|
-
/// print(debug_show Text.compare("abc", "def")); // #less
|
|
134
|
-
/// print(debug_show Text.compare("abc", "ABC")); // #greater
|
|
135
|
-
/// ```
|
|
136
|
-
public func compare(t1 : Text, t2 : Text) : { #less; #equal; #greater } {
|
|
137
|
-
let c = Prim.textCompare(t1, t2);
|
|
138
|
-
if (c < 0) #less else if (c == 0) #equal else #greater
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
private func extract(t : Text, i : Nat, j : Nat) : Text {
|
|
142
|
-
let size = t.size();
|
|
143
|
-
if (i == 0 and j == size) return t;
|
|
144
|
-
assert (j <= size);
|
|
145
|
-
let cs = t.chars();
|
|
146
|
-
var r = "";
|
|
147
|
-
var n = i;
|
|
148
|
-
while (n > 0) {
|
|
149
|
-
ignore cs.next();
|
|
150
|
-
n -= 1
|
|
151
|
-
};
|
|
152
|
-
n := j;
|
|
153
|
-
while (n > 0) {
|
|
154
|
-
switch (cs.next()) {
|
|
155
|
-
case null { assert false };
|
|
156
|
-
case (?c) { r #= Prim.charToText(c) }
|
|
157
|
-
};
|
|
158
|
-
n -= 1
|
|
159
|
-
};
|
|
160
|
-
return r
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
/// Join an iterator of `Text` values with a given delimiter.
|
|
164
|
-
///
|
|
165
|
-
/// ```motoko include=import
|
|
166
|
-
/// let joined = Text.join(", ", ["a", "b", "c"].vals()); // "a, b, c"
|
|
167
|
-
/// ```
|
|
168
|
-
public func join(sep : Text, ts : Iter.Iter<Text>) : Text {
|
|
169
|
-
var r = "";
|
|
170
|
-
if (sep.size() == 0) {
|
|
171
|
-
for (t in ts) {
|
|
172
|
-
r #= t
|
|
173
|
-
};
|
|
174
|
-
return r
|
|
175
|
-
};
|
|
176
|
-
let next = ts.next;
|
|
177
|
-
switch (next()) {
|
|
178
|
-
case null { return r };
|
|
179
|
-
case (?t) {
|
|
180
|
-
r #= t
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
loop {
|
|
184
|
-
switch (next()) {
|
|
185
|
-
case null { return r };
|
|
186
|
-
case (?t) {
|
|
187
|
-
r #= sep;
|
|
188
|
-
r #= t
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
/// Applies a function to each character in a `Text` value, returning the concatenated `Char` results.
|
|
195
|
-
///
|
|
196
|
-
/// ```motoko include=import
|
|
197
|
-
/// // Replace all occurrences of '?' with '!'
|
|
198
|
-
/// let result = Text.map("Motoko?", func(c) {
|
|
199
|
-
/// if (c == '?') '!'
|
|
200
|
-
/// else c
|
|
201
|
-
/// });
|
|
202
|
-
/// ```
|
|
203
|
-
public func map(t : Text, f : Char -> Char) : Text {
|
|
204
|
-
var r = "";
|
|
205
|
-
for (c in t.chars()) {
|
|
206
|
-
r #= Prim.charToText(f(c))
|
|
207
|
-
};
|
|
208
|
-
return r
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
/// Returns the result of applying `f` to each character in `ts`, concatenating the intermediate text values.
|
|
212
|
-
///
|
|
213
|
-
/// ```motoko include=import
|
|
214
|
-
/// // Replace all occurrences of '?' with "!!"
|
|
215
|
-
/// let result = Text.translate("Motoko?", func(c) {
|
|
216
|
-
/// if (c == '?') "!!"
|
|
217
|
-
/// else Text.fromChar(c)
|
|
218
|
-
/// }); // "Motoko!!"
|
|
219
|
-
/// ```
|
|
220
|
-
public func translate(t : Text, f : Char -> Text) : Text {
|
|
221
|
-
var r = "";
|
|
222
|
-
for (c in t.chars()) {
|
|
223
|
-
r #= f(c)
|
|
224
|
-
};
|
|
225
|
-
return r
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
/// A pattern `p` describes a sequence of characters. A pattern has one of the following forms:
|
|
229
|
-
///
|
|
230
|
-
/// * `#char c` matches the single character sequence, `c`.
|
|
231
|
-
/// * `#text t` matches multi-character text sequence `t`.
|
|
232
|
-
/// * `#predicate p` matches any single character sequence `c` satisfying predicate `p(c)`.
|
|
233
|
-
///
|
|
234
|
-
/// A _match_ for `p` is any sequence of characters matching the pattern `p`.
|
|
235
|
-
///
|
|
236
|
-
/// ```motoko include=import
|
|
237
|
-
/// let charPattern = #char 'A';
|
|
238
|
-
/// let textPattern = #text "phrase";
|
|
239
|
-
/// let predicatePattern : Text.Pattern = #predicate (func(c) { c == 'A' or c == 'B' }); // matches "A" or "B"
|
|
240
|
-
/// ```
|
|
241
|
-
public type Pattern = {
|
|
242
|
-
#char : Char;
|
|
243
|
-
#text : Text;
|
|
244
|
-
#predicate : (Char -> Bool)
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
private func take(n : Nat, cs : Iter.Iter<Char>) : Iter.Iter<Char> {
|
|
248
|
-
var i = n;
|
|
249
|
-
object {
|
|
250
|
-
public func next() : ?Char {
|
|
251
|
-
if (i == 0) return null;
|
|
252
|
-
i -= 1;
|
|
253
|
-
return cs.next()
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
private func empty() : Iter.Iter<Char> {
|
|
259
|
-
object {
|
|
260
|
-
public func next() : ?Char = null
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
private type Match = {
|
|
265
|
-
/// #success on complete match
|
|
266
|
-
#success;
|
|
267
|
-
/// #fail(cs,c) on partial match of cs, but failing match on c
|
|
268
|
-
#fail : (cs : Iter.Iter<Char>, c : Char);
|
|
269
|
-
/// #empty(cs) on partial match of cs and empty stream
|
|
270
|
-
#empty : (cs : Iter.Iter<Char>)
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
private func sizeOfPattern(pat : Pattern) : Nat {
|
|
274
|
-
switch pat {
|
|
275
|
-
case (#text(t)) { t.size() };
|
|
276
|
-
case (#predicate(_) or #char(_)) { 1 }
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
private func matchOfPattern(pat : Pattern) : (cs : Iter.Iter<Char>) -> Match {
|
|
281
|
-
switch pat {
|
|
282
|
-
case (#char(p)) {
|
|
283
|
-
func(cs : Iter.Iter<Char>) : Match {
|
|
284
|
-
switch (cs.next()) {
|
|
285
|
-
case (?c) {
|
|
286
|
-
if (p == c) {
|
|
287
|
-
#success
|
|
288
|
-
} else {
|
|
289
|
-
#fail(empty(), c)
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
case null { #empty(empty()) }
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
case (#predicate(p)) {
|
|
297
|
-
func(cs : Iter.Iter<Char>) : Match {
|
|
298
|
-
switch (cs.next()) {
|
|
299
|
-
case (?c) {
|
|
300
|
-
if (p(c)) {
|
|
301
|
-
#success
|
|
302
|
-
} else {
|
|
303
|
-
#fail(empty(), c)
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
case null { #empty(empty()) }
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
|
-
case (#text(p)) {
|
|
311
|
-
func(cs : Iter.Iter<Char>) : Match {
|
|
312
|
-
var i = 0;
|
|
313
|
-
let ds = p.chars();
|
|
314
|
-
loop {
|
|
315
|
-
switch (ds.next()) {
|
|
316
|
-
case (?d) {
|
|
317
|
-
switch (cs.next()) {
|
|
318
|
-
case (?c) {
|
|
319
|
-
if (c != d) {
|
|
320
|
-
return #fail(take(i, p.chars()), c)
|
|
321
|
-
};
|
|
322
|
-
i += 1
|
|
323
|
-
};
|
|
324
|
-
case null {
|
|
325
|
-
return #empty(take(i, p.chars()))
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
case null { return #success }
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
private class CharBuffer(cs : Iter.Iter<Char>) : Iter.Iter<Char> = {
|
|
338
|
-
|
|
339
|
-
var stack : Stack.Stack<(Iter.Iter<Char>, Char)> = Stack.Stack();
|
|
340
|
-
|
|
341
|
-
public func pushBack(cs0 : Iter.Iter<Char>, c : Char) {
|
|
342
|
-
stack.push((cs0, c))
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
public func next() : ?Char {
|
|
346
|
-
switch (stack.peek()) {
|
|
347
|
-
case (?(buff, c)) {
|
|
348
|
-
switch (buff.next()) {
|
|
349
|
-
case null {
|
|
350
|
-
ignore stack.pop();
|
|
351
|
-
return ?c
|
|
352
|
-
};
|
|
353
|
-
case oc {
|
|
354
|
-
return oc
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
case null {
|
|
359
|
-
return cs.next()
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
/// Splits the input `Text` with the specified `Pattern`.
|
|
366
|
-
///
|
|
367
|
-
/// Two fields are separated by exactly one match.
|
|
368
|
-
///
|
|
369
|
-
/// ```motoko include=import
|
|
370
|
-
/// let words = Text.split("This is a sentence.", #char ' ');
|
|
371
|
-
/// Text.join("|", words) // "This|is|a|sentence."
|
|
372
|
-
/// ```
|
|
373
|
-
public func split(t : Text, p : Pattern) : Iter.Iter<Text> {
|
|
374
|
-
let match = matchOfPattern(p);
|
|
375
|
-
let cs = CharBuffer(t.chars());
|
|
376
|
-
var state = 0;
|
|
377
|
-
var field = "";
|
|
378
|
-
object {
|
|
379
|
-
public func next() : ?Text {
|
|
380
|
-
switch state {
|
|
381
|
-
case (0 or 1) {
|
|
382
|
-
loop {
|
|
383
|
-
switch (match(cs)) {
|
|
384
|
-
case (#success) {
|
|
385
|
-
let r = field;
|
|
386
|
-
field := "";
|
|
387
|
-
state := 1;
|
|
388
|
-
return ?r
|
|
389
|
-
};
|
|
390
|
-
case (#empty(cs1)) {
|
|
391
|
-
for (c in cs1) {
|
|
392
|
-
field #= fromChar(c)
|
|
393
|
-
};
|
|
394
|
-
let r = if (state == 0 and field == "") {
|
|
395
|
-
null
|
|
396
|
-
} else {
|
|
397
|
-
?field
|
|
398
|
-
};
|
|
399
|
-
state := 2;
|
|
400
|
-
return r
|
|
401
|
-
};
|
|
402
|
-
case (#fail(cs1, c)) {
|
|
403
|
-
cs.pushBack(cs1, c);
|
|
404
|
-
switch (cs.next()) {
|
|
405
|
-
case (?ci) {
|
|
406
|
-
field #= fromChar(ci)
|
|
407
|
-
};
|
|
408
|
-
case null {
|
|
409
|
-
let r = if (state == 0 and field == "") {
|
|
410
|
-
null
|
|
411
|
-
} else {
|
|
412
|
-
?field
|
|
413
|
-
};
|
|
414
|
-
state := 2;
|
|
415
|
-
return r
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
case _ { return null }
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
/// Returns a sequence of tokens from the input `Text` delimited by the specified `Pattern`, derived from start to end.
|
|
429
|
-
/// A "token" is a non-empty maximal subsequence of `t` not containing a match for pattern `p`.
|
|
430
|
-
/// Two tokens may be separated by one or more matches of `p`.
|
|
431
|
-
///
|
|
432
|
-
/// ```motoko include=import
|
|
433
|
-
/// let tokens = Text.tokens("this needs\n an example", #predicate (func(c) { c == ' ' or c == '\n' }));
|
|
434
|
-
/// Text.join("|", tokens) // "this|needs|an|example"
|
|
435
|
-
/// ```
|
|
436
|
-
public func tokens(t : Text, p : Pattern) : Iter.Iter<Text> {
|
|
437
|
-
let fs = split(t, p);
|
|
438
|
-
object {
|
|
439
|
-
public func next() : ?Text {
|
|
440
|
-
switch (fs.next()) {
|
|
441
|
-
case (?"") { next() };
|
|
442
|
-
case ot { ot }
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
/// Returns `true` if the input `Text` contains a match for the specified `Pattern`.
|
|
449
|
-
///
|
|
450
|
-
/// ```motoko include=import
|
|
451
|
-
/// Text.contains("Motoko", #text "oto") // true
|
|
452
|
-
/// ```
|
|
453
|
-
public func contains(t : Text, p : Pattern) : Bool {
|
|
454
|
-
let match = matchOfPattern(p);
|
|
455
|
-
let cs = CharBuffer(t.chars());
|
|
456
|
-
loop {
|
|
457
|
-
switch (match(cs)) {
|
|
458
|
-
case (#success) {
|
|
459
|
-
return true
|
|
460
|
-
};
|
|
461
|
-
case (#empty(cs1)) {
|
|
462
|
-
return false
|
|
463
|
-
};
|
|
464
|
-
case (#fail(cs1, c)) {
|
|
465
|
-
cs.pushBack(cs1, c);
|
|
466
|
-
switch (cs.next()) {
|
|
467
|
-
case null {
|
|
468
|
-
return false
|
|
469
|
-
};
|
|
470
|
-
case _ {}; // continue
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
/// Returns `true` if the input `Text` starts with a prefix matching the specified `Pattern`.
|
|
478
|
-
///
|
|
479
|
-
/// ```motoko include=import
|
|
480
|
-
/// Text.startsWith("Motoko", #text "Mo") // true
|
|
481
|
-
/// ```
|
|
482
|
-
public func startsWith(t : Text, p : Pattern) : Bool {
|
|
483
|
-
var cs = t.chars();
|
|
484
|
-
let match = matchOfPattern(p);
|
|
485
|
-
switch (match(cs)) {
|
|
486
|
-
case (#success) { true };
|
|
487
|
-
case _ { false }
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
|
|
491
|
-
/// Returns `true` if the input `Text` ends with a suffix matching the specified `Pattern`.
|
|
492
|
-
///
|
|
493
|
-
/// ```motoko include=import
|
|
494
|
-
/// Text.endsWith("Motoko", #char 'o') // true
|
|
495
|
-
/// ```
|
|
496
|
-
public func endsWith(t : Text, p : Pattern) : Bool {
|
|
497
|
-
let s2 = sizeOfPattern(p);
|
|
498
|
-
if (s2 == 0) return true;
|
|
499
|
-
let s1 = t.size();
|
|
500
|
-
if (s2 > s1) return false;
|
|
501
|
-
let match = matchOfPattern(p);
|
|
502
|
-
var cs1 = t.chars();
|
|
503
|
-
var diff : Nat = s1 - s2;
|
|
504
|
-
while (diff > 0) {
|
|
505
|
-
ignore cs1.next();
|
|
506
|
-
diff -= 1
|
|
507
|
-
};
|
|
508
|
-
switch (match(cs1)) {
|
|
509
|
-
case (#success) { true };
|
|
510
|
-
case _ { false }
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
/// Returns the input text `t` with all matches of pattern `p` replaced by text `r`.
|
|
515
|
-
///
|
|
516
|
-
/// ```motoko include=import
|
|
517
|
-
/// let result = Text.replace("abcabc", #char 'a', "A"); // "AbcAbc"
|
|
518
|
-
/// ```
|
|
519
|
-
public func replace(t : Text, p : Pattern, r : Text) : Text {
|
|
520
|
-
let match = matchOfPattern(p);
|
|
521
|
-
let size = sizeOfPattern(p);
|
|
522
|
-
let cs = CharBuffer(t.chars());
|
|
523
|
-
var res = "";
|
|
524
|
-
label l loop {
|
|
525
|
-
switch (match(cs)) {
|
|
526
|
-
case (#success) {
|
|
527
|
-
res #= r;
|
|
528
|
-
if (size > 0) {
|
|
529
|
-
continue l
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
case (#empty(cs1)) {
|
|
533
|
-
for (c1 in cs1) {
|
|
534
|
-
res #= fromChar(c1)
|
|
535
|
-
};
|
|
536
|
-
break l
|
|
537
|
-
};
|
|
538
|
-
case (#fail(cs1, c)) {
|
|
539
|
-
cs.pushBack(cs1, c)
|
|
540
|
-
}
|
|
541
|
-
};
|
|
542
|
-
switch (cs.next()) {
|
|
543
|
-
case null {
|
|
544
|
-
break l
|
|
545
|
-
};
|
|
546
|
-
case (?c1) {
|
|
547
|
-
res #= fromChar(c1)
|
|
548
|
-
}; // continue
|
|
549
|
-
}
|
|
550
|
-
};
|
|
551
|
-
return res
|
|
552
|
-
};
|
|
553
|
-
|
|
554
|
-
/// Strips one occurrence of the given `Pattern` from the beginning of the input `Text`.
|
|
555
|
-
/// If you want to remove multiple instances of the pattern, use `Text.trimStart()` instead.
|
|
556
|
-
///
|
|
557
|
-
/// ```motoko include=import
|
|
558
|
-
/// // Try to strip a nonexistent character
|
|
559
|
-
/// let none = Text.stripStart("abc", #char '-'); // null
|
|
560
|
-
/// // Strip just one '-'
|
|
561
|
-
/// let one = Text.stripStart("--abc", #char '-'); // ?"-abc"
|
|
562
|
-
/// ```
|
|
563
|
-
public func stripStart(t : Text, p : Pattern) : ?Text {
|
|
564
|
-
let s = sizeOfPattern(p);
|
|
565
|
-
if (s == 0) return ?t;
|
|
566
|
-
var cs = t.chars();
|
|
567
|
-
let match = matchOfPattern(p);
|
|
568
|
-
switch (match(cs)) {
|
|
569
|
-
case (#success) return ?fromIter(cs);
|
|
570
|
-
case _ return null
|
|
571
|
-
}
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
/// Strips one occurrence of the given `Pattern` from the end of the input `Text`.
|
|
575
|
-
/// If you want to remove multiple instances of the pattern, use `Text.trimEnd()` instead.
|
|
576
|
-
///
|
|
577
|
-
/// ```motoko include=import
|
|
578
|
-
/// // Try to strip a nonexistent character
|
|
579
|
-
/// let none = Text.stripEnd("xyz", #char '-'); // null
|
|
580
|
-
/// // Strip just one '-'
|
|
581
|
-
/// let one = Text.stripEnd("xyz--", #char '-'); // ?"xyz-"
|
|
582
|
-
/// ```
|
|
583
|
-
public func stripEnd(t : Text, p : Pattern) : ?Text {
|
|
584
|
-
let s2 = sizeOfPattern(p);
|
|
585
|
-
if (s2 == 0) return ?t;
|
|
586
|
-
let s1 = t.size();
|
|
587
|
-
if (s2 > s1) return null;
|
|
588
|
-
let match = matchOfPattern(p);
|
|
589
|
-
var cs1 = t.chars();
|
|
590
|
-
var diff : Nat = s1 - s2;
|
|
591
|
-
while (diff > 0) {
|
|
592
|
-
ignore cs1.next();
|
|
593
|
-
diff -= 1
|
|
594
|
-
};
|
|
595
|
-
switch (match(cs1)) {
|
|
596
|
-
case (#success) return ?extract(t, 0, s1 - s2);
|
|
597
|
-
case _ return null
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
|
-
|
|
601
|
-
/// Trims the given `Pattern` from the start of the input `Text`.
|
|
602
|
-
/// If you only want to remove a single instance of the pattern, use `Text.stripStart()` instead.
|
|
603
|
-
///
|
|
604
|
-
/// ```motoko include=import
|
|
605
|
-
/// let trimmed = Text.trimStart("---abc", #char '-'); // "abc"
|
|
606
|
-
/// ```
|
|
607
|
-
public func trimStart(t : Text, p : Pattern) : Text {
|
|
608
|
-
let cs = t.chars();
|
|
609
|
-
let size = sizeOfPattern(p);
|
|
610
|
-
if (size == 0) return t;
|
|
611
|
-
var matchSize = 0;
|
|
612
|
-
let match = matchOfPattern(p);
|
|
613
|
-
loop {
|
|
614
|
-
switch (match(cs)) {
|
|
615
|
-
case (#success) {
|
|
616
|
-
matchSize += size
|
|
617
|
-
}; // continue
|
|
618
|
-
case (#empty(cs1)) {
|
|
619
|
-
return if (matchSize == 0) {
|
|
620
|
-
t
|
|
621
|
-
} else {
|
|
622
|
-
fromIter(cs1)
|
|
623
|
-
}
|
|
624
|
-
};
|
|
625
|
-
case (#fail(cs1, c)) {
|
|
626
|
-
return if (matchSize == 0) {
|
|
627
|
-
t
|
|
628
|
-
} else {
|
|
629
|
-
fromIter(cs1) # fromChar(c) # fromIter(cs)
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
};
|
|
635
|
-
|
|
636
|
-
/// Trims the given `Pattern` from the end of the input `Text`.
|
|
637
|
-
/// If you only want to remove a single instance of the pattern, use `Text.stripEnd()` instead.
|
|
638
|
-
///
|
|
639
|
-
/// ```motoko include=import
|
|
640
|
-
/// let trimmed = Text.trimEnd("xyz---", #char '-'); // "xyz"
|
|
641
|
-
/// ```
|
|
642
|
-
public func trimEnd(t : Text, p : Pattern) : Text {
|
|
643
|
-
let cs = CharBuffer(t.chars());
|
|
644
|
-
let size = sizeOfPattern(p);
|
|
645
|
-
if (size == 0) return t;
|
|
646
|
-
let match = matchOfPattern(p);
|
|
647
|
-
var matchSize = 0;
|
|
648
|
-
label l loop {
|
|
649
|
-
switch (match(cs)) {
|
|
650
|
-
case (#success) {
|
|
651
|
-
matchSize += size
|
|
652
|
-
}; // continue
|
|
653
|
-
case (#empty(cs1)) {
|
|
654
|
-
switch (cs1.next()) {
|
|
655
|
-
case null break l;
|
|
656
|
-
case (?_) return t
|
|
657
|
-
}
|
|
658
|
-
};
|
|
659
|
-
case (#fail(cs1, c)) {
|
|
660
|
-
matchSize := 0;
|
|
661
|
-
cs.pushBack(cs1, c);
|
|
662
|
-
ignore cs.next()
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
|
-
extract(t, 0, t.size() - matchSize)
|
|
667
|
-
};
|
|
668
|
-
|
|
669
|
-
/// Trims the given `Pattern` from both the start and end of the input `Text`.
|
|
670
|
-
///
|
|
671
|
-
/// ```motoko include=import
|
|
672
|
-
/// let trimmed = Text.trim("---abcxyz---", #char '-'); // "abcxyz"
|
|
673
|
-
/// ```
|
|
674
|
-
public func trim(t : Text, p : Pattern) : Text {
|
|
675
|
-
let cs = t.chars();
|
|
676
|
-
let size = sizeOfPattern(p);
|
|
677
|
-
if (size == 0) return t;
|
|
678
|
-
var matchSize = 0;
|
|
679
|
-
let match = matchOfPattern(p);
|
|
680
|
-
loop {
|
|
681
|
-
switch (match(cs)) {
|
|
682
|
-
case (#success) {
|
|
683
|
-
matchSize += size
|
|
684
|
-
}; // continue
|
|
685
|
-
case (#empty(cs1)) {
|
|
686
|
-
return if (matchSize == 0) { t } else { fromIter(cs1) }
|
|
687
|
-
};
|
|
688
|
-
case (#fail(cs1, c)) {
|
|
689
|
-
let start = matchSize;
|
|
690
|
-
let cs2 = CharBuffer(cs);
|
|
691
|
-
cs2.pushBack(cs1, c);
|
|
692
|
-
ignore cs2.next();
|
|
693
|
-
matchSize := 0;
|
|
694
|
-
label l loop {
|
|
695
|
-
switch (match(cs2)) {
|
|
696
|
-
case (#success) {
|
|
697
|
-
matchSize += size
|
|
698
|
-
}; // continue
|
|
699
|
-
case (#empty(cs3)) {
|
|
700
|
-
switch (cs1.next()) {
|
|
701
|
-
case null break l;
|
|
702
|
-
case (?_) return t
|
|
703
|
-
}
|
|
704
|
-
};
|
|
705
|
-
case (#fail(cs3, c1)) {
|
|
706
|
-
matchSize := 0;
|
|
707
|
-
cs2.pushBack(cs3, c1);
|
|
708
|
-
ignore cs2.next()
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
};
|
|
712
|
-
return extract(t, start, t.size() - matchSize - start)
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
|
|
718
|
-
/// Compares `t1` and `t2` using the provided character-wise comparison function.
|
|
719
|
-
///
|
|
720
|
-
/// ```motoko include=import
|
|
721
|
-
/// import Char "mo:base/Char";
|
|
722
|
-
///
|
|
723
|
-
/// Text.compareWith("abc", "ABC", func(c1, c2) { Char.compare(c1, c2) }) // #greater
|
|
724
|
-
/// ```
|
|
725
|
-
public func compareWith(
|
|
726
|
-
t1 : Text,
|
|
727
|
-
t2 : Text,
|
|
728
|
-
cmp : (Char, Char) -> { #less; #equal; #greater }
|
|
729
|
-
) : { #less; #equal; #greater } {
|
|
730
|
-
let cs1 = t1.chars();
|
|
731
|
-
let cs2 = t2.chars();
|
|
732
|
-
loop {
|
|
733
|
-
switch (cs1.next(), cs2.next()) {
|
|
734
|
-
case (null, null) { return #equal };
|
|
735
|
-
case (null, ?_) { return #less };
|
|
736
|
-
case (?_, null) { return #greater };
|
|
737
|
-
case (?c1, ?c2) {
|
|
738
|
-
switch (cmp(c1, c2)) {
|
|
739
|
-
case (#equal) {}; // continue
|
|
740
|
-
case other { return other }
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
|
|
747
|
-
/// Returns a UTF-8 encoded `Blob` from the given `Text`.
|
|
748
|
-
///
|
|
749
|
-
/// ```motoko include=import
|
|
750
|
-
/// let blob = Text.encodeUtf8("Hello");
|
|
751
|
-
/// ```
|
|
752
|
-
public let encodeUtf8 : Text -> Blob = Prim.encodeUtf8;
|
|
753
|
-
|
|
754
|
-
/// Tries to decode the given `Blob` as UTF-8.
|
|
755
|
-
/// Returns `null` if the blob is not valid UTF-8.
|
|
756
|
-
///
|
|
757
|
-
/// ```motoko include=import
|
|
758
|
-
/// let text = Text.decodeUtf8("\48\65\6C\6C\6F"); // ?"Hello"
|
|
759
|
-
/// ```
|
|
760
|
-
public let decodeUtf8 : Blob -> ?Text = Prim.decodeUtf8
|
|
761
|
-
}
|