test/test_string.cpp

Thu, 02 Feb 2023 20:25:34 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 02 Feb 2023 20:25:34 +0100
changeset 645
ec50abb285ad
parent 628
1e2be40f0cb5
permissions
-rw-r--r--

add strtok API - fixes #220

     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);
   216 }
   218 TEST(String, strcasecmp) {
   219     cxstring str = CX_STR("compare this");
   221     EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0);
   222     EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0);
   223     EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0);
   224     EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0);
   225     EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0);
   226     EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0);
   227     EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0);
   228     EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0);
   229 }
   231 TEST(String, strcat) {
   232     cxstring s1 = CX_STR("12");
   233     cxstring s2 = CX_STR("34");
   234     cxstring s3 = CX_STR("56");
   235     cxstring sn = {nullptr, 0};
   237     CxTestingAllocator alloc;
   239     cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2);
   240     EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0);
   241     EXPECT_ZERO_TERMINATED(t1);
   242     cx_strfree_a(&alloc, &t1);
   244     cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3);
   245     EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0);
   246     EXPECT_ZERO_TERMINATED(t2);
   247     cx_strfree_a(&alloc, &t2);
   249     cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn);
   250     EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0);
   251     EXPECT_ZERO_TERMINATED(t3);
   252     cx_strfree_a(&alloc, &t3);
   254     cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn);
   255     EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0);
   256     EXPECT_ZERO_TERMINATED(t4);
   257     cx_strfree_a(&alloc, &t4);
   259     EXPECT_TRUE(alloc.verify());
   261     // use the macro
   262     cxmutstr t5 = cx_strcat(3, s3, s1, s2);
   263     EXPECT_EQ(cx_strcmp(cx_strcast(t5), cx_str("561234")), 0);
   264     EXPECT_ZERO_TERMINATED(t5);
   265     cx_strfree(&t5);
   266 }
   268 TEST(String, strsplit) {
   270     cxstring test = cx_str("this,is,a,csv,string");
   271     size_t capa = 8;
   272     cxstring list[8];
   273     size_t n;
   275     // special case: empty string
   276     n = cx_strsplit(test, cx_str(""), capa, list);
   277     ASSERT_EQ(n, 1);
   278     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   280     // no delimiter occurrence
   281     n = cx_strsplit(test, cx_str("z"), capa, list);
   282     ASSERT_EQ(n, 1);
   283     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   285     // partially matching delimiter
   286     n = cx_strsplit(test, cx_str("is,not"), capa, list);
   287     ASSERT_EQ(n, 1);
   288     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   290     // matching single-char delimiter
   291     n = cx_strsplit(test, cx_str(","), capa, list);
   292     ASSERT_EQ(n, 5);
   293     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   294     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   295     EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
   296     EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
   297     EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
   299     // matching multi-char delimiter
   300     n = cx_strsplit(test, cx_str("is"), capa, list);
   301     ASSERT_EQ(n, 3);
   302     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   303     EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
   304     EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
   306     // bounded list using single-char delimiter
   307     n = cx_strsplit(test, cx_str(","), 3, list);
   308     ASSERT_EQ(n, 3);
   309     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   310     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   311     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   313     // bounded list using multi-char delimiter
   314     n = cx_strsplit(test, cx_str("is"), 2, list);
   315     ASSERT_EQ(n, 2);
   316     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   317     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   319     // start with delimiter
   320     n = cx_strsplit(test, cx_str("this"), capa, list);
   321     ASSERT_EQ(n, 2);
   322     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   323     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   325     // end with delimiter
   326     n = cx_strsplit(test, cx_str("string"), capa, list);
   327     ASSERT_EQ(n, 2);
   328     EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
   329     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   332     // end with delimiter exceed bound
   333     n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list);
   334     ASSERT_EQ(n, 3);
   335     EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
   336     EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
   337     EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
   339     // exact match
   340     n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list);
   341     ASSERT_EQ(n, 2);
   342     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   343     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   345     // string to be split is only substring
   346     n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list);
   347     ASSERT_EQ(n, 1);
   348     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   350     // subsequent encounter of delimiter (the string between is empty)
   351     n = cx_strsplit(test, cx_str("is,"), capa, list);
   352     ASSERT_EQ(n, 3);
   353     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   354     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   355     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   357     // call the _m variant just for coverage
   358     auto mtest = cx_strdup(test);
   359     cxmutstr mlist[4];
   360     n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist);
   361     ASSERT_EQ(n, 3);
   362     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
   363     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
   364     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
   365     cx_strfree(&mtest);
   366 }
   368 TEST(String, strsplit_a) {
   369     CxTestingAllocator alloc;
   371     cxstring test = cx_str("this,is,a,csv,string");
   372     size_t capa = 8;
   373     cxstring *list;
   374     size_t n;
   376     // special case: empty string
   377     n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list);
   378     ASSERT_EQ(n, 1);
   379     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   380     cxFree(&alloc, list);
   382     // no delimiter occurrence
   383     n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list);
   384     ASSERT_EQ(n, 1);
   385     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   386     cxFree(&alloc, list);
   388     // partially matching delimiter
   389     n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list);
   390     ASSERT_EQ(n, 1);
   391     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   392     cxFree(&alloc, list);
   394     // matching single-char delimiter
   395     n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list);
   396     ASSERT_EQ(n, 5);
   397     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   398     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   399     EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
   400     EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
   401     EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
   402     cxFree(&alloc, list);
   404     // matching multi-char delimiter
   405     n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list);
   406     ASSERT_EQ(n, 3);
   407     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   408     EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
   409     EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
   410     cxFree(&alloc, list);
   412     // bounded list using single-char delimiter
   413     n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list);
   414     ASSERT_EQ(n, 3);
   415     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   416     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   417     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   418     cxFree(&alloc, list);
   420     // bounded list using multi-char delimiter
   421     n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list);
   422     ASSERT_EQ(n, 2);
   423     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   424     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   425     cxFree(&alloc, list);
   427     // start with delimiter
   428     n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list);
   429     ASSERT_EQ(n, 2);
   430     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   431     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   432     cxFree(&alloc, list);
   434     // end with delimiter
   435     n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list);
   436     ASSERT_EQ(n, 2);
   437     EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
   438     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   439     cxFree(&alloc, list);
   441     // end with delimiter exceed bound
   442     n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list);
   443     ASSERT_EQ(n, 3);
   444     EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
   445     EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
   446     EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
   447     cxFree(&alloc, list);
   449     // exact match
   450     n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list);
   451     ASSERT_EQ(n, 2);
   452     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   453     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   454     cxFree(&alloc, list);
   456     // string to be split is only substring
   457     n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list);
   458     ASSERT_EQ(n, 1);
   459     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   460     cxFree(&alloc, list);
   462     // subsequent encounter of delimiter (the string between is empty)
   463     n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list);
   464     ASSERT_EQ(n, 3);
   465     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   466     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   467     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   468     cxFree(&alloc, list);
   470     // call the _m variant just for coverage
   471     auto mtest = cx_strdup(test);
   472     cxmutstr *mlist;
   473     n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist);
   474     ASSERT_EQ(n, 3);
   475     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
   476     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
   477     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
   478     cxFree(&alloc, mlist);
   479     cx_strfree(&mtest);
   481     EXPECT_TRUE(alloc.verify());
   482 }
   484 TEST(String, strtrim) {
   485     cxstring t1 = cx_strtrim(cx_str("  ein test  \t "));
   486     cxstring t2 = cx_strtrim(cx_str("abc"));
   487     cxstring t3 = cx_strtrim(cx_str(" 123"));
   488     cxstring t4 = cx_strtrim(cx_str("xyz "));
   489     cxstring t5 = cx_strtrim(cx_str("   "));
   490     cxstring empty = cx_strtrim(cx_str(""));
   492     EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0);
   493     EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0);
   494     EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0);
   495     EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0);
   496     EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0);
   497     EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0);
   499     // call the _m variant just for coverage
   500     cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) "  ein test  \t "));
   501     EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0);
   502 }
   504 TEST(String, strprefix) {
   505     cxstring str = CX_STR("test my prefix and my suffix");
   506     cxstring empty = CX_STR("");
   507     EXPECT_FALSE(cx_strprefix(empty, cx_str("pref")));
   508     EXPECT_TRUE(cx_strprefix(str, empty));
   509     EXPECT_TRUE(cx_strprefix(empty, empty));
   510     EXPECT_TRUE(cx_strprefix(str, cx_str("test ")));
   511     EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck ")));
   512 }
   514 TEST(String, strsuffix) {
   515     cxstring str = CX_STR("test my prefix and my suffix");
   516     cxstring empty = CX_STR("");
   517     EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf")));
   518     EXPECT_TRUE(cx_strsuffix(str, empty));
   519     EXPECT_TRUE(cx_strsuffix(empty, empty));
   520     EXPECT_TRUE(cx_strsuffix(str, cx_str("fix")));
   521     EXPECT_FALSE(cx_strsuffix(str, cx_str("fox")));
   522 }
   524 TEST(String, strcaseprefix) {
   525     cxstring str = CX_STR("test my prefix and my suffix");
   526     cxstring empty = CX_STR("");
   527     EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf")));
   528     EXPECT_TRUE(cx_strcaseprefix(str, empty));
   529     EXPECT_TRUE(cx_strcaseprefix(empty, empty));
   530     EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST ")));
   531     EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck ")));
   532 }
   534 TEST(String, strcasesuffix) {
   535     cxstring str = CX_STR("test my prefix and my suffix");
   536     cxstring empty = CX_STR("");
   537     EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf")));
   538     EXPECT_TRUE(cx_strcasesuffix(str, empty));
   539     EXPECT_TRUE(cx_strcasesuffix(empty, empty));
   540     EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX")));
   541     EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox")));
   542 }
   544 TEST(String, strreplace) {
   545     CxTestingAllocator alloc;
   546     cxstring str = CX_STR("test ababab string aba");
   547     cxstring longstr = CX_STR(
   548             "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd");
   549     cxstring notrail = CX_STR("test abab");
   550     cxstring empty = CX_STR("");
   551     cxstring astr = CX_STR("aaaaaaaaaa");
   552     cxstring csstr = CX_STR("test AB ab TEST xyz");
   554     cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger"));
   555     auto expected = "test muchlongerab string aba";
   557     cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2);
   558     auto expectedn = "test ccab string aba";
   560     cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z"));
   561     auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd";
   563     cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z"));
   564     auto notrailexpect = "test zz";
   566     cxmutstr repleq = cx_strreplace(str, str, cx_str("hello"));
   567     auto eqexpect = "hello";
   569     cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty
   570     cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty);
   571     auto emptyexpect2 = "test ab string aba";
   573     cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST "));
   574     auto preexpected = "TEST ababab string aba";
   576     cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1);
   577     auto an1expected = "xaaaaaaaaa";
   579     cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4);
   580     auto an4expected = "xxxxaaaaaa";
   582     cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9);
   583     auto an9expected = "xxxxxxxxxa";
   585     cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10);
   586     auto an10expected = "xxxxxxxxxx";
   588     cxmutstr repl1_a = cx_strreplace_a(&alloc, csstr, cx_str("AB"), cx_str("*"));
   589     auto expeced1_a = "test * ab TEST xyz";
   591     cxmutstr repl2_a = cx_strreplace_a(&alloc, csstr, cx_str("test"), cx_str("TEST"));
   592     auto expected2_a = "TEST AB ab TEST xyz";
   595     EXPECT_NE(repl.ptr, str.ptr);
   596     EXPECT_ZERO_TERMINATED(repl);
   597     EXPECT_STREQ(repl.ptr, expected);
   598     EXPECT_ZERO_TERMINATED(repln);
   599     EXPECT_STREQ(repln.ptr, expectedn);
   600     EXPECT_ZERO_TERMINATED(longrepl);
   601     EXPECT_STREQ(longrepl.ptr, longexpect);
   602     EXPECT_ZERO_TERMINATED(replnotrail);
   603     EXPECT_STREQ(replnotrail.ptr, notrailexpect);
   604     EXPECT_ZERO_TERMINATED(repleq);
   605     EXPECT_STREQ(repleq.ptr, eqexpect);
   606     EXPECT_ZERO_TERMINATED(replempty1);
   607     EXPECT_STREQ(replempty1.ptr, "");
   608     EXPECT_ZERO_TERMINATED(replempty2);
   609     EXPECT_STREQ(replempty2.ptr, emptyexpect2);
   610     EXPECT_ZERO_TERMINATED(replpre);
   611     EXPECT_STREQ(replpre.ptr, preexpected);
   612     EXPECT_ZERO_TERMINATED(replan1);
   613     EXPECT_STREQ(replan1.ptr, an1expected);
   614     EXPECT_ZERO_TERMINATED(replan4);
   615     EXPECT_STREQ(replan4.ptr, an4expected);
   616     EXPECT_ZERO_TERMINATED(replan9);
   617     EXPECT_STREQ(replan9.ptr, an9expected);
   618     EXPECT_ZERO_TERMINATED(replan10);
   619     EXPECT_STREQ(replan10.ptr, an10expected);
   620     EXPECT_ZERO_TERMINATED(repl1_a);
   621     EXPECT_STREQ(repl1_a.ptr, expeced1_a);
   622     EXPECT_ZERO_TERMINATED(repl2_a);
   623     EXPECT_STREQ(repl2_a.ptr, expected2_a);
   625     cx_strfree(&repl);
   626     cx_strfree(&repln);
   627     cx_strfree(&longrepl);
   628     cx_strfree(&replnotrail);
   629     cx_strfree(&repleq);
   630     cx_strfree(&replempty1);
   631     cx_strfree(&replempty2);
   632     cx_strfree(&replpre);
   633     cx_strfree(&replan1);
   634     cx_strfree(&replan4);
   635     cx_strfree(&replan9);
   636     cx_strfree(&replan10);
   638     cx_strfree_a(&alloc, &repl1_a);
   639     cx_strfree_a(&alloc, &repl2_a);
   640     EXPECT_TRUE(alloc.verify());
   641 }
   643 TEST(String, strupper) {
   644     cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
   645     cx_strupper(str);
   646     EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T");
   647     cx_strfree(&str);
   648 }
   650 TEST(String, strlower) {
   651     cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
   652     cx_strlower(str);
   653     EXPECT_STREQ(str.ptr, "this 1s @ te$t");
   654     cx_strfree(&str);
   655 }
   657 TEST(String, strtok) {
   658     cxstring str = cx_str("a,comma,separated,string");
   659     cxstring delim = cx_str(",");
   660     CxStrtokCtx ctx = cx_strtok(str, delim, 3);
   661     EXPECT_EQ(ctx.str.ptr, str.ptr);
   662     EXPECT_EQ(ctx.str.length, str.length);
   663     EXPECT_EQ(ctx.delim.ptr, delim.ptr);
   664     EXPECT_EQ(ctx.delim.length, delim.length);
   665     EXPECT_EQ(ctx.limit, 3);
   666     EXPECT_EQ(ctx.found, 0);
   667     EXPECT_EQ(ctx.pos, 0);
   668     EXPECT_EQ(ctx.next_pos, 0);
   669     EXPECT_EQ(ctx.delim_more, nullptr);
   670     EXPECT_EQ(ctx.delim_more_count, 0);
   671 }
   673 TEST(String, strtok_m) {
   674     cxmutstr str = cx_strdup(cx_str("a,comma,separated,string"));
   675     cxstring delim = cx_str(",");
   676     CxStrtokCtx ctx = cx_strtok_m(str, delim, 3);
   677     EXPECT_EQ(ctx.str.ptr, str.ptr);
   678     EXPECT_EQ(ctx.str.length, str.length);
   679     EXPECT_EQ(ctx.delim.ptr, delim.ptr);
   680     EXPECT_EQ(ctx.delim.length, delim.length);
   681     EXPECT_EQ(ctx.limit, 3);
   682     EXPECT_EQ(ctx.found, 0);
   683     EXPECT_EQ(ctx.pos, 0);
   684     EXPECT_EQ(ctx.next_pos, 0);
   685     EXPECT_EQ(ctx.delim_more, nullptr);
   686     EXPECT_EQ(ctx.delim_more_count, 0);
   687     cx_strfree(&str);
   688 }
   690 TEST(String, strtok_delim) {
   691     cxstring str = cx_str("an,arbitrarily|separated;string");
   692     cxstring delim = cx_str(",");
   693     cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")};
   694     CxStrtokCtx ctx = cx_strtok(str, delim, 3);
   695     cx_strtok_delim(&ctx, delim_more, 2);
   696     EXPECT_EQ(ctx.str.ptr, str.ptr);
   697     EXPECT_EQ(ctx.str.length, str.length);
   698     EXPECT_EQ(ctx.delim.ptr, delim.ptr);
   699     EXPECT_EQ(ctx.delim.length, delim.length);
   700     EXPECT_EQ(ctx.limit, 3);
   701     EXPECT_EQ(ctx.found, 0);
   702     EXPECT_EQ(ctx.pos, 0);
   703     EXPECT_EQ(ctx.next_pos, 0);
   704     EXPECT_EQ(ctx.delim_more, delim_more);
   705     EXPECT_EQ(ctx.delim_more_count, 2);
   706 }
   708 TEST(String, strtok_next_easy) {
   709     cxstring str = cx_str("a,comma,separated,string");
   710     cxstring delim = cx_str(",");
   711     CxStrtokCtx ctx = cx_strtok(str, delim, 3);
   712     bool ret;
   713     cxstring tok;
   715     ret = cx_strtok_next(&ctx, &tok);
   716     ASSERT_TRUE(ret);
   717     EXPECT_EQ(cx_strcmp(tok, cx_str("a")), 0);
   718     EXPECT_EQ(ctx.pos, 0);
   719     EXPECT_EQ(ctx.next_pos, 2);
   720     EXPECT_EQ(ctx.delim_pos, 1);
   721     EXPECT_EQ(ctx.found, 1);
   723     ret = cx_strtok_next(&ctx, &tok);
   724     ASSERT_TRUE(ret);
   725     EXPECT_EQ(cx_strcmp(tok, cx_str("comma")), 0);
   726     EXPECT_EQ(ctx.pos, 2);
   727     EXPECT_EQ(ctx.next_pos, 8);
   728     EXPECT_EQ(ctx.delim_pos, 7);
   729     EXPECT_EQ(ctx.found, 2);
   731     ret = cx_strtok_next(&ctx, &tok);
   732     ASSERT_TRUE(ret);
   733     EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0);
   734     EXPECT_EQ(ctx.pos, 8);
   735     EXPECT_EQ(ctx.next_pos, 18);
   736     EXPECT_EQ(ctx.delim_pos, 17);
   737     EXPECT_EQ(ctx.found, 3);
   739     ret = cx_strtok_next(&ctx, &tok);
   740     ASSERT_FALSE(ret);
   741     EXPECT_EQ(ctx.pos, 8);
   742     EXPECT_EQ(ctx.next_pos, 18);
   743     EXPECT_EQ(ctx.delim_pos, 17);
   744     EXPECT_EQ(ctx.found, 3);
   745 }
   747 TEST(String, strtok_next_unlimited) {
   748     cxstring str = cx_str("some;-;otherwise;-;separated;-;string;-;");
   749     cxstring delim = cx_str(";-;");
   750     CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX);
   751     bool ret;
   752     cxstring tok;
   754     ret = cx_strtok_next(&ctx, &tok);
   755     ASSERT_TRUE(ret);
   756     EXPECT_EQ(cx_strcmp(tok, cx_str("some")), 0);
   757     EXPECT_EQ(ctx.pos, 0);
   758     EXPECT_EQ(ctx.next_pos, 7);
   759     EXPECT_EQ(ctx.delim_pos, 4);
   760     EXPECT_EQ(ctx.found, 1);
   762     ret = cx_strtok_next(&ctx, &tok);
   763     ASSERT_TRUE(ret);
   764     EXPECT_EQ(cx_strcmp(tok, cx_str("otherwise")), 0);
   765     EXPECT_EQ(ctx.pos, 7);
   766     EXPECT_EQ(ctx.next_pos, 19);
   767     EXPECT_EQ(ctx.delim_pos, 16);
   768     EXPECT_EQ(ctx.found, 2);
   770     ret = cx_strtok_next(&ctx, &tok);
   771     ASSERT_TRUE(ret);
   772     EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0);
   773     EXPECT_EQ(ctx.pos, 19);
   774     EXPECT_EQ(ctx.next_pos, 31);
   775     EXPECT_EQ(ctx.delim_pos, 28);
   776     EXPECT_EQ(ctx.found, 3);
   778     ret = cx_strtok_next(&ctx, &tok);
   779     ASSERT_TRUE(ret);
   780     EXPECT_EQ(cx_strcmp(tok, cx_str("string")), 0);
   781     EXPECT_EQ(ctx.pos, 31);
   782     EXPECT_EQ(ctx.next_pos, 40);
   783     EXPECT_EQ(ctx.delim_pos, 37);
   784     EXPECT_EQ(ctx.found, 4);
   786     ret = cx_strtok_next(&ctx, &tok);
   787     ASSERT_TRUE(ret);
   788     EXPECT_EQ(cx_strcmp(tok, cx_str("")), 0);
   789     EXPECT_EQ(ctx.pos, 40);
   790     EXPECT_EQ(ctx.next_pos, 40);
   791     EXPECT_EQ(ctx.delim_pos, 40);
   792     EXPECT_EQ(ctx.found, 5);
   794     ret = cx_strtok_next(&ctx, &tok);
   795     ASSERT_FALSE(ret);
   796     EXPECT_EQ(ctx.pos, 40);
   797     EXPECT_EQ(ctx.delim_pos, 40);
   798     EXPECT_EQ(ctx.found, 5);
   799 }
   801 TEST(String, strtok_next_advanced) {
   802     cxmutstr str = cx_strdup(cx_str("an,arbitrarily;||separated;string"));
   803     cxstring delim = cx_str(",");
   804     cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")};
   805     CxStrtokCtx ctx = cx_strtok_m(str, delim, 10);
   806     cx_strtok_delim(&ctx, delim_more, 2);
   807     bool ret;
   808     cxmutstr tok;
   810     ret = cx_strtok_next_m(&ctx, &tok);
   811     ASSERT_TRUE(ret);
   812     EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("an")), 0);
   813     EXPECT_EQ(ctx.pos, 0);
   814     EXPECT_EQ(ctx.next_pos, 3);
   815     EXPECT_EQ(ctx.delim_pos, 2);
   816     EXPECT_EQ(ctx.found, 1);
   817     cx_strupper(tok);
   819     ret = cx_strtok_next_m(&ctx, &tok);
   820     ASSERT_TRUE(ret);
   821     EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("arbitrarily")), 0);
   822     EXPECT_EQ(ctx.pos, 3);
   823     EXPECT_EQ(ctx.next_pos, 15);
   824     EXPECT_EQ(ctx.delim_pos, 14);
   825     EXPECT_EQ(ctx.found, 2);
   826     cx_strupper(tok);
   828     ret = cx_strtok_next_m(&ctx, &tok);
   829     ASSERT_TRUE(ret);
   830     EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("")), 0);
   831     EXPECT_EQ(ctx.pos, 15);
   832     EXPECT_EQ(ctx.next_pos, 17);
   833     EXPECT_EQ(ctx.delim_pos, 15);
   834     EXPECT_EQ(ctx.found, 3);
   835     cx_strupper(tok);
   837     ret = cx_strtok_next_m(&ctx, &tok);
   838     ASSERT_TRUE(ret);
   839     EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("separated")), 0);
   840     EXPECT_EQ(ctx.pos, 17);
   841     EXPECT_EQ(ctx.next_pos, 27);
   842     EXPECT_EQ(ctx.delim_pos, 26);
   843     EXPECT_EQ(ctx.found, 4);
   844     cx_strupper(tok);
   846     ret = cx_strtok_next_m(&ctx, &tok);
   847     ASSERT_TRUE(ret);
   848     EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("string")), 0);
   849     EXPECT_EQ(ctx.pos, 27);
   850     EXPECT_EQ(ctx.next_pos, 33);
   851     EXPECT_EQ(ctx.delim_pos, 33);
   852     EXPECT_EQ(ctx.found, 5);
   853     cx_strupper(tok);
   855     ret = cx_strtok_next_m(&ctx, &tok);
   856     ASSERT_FALSE(ret);
   857     EXPECT_EQ(ctx.pos, 27);
   858     EXPECT_EQ(ctx.next_pos, 33);
   859     EXPECT_EQ(ctx.delim_pos, 33);
   860     EXPECT_EQ(ctx.found, 5);
   862     EXPECT_EQ(cx_strcmp(cx_strcast(str), cx_str("AN,ARBITRARILY;||SEPARATED;STRING")), 0);
   864     cx_strfree(&str);
   865 }

mercurial