1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tests/test_string.c Thu Dec 28 20:37:53 2023 +0100 1.3 @@ -0,0 +1,986 @@ 1.4 +/* 1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 1.6 + * 1.7 + * Copyright 2023 Mike Becker, Olaf Wintermann All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * 1. Redistributions of source code must retain the above copyright 1.13 + * notice, this list of conditions and the following disclaimer. 1.14 + * 1.15 + * 2. Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in the 1.17 + * documentation and/or other materials provided with the distribution. 1.18 + * 1.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 1.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.29 + * POSSIBILITY OF SUCH DAMAGE. 1.30 + */ 1.31 + 1.32 +#include "cx/test.h" 1.33 +#include "util_allocator.h" 1.34 + 1.35 +#include "cx/string.h" 1.36 + 1.37 +#define ASSERT_ZERO_TERMINATED(str) CX_TEST_ASSERTM((str).ptr[(str).length] == '\0', \ 1.38 + #str " is not zero terminated") 1.39 + 1.40 +CX_TEST(test_string_construct) { 1.41 + cxstring s1 = CX_STR("1234"); 1.42 + cxstring s2 = cx_strn("abcd", 2); 1.43 + cxmutstr s3 = cx_mutstr((char *) "1234"); 1.44 + cxmutstr s4 = cx_mutstrn((char *) "abcd", 2); 1.45 + CX_TEST_DO { 1.46 + CX_TEST_ASSERT(s1.length == 4); 1.47 + CX_TEST_ASSERT(strncmp(s1.ptr, "1234", 4) == 0); 1.48 + CX_TEST_ASSERT(s2.length == 2); 1.49 + CX_TEST_ASSERT(strncmp(s2.ptr, "ab", 2) == 0); 1.50 + CX_TEST_ASSERT(s3.length == 4); 1.51 + CX_TEST_ASSERT(strncmp(s3.ptr, "1234", 4) == 0); 1.52 + CX_TEST_ASSERT(s4.length == 2); 1.53 + CX_TEST_ASSERT(strncmp(s4.ptr, "ab", 2) == 0); 1.54 + } 1.55 +} 1.56 + 1.57 +CX_TEST(test_strfree) { 1.58 + CxTestingAllocator talloc; 1.59 + cx_testing_allocator_init(&talloc); 1.60 + CxAllocator *alloc = &talloc.base; 1.61 + CX_TEST_DO { 1.62 + char *test = cxMalloc(alloc, 16); 1.63 + cxmutstr str = cx_mutstrn(test, 16); 1.64 + CX_TEST_ASSERT(str.ptr == test); 1.65 + CX_TEST_ASSERT(str.length == 16); 1.66 + cx_strfree_a(alloc, &str); 1.67 + CX_TEST_ASSERT(str.ptr == NULL); 1.68 + CX_TEST_ASSERT(str.length == 0); 1.69 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 1.70 + } 1.71 + cx_testing_allocator_destroy(&talloc); 1.72 +} 1.73 + 1.74 +CX_TEST(test_strdup) { 1.75 + cxstring str = CX_STR("test"); 1.76 + cxmutstr dup = cx_strdup(str); 1.77 + CX_TEST_DO { 1.78 + CX_TEST_ASSERT(dup.length == str.length); 1.79 + CX_TEST_ASSERT(0 == strcmp(dup.ptr, str.ptr)); 1.80 + ASSERT_ZERO_TERMINATED(dup); 1.81 + } 1.82 + cx_strfree(&dup); 1.83 +} 1.84 + 1.85 +CX_TEST(test_strdup_shortened) { 1.86 + cxstring str = CX_STR("test"); 1.87 + str.length = 2; 1.88 + cxmutstr dup = cx_strdup(str); 1.89 + CX_TEST_DO { 1.90 + CX_TEST_ASSERT(dup.length == str.length); 1.91 + CX_TEST_ASSERT(0 == strcmp(dup.ptr, "te")); 1.92 + ASSERT_ZERO_TERMINATED(dup); 1.93 + } 1.94 + cx_strfree(&dup); 1.95 +} 1.96 + 1.97 +CX_TEST(test_strlen) { 1.98 + cxstring s1 = CX_STR("1234"); 1.99 + cxstring s2 = CX_STR(".:.:."); 1.100 + cxstring s3 = CX_STR("X"); 1.101 + CX_TEST_DO { 1.102 + size_t len0 = cx_strlen(0); 1.103 + size_t len1 = cx_strlen(1, s1); 1.104 + size_t len2 = cx_strlen(2, s1, s2); 1.105 + size_t len3 = cx_strlen(3, s1, s2, s3); 1.106 + 1.107 + CX_TEST_ASSERT(len0 == 0); 1.108 + CX_TEST_ASSERT(len1 == 4); 1.109 + CX_TEST_ASSERT(len2 == 9); 1.110 + CX_TEST_ASSERT(len3 == 10); 1.111 + } 1.112 +} 1.113 + 1.114 +CX_TEST(test_strsubs) { 1.115 + cxstring str = CX_STR("A test string"); 1.116 + 1.117 + CX_TEST_DO { 1.118 + cxstring sub = cx_strsubs(str, 0); 1.119 + CX_TEST_ASSERT(0 == cx_strcmp(sub, str)); 1.120 + 1.121 + sub = cx_strsubs(str, 2); 1.122 + CX_TEST_ASSERT(0 == cx_strcmp(sub, CX_STR("test string"))); 1.123 + 1.124 + sub = cx_strsubs(str, 7); 1.125 + CX_TEST_ASSERT(0 == cx_strcmp(sub, CX_STR("string"))); 1.126 + 1.127 + sub = cx_strsubs(str, 15); 1.128 + CX_TEST_ASSERT(0 == cx_strcmp(sub, CX_STR(""))); 1.129 + 1.130 + sub = cx_strsubsl(str, 2, 4); 1.131 + CX_TEST_ASSERT(0 == cx_strcmp(sub, CX_STR("test"))); 1.132 + 1.133 + sub = cx_strsubsl(str, 7, 3); 1.134 + CX_TEST_ASSERT(0 == cx_strcmp(sub, CX_STR("str"))); 1.135 + 1.136 + sub = cx_strsubsl(str, 7, 20); 1.137 + CX_TEST_ASSERT(0 == cx_strcmp(sub, CX_STR("string"))); 1.138 + 1.139 + // just for coverage, call the _m variant 1.140 + cxmutstr m = cx_strsubs_m(cx_mutstrn(NULL, 0), 0); 1.141 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(m), CX_STR(""))); 1.142 + } 1.143 +} 1.144 + 1.145 +CX_TEST(test_strchr) { 1.146 + cxstring str = CX_STR("I will find you - and I will kill you"); 1.147 + 1.148 + CX_TEST_DO { 1.149 + cxstring notfound = cx_strchr(str, 'x'); 1.150 + CX_TEST_ASSERT(notfound.length == 0); 1.151 + 1.152 + cxstring result = cx_strchr(str, 'w'); 1.153 + CX_TEST_ASSERT(result.length == 35); 1.154 + CX_TEST_ASSERT(0 == strcmp(result.ptr, "will find you - and I will kill you")); 1.155 + 1.156 + // just for coverage, call the _m variant 1.157 + cxmutstr m = cx_strchr_m(cx_mutstrn(NULL, 0), 'a'); 1.158 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(m), CX_STR(""))); 1.159 + } 1.160 +} 1.161 + 1.162 +CX_TEST(test_strrchr) { 1.163 + cxstring str = CX_STR("I will find you - and I will kill you"); 1.164 + 1.165 + CX_TEST_DO { 1.166 + cxstring notfound = cx_strrchr(str, 'x'); 1.167 + CX_TEST_ASSERT(notfound.length == 0); 1.168 + 1.169 + cxstring result = cx_strrchr(str, 'w'); 1.170 + CX_TEST_ASSERT(result.length == 13); 1.171 + CX_TEST_ASSERT(0 == strcmp(result.ptr, "will kill you")); 1.172 + 1.173 + // just for coverage, call the _m variant 1.174 + cxmutstr m = cx_strrchr_m(cx_mutstrn(NULL, 0), 'a'); 1.175 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(m), CX_STR(""))); 1.176 + } 1.177 +} 1.178 + 1.179 +CX_TEST(test_strstr) { 1.180 + cxstring str = CX_STR("find the match in this string"); 1.181 + cxstring longstr = CX_STR( 1.182 + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" 1.183 + "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx" 1.184 + "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij" 1.185 + "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv" 1.186 + "abababababababababababababababababababababababababababababababab" 1.187 + "abababababababababababababababababababababababababababababababab" 1.188 + "abababababababababababababababababababababababababababababababab" 1.189 + "abababababababababababababababababababababababababababababababab" 1.190 + "abababababababababababababababababababababababababababababababab" 1.191 + "abababababababababababababababababababababababababababababababab" 1.192 + "wxyz1234567890"); 1.193 + cxstring longstrpattern = CX_STR( 1.194 + "abababababababababababababababababababababababababababababababab" 1.195 + "abababababababababababababababababababababababababababababababab" 1.196 + "abababababababababababababababababababababababababababababababab" 1.197 + "abababababababababababababababababababababababababababababababab" 1.198 + "abababababababababababababababababababababababababababababababab" 1.199 + ); 1.200 + cxstring longstrresult = CX_STR( 1.201 + "abababababababababababababababababababababababababababababababab" 1.202 + "abababababababababababababababababababababababababababababababab" 1.203 + "abababababababababababababababababababababababababababababababab" 1.204 + "abababababababababababababababababababababababababababababababab" 1.205 + "abababababababababababababababababababababababababababababababab" 1.206 + "abababababababababababababababababababababababababababababababab" 1.207 + "wxyz1234567890" 1.208 + ); 1.209 + 1.210 + CX_TEST_DO { 1.211 + cxstring notfound = cx_strstr(str, CX_STR("no match")); 1.212 + CX_TEST_ASSERT(notfound.length == 0); 1.213 + 1.214 + cxstring result = cx_strstr(str, CX_STR("match")); 1.215 + CX_TEST_ASSERT(result.length == 20); 1.216 + CX_TEST_ASSERT(0 == strcmp(result.ptr, "match in this string")); 1.217 + 1.218 + result = cx_strstr(str, CX_STR("")); 1.219 + CX_TEST_ASSERT(result.length == str.length); 1.220 + CX_TEST_ASSERT(0 == strcmp(result.ptr, str.ptr)); 1.221 + 1.222 + result = cx_strstr(longstr, longstrpattern); 1.223 + CX_TEST_ASSERT(result.length == longstrresult.length); 1.224 + CX_TEST_ASSERT(0 == strcmp(result.ptr, longstrresult.ptr)); 1.225 + 1.226 + // just for coverage, call the _m variant 1.227 + cxmutstr mstr = cx_strdup(longstr); 1.228 + cxmutstr m = cx_strstr_m(mstr, longstrpattern); 1.229 + CX_TEST_ASSERT(m.length == longstrresult.length); 1.230 + CX_TEST_ASSERT(0 == strcmp(m.ptr, longstrresult.ptr)); 1.231 + cx_strfree(&mstr); 1.232 + } 1.233 +} 1.234 + 1.235 +CX_TEST(test_strcmp) { 1.236 + cxstring str = CX_STR("compare this"); 1.237 + CX_TEST_DO { 1.238 + CX_TEST_ASSERT(0 == cx_strcmp(CX_STR(""), CX_STR(""))); 1.239 + CX_TEST_ASSERT(0 < cx_strcmp(str, CX_STR(""))); 1.240 + CX_TEST_ASSERT(0 == cx_strcmp(str, CX_STR("compare this"))); 1.241 + CX_TEST_ASSERT(0 != cx_strcmp(str, CX_STR("Compare This"))); 1.242 + CX_TEST_ASSERT(0 > cx_strcmp(str, CX_STR("compare tool"))); 1.243 + CX_TEST_ASSERT(0 < cx_strcmp(str, CX_STR("compare shit"))); 1.244 + CX_TEST_ASSERT(0 > cx_strcmp(str, CX_STR("compare this not"))); 1.245 + CX_TEST_ASSERT(0 < cx_strcmp(str, CX_STR("compare"))); 1.246 + 1.247 + cxstring str2 = CX_STR("Compare This"); 1.248 + CX_TEST_ASSERT(0 != cx_strcmp_p(&str, &str2)); 1.249 + str2 = CX_STR("compare this"); 1.250 + CX_TEST_ASSERT(0 == cx_strcmp_p(&str, &str2)); 1.251 + } 1.252 +} 1.253 + 1.254 +CX_TEST(test_strcasecmp) { 1.255 + cxstring str = CX_STR("compare this"); 1.256 + CX_TEST_DO { 1.257 + CX_TEST_ASSERT(0 == cx_strcasecmp(CX_STR(""), CX_STR(""))); 1.258 + CX_TEST_ASSERT(0 < cx_strcasecmp(str, CX_STR(""))); 1.259 + CX_TEST_ASSERT(0 == cx_strcasecmp(str, CX_STR("compare this"))); 1.260 + CX_TEST_ASSERT(0 == cx_strcasecmp(str, CX_STR("Compare This"))); 1.261 + CX_TEST_ASSERT(0 > cx_strcasecmp(str, CX_STR("compare tool"))); 1.262 + CX_TEST_ASSERT(0 < cx_strcasecmp(str, CX_STR("compare shit"))); 1.263 + CX_TEST_ASSERT(0 > cx_strcasecmp(str, CX_STR("compare this not"))); 1.264 + CX_TEST_ASSERT(0 < cx_strcasecmp(str, CX_STR("compare"))); 1.265 + 1.266 + cxstring str2 = CX_STR("Compare This"); 1.267 + CX_TEST_ASSERT(0 == cx_strcasecmp_p(&str, &str2)); 1.268 + str2 = CX_STR("Compare Tool"); 1.269 + CX_TEST_ASSERT(0 > cx_strcasecmp_p(&str, &str2)); 1.270 + } 1.271 +} 1.272 + 1.273 +CX_TEST(test_strcat) { 1.274 + cxstring s1 = CX_STR("12"); 1.275 + cxstring s2 = CX_STR("34"); 1.276 + cxstring s3 = CX_STR("56"); 1.277 + cxstring sn = {NULL, 0}; 1.278 + 1.279 + CxTestingAllocator talloc; 1.280 + cx_testing_allocator_init(&talloc); 1.281 + CxAllocator *alloc = &talloc.base; 1.282 + 1.283 + CX_TEST_DO { 1.284 + cxmutstr t1 = cx_strcat_a(alloc, 2, s1, s2); 1.285 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(t1), CX_STR("1234"))); 1.286 + ASSERT_ZERO_TERMINATED(t1); 1.287 + cx_strfree_a(alloc, &t1); 1.288 + 1.289 + cxmutstr t2 = cx_strcat_a(alloc, 3, s1, s2, s3); 1.290 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(t2), CX_STR("123456"))); 1.291 + ASSERT_ZERO_TERMINATED(t2); 1.292 + cx_strfree_a(alloc, &t2); 1.293 + 1.294 + cxmutstr t3 = cx_strcat_a(alloc, 6, s1, sn, s2, sn, s3, sn); 1.295 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(t3), CX_STR("123456"))); 1.296 + ASSERT_ZERO_TERMINATED(t3); 1.297 + cx_strfree_a(alloc, &t3); 1.298 + 1.299 + cxmutstr t4 = cx_strcat_a(alloc, 2, sn, sn); 1.300 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(t4), CX_STR(""))); 1.301 + ASSERT_ZERO_TERMINATED(t4); 1.302 + cx_strfree_a(alloc, &t4); 1.303 + 1.304 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 1.305 + 1.306 + // use the macro 1.307 + cxmutstr t5 = cx_strcat(3, s3, s1, s2); 1.308 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(t5), CX_STR("561234"))); 1.309 + ASSERT_ZERO_TERMINATED(t5); 1.310 + cx_strfree(&t5); 1.311 + 1.312 + // use an initial string 1.313 + cxmutstr t6 = cx_strdup(CX_STR("Hello")); 1.314 + t6 = cx_strcat_m(t6, 2, CX_STR(", "), CX_STR("World!")); 1.315 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(t6), CX_STR("Hello, World!"))); 1.316 + ASSERT_ZERO_TERMINATED(t6); 1.317 + cx_strfree(&t6); 1.318 + } 1.319 + cx_testing_allocator_destroy(&talloc); 1.320 +} 1.321 + 1.322 +CX_TEST(test_strsplit) { 1.323 + cxstring test = CX_STR("this,is,a,csv,string"); 1.324 + size_t capa = 8; 1.325 + cxstring list[8]; 1.326 + size_t n; 1.327 + CX_TEST_DO { 1.328 + // special case: empty string 1.329 + n = cx_strsplit(test, CX_STR(""), capa, list); 1.330 + CX_TEST_ASSERT(n == 1); 1.331 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.332 + 1.333 + // no delimiter occurrence 1.334 + n = cx_strsplit(test, CX_STR("z"), capa, list); 1.335 + CX_TEST_ASSERT(n == 1); 1.336 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.337 + 1.338 + // partially matching delimiter 1.339 + n = cx_strsplit(test, CX_STR("is,not"), capa, list); 1.340 + CX_TEST_ASSERT(n == 1); 1.341 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.342 + 1.343 + // matching single-char delimiter 1.344 + n = cx_strsplit(test, CX_STR(","), capa, list); 1.345 + CX_TEST_ASSERT(n == 5); 1.346 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("this"))); 1.347 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR("is"))); 1.348 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("a"))); 1.349 + CX_TEST_ASSERT(0 == cx_strcmp(list[3], CX_STR("csv"))); 1.350 + CX_TEST_ASSERT(0 == cx_strcmp(list[4], CX_STR("string"))); 1.351 + 1.352 + // matching multi-char delimiter 1.353 + n = cx_strsplit(test, CX_STR("is"), capa, list); 1.354 + CX_TEST_ASSERT(n == 3); 1.355 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("th"))); 1.356 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(","))); 1.357 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR(",a,csv,string"))); 1.358 + 1.359 + // bounded list using single-char delimiter 1.360 + n = cx_strsplit(test, CX_STR(","), 3, list); 1.361 + CX_TEST_ASSERT(n == 3); 1.362 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("this"))); 1.363 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR("is"))); 1.364 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("a,csv,string"))); 1.365 + 1.366 + // bounded list using multi-char delimiter 1.367 + n = cx_strsplit(test, CX_STR("is"), 2, list); 1.368 + CX_TEST_ASSERT(n == 2); 1.369 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("th"))); 1.370 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(",is,a,csv,string"))); 1.371 + 1.372 + // start with delimiter 1.373 + n = cx_strsplit(test, CX_STR("this"), capa, list); 1.374 + CX_TEST_ASSERT(n == 2); 1.375 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR(""))); 1.376 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(",is,a,csv,string"))); 1.377 + 1.378 + // end with delimiter 1.379 + n = cx_strsplit(test, CX_STR("string"), capa, list); 1.380 + CX_TEST_ASSERT(n == 2); 1.381 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("this,is,a,csv,"))); 1.382 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(""))); 1.383 + 1.384 + 1.385 + // end with delimiter exceed bound 1.386 + n = cx_strsplit(CX_STR("a,b,c,"), CX_STR(","), 3, list); 1.387 + CX_TEST_ASSERT(n == 3); 1.388 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("a"))); 1.389 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR("b"))); 1.390 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("c,"))); 1.391 + 1.392 + // exact match 1.393 + n = cx_strsplit(test, CX_STR("this,is,a,csv,string"), capa, list); 1.394 + CX_TEST_ASSERT(n == 2); 1.395 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR(""))); 1.396 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(""))); 1.397 + 1.398 + // string to be split is only substring 1.399 + n = cx_strsplit(test, CX_STR("this,is,a,csv,string,with,extension"), capa, list); 1.400 + CX_TEST_ASSERT(n == 1); 1.401 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.402 + 1.403 + // subsequent encounter of delimiter (the string between is empty) 1.404 + n = cx_strsplit(test, CX_STR("is,"), capa, list); 1.405 + CX_TEST_ASSERT(n == 3); 1.406 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("th"))); 1.407 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(""))); 1.408 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("a,csv,string"))); 1.409 + 1.410 + // call the _m variant just for coverage 1.411 + cxmutstr mtest = cx_strdup(test); 1.412 + cxmutstr mlist[4]; 1.413 + n = cx_strsplit_m(mtest, CX_STR("is,"), 4, mlist); 1.414 + CX_TEST_ASSERT(n == 3); 1.415 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(mlist[0]), CX_STR("th"))); 1.416 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(mlist[1]), CX_STR(""))); 1.417 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(mlist[2]), CX_STR("a,csv,string"))); 1.418 + cx_strfree(&mtest); 1.419 + } 1.420 +} 1.421 + 1.422 +CX_TEST(test_strsplit_a) { 1.423 + CxTestingAllocator talloc; 1.424 + cx_testing_allocator_init(&talloc); 1.425 + CxAllocator *alloc = &talloc.base; 1.426 + 1.427 + cxstring test = CX_STR("this,is,a,csv,string"); 1.428 + size_t capa = 8; 1.429 + cxstring *list; 1.430 + size_t n; 1.431 + CX_TEST_DO { 1.432 + // special case: empty string 1.433 + n = cx_strsplit_a(alloc, test, CX_STR(""), capa, &list); 1.434 + CX_TEST_ASSERT(n == 1); 1.435 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.436 + cxFree(alloc, list); 1.437 + 1.438 + // no delimiter occurrence 1.439 + n = cx_strsplit_a(alloc, test, CX_STR("z"), capa, &list); 1.440 + CX_TEST_ASSERT(n == 1); 1.441 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.442 + cxFree(alloc, list); 1.443 + 1.444 + // partially matching delimiter 1.445 + n = cx_strsplit_a(alloc, test, CX_STR("is,not"), capa, &list); 1.446 + CX_TEST_ASSERT(n == 1); 1.447 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.448 + cxFree(alloc, list); 1.449 + 1.450 + // matching single-char delimiter 1.451 + n = cx_strsplit_a(alloc, test, CX_STR(","), capa, &list); 1.452 + CX_TEST_ASSERT(n == 5); 1.453 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("this"))); 1.454 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR("is"))); 1.455 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("a"))); 1.456 + CX_TEST_ASSERT(0 == cx_strcmp(list[3], CX_STR("csv"))); 1.457 + CX_TEST_ASSERT(0 == cx_strcmp(list[4], CX_STR("string"))); 1.458 + cxFree(alloc, list); 1.459 + 1.460 + // matching multi-char delimiter 1.461 + n = cx_strsplit_a(alloc, test, CX_STR("is"), capa, &list); 1.462 + CX_TEST_ASSERT(n == 3); 1.463 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("th"))); 1.464 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(","))); 1.465 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR(",a,csv,string"))); 1.466 + cxFree(alloc, list); 1.467 + 1.468 + // bounded list using single-char delimiter 1.469 + n = cx_strsplit_a(alloc, test, CX_STR(","), 3, &list); 1.470 + CX_TEST_ASSERT(n == 3); 1.471 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("this"))); 1.472 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR("is"))); 1.473 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("a,csv,string"))); 1.474 + cxFree(alloc, list); 1.475 + 1.476 + // bounded list using multi-char delimiter 1.477 + n = cx_strsplit_a(alloc, test, CX_STR("is"), 2, &list); 1.478 + CX_TEST_ASSERT(n == 2); 1.479 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("th"))); 1.480 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(",is,a,csv,string"))); 1.481 + cxFree(alloc, list); 1.482 + 1.483 + // start with delimiter 1.484 + n = cx_strsplit_a(alloc, test, CX_STR("this"), capa, &list); 1.485 + CX_TEST_ASSERT(n == 2); 1.486 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR(""))); 1.487 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(",is,a,csv,string"))); 1.488 + cxFree(alloc, list); 1.489 + 1.490 + // end with delimiter 1.491 + n = cx_strsplit_a(alloc, test, CX_STR("string"), capa, &list); 1.492 + CX_TEST_ASSERT(n == 2); 1.493 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("this,is,a,csv,"))); 1.494 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(""))); 1.495 + cxFree(alloc, list); 1.496 + 1.497 + // end with delimiter exceed bound 1.498 + n = cx_strsplit_a(alloc, CX_STR("a,b,c,"), CX_STR(","), 3, &list); 1.499 + CX_TEST_ASSERT(n == 3); 1.500 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("a"))); 1.501 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR("b"))); 1.502 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("c,"))); 1.503 + cxFree(alloc, list); 1.504 + 1.505 + // exact match 1.506 + n = cx_strsplit_a(alloc, test, CX_STR("this,is,a,csv,string"), capa, &list); 1.507 + CX_TEST_ASSERT(n == 2); 1.508 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR(""))); 1.509 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(""))); 1.510 + cxFree(alloc, list); 1.511 + 1.512 + // string to be split is only substring 1.513 + n = cx_strsplit_a(alloc, test, CX_STR("this,is,a,csv,string,with,extension"), capa, &list); 1.514 + CX_TEST_ASSERT(n == 1); 1.515 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], test)); 1.516 + cxFree(alloc, list); 1.517 + 1.518 + // subsequent encounter of delimiter (the string between is empty) 1.519 + n = cx_strsplit_a(alloc, test, CX_STR("is,"), capa, &list); 1.520 + CX_TEST_ASSERT(n == 3); 1.521 + CX_TEST_ASSERT(0 == cx_strcmp(list[0], CX_STR("th"))); 1.522 + CX_TEST_ASSERT(0 == cx_strcmp(list[1], CX_STR(""))); 1.523 + CX_TEST_ASSERT(0 == cx_strcmp(list[2], CX_STR("a,csv,string"))); 1.524 + cxFree(alloc, list); 1.525 + 1.526 + // call the _m variant just for coverage 1.527 + cxmutstr mtest = cx_strdup(test); 1.528 + cxmutstr *mlist; 1.529 + n = cx_strsplit_ma(alloc, mtest, CX_STR("is,"), 4, &mlist); 1.530 + CX_TEST_ASSERT(n == 3); 1.531 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(mlist[0]), CX_STR("th"))); 1.532 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(mlist[1]), CX_STR(""))); 1.533 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(mlist[2]), CX_STR("a,csv,string"))); 1.534 + cxFree(alloc, mlist); 1.535 + cx_strfree(&mtest); 1.536 + 1.537 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 1.538 + } 1.539 + cx_testing_allocator_destroy(&talloc); 1.540 +} 1.541 + 1.542 +CX_TEST(test_strtrim) { 1.543 + cxstring t1 = cx_strtrim(CX_STR(" ein test \t ")); 1.544 + cxstring t2 = cx_strtrim(CX_STR("abc")); 1.545 + cxstring t3 = cx_strtrim(CX_STR(" 123")); 1.546 + cxstring t4 = cx_strtrim(CX_STR("xyz ")); 1.547 + cxstring t5 = cx_strtrim(CX_STR(" ")); 1.548 + cxstring empty = cx_strtrim(CX_STR("")); 1.549 + 1.550 + CX_TEST_DO { 1.551 + CX_TEST_ASSERT(0 == cx_strcmp(t1, CX_STR("ein test"))); 1.552 + CX_TEST_ASSERT(0 == cx_strcmp(t2, CX_STR("abc"))); 1.553 + CX_TEST_ASSERT(0 == cx_strcmp(t3, CX_STR("123"))); 1.554 + CX_TEST_ASSERT(0 == cx_strcmp(t4, CX_STR("xyz"))); 1.555 + CX_TEST_ASSERT(0 == cx_strcmp(t5, CX_STR(""))); 1.556 + CX_TEST_ASSERT(0 == cx_strcmp(empty, CX_STR(""))); 1.557 + 1.558 + // call the _m variant just for coverage 1.559 + cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) " ein test \t ")); 1.560 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(m1), CX_STR("ein test"))); 1.561 + } 1.562 +} 1.563 + 1.564 +CX_TEST(test_strprefix) { 1.565 + cxstring str = CX_STR("test my prefix and my suffix"); 1.566 + cxstring empty = CX_STR(""); 1.567 + CX_TEST_DO { 1.568 + CX_TEST_ASSERT(!cx_strprefix(empty, CX_STR("pref"))); 1.569 + CX_TEST_ASSERT(cx_strprefix(str, empty)); 1.570 + CX_TEST_ASSERT(cx_strprefix(empty, empty)); 1.571 + CX_TEST_ASSERT(cx_strprefix(str, CX_STR("test "))); 1.572 + CX_TEST_ASSERT(!cx_strprefix(str, CX_STR("8-) fsck "))); 1.573 + } 1.574 +} 1.575 + 1.576 +CX_TEST(test_strsuffix) { 1.577 + cxstring str = CX_STR("test my prefix and my suffix"); 1.578 + cxstring empty = CX_STR(""); 1.579 + CX_TEST_DO { 1.580 + CX_TEST_ASSERT(!cx_strsuffix(empty, CX_STR("suf"))); 1.581 + CX_TEST_ASSERT(cx_strsuffix(str, empty)); 1.582 + CX_TEST_ASSERT(cx_strsuffix(empty, empty)); 1.583 + CX_TEST_ASSERT(cx_strsuffix(str, CX_STR("fix"))); 1.584 + CX_TEST_ASSERT(!cx_strsuffix(str, CX_STR("fox"))); 1.585 + } 1.586 +} 1.587 + 1.588 +CX_TEST(test_strcaseprefix) { 1.589 + cxstring str = CX_STR("test my prefix and my suffix"); 1.590 + cxstring empty = CX_STR(""); 1.591 + CX_TEST_DO { 1.592 + CX_TEST_ASSERT(!cx_strcaseprefix(empty, CX_STR("pREf"))); 1.593 + CX_TEST_ASSERT(cx_strcaseprefix(str, empty)); 1.594 + CX_TEST_ASSERT(cx_strcaseprefix(empty, empty)); 1.595 + CX_TEST_ASSERT(cx_strcaseprefix(str, CX_STR("TEST "))); 1.596 + CX_TEST_ASSERT(!cx_strcaseprefix(str, CX_STR("8-) fsck "))); 1.597 + } 1.598 +} 1.599 + 1.600 +CX_TEST(test_strcasesuffix) { 1.601 + cxstring str = CX_STR("test my prefix and my suffix"); 1.602 + cxstring empty = CX_STR(""); 1.603 + CX_TEST_DO { 1.604 + CX_TEST_ASSERT(!cx_strcasesuffix(empty, CX_STR("sUf"))); 1.605 + CX_TEST_ASSERT(cx_strcasesuffix(str, empty)); 1.606 + CX_TEST_ASSERT(cx_strcasesuffix(empty, empty)); 1.607 + CX_TEST_ASSERT(cx_strcasesuffix(str, CX_STR("FIX"))); 1.608 + CX_TEST_ASSERT(!cx_strcasesuffix(str, CX_STR("fox"))); 1.609 + } 1.610 +} 1.611 + 1.612 +CX_TEST(test_strreplace) { 1.613 + CxTestingAllocator talloc; 1.614 + cx_testing_allocator_init(&talloc); 1.615 + CxAllocator *alloc = &talloc.base; 1.616 + 1.617 + cxstring str = CX_STR("test ababab string aba"); 1.618 + cxstring longstr = CX_STR( 1.619 + "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd"); 1.620 + cxstring notrail = CX_STR("test abab"); 1.621 + cxstring empty = CX_STR(""); 1.622 + cxstring astr = CX_STR("aaaaaaaaaa"); 1.623 + cxstring csstr = CX_STR("test AB ab TEST xyz"); 1.624 + 1.625 + cxmutstr repl = cx_strreplace(str, CX_STR("abab"), CX_STR("muchlonger")); 1.626 + char const *expected = "test muchlongerab string aba"; 1.627 + 1.628 + cxmutstr repln = cx_strreplacen(str, CX_STR("ab"), CX_STR("c"), 2); 1.629 + char const *expectedn = "test ccab string aba"; 1.630 + 1.631 + cxmutstr longrepl = cx_strreplace(longstr, CX_STR("a"), CX_STR("z")); 1.632 + char const *longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd"; 1.633 + 1.634 + cxmutstr replnotrail = cx_strreplace(notrail, CX_STR("ab"), CX_STR("z")); 1.635 + char const *notrailexpect = "test zz"; 1.636 + 1.637 + cxmutstr repleq = cx_strreplace(str, str, CX_STR("hello")); 1.638 + char const *eqexpect = "hello"; 1.639 + 1.640 + cxmutstr replempty1 = cx_strreplace(empty, CX_STR("ab"), CX_STR("c")); // expect: empty 1.641 + cxmutstr replempty2 = cx_strreplace(str, CX_STR("abab"), empty); 1.642 + char const *emptyexpect2 = "test ab string aba"; 1.643 + 1.644 + cxmutstr replpre = cx_strreplace(str, CX_STR("test "), CX_STR("TEST ")); 1.645 + char const *preexpected = "TEST ababab string aba"; 1.646 + 1.647 + cxmutstr replan1 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 1); 1.648 + char const *an1expected = "xaaaaaaaaa"; 1.649 + 1.650 + cxmutstr replan4 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 4); 1.651 + char const *an4expected = "xxxxaaaaaa"; 1.652 + 1.653 + cxmutstr replan9 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 9); 1.654 + char const *an9expected = "xxxxxxxxxa"; 1.655 + 1.656 + cxmutstr replan10 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 10); 1.657 + char const *an10expected = "xxxxxxxxxx"; 1.658 + 1.659 + CX_TEST_DO { 1.660 + cxmutstr repl1_a = cx_strreplace_a(alloc, csstr, CX_STR("AB"), CX_STR("*")); 1.661 + char const *expeced1_a = "test * ab TEST xyz"; 1.662 + 1.663 + cxmutstr repl2_a = cx_strreplace_a(alloc, csstr, CX_STR("test"), CX_STR("TEST")); 1.664 + char const *expected2_a = "TEST AB ab TEST xyz"; 1.665 + 1.666 + CX_TEST_ASSERT(repl.ptr != str.ptr); 1.667 + ASSERT_ZERO_TERMINATED(repl); 1.668 + CX_TEST_ASSERT(0 == strcmp(repl.ptr, expected)); 1.669 + ASSERT_ZERO_TERMINATED(repln); 1.670 + CX_TEST_ASSERT(0 == strcmp(repln.ptr, expectedn)); 1.671 + ASSERT_ZERO_TERMINATED(longrepl); 1.672 + CX_TEST_ASSERT(0 == strcmp(longrepl.ptr, longexpect)); 1.673 + ASSERT_ZERO_TERMINATED(replnotrail); 1.674 + CX_TEST_ASSERT(0 == strcmp(replnotrail.ptr, notrailexpect)); 1.675 + ASSERT_ZERO_TERMINATED(repleq); 1.676 + CX_TEST_ASSERT(0 == strcmp(repleq.ptr, eqexpect)); 1.677 + ASSERT_ZERO_TERMINATED(replempty1); 1.678 + CX_TEST_ASSERT(0 == strcmp(replempty1.ptr, "")); 1.679 + ASSERT_ZERO_TERMINATED(replempty2); 1.680 + CX_TEST_ASSERT(0 == strcmp(replempty2.ptr, emptyexpect2)); 1.681 + ASSERT_ZERO_TERMINATED(replpre); 1.682 + CX_TEST_ASSERT(0 == strcmp(replpre.ptr, preexpected)); 1.683 + ASSERT_ZERO_TERMINATED(replan1); 1.684 + CX_TEST_ASSERT(0 == strcmp(replan1.ptr, an1expected)); 1.685 + ASSERT_ZERO_TERMINATED(replan4); 1.686 + CX_TEST_ASSERT(0 == strcmp(replan4.ptr, an4expected)); 1.687 + ASSERT_ZERO_TERMINATED(replan9); 1.688 + CX_TEST_ASSERT(0 == strcmp(replan9.ptr, an9expected)); 1.689 + ASSERT_ZERO_TERMINATED(replan10); 1.690 + CX_TEST_ASSERT(0 == strcmp(replan10.ptr, an10expected)); 1.691 + ASSERT_ZERO_TERMINATED(repl1_a); 1.692 + CX_TEST_ASSERT(0 == strcmp(repl1_a.ptr, expeced1_a)); 1.693 + ASSERT_ZERO_TERMINATED(repl2_a); 1.694 + CX_TEST_ASSERT(0 == strcmp(repl2_a.ptr, expected2_a)); 1.695 + 1.696 + cx_strfree_a(alloc, &repl1_a); 1.697 + cx_strfree_a(alloc, &repl2_a); 1.698 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 1.699 + } 1.700 + 1.701 + cx_strfree(&repl); 1.702 + cx_strfree(&repln); 1.703 + cx_strfree(&longrepl); 1.704 + cx_strfree(&replnotrail); 1.705 + cx_strfree(&repleq); 1.706 + cx_strfree(&replempty1); 1.707 + cx_strfree(&replempty2); 1.708 + cx_strfree(&replpre); 1.709 + cx_strfree(&replan1); 1.710 + cx_strfree(&replan4); 1.711 + cx_strfree(&replan9); 1.712 + cx_strfree(&replan10); 1.713 + cx_testing_allocator_destroy(&talloc); 1.714 +} 1.715 + 1.716 +CX_TEST(test_strupper) { 1.717 + cxmutstr str = cx_strdup(CX_STR("thIs 1s @ Te$t")); 1.718 + CX_TEST_DO { 1.719 + cx_strupper(str); 1.720 + CX_TEST_ASSERT(0 == strcmp(str.ptr, "THIS 1S @ TE$T")); 1.721 + } 1.722 + cx_strfree(&str); 1.723 +} 1.724 + 1.725 +CX_TEST(test_strlower) { 1.726 + cxmutstr str = cx_strdup(CX_STR("thIs 1s @ Te$t")); 1.727 + CX_TEST_DO { 1.728 + cx_strlower(str); 1.729 + CX_TEST_ASSERT(0 == strcmp(str.ptr, "this 1s @ te$t")); 1.730 + } 1.731 + cx_strfree(&str); 1.732 +} 1.733 + 1.734 +CX_TEST(test_strtok) { 1.735 + cxstring str = CX_STR("a,comma,separated,string"); 1.736 + cxstring delim = CX_STR(","); 1.737 + CX_TEST_DO { 1.738 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 1.739 + CX_TEST_ASSERT(ctx.str.ptr == str.ptr); 1.740 + CX_TEST_ASSERT(ctx.str.length == str.length); 1.741 + CX_TEST_ASSERT(ctx.delim.ptr == delim.ptr); 1.742 + CX_TEST_ASSERT(ctx.delim.length == delim.length); 1.743 + CX_TEST_ASSERT(ctx.limit == 3); 1.744 + CX_TEST_ASSERT(ctx.found == 0); 1.745 + CX_TEST_ASSERT(ctx.pos == 0); 1.746 + CX_TEST_ASSERT(ctx.next_pos == 0); 1.747 + CX_TEST_ASSERT(ctx.delim_more == NULL); 1.748 + CX_TEST_ASSERT(ctx.delim_more_count == 0); 1.749 + } 1.750 +} 1.751 + 1.752 +CX_TEST(test_strtok_m) { 1.753 + cxmutstr str = cx_strdup(CX_STR("a,comma,separated,string")); 1.754 + cxstring delim = CX_STR(","); 1.755 + CX_TEST_DO { 1.756 + CxStrtokCtx ctx = cx_strtok_m(str, delim, 3); 1.757 + CX_TEST_ASSERT(ctx.str.ptr == str.ptr); 1.758 + CX_TEST_ASSERT(ctx.str.length == str.length); 1.759 + CX_TEST_ASSERT(ctx.delim.ptr == delim.ptr); 1.760 + CX_TEST_ASSERT(ctx.delim.length == delim.length); 1.761 + CX_TEST_ASSERT(ctx.limit == 3); 1.762 + CX_TEST_ASSERT(ctx.found == 0); 1.763 + CX_TEST_ASSERT(ctx.pos == 0); 1.764 + CX_TEST_ASSERT(ctx.next_pos == 0); 1.765 + CX_TEST_ASSERT(ctx.delim_more == NULL); 1.766 + CX_TEST_ASSERT(ctx.delim_more_count == 0); 1.767 + } 1.768 + cx_strfree(&str); 1.769 +} 1.770 + 1.771 +CX_TEST(test_strtok_delim) { 1.772 + cxstring str = CX_STR("an,arbitrarily|separated;string"); 1.773 + cxstring delim = CX_STR(","); 1.774 + cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")}; 1.775 + CX_TEST_DO { 1.776 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 1.777 + cx_strtok_delim(&ctx, delim_more, 2); 1.778 + CX_TEST_ASSERT(ctx.str.ptr == str.ptr); 1.779 + CX_TEST_ASSERT(ctx.str.length == str.length); 1.780 + CX_TEST_ASSERT(ctx.delim.ptr == delim.ptr); 1.781 + CX_TEST_ASSERT(ctx.delim.length == delim.length); 1.782 + CX_TEST_ASSERT(ctx.limit == 3); 1.783 + CX_TEST_ASSERT(ctx.found == 0); 1.784 + CX_TEST_ASSERT(ctx.pos == 0); 1.785 + CX_TEST_ASSERT(ctx.next_pos == 0); 1.786 + CX_TEST_ASSERT(ctx.delim_more == delim_more); 1.787 + CX_TEST_ASSERT(ctx.delim_more_count == 2); 1.788 + } 1.789 +} 1.790 + 1.791 +CX_TEST(test_strtok_next_easy) { 1.792 + cxstring str = CX_STR("a,comma,separated,string"); 1.793 + cxstring delim = CX_STR(","); 1.794 + CX_TEST_DO { 1.795 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 1.796 + bool ret; 1.797 + cxstring tok; 1.798 + 1.799 + ret = cx_strtok_next(&ctx, &tok); 1.800 + CX_TEST_ASSERT(ret); 1.801 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR("a"))); 1.802 + CX_TEST_ASSERT(ctx.pos == 0); 1.803 + CX_TEST_ASSERT(ctx.next_pos == 2); 1.804 + CX_TEST_ASSERT(ctx.delim_pos == 1); 1.805 + CX_TEST_ASSERT(ctx.found == 1); 1.806 + 1.807 + ret = cx_strtok_next(&ctx, &tok); 1.808 + CX_TEST_ASSERT(ret); 1.809 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR("comma"))); 1.810 + CX_TEST_ASSERT(ctx.pos == 2); 1.811 + CX_TEST_ASSERT(ctx.next_pos == 8); 1.812 + CX_TEST_ASSERT(ctx.delim_pos == 7); 1.813 + CX_TEST_ASSERT(ctx.found == 2); 1.814 + 1.815 + ret = cx_strtok_next(&ctx, &tok); 1.816 + CX_TEST_ASSERT(ret); 1.817 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR("separated"))); 1.818 + CX_TEST_ASSERT(ctx.pos == 8); 1.819 + CX_TEST_ASSERT(ctx.next_pos == 18); 1.820 + CX_TEST_ASSERT(ctx.delim_pos == 17); 1.821 + CX_TEST_ASSERT(ctx.found == 3); 1.822 + 1.823 + ret = cx_strtok_next(&ctx, &tok); 1.824 + CX_TEST_ASSERT(!ret); 1.825 + CX_TEST_ASSERT(ctx.pos == 8); 1.826 + CX_TEST_ASSERT(ctx.next_pos == 18); 1.827 + CX_TEST_ASSERT(ctx.delim_pos == 17); 1.828 + CX_TEST_ASSERT(ctx.found == 3); 1.829 + } 1.830 +} 1.831 + 1.832 +CX_TEST(test_strtok_next_unlimited) { 1.833 + cxstring str = CX_STR("some;-;otherwise;-;separated;-;string;-;"); 1.834 + cxstring delim = CX_STR(";-;"); 1.835 + CX_TEST_DO { 1.836 + CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX); 1.837 + bool ret; 1.838 + cxstring tok; 1.839 + 1.840 + ret = cx_strtok_next(&ctx, &tok); 1.841 + CX_TEST_ASSERT(ret); 1.842 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR("some"))); 1.843 + CX_TEST_ASSERT(ctx.pos == 0); 1.844 + CX_TEST_ASSERT(ctx.next_pos == 7); 1.845 + CX_TEST_ASSERT(ctx.delim_pos == 4); 1.846 + CX_TEST_ASSERT(ctx.found == 1); 1.847 + 1.848 + ret = cx_strtok_next(&ctx, &tok); 1.849 + CX_TEST_ASSERT(ret); 1.850 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR("otherwise"))); 1.851 + CX_TEST_ASSERT(ctx.pos == 7); 1.852 + CX_TEST_ASSERT(ctx.next_pos == 19); 1.853 + CX_TEST_ASSERT(ctx.delim_pos == 16); 1.854 + CX_TEST_ASSERT(ctx.found == 2); 1.855 + 1.856 + ret = cx_strtok_next(&ctx, &tok); 1.857 + CX_TEST_ASSERT(ret); 1.858 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR("separated"))); 1.859 + CX_TEST_ASSERT(ctx.pos == 19); 1.860 + CX_TEST_ASSERT(ctx.next_pos == 31); 1.861 + CX_TEST_ASSERT(ctx.delim_pos == 28); 1.862 + CX_TEST_ASSERT(ctx.found == 3); 1.863 + 1.864 + ret = cx_strtok_next(&ctx, &tok); 1.865 + CX_TEST_ASSERT(ret); 1.866 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR("string"))); 1.867 + CX_TEST_ASSERT(ctx.pos == 31); 1.868 + CX_TEST_ASSERT(ctx.next_pos == 40); 1.869 + CX_TEST_ASSERT(ctx.delim_pos == 37); 1.870 + CX_TEST_ASSERT(ctx.found == 4); 1.871 + 1.872 + ret = cx_strtok_next(&ctx, &tok); 1.873 + CX_TEST_ASSERT(ret); 1.874 + CX_TEST_ASSERT(0 == cx_strcmp(tok, CX_STR(""))); 1.875 + CX_TEST_ASSERT(ctx.pos == 40); 1.876 + CX_TEST_ASSERT(ctx.next_pos == 40); 1.877 + CX_TEST_ASSERT(ctx.delim_pos == 40); 1.878 + CX_TEST_ASSERT(ctx.found == 5); 1.879 + 1.880 + ret = cx_strtok_next(&ctx, &tok); 1.881 + CX_TEST_ASSERT(!ret); 1.882 + CX_TEST_ASSERT(ctx.pos == 40); 1.883 + CX_TEST_ASSERT(ctx.delim_pos == 40); 1.884 + CX_TEST_ASSERT(ctx.found == 5); 1.885 + } 1.886 +} 1.887 + 1.888 +CX_TEST(test_strtok_next_advanced) { 1.889 + cxmutstr str = cx_strdup(CX_STR("an,arbitrarily;||separated;string")); 1.890 + cxstring delim = CX_STR(","); 1.891 + cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")}; 1.892 + CX_TEST_DO { 1.893 + CxStrtokCtx ctx = cx_strtok_m(str, delim, 10); 1.894 + cx_strtok_delim(&ctx, delim_more, 2); 1.895 + bool ret; 1.896 + cxmutstr tok; 1.897 + 1.898 + ret = cx_strtok_next_m(&ctx, &tok); 1.899 + CX_TEST_ASSERT(ret); 1.900 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(tok), CX_STR("an"))); 1.901 + CX_TEST_ASSERT(ctx.pos == 0); 1.902 + CX_TEST_ASSERT(ctx.next_pos == 3); 1.903 + CX_TEST_ASSERT(ctx.delim_pos == 2); 1.904 + CX_TEST_ASSERT(ctx.found == 1); 1.905 + cx_strupper(tok); 1.906 + 1.907 + ret = cx_strtok_next_m(&ctx, &tok); 1.908 + CX_TEST_ASSERT(ret); 1.909 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(tok), CX_STR("arbitrarily"))); 1.910 + CX_TEST_ASSERT(ctx.pos == 3); 1.911 + CX_TEST_ASSERT(ctx.next_pos == 15); 1.912 + CX_TEST_ASSERT(ctx.delim_pos == 14); 1.913 + CX_TEST_ASSERT(ctx.found == 2); 1.914 + cx_strupper(tok); 1.915 + 1.916 + ret = cx_strtok_next_m(&ctx, &tok); 1.917 + CX_TEST_ASSERT(ret); 1.918 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(tok), CX_STR(""))); 1.919 + CX_TEST_ASSERT(ctx.pos == 15); 1.920 + CX_TEST_ASSERT(ctx.next_pos == 17); 1.921 + CX_TEST_ASSERT(ctx.delim_pos == 15); 1.922 + CX_TEST_ASSERT(ctx.found == 3); 1.923 + cx_strupper(tok); 1.924 + 1.925 + ret = cx_strtok_next_m(&ctx, &tok); 1.926 + CX_TEST_ASSERT(ret); 1.927 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(tok), CX_STR("separated"))); 1.928 + CX_TEST_ASSERT(ctx.pos == 17); 1.929 + CX_TEST_ASSERT(ctx.next_pos == 27); 1.930 + CX_TEST_ASSERT(ctx.delim_pos == 26); 1.931 + CX_TEST_ASSERT(ctx.found == 4); 1.932 + cx_strupper(tok); 1.933 + 1.934 + ret = cx_strtok_next_m(&ctx, &tok); 1.935 + CX_TEST_ASSERT(ret); 1.936 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(tok), CX_STR("string"))); 1.937 + CX_TEST_ASSERT(ctx.pos == 27); 1.938 + CX_TEST_ASSERT(ctx.next_pos == 33); 1.939 + CX_TEST_ASSERT(ctx.delim_pos == 33); 1.940 + CX_TEST_ASSERT(ctx.found == 5); 1.941 + cx_strupper(tok); 1.942 + 1.943 + ret = cx_strtok_next_m(&ctx, &tok); 1.944 + CX_TEST_ASSERT(!ret); 1.945 + CX_TEST_ASSERT(ctx.pos == 27); 1.946 + CX_TEST_ASSERT(ctx.next_pos == 33); 1.947 + CX_TEST_ASSERT(ctx.delim_pos == 33); 1.948 + CX_TEST_ASSERT(ctx.found == 5); 1.949 + 1.950 + CX_TEST_ASSERT(0 == cx_strcmp(cx_strcast(str), CX_STR("AN,ARBITRARILY;||SEPARATED;STRING"))); 1.951 + } 1.952 + cx_strfree(&str); 1.953 +} 1.954 + 1.955 + 1.956 +CxTestSuite *cx_test_suite_string(void) { 1.957 + CxTestSuite *suite = cx_test_suite_new("string"); 1.958 + 1.959 + cx_test_register(suite, test_string_construct); 1.960 + cx_test_register(suite, test_strfree); 1.961 + cx_test_register(suite, test_strdup); 1.962 + cx_test_register(suite, test_strdup_shortened); 1.963 + cx_test_register(suite, test_strlen); 1.964 + cx_test_register(suite, test_strsubs); 1.965 + cx_test_register(suite, test_strchr); 1.966 + cx_test_register(suite, test_strrchr); 1.967 + cx_test_register(suite, test_strstr); 1.968 + cx_test_register(suite, test_strcmp); 1.969 + cx_test_register(suite, test_strcasecmp); 1.970 + cx_test_register(suite, test_strcat); 1.971 + cx_test_register(suite, test_strsplit); 1.972 + cx_test_register(suite, test_strsplit_a); 1.973 + cx_test_register(suite, test_strtrim); 1.974 + cx_test_register(suite, test_strprefix); 1.975 + cx_test_register(suite, test_strsuffix); 1.976 + cx_test_register(suite, test_strcaseprefix); 1.977 + cx_test_register(suite, test_strcasesuffix); 1.978 + cx_test_register(suite, test_strreplace); 1.979 + cx_test_register(suite, test_strupper); 1.980 + cx_test_register(suite, test_strlower); 1.981 + cx_test_register(suite, test_strtok); 1.982 + cx_test_register(suite, test_strtok_m); 1.983 + cx_test_register(suite, test_strtok_delim); 1.984 + cx_test_register(suite, test_strtok_next_easy); 1.985 + cx_test_register(suite, test_strtok_next_unlimited); 1.986 + cx_test_register(suite, test_strtok_next_advanced); 1.987 + 1.988 + return suite; 1.989 +}