asar coverage - build #262


src/asar/
File: src/asar/libstr.cpp
Date: 2025-02-27 19:01:43
Lines:
213/268
79.5%
Functions:
15/18
83.3%
Branches:
162/254
63.8%

Line Branch Exec Source
1 #include "asar.h"
2 #include "virtualfile.h"
3 #include "unicode.h"
4
5 #include "platform/file-helpers.h"
6
7 #define typed_malloc(type, count) (type*)malloc(sizeof(type)*(count))
8 #define typed_realloc(type, ptr, count) (type*)realloc(ptr, sizeof(type)*(count))
9
10
11 // This function is intentionally left out of the header file so that it is not visible to the
12 // compiler and less likely to be inlined into resize(). This in turn reduces the size of resize()
13 // so that it is then inlined in more places.
14 23794 void string::reallocate_capacity(unsigned int new_length)
15 {
16 // Allocate 1 extra byte for NUL terminator
17
2/2
✓ Branch 0 taken 11531 times.
✓ Branch 1 taken 397 times.
23794 int new_alloc_capacity = bitround(new_length + 1);
18
19
2/2
✓ Branch 0 taken 22910 times.
✓ Branch 1 taken 884 times.
23794 if (is_inlined()) {
20 22910 data_ptr = copy(data_ptr, min(len, new_length), (char*)malloc(new_alloc_capacity));
21 }
22 else {
23 884 data_ptr = (char*)realloc(data_ptr, new_alloc_capacity);
24 }
25 23794 allocated.capacity = new_alloc_capacity - 1; // capacity field doesn't count NUL terminator
26 23794 }
27
28
29 // Detects if str starts with a UTF-8 byte order mark.
30 // If so, throws a warning, then returns the number of bytes we should skip ahead in the string.
31 1926 static size_t check_bom(const char* str)
32 {
33 // RPG Hacker: We could also check for BoMs of incompatible encodings here (like UTF-16)
34 // and throw errors, but not sure if that's worth adding. Asar never supported any wide
35 // encodings to begin with, so it's unreasonable to assume that any UTF-16 patches currently
36 // exist for it. As for future patches, those should be caught by the "must be UTF-8" checks
37 // I have already implemented further below.
38 // I think UTF-8 + BoM is the only case that could lead to confusion if we didn't handle it,
39 // so that's why I have added this.
40
4/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1920 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
1926 if (str[0u] == '\xEF' && str[1u] == '\xBB' && str[2u] == '\xBF')
41 {
42 6 asar_throw_warning(0, warning_id_byte_order_mark_utf8);
43 6 return 3u;
44 }
45
46 982 return 0u;
47 }
48
49
50 928 char * readfile(const char * fname, const char * basepath)
51 {
52 928 virtual_file_handle myfile = filesystem->open_file(fname, basepath);
53
2/2
✓ Branch 0 taken 445 times.
✓ Branch 1 taken 483 times.
928 if (myfile == INVALID_VIRTUAL_FILE_HANDLE) return nullptr;
54 910 size_t datalen = filesystem->get_file_size(myfile);
55 910 char * data= typed_malloc(char, datalen+1);
56 910 data[filesystem->read_file(myfile, data, 0u, datalen)] = 0;
57 910 filesystem->close_file(myfile);
58
59
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 904 times.
910 if (!is_valid_utf8(data))
60 {
61 6 free(data);
62 6 asar_throw_error(0, error_type_block, error_id_invalid_utf8);
63 }
64
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 898 times.
904 if(check_bom(data)){
65 6 data[0] = ' ';
66 6 data[1] = ' ';
67 6 data[2] = ' ';
68 }
69 471 return data;
70 }
71
72 // RPG Hacker: like readfile(), but doesn't use virtual file system
73 // and instead read our file directly.
74 1022 char * readfilenative(const char * fname)
75 {
76 1022 FileHandleType myfile = open_file(fname, FileOpenMode_Read);
77
2/2
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 514 times.
1022 if (myfile == InvalidFileHandle) return nullptr;
78 1022 size_t datalen = (size_t)get_file_size(myfile);
79 1022 char * data = typed_malloc(char, datalen + 1);
80 1022 data[read_file(myfile, data, datalen)] = 0;
81 1022 close_file(myfile);
82
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1022 times.
1022 if (!is_valid_utf8(data)) asar_throw_error(0, error_type_block, error_id_invalid_utf8);
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1022 times.
1022 if(check_bom(data)){
85 data[0] = ' ';
86 data[1] = ' ';
87 data[2] = ' ';
88 }
89 514 return data;
90 }
91
92 759 bool readfile(const char * fname, const char * basepath, char ** data, int * len)
93 {
94 759 virtual_file_handle myfile = filesystem->open_file(fname, basepath);
95
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 390 times.
759 if (!myfile) return false;
96 723 size_t datalen = filesystem->get_file_size(myfile);
97 723 *data= typed_malloc(char, datalen);
98 723 *len = (int)filesystem->read_file(myfile, *data, 0, datalen);
99 723 filesystem->close_file(myfile);
100 723 return true;
101 }
102
103 #define isq(n) (((0x2227 ^ (0x0101 * (n))) - 0x0101UL) & ~(0x2227 ^ (0x0101 * (n))) & 0x8080UL)
104 #define isqp(n) (((0x22272829 ^ (0x01010101 * (n))) - 0x01010101UL) & ~(0x22272829 ^ (0x01010101 * (n))) & 0x80808080UL)
105
106 // RPG Hacker: Only index this with ASCII characters.
107 // Anything else doesn't make sense, anyways.
108 const bool qparlut[128] = {
109 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117 };
118
119 //this will leave the last char found as the one pointed at
120 305065 inline bool skip_quote(char *&str)
121 {
122
123
2/2
✓ Branch 0 taken 32338 times.
✓ Branch 1 taken 272727 times.
305065 if(*str == '"') str = strchr(str + 1, '"');
124
2/2
✓ Branch 0 taken 2520 times.
✓ Branch 1 taken 270207 times.
272727 else if(*str == '\'')
125 {
126 int codepoint;
127
1/2
✓ Branch 0 taken 1260 times.
✗ Branch 1 not taken.
2520 str += utf8_val(&codepoint, str + 1) + 1;
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2520 times.
2520 if(*str != '\'') return false;
129 }
130 305065 return str;
131 }
132
133 //eat 1 char or quote/par
134 37838 inline bool skip_par(char *&str)
135 {
136 18926 int par = 0;
137
7/8
✓ Branch 0 taken 18780 times.
✓ Branch 1 taken 19058 times.
✓ Branch 2 taken 15677 times.
✓ Branch 3 taken 22011 times.
✓ Branch 4 taken 18774 times.
✓ Branch 5 taken 15552 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15552 times.
37838 if(*str != '\'' && *str != '"' && *str != '(' && *str != ')')
138 {
139 31095 str++;
140 31095 return true;
141 }
142 while(true)
143 {
144 41091 char *t = str;
145
2/2
✓ Branch 0 taken 842 times.
✓ Branch 1 taken 40249 times.
41091 if(*str == '"') t = strchr(t + 1, '"');
146
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 40231 times.
40249 else if(*str == '\'')
147 {
148 int codepoint;
149
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
18 t += utf8_val(&codepoint, t + 1) + 1;
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if(*t != '\'') return false;
151 }
152
2/2
✓ Branch 0 taken 6507 times.
✓ Branch 1 taken 33724 times.
40231 else if(*t == '(')
153 {
154 6507 par++;
155 }
156
2/2
✓ Branch 0 taken 6507 times.
✓ Branch 1 taken 27217 times.
33724 else if(*t == ')')
157 {
158 6507 par--;
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6507 times.
6507 if(par < 0) return false;
160 }
161
162 41091 str = t + 1;
163
4/4
✓ Branch 0 taken 36271 times.
✓ Branch 1 taken 4820 times.
✓ Branch 2 taken 18129 times.
✓ Branch 3 taken 18142 times.
41091 if(!*str || !par) return par == 0 ? true : false;
164 17182 }
165 }
166
167 //instr should not be duplicate chars. Instr should also not be 1 char
168 string& string::qreplace(const char * instr, const char * outstr)
169 {
170 string& thisstring =*this;
171 if (!strstr(thisstring, instr)) return thisstring;
172 int inlen = strlen(instr);
173 string out;
174 for (int i=0;thisstring[i];)
175 {
176 if (!strncmp((const char*)thisstring +i, instr, inlen))
177 {
178 out+=outstr;
179 i+=inlen;
180 }
181 // randomdude999: prevent appending the null terminator to the output
182 else if(!isq(thisstring[i])) out+= thisstring[i++];
183 else
184 {
185 char *start = raw() + i;
186 char *end = start;
187 if(!skip_quote(end)) return thisstring;
188 out.append(raw(), i, end - start + i + 1);
189 i += end - start + 1;
190
191 }
192 }
193 thisstring =out;
194 return thisstring;
195 }
196
197 163313 string& string::qnormalize()
198 {
199 79232 string& thisstring =*this;
200 79232 string out;
201 79232 char *startstr = thisstring.raw();
202 79232 char *str = startstr;
203
2/2
✓ Branch 0 taken 200817 times.
✓ Branch 1 taken 163223 times.
364040 while((str = strpbrk(str, "'\" \t,\r")))
204 {
205
2/2
✓ Branch 0 taken 147246 times.
✓ Branch 1 taken 53571 times.
200817 if(is_space(*str))
206 {
207
6/6
✓ Branch 0 taken 147210 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 147066 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 71157 times.
✓ Branch 5 taken 90 times.
147246 if(str[0] == ' ' && !is_space(str[1]))
208 {
209 147066 str++;
210 147066 continue;
211 }
212
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
180 out.append(startstr, 0, str - startstr);
213
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
180 out += ' ';
214
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 180 times.
756 while(is_space(*str)) str++;
215 90 startstr = str;
216
2/2
✓ Branch 0 taken 18678 times.
✓ Branch 1 taken 34893 times.
53571 }else if(*str == ',')
217 {
218 18678 str++;
219
2/2
✓ Branch 0 taken 5472 times.
✓ Branch 1 taken 13206 times.
18678 if(is_space(*str))
220 {
221
1/2
✓ Branch 0 taken 2739 times.
✗ Branch 1 not taken.
5472 out.append(startstr, 0, str - startstr);
222
2/2
✓ Branch 0 taken 5598 times.
✓ Branch 1 taken 5472 times.
11070 while(is_space(*str)) str++;
223 2739 startstr = str;
224 }
225 }
226 else
227 {
228 34893 str = strchr(str + 1, *str); //confirm quotes has already been run, so this should be okay
229
2/2
✓ Branch 0 taken 20013 times.
✓ Branch 1 taken 14880 times.
34893 if(!str) return thisstring;
230 34803 str++;
231 }
232 }
233
2/2
✓ Branch 0 taken 4476 times.
✓ Branch 1 taken 158747 times.
163223 if(startstr != thisstring.raw())
234 {
235
1/2
✓ Branch 0 taken 2241 times.
✗ Branch 1 not taken.
4476 out.append(startstr, 0, strlen(startstr)); //the remaining
236
237
1/2
✓ Branch 0 taken 2241 times.
✗ Branch 1 not taken.
2241 thisstring = out;
238 }
239 79187 return thisstring;
240 163313 }
241
242 227747 bool confirmquotes(const char * str)
243 {
244
2/2
✓ Branch 0 taken 162673 times.
✓ Branch 1 taken 101224 times.
263897 while(*str)
245 {
246 162673 char *dquote = strchr((char *)str, '"');
247 162673 char *squote = strchr((char *)str, '\'');
248
4/4
✓ Branch 0 taken 85439 times.
✓ Branch 1 taken 77234 times.
✓ Branch 2 taken 1392 times.
✓ Branch 3 taken 63403 times.
162673 if(dquote || squote)
249 {
250
6/6
✓ Branch 0 taken 33396 times.
✓ Branch 1 taken 2784 times.
✓ Branch 2 taken 33237 times.
✓ Branch 3 taken 159 times.
✓ Branch 4 taken 13985 times.
✓ Branch 5 taken 12 times.
36180 if(dquote && (dquote < squote || !squote))
251 {
252 33372 dquote = strchr(dquote+1, '"');
253
2/2
✓ Branch 0 taken 33348 times.
✓ Branch 1 taken 24 times.
33372 if(dquote) str = dquote+1;
254 12 else return false;
255 }
256 else
257 {
258 int codepoint;
259
1/2
✓ Branch 0 taken 1404 times.
✗ Branch 1 not taken.
2808 squote += utf8_val(&codepoint, squote + 1) + 1;
260
2/2
✓ Branch 0 taken 2802 times.
✓ Branch 1 taken 6 times.
2808 if(*squote == '\'') str = squote+1;
261 6 else return false;
262 }
263 15521 }
264 else
265 {
266 63403 return true;
267 }
268 }
269 48095 return true;
270 }
271
272 2108 bool confirmqpar(const char * str)
273 {
274 //todo fully optimize
275 1061 int par = 0;
276
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28726 times.
✓ Branch 2 taken 26618 times.
✓ Branch 3 taken 2108 times.
28726 while((unsigned char)*str >= 128 || !qparlut[(unsigned char)*str]) str++;
277
2/2
✓ Branch 0 taken 5386 times.
✓ Branch 1 taken 2108 times.
7494 while(*str)
278 {
279
2/2
✓ Branch 0 taken 1098 times.
✓ Branch 1 taken 4288 times.
5386 if(*str == '"')
280 {
281 1098 str = strchr(str + 1, '"');
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1098 times.
1098 if(!str++) return false;
283 }
284
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 4216 times.
4288 else if(*str == '\'')
285 {
286 int codepoint;
287
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 str += utf8_val(&codepoint, str + 1) + 1;
288
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if(*str == '\'') str++;
289 else return false;
290 }
291 else
292 {
293 4216 par += 1 - ((*str++ - '(') << 1);
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4216 times.
4216 if(par < 0) return false;
295 }
296
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 13416 times.
✓ Branch 2 taken 8030 times.
✓ Branch 3 taken 5386 times.
13416 while((unsigned char)*str >= 128 || !qparlut[(unsigned char)*str]) str++;
297 }
298 2108 return !par;
299 }
300
301 167319 char ** split(char * str, char key, int * len)
302 {
303 167319 char *thisentry=strchr(str, key);
304
2/2
✓ Branch 0 taken 95229 times.
✓ Branch 1 taken 72090 times.
167319 if (!thisentry)
305 {
306 95229 char ** out= typed_malloc(char*, 2);
307 95229 out[0]=str;
308 95229 out[1]=nullptr;
309
2/2
✓ Branch 0 taken 81359 times.
✓ Branch 1 taken 13870 times.
95229 if (len) *len=1;
310 95229 return out;
311 }
312 36163 int count=15; //makes the default alloc 8 elements, sounds fair.
313 72090 char ** outdata= typed_malloc(char*, (size_t)count+1);
314
315 36163 int newcount=0;
316 72090 outdata[newcount++]=str;
317 do{
318 128808 *thisentry = 0;
319 128808 thisentry++;
320 128808 outdata[newcount++]=thisentry;
321
2/2
✓ Branch 0 taken 931 times.
✓ Branch 1 taken 127877 times.
128808 if(newcount >= count)
322 {
323 931 count *= 2;
324 931 outdata = typed_realloc(char *, outdata, count);
325 }
326
2/2
✓ Branch 0 taken 56718 times.
✓ Branch 1 taken 72090 times.
128808 }while((thisentry = strchr(thisentry, key)));
327
328 72090 outdata[newcount]= nullptr;
329
2/2
✓ Branch 0 taken 69840 times.
✓ Branch 1 taken 2250 times.
72090 if (len) *len=newcount;
330 36163 return outdata;
331 }
332
333 194293 char ** qsplit(char * str, char key, int * len)
334 {
335
5/6
✓ Branch 0 taken 163701 times.
✓ Branch 1 taken 30592 times.
✓ Branch 2 taken 161829 times.
✓ Branch 3 taken 1872 times.
✓ Branch 4 taken 54135 times.
✗ Branch 5 not taken.
194293 if (!strchr(str, '"') && !strchr(str, '\'')) return split(str, key, len);
336
337 13666 int count=15;
338 32464 char ** outdata= typed_malloc(char*, (size_t)count+1);
339 13666 int newcount=0;
340 32464 char * thisentry=str;
341 32464 outdata[newcount++]=thisentry;
342
2/2
✓ Branch 0 taken 278065 times.
✓ Branch 1 taken 32464 times.
310529 while (*thisentry) /*todo fix*/
343 {
344
2/2
✓ Branch 0 taken 33753 times.
✓ Branch 1 taken 244312 times.
278065 if (*thisentry == key)
345 {
346 33753 *thisentry=0;
347 33753 thisentry++;
348 33753 outdata[newcount++]=thisentry;
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33753 times.
33753 if(newcount >= count)
350 {
351 count *= 2;
352 outdata = typed_realloc(char *, outdata, count);
353 }
354 }
355
2/4
✓ Branch 0 taken 244312 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104200 times.
✗ Branch 3 not taken.
244312 else if(skip_quote(thisentry)) thisentry++;
356 else return nullptr;
357 }
358 32464 outdata[newcount]= nullptr;
359
2/2
✓ Branch 0 taken 31383 times.
✓ Branch 1 taken 1081 times.
32464 if (len) *len=newcount;
360 13666 return outdata;
361 }
362
363 160785 char ** qsplitstr(char * str, const char * key, int * len)
364 {
365 //check if the str is found first
366
2/2
✓ Branch 0 taken 159411 times.
✓ Branch 1 taken 1374 times.
160785 if (!strstr(str, key))
367 {
368 159411 char ** out= typed_malloc(char*, 2);
369 159411 out[0]=str;
370 159411 out[1]=nullptr;
371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 159411 times.
159411 if (len) *len=1;
372 159411 return out;
373 }
374
375 1374 int keylen=(int)strlen(key);
376 717 int count=15;
377 1374 char ** outdata= typed_malloc(char*, (size_t)count+1);
378 717 int newcount=0;
379 1374 char * thisentry=str;
380 1374 outdata[newcount++]=thisentry;
381
2/2
✓ Branch 0 taken 66222 times.
✓ Branch 1 taken 1374 times.
67596 while (*thisentry) /*todo fix*/
382 {
383
2/2
✓ Branch 0 taken 5469 times.
✓ Branch 1 taken 60753 times.
66222 if (!strncmp(thisentry, key, (size_t)keylen))
384 {
385 5469 *thisentry=0;
386 5469 thisentry+=keylen;
387 5469 outdata[newcount++]=thisentry;
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5469 times.
5469 if(newcount >= count)
389 {
390 count *= 2;
391 outdata = typed_realloc(char *, outdata, count);
392 }
393 }
394
2/4
✓ Branch 0 taken 60753 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30927 times.
✗ Branch 3 not taken.
60753 else if(skip_quote(thisentry)) thisentry++;
395 else return nullptr;
396 }
397 1374 outdata[newcount]= nullptr;
398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1374 times.
1374 if (len) *len=newcount;
399 717 return outdata;
400 }
401
402 //this function is most commonly called in cases where additional chars are very likely
403 34227 char ** qpsplit(char * str, char key, int * len)
404 {
405
4/6
✓ Branch 0 taken 28039 times.
✓ Branch 1 taken 6188 times.
✓ Branch 2 taken 28039 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14071 times.
✗ Branch 5 not taken.
34227 if (!strchr(str, '(') && !strchr(str, ')')) return qsplit(str, key, len);
406 3095 int count=7;
407 6188 char ** outdata= typed_malloc(char*, (size_t)count+1);
408
409 3095 int newcount=0;
410 6188 char * thisentry=str;
411 6188 outdata[newcount++]=thisentry;
412
2/2
✓ Branch 0 taken 38729 times.
✓ Branch 1 taken 6188 times.
44917 while (*thisentry)
413 {
414 //skippar(*thisentry, thisentry++, return nullptr;)
415
2/2
✓ Branch 0 taken 2331 times.
✓ Branch 1 taken 36398 times.
38729 if (*thisentry == key)
416 {
417 2331 *thisentry=0;
418 2331 thisentry++;
419 2331 outdata[newcount++]=thisentry;
420
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2307 times.
2331 if(newcount >= count)
421 {
422 24 count *= 2;
423 24 outdata = typed_realloc(char *, outdata, count);
424 }
425 }
426
2/4
✓ Branch 0 taken 36398 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18206 times.
36398 else if(!skip_par(thisentry)) return nullptr;
427 }
428 6188 outdata[newcount]= nullptr;
429
2/2
✓ Branch 0 taken 2730 times.
✓ Branch 1 taken 3458 times.
6188 if (len) *len=newcount;
430 3095 return outdata;
431 }
432
433 string &itrim(string &input, const char * left, const char * right)
434 {
435 bool nukeright=true;
436 int totallen=input.length();
437 int rightlen=(int)strlen(right);
438 if (rightlen && rightlen<=totallen)
439 {
440 const char * rightend=right+rightlen;
441 const char * strend=input.data()+totallen;
442 while (right!=rightend)
443 {
444 rightend--;
445 strend--;
446 if (to_lower(*strend)!=to_lower(*rightend)) nukeright=false;
447 }
448 if (nukeright)
449 {
450 totallen-=rightlen;
451 input.truncate(totallen);
452 }
453 }
454 bool nukeleft=true;
455 int leftlen = strlen(left);
456 if(leftlen == 1 && input.data()[0] == left[0])
457 {
458 return input = string(input.data()+1, (input.length()-1));
459 }
460 else
461 {
462 for (int i = 0; i < leftlen; i++)
463 {
464 if (to_lower(input.data()[i])!=to_lower(left[i])) nukeleft=false;
465 }
466 if (nukeleft) input = string(input.data()+leftlen, (input.length()-leftlen));
467 }
468 return input;
469 }
470
471 char* strqpchr(char* str, char key)
472 {
473 while (*str)
474 {
475 if (*str == key) return str;
476 else if(!skip_par(str)) return nullptr;
477 }
478 return nullptr;
479 }
480
481 378 char* strqpstr(char* str, const char* key)
482 {
483 378 size_t keylen = strlen(key);
484
2/2
✓ Branch 0 taken 1800 times.
✓ Branch 1 taken 18 times.
1818 while (*str)
485 {
486
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 1440 times.
1800 if (!strncmp(str, key, keylen)) return str;
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1440 times.
1440 else if(!skip_par(str)) return nullptr;
488 }
489 9 return nullptr;
490 }
491
492 extern const uint8_t char_props[256] = {
493 //x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
494 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00, // 0x
495 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1x
496 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2x !"#$%&'()*+,-./
497 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00, // 3x 0123456789:;<=>?
498 0x00,0x23,0x23,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, // 4x @ABCDEFGHIJKLMNO
499 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x08, // 5x PQRSTUVWXYZ[\]^_
500 0x00,0x25,0x25,0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, // 6x `abcdefghijklmno
501 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00, // 7x pqrstuvwxyz{|}~
502 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8x
503 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9x
504 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Ax
505 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Bx
506 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Cx
507 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Dx
508 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Ex
509 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Fx
510 };
511