@ugo-studio/jspp 0.1.2 → 0.1.3
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/README.md +3 -1
- package/dist/analysis/scope.js +22 -11
- package/dist/analysis/typeAnalyzer.js +4 -3
- package/dist/cli.js +2 -2
- package/dist/core/codegen/expression-handlers.js +10 -6
- package/dist/core/codegen/function-handlers.js +27 -6
- package/dist/core/codegen/helpers.js +12 -8
- package/dist/core/codegen/index.js +3 -1
- package/dist/core/codegen/statement-handlers.js +53 -16
- package/dist/core/codegen/visitor.js +7 -1
- package/package.json +1 -1
- package/src/prelude/access.hpp +8 -3
- package/src/prelude/any_value.hpp +141 -241
- package/src/prelude/any_value_helpers.hpp +225 -0
- package/src/prelude/error_helpers.hpp +3 -3
- package/src/prelude/index.hpp +17 -3
- package/src/prelude/library/console.hpp +7 -7
- package/src/prelude/library/performance.hpp +25 -0
- package/src/prelude/library/symbol.hpp +60 -3
- package/src/prelude/log_string.hpp +10 -6
- package/src/prelude/operators.hpp +2 -2
- package/src/prelude/types.hpp +24 -6
- package/src/prelude/values/array.hpp +2 -0
- package/src/prelude/values/function.hpp +33 -1
- package/src/prelude/values/{operators → helpers}/array.hpp +14 -7
- package/src/prelude/values/helpers/function.hpp +77 -0
- package/src/prelude/values/helpers/iterator.hpp +101 -0
- package/src/prelude/values/helpers/string.hpp +50 -0
- package/src/prelude/values/helpers/symbol.hpp +23 -0
- package/src/prelude/values/iterator.hpp +88 -0
- package/src/prelude/values/object.hpp +2 -1
- package/src/prelude/values/prototypes/array.hpp +18 -11
- package/src/prelude/values/prototypes/function.hpp +26 -0
- package/src/prelude/values/prototypes/iterator.hpp +57 -0
- package/src/prelude/values/prototypes/string.hpp +366 -357
- package/src/prelude/values/prototypes/symbol.hpp +39 -0
- package/src/prelude/values/string.hpp +25 -0
- package/src/prelude/values/symbol.hpp +102 -0
- package/src/prelude/well_known_symbols.hpp +7 -3
- package/src/prelude/values/operators/function.hpp +0 -34
- /package/src/prelude/values/{operators → helpers}/object.hpp +0 -0
|
@@ -1,357 +1,366 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include "types.hpp"
|
|
4
|
-
#include "
|
|
5
|
-
#include "
|
|
6
|
-
#include
|
|
7
|
-
#include <
|
|
8
|
-
#include <
|
|
9
|
-
#include <
|
|
10
|
-
#include <
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
std::string
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return AnyValue::make_string(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return AnyValue::make_string(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "values/string.hpp" // Make sure this is included
|
|
5
|
+
#include "any_value.hpp"
|
|
6
|
+
#include "operators.hpp"
|
|
7
|
+
#include <optional>
|
|
8
|
+
#include <string>
|
|
9
|
+
#include <vector>
|
|
10
|
+
#include <algorithm>
|
|
11
|
+
#include <cctype>
|
|
12
|
+
|
|
13
|
+
namespace jspp
|
|
14
|
+
{
|
|
15
|
+
namespace StringPrototypes
|
|
16
|
+
{
|
|
17
|
+
// This function retrieves a prototype method for a given string instance.
|
|
18
|
+
// It captures the string instance to act as the 'this' context for the method.
|
|
19
|
+
inline std::optional<AnyValue> get(const std::string &key, JsString *self)
|
|
20
|
+
{
|
|
21
|
+
// --- toString() & valueOf() ---
|
|
22
|
+
if (key == "toString" || key == WellKnownSymbols::toString->key || key == "valueOf")
|
|
23
|
+
{
|
|
24
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
25
|
+
{ return AnyValue::make_string(self->value); },
|
|
26
|
+
key);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// --- [Symbol.iterator]() method ---
|
|
30
|
+
if (key == WellKnownSymbols::iterator->key)
|
|
31
|
+
{
|
|
32
|
+
return AnyValue::make_generator([self](const std::vector<AnyValue> &_) -> AnyValue
|
|
33
|
+
{ return AnyValue::from_iterator(self->get_iterator()); },
|
|
34
|
+
key);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// --- length property ---
|
|
38
|
+
if (key == "length")
|
|
39
|
+
{
|
|
40
|
+
return AnyValue::make_accessor_descriptor([self](const std::vector<AnyValue>) -> AnyValue
|
|
41
|
+
{ return AnyValue::make_number(self->value.length()); },
|
|
42
|
+
[self](const std::vector<AnyValue>) -> AnyValue
|
|
43
|
+
{ return AnyValue::make_undefined(); },
|
|
44
|
+
false,
|
|
45
|
+
false);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// --- charAt(pos) ---
|
|
49
|
+
if (key == "charAt")
|
|
50
|
+
{
|
|
51
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
52
|
+
{
|
|
53
|
+
double pos = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
|
|
54
|
+
int index = static_cast<int>(pos);
|
|
55
|
+
if (index < 0 || index >= self->value.length()) {
|
|
56
|
+
return AnyValue::make_string("");
|
|
57
|
+
}
|
|
58
|
+
return AnyValue::make_string(std::string(1, self->value[index])); },
|
|
59
|
+
key);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// --- concat(str1, str2, ...) ---
|
|
63
|
+
if (key == "concat")
|
|
64
|
+
{
|
|
65
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
66
|
+
{
|
|
67
|
+
std::string result = self->value;
|
|
68
|
+
for (const auto& arg : args)
|
|
69
|
+
{
|
|
70
|
+
result += arg.to_std_string();
|
|
71
|
+
}
|
|
72
|
+
return AnyValue::make_string(result); },
|
|
73
|
+
key);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// --- endsWith(searchString, endPosition) ---
|
|
77
|
+
if (key == "endsWith")
|
|
78
|
+
{
|
|
79
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
80
|
+
{
|
|
81
|
+
if(args.empty()) return AnyValue::make_boolean(false);
|
|
82
|
+
std::string search = args[0].to_std_string();
|
|
83
|
+
size_t end_pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : self->value.length();
|
|
84
|
+
|
|
85
|
+
if (end_pos > self->value.length()) end_pos = self->value.length();
|
|
86
|
+
if (search.length() > end_pos) return AnyValue::make_boolean(false);
|
|
87
|
+
|
|
88
|
+
return AnyValue::make_boolean(self->value.substr(end_pos - search.length(), search.length()) == search); },
|
|
89
|
+
key);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// --- includes(searchString, position) ---
|
|
93
|
+
if (key == "includes")
|
|
94
|
+
{
|
|
95
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
96
|
+
{
|
|
97
|
+
if(args.empty()) return AnyValue::make_boolean(false);
|
|
98
|
+
std::string search = args[0].to_std_string();
|
|
99
|
+
size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
|
|
100
|
+
|
|
101
|
+
return AnyValue::make_boolean(self->value.find(search, pos) != std::string::npos); },
|
|
102
|
+
key);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// --- indexOf(searchString, position) ---
|
|
106
|
+
if (key == "indexOf")
|
|
107
|
+
{
|
|
108
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
109
|
+
{
|
|
110
|
+
if (args.empty()) return AnyValue::make_number(-1);
|
|
111
|
+
std::string search = args[0].to_std_string();
|
|
112
|
+
size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
|
|
113
|
+
size_t result = self->value.find(search, pos);
|
|
114
|
+
return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
|
|
115
|
+
key);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// --- lastIndexOf(searchString, position) ---
|
|
119
|
+
if (key == "lastIndexOf")
|
|
120
|
+
{
|
|
121
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
122
|
+
{
|
|
123
|
+
if (args.empty()) return AnyValue::make_number(-1);
|
|
124
|
+
std::string search = args[0].to_std_string();
|
|
125
|
+
size_t pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : std::string::npos;
|
|
126
|
+
size_t result = self->value.rfind(search, pos);
|
|
127
|
+
return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
|
|
128
|
+
key);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// --- padEnd(targetLength, padString) ---
|
|
132
|
+
if (key == "padEnd")
|
|
133
|
+
{
|
|
134
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
135
|
+
{
|
|
136
|
+
size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
|
|
137
|
+
if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
|
|
138
|
+
std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
|
|
139
|
+
std::string result = self->value;
|
|
140
|
+
while (result.length() < target_length)
|
|
141
|
+
{
|
|
142
|
+
result += pad_string;
|
|
143
|
+
}
|
|
144
|
+
return AnyValue::make_string(result.substr(0, target_length)); },
|
|
145
|
+
key);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// --- padStart(targetLength, padString) ---
|
|
149
|
+
if (key == "padStart")
|
|
150
|
+
{
|
|
151
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
152
|
+
{
|
|
153
|
+
size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
|
|
154
|
+
if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
|
|
155
|
+
std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
|
|
156
|
+
std::string padding;
|
|
157
|
+
while (padding.length() < target_length - self->value.length())
|
|
158
|
+
{
|
|
159
|
+
padding += pad_string;
|
|
160
|
+
}
|
|
161
|
+
return AnyValue::make_string(padding.substr(0, target_length - self->value.length()) + self->value); },
|
|
162
|
+
key);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// --- repeat(count) ---
|
|
166
|
+
if (key == "repeat")
|
|
167
|
+
{
|
|
168
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
169
|
+
{
|
|
170
|
+
double count = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
|
|
171
|
+
if (count < 0) {
|
|
172
|
+
// In a real implementation, this should throw a RangeError.
|
|
173
|
+
return AnyValue::make_string("");
|
|
174
|
+
}
|
|
175
|
+
std::string result = "";
|
|
176
|
+
for (int i = 0; i < count; ++i)
|
|
177
|
+
{
|
|
178
|
+
result += self->value;
|
|
179
|
+
}
|
|
180
|
+
return AnyValue::make_string(result); },
|
|
181
|
+
key);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// --- replace(substr, newSubstr) ---
|
|
185
|
+
if (key == "replace")
|
|
186
|
+
{
|
|
187
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
188
|
+
{
|
|
189
|
+
if (args.size() < 2) return AnyValue::make_string(self->value);
|
|
190
|
+
std::string search = args[0].to_std_string();
|
|
191
|
+
std::string replacement = args[1].to_std_string();
|
|
192
|
+
std::string result = self->value;
|
|
193
|
+
size_t pos = result.find(search);
|
|
194
|
+
if (pos != std::string::npos)
|
|
195
|
+
{
|
|
196
|
+
result.replace(pos, search.length(), replacement);
|
|
197
|
+
}
|
|
198
|
+
return AnyValue::make_string(result); },
|
|
199
|
+
key);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// --- replaceAll(substr, newSubstr) ---
|
|
203
|
+
if (key == "replaceAll")
|
|
204
|
+
{
|
|
205
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
206
|
+
{
|
|
207
|
+
if (args.size() < 2) return AnyValue::make_string(self->value);
|
|
208
|
+
std::string search = args[0].to_std_string();
|
|
209
|
+
if (search.empty()) return AnyValue::make_string(self->value);
|
|
210
|
+
std::string replacement = args[1].to_std_string();
|
|
211
|
+
std::string result = self->value;
|
|
212
|
+
size_t pos = result.find(search);
|
|
213
|
+
while (pos != std::string::npos)
|
|
214
|
+
{
|
|
215
|
+
result.replace(pos, search.length(), replacement);
|
|
216
|
+
pos = result.find(search, pos + replacement.length());
|
|
217
|
+
}
|
|
218
|
+
return AnyValue::make_string(result); },
|
|
219
|
+
key);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// --- slice(beginIndex, endIndex) ---
|
|
223
|
+
if (key == "slice")
|
|
224
|
+
{
|
|
225
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
226
|
+
{
|
|
227
|
+
int len = self->value.length();
|
|
228
|
+
int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
|
|
229
|
+
int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
|
|
230
|
+
|
|
231
|
+
if (start < 0) start += len;
|
|
232
|
+
if (end < 0) end += len;
|
|
233
|
+
|
|
234
|
+
start = std::max(0, std::min(len, start));
|
|
235
|
+
end = std::max(0, std::min(len, end));
|
|
236
|
+
|
|
237
|
+
if (start >= end) return AnyValue::make_string("");
|
|
238
|
+
return AnyValue::make_string(self->value.substr(start, end - start)); },
|
|
239
|
+
key);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// --- split(separator) ---
|
|
243
|
+
if (key == "split")
|
|
244
|
+
{
|
|
245
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
246
|
+
{
|
|
247
|
+
std::string separator = (args.empty() || args[0].is_undefined()) ? "" : args[0].to_std_string();
|
|
248
|
+
std::vector<std::optional<AnyValue>> result_vec;
|
|
249
|
+
|
|
250
|
+
if (separator.empty()) {
|
|
251
|
+
for (char c : (self->value)) {
|
|
252
|
+
result_vec.push_back(AnyValue::make_string(std::string(1, c)));
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
255
|
+
std::string temp = (self->value);
|
|
256
|
+
size_t pos = 0;
|
|
257
|
+
while ((pos = temp.find(separator)) != std::string::npos) {
|
|
258
|
+
result_vec.push_back(AnyValue::make_string(temp.substr(0, pos)));
|
|
259
|
+
temp.erase(0, pos + separator.length());
|
|
260
|
+
}
|
|
261
|
+
result_vec.push_back(AnyValue::make_string(temp));
|
|
262
|
+
}
|
|
263
|
+
return AnyValue::make_array(result_vec); },
|
|
264
|
+
key);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// --- startsWith(searchString, position) ---
|
|
268
|
+
if (key == "startsWith")
|
|
269
|
+
{
|
|
270
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
271
|
+
{
|
|
272
|
+
if(args.empty()) return AnyValue::make_boolean(false);
|
|
273
|
+
std::string search = args[0].to_std_string();
|
|
274
|
+
size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
|
|
275
|
+
if (pos > self->value.length()) pos = self->value.length();
|
|
276
|
+
|
|
277
|
+
return AnyValue::make_boolean(self->value.rfind(search, pos) == pos); },
|
|
278
|
+
key);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// --- substring(indexStart, indexEnd) ---
|
|
282
|
+
if (key == "substring")
|
|
283
|
+
{
|
|
284
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
285
|
+
{
|
|
286
|
+
int len = self->value.length();
|
|
287
|
+
int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
|
|
288
|
+
int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
|
|
289
|
+
|
|
290
|
+
start = std::max(0, start);
|
|
291
|
+
end = std::max(0, end);
|
|
292
|
+
|
|
293
|
+
if (start > end) std::swap(start, end);
|
|
294
|
+
|
|
295
|
+
start = std::min(len, start);
|
|
296
|
+
end = std::min(len, end);
|
|
297
|
+
|
|
298
|
+
return AnyValue::make_string(self->value.substr(start, end - start)); },
|
|
299
|
+
key);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// --- toLowerCase() ---
|
|
303
|
+
if (key == "toLowerCase")
|
|
304
|
+
{
|
|
305
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
306
|
+
{
|
|
307
|
+
std::string result = self->value;
|
|
308
|
+
std::transform(result.begin(), result.end(), result.begin(),
|
|
309
|
+
[](unsigned char c){ return std::tolower(c); });
|
|
310
|
+
return AnyValue::make_string(result); },
|
|
311
|
+
key);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// --- toUpperCase() ---
|
|
315
|
+
if (key == "toUpperCase")
|
|
316
|
+
{
|
|
317
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
318
|
+
{
|
|
319
|
+
std::string result = self->value;
|
|
320
|
+
std::transform(result.begin(), result.end(), result.begin(),
|
|
321
|
+
[](unsigned char c){ return std::toupper(c); });
|
|
322
|
+
return AnyValue::make_string(result); },
|
|
323
|
+
key);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// --- trim() ---
|
|
327
|
+
if (key == "trim")
|
|
328
|
+
{
|
|
329
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
330
|
+
{
|
|
331
|
+
const char* whitespace = " \t\n\r\f\v";
|
|
332
|
+
std::string result = self->value;
|
|
333
|
+
result.erase(0, result.find_first_not_of(whitespace));
|
|
334
|
+
result.erase(result.find_last_not_of(whitespace) + 1);
|
|
335
|
+
return AnyValue::make_string(result); },
|
|
336
|
+
key);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// --- trimEnd() ---
|
|
340
|
+
if (key == "trimEnd")
|
|
341
|
+
{
|
|
342
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
343
|
+
{
|
|
344
|
+
const char* whitespace = " \t\n\r\f\v";
|
|
345
|
+
std::string result = self->value;
|
|
346
|
+
result.erase(result.find_last_not_of(whitespace) + 1);
|
|
347
|
+
return AnyValue::make_string(result); },
|
|
348
|
+
key);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// --- trimStart() ---
|
|
352
|
+
if (key == "trimStart")
|
|
353
|
+
{
|
|
354
|
+
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
355
|
+
{
|
|
356
|
+
const char* whitespace = " \t\n\r\f\v";
|
|
357
|
+
std::string result = self->value;
|
|
358
|
+
result.erase(0, result.find_first_not_of(whitespace));
|
|
359
|
+
return AnyValue::make_string(result); },
|
|
360
|
+
key);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return std::nullopt;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|