diff --git a/storm/String.cpp b/storm/String.cpp index e992095..aeb8913 100644 --- a/storm/String.cpp +++ b/storm/String.cpp @@ -374,6 +374,93 @@ const char* SStrStr(const char* string, const char* search) { return substring; } +void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted) { + STORM_ASSERT_VOID(string); + STORM_ASSERT_VOID(*string); + STORM_ASSERT_VOID(buffer || !bufferchars); + STORM_ASSERT_VOID(whitespace); + + int32_t inquotes = 0; + int32_t usedquotes = 0; + auto curstring = *string; + + auto v17 = false; + for (const char* w = whitespace; w && *w; w++) { + if (*w == '"') { + v17 = true; + break; + } + } + + while (*curstring && SStrChr(whitespace, *curstring)) { + if (v17 && *curstring == '"') { + inquotes = 1; + usedquotes = 1; + curstring++; + + break; + } + + curstring++; + } + + uint32_t bufferlen = 0; + + if (*curstring) { + auto curbuffer = buffer; + + while (v17 && *curstring == '"') { + if (bufferlen && !inquotes) { + goto LABEL_35; + } + + curstring++; + usedquotes = 1; + inquotes = inquotes == 0; + + if (!inquotes) { + goto LABEL_35; + } +LABEL_32: + if (!*curstring) { + goto LABEL_35; + } + } + + if (inquotes) { +LABEL_29: + if (curbuffer - buffer < bufferchars) { + bufferlen++; + *curbuffer = *curstring; + curbuffer++; + } + + curstring++; + + goto LABEL_32; + } + + auto v14 = SStrChr(whitespace, *curstring); + + if (!v14) { + goto LABEL_29; + } + + curstring++; + } + +LABEL_35: + if (bufferlen < bufferchars) { + buffer[bufferlen] = 0; + } + + *string = curstring; + + if (quoted) { + *quoted = usedquotes; + } +} + float SStrToFloat(const char* string) { STORM_ASSERT(string); diff --git a/storm/String.hpp b/storm/String.hpp index 8211b4a..0299f40 100644 --- a/storm/String.hpp +++ b/storm/String.hpp @@ -29,6 +29,8 @@ uint32_t SStrPack(char* dest, const char* source, uint32_t destsize); const char* SStrStr(const char* string, const char* search); +void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted); + float SStrToFloat(const char* string); int32_t SStrToInt(const char* string); diff --git a/test/String.cpp b/test/String.cpp index 06d505c..3f9f7d6 100644 --- a/test/String.cpp +++ b/test/String.cpp @@ -244,6 +244,37 @@ TEST_CASE("SStrStr", "[string]") { } } +TEST_CASE("SStrTokenize", "[string]") { + SECTION("finds all tokens in comma-delimited string") { + auto string = "foo,bar,baz"; + char buffer[100] = { 0 }; + const char* tokens[] = { "foo", "bar", "baz" }; + + for (auto& token : tokens) { + SStrTokenize(&string, buffer, 1000, " ,", nullptr); + REQUIRE(!SStrCmp(buffer, token, STORM_MAX_STR)); + } + } + + SECTION("finds all tokens in comma-and-whitespace-delimited string") { + auto string = "foo , bar , baz"; + char buffer[100] = { 0 }; + const char* tokens[] = { "foo", "bar", "baz" }; + + for (auto& token : tokens) { + SStrTokenize(&string, buffer, 1000, " ,", nullptr); + REQUIRE(!SStrCmp(buffer, token, STORM_MAX_STR)); + } + } + + SECTION("finds no tokens empty string") { + auto string = ""; + char buffer[100] = { 0 }; + SStrTokenize(&string, buffer, 1000, " ,", nullptr); + REQUIRE(!SStrCmp(buffer, "", STORM_MAX_STR)); + } +} + TEST_CASE("SStrToFloat", "[string]") { SECTION("converts empty string to float") { auto string = "";