Gwion coverage report


Directory: src/
File: src/lib/string.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 308 430 71.6%
Functions: 31 41 75.6%
Branches: 99 176 56.2%

Line Branch Exec Source
1 #include <stdlib.h>
2 #include <string.h>
3 #include <math.h>
4 #include "gwion_util.h"
5 #include "gwion_ast.h"
6 #include "gwion_env.h"
7 #include "vm.h"
8 #include "instr.h"
9 #include "gwion.h"
10 #include "object.h"
11 #include "operator.h"
12 #include "import.h"
13 #include "emit.h"
14 #include "specialid.h"
15 #include "gwi.h"
16 #include "gack.h"
17 #include "array.h"
18
19 #define describe_string_logical(name, action) \
20 static INSTR(String_##name) { \
21 POP_REG(shred, SZ_INT); \
22 const M_Object lhs = *(M_Object *)REG(-SZ_INT); \
23 const M_Object rhs = *(M_Object *)REG(0); \
24 *(m_int *)REG(-SZ_INT) = action; \
25 }
26 6 describe_string_logical(eq, (!strcmp(STRING(lhs), STRING(rhs))))
27 2 describe_string_logical(neq, (strcmp(STRING(lhs), STRING(rhs))))
28
29 20 static inline uint is_const_str(const Exp exp) {
30
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
40 return exp->exp_type == ae_exp_primary &&
31
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 13 times.
20 exp->d.prim.prim_type == ae_prim_str;
32 }
33
34 #define opck_str(name, __exp__) \
35 OP_CHECK(opck_string_##name) { \
36 Exp_Binary *bin = (Exp_Binary *)data; \
37 if (!is_const_str(bin->lhs) || !is_const_str(bin->rhs)) \
38 return env->gwion->type[et_bool]; \
39 const int ret = __exp__; \
40 free_exp(env->gwion->mp, bin->lhs); \
41 free_exp(env->gwion->mp, bin->rhs); \
42 const Exp e = exp_self(bin); \
43 e->exp_type = ae_exp_primary; \
44 e->d.prim.prim_type = ae_prim_num; \
45 e->d.prim.d.num = ret; \
46 return env->gwion->type[et_bool]; \
47 }
48
49
4/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
14 opck_str(eq, !strcmp(bin->lhs->d.prim.d.string.data, bin->rhs->d.prim.d.string.data))
50
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 opck_str(neq, strcmp(bin->lhs->d.prim.d.string.data, bin->rhs->d.prim.d.string.data))
51
52 9 static CTOR(string_ctor) {
53 9 STRING(o) = _mp_calloc(shred->info->mp, 1);
54 9 }
55
56 121 static DTOR(string_dtor) { free_mstr(shred->info->mp, STRING(o)); }
57
58 2 ID_CHECK(check_filepp) {
59 2 ((Exp_Primary *)prim)->prim_type = ae_prim_str;
60 2 ((Exp_Primary *)prim)->d.string.data = env->name;
61 2 ((Exp_Primary *)prim)->value = global_string(env, prim->d.string.data, prim_pos(prim));
62 2 return prim->value->type;
63 }
64
65 45 ID_CHECK(check_funcpp) {
66 45 ((Exp_Primary *)prim)->prim_type = ae_prim_str;
67 134 ((Exp_Primary *)prim)->d.string.data = env->func ? env->func->name
68
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 1 times.
46 : env->class_def ? env->class_def->name
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 : env->name;
70 // handle delim?
71 45 ((Exp_Primary *)prim)->value = global_string(env, prim->d.string.data, prim_pos(prim));
72 45 return prim->value->type;
73 }
74
75 ID_CHECK(check_linepp) {
76 ((Exp_Primary *)prim)->prim_type = ae_prim_num;
77 ((Exp_Primary *)prim)->d.num = prim_pos(prim).first.line;
78 return env->gwion->type[et_int];
79 }
80
81 784 static GACK(gack_string) {
82 784 const M_Object obj = *(M_Object *)VALUE;
83
1/2
✓ Branch 0 taken 784 times.
✗ Branch 1 not taken.
784 INTERP_PRINTF("%s", obj ? STRING(obj) : "(null string)");
84 784 }
85
86 5 static inline m_bool bounds(const m_str str, const m_int i) {
87
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 CHECK_BB(i);
88
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 return (m_uint)i <= strlen(str) ? GW_OK : GW_ERROR;
89 }
90
91 3 static INSTR(StringSlice) {
92 3 shred->reg -= SZ_INT * 2;
93 3 const M_Object obj = *(M_Object *)REG(-SZ_INT);
94 3 m_str str = STRING(obj);
95 3 const m_int start = *(m_uint *)REG(0);
96 3 const size_t strsz = strlen(str);
97 3 m_int end = *(m_uint *)REG(SZ_INT);
98
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (end < 0) end = strsz + end - 1;
99
3/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
3 if (bounds(str, start) < 0 || bounds(str, end) < 0) {
100 1 handle(shred, "OutOfBoundsStringSlice");
101 1 return;
102 }
103
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 const m_int op = start < end ? 1 : -1;
104
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 const m_uint sz = (op > 0 ? end - start : start - end) + 1;
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(sz >= SIZE_MAX/SZ_INT) {
106 handle(shred, "SliceTooBig");
107 return;
108 }
109 2 char c[sz + 1];
110
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 for (m_int i = start, j = 0; j < (m_int)sz; i += op, ++j) c[j] = str[i];
111 2 c[sz] = '\0';
112 2 *(M_Object *)REG(-SZ_INT) = new_string(shred->info->vm->gwion, c);
113 }
114
115 1 static MFUN(string_len) { *(m_uint *)RETURN = strlen(STRING(o)); }
116
117 1 static MFUN(string_upper) {
118 1 char c[strlen(STRING(o)) + 1];
119 1 strcpy(c, STRING(o));
120
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 for (m_uint i = 0; i < strlen(c); i++)
121
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
11 if (c[i] >= 'a' && c[i] <= 'z') c[i] += 'A' - 'a';
122 1 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
123 1 }
124
125 1 static MFUN(string_lower) {
126 1 char c[strlen(STRING(o)) + 1];
127 1 strcpy(c, STRING(o));
128
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 for (m_uint i = 0; i < strlen(c); i++)
129
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
11 if (c[i] >= 'A' && c[i] <= 'Z') c[i] -= 'A' - 'a';
130 1 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
131 1 }
132
133 2 static MFUN(string_ltrim) {
134 2 m_uint i = 0;
135 2 const m_str str = STRING(o);
136
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 while (str[i] == ' ') i++;
137 2 char c[strlen(str) - i + 1];
138 2 strcpy(c, STRING(o) + i);
139 2 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
140 2 }
141
142 2 static MFUN(string_rtrim) {
143 2 const m_str str = STRING(o);
144 2 const size_t sz = strlen(str);
145
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (sz) {
146 1 m_uint len = strlen(str) - 1;
147
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 while (str[len] == ' ') len--;
148 1 char c[len + 2];
149 1 strncpy(c, str, len + 1);
150 1 c[len + 1] = '\0';
151 1 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
152 } else {
153 1 ++o->ref;
154 1 *(M_Object *)RETURN = o;
155 }
156 2 }
157
158 2 static MFUN(string_trim) {
159 2 const m_str str = STRING(o);
160 2 m_int i, start = 0, end = 0, len = 0;
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 while (str[len] != '\0') len++;
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (i = 0; i < len; i++) {
163 if (str[i] == ' ')
164 start++;
165 else
166 break;
167 }
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (i = len - 1; i >= 0; i--) {
169 if (str[i] == ' ')
170 end++;
171 else
172 break;
173 }
174
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (len - start - end <= 0) {
175 2 xfun_handle(shred, "InvalidStringTrimRequest");
176 2 return;
177 }
178 char c[len - start - end + 1];
179 for (i = start; i < len - end; i++) c[i - start] = str[i];
180 c[len - start - end] = '\0';
181 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
182 }
183
184 static MFUN(string_insert) {
185 char str[strlen(STRING(o)) + 1];
186 strcpy(str, STRING(o));
187 m_int i, len_insert = 0, index = *(m_int *)MEM(SZ_INT);
188 const M_Object arg = *(M_Object *)MEM(SZ_INT * 2);
189 char insert[strlen(STRING(arg)) + 1];
190 strcpy(insert, STRING(arg));
191 const m_uint len = strlen(str);
192 len_insert = strlen(insert);
193 char c[len + len_insert + 1];
194 for (i = 0; i < index; i++) c[i] = str[i];
195 for (i = 0; i < len_insert; i++) c[i + index] = insert[i];
196 for (i = index; i < (m_int)len; i++) c[i + len_insert] = str[i];
197 c[len + len_insert] = '\0';
198 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
199 ;
200 }
201
202 static MFUN(string_replace) {
203 char str[strlen(STRING(o)) + 1];
204 strcpy(str, STRING(o));
205 m_int i, len_insert = 0, index = *(m_int *)MEM(SZ_INT);
206 const M_Object arg = *(M_Object *)MEM(SZ_INT * 2);
207 if (!arg) {
208 *(M_Object *)RETURN = o;
209 return;
210 }
211 char insert[strlen(STRING(arg)) + 1];
212 strcpy(insert, STRING(arg));
213 const m_uint len = strlen(str);
214 len_insert = strlen(insert);
215 if (index >= (m_int)len || index < 0 || (index + len_insert + 1) <= 0) {
216 xfun_handle(shred, "InvalidStringReplace");
217 return;
218 }
219 char c[index + len_insert + 1];
220 for (i = 0; i < index; i++) c[i] = str[i];
221 for (i = 0; i < len_insert; i++) c[i + index] = insert[i];
222 c[index + len_insert] = '\0';
223 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
224 ;
225 }
226
227 1 static MFUN(string_replaceN) {
228 1 char str[strlen(STRING(o)) + 1];
229 1 strcpy(str, STRING(o));
230 1 m_int i, index = *(m_int *)MEM(SZ_INT);
231 1 const M_Object arg = *(M_Object *)MEM(SZ_INT * 3);
232 1 const m_int _len = *(m_int *)MEM(SZ_INT * 2);
233
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (!arg || index > (m_int)strlen(STRING(o)) ||
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 _len > (m_int)strlen(STRING(arg))) {
235 xfun_handle(shred, "InvalidStringReplace");
236 return;
237 }
238 1 char insert[strlen(STRING(arg)) + 1];
239 1 const m_uint len = strlen(str);
240 // memset(insert, 0, len + 1);
241 1 strcpy(insert, STRING(arg));
242 1 str[len] = '\0';
243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (index > (m_int)len) index = len - 1;
244 1 char c[len + _len];
245 1 memset(c, 0, len + _len);
246
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = 0; i < index; i++) c[i] = str[i];
247
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (i = 0; i < _len; i++) c[i + index] = insert[i];
248
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (i = index + _len; i < (m_int)len; i++) c[i] = str[i];
249 1 c[len + _len - 1] = '\0';
250 1 *(M_Object *)RETURN = new_string(shred->info->vm->gwion, c);
251 ;
252 }
253
254 3 static MFUN(string_find) {
255 3 const m_str base = STRING(o);
256 3 char c = *(m_int *)MEM(SZ_INT);
257 3 char * str = strchr(base, c);
258
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 *(m_uint *)RETURN = str ? str - base : -1;
259 3 }
260
261 4 static MFUN(string_findStart) {
262 4 const m_str base = STRING(o);
263 4 const size_t sz = strlen(base);
264 4 const int pos = *(m_int *)MEM(SZ_INT * 2);
265
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
4 if (pos >= 0 && (size_t)pos < sz) {
266 2 const char arg = *(m_int *)MEM(SZ_INT);
267 2 char * str = strchr(base + pos, arg);
268
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 *(m_uint *)RETURN = str ? str - pos - base : -1;
269 } else
270 2 *(m_uint *)RETURN = -1;
271 4 }
272
273 3 static MFUN(string_findStr) {
274 3 const m_str base = STRING(o);
275 3 const size_t sz = strlen(base);
276 3 const M_Object obj = *(M_Object *)MEM(SZ_INT);
277
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (sz) {
278 2 const m_str arg = STRING(obj);
279 2 const m_str str = strstr(base, arg);
280
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 *(m_uint *)RETURN = str ? str - base : -1;
281 } else
282 1 *(m_uint *)RETURN = -1;
283 3 }
284
285 4 static MFUN(string_findStrStart) {
286 4 const m_str base = STRING(o);
287 4 const size_t sz = strlen(base);
288 4 const int pos = *(m_int *)MEM(SZ_INT * 2);
289 4 const M_Object obj = *(M_Object *)MEM(SZ_INT);
290
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
4 if (pos >= 0 && (size_t)pos < sz) {
291 2 const m_str arg = STRING(obj);
292 2 const m_str str = strstr(base + pos, arg);
293
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 *(m_uint *)RETURN = str ? str - pos - base : -1;
294 } else
295 2 *(m_uint *)RETURN = -1;
296 4 }
297
298 static MFUN(string_rfind) {
299 const m_str base = STRING(o);
300 char c = *(m_int *)MEM(SZ_INT);
301 char * str = strrchr(base, c);
302 *(m_uint *)RETURN = str ? str - base : -1;
303 }
304
305 static MFUN(string_rfindStart) {
306 const m_str base = STRING(o);
307 const size_t sz = strlen(base);
308 const int pos = *(m_int *)MEM(SZ_INT);
309 if (pos >= 0 && (size_t)pos < sz) {
310 const char arg = *(m_int *)MEM(SZ_INT * 2);
311 char * str = strrchr(base + pos, arg);
312 *(m_uint *)RETURN = str ? str - pos - base : -1;
313 } else
314 *(m_uint *)RETURN = -1;
315 }
316
317 3 static MFUN(string_rfindStr) {
318 3 const m_str base = STRING(o);
319 3 const size_t sz = strlen(base);
320 3 const M_Object obj = *(M_Object *)MEM(SZ_INT);
321
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (sz) {
322 2 const m_str arg = STRING(obj);
323 2 m_str tmp = base, str = NULL;
324
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 while ((tmp = strstr(tmp, arg))) str = tmp++;
325
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 *(m_uint *)RETURN = str ? str - base : -1;
326 } else
327 1 *(m_uint *)RETURN = -1;
328 3 }
329
330 4 static MFUN(string_rfindStrStart) {
331 4 const m_str base = STRING(o);
332 4 const size_t sz = strlen(base);
333 4 const m_int pos = *(m_int *)MEM(SZ_INT * 2);
334 4 const M_Object obj = *(M_Object *)MEM(SZ_INT);
335
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
4 if (sz && (size_t)pos < sz) {
336 2 const m_str arg = STRING(obj);
337 2 m_str tmp = base + pos, str = NULL;
338
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 while ((tmp = strstr(tmp, arg))) str = tmp++;
339
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 *(m_uint *)RETURN = str ? str - pos - base : -1;
340 } else
341 2 *(m_uint *)RETURN = -1;
342 4 }
343
344 1 static MFUN(string_erase) {
345 1 const m_str str = STRING(o);
346 1 const m_int _start = *(m_int *)MEM(SZ_INT);
347 1 const m_int rem = *(m_int *)MEM(SZ_INT * 2);
348 1 const m_int len = strlen(str);
349 1 const m_int size = len - rem + 1;
350
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 const m_int start = _start >= 0 ? _start : len - _start;
351
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (start >= len || size <= 0) {
352 1 xfun_handle(shred, "InvalidStringErase");
353 1 return;
354 }
355 char c[size];
356 c[size - 1] = '\0';
357 for (m_int i = 0; i < start; i++) c[i] = str[i];
358 for (m_int i = start + rem; i < len; i++) c[i - rem] = str[i];
359 STRING(o) = s_name(insert_symbol(shred->info->vm->gwion->st, c));
360 }
361
362 static MFUN(string_save) {
363 const m_str path = STRING(*(M_Object*)MEM(SZ_INT));
364 FILE *f = fopen(path, "w");
365 if(!f) {
366 xfun_handle(shred, "StringLoadException");
367 return;
368 }
369 const m_str str = STRING(o);
370 fprintf(f, "%s", str);
371 fclose(f);
372 }
373
374 static SFUN(string_load) {
375 const m_str path = STRING(*(M_Object*)MEM(0));
376 FILE *f = fopen(path, "r");
377 if(!f) {
378 xfun_handle(shred, "StringLoadException");
379 return;
380 }
381 fseek(f, 0, SEEK_END);
382 const size_t sz = ftell(f);
383 char c[sz + 1];
384 rewind(f);
385 (void)fread(c, 1, sz, f);
386 fclose(f);
387 *(M_Object*)RETURN = new_string(shred->info->vm->gwion, c);
388 }
389
390 static MFUN(string_atoi) {
391 const M_Object obj = *(M_Object*)MEM(0);
392 const m_str str = STRING(obj);
393 *(m_int*)RETURN = atoi(str);
394 }
395
396 static MFUN(string_atof) {
397 const M_Object obj = *(M_Object*)MEM(0);
398 const m_str str = STRING(obj);
399 *(m_float*)RETURN = (m_float)atof(str);
400 }
401 #include <errno.h>
402 static MFUN(string_atoi2) {
403 const M_Object obj = *(M_Object*)MEM(0);
404 const m_str str = STRING(obj);
405 char *endptr = NULL;
406 if(!(*(m_int*)RETURN = strtol(str, &endptr, 10))) {
407 if(errno == EINVAL) {
408 xfun_handle(shred, "ErrorInvalidValue");
409 return;
410 }
411 if(errno == ERANGE) {
412 xfun_handle(shred, "ValueOutOfRange");
413 return;
414 }
415 }
416 **(m_uint**)MEM(SZ_INT) = endptr - str;
417 }
418
419 ANN Type check_array_access(const Env env, const Array_Sub array);
420
421 2 static OP_CHECK(opck_string_access) {
422 2 const Array_Sub array = (Array_Sub)data;
423 2 const Exp exp = array->exp;
424
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(!exp->next)
425 2 return env->gwion->type[et_char];
426 struct Array_Sub_ next = { exp->next, env->gwion->type[et_char], array->depth - 1 };
427 return check_array_access(env, &next);
428 }
429
430 1 static INSTR(string_at) {
431 1 POP_REG(shred, SZ_INT);
432 1 const m_str str = STRING(*(M_Object*)REG(-SZ_INT));
433 1 const m_int i = *(m_int *)REG(0);
434 1 const m_uint len = strlen(str);
435
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (i < 0 || (m_uint)i >= len) {
436 handle(shred, "invalid string access");
437 return;
438 } else
439 1 *(m_int *)REG(-SZ_INT) = str[i];
440 }
441
442 1 static INSTR(string_at_set) {
443 1 POP_REG(shred, SZ_INT);
444 1 const m_str str = STRING((*(M_Object*)REG(-SZ_INT)));
445 1 const m_int i = *(m_int *)REG(0);
446 1 const m_uint len = strlen(str);
447
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (i < 0 || (m_uint)i >= len) {
448 handle(shred, "StringAccessException");
449 return;
450 }
451 1 const m_int c = *(m_int*)REG(-SZ_INT*2);
452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(c == '\0') {
453 handle(shred, "StringAccessException");
454 return;
455 }
456 1 *(char**)REG(-SZ_INT) = str + i;
457 1 memcpy(REG(-SZ_INT*2 + 1), str + i + 1, SZ_INT - 1);
458 }
459
460
461 2 static OP_EMIT(opem_string_access) {
462 2 struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)data;
463 2 const Exp exp = info->array.exp;
464 2 const Exp next = exp->next;
465
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(emit_exp(emit, exp));
466 2 exp->next = next;
467
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 emit_add_instr(emit, !info->is_var ? string_at : string_at_set);
468 2 return GW_OK;
469 }
470
471 638 GWION_IMPORT(string) {
472 638 const Type t_string = gwi_class_ini(gwi, "string", NULL);
473 638 gwi->gwion->type[et_string] = t_string; // use func
474 638 gwi_class_xtor(gwi, string_ctor, string_dtor);
475 638 GWI_BB(gwi_gack(gwi, t_string, gack_string))
476 638 t_string->nspc->offset += SZ_INT;
477
478 638 gwi_func_ini(gwi, "int", "size");
479 638 GWI_BB(gwi_func_end(gwi, string_len, ae_flag_none))
480
481 638 gwi_func_ini(gwi, "string", "upper");
482 638 GWI_BB(gwi_func_end(gwi, string_upper, ae_flag_none))
483
484 638 gwi_func_ini(gwi, "string", "lower");
485 638 GWI_BB(gwi_func_end(gwi, string_lower, ae_flag_none))
486
487 638 gwi_func_ini(gwi, "string", "ltrim");
488 638 GWI_BB(gwi_func_end(gwi, string_ltrim, ae_flag_none))
489
490 638 gwi_func_ini(gwi, "string", "rtrim");
491 638 GWI_BB(gwi_func_end(gwi, string_rtrim, ae_flag_none))
492
493 638 gwi_func_ini(gwi, "string", "trim");
494 638 GWI_BB(gwi_func_end(gwi, string_trim, ae_flag_none))
495
496 638 gwi_func_ini(gwi, "string", "insert");
497 638 gwi_func_arg(gwi, "int", "pos");
498 638 gwi_func_arg(gwi, "string", "str");
499 638 GWI_BB(gwi_func_end(gwi, string_insert, ae_flag_none))
500
501 638 gwi_func_ini(gwi, "string", "replace");
502 638 gwi_func_arg(gwi, "int", "pos");
503 638 gwi_func_arg(gwi, "string", "str");
504 638 GWI_BB(gwi_func_end(gwi, string_replace, ae_flag_none))
505
506 638 gwi_func_ini(gwi, "string", "replace");
507 638 gwi_func_arg(gwi, "int", "pos");
508 638 gwi_func_arg(gwi, "int", "n");
509 638 gwi_func_arg(gwi, "string", "str");
510 638 GWI_BB(gwi_func_end(gwi, string_replaceN, ae_flag_none))
511
512 638 gwi_func_ini(gwi, "int", "find");
513 638 gwi_func_arg(gwi, "char", "c");
514 638 GWI_BB(gwi_func_end(gwi, string_find, ae_flag_none))
515
516 638 gwi_func_ini(gwi, "int", "find");
517 638 gwi_func_arg(gwi, "char", "c");
518 638 gwi_func_arg(gwi, "int", "pos");
519 638 GWI_BB(gwi_func_end(gwi, string_findStart, ae_flag_none))
520
521 638 gwi_func_ini(gwi, "int", "find");
522 638 gwi_func_arg(gwi, "string", "str");
523 638 GWI_BB(gwi_func_end(gwi, string_findStr, ae_flag_none))
524
525 638 gwi_func_ini(gwi, "int", "find");
526 638 gwi_func_arg(gwi, "string", "str");
527 638 gwi_func_arg(gwi, "int", "pos");
528 638 GWI_BB(gwi_func_end(gwi, string_findStrStart, ae_flag_none))
529
530 638 gwi_func_ini(gwi, "int", "rfind");
531 638 gwi_func_arg(gwi, "char", "c");
532 638 GWI_BB(gwi_func_end(gwi, string_rfind, ae_flag_none))
533
534 638 gwi_func_ini(gwi, "int", "rfind");
535 638 gwi_func_arg(gwi, "char", "c");
536 638 gwi_func_arg(gwi, "int", "pos");
537 638 GWI_BB(gwi_func_end(gwi, string_rfindStart, ae_flag_none))
538
539 638 gwi_func_ini(gwi, "int", "rfind");
540 638 gwi_func_arg(gwi, "string", "str");
541 638 GWI_BB(gwi_func_end(gwi, string_rfindStr, ae_flag_none))
542
543 638 gwi_func_ini(gwi, "int", "rfind");
544 638 gwi_func_arg(gwi, "string", "str");
545 638 gwi_func_arg(gwi, "int", "pos");
546 638 GWI_BB(gwi_func_end(gwi, string_rfindStrStart, ae_flag_none))
547
548 638 gwi_func_ini(gwi, "void", "erase");
549 638 gwi_func_arg(gwi, "int", "start");
550 638 gwi_func_arg(gwi, "int", "length");
551 638 GWI_BB(gwi_func_end(gwi, string_erase, ae_flag_none))
552
553 638 gwi_func_ini(gwi, "void", "save");
554 638 gwi_func_arg(gwi, "string", "path");
555 638 GWI_BB(gwi_func_end(gwi, string_save, ae_flag_none))
556
557 638 gwi_func_ini(gwi, "string", "load");
558 638 gwi_func_arg(gwi, "string", "path");
559 638 GWI_BB(gwi_func_end(gwi, string_load, ae_flag_static))
560
561 638 gwi_func_ini(gwi, "int", "atoi");
562 638 GWI_BB(gwi_func_end(gwi, string_atoi, ae_flag_none))
563
564 638 gwi_func_ini(gwi, "int", "atoi2");
565 638 gwi_func_arg(gwi, "&int", "offset");
566 638 GWI_BB(gwi_func_end(gwi, string_atoi2, ae_flag_none))
567
568 638 gwi_func_ini(gwi, "float", "atof");
569 638 GWI_BB(gwi_func_end(gwi, string_atof, ae_flag_none))
570
571 638 GWI_BB(gwi_class_end(gwi))
572
573 638 GWI_BB(gwi_oper_ini(gwi, "int", "string", NULL))
574 638 GWI_BB(gwi_oper_add(gwi, opck_string_access))
575 638 GWI_BB(gwi_oper_emi(gwi, opem_string_access))
576 638 GWI_BB(gwi_oper_end(gwi, "[]", NULL))
577
578 638 GWI_BB(gwi_oper_ini(gwi, "string", "string", "bool"))
579 638 GWI_BB(gwi_oper_add(gwi, opck_string_eq))
580 638 GWI_BB(gwi_oper_end(gwi, "==", String_eq))
581 638 GWI_BB(gwi_oper_add(gwi, opck_string_neq))
582 638 GWI_BB(gwi_oper_end(gwi, "!=", String_neq))
583
584 638 GWI_BB(gwi_oper_ini(gwi, "int", "string", "string"))
585 638 GWI_BB(gwi_oper_end(gwi, "[:]", StringSlice))
586
587 638 struct SpecialId_ file_spid = {
588 .ck = check_filepp, .is_const = 1};
589 638 gwi_specialid(gwi, "__file__", &file_spid);
590 638 struct SpecialId_ func_spid = {
591 .ck = check_funcpp, .is_const = 1};
592 638 gwi_specialid(gwi, "__func__", &func_spid);
593 638 struct SpecialId_ line_spid = {
594 .ck = check_linepp, .is_const = 1};
595 638 gwi_specialid(gwi, "__line__", &line_spid);
596 638 return GW_OK;
597 }
598