diff --git a/storm/String.cpp b/storm/String.cpp index 0cf003e..0b732f0 100644 --- a/storm/String.cpp +++ b/storm/String.cpp @@ -498,6 +498,38 @@ const char* SStrStr(const char* string, const char* search) { return nullptr; } +char* SStrStrI(char* string, const char* search) { + STORM_VALIDATE_BEGIN; + STORM_VALIDATE(string); + STORM_VALIDATE(search); + STORM_VALIDATE_END; + + size_t searchLength = SStrLen(search); + + for (; *string; string++) { + if (!SStrCmpI(string, search, searchLength)) { + return string; + } + } + return nullptr; +} + +const char* SStrStrI(const char* string, const char* search) { + STORM_VALIDATE_BEGIN; + STORM_VALIDATE(string); + STORM_VALIDATE(search); + STORM_VALIDATE_END; + + size_t searchLength = SStrLen(search); + + for (; *string; string++) { + if (!SStrCmpI(string, search, searchLength)) { + return string; + } + } + return nullptr; +} + void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted) { STORM_VALIDATE_BEGIN; STORM_VALIDATE(string); diff --git a/storm/String.hpp b/storm/String.hpp index d489607..275d663 100644 --- a/storm/String.hpp +++ b/storm/String.hpp @@ -40,6 +40,10 @@ char* SStrStr(char* string, const char* search); const char* SStrStr(const char* string, const char* search); +char* SStrStrI(char* string, const char* search); + +const char* SStrStrI(const char* string, const char* search); + void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted); double SStrToDouble(const char* string); diff --git a/test/String.cpp b/test/String.cpp index 16c8b7e..574b322 100644 --- a/test/String.cpp +++ b/test/String.cpp @@ -440,6 +440,11 @@ TEST_CASE("SStrStr", "[string]") { static_assert(std::is_same::value, "Expect result to be char*"); + SECTION("is case sensitive") { + char* substring = SStrStr(string, "OOBA"); + REQUIRE(substring == nullptr); + } + SECTION("finds substring when it exists at end of string") { char* substring = SStrStr(string, "bar"); REQUIRE(substring == string + 3); @@ -472,6 +477,11 @@ TEST_CASE("SStrStr const", "[string]") { static_assert(std::is_same::value, "Expect result to be const char*"); + SECTION("is case sensitive") { + const char* substring = SStrStr(string, "OOBA"); + REQUIRE(substring == nullptr); + } + SECTION("finds substring when it exists at end of string") { const char* substring = SStrStr(string, "bar"); REQUIRE(substring == string + 3); @@ -498,6 +508,79 @@ TEST_CASE("SStrStr const", "[string]") { } } +TEST_CASE("SStrStrI", "[string]") { + char* string = "foobar"; + + static_assert(std::is_same::value, "Expect result to be char*"); + + SECTION("is case insensitive") { + char* substring = SStrStrI(string, "OOBA"); + REQUIRE(substring == string + 1); + } + + SECTION("finds substring when it exists at end of string") { + char* substring = SStrStrI(string, "bar"); + REQUIRE(substring == string + 3); + } + + SECTION("finds substring when it exists at start of string") { + char* substring = SStrStrI(string, "foo"); + REQUIRE(substring == string); + } + + SECTION("finds substring when search is empty") { + char* substring = SStrStrI(string, ""); + REQUIRE(substring == string); + } + + SECTION("returns nullptr when search does not exist in string") { + char* substring = SStrStrI(string, "xyzzy"); + REQUIRE(substring == nullptr); + } + + SECTION("returns nullptr when given empty string") { + char* string = ""; + char* substring = SStrStrI(string, "bar"); + REQUIRE(substring == nullptr); + } +} + +TEST_CASE("SStrStrI const", "[string]") { + const char* string = "foobar"; + + static_assert(std::is_same::value, "Expect result to be const char*"); + + SECTION("is case insensitive") { + const char* substring = SStrStrI(string, "OOBA"); + REQUIRE(substring == string + 1); + } + + SECTION("finds substring when it exists at end of string") { + const char* substring = SStrStrI(string, "bar"); + REQUIRE(substring == string + 3); + } + + SECTION("finds substring when it exists at start of string") { + const char* substring = SStrStrI(string, "foo"); + REQUIRE(substring == string); + } + + SECTION("finds substring when search is empty") { + const char* substring = SStrStrI(string, ""); + REQUIRE(substring == string); + } + + SECTION("returns nullptr when search does not exist in string") { + const char* substring = SStrStrI(string, "xyzzy"); + REQUIRE(substring == nullptr); + } + + SECTION("returns nullptr when given empty string") { + const char* substring = SStrStrI("", "bar"); + REQUIRE(substring == nullptr); + } +} + TEST_CASE("SStrTokenize", "[string]") { SECTION("finds all tokens in comma-delimited string") { auto string = "foo,bar,baz";