tests/test_string.cpp

changeset 653
e081643aae2a
parent 645
ec50abb285ad
child 671
d7a67375a7ac
equal deleted inserted replaced
652:bf817b825ed2 653:e081643aae2a
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "cx/string.h"
30 #include "util_allocator.h"
31
32 #include <gtest/gtest.h>
33
34 #define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0')
35
36 TEST(String, construct) {
37 cxstring s1 = cx_str("1234");
38 cxstring s2 = cx_strn("abcd", 2);
39 cxmutstr s3 = cx_mutstr((char *) "1234");
40 cxmutstr s4 = cx_mutstrn((char *) "abcd", 2);
41
42 EXPECT_EQ(s1.length, 4);
43 EXPECT_EQ(s2.length, 2);
44 EXPECT_EQ(s3.length, 4);
45 EXPECT_EQ(s4.length, 2);
46 }
47
48 TEST(String, strfree) {
49 CxTestingAllocator alloc;
50 auto test = (char *) cxMalloc(&alloc, 16);
51 cxmutstr str = cx_mutstrn(test, 16);
52 ASSERT_EQ(str.ptr, test);
53 EXPECT_EQ(str.length, 16);
54 cx_strfree_a(&alloc, &str);
55 EXPECT_EQ(str.ptr, nullptr);
56 EXPECT_EQ(str.length, 0);
57 EXPECT_TRUE(alloc.verify());
58 }
59
60 TEST(String, strdup) {
61 cxstring str = CX_STR("test");
62 cxmutstr dup = cx_strdup(str);
63 ASSERT_EQ(dup.length, str.length);
64 EXPECT_STREQ(dup.ptr, str.ptr);
65 EXPECT_ZERO_TERMINATED(dup);
66 cx_strfree(&dup);
67
68 str.length = 2;
69 dup = cx_strdup(str);
70 ASSERT_EQ(dup.length, str.length);
71 EXPECT_STREQ(dup.ptr, "te");
72 EXPECT_ZERO_TERMINATED(dup);
73 cx_strfree(&dup);
74 }
75
76 TEST(String, strlen) {
77 cxstring s1 = CX_STR("1234");
78 cxstring s2 = CX_STR(".:.:.");
79 cxstring s3 = CX_STR("X");
80
81 size_t len0 = cx_strlen(0);
82 size_t len1 = cx_strlen(1, s1);
83 size_t len2 = cx_strlen(2, s1, s2);
84 size_t len3 = cx_strlen(3, s1, s2, s3);
85
86 EXPECT_EQ(len0, 0);
87 EXPECT_EQ(len1, 4);
88 EXPECT_EQ(len2, 9);
89 EXPECT_EQ(len3, 10);
90 }
91
92 TEST(String, strsubs) {
93 cxstring str = CX_STR("A test string");
94
95 cxstring sub = cx_strsubs(str, 0);
96 EXPECT_EQ(cx_strcmp(sub, str), 0);
97
98 sub = cx_strsubs(str, 2);
99 EXPECT_EQ(cx_strcmp(sub, cx_str("test string")), 0);
100
101 sub = cx_strsubs(str, 7);
102 EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0);
103
104 sub = cx_strsubs(str, 15);
105 EXPECT_EQ(cx_strcmp(sub, cx_str("")), 0);
106
107 sub = cx_strsubsl(str, 2, 4);
108 EXPECT_EQ(cx_strcmp(sub, cx_str("test")), 0);
109
110 sub = cx_strsubsl(str, 7, 3);
111 EXPECT_EQ(cx_strcmp(sub, cx_str("str")), 0);
112
113 sub = cx_strsubsl(str, 7, 20);
114 EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0);
115
116 // just for coverage, call the _m variant
117 auto m = cx_strsubs_m(cx_mutstrn(nullptr, 0), 0);
118 EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
119 }
120
121 TEST(String, strchr) {
122 cxstring str = CX_STR("I will find you - and I will kill you");
123
124 cxstring notfound = cx_strchr(str, 'x');
125 EXPECT_EQ(notfound.length, 0);
126
127 cxstring result = cx_strchr(str, 'w');
128 EXPECT_EQ(result.length, 35);
129 EXPECT_STREQ(result.ptr, "will find you - and I will kill you");
130
131 // just for coverage, call the _m variant
132 auto m = cx_strchr_m(cx_mutstrn(nullptr, 0), 'a');
133 EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
134 }
135
136 TEST(String, strrchr) {
137 cxstring str = CX_STR("I will find you - and I will kill you");
138
139 cxstring notfound = cx_strrchr(str, 'x');
140 EXPECT_EQ(notfound.length, 0);
141
142 cxstring result = cx_strrchr(str, 'w');
143 EXPECT_EQ(result.length, 13);
144 EXPECT_STREQ(result.ptr, "will kill you");
145
146 // just for coverage, call the _m variant
147 auto m = cx_strrchr_m(cx_mutstrn(nullptr, 0), 'a');
148 EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
149 }
150
151 TEST(String, strstr) {
152 cxstring str = CX_STR("find the match in this string");
153 cxstring longstr = CX_STR(
154 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl"
155 "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx"
156 "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij"
157 "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv"
158 "abababababababababababababababababababababababababababababababab"
159 "abababababababababababababababababababababababababababababababab"
160 "abababababababababababababababababababababababababababababababab"
161 "abababababababababababababababababababababababababababababababab"
162 "abababababababababababababababababababababababababababababababab"
163 "abababababababababababababababababababababababababababababababab"
164 "wxyz1234567890");
165 cxstring longstrpattern = CX_STR(
166 "abababababababababababababababababababababababababababababababab"
167 "abababababababababababababababababababababababababababababababab"
168 "abababababababababababababababababababababababababababababababab"
169 "abababababababababababababababababababababababababababababababab"
170 "abababababababababababababababababababababababababababababababab"
171 );
172 cxstring longstrresult = CX_STR(
173 "abababababababababababababababababababababababababababababababab"
174 "abababababababababababababababababababababababababababababababab"
175 "abababababababababababababababababababababababababababababababab"
176 "abababababababababababababababababababababababababababababababab"
177 "abababababababababababababababababababababababababababababababab"
178 "abababababababababababababababababababababababababababababababab"
179 "wxyz1234567890"
180 );
181
182 cxstring notfound = cx_strstr(str, cx_str("no match"));
183 EXPECT_EQ(notfound.length, 0);
184
185 cxstring result = cx_strstr(str, cx_str("match"));
186 EXPECT_EQ(result.length, 20);
187 EXPECT_STREQ(result.ptr, "match in this string");
188
189 result = cx_strstr(str, cx_str(""));
190 EXPECT_EQ(result.length, str.length);
191 EXPECT_STREQ(result.ptr, str.ptr);
192
193 result = cx_strstr(longstr, longstrpattern);
194 EXPECT_EQ(result.length, longstrresult.length);
195 EXPECT_STREQ(result.ptr, longstrresult.ptr);
196
197 // just for coverage, call the _m variant
198 auto mstr = cx_strdup(longstr);
199 auto m = cx_strstr_m(mstr, longstrpattern);
200 EXPECT_EQ(m.length, longstrresult.length);
201 EXPECT_STREQ(m.ptr, longstrresult.ptr);
202 cx_strfree(&mstr);
203 }
204
205 TEST(String, strcmp) {
206 cxstring str = CX_STR("compare this");
207
208 EXPECT_EQ(cx_strcmp(cx_str(""), cx_str("")), 0);
209 EXPECT_GT(cx_strcmp(str, cx_str("")), 0);
210 EXPECT_EQ(cx_strcmp(str, cx_str("compare this")), 0);
211 EXPECT_NE(cx_strcmp(str, cx_str("Compare This")), 0);
212 EXPECT_LT(cx_strcmp(str, cx_str("compare tool")), 0);
213 EXPECT_GT(cx_strcmp(str, cx_str("compare shit")), 0);
214 EXPECT_LT(cx_strcmp(str, cx_str("compare this not")), 0);
215 EXPECT_GT(cx_strcmp(str, cx_str("compare")), 0);
216 }
217
218 TEST(String, strcasecmp) {
219 cxstring str = CX_STR("compare this");
220
221 EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0);
222 EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0);
223 EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0);
224 EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0);
225 EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0);
226 EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0);
227 EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0);
228 EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0);
229 }
230
231 TEST(String, strcat) {
232 cxstring s1 = CX_STR("12");
233 cxstring s2 = CX_STR("34");
234 cxstring s3 = CX_STR("56");
235 cxstring sn = {nullptr, 0};
236
237 CxTestingAllocator alloc;
238
239 cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2);
240 EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0);
241 EXPECT_ZERO_TERMINATED(t1);
242 cx_strfree_a(&alloc, &t1);
243
244 cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3);
245 EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0);
246 EXPECT_ZERO_TERMINATED(t2);
247 cx_strfree_a(&alloc, &t2);
248
249 cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn);
250 EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0);
251 EXPECT_ZERO_TERMINATED(t3);
252 cx_strfree_a(&alloc, &t3);
253
254 cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn);
255 EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0);
256 EXPECT_ZERO_TERMINATED(t4);
257 cx_strfree_a(&alloc, &t4);
258
259 EXPECT_TRUE(alloc.verify());
260
261 // use the macro
262 cxmutstr t5 = cx_strcat(3, s3, s1, s2);
263 EXPECT_EQ(cx_strcmp(cx_strcast(t5), cx_str("561234")), 0);
264 EXPECT_ZERO_TERMINATED(t5);
265 cx_strfree(&t5);
266 }
267
268 TEST(String, strsplit) {
269
270 cxstring test = cx_str("this,is,a,csv,string");
271 size_t capa = 8;
272 cxstring list[8];
273 size_t n;
274
275 // special case: empty string
276 n = cx_strsplit(test, cx_str(""), capa, list);
277 ASSERT_EQ(n, 1);
278 EXPECT_EQ(cx_strcmp(list[0], test), 0);
279
280 // no delimiter occurrence
281 n = cx_strsplit(test, cx_str("z"), capa, list);
282 ASSERT_EQ(n, 1);
283 EXPECT_EQ(cx_strcmp(list[0], test), 0);
284
285 // partially matching delimiter
286 n = cx_strsplit(test, cx_str("is,not"), capa, list);
287 ASSERT_EQ(n, 1);
288 EXPECT_EQ(cx_strcmp(list[0], test), 0);
289
290 // matching single-char delimiter
291 n = cx_strsplit(test, cx_str(","), capa, list);
292 ASSERT_EQ(n, 5);
293 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
294 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
295 EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
296 EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
297 EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
298
299 // matching multi-char delimiter
300 n = cx_strsplit(test, cx_str("is"), capa, list);
301 ASSERT_EQ(n, 3);
302 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
303 EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
304 EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
305
306 // bounded list using single-char delimiter
307 n = cx_strsplit(test, cx_str(","), 3, list);
308 ASSERT_EQ(n, 3);
309 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
310 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
311 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
312
313 // bounded list using multi-char delimiter
314 n = cx_strsplit(test, cx_str("is"), 2, list);
315 ASSERT_EQ(n, 2);
316 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
317 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
318
319 // start with delimiter
320 n = cx_strsplit(test, cx_str("this"), capa, list);
321 ASSERT_EQ(n, 2);
322 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
323 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
324
325 // end with delimiter
326 n = cx_strsplit(test, cx_str("string"), capa, list);
327 ASSERT_EQ(n, 2);
328 EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
329 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
330
331
332 // end with delimiter exceed bound
333 n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list);
334 ASSERT_EQ(n, 3);
335 EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
336 EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
337 EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
338
339 // exact match
340 n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list);
341 ASSERT_EQ(n, 2);
342 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
343 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
344
345 // string to be split is only substring
346 n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list);
347 ASSERT_EQ(n, 1);
348 EXPECT_EQ(cx_strcmp(list[0], test), 0);
349
350 // subsequent encounter of delimiter (the string between is empty)
351 n = cx_strsplit(test, cx_str("is,"), capa, list);
352 ASSERT_EQ(n, 3);
353 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
354 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
355 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
356
357 // call the _m variant just for coverage
358 auto mtest = cx_strdup(test);
359 cxmutstr mlist[4];
360 n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist);
361 ASSERT_EQ(n, 3);
362 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
363 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
364 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
365 cx_strfree(&mtest);
366 }
367
368 TEST(String, strsplit_a) {
369 CxTestingAllocator alloc;
370
371 cxstring test = cx_str("this,is,a,csv,string");
372 size_t capa = 8;
373 cxstring *list;
374 size_t n;
375
376 // special case: empty string
377 n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list);
378 ASSERT_EQ(n, 1);
379 EXPECT_EQ(cx_strcmp(list[0], test), 0);
380 cxFree(&alloc, list);
381
382 // no delimiter occurrence
383 n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list);
384 ASSERT_EQ(n, 1);
385 EXPECT_EQ(cx_strcmp(list[0], test), 0);
386 cxFree(&alloc, list);
387
388 // partially matching delimiter
389 n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list);
390 ASSERT_EQ(n, 1);
391 EXPECT_EQ(cx_strcmp(list[0], test), 0);
392 cxFree(&alloc, list);
393
394 // matching single-char delimiter
395 n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list);
396 ASSERT_EQ(n, 5);
397 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
398 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
399 EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
400 EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
401 EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
402 cxFree(&alloc, list);
403
404 // matching multi-char delimiter
405 n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list);
406 ASSERT_EQ(n, 3);
407 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
408 EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
409 EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
410 cxFree(&alloc, list);
411
412 // bounded list using single-char delimiter
413 n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list);
414 ASSERT_EQ(n, 3);
415 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
416 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
417 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
418 cxFree(&alloc, list);
419
420 // bounded list using multi-char delimiter
421 n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list);
422 ASSERT_EQ(n, 2);
423 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
424 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
425 cxFree(&alloc, list);
426
427 // start with delimiter
428 n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list);
429 ASSERT_EQ(n, 2);
430 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
431 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
432 cxFree(&alloc, list);
433
434 // end with delimiter
435 n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list);
436 ASSERT_EQ(n, 2);
437 EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
438 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
439 cxFree(&alloc, list);
440
441 // end with delimiter exceed bound
442 n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list);
443 ASSERT_EQ(n, 3);
444 EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
445 EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
446 EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
447 cxFree(&alloc, list);
448
449 // exact match
450 n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list);
451 ASSERT_EQ(n, 2);
452 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
453 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
454 cxFree(&alloc, list);
455
456 // string to be split is only substring
457 n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list);
458 ASSERT_EQ(n, 1);
459 EXPECT_EQ(cx_strcmp(list[0], test), 0);
460 cxFree(&alloc, list);
461
462 // subsequent encounter of delimiter (the string between is empty)
463 n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list);
464 ASSERT_EQ(n, 3);
465 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
466 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
467 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
468 cxFree(&alloc, list);
469
470 // call the _m variant just for coverage
471 auto mtest = cx_strdup(test);
472 cxmutstr *mlist;
473 n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist);
474 ASSERT_EQ(n, 3);
475 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
476 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
477 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
478 cxFree(&alloc, mlist);
479 cx_strfree(&mtest);
480
481 EXPECT_TRUE(alloc.verify());
482 }
483
484 TEST(String, strtrim) {
485 cxstring t1 = cx_strtrim(cx_str(" ein test \t "));
486 cxstring t2 = cx_strtrim(cx_str("abc"));
487 cxstring t3 = cx_strtrim(cx_str(" 123"));
488 cxstring t4 = cx_strtrim(cx_str("xyz "));
489 cxstring t5 = cx_strtrim(cx_str(" "));
490 cxstring empty = cx_strtrim(cx_str(""));
491
492 EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0);
493 EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0);
494 EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0);
495 EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0);
496 EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0);
497 EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0);
498
499 // call the _m variant just for coverage
500 cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) " ein test \t "));
501 EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0);
502 }
503
504 TEST(String, strprefix) {
505 cxstring str = CX_STR("test my prefix and my suffix");
506 cxstring empty = CX_STR("");
507 EXPECT_FALSE(cx_strprefix(empty, cx_str("pref")));
508 EXPECT_TRUE(cx_strprefix(str, empty));
509 EXPECT_TRUE(cx_strprefix(empty, empty));
510 EXPECT_TRUE(cx_strprefix(str, cx_str("test ")));
511 EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck ")));
512 }
513
514 TEST(String, strsuffix) {
515 cxstring str = CX_STR("test my prefix and my suffix");
516 cxstring empty = CX_STR("");
517 EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf")));
518 EXPECT_TRUE(cx_strsuffix(str, empty));
519 EXPECT_TRUE(cx_strsuffix(empty, empty));
520 EXPECT_TRUE(cx_strsuffix(str, cx_str("fix")));
521 EXPECT_FALSE(cx_strsuffix(str, cx_str("fox")));
522 }
523
524 TEST(String, strcaseprefix) {
525 cxstring str = CX_STR("test my prefix and my suffix");
526 cxstring empty = CX_STR("");
527 EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf")));
528 EXPECT_TRUE(cx_strcaseprefix(str, empty));
529 EXPECT_TRUE(cx_strcaseprefix(empty, empty));
530 EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST ")));
531 EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck ")));
532 }
533
534 TEST(String, strcasesuffix) {
535 cxstring str = CX_STR("test my prefix and my suffix");
536 cxstring empty = CX_STR("");
537 EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf")));
538 EXPECT_TRUE(cx_strcasesuffix(str, empty));
539 EXPECT_TRUE(cx_strcasesuffix(empty, empty));
540 EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX")));
541 EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox")));
542 }
543
544 TEST(String, strreplace) {
545 CxTestingAllocator alloc;
546 cxstring str = CX_STR("test ababab string aba");
547 cxstring longstr = CX_STR(
548 "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd");
549 cxstring notrail = CX_STR("test abab");
550 cxstring empty = CX_STR("");
551 cxstring astr = CX_STR("aaaaaaaaaa");
552 cxstring csstr = CX_STR("test AB ab TEST xyz");
553
554 cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger"));
555 auto expected = "test muchlongerab string aba";
556
557 cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2);
558 auto expectedn = "test ccab string aba";
559
560 cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z"));
561 auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd";
562
563 cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z"));
564 auto notrailexpect = "test zz";
565
566 cxmutstr repleq = cx_strreplace(str, str, cx_str("hello"));
567 auto eqexpect = "hello";
568
569 cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty
570 cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty);
571 auto emptyexpect2 = "test ab string aba";
572
573 cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST "));
574 auto preexpected = "TEST ababab string aba";
575
576 cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1);
577 auto an1expected = "xaaaaaaaaa";
578
579 cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4);
580 auto an4expected = "xxxxaaaaaa";
581
582 cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9);
583 auto an9expected = "xxxxxxxxxa";
584
585 cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10);
586 auto an10expected = "xxxxxxxxxx";
587
588 cxmutstr repl1_a = cx_strreplace_a(&alloc, csstr, cx_str("AB"), cx_str("*"));
589 auto expeced1_a = "test * ab TEST xyz";
590
591 cxmutstr repl2_a = cx_strreplace_a(&alloc, csstr, cx_str("test"), cx_str("TEST"));
592 auto expected2_a = "TEST AB ab TEST xyz";
593
594
595 EXPECT_NE(repl.ptr, str.ptr);
596 EXPECT_ZERO_TERMINATED(repl);
597 EXPECT_STREQ(repl.ptr, expected);
598 EXPECT_ZERO_TERMINATED(repln);
599 EXPECT_STREQ(repln.ptr, expectedn);
600 EXPECT_ZERO_TERMINATED(longrepl);
601 EXPECT_STREQ(longrepl.ptr, longexpect);
602 EXPECT_ZERO_TERMINATED(replnotrail);
603 EXPECT_STREQ(replnotrail.ptr, notrailexpect);
604 EXPECT_ZERO_TERMINATED(repleq);
605 EXPECT_STREQ(repleq.ptr, eqexpect);
606 EXPECT_ZERO_TERMINATED(replempty1);
607 EXPECT_STREQ(replempty1.ptr, "");
608 EXPECT_ZERO_TERMINATED(replempty2);
609 EXPECT_STREQ(replempty2.ptr, emptyexpect2);
610 EXPECT_ZERO_TERMINATED(replpre);
611 EXPECT_STREQ(replpre.ptr, preexpected);
612 EXPECT_ZERO_TERMINATED(replan1);
613 EXPECT_STREQ(replan1.ptr, an1expected);
614 EXPECT_ZERO_TERMINATED(replan4);
615 EXPECT_STREQ(replan4.ptr, an4expected);
616 EXPECT_ZERO_TERMINATED(replan9);
617 EXPECT_STREQ(replan9.ptr, an9expected);
618 EXPECT_ZERO_TERMINATED(replan10);
619 EXPECT_STREQ(replan10.ptr, an10expected);
620 EXPECT_ZERO_TERMINATED(repl1_a);
621 EXPECT_STREQ(repl1_a.ptr, expeced1_a);
622 EXPECT_ZERO_TERMINATED(repl2_a);
623 EXPECT_STREQ(repl2_a.ptr, expected2_a);
624
625 cx_strfree(&repl);
626 cx_strfree(&repln);
627 cx_strfree(&longrepl);
628 cx_strfree(&replnotrail);
629 cx_strfree(&repleq);
630 cx_strfree(&replempty1);
631 cx_strfree(&replempty2);
632 cx_strfree(&replpre);
633 cx_strfree(&replan1);
634 cx_strfree(&replan4);
635 cx_strfree(&replan9);
636 cx_strfree(&replan10);
637
638 cx_strfree_a(&alloc, &repl1_a);
639 cx_strfree_a(&alloc, &repl2_a);
640 EXPECT_TRUE(alloc.verify());
641 }
642
643 TEST(String, strupper) {
644 cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
645 cx_strupper(str);
646 EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T");
647 cx_strfree(&str);
648 }
649
650 TEST(String, strlower) {
651 cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
652 cx_strlower(str);
653 EXPECT_STREQ(str.ptr, "this 1s @ te$t");
654 cx_strfree(&str);
655 }
656
657 TEST(String, strtok) {
658 cxstring str = cx_str("a,comma,separated,string");
659 cxstring delim = cx_str(",");
660 CxStrtokCtx ctx = cx_strtok(str, delim, 3);
661 EXPECT_EQ(ctx.str.ptr, str.ptr);
662 EXPECT_EQ(ctx.str.length, str.length);
663 EXPECT_EQ(ctx.delim.ptr, delim.ptr);
664 EXPECT_EQ(ctx.delim.length, delim.length);
665 EXPECT_EQ(ctx.limit, 3);
666 EXPECT_EQ(ctx.found, 0);
667 EXPECT_EQ(ctx.pos, 0);
668 EXPECT_EQ(ctx.next_pos, 0);
669 EXPECT_EQ(ctx.delim_more, nullptr);
670 EXPECT_EQ(ctx.delim_more_count, 0);
671 }
672
673 TEST(String, strtok_m) {
674 cxmutstr str = cx_strdup(cx_str("a,comma,separated,string"));
675 cxstring delim = cx_str(",");
676 CxStrtokCtx ctx = cx_strtok_m(str, delim, 3);
677 EXPECT_EQ(ctx.str.ptr, str.ptr);
678 EXPECT_EQ(ctx.str.length, str.length);
679 EXPECT_EQ(ctx.delim.ptr, delim.ptr);
680 EXPECT_EQ(ctx.delim.length, delim.length);
681 EXPECT_EQ(ctx.limit, 3);
682 EXPECT_EQ(ctx.found, 0);
683 EXPECT_EQ(ctx.pos, 0);
684 EXPECT_EQ(ctx.next_pos, 0);
685 EXPECT_EQ(ctx.delim_more, nullptr);
686 EXPECT_EQ(ctx.delim_more_count, 0);
687 cx_strfree(&str);
688 }
689
690 TEST(String, strtok_delim) {
691 cxstring str = cx_str("an,arbitrarily|separated;string");
692 cxstring delim = cx_str(",");
693 cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")};
694 CxStrtokCtx ctx = cx_strtok(str, delim, 3);
695 cx_strtok_delim(&ctx, delim_more, 2);
696 EXPECT_EQ(ctx.str.ptr, str.ptr);
697 EXPECT_EQ(ctx.str.length, str.length);
698 EXPECT_EQ(ctx.delim.ptr, delim.ptr);
699 EXPECT_EQ(ctx.delim.length, delim.length);
700 EXPECT_EQ(ctx.limit, 3);
701 EXPECT_EQ(ctx.found, 0);
702 EXPECT_EQ(ctx.pos, 0);
703 EXPECT_EQ(ctx.next_pos, 0);
704 EXPECT_EQ(ctx.delim_more, delim_more);
705 EXPECT_EQ(ctx.delim_more_count, 2);
706 }
707
708 TEST(String, strtok_next_easy) {
709 cxstring str = cx_str("a,comma,separated,string");
710 cxstring delim = cx_str(",");
711 CxStrtokCtx ctx = cx_strtok(str, delim, 3);
712 bool ret;
713 cxstring tok;
714
715 ret = cx_strtok_next(&ctx, &tok);
716 ASSERT_TRUE(ret);
717 EXPECT_EQ(cx_strcmp(tok, cx_str("a")), 0);
718 EXPECT_EQ(ctx.pos, 0);
719 EXPECT_EQ(ctx.next_pos, 2);
720 EXPECT_EQ(ctx.delim_pos, 1);
721 EXPECT_EQ(ctx.found, 1);
722
723 ret = cx_strtok_next(&ctx, &tok);
724 ASSERT_TRUE(ret);
725 EXPECT_EQ(cx_strcmp(tok, cx_str("comma")), 0);
726 EXPECT_EQ(ctx.pos, 2);
727 EXPECT_EQ(ctx.next_pos, 8);
728 EXPECT_EQ(ctx.delim_pos, 7);
729 EXPECT_EQ(ctx.found, 2);
730
731 ret = cx_strtok_next(&ctx, &tok);
732 ASSERT_TRUE(ret);
733 EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0);
734 EXPECT_EQ(ctx.pos, 8);
735 EXPECT_EQ(ctx.next_pos, 18);
736 EXPECT_EQ(ctx.delim_pos, 17);
737 EXPECT_EQ(ctx.found, 3);
738
739 ret = cx_strtok_next(&ctx, &tok);
740 ASSERT_FALSE(ret);
741 EXPECT_EQ(ctx.pos, 8);
742 EXPECT_EQ(ctx.next_pos, 18);
743 EXPECT_EQ(ctx.delim_pos, 17);
744 EXPECT_EQ(ctx.found, 3);
745 }
746
747 TEST(String, strtok_next_unlimited) {
748 cxstring str = cx_str("some;-;otherwise;-;separated;-;string;-;");
749 cxstring delim = cx_str(";-;");
750 CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX);
751 bool ret;
752 cxstring tok;
753
754 ret = cx_strtok_next(&ctx, &tok);
755 ASSERT_TRUE(ret);
756 EXPECT_EQ(cx_strcmp(tok, cx_str("some")), 0);
757 EXPECT_EQ(ctx.pos, 0);
758 EXPECT_EQ(ctx.next_pos, 7);
759 EXPECT_EQ(ctx.delim_pos, 4);
760 EXPECT_EQ(ctx.found, 1);
761
762 ret = cx_strtok_next(&ctx, &tok);
763 ASSERT_TRUE(ret);
764 EXPECT_EQ(cx_strcmp(tok, cx_str("otherwise")), 0);
765 EXPECT_EQ(ctx.pos, 7);
766 EXPECT_EQ(ctx.next_pos, 19);
767 EXPECT_EQ(ctx.delim_pos, 16);
768 EXPECT_EQ(ctx.found, 2);
769
770 ret = cx_strtok_next(&ctx, &tok);
771 ASSERT_TRUE(ret);
772 EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0);
773 EXPECT_EQ(ctx.pos, 19);
774 EXPECT_EQ(ctx.next_pos, 31);
775 EXPECT_EQ(ctx.delim_pos, 28);
776 EXPECT_EQ(ctx.found, 3);
777
778 ret = cx_strtok_next(&ctx, &tok);
779 ASSERT_TRUE(ret);
780 EXPECT_EQ(cx_strcmp(tok, cx_str("string")), 0);
781 EXPECT_EQ(ctx.pos, 31);
782 EXPECT_EQ(ctx.next_pos, 40);
783 EXPECT_EQ(ctx.delim_pos, 37);
784 EXPECT_EQ(ctx.found, 4);
785
786 ret = cx_strtok_next(&ctx, &tok);
787 ASSERT_TRUE(ret);
788 EXPECT_EQ(cx_strcmp(tok, cx_str("")), 0);
789 EXPECT_EQ(ctx.pos, 40);
790 EXPECT_EQ(ctx.next_pos, 40);
791 EXPECT_EQ(ctx.delim_pos, 40);
792 EXPECT_EQ(ctx.found, 5);
793
794 ret = cx_strtok_next(&ctx, &tok);
795 ASSERT_FALSE(ret);
796 EXPECT_EQ(ctx.pos, 40);
797 EXPECT_EQ(ctx.delim_pos, 40);
798 EXPECT_EQ(ctx.found, 5);
799 }
800
801 TEST(String, strtok_next_advanced) {
802 cxmutstr str = cx_strdup(cx_str("an,arbitrarily;||separated;string"));
803 cxstring delim = cx_str(",");
804 cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")};
805 CxStrtokCtx ctx = cx_strtok_m(str, delim, 10);
806 cx_strtok_delim(&ctx, delim_more, 2);
807 bool ret;
808 cxmutstr tok;
809
810 ret = cx_strtok_next_m(&ctx, &tok);
811 ASSERT_TRUE(ret);
812 EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("an")), 0);
813 EXPECT_EQ(ctx.pos, 0);
814 EXPECT_EQ(ctx.next_pos, 3);
815 EXPECT_EQ(ctx.delim_pos, 2);
816 EXPECT_EQ(ctx.found, 1);
817 cx_strupper(tok);
818
819 ret = cx_strtok_next_m(&ctx, &tok);
820 ASSERT_TRUE(ret);
821 EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("arbitrarily")), 0);
822 EXPECT_EQ(ctx.pos, 3);
823 EXPECT_EQ(ctx.next_pos, 15);
824 EXPECT_EQ(ctx.delim_pos, 14);
825 EXPECT_EQ(ctx.found, 2);
826 cx_strupper(tok);
827
828 ret = cx_strtok_next_m(&ctx, &tok);
829 ASSERT_TRUE(ret);
830 EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("")), 0);
831 EXPECT_EQ(ctx.pos, 15);
832 EXPECT_EQ(ctx.next_pos, 17);
833 EXPECT_EQ(ctx.delim_pos, 15);
834 EXPECT_EQ(ctx.found, 3);
835 cx_strupper(tok);
836
837 ret = cx_strtok_next_m(&ctx, &tok);
838 ASSERT_TRUE(ret);
839 EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("separated")), 0);
840 EXPECT_EQ(ctx.pos, 17);
841 EXPECT_EQ(ctx.next_pos, 27);
842 EXPECT_EQ(ctx.delim_pos, 26);
843 EXPECT_EQ(ctx.found, 4);
844 cx_strupper(tok);
845
846 ret = cx_strtok_next_m(&ctx, &tok);
847 ASSERT_TRUE(ret);
848 EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("string")), 0);
849 EXPECT_EQ(ctx.pos, 27);
850 EXPECT_EQ(ctx.next_pos, 33);
851 EXPECT_EQ(ctx.delim_pos, 33);
852 EXPECT_EQ(ctx.found, 5);
853 cx_strupper(tok);
854
855 ret = cx_strtok_next_m(&ctx, &tok);
856 ASSERT_FALSE(ret);
857 EXPECT_EQ(ctx.pos, 27);
858 EXPECT_EQ(ctx.next_pos, 33);
859 EXPECT_EQ(ctx.delim_pos, 33);
860 EXPECT_EQ(ctx.found, 5);
861
862 EXPECT_EQ(cx_strcmp(cx_strcast(str), cx_str("AN,ARBITRARILY;||SEPARATED;STRING")), 0);
863
864 cx_strfree(&str);
865 }

mercurial