asar coverage - build #268


src/asar/
File: src/asar/libstr.h
Date: 2025-03-01 20:34:29
Lines:
200/215
93.0%
Functions:
54/57
94.7%
Branches:
154/215
71.6%

Line Branch Exec Source
1 #pragma once
2
3 #include "std-includes.h"
4 #include <cstdint>
5 #include <cstring>
6 #include <utility>
7 #include <string_view>
8
9 //ty alcaro
10 extern const unsigned char char_props[256];
11 1467140 static inline int to_lower(unsigned char c) { return c|(char_props[c]&0x20); }
12 static inline int to_upper(unsigned char c) { return c&~(char_props[c]&0x20); }
13
14 237705 inline bool is_space(unsigned char c) { return char_props[c] & 0x80; } // C standard says \f \v are space, but this one disagrees
15 // TODO is this opaque table lookup really faster than c >= '0' && c <= '9'?
16 49313 inline bool is_digit(unsigned char c) { return char_props[c] & 0x40; }
17 inline bool is_alpha(unsigned char c) { return char_props[c] & 0x20; }
18 inline bool is_lower(unsigned char c) { return char_props[c] & 0x04; }
19 106 inline bool is_upper(unsigned char c) { return char_props[c] & 0x02; }
20 inline bool is_alnum(unsigned char c) { return char_props[c] & 0x60; }
21 14306 inline bool is_ualpha(unsigned char c) { return char_props[c] & 0x28; }
22 120117 inline bool is_ualnum(unsigned char c) { return char_props[c] & 0x68; }
23 7316 inline bool is_xdigit(unsigned char c) { return char_props[c] & 0x01; }
24
25 1222175 inline char *copy(const char *source, int copy_length, char *dest)
26 {
27
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 578780 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 578780 times.
1222175 memcpy(dest, source, copy_length*sizeof(char));
28 1222175 return dest;
29 }
30
31 class string {
32 public:
33 2672403 const char *data() const
34 {
35 2672403 return data_ptr;
36 }
37
38 116008 char *temp_raw() const //things to cleanup and take a look at
39 {
40 116008 return data_ptr;
41 }
42
43 380356 char *raw() const
44 {
45 380356 return data_ptr;
46 }
47
48 2860836 int length() const
49 {
50 2860836 return len;
51 }
52
53 1739880 void resize(unsigned int new_length)
54 {
55
3/3
✓ Branch 0 taken 2115 times.
✓ Branch 1 taken 928309 times.
✓ Branch 2 taken 809456 times.
1739880 if (new_length > capacity()) {
56 4569 reallocate_capacity(new_length);
57 }
58
59 1739880 len = new_length;
60 1739880 data_ptr[new_length] = 0; //always ensure null terminator
61 1739880 }
62
63 792 void truncate(int newlen)
64 {
65 792 resize(newlen);
66 792 }
67
68 627446 void assign(const char * newstr)
69 {
70
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 627443 times.
627446 if (!newstr) newstr = "";
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303449 times.
627446 assign(newstr, strlen(newstr));
72 627446 }
73
74 334290 void assign(const string &newstr)
75 {
76 334290 assign(newstr.data(), newstr.length());
77 334290 }
78
79 1037217 void assign(const char * newstr, int end)
80 {
81 1037217 resize(end);
82 1037217 copy(newstr, end, data_ptr);
83 1037217 }
84
85
86 227735 string& operator=(const char * newstr)
87 {
88 227735 assign(newstr);
89 227735 return *this;
90 }
91
92 334290 string& operator=(const string &newstr)
93 {
94 334290 assign(newstr);
95 334290 return *this;
96 }
97
98 string& append(const string& other, int start, int end)
99 {
100 int current_end = length();
101 resize(length() + end - start);
102 copy(other.data() + start, end - start, data_ptr + current_end);
103 return *this;
104 }
105
106 3384 string& append(const char *other, int start, int end)
107 {
108 3384 int current_end = length();
109 3384 resize(length() + end - start);
110 3384 copy(other + start, end - start, data_ptr + current_end);
111 3384 return *this;
112 }
113
114 49971 string& operator+=(const string& other)
115 {
116 49971 int current_end = length();
117 49971 resize(length() + other.length());
118 49971 copy(other.data(), other.length(), data_ptr + current_end);
119 49971 return *this;
120 }
121
122 127212 string& operator+=(const char *other)
123 {
124 127212 int current_end = length();
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60417 times.
127212 int otherlen=(int)strlen(other);
126 127212 resize(length() + otherlen);
127 127212 copy(other, otherlen, data_ptr + current_end);
128 127212 return *this;
129 }
130
131 521300 string& operator+=(char c)
132 {
133 521300 resize(length() + 1);
134 521300 data_ptr[length() - 1] = c;
135 521300 return *this;
136 }
137
138 string operator+(char right) const
139 {
140 string ret=*this;
141 ret+=right;
142 return ret;
143 }
144
145 19553 string operator+(const char * right) const
146 {
147 19553 string ret=*this;
148
1/2
✓ Branch 0 taken 19553 times.
✗ Branch 1 not taken.
19553 ret+=right;
149 19553 return ret;
150 }
151
152 1849315 operator const char*() const
153 {
154 1849315 return data();
155 }
156
157 10318 explicit operator bool() const
158 {
159 10318 return length();
160 }
161
162 1321615 string()
163 1321615 {
164 1321615 data_ptr = inlined.data;
165 1321615 len = 0;
166 1321615 inlined.data[0] = '\0';
167 1321615 }
168 311553 string(const char * newstr) : string()
169 {
170
2/3
✓ Branch 0 taken 160998 times.
✓ Branch 1 taken 150555 times.
✗ Branch 2 not taken.
311553 assign(newstr);
171 311553 }
172 63273 string(const char * newstr, int newlen) : string()
173 {
174
2/3
✓ Branch 0 taken 33056 times.
✓ Branch 1 taken 30217 times.
✗ Branch 2 not taken.
63273 assign(newstr, newlen);
175 63273 }
176 88158 string(const string& old) : string()
177 {
178
2/4
✓ Branch 0 taken 45732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42426 times.
✗ Branch 3 not taken.
88158 assign(old.data());
179 88158 }
180
181 12586 string(string &&move) noexcept : string()
182 {
183 12586 *this = move;
184 12586 }
185
186 66330 string& operator=(string&& other) noexcept
187 {
188
3/3
✓ Branch 0 taken 42256 times.
✓ Branch 1 taken 24054 times.
✓ Branch 2 taken 20 times.
66330 if (other.is_inlined()) {
189 // No resources to steal so just do a normal assignment
190 66292 *this = other;
191 } else {
192
2/3
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
38 if (is_inlined()) {
193 38 data_ptr = other.data_ptr;
194 38 other.data_ptr = 0;
195 } else {
196 // Give our old allocation back so other can free it for us
197 std::swap(data_ptr, other.data_ptr);
198 }
199 38 len = other.len;
200 38 allocated = other.allocated;
201 }
202 66330 return *this;
203 }
204
205 1278518 ~string()
206 {
207
3/3
✓ Branch 0 taken 2062 times.
✓ Branch 1 taken 658814 times.
✓ Branch 2 taken 617642 times.
1278518 if(!is_inlined()){
208 4429 free(data_ptr);
209 }
210 1278518 }
211
212 //maybe these should return refs to chain. but also good not to encourage chaining
213 11 void strip_prefix(char c)
214 {
215
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 7 times.
11 if(data()[0] == c){
216
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 std::memmove(data_ptr, data_ptr + 1, length() - 1);
217 4 resize(length() - 1);
218 }
219 11 }
220
221 void strip_suffix(char c)
222 {
223 if (data()[length() - 1] == c) {
224 truncate(length() - 1);
225 }
226 }
227
228 string& qreplace(const char * instr, const char * outstr);
229 string& qnormalize();
230
231 // RPG Hacker: My hack shmeck to get around no longer supporting text mode.
232 // Symbol files are currently the only thing that use text mode, anyways, and I don't even know
233 // if the emulators that read them care about line endings.
234 string& convert_line_endings_to_native()
235 {
236 #if defined(windows)
237 // RPG Hacker: This is quite stinky, but doing the replacement directly will lead to a dead-lock.
238 // \x08 = backspace should never appear inside a string, so I'm abusing it here.
239 return qreplace("\n", "\x08").qreplace("\x08", "\r\n");
240 #else
241 return *this;
242 #endif
243 }
244
245 private:
246 static const int scale_factor = 4; //scale sso
247 static const int inline_capacity = ((sizeof(char *) + sizeof(int) * 2) * scale_factor) - 2;
248
249 // Points to a malloc'd data block or to inlined.data
250 char *data_ptr;
251 unsigned int len;
252 union {
253 struct {
254 // Actual allocated capacity is +1 this value, to cover for the terminating NUL
255 unsigned int capacity;
256 } allocated;
257 struct {
258 char data[inline_capacity + 1];
259 } inlined;
260 };
261
262 void reallocate_capacity(unsigned int new_length);
263
264 1739880 unsigned capacity() const
265 {
266
3/3
✓ Branch 0 taken 927283 times.
✓ Branch 1 taken 811694 times.
✓ Branch 2 taken 903 times.
1739880 return is_inlined() ? inline_capacity : allocated.capacity;
267 }
268
269 3089335 bool is_inlined() const
270 {
271 3089335 return data_ptr == inlined.data;
272 }
273 };
274 #define STR (string)
275
276 #define ASAR_STRCMP_OPERATORS(op) \
277 inline bool operator op(const string& left, const string& right) { \
278 return strcmp(left, right) op 0; \
279 } \
280 inline bool operator op(const string& left, const char* right) { \
281 return strcmp(left, right) op 0; \
282 } \
283 inline bool operator op(const char* left, const string& right) { \
284 return strcmp(left, right) op 0; \
285 }
286
287
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3550 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23412 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 19862 times.
55097 ASAR_STRCMP_OPERATORS(==)
288
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1677 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1677 times.
4395 ASAR_STRCMP_OPERATORS(!=)
289 ASAR_STRCMP_OPERATORS(<)
290 ASAR_STRCMP_OPERATORS(<=)
291 ASAR_STRCMP_OPERATORS(>)
292 ASAR_STRCMP_OPERATORS(>=)
293 #undef ASAR_STRCMP_OPERATORS
294
295 template<>
296 struct std::hash<string> {
297 67322 size_t operator()(const ::string& s) const {
298 67322 return std::hash<std::string_view>()(std::string_view(s.data(), s.length()));
299 }
300 };
301
302 char * readfile(const char * fname, const char * basepath);
303 char * readfilenative(const char * fname);
304 bool readfile(const char * fname, const char * basepath, char ** data, int * len);//if you want an uchar*, cast it
305 char ** split(char * str, char key, int * len= nullptr);
306 char ** qsplit(char * str, char key, int * len= nullptr);
307 char ** qpsplit(char * str, char key, int * len= nullptr);
308 char ** qsplitstr(char * str, const char * key, int * len= nullptr);
309 bool confirmquotes(const char * str);
310 bool confirmqpar(const char * str);
311 char* strqpchr(char* str, char key);
312 char* strqpstr(char* str, const char* key);
313
314 inline string hex(unsigned int value)
315 {
316 char buffer[64];
317 if(0);
318 else if (value<=0x000000FF) snprintf(buffer, sizeof(buffer), "%.2X", value);
319 else if (value<=0x0000FFFF) snprintf(buffer, sizeof(buffer), "%.4X", value);
320 else if (value<=0x00FFFFFF) snprintf(buffer, sizeof(buffer), "%.6X", value);
321 else snprintf(buffer, sizeof(buffer), "%.8X", value);
322 return buffer;
323 }
324
325 2 inline string hex(unsigned int value, int width)
326 {
327 1 char buffer[64];
328
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 snprintf(buffer, sizeof(buffer), "%.*X", width, value);
329
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 return buffer;
330 }
331
332 1380 inline string dec(int value)
333 {
334 745 char buffer[64];
335
2/2
✓ Branch 0 taken 635 times.
✓ Branch 1 taken 745 times.
1380 snprintf(buffer, sizeof(buffer), "%i", value);
336
1/2
✓ Branch 0 taken 1380 times.
✗ Branch 1 not taken.
2760 return buffer;
337 }
338
339 2166 inline string ftostr(double value)
340 {
341 // randomdude999: With 100 digits of precision, the buffer needs to be approx. 311+100,
342 // but let's be safe here https://stackoverflow.com/questions/7235456
343 1083 char rval[512];
344 // RPG Hacker: Ridiculously high precision, I know, but we're working with doubles
345 // here and can afford it, so no need to waste any precision
346
1/2
✓ Branch 0 taken 1083 times.
✗ Branch 1 not taken.
2166 snprintf(rval, sizeof(rval), "%.100f", value);
347
1/2
✓ Branch 0 taken 2166 times.
✗ Branch 1 not taken.
2166 if (strchr(rval, '.'))//nuke useless zeroes
348 {
349 2166 char * end=strrchr(rval, '\0')-1;
350
3/3
✓ Branch 0 taken 108126 times.
✓ Branch 1 taken 109209 times.
✓ Branch 2 taken 1083 times.
218418 while (*end=='0')
351 {
352 216252 *end='\0';
353 216252 end--;
354 }
355
3/3
✓ Branch 0 taken 1080 times.
✓ Branch 1 taken 1083 times.
✓ Branch 2 taken 3 times.
2166 if (*end=='.') *end='\0';
356 }
357
1/2
✓ Branch 0 taken 2166 times.
✗ Branch 1 not taken.
4332 return rval;
358 }
359
360 // Same as above, but with variable precision
361 24 inline string ftostrvar(double value, int precision)
362 {
363 24 int clampedprecision = precision;
364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (clampedprecision < 0) clampedprecision = 0;
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (clampedprecision > 100) clampedprecision = 100;
366
367 // see above
368 12 char rval[512];
369
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
24 snprintf(rval, sizeof(rval), "%.*f", clampedprecision, (double)value);
370
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
24 if (strchr(rval, '.'))//nuke useless zeroes
371 {
372 22 char * end = strrchr(rval, '\0') - 1;
373
3/3
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 11 times.
68 while (*end == '0')
374 {
375 46 *end = '\0';
376 46 end--;
377 }
378
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 8 times.
22 if (*end == '.') *end = '\0';
379 }
380
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 return rval;
381 }
382
383 80925 inline bool stribegin(const char * str, const char * key)
384 {
385
4/4
✓ Branch 0 taken 115506 times.
✓ Branch 1 taken 4169 times.
✓ Branch 2 taken 78127 times.
✓ Branch 3 taken 1901 times.
199703 for (int i=0;key[i];i++)
386 {
387
4/4
✓ Branch 0 taken 37179 times.
✓ Branch 1 taken 78327 times.
✓ Branch 2 taken 37676 times.
✓ Branch 3 taken 40451 times.
193633 if (to_lower(str[i])!=to_lower(key[i])) return false;
388 }
389 6070 return true;
390 }
391
392 inline bool striend(const char * str, const char * key)
393 {
394 const char * keyend=strrchr(key, '\0');
395 const char * strend=strrchr(str, '\0');
396 if(keyend-key > strend-str) return false;
397
398 while (key!=keyend)
399 {
400 keyend--;
401 strend--;
402 if (to_lower(*strend)!=to_lower(*keyend)) return false;
403 }
404 return true;
405 }
406
407 inline bool stricmpwithupper(const char *word1, const char *word2)
408 {
409 while(*word2)
410 {
411 if(to_upper(*word1++) != *word2++) return true;
412 }
413 return *word1;
414 }
415
416 572040 inline bool stricmpwithlower(const char *word1, const char *word2)
417 {
418
3/3
✓ Branch 0 taken 412446 times.
✓ Branch 1 taken 383146 times.
✓ Branch 2 taken 16889 times.
812481 while(*word2)
419 {
420
4/4
✓ Branch 0 taken 286884 times.
✓ Branch 1 taken 125562 times.
✓ Branch 2 taken 250551 times.
✓ Branch 3 taken 114879 times.
777876 if(to_lower(*word1++) != *word2++) return true;
421 }
422 34605 return *word1;
423 }
424
425 //function: return the string without quotes around it, if any exists
426 //if they don't exist, return it unaltered
427 //it is not guaranteed to return str
428 //it is not guaranteed to not edit str
429 //the input must be freed even though it's garbage, the output must not
430 5214 inline const char * dequote(char * str)
431 {
432
3/3
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 3158 times.
✓ Branch 2 taken 1684 times.
5214 if (*str!='"') return str;
433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1684 times.
4434 char *end = strrchr(str, '"');
434
1/2
✓ Branch 0 taken 4434 times.
✗ Branch 1 not taken.
4434 if (end)
435 {
436 4434 *end = 0;
437 4434 char *quote = str+1;
438
7/10
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 2822 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 72 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1756 times.
✓ Branch 8 taken 72 times.
✓ Branch 9 taken 1684 times.
4578 while((quote = strstr(quote, "\"\""))) memmove(quote, quote+1, strlen(quote));
439 4434 return str + 1;
440 }
441 return nullptr;
442 }
443
444 15657 inline char * strqchr(const char * str, char key)
445 {
446
3/3
✓ Branch 0 taken 68653 times.
✓ Branch 1 taken 75957 times.
✓ Branch 2 taken 5961 times.
150571 while (*str != '\0')
447 {
448
3/3
✓ Branch 0 taken 1914 times.
✓ Branch 1 taken 68659 times.
✓ Branch 2 taken 68177 times.
138750 if (*str == key) { return const_cast<char*>(str); }
449
6/6
✓ Branch 0 taken 66418 times.
✓ Branch 1 taken 68168 times.
✓ Branch 2 taken 422 times.
✓ Branch 3 taken 66326 times.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 67755 times.
134916 else if (*str == '"' || *str == '\'')
450 {
451 // Special case hack for ''', which is currently our official way of handling the ' character.
452 // Even though it really stinks.
453
8/9
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 413 times.
✓ Branch 2 taken 336 times.
✓ Branch 3 taken 86 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
835 if (str[0] == '\'' && str[1] == '\'' && str[2] == '\'') { str += 2; }
454 else
455 {
456 823 char delimiter = *str;
457
458 do
459 {
460 8947 str++;
461
462 // If we want to support backslash escapes, we'll have to add that right here.
463
6/6
✓ Branch 0 taken 4025 times.
✓ Branch 1 taken 4507 times.
✓ Branch 2 taken 4439 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4100 times.
✓ Branch 5 taken 1 times.
8947 } while (*str != delimiter && *str != '\0');
464
465 // This feels like a superfluous check, but I can't really find a clean way to avoid it.
466
3/3
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 407 times.
✓ Branch 2 taken 415 times.
823 if (*str == '\0') { return nullptr; }
467 }
468 }
469
470 134914 str++;
471 }
472
473 11821 return nullptr;
474 }
475
476 2580 inline string substr(const char * str, int len)
477 {
478 2580 return string(str, len);
479 }
480
481
482 63825 inline char *strip_whitespace(char *str)
483 {
484
4/4
✓ Branch 0 taken 1530 times.
✓ Branch 1 taken 32202 times.
✓ Branch 2 taken 1969 times.
✓ Branch 3 taken 31623 times.
67324 while(is_space(*str)) str++;
485
4/4
✓ Branch 0 taken 29267 times.
✓ Branch 1 taken 42126 times.
✓ Branch 2 taken 28612 times.
✓ Branch 3 taken 10587 times.
78969 for(int i = strlen(str) - 1; i >= 0; i--)
486 {
487
4/4
✓ Branch 0 taken 21699 times.
✓ Branch 1 taken 7568 times.
✓ Branch 2 taken 21036 times.
✓ Branch 3 taken 7576 times.
57879 if(!is_space(str[i]))
488 {
489 42735 str[i + 1] = 0;
490 42735 return str;
491 }
492 }
493 21090 return str;
494 }
495 267 inline void strip_whitespace(string &str)
496 {
497
2/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
✗ Branch 3 not taken.
267 str = string(strip_whitespace(str.temp_raw()));
498 267 }
499
500 string &itrim(string &str, const char * left, const char * right);
501
502 5851 inline string &lower(string &old)
503 {
504 5851 int length = old.length();
505
4/4
✓ Branch 0 taken 173769 times.
✓ Branch 1 taken 5849 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
179626 for (int i=0;i<length;i++) old.raw()[i]=(char)to_lower(old.data()[i]);
506 5851 return old;
507 }
508
509
510 // Returns number of connected lines - 1
511 template<typename stringarraytype>
512 45272 inline int getconnectedlines(stringarraytype& lines, int startline, string& out)
513 {
514 45272 int count = 0;
515
516
2/4
✓ Branch 0 taken 23031 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22259 times.
✗ Branch 3 not taken.
45290 for (int i = startline; lines[i]; i++)
517 {
518 // The line should already be stripped of any comments at this point
519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22259 times.
45290 int linestartpos = (int)strlen(lines[i]);
520
521
6/6
✓ Branch 0 taken 31794 times.
✓ Branch 1 taken 13496 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 16298 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 15478 times.
45290 if(linestartpos && lines[i][linestartpos - 1] == '\\')
522 {
523 18 count++;
524
4/7
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
18 out += string(lines[i], linestartpos - 1);
525 18 continue;
526 }
527 else
528 {
529
4/7
✓ Branch 0 taken 23022 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23022 times.
✓ Branch 3 taken 22250 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 22250 times.
✗ Branch 6 not taken.
45272 out += string(lines[i], linestartpos);
530 45272 return count;
531 }
532 }
533
534 return count;
535 }
536