From dfa064399e27c8017a51c8af09de414722de9769 Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Fri, 18 Oct 2024 18:36:32 +0300 Subject: [PATCH] more features on String --- openVulkanoCpp/Data/Containers/String.hpp | 157 +++++++++++++++++++--- tests/StringTest.cpp | 64 +++++++++ 2 files changed, 206 insertions(+), 15 deletions(-) diff --git a/openVulkanoCpp/Data/Containers/String.hpp b/openVulkanoCpp/Data/Containers/String.hpp index 05c70ff..6796a37 100644 --- a/openVulkanoCpp/Data/Containers/String.hpp +++ b/openVulkanoCpp/Data/Containers/String.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -93,21 +94,10 @@ namespace OpenVulkano size_t FindStartIndexOf(const std::string_view& str) const { return m_string.find(str); } size_t FindEndIndexOf(const std::string_view& str) const { return m_string.rfind(str); } - String& Trim() noexcept + String Trim() noexcept { - size_t start = m_string.find_first_not_of(" \t\n\r"); - if (start == std::string::npos) - { - m_string.clear(); - return *this; - } - - size_t end = m_string.find_last_not_of(" \t\n\r"); - - m_string.erase(0, start); - m_string.resize(end - start + 1); - - return *this; + String trimmed = TrimBack(); + return trimmed.TrimFront(); } String& TrimFront() noexcept @@ -119,7 +109,7 @@ namespace OpenVulkano } else { - m_string.erase(0, start); + m_string.erase(0, start); } return *this; } @@ -138,6 +128,143 @@ namespace OpenVulkano return *this; } + std::vector Split(const std::string_view& delimiter) const + { + std::vector result; + size_t start = 0; + size_t end = m_string.find(delimiter); + while (end != std::string::npos) + { + result.push_back(m_string.substr(start, end - start)); + start = end + delimiter.size(); + end = m_string.find(delimiter, start); + } + result.push_back(m_string.substr(start, end)); + return result; + } + + std::pair SplitAtLastOccurrence(const std::string_view& delimiter) const + { + size_t end = m_string.rfind(delimiter); + if (end == std::string::npos) + { + return { m_string, "" }; + } + return { m_string.substr(0, end), m_string.substr(end + delimiter.size()) }; + } + + std::pair SplitAtFirstOccurrence(const std::string_view& delimiter) const + { + size_t end = m_string.find(delimiter); + if (end == std::string::npos) + { + return { m_string, "" }; + } + return { m_string.substr(0, end), m_string.substr(end + delimiter.size()) }; + } + + std::vector SplitAsStringViews(const std::string_view& delimiter) const + { + std::vector result; + size_t start = 0; + size_t end = m_string.find(delimiter); + while (end != std::string::npos) + { + result.push_back(std::string_view(m_string.c_str() + start, end - start)); + start = end + delimiter.size(); + end = m_string.find(delimiter, start); + } + result.push_back( + std::string_view(m_string.c_str() + start, m_string.size() - (start + end + delimiter.size()))); + return result; + } + + std::pair + SplitAtLastOccurenceAsStringViews(const std::string_view& delimiter) const + { + size_t end = m_string.rfind(delimiter); + if (end == std::string::npos) + { + return { m_string, "" }; + } + return { std::string_view(m_string.c_str(), end), + std::string_view(m_string.c_str() + end + delimiter.size(), + m_string.size() - end - delimiter.size()) }; + } + + std::pair + SplitAtFirstOccurenceAsStringViews(const std::string_view& delimiter) const + { + size_t end = m_string.find(delimiter); + if (end == std::string::npos) + { + return { m_string, "" }; + } + return { std::string_view(m_string.c_str(), end), + std::string_view(m_string.c_str() + end + delimiter.size(), + m_string.size() - end - delimiter.size()) }; + } + + static inline constexpr int64_t OctToInt(std::string_view string) + { + int64_t result = 0; + for (int i = 0; i < static_cast(string.length()); i++) + { + char c = string[i]; + if (c == 0) + { + break; + } + if (c == ' ') + { + continue; + } + if (c < '0' || c > '7') + { + return -1; + } + result = result * 8 + c - '0'; + } + return result; + } + + constexpr int64_t OctToInt() { return OctToInt(m_string); } + + static inline constexpr int64_t HexToInt(std::string string) + { + int64_t result = 0; + for (char c: string) + { + if (c == 0) + { + break; + } + if (c == ' ') + { + continue; + } + if (c >= '0' && c <= '9') + { + result = result * 16 + c - '0'; + } + else if (c >= 'A' && c <= 'F') + { + result = result * 16 + c - 'A' + 10; + } + else if (c >= 'a' && c <= 'f') + { + result = result * 16 + c - 'a' + 10; + } + else + { + return -1; + } + } + return result; + } + + constexpr int64_t HexToInt() { return HexToInt(m_string); } + void ToUpper() noexcept { std::transform(m_string.begin(), m_string.end(), m_string.begin(), diff --git a/tests/StringTest.cpp b/tests/StringTest.cpp index a14821b..5f2d7c3 100644 --- a/tests/StringTest.cpp +++ b/tests/StringTest.cpp @@ -215,3 +215,67 @@ TEST_CASE("Clear") str1.Clear(); REQUIRE(str1.Empty()); } + +TEST_CASE("Split") +{ + String str1("Hello,World"); + auto split = str1.Split(","); + REQUIRE(split.size() == 2); + REQUIRE(split[0] == "Hello"); + REQUIRE(split[1] == "World"); +} + +TEST_CASE("SplitAtLastOccurrence") +{ + String str1 = "Hello,World,Georg"; + auto split = str1.SplitAtLastOccurrence(","); + REQUIRE(split.first == "Hello,World"); + REQUIRE(split.second == "Georg"); +} + +TEST_CASE("SplitAtFirstOccurrence") +{ + String str1 = "Hello,World,Georg"; + auto split = str1.SplitAtFirstOccurrence(","); + REQUIRE(split.first == "Hello"); + REQUIRE(split.second == "World,Georg"); +} + +TEST_CASE("SplitAsStringViews") +{ + String str1("Hello,World"); + auto split = str1.SplitAsStringViews(","); + REQUIRE(split.size() == 2); + REQUIRE(split[0] == "Hello"); + REQUIRE(split[1] == "World"); +} + +TEST_CASE("SplitAtFirstOccurrenceAsStringViews") +{ + String str1 = "Hello,World,Georg"; + auto split = str1.SplitAtFirstOccurenceAsStringViews(","); + REQUIRE(split.first == "Hello"); + REQUIRE(split.second == "World,Georg"); +} + +TEST_CASE("SplitAtLastOccurenceAsStringViews") +{ + String str1 = "Hello,World,Georg"; + auto split = str1.SplitAtLastOccurenceAsStringViews(","); + REQUIRE(split.first == "Hello,World"); + REQUIRE(split.second == "Georg"); +} + +TEST_CASE("OctToInt") +{ + String str1("47"); + REQUIRE(str1.OctToInt() == 39); + REQUIRE(String::OctToInt("552") == 362); +} + +TEST_CASE("HexToInt") +{ + String str1("2A"); + REQUIRE(str1.HexToInt() == 42); + REQUIRE(String::HexToInt("FF") == 255); +}