#include "rexy/string.hpp" #include "rexy/allocator.hpp" #include #include #include #include #include [[noreturn]] void error(const char* str){ fprintf(stderr, "%s", str); exit(1); } using namespace rexy::str_literals; using test_str = rexy::basic_string>; void check_empty_construction(){ test_str str1; if(str1.length() != 0) error("length() should return 0 on default init\n"); if(test_str::uses_sso()){ if(str1.data()[0] != 0) error("data() should return an empty, zero length string\n"); }else{ if(str1.data() != nullptr) error("data() should return a null string\n"); } if(str1.valid()) error("valid() should return false on empty string\n"); if(str1.data() != str1.c_str()) error("c_str() should be a synonymn of data()\n"); test_str str2(str1); if(str2.length() != str1.length()) error("copy construction on empty string should give equivalent length()\n"); if(str2.capacity() != str1.capacity()) error("copy construction on empty string should give equivalent capacity()\n"); if(test_str::uses_sso()){ if(str2.data()[0] != str1.data()[0]) error("copy construction on empty string should give equivalent data()\n"); }else{ if(str2.data() != str1.data()) error("copy construction on empty string should give equivalent data()\n"); } test_str str3(std::move(str2)); if(str3.length() != str1.length()) error("move construction on empty string should give equivalent length()\n"); if(str3.capacity() != str1.capacity()) error("move construction on empty string should give equivalent capacity()\n"); if(test_str::uses_sso()){ if(str3.data()[0] != str1.data()[0]) error("move construction on empty string should give equivalent data()\n"); }else{ if(str3.data() != str1.data()) error("move construction on empty string should give equivalent data()\n"); } } void check_short_construction(){ if(!test_str::uses_sso()) return; test_str::size_type cap = test_str::short_string_size(); test_str str1("a"); if(str1.length() != 1) error("short constructed string 'a' should be length() == 1\n"); if(str1.capacity() != cap) error("short constructed string 'a' should be capacity() == short_string_size()\n"); if(strcmp(str1.data(), "a")) error("short constructed string 'a' should be !strcmp(data(), \"a\")\n"); test_str str2(str1); if(str2.length() != str1.length()) error("short copy constructed string should have equal length()\n"); if(str2.capacity() != str1.capacity()) error("short copy constructed string should have equal capacity()\n"); if(strcmp(str2.data(), str1.data())) error("short copy constructed string should have equivalent data()\n"); test_str str3(std::move(str2)); if(str3.length() != str1.length()) error("short move constructed string should have equal length()\n"); if(str3.capacity() != str1.capacity()) error("short move constructed string should have equal capacity()\n"); if(strcmp(str3.data(), str1.data())) error("short move constructed string should have equivalent data()\n"); } void check_long_construction(){ const char* data = "this is a really long string that should ensure that it makes a dynamic allocation even if it has a big buffer."; size_t len = strlen(data); test_str str1(data); if(str1.length() != len) error("long constructed string should be length() == strlen(data)\n"); if(str1.capacity() < len) error("long constructed string should be capacity() >= strlen(data)\n"); if(strcmp(str1.data(), data)) error("long constructed string should be !strcmp(data(), data)\n"); test_str str2(str1); if(str2.length() != str1.length()) error("long copy constructed string should have equal length()\n"); if(str2.capacity() != str1.capacity()) error("long copy constructed string should have equal capacity()\n"); if(strcmp(str2.data(), str1.data())) error("long copy constructed string should have equivalent data()\n"); test_str str3(std::move(str2)); if(str3.length() != str1.length()) error("long move constructed string should have equal length()\n"); if(str3.capacity() != str1.capacity()) error("long move constructed string should have equal capacity()\n"); if(strcmp(str3.data(), str1.data())) error("long move constructed string should have equivalent data()\n"); } void check_short_assignment(){ if(!test_str::uses_sso()) return; const char* longstartdata = "this is another really long string that should ensure that it makes some sort of dyn alloc for big buf"; test_str::size_type cap = test_str::short_string_size(); test_str str1("zy"); str1 = "a"; if(str1.length() != 1) error("short assigned string 'a' should be length() == 1\n"); if(str1.capacity() != cap) error("short assigned string 'a' should be capacity() == short_string_size()\n"); if(strcmp(str1.data(), "a")) error("short assigned string 'a' should be !strcmp(data(), \"a\")\n"); test_str str2("ba"); str2 = str1; if(str2.length() != str1.length()) error("short copy assigned string should have equal length()\n"); if(str2.capacity() != str1.capacity()) error("short copy assigned string should have equal capacity()\n"); if(strcmp(str2.data(), str1.data())) error("short copy assigned string should have equivalent data()\n"); test_str str3("cb"); str3 = std::move(str2); if(str3.length() != str1.length()) error("short move assigned string should have equal length()\n"); if(str3.capacity() != str1.capacity()) error("short move assigned string should have equal capacity()\n"); if(strcmp(str3.data(), str1.data())) error("short move assigned string should have equivalent data()\n"); test_str str4(longstartdata); str4 = str1; if(str4.length() != str1.length()) error("long->short copy assigned string should have equal length()\n"); if(str4.capacity() < str1.capacity()) error("long->short copy assigned string should have equal or greater capacity()\n"); if(strcmp(str4.data(), str1.data())) error("long->short copy assigned string should have equivalent data()\n"); test_str str5(longstartdata); str5 = std::move(str4); if(str5.length() != str1.length()) error("long->short move assigned string should have equal length()\n"); if(str5.capacity() < str1.capacity()) error("long->short move assigned string should have equal or greater capacity()\n"); if(strcmp(str5.data(), str1.data())) error("long->short move assigned string should have equivalent data()\n"); } void check_long_assignment(){ const char* startdata1 = "this is another really long string that should ensure that it makes some sort of dyn alloc for big buf"; const char* startdata2 = "zy"; const char* data = "this is a really long string that should ensure that it makes a dynamic allocation even if it has a big buffer."; size_t len = strlen(data); test_str str1(startdata1); str1 = data; if(str1.length() != len) error("long assigned string should be length() == strlen(data)\n"); if(str1.capacity() < len) error("long assigned string should be capacity() >= strlen(data)\n"); if(strcmp(str1.data(), data)) error("long assigned string should be !strcmp(data(), data)\n"); test_str str2(startdata1); str2 = str1; if(str2.length() != str1.length()) error("long copy assigned string should have equal length()\n"); if(str2.capacity() != str1.capacity()) error("long copy assigned string should have equal capacity()\n"); if(strcmp(str2.data(), str1.data())) error("long copy assigned string should have equivalent data()\n"); test_str str3(startdata1); str3 = std::move(str2); if(str3.length() != str1.length()) error("long move assigned string should have equal length()\n"); if(str3.capacity() != str1.capacity()) error("long move assigned string should have equal capacity()\n"); if(strcmp(str3.data(), str1.data())) error("long move assigned string should have equivalent data()\n"); test_str str4(startdata2); str4 = str1; if(str4.length() != str1.length()) error("short->long copy assigned string should have equal length()\n"); if(str4.capacity() != str1.capacity()) error("short->long copy assigned string should have equal capacity()\n"); if(strcmp(str4.data(), str1.data())) error("short->long copy assigned string should have equivalent data()\n"); test_str str5(startdata2); str5 = std::move(str4); if(str5.length() != str1.length()) error("short->long move assigned string should have equal length()\n"); if(str5.capacity() != str1.capacity()) error("short->long move assigned string should have equal capacity()\n"); if(strcmp(str5.data(), str1.data())) error("short->long move assigned string should have equivalent data()\n"); } void check_short_append(){ test_str str1; test_str str2("bc"); test_str str3("really long string that should trigger a short to long conversion in the string"); str1.append("a"); str1.append("b"); str1.append(str2); if(strcmp(str1.data(), "abbc")) error("short append should have resulted in abbc\n"); str1.append(str3); if(strcmp(str1.c_str(), "abbcreally long string that should trigger a short to long conversion in the string")) error("short->long append should have resulted in abbcreally long string that should trigger a short to long conversion in the string\n"); } void check_long_append(){ const char* startdata1 = "this is another really long string that should ensure that it makes some sort of dyn alloc for big buf"; const char* appendeddata = "this is another really long string that should ensure that it makes some sort of dyn alloc for big bufstuff"; test_str str1(startdata1); str1.append("stuff"); if(strcmp(str1.c_str(), appendeddata)) error("long append should have resulted in this is another really long string that should ensure that it makes some sort of dyn alloc for big bufstuff\n"); } void check_substring(){ rexy::string test = "this is a test string"; rexy::string test2 = test.substring(5, 7); if(strcmp(test2.c_str(), "is") || test2.length() != 2) error("substring operation should have resulted in 'is'\n"); } void check_string_search(){ rexy::string test1 = "this is a test string"; rexy::string test2 = "string"; auto res = test1.search(test2.create_view()); if(test1.data() + 15 != res){ error("string search operation did not result in a correct result\n"); } } void check_string_insert(){ rexy::string test = "this is a string"; auto it = test.search("string"); if(it == test.end()){ error("string search failed\n"); } test.insert(it - test.begin(), "test ", 5); if(test != "this is a test string" || test.length() != 21){ error("string insert operation failed\n"); } test.insert(0, "wow "); if(test != "wow this is a test string" || test.length() != 25){ error("string insert operation 2 failed\n"); } test.insert(test.length(), " oof"); if(test != "wow this is a test string oof" || test.length() != 29){ error("string insert operation 3 failed\n"); } } void check_string_erase(){ rexy::string test = "this is a test string"; test.erase(0, 5); if(test != "is a test string" || test.length() != 16){ error("string erase operation 1 did not result in a correct result\n"); } test.erase(5, 5); if(test != "is a string" || test.length() != 11){ error("string erase operation 2 did not result in a correct result\n"); } test.erase(9, 2); if(test != "is a stri" || test.length() != 9){ error("string erase operation 3 did not result in a correct result\n"); } test.erase(8, 2); if(test != "is a str" || test.length() != 8){ error("string erase operation 4 did not result in a correct result\n"); } test.pop_back(); if(test != "is a st" || test.length() != 7){ error("string erase operation 5 did not result in a correct result\n"); } } void check_string_replace(){ rexy::string test = "test string"; test.replace(0, 4, "yolo"); if(test != "yolo string"){ error("string replace operation 1 did not result in a correct result\n"); } test = "this is a long string version"_sv; auto it = test.search("long"_sv); if(it == test.end()){ error("string search failed in replace test\n"); } test.replace(it, it+4, "thic"); if(test != "this is a thic string version"){ error("string replace operation 2 did not result in a correct result\n"); } test.replace(test.end() - 7, test.end(), "vrisiod"); if(test != "this is a thic string vrisiod"){ error("string replace operation 3 did not result in a correct result\n"); } test.replace(test.begin(), test.end(), "change"); if(test != "changes a thic string vrisiod"){ error("string replace operation 4 did not result in a correct result\n"); } test = "short"_sv; test.replace(test.begin(), test.end(), "a longer string"); if(test != "a lon"){ error("string replace operation 5 did not result in a correct result\n"); } } #include int main(){ check_empty_construction(); check_short_construction(); check_long_construction(); check_short_assignment(); check_long_assignment(); check_short_append(); check_long_append(); check_substring(); check_string_search(); check_string_insert(); check_string_erase(); check_string_replace(); }