tests/test_string.cpp

Sun, 21 May 2023 16:22:09 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 21 May 2023 16:22:09 +0200
changeset 710
2dd409ed056f
parent 697
ebdce4bf262b
permissions
-rw-r--r--

fix const-ness of non-mutating iterator creation for maps

     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  */
    29 #include "cx/string.h"
    30 #include "util_allocator.h"
    32 #include <gtest/gtest.h>
    34 #define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0')
    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);
    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 }
    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 }
    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);
    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 }
    76 TEST(String, strlen) {
    77     cxstring s1 = CX_STR("1234");
    78     cxstring s2 = CX_STR(".:.:.");
    79     cxstring s3 = CX_STR("X");
    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);
    86     EXPECT_EQ(len0, 0);
    87     EXPECT_EQ(len1, 4);
    88     EXPECT_EQ(len2, 9);
    89     EXPECT_EQ(len3, 10);
    90 }
    92 TEST(String, strsubs) {
    93     cxstring str = CX_STR("A test string");
    95     cxstring sub = cx_strsubs(str, 0);
    96     EXPECT_EQ(cx_strcmp(sub, str), 0);
    98     sub = cx_strsubs(str, 2);
    99     EXPECT_EQ(cx_strcmp(sub, CX_STR("test string")), 0);
   101     sub = cx_strsubs(str, 7);
   102     EXPECT_EQ(cx_strcmp(sub, CX_STR("string")), 0);
   104     sub = cx_strsubs(str, 15);
   105     EXPECT_EQ(cx_strcmp(sub, CX_STR("")), 0);
   107     sub = cx_strsubsl(str, 2, 4);
   108     EXPECT_EQ(cx_strcmp(sub, CX_STR("test")), 0);
   110     sub = cx_strsubsl(str, 7, 3);
   111     EXPECT_EQ(cx_strcmp(sub, CX_STR("str")), 0);
   113     sub = cx_strsubsl(str, 7, 20);
   114     EXPECT_EQ(cx_strcmp(sub, CX_STR("string")), 0);
   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 }
   121 TEST(String, strchr) {
   122     cxstring str = CX_STR("I will find you - and I will kill you");
   124     cxstring notfound = cx_strchr(str, 'x');
   125     EXPECT_EQ(notfound.length, 0);
   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");
   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 }
   136 TEST(String, strrchr) {
   137     cxstring str = CX_STR("I will find you - and I will kill you");
   139     cxstring notfound = cx_strrchr(str, 'x');
   140     EXPECT_EQ(notfound.length, 0);
   142     cxstring result = cx_strrchr(str, 'w');
   143     EXPECT_EQ(result.length, 13);
   144     EXPECT_STREQ(result.ptr, "will kill you");
   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 }
   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     );
   182     cxstring notfound = cx_strstr(str, CX_STR("no match"));
   183     EXPECT_EQ(notfound.length, 0);
   185     cxstring result = cx_strstr(str, CX_STR("match"));
   186     EXPECT_EQ(result.length, 20);
   187     EXPECT_STREQ(result.ptr, "match in this string");
   189     result = cx_strstr(str, CX_STR(""));
   190     EXPECT_EQ(result.length, str.length);
   191     EXPECT_STREQ(result.ptr, str.ptr);
   193     result = cx_strstr(longstr, longstrpattern);
   194     EXPECT_EQ(result.length, longstrresult.length);
   195     EXPECT_STREQ(result.ptr, longstrresult.ptr);
   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 }
   205 TEST(String, strcmp) {
   206     cxstring str = CX_STR("compare this");
   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);
   217     cxstring str2 = CX_STR("Compare This");
   218     EXPECT_NE(cx_strcmp_p(&str, &str2), 0);
   219     str2 = CX_STR("compare this");
   220     EXPECT_EQ(cx_strcmp_p(&str, &str2), 0);
   221 }
   223 TEST(String, strcasecmp) {
   224     cxstring str = CX_STR("compare this");
   226     EXPECT_EQ(cx_strcasecmp(CX_STR(""), CX_STR("")), 0);
   227     EXPECT_GT(cx_strcasecmp(str, CX_STR("")), 0);
   228     EXPECT_EQ(cx_strcasecmp(str, CX_STR("compare this")), 0);
   229     EXPECT_EQ(cx_strcasecmp(str, CX_STR("Compare This")), 0);
   230     EXPECT_LT(cx_strcasecmp(str, CX_STR("compare tool")), 0);
   231     EXPECT_GT(cx_strcasecmp(str, CX_STR("compare shit")), 0);
   232     EXPECT_LT(cx_strcasecmp(str, CX_STR("compare this not")), 0);
   233     EXPECT_GT(cx_strcasecmp(str, CX_STR("compare")), 0);
   235     cxstring str2 = CX_STR("Compare This");
   236     EXPECT_EQ(cx_strcasecmp_p(&str, &str2), 0);
   237     str2 = CX_STR("Compare Tool");
   238     EXPECT_LT(cx_strcasecmp_p(&str, &str2), 0);
   239 }
   241 TEST(String, strcat) {
   242     cxstring s1 = CX_STR("12");
   243     cxstring s2 = CX_STR("34");
   244     cxstring s3 = CX_STR("56");
   245     cxstring sn = {nullptr, 0};
   247     CxTestingAllocator alloc;
   249     cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2);
   250     EXPECT_EQ(cx_strcmp(cx_strcast(t1), CX_STR("1234")), 0);
   251     EXPECT_ZERO_TERMINATED(t1);
   252     cx_strfree_a(&alloc, &t1);
   254     cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3);
   255     EXPECT_EQ(cx_strcmp(cx_strcast(t2), CX_STR("123456")), 0);
   256     EXPECT_ZERO_TERMINATED(t2);
   257     cx_strfree_a(&alloc, &t2);
   259     cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn);
   260     EXPECT_EQ(cx_strcmp(cx_strcast(t3), CX_STR("123456")), 0);
   261     EXPECT_ZERO_TERMINATED(t3);
   262     cx_strfree_a(&alloc, &t3);
   264     cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn);
   265     EXPECT_EQ(cx_strcmp(cx_strcast(t4), CX_STR("")), 0);
   266     EXPECT_ZERO_TERMINATED(t4);
   267     cx_strfree_a(&alloc, &t4);
   269     EXPECT_TRUE(alloc.verify());
   271     // use the macro
   272     cxmutstr t5 = cx_strcat(3, s3, s1, s2);
   273     EXPECT_EQ(cx_strcmp(cx_strcast(t5), CX_STR("561234")), 0);
   274     EXPECT_ZERO_TERMINATED(t5);
   275     cx_strfree(&t5);
   277     // use an initial string
   278     cxmutstr t6 = cx_strdup(CX_STR("Hello"));
   279     t6 = cx_strcat_m(t6, 2, CX_STR(", "), CX_STR("World!"));
   280     EXPECT_EQ(cx_strcmp(cx_strcast(t6), CX_STR("Hello, World!")), 0);
   281     EXPECT_ZERO_TERMINATED(t6);
   282     cx_strfree(&t6);
   283 }
   285 TEST(String, strsplit) {
   287     cxstring test = CX_STR("this,is,a,csv,string");
   288     size_t capa = 8;
   289     cxstring list[8];
   290     size_t n;
   292     // special case: empty string
   293     n = cx_strsplit(test, CX_STR(""), capa, list);
   294     ASSERT_EQ(n, 1);
   295     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   297     // no delimiter occurrence
   298     n = cx_strsplit(test, CX_STR("z"), capa, list);
   299     ASSERT_EQ(n, 1);
   300     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   302     // partially matching delimiter
   303     n = cx_strsplit(test, CX_STR("is,not"), capa, list);
   304     ASSERT_EQ(n, 1);
   305     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   307     // matching single-char delimiter
   308     n = cx_strsplit(test, CX_STR(","), capa, list);
   309     ASSERT_EQ(n, 5);
   310     EXPECT_EQ(cx_strcmp(list[0], CX_STR("this")), 0);
   311     EXPECT_EQ(cx_strcmp(list[1], CX_STR("is")), 0);
   312     EXPECT_EQ(cx_strcmp(list[2], CX_STR("a")), 0);
   313     EXPECT_EQ(cx_strcmp(list[3], CX_STR("csv")), 0);
   314     EXPECT_EQ(cx_strcmp(list[4], CX_STR("string")), 0);
   316     // matching multi-char delimiter
   317     n = cx_strsplit(test, CX_STR("is"), capa, list);
   318     ASSERT_EQ(n, 3);
   319     EXPECT_EQ(cx_strcmp(list[0], CX_STR("th")), 0);
   320     EXPECT_EQ(cx_strcmp(list[1], CX_STR(",")), 0);
   321     EXPECT_EQ(cx_strcmp(list[2], CX_STR(",a,csv,string")), 0);
   323     // bounded list using single-char delimiter
   324     n = cx_strsplit(test, CX_STR(","), 3, list);
   325     ASSERT_EQ(n, 3);
   326     EXPECT_EQ(cx_strcmp(list[0], CX_STR("this")), 0);
   327     EXPECT_EQ(cx_strcmp(list[1], CX_STR("is")), 0);
   328     EXPECT_EQ(cx_strcmp(list[2], CX_STR("a,csv,string")), 0);
   330     // bounded list using multi-char delimiter
   331     n = cx_strsplit(test, CX_STR("is"), 2, list);
   332     ASSERT_EQ(n, 2);
   333     EXPECT_EQ(cx_strcmp(list[0], CX_STR("th")), 0);
   334     EXPECT_EQ(cx_strcmp(list[1], CX_STR(",is,a,csv,string")), 0);
   336     // start with delimiter
   337     n = cx_strsplit(test, CX_STR("this"), capa, list);
   338     ASSERT_EQ(n, 2);
   339     EXPECT_EQ(cx_strcmp(list[0], CX_STR("")), 0);
   340     EXPECT_EQ(cx_strcmp(list[1], CX_STR(",is,a,csv,string")), 0);
   342     // end with delimiter
   343     n = cx_strsplit(test, CX_STR("string"), capa, list);
   344     ASSERT_EQ(n, 2);
   345     EXPECT_EQ(cx_strcmp(list[0], CX_STR("this,is,a,csv,")), 0);
   346     EXPECT_EQ(cx_strcmp(list[1], CX_STR("")), 0);
   349     // end with delimiter exceed bound
   350     n = cx_strsplit(CX_STR("a,b,c,"), CX_STR(","), 3, list);
   351     ASSERT_EQ(n, 3);
   352     EXPECT_EQ(cx_strcmp(list[0], CX_STR("a")), 0);
   353     EXPECT_EQ(cx_strcmp(list[1], CX_STR("b")), 0);
   354     EXPECT_EQ(cx_strcmp(list[2], CX_STR("c,")), 0);
   356     // exact match
   357     n = cx_strsplit(test, CX_STR("this,is,a,csv,string"), capa, list);
   358     ASSERT_EQ(n, 2);
   359     EXPECT_EQ(cx_strcmp(list[0], CX_STR("")), 0);
   360     EXPECT_EQ(cx_strcmp(list[1], CX_STR("")), 0);
   362     // string to be split is only substring
   363     n = cx_strsplit(test, CX_STR("this,is,a,csv,string,with,extension"), capa, list);
   364     ASSERT_EQ(n, 1);
   365     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   367     // subsequent encounter of delimiter (the string between is empty)
   368     n = cx_strsplit(test, CX_STR("is,"), capa, list);
   369     ASSERT_EQ(n, 3);
   370     EXPECT_EQ(cx_strcmp(list[0], CX_STR("th")), 0);
   371     EXPECT_EQ(cx_strcmp(list[1], CX_STR("")), 0);
   372     EXPECT_EQ(cx_strcmp(list[2], CX_STR("a,csv,string")), 0);
   374     // call the _m variant just for coverage
   375     auto mtest = cx_strdup(test);
   376     cxmutstr mlist[4];
   377     n = cx_strsplit_m(mtest, CX_STR("is,"), 4, mlist);
   378     ASSERT_EQ(n, 3);
   379     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), CX_STR("th")), 0);
   380     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), CX_STR("")), 0);
   381     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), CX_STR("a,csv,string")), 0);
   382     cx_strfree(&mtest);
   383 }
   385 TEST(String, strsplit_a) {
   386     CxTestingAllocator alloc;
   388     cxstring test = CX_STR("this,is,a,csv,string");
   389     size_t capa = 8;
   390     cxstring *list;
   391     size_t n;
   393     // special case: empty string
   394     n = cx_strsplit_a(&alloc, test, CX_STR(""), capa, &list);
   395     ASSERT_EQ(n, 1);
   396     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   397     cxFree(&alloc, list);
   399     // no delimiter occurrence
   400     n = cx_strsplit_a(&alloc, test, CX_STR("z"), capa, &list);
   401     ASSERT_EQ(n, 1);
   402     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   403     cxFree(&alloc, list);
   405     // partially matching delimiter
   406     n = cx_strsplit_a(&alloc, test, CX_STR("is,not"), capa, &list);
   407     ASSERT_EQ(n, 1);
   408     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   409     cxFree(&alloc, list);
   411     // matching single-char delimiter
   412     n = cx_strsplit_a(&alloc, test, CX_STR(","), capa, &list);
   413     ASSERT_EQ(n, 5);
   414     EXPECT_EQ(cx_strcmp(list[0], CX_STR("this")), 0);
   415     EXPECT_EQ(cx_strcmp(list[1], CX_STR("is")), 0);
   416     EXPECT_EQ(cx_strcmp(list[2], CX_STR("a")), 0);
   417     EXPECT_EQ(cx_strcmp(list[3], CX_STR("csv")), 0);
   418     EXPECT_EQ(cx_strcmp(list[4], CX_STR("string")), 0);
   419     cxFree(&alloc, list);
   421     // matching multi-char delimiter
   422     n = cx_strsplit_a(&alloc, test, CX_STR("is"), capa, &list);
   423     ASSERT_EQ(n, 3);
   424     EXPECT_EQ(cx_strcmp(list[0], CX_STR("th")), 0);
   425     EXPECT_EQ(cx_strcmp(list[1], CX_STR(",")), 0);
   426     EXPECT_EQ(cx_strcmp(list[2], CX_STR(",a,csv,string")), 0);
   427     cxFree(&alloc, list);
   429     // bounded list using single-char delimiter
   430     n = cx_strsplit_a(&alloc, test, CX_STR(","), 3, &list);
   431     ASSERT_EQ(n, 3);
   432     EXPECT_EQ(cx_strcmp(list[0], CX_STR("this")), 0);
   433     EXPECT_EQ(cx_strcmp(list[1], CX_STR("is")), 0);
   434     EXPECT_EQ(cx_strcmp(list[2], CX_STR("a,csv,string")), 0);
   435     cxFree(&alloc, list);
   437     // bounded list using multi-char delimiter
   438     n = cx_strsplit_a(&alloc, test, CX_STR("is"), 2, &list);
   439     ASSERT_EQ(n, 2);
   440     EXPECT_EQ(cx_strcmp(list[0], CX_STR("th")), 0);
   441     EXPECT_EQ(cx_strcmp(list[1], CX_STR(",is,a,csv,string")), 0);
   442     cxFree(&alloc, list);
   444     // start with delimiter
   445     n = cx_strsplit_a(&alloc, test, CX_STR("this"), capa, &list);
   446     ASSERT_EQ(n, 2);
   447     EXPECT_EQ(cx_strcmp(list[0], CX_STR("")), 0);
   448     EXPECT_EQ(cx_strcmp(list[1], CX_STR(",is,a,csv,string")), 0);
   449     cxFree(&alloc, list);
   451     // end with delimiter
   452     n = cx_strsplit_a(&alloc, test, CX_STR("string"), capa, &list);
   453     ASSERT_EQ(n, 2);
   454     EXPECT_EQ(cx_strcmp(list[0], CX_STR("this,is,a,csv,")), 0);
   455     EXPECT_EQ(cx_strcmp(list[1], CX_STR("")), 0);
   456     cxFree(&alloc, list);
   458     // end with delimiter exceed bound
   459     n = cx_strsplit_a(&alloc, CX_STR("a,b,c,"), CX_STR(","), 3, &list);
   460     ASSERT_EQ(n, 3);
   461     EXPECT_EQ(cx_strcmp(list[0], CX_STR("a")), 0);
   462     EXPECT_EQ(cx_strcmp(list[1], CX_STR("b")), 0);
   463     EXPECT_EQ(cx_strcmp(list[2], CX_STR("c,")), 0);
   464     cxFree(&alloc, list);
   466     // exact match
   467     n = cx_strsplit_a(&alloc, test, CX_STR("this,is,a,csv,string"), capa, &list);
   468     ASSERT_EQ(n, 2);
   469     EXPECT_EQ(cx_strcmp(list[0], CX_STR("")), 0);
   470     EXPECT_EQ(cx_strcmp(list[1], CX_STR("")), 0);
   471     cxFree(&alloc, list);
   473     // string to be split is only substring
   474     n = cx_strsplit_a(&alloc, test, CX_STR("this,is,a,csv,string,with,extension"), capa, &list);
   475     ASSERT_EQ(n, 1);
   476     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   477     cxFree(&alloc, list);
   479     // subsequent encounter of delimiter (the string between is empty)
   480     n = cx_strsplit_a(&alloc, test, CX_STR("is,"), capa, &list);
   481     ASSERT_EQ(n, 3);
   482     EXPECT_EQ(cx_strcmp(list[0], CX_STR("th")), 0);
   483     EXPECT_EQ(cx_strcmp(list[1], CX_STR("")), 0);
   484     EXPECT_EQ(cx_strcmp(list[2], CX_STR("a,csv,string")), 0);
   485     cxFree(&alloc, list);
   487     // call the _m variant just for coverage
   488     auto mtest = cx_strdup(test);
   489     cxmutstr *mlist;
   490     n = cx_strsplit_ma(&alloc, mtest, CX_STR("is,"), 4, &mlist);
   491     ASSERT_EQ(n, 3);
   492     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), CX_STR("th")), 0);
   493     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), CX_STR("")), 0);
   494     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), CX_STR("a,csv,string")), 0);
   495     cxFree(&alloc, mlist);
   496     cx_strfree(&mtest);
   498     EXPECT_TRUE(alloc.verify());
   499 }
   501 TEST(String, strtrim) {
   502     cxstring t1 = cx_strtrim(CX_STR("  ein test  \t "));
   503     cxstring t2 = cx_strtrim(CX_STR("abc"));
   504     cxstring t3 = cx_strtrim(CX_STR(" 123"));
   505     cxstring t4 = cx_strtrim(CX_STR("xyz "));
   506     cxstring t5 = cx_strtrim(CX_STR("   "));
   507     cxstring empty = cx_strtrim(CX_STR(""));
   509     EXPECT_EQ(cx_strcmp(t1, CX_STR("ein test")), 0);
   510     EXPECT_EQ(cx_strcmp(t2, CX_STR("abc")), 0);
   511     EXPECT_EQ(cx_strcmp(t3, CX_STR("123")), 0);
   512     EXPECT_EQ(cx_strcmp(t4, CX_STR("xyz")), 0);
   513     EXPECT_EQ(cx_strcmp(t5, CX_STR("")), 0);
   514     EXPECT_EQ(cx_strcmp(empty, CX_STR("")), 0);
   516     // call the _m variant just for coverage
   517     cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) "  ein test  \t "));
   518     EXPECT_EQ(cx_strcmp(cx_strcast(m1), CX_STR("ein test")), 0);
   519 }
   521 TEST(String, strprefix) {
   522     cxstring str = CX_STR("test my prefix and my suffix");
   523     cxstring empty = CX_STR("");
   524     EXPECT_FALSE(cx_strprefix(empty, CX_STR("pref")));
   525     EXPECT_TRUE(cx_strprefix(str, empty));
   526     EXPECT_TRUE(cx_strprefix(empty, empty));
   527     EXPECT_TRUE(cx_strprefix(str, CX_STR("test ")));
   528     EXPECT_FALSE(cx_strprefix(str, CX_STR("8-) fsck ")));
   529 }
   531 TEST(String, strsuffix) {
   532     cxstring str = CX_STR("test my prefix and my suffix");
   533     cxstring empty = CX_STR("");
   534     EXPECT_FALSE(cx_strsuffix(empty, CX_STR("suf")));
   535     EXPECT_TRUE(cx_strsuffix(str, empty));
   536     EXPECT_TRUE(cx_strsuffix(empty, empty));
   537     EXPECT_TRUE(cx_strsuffix(str, CX_STR("fix")));
   538     EXPECT_FALSE(cx_strsuffix(str, CX_STR("fox")));
   539 }
   541 TEST(String, strcaseprefix) {
   542     cxstring str = CX_STR("test my prefix and my suffix");
   543     cxstring empty = CX_STR("");
   544     EXPECT_FALSE(cx_strcaseprefix(empty, CX_STR("pREf")));
   545     EXPECT_TRUE(cx_strcaseprefix(str, empty));
   546     EXPECT_TRUE(cx_strcaseprefix(empty, empty));
   547     EXPECT_TRUE(cx_strcaseprefix(str, CX_STR("TEST ")));
   548     EXPECT_FALSE(cx_strcaseprefix(str, CX_STR("8-) fsck ")));
   549 }
   551 TEST(String, strcasesuffix) {
   552     cxstring str = CX_STR("test my prefix and my suffix");
   553     cxstring empty = CX_STR("");
   554     EXPECT_FALSE(cx_strcasesuffix(empty, CX_STR("sUf")));
   555     EXPECT_TRUE(cx_strcasesuffix(str, empty));
   556     EXPECT_TRUE(cx_strcasesuffix(empty, empty));
   557     EXPECT_TRUE(cx_strcasesuffix(str, CX_STR("FIX")));
   558     EXPECT_FALSE(cx_strcasesuffix(str, CX_STR("fox")));
   559 }
   561 TEST(String, strreplace) {
   562     CxTestingAllocator alloc;
   563     cxstring str = CX_STR("test ababab string aba");
   564     cxstring longstr = CX_STR(
   565             "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd");
   566     cxstring notrail = CX_STR("test abab");
   567     cxstring empty = CX_STR("");
   568     cxstring astr = CX_STR("aaaaaaaaaa");
   569     cxstring csstr = CX_STR("test AB ab TEST xyz");
   571     cxmutstr repl = cx_strreplace(str, CX_STR("abab"), CX_STR("muchlonger"));
   572     auto expected = "test muchlongerab string aba";
   574     cxmutstr repln = cx_strreplacen(str, CX_STR("ab"), CX_STR("c"), 2);
   575     auto expectedn = "test ccab string aba";
   577     cxmutstr longrepl = cx_strreplace(longstr, CX_STR("a"), CX_STR("z"));
   578     auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd";
   580     cxmutstr replnotrail = cx_strreplace(notrail, CX_STR("ab"), CX_STR("z"));
   581     auto notrailexpect = "test zz";
   583     cxmutstr repleq = cx_strreplace(str, str, CX_STR("hello"));
   584     auto eqexpect = "hello";
   586     cxmutstr replempty1 = cx_strreplace(empty, CX_STR("ab"), CX_STR("c")); // expect: empty
   587     cxmutstr replempty2 = cx_strreplace(str, CX_STR("abab"), empty);
   588     auto emptyexpect2 = "test ab string aba";
   590     cxmutstr replpre = cx_strreplace(str, CX_STR("test "), CX_STR("TEST "));
   591     auto preexpected = "TEST ababab string aba";
   593     cxmutstr replan1 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 1);
   594     auto an1expected = "xaaaaaaaaa";
   596     cxmutstr replan4 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 4);
   597     auto an4expected = "xxxxaaaaaa";
   599     cxmutstr replan9 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 9);
   600     auto an9expected = "xxxxxxxxxa";
   602     cxmutstr replan10 = cx_strreplacen(astr, CX_STR("a"), CX_STR("x"), 10);
   603     auto an10expected = "xxxxxxxxxx";
   605     cxmutstr repl1_a = cx_strreplace_a(&alloc, csstr, CX_STR("AB"), CX_STR("*"));
   606     auto expeced1_a = "test * ab TEST xyz";
   608     cxmutstr repl2_a = cx_strreplace_a(&alloc, csstr, CX_STR("test"), CX_STR("TEST"));
   609     auto expected2_a = "TEST AB ab TEST xyz";
   612     EXPECT_NE(repl.ptr, str.ptr);
   613     EXPECT_ZERO_TERMINATED(repl);
   614     EXPECT_STREQ(repl.ptr, expected);
   615     EXPECT_ZERO_TERMINATED(repln);
   616     EXPECT_STREQ(repln.ptr, expectedn);
   617     EXPECT_ZERO_TERMINATED(longrepl);
   618     EXPECT_STREQ(longrepl.ptr, longexpect);
   619     EXPECT_ZERO_TERMINATED(replnotrail);
   620     EXPECT_STREQ(replnotrail.ptr, notrailexpect);
   621     EXPECT_ZERO_TERMINATED(repleq);
   622     EXPECT_STREQ(repleq.ptr, eqexpect);
   623     EXPECT_ZERO_TERMINATED(replempty1);
   624     EXPECT_STREQ(replempty1.ptr, "");
   625     EXPECT_ZERO_TERMINATED(replempty2);
   626     EXPECT_STREQ(replempty2.ptr, emptyexpect2);
   627     EXPECT_ZERO_TERMINATED(replpre);
   628     EXPECT_STREQ(replpre.ptr, preexpected);
   629     EXPECT_ZERO_TERMINATED(replan1);
   630     EXPECT_STREQ(replan1.ptr, an1expected);
   631     EXPECT_ZERO_TERMINATED(replan4);
   632     EXPECT_STREQ(replan4.ptr, an4expected);
   633     EXPECT_ZERO_TERMINATED(replan9);
   634     EXPECT_STREQ(replan9.ptr, an9expected);
   635     EXPECT_ZERO_TERMINATED(replan10);
   636     EXPECT_STREQ(replan10.ptr, an10expected);
   637     EXPECT_ZERO_TERMINATED(repl1_a);
   638     EXPECT_STREQ(repl1_a.ptr, expeced1_a);
   639     EXPECT_ZERO_TERMINATED(repl2_a);
   640     EXPECT_STREQ(repl2_a.ptr, expected2_a);
   642     cx_strfree(&repl);
   643     cx_strfree(&repln);
   644     cx_strfree(&longrepl);
   645     cx_strfree(&replnotrail);
   646     cx_strfree(&repleq);
   647     cx_strfree(&replempty1);
   648     cx_strfree(&replempty2);
   649     cx_strfree(&replpre);
   650     cx_strfree(&replan1);
   651     cx_strfree(&replan4);
   652     cx_strfree(&replan9);
   653     cx_strfree(&replan10);
   655     cx_strfree_a(&alloc, &repl1_a);
   656     cx_strfree_a(&alloc, &repl2_a);
   657     EXPECT_TRUE(alloc.verify());
   658 }
   660 TEST(String, strupper) {
   661     cxmutstr str = cx_strdup(CX_STR("thIs 1s @ Te$t"));
   662     cx_strupper(str);
   663     EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T");
   664     cx_strfree(&str);
   665 }
   667 TEST(String, strlower) {
   668     cxmutstr str = cx_strdup(CX_STR("thIs 1s @ Te$t"));
   669     cx_strlower(str);
   670     EXPECT_STREQ(str.ptr, "this 1s @ te$t");
   671     cx_strfree(&str);
   672 }
   674 TEST(String, strtok) {
   675     cxstring str = CX_STR("a,comma,separated,string");
   676     cxstring delim = CX_STR(",");
   677     CxStrtokCtx ctx = cx_strtok(str, delim, 3);
   678     EXPECT_EQ(ctx.str.ptr, str.ptr);
   679     EXPECT_EQ(ctx.str.length, str.length);
   680     EXPECT_EQ(ctx.delim.ptr, delim.ptr);
   681     EXPECT_EQ(ctx.delim.length, delim.length);
   682     EXPECT_EQ(ctx.limit, 3);
   683     EXPECT_EQ(ctx.found, 0);
   684     EXPECT_EQ(ctx.pos, 0);
   685     EXPECT_EQ(ctx.next_pos, 0);
   686     EXPECT_EQ(ctx.delim_more, nullptr);
   687     EXPECT_EQ(ctx.delim_more_count, 0);
   688 }
   690 TEST(String, strtok_m) {
   691     cxmutstr str = cx_strdup(CX_STR("a,comma,separated,string"));
   692     cxstring delim = CX_STR(",");
   693     CxStrtokCtx ctx = cx_strtok_m(str, delim, 3);
   694     EXPECT_EQ(ctx.str.ptr, str.ptr);
   695     EXPECT_EQ(ctx.str.length, str.length);
   696     EXPECT_EQ(ctx.delim.ptr, delim.ptr);
   697     EXPECT_EQ(ctx.delim.length, delim.length);
   698     EXPECT_EQ(ctx.limit, 3);
   699     EXPECT_EQ(ctx.found, 0);
   700     EXPECT_EQ(ctx.pos, 0);
   701     EXPECT_EQ(ctx.next_pos, 0);
   702     EXPECT_EQ(ctx.delim_more, nullptr);
   703     EXPECT_EQ(ctx.delim_more_count, 0);
   704     cx_strfree(&str);
   705 }
   707 TEST(String, strtok_delim) {
   708     cxstring str = CX_STR("an,arbitrarily|separated;string");
   709     cxstring delim = CX_STR(",");
   710     cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")};
   711     CxStrtokCtx ctx = cx_strtok(str, delim, 3);
   712     cx_strtok_delim(&ctx, delim_more, 2);
   713     EXPECT_EQ(ctx.str.ptr, str.ptr);
   714     EXPECT_EQ(ctx.str.length, str.length);
   715     EXPECT_EQ(ctx.delim.ptr, delim.ptr);
   716     EXPECT_EQ(ctx.delim.length, delim.length);
   717     EXPECT_EQ(ctx.limit, 3);
   718     EXPECT_EQ(ctx.found, 0);
   719     EXPECT_EQ(ctx.pos, 0);
   720     EXPECT_EQ(ctx.next_pos, 0);
   721     EXPECT_EQ(ctx.delim_more, delim_more);
   722     EXPECT_EQ(ctx.delim_more_count, 2);
   723 }
   725 TEST(String, strtok_next_easy) {
   726     cxstring str = CX_STR("a,comma,separated,string");
   727     cxstring delim = CX_STR(",");
   728     CxStrtokCtx ctx = cx_strtok(str, delim, 3);
   729     bool ret;
   730     cxstring tok;
   732     ret = cx_strtok_next(&ctx, &tok);
   733     ASSERT_TRUE(ret);
   734     EXPECT_EQ(cx_strcmp(tok, CX_STR("a")), 0);
   735     EXPECT_EQ(ctx.pos, 0);
   736     EXPECT_EQ(ctx.next_pos, 2);
   737     EXPECT_EQ(ctx.delim_pos, 1);
   738     EXPECT_EQ(ctx.found, 1);
   740     ret = cx_strtok_next(&ctx, &tok);
   741     ASSERT_TRUE(ret);
   742     EXPECT_EQ(cx_strcmp(tok, CX_STR("comma")), 0);
   743     EXPECT_EQ(ctx.pos, 2);
   744     EXPECT_EQ(ctx.next_pos, 8);
   745     EXPECT_EQ(ctx.delim_pos, 7);
   746     EXPECT_EQ(ctx.found, 2);
   748     ret = cx_strtok_next(&ctx, &tok);
   749     ASSERT_TRUE(ret);
   750     EXPECT_EQ(cx_strcmp(tok, CX_STR("separated")), 0);
   751     EXPECT_EQ(ctx.pos, 8);
   752     EXPECT_EQ(ctx.next_pos, 18);
   753     EXPECT_EQ(ctx.delim_pos, 17);
   754     EXPECT_EQ(ctx.found, 3);
   756     ret = cx_strtok_next(&ctx, &tok);
   757     ASSERT_FALSE(ret);
   758     EXPECT_EQ(ctx.pos, 8);
   759     EXPECT_EQ(ctx.next_pos, 18);
   760     EXPECT_EQ(ctx.delim_pos, 17);
   761     EXPECT_EQ(ctx.found, 3);
   762 }
   764 TEST(String, strtok_next_unlimited) {
   765     cxstring str = CX_STR("some;-;otherwise;-;separated;-;string;-;");
   766     cxstring delim = CX_STR(";-;");
   767     CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX);
   768     bool ret;
   769     cxstring tok;
   771     ret = cx_strtok_next(&ctx, &tok);
   772     ASSERT_TRUE(ret);
   773     EXPECT_EQ(cx_strcmp(tok, CX_STR("some")), 0);
   774     EXPECT_EQ(ctx.pos, 0);
   775     EXPECT_EQ(ctx.next_pos, 7);
   776     EXPECT_EQ(ctx.delim_pos, 4);
   777     EXPECT_EQ(ctx.found, 1);
   779     ret = cx_strtok_next(&ctx, &tok);
   780     ASSERT_TRUE(ret);
   781     EXPECT_EQ(cx_strcmp(tok, CX_STR("otherwise")), 0);
   782     EXPECT_EQ(ctx.pos, 7);
   783     EXPECT_EQ(ctx.next_pos, 19);
   784     EXPECT_EQ(ctx.delim_pos, 16);
   785     EXPECT_EQ(ctx.found, 2);
   787     ret = cx_strtok_next(&ctx, &tok);
   788     ASSERT_TRUE(ret);
   789     EXPECT_EQ(cx_strcmp(tok, CX_STR("separated")), 0);
   790     EXPECT_EQ(ctx.pos, 19);
   791     EXPECT_EQ(ctx.next_pos, 31);
   792     EXPECT_EQ(ctx.delim_pos, 28);
   793     EXPECT_EQ(ctx.found, 3);
   795     ret = cx_strtok_next(&ctx, &tok);
   796     ASSERT_TRUE(ret);
   797     EXPECT_EQ(cx_strcmp(tok, CX_STR("string")), 0);
   798     EXPECT_EQ(ctx.pos, 31);
   799     EXPECT_EQ(ctx.next_pos, 40);
   800     EXPECT_EQ(ctx.delim_pos, 37);
   801     EXPECT_EQ(ctx.found, 4);
   803     ret = cx_strtok_next(&ctx, &tok);
   804     ASSERT_TRUE(ret);
   805     EXPECT_EQ(cx_strcmp(tok, CX_STR("")), 0);
   806     EXPECT_EQ(ctx.pos, 40);
   807     EXPECT_EQ(ctx.next_pos, 40);
   808     EXPECT_EQ(ctx.delim_pos, 40);
   809     EXPECT_EQ(ctx.found, 5);
   811     ret = cx_strtok_next(&ctx, &tok);
   812     ASSERT_FALSE(ret);
   813     EXPECT_EQ(ctx.pos, 40);
   814     EXPECT_EQ(ctx.delim_pos, 40);
   815     EXPECT_EQ(ctx.found, 5);
   816 }
   818 TEST(String, strtok_next_advanced) {
   819     cxmutstr str = cx_strdup(CX_STR("an,arbitrarily;||separated;string"));
   820     cxstring delim = CX_STR(",");
   821     cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")};
   822     CxStrtokCtx ctx = cx_strtok_m(str, delim, 10);
   823     cx_strtok_delim(&ctx, delim_more, 2);
   824     bool ret;
   825     cxmutstr tok;
   827     ret = cx_strtok_next_m(&ctx, &tok);
   828     ASSERT_TRUE(ret);
   829     EXPECT_EQ(cx_strcmp(cx_strcast(tok), CX_STR("an")), 0);
   830     EXPECT_EQ(ctx.pos, 0);
   831     EXPECT_EQ(ctx.next_pos, 3);
   832     EXPECT_EQ(ctx.delim_pos, 2);
   833     EXPECT_EQ(ctx.found, 1);
   834     cx_strupper(tok);
   836     ret = cx_strtok_next_m(&ctx, &tok);
   837     ASSERT_TRUE(ret);
   838     EXPECT_EQ(cx_strcmp(cx_strcast(tok), CX_STR("arbitrarily")), 0);
   839     EXPECT_EQ(ctx.pos, 3);
   840     EXPECT_EQ(ctx.next_pos, 15);
   841     EXPECT_EQ(ctx.delim_pos, 14);
   842     EXPECT_EQ(ctx.found, 2);
   843     cx_strupper(tok);
   845     ret = cx_strtok_next_m(&ctx, &tok);
   846     ASSERT_TRUE(ret);
   847     EXPECT_EQ(cx_strcmp(cx_strcast(tok), CX_STR("")), 0);
   848     EXPECT_EQ(ctx.pos, 15);
   849     EXPECT_EQ(ctx.next_pos, 17);
   850     EXPECT_EQ(ctx.delim_pos, 15);
   851     EXPECT_EQ(ctx.found, 3);
   852     cx_strupper(tok);
   854     ret = cx_strtok_next_m(&ctx, &tok);
   855     ASSERT_TRUE(ret);
   856     EXPECT_EQ(cx_strcmp(cx_strcast(tok), CX_STR("separated")), 0);
   857     EXPECT_EQ(ctx.pos, 17);
   858     EXPECT_EQ(ctx.next_pos, 27);
   859     EXPECT_EQ(ctx.delim_pos, 26);
   860     EXPECT_EQ(ctx.found, 4);
   861     cx_strupper(tok);
   863     ret = cx_strtok_next_m(&ctx, &tok);
   864     ASSERT_TRUE(ret);
   865     EXPECT_EQ(cx_strcmp(cx_strcast(tok), CX_STR("string")), 0);
   866     EXPECT_EQ(ctx.pos, 27);
   867     EXPECT_EQ(ctx.next_pos, 33);
   868     EXPECT_EQ(ctx.delim_pos, 33);
   869     EXPECT_EQ(ctx.found, 5);
   870     cx_strupper(tok);
   872     ret = cx_strtok_next_m(&ctx, &tok);
   873     ASSERT_FALSE(ret);
   874     EXPECT_EQ(ctx.pos, 27);
   875     EXPECT_EQ(ctx.next_pos, 33);
   876     EXPECT_EQ(ctx.delim_pos, 33);
   877     EXPECT_EQ(ctx.found, 5);
   879     EXPECT_EQ(cx_strcmp(cx_strcast(str), CX_STR("AN,ARBITRARILY;||SEPARATED;STRING")), 0);
   881     cx_strfree(&str);
   882 }

mercurial