test/test_string.cpp

Tue, 04 Oct 2022 19:25:07 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 04 Oct 2022 19:25:07 +0200
changeset 591
7df0bcaecffa
parent 589
c290f8fd979e
child 597
8b48126671cf
permissions
-rw-r--r--

fix over-optimization of strstr

1. it's actually less performant to frequently read bytes
from an array instead of using the native word length
2. the SBO buffer should be local and not static to allow
multi-threading usage

universe@583 1 /*
universe@583 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@583 3 *
universe@583 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
universe@583 5 *
universe@583 6 * Redistribution and use in source and binary forms, with or without
universe@583 7 * modification, are permitted provided that the following conditions are met:
universe@583 8 *
universe@583 9 * 1. Redistributions of source code must retain the above copyright
universe@583 10 * notice, this list of conditions and the following disclaimer.
universe@583 11 *
universe@583 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@583 13 * notice, this list of conditions and the following disclaimer in the
universe@583 14 * documentation and/or other materials provided with the distribution.
universe@583 15 *
universe@583 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@583 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@583 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@583 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@583 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@583 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@583 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@583 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@583 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@583 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@583 26 * POSSIBILITY OF SUCH DAMAGE.
universe@583 27 */
universe@583 28
universe@583 29 #include "cx/string.h"
universe@583 30 #include "util_allocator.h"
universe@583 31
universe@583 32 #include <gtest/gtest.h>
universe@583 33
universe@589 34 #define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0')
universe@589 35
universe@583 36 TEST(String, construct) {
universe@583 37 cxstring s1 = cx_str("1234");
universe@583 38 cxstring s2 = cx_strn("abcd", 2);
universe@583 39 cxmutstr s3 = cx_mutstr((char *) "1234");
universe@583 40 cxmutstr s4 = cx_mutstrn((char *) "abcd", 2);
universe@583 41
universe@583 42 EXPECT_EQ(s1.length, 4);
universe@583 43 EXPECT_EQ(s2.length, 2);
universe@583 44 EXPECT_EQ(s3.length, 4);
universe@583 45 EXPECT_EQ(s4.length, 2);
universe@583 46 }
universe@583 47
universe@583 48 TEST(String, strfree) {
universe@583 49 CxTestingAllocator alloc;
universe@583 50 auto test = (char *) cxMalloc(&alloc, 16);
universe@583 51 cxmutstr str = cx_mutstrn(test, 16);
universe@583 52 ASSERT_EQ(str.ptr, test);
universe@583 53 EXPECT_EQ(str.length, 16);
universe@583 54 cx_strfree_a(&alloc, &str);
universe@583 55 EXPECT_EQ(str.ptr, nullptr);
universe@583 56 EXPECT_EQ(str.length, 0);
universe@583 57 EXPECT_TRUE(alloc.verify());
universe@583 58 }
universe@583 59
universe@589 60 TEST(String, strdup) {
universe@589 61 cxstring str = CX_STR("test");
universe@589 62 cxmutstr dup = cx_strdup(str);
universe@589 63 ASSERT_EQ(dup.length, str.length);
universe@589 64 EXPECT_STREQ(dup.ptr, str.ptr);
universe@589 65 EXPECT_ZERO_TERMINATED(dup);
universe@589 66 cx_strfree(&dup);
universe@589 67
universe@589 68 str.length = 2;
universe@589 69 dup = cx_strdup(str);
universe@589 70 ASSERT_EQ(dup.length, str.length);
universe@589 71 EXPECT_STREQ(dup.ptr, "te");
universe@589 72 EXPECT_ZERO_TERMINATED(dup);
universe@589 73 cx_strfree(&dup);
universe@589 74 }
universe@589 75
universe@583 76 TEST(String, strlen) {
universe@583 77 cxstring s1 = CX_STR("1234");
universe@583 78 cxstring s2 = CX_STR(".:.:.");
universe@583 79 cxstring s3 = CX_STR("X");
universe@583 80
universe@583 81 size_t len0 = cx_strlen(0);
universe@583 82 size_t len1 = cx_strlen(1, s1);
universe@583 83 size_t len2 = cx_strlen(2, s1, s2);
universe@583 84 size_t len3 = cx_strlen(3, s1, s2, s3);
universe@583 85
universe@583 86 EXPECT_EQ(len0, 0);
universe@583 87 EXPECT_EQ(len1, 4);
universe@583 88 EXPECT_EQ(len2, 9);
universe@583 89 EXPECT_EQ(len3, 10);
universe@583 90 }
universe@583 91
universe@585 92 TEST(String, strsubs) {
universe@585 93 cxstring str = CX_STR("A test string");
universe@585 94
universe@585 95 cxstring sub = cx_strsubs(str, 0);
universe@585 96 EXPECT_EQ(cx_strcmp(sub, str), 0);
universe@585 97
universe@585 98 sub = cx_strsubs(str, 2);
universe@585 99 EXPECT_EQ(cx_strcmp(sub, cx_str("test string")), 0);
universe@585 100
universe@585 101 sub = cx_strsubs(str, 7);
universe@585 102 EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0);
universe@585 103
universe@585 104 sub = cx_strsubs(str, 15);
universe@585 105 EXPECT_EQ(cx_strcmp(sub, cx_str("")), 0);
universe@585 106
universe@585 107 sub = cx_strsubsl(str, 2, 4);
universe@585 108 EXPECT_EQ(cx_strcmp(sub, cx_str("test")), 0);
universe@585 109
universe@585 110 sub = cx_strsubsl(str, 7, 3);
universe@585 111 EXPECT_EQ(cx_strcmp(sub, cx_str("str")), 0);
universe@585 112
universe@585 113 sub = cx_strsubsl(str, 7, 20);
universe@585 114 EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0);
universe@585 115
universe@585 116 // just for coverage, call the _m variant
universe@585 117 auto m = cx_strsubs_m(cx_mutstrn(nullptr, 0), 0);
universe@585 118 EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
universe@585 119 }
universe@583 120
universe@583 121 TEST(String, strchr) {
universe@583 122 cxstring str = CX_STR("I will find you - and I will kill you");
universe@583 123
universe@583 124 cxstring notfound = cx_strchr(str, 'x');
universe@583 125 EXPECT_EQ(notfound.length, 0);
universe@583 126
universe@583 127 cxstring result = cx_strchr(str, 'w');
universe@583 128 EXPECT_EQ(result.length, 35);
universe@587 129 EXPECT_STREQ(result.ptr, "will find you - and I will kill you");
universe@585 130
universe@585 131 // just for coverage, call the _m variant
universe@585 132 auto m = cx_strchr_m(cx_mutstrn(nullptr, 0), 'a');
universe@585 133 EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
universe@583 134 }
universe@583 135
universe@583 136 TEST(String, strrchr) {
universe@583 137 cxstring str = CX_STR("I will find you - and I will kill you");
universe@583 138
universe@583 139 cxstring notfound = cx_strrchr(str, 'x');
universe@583 140 EXPECT_EQ(notfound.length, 0);
universe@583 141
universe@583 142 cxstring result = cx_strrchr(str, 'w');
universe@583 143 EXPECT_EQ(result.length, 13);
universe@587 144 EXPECT_STREQ(result.ptr, "will kill you");
universe@585 145
universe@585 146 // just for coverage, call the _m variant
universe@585 147 auto m = cx_strrchr_m(cx_mutstrn(nullptr, 0), 'a');
universe@585 148 EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
universe@583 149 }
universe@583 150
universe@583 151 TEST(String, strstr) {
universe@583 152 cxstring str = CX_STR("find the match in this string");
universe@583 153 cxstring longstr = CX_STR(
universe@583 154 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl"
universe@583 155 "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx"
universe@583 156 "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij"
universe@583 157 "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv"
universe@583 158 "abababababababababababababababababababababababababababababababab"
universe@583 159 "abababababababababababababababababababababababababababababababab"
universe@583 160 "abababababababababababababababababababababababababababababababab"
universe@583 161 "abababababababababababababababababababababababababababababababab"
universe@583 162 "abababababababababababababababababababababababababababababababab"
universe@583 163 "abababababababababababababababababababababababababababababababab"
universe@583 164 "wxyz1234567890");
universe@583 165 cxstring longstrpattern = CX_STR(
universe@583 166 "abababababababababababababababababababababababababababababababab"
universe@583 167 "abababababababababababababababababababababababababababababababab"
universe@583 168 "abababababababababababababababababababababababababababababababab"
universe@583 169 "abababababababababababababababababababababababababababababababab"
universe@583 170 "abababababababababababababababababababababababababababababababab"
universe@583 171 );
universe@583 172 cxstring longstrresult = CX_STR(
universe@583 173 "abababababababababababababababababababababababababababababababab"
universe@583 174 "abababababababababababababababababababababababababababababababab"
universe@583 175 "abababababababababababababababababababababababababababababababab"
universe@583 176 "abababababababababababababababababababababababababababababababab"
universe@583 177 "abababababababababababababababababababababababababababababababab"
universe@583 178 "abababababababababababababababababababababababababababababababab"
universe@583 179 "wxyz1234567890"
universe@583 180 );
universe@583 181
universe@583 182 cxstring notfound = cx_strstr(str, cx_str("no match"));
universe@583 183 EXPECT_EQ(notfound.length, 0);
universe@583 184
universe@583 185 cxstring result = cx_strstr(str, cx_str("match"));
universe@583 186 EXPECT_EQ(result.length, 20);
universe@587 187 EXPECT_STREQ(result.ptr, "match in this string");
universe@583 188
universe@583 189 result = cx_strstr(str, cx_str(""));
universe@583 190 EXPECT_EQ(result.length, str.length);
universe@587 191 EXPECT_STREQ(result.ptr, str.ptr);
universe@583 192
universe@583 193 result = cx_strstr(longstr, longstrpattern);
universe@583 194 EXPECT_EQ(result.length, longstrresult.length);
universe@587 195 EXPECT_STREQ(result.ptr, longstrresult.ptr);
universe@585 196
universe@585 197 // just for coverage, call the _m variant
universe@585 198 auto mstr = cx_strdup(longstr);
universe@585 199 auto m = cx_strstr_m(mstr, longstrpattern);
universe@585 200 EXPECT_EQ(m.length, longstrresult.length);
universe@587 201 EXPECT_STREQ(m.ptr, longstrresult.ptr);
universe@585 202 cx_strfree(&mstr);
universe@583 203 }
universe@583 204
universe@583 205 TEST(String, strcmp) {
universe@583 206 cxstring str = CX_STR("compare this");
universe@583 207
universe@588 208 EXPECT_EQ(cx_strcmp(cx_str(""), cx_str("")), 0);
universe@588 209 EXPECT_GT(cx_strcmp(str, cx_str("")), 0);
universe@588 210 EXPECT_EQ(cx_strcmp(str, cx_str("compare this")), 0);
universe@588 211 EXPECT_NE(cx_strcmp(str, cx_str("Compare This")), 0);
universe@588 212 EXPECT_LT(cx_strcmp(str, cx_str("compare tool")), 0);
universe@588 213 EXPECT_GT(cx_strcmp(str, cx_str("compare shit")), 0);
universe@588 214 EXPECT_LT(cx_strcmp(str, cx_str("compare this not")), 0);
universe@588 215 EXPECT_GT(cx_strcmp(str, cx_str("compare")), 0);
universe@583 216 }
universe@583 217
universe@583 218 TEST(String, strcasecmp) {
universe@583 219 cxstring str = CX_STR("compare this");
universe@583 220
universe@588 221 EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0);
universe@588 222 EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0);
universe@588 223 EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0);
universe@588 224 EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0);
universe@588 225 EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0);
universe@588 226 EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0);
universe@588 227 EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0);
universe@588 228 EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0);
universe@583 229 }
universe@583 230
universe@583 231 TEST(String, strcat) {
universe@583 232 cxstring s1 = CX_STR("12");
universe@583 233 cxstring s2 = CX_STR("34");
universe@583 234 cxstring s3 = CX_STR("56");
universe@583 235 cxstring sn = {nullptr, 0};
universe@583 236
universe@583 237 CxTestingAllocator alloc;
universe@583 238
universe@583 239 cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2);
universe@588 240 EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0);
universe@589 241 EXPECT_ZERO_TERMINATED(t1);
universe@583 242 cx_strfree_a(&alloc, &t1);
universe@583 243
universe@583 244 cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3);
universe@588 245 EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0);
universe@589 246 EXPECT_ZERO_TERMINATED(t2);
universe@583 247 cx_strfree_a(&alloc, &t2);
universe@583 248
universe@583 249 cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn);
universe@588 250 EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0);
universe@589 251 EXPECT_ZERO_TERMINATED(t3);
universe@583 252 cx_strfree_a(&alloc, &t3);
universe@583 253
universe@583 254 cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn);
universe@588 255 EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0);
universe@589 256 EXPECT_ZERO_TERMINATED(t4);
universe@583 257 cx_strfree_a(&alloc, &t4);
universe@583 258
universe@583 259 EXPECT_TRUE(alloc.verify());
universe@583 260 }
universe@583 261
universe@583 262 TEST(String, strsplit) {
universe@583 263
universe@583 264 cxstring test = cx_str("this,is,a,csv,string");
universe@583 265 size_t capa = 8;
universe@583 266 cxstring list[8];
universe@583 267 size_t n;
universe@583 268
universe@583 269 /* special case: empty string */
universe@583 270 n = cx_strsplit(test, cx_str(""), capa, list);
universe@583 271 ASSERT_EQ(n, 1);
universe@583 272 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 273
universe@583 274 /* no delimiter occurrence */
universe@583 275 n = cx_strsplit(test, cx_str("z"), capa, list);
universe@583 276 ASSERT_EQ(n, 1);
universe@583 277 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 278
universe@583 279 /* partially matching delimiter */
universe@583 280 n = cx_strsplit(test, cx_str("is,not"), capa, list);
universe@583 281 ASSERT_EQ(n, 1);
universe@583 282 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 283
universe@583 284 /* matching single-char delimiter */
universe@583 285 n = cx_strsplit(test, cx_str(","), capa, list);
universe@583 286 ASSERT_EQ(n, 5);
universe@583 287 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
universe@583 288 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
universe@583 289 EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
universe@583 290 EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
universe@583 291 EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
universe@583 292
universe@583 293 /* matching multi-char delimiter */
universe@583 294 n = cx_strsplit(test, cx_str("is"), capa, list);
universe@583 295 ASSERT_EQ(n, 3);
universe@583 296 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
universe@583 297 EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
universe@583 298 EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
universe@583 299
universe@583 300 /* bounded list using single-char delimiter */
universe@583 301 n = cx_strsplit(test, cx_str(","), 3, list);
universe@583 302 ASSERT_EQ(n, 3);
universe@583 303 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
universe@583 304 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
universe@583 305 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
universe@583 306
universe@583 307 /* bounded list using multi-char delimiter */
universe@583 308 n = cx_strsplit(test, cx_str("is"), 2, list);
universe@583 309 ASSERT_EQ(n, 2);
universe@583 310 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
universe@583 311 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
universe@583 312
universe@583 313 /* start with delimiter */
universe@583 314 n = cx_strsplit(test, cx_str("this"), capa, list);
universe@583 315 ASSERT_EQ(n, 2);
universe@583 316 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
universe@583 317 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
universe@583 318
universe@583 319 /* end with delimiter */
universe@583 320 n = cx_strsplit(test, cx_str("string"), capa, list);
universe@583 321 ASSERT_EQ(n, 2);
universe@583 322 EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
universe@583 323 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
universe@583 324
universe@583 325
universe@583 326 /* end with delimiter exceed bound */
universe@583 327 n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list);
universe@583 328 ASSERT_EQ(n, 3);
universe@583 329 EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
universe@583 330 EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
universe@583 331 EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
universe@583 332
universe@583 333 /* exact match */
universe@583 334 n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list);
universe@583 335 ASSERT_EQ(n, 2);
universe@583 336 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
universe@583 337 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
universe@583 338
universe@583 339 /* string to be split is only substring */
universe@583 340 n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list);
universe@583 341 ASSERT_EQ(n, 1);
universe@583 342 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 343
universe@583 344 /* subsequent encounter of delimiter (the string between is empty) */
universe@583 345 n = cx_strsplit(test, cx_str("is,"), capa, list);
universe@583 346 ASSERT_EQ(n, 3);
universe@583 347 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
universe@583 348 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
universe@583 349 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
universe@585 350
universe@585 351 /* call the _m variant just for coverage */
universe@585 352 auto mtest = cx_strdup(test);
universe@585 353 cxmutstr mlist[4];
universe@585 354 n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist);
universe@585 355 ASSERT_EQ(n, 3);
universe@585 356 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
universe@585 357 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
universe@585 358 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
universe@585 359 cx_strfree(&mtest);
universe@583 360 }
universe@583 361
universe@583 362 TEST(String, strsplit_a) {
universe@583 363 CxTestingAllocator alloc;
universe@583 364
universe@583 365 cxstring test = cx_str("this,is,a,csv,string");
universe@583 366 size_t capa = 8;
universe@583 367 cxstring *list;
universe@583 368 size_t n;
universe@583 369
universe@583 370 /* special case: empty string */
universe@583 371 n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list);
universe@583 372 ASSERT_EQ(n, 1);
universe@583 373 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 374 cxFree(&alloc, list);
universe@583 375
universe@583 376 /* no delimiter occurrence */
universe@583 377 n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list);
universe@583 378 ASSERT_EQ(n, 1);
universe@583 379 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 380 cxFree(&alloc, list);
universe@583 381
universe@583 382 /* partially matching delimiter */
universe@583 383 n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list);
universe@583 384 ASSERT_EQ(n, 1);
universe@583 385 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 386 cxFree(&alloc, list);
universe@583 387
universe@583 388 /* matching single-char delimiter */
universe@583 389 n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list);
universe@583 390 ASSERT_EQ(n, 5);
universe@583 391 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
universe@583 392 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
universe@583 393 EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
universe@583 394 EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
universe@583 395 EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
universe@583 396 cxFree(&alloc, list);
universe@583 397
universe@583 398 /* matching multi-char delimiter */
universe@583 399 n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list);
universe@583 400 ASSERT_EQ(n, 3);
universe@583 401 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
universe@583 402 EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
universe@583 403 EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
universe@583 404 cxFree(&alloc, list);
universe@583 405
universe@583 406 /* bounded list using single-char delimiter */
universe@583 407 n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list);
universe@583 408 ASSERT_EQ(n, 3);
universe@583 409 EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
universe@583 410 EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
universe@583 411 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
universe@583 412 cxFree(&alloc, list);
universe@583 413
universe@583 414 /* bounded list using multi-char delimiter */
universe@583 415 n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list);
universe@583 416 ASSERT_EQ(n, 2);
universe@583 417 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
universe@583 418 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
universe@583 419 cxFree(&alloc, list);
universe@583 420
universe@583 421 /* start with delimiter */
universe@583 422 n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list);
universe@583 423 ASSERT_EQ(n, 2);
universe@583 424 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
universe@583 425 EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
universe@583 426 cxFree(&alloc, list);
universe@583 427
universe@583 428 /* end with delimiter */
universe@583 429 n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list);
universe@583 430 ASSERT_EQ(n, 2);
universe@583 431 EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
universe@583 432 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
universe@583 433 cxFree(&alloc, list);
universe@583 434
universe@583 435 /* end with delimiter exceed bound */
universe@583 436 n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list);
universe@583 437 ASSERT_EQ(n, 3);
universe@583 438 EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
universe@583 439 EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
universe@583 440 EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
universe@583 441 cxFree(&alloc, list);
universe@583 442
universe@583 443 /* exact match */
universe@583 444 n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list);
universe@583 445 ASSERT_EQ(n, 2);
universe@583 446 EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
universe@583 447 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
universe@583 448 cxFree(&alloc, list);
universe@583 449
universe@583 450 /* string to be split is only substring */
universe@583 451 n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list);
universe@583 452 ASSERT_EQ(n, 1);
universe@583 453 EXPECT_EQ(cx_strcmp(list[0], test), 0);
universe@583 454 cxFree(&alloc, list);
universe@583 455
universe@583 456 /* subsequent encounter of delimiter (the string between is empty) */
universe@583 457 n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list);
universe@583 458 ASSERT_EQ(n, 3);
universe@583 459 EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
universe@583 460 EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
universe@583 461 EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
universe@583 462 cxFree(&alloc, list);
universe@583 463
universe@585 464 /* call the _m variant just for coverage */
universe@585 465 auto mtest = cx_strdup(test);
universe@585 466 cxmutstr *mlist;
universe@585 467 n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist);
universe@585 468 ASSERT_EQ(n, 3);
universe@585 469 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
universe@585 470 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
universe@585 471 EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
universe@585 472 cxFree(&alloc, mlist);
universe@585 473 cx_strfree(&mtest);
universe@585 474
universe@583 475 EXPECT_TRUE(alloc.verify());
universe@583 476 }
universe@583 477
universe@583 478 TEST(String, strtrim) {
universe@583 479 cxstring t1 = cx_strtrim(cx_str(" ein test \t "));
universe@583 480 cxstring t2 = cx_strtrim(cx_str("abc"));
universe@583 481 cxstring t3 = cx_strtrim(cx_str(" 123"));
universe@583 482 cxstring t4 = cx_strtrim(cx_str("xyz "));
universe@583 483 cxstring t5 = cx_strtrim(cx_str(" "));
universe@583 484 cxstring empty = cx_strtrim(cx_str(""));
universe@583 485
universe@583 486 EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0);
universe@583 487 EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0);
universe@583 488 EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0);
universe@583 489 EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0);
universe@583 490 EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0);
universe@583 491 EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0);
universe@585 492
universe@585 493 /* call the _m variant just for coverage */
universe@585 494 cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) " ein test \t "));
universe@585 495 EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0);
universe@583 496 }
universe@583 497
universe@583 498 TEST(String, strprefix) {
universe@583 499 cxstring str = CX_STR("test my prefix and my suffix");
universe@583 500 cxstring empty = CX_STR("");
universe@583 501 EXPECT_FALSE(cx_strprefix(empty, cx_str("pref")));
universe@583 502 EXPECT_TRUE(cx_strprefix(str, empty));
universe@583 503 EXPECT_TRUE(cx_strprefix(empty, empty));
universe@583 504 EXPECT_TRUE(cx_strprefix(str, cx_str("test ")));
universe@583 505 EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck ")));
universe@583 506 }
universe@583 507
universe@583 508 TEST(String, strsuffix) {
universe@583 509 cxstring str = CX_STR("test my prefix and my suffix");
universe@583 510 cxstring empty = CX_STR("");
universe@583 511 EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf")));
universe@583 512 EXPECT_TRUE(cx_strsuffix(str, empty));
universe@583 513 EXPECT_TRUE(cx_strsuffix(empty, empty));
universe@583 514 EXPECT_TRUE(cx_strsuffix(str, cx_str("fix")));
universe@583 515 EXPECT_FALSE(cx_strsuffix(str, cx_str("fox")));
universe@583 516 }
universe@583 517
universe@583 518 TEST(String, strcaseprefix) {
universe@583 519 cxstring str = CX_STR("test my prefix and my suffix");
universe@583 520 cxstring empty = CX_STR("");
universe@583 521 EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf")));
universe@583 522 EXPECT_TRUE(cx_strcaseprefix(str, empty));
universe@583 523 EXPECT_TRUE(cx_strcaseprefix(empty, empty));
universe@583 524 EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST ")));
universe@583 525 EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck ")));
universe@583 526 }
universe@583 527
universe@583 528 TEST(String, strcasesuffix) {
universe@583 529 cxstring str = CX_STR("test my prefix and my suffix");
universe@583 530 cxstring empty = CX_STR("");
universe@583 531 EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf")));
universe@583 532 EXPECT_TRUE(cx_strcasesuffix(str, empty));
universe@583 533 EXPECT_TRUE(cx_strcasesuffix(empty, empty));
universe@583 534 EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX")));
universe@583 535 EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox")));
universe@583 536 }
universe@583 537
universe@583 538 TEST(String, strreplace) {
universe@583 539 cxstring str = CX_STR("test ababab string aba");
universe@583 540 cxstring longstr = CX_STR(
universe@583 541 "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd");
universe@583 542 cxstring notrail = CX_STR("test abab");
universe@583 543 cxstring empty = CX_STR("");
universe@583 544 cxstring astr = CX_STR("aaaaaaaaaa");
universe@583 545 cxstring csstr = CX_STR("test AB ab TEST xyz");
universe@583 546
universe@583 547 cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger"));
universe@589 548 auto expected = "test muchlongerab string aba";
universe@583 549
universe@583 550 cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2);
universe@589 551 auto expectedn = "test ccab string aba";
universe@583 552
universe@583 553 cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z"));
universe@589 554 auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd";
universe@583 555
universe@583 556 cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z"));
universe@589 557 auto notrailexpect = "test zz";
universe@583 558
universe@583 559 cxmutstr repleq = cx_strreplace(str, str, cx_str("hello"));
universe@589 560 auto eqexpect = "hello";
universe@583 561
universe@583 562 cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty
universe@583 563 cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty);
universe@589 564 auto emptyexpect2 = "test ab string aba";
universe@583 565
universe@583 566 cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST "));
universe@589 567 auto preexpected = "TEST ababab string aba";
universe@583 568
universe@583 569 cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1);
universe@589 570 auto an1expected = "xaaaaaaaaa";
universe@583 571
universe@583 572 cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4);
universe@589 573 auto an4expected = "xxxxaaaaaa";
universe@583 574
universe@583 575 cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9);
universe@589 576 auto an9expected = "xxxxxxxxxa";
universe@583 577
universe@583 578 cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10);
universe@589 579 auto an10expected = "xxxxxxxxxx";
universe@583 580
universe@583 581 cxmutstr replcs1 = cx_strreplace(csstr, cx_str("AB"), cx_str("*"));
universe@589 582 auto cs1expected = "test * ab TEST xyz";
universe@583 583
universe@583 584 cxmutstr replcs2 = cx_strreplace(csstr, cx_str("test"), cx_str("TEST"));
universe@589 585 auto cs2expected = "TEST AB ab TEST xyz";
universe@583 586
universe@583 587
universe@583 588 EXPECT_NE(repl.ptr, str.ptr);
universe@589 589 EXPECT_ZERO_TERMINATED(repl);
universe@589 590 EXPECT_STREQ(repl.ptr, expected);
universe@589 591 EXPECT_ZERO_TERMINATED(repln);
universe@589 592 EXPECT_STREQ(repln.ptr, expectedn);
universe@589 593 EXPECT_ZERO_TERMINATED(longrepl);
universe@589 594 EXPECT_STREQ(longrepl.ptr, longexpect);
universe@589 595 EXPECT_ZERO_TERMINATED(replnotrail);
universe@589 596 EXPECT_STREQ(replnotrail.ptr, notrailexpect);
universe@589 597 EXPECT_ZERO_TERMINATED(repleq);
universe@589 598 EXPECT_STREQ(repleq.ptr, eqexpect);
universe@589 599 EXPECT_ZERO_TERMINATED(replempty1);
universe@589 600 EXPECT_STREQ(replempty1.ptr, "");
universe@589 601 EXPECT_ZERO_TERMINATED(replempty2);
universe@589 602 EXPECT_STREQ(replempty2.ptr, emptyexpect2);
universe@589 603 EXPECT_ZERO_TERMINATED(replpre);
universe@589 604 EXPECT_STREQ(replpre.ptr, preexpected);
universe@589 605 EXPECT_ZERO_TERMINATED(replan1);
universe@589 606 EXPECT_STREQ(replan1.ptr, an1expected);
universe@589 607 EXPECT_ZERO_TERMINATED(replan4);
universe@589 608 EXPECT_STREQ(replan4.ptr, an4expected);
universe@589 609 EXPECT_ZERO_TERMINATED(replan9);
universe@589 610 EXPECT_STREQ(replan9.ptr, an9expected);
universe@589 611 EXPECT_ZERO_TERMINATED(replan10);
universe@589 612 EXPECT_STREQ(replan10.ptr, an10expected);
universe@589 613 EXPECT_ZERO_TERMINATED(replcs1);
universe@589 614 EXPECT_STREQ(replcs1.ptr, cs1expected);
universe@589 615 EXPECT_ZERO_TERMINATED(replcs2);
universe@589 616 EXPECT_STREQ(replcs2.ptr, cs2expected);
universe@583 617
universe@583 618 cx_strfree(&repl);
universe@583 619 cx_strfree(&repln);
universe@583 620 cx_strfree(&longrepl);
universe@583 621 cx_strfree(&replnotrail);
universe@583 622 cx_strfree(&repleq);
universe@583 623 cx_strfree(&replempty1);
universe@583 624 cx_strfree(&replempty2);
universe@583 625 cx_strfree(&replpre);
universe@583 626 cx_strfree(&replan1);
universe@583 627 cx_strfree(&replan4);
universe@583 628 cx_strfree(&replan9);
universe@583 629 cx_strfree(&replan10);
universe@583 630 cx_strfree(&replcs1);
universe@583 631 cx_strfree(&replcs2);
universe@583 632 }
universe@586 633
universe@586 634 TEST(String, strupper) {
universe@586 635 cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
universe@586 636 cx_strupper(str);
universe@586 637 EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T");
universe@586 638 cx_strfree(&str);
universe@586 639 }
universe@586 640
universe@586 641 TEST(String, strlower) {
universe@586 642 cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
universe@586 643 cx_strlower(str);
universe@586 644 EXPECT_STREQ(str.ptr, "this 1s @ te$t");
universe@586 645 cx_strfree(&str);
universe@586 646 }

mercurial