diff --git a/source/base/lib/CMakeLists.txt b/source/base/lib/CMakeLists.txt index a3ce4bf82..f52dd74a7 100644 --- a/source/base/lib/CMakeLists.txt +++ b/source/base/lib/CMakeLists.txt @@ -6,8 +6,9 @@ add_library(tactile::base ALIAS tactile-base) target_sources(tactile-base INTERFACE FILE_SET "HEADERS" BASE_DIRS "inc" FILES "inc/tactile/base/container/buffer.hpp" - "inc/tactile/base/container/string_map.hpp" "inc/tactile/base/container/lookup.hpp" + "inc/tactile/base/container/string.hpp" + "inc/tactile/base/container/string_map.hpp" "inc/tactile/base/document/component_view.hpp" "inc/tactile/base/document/document.hpp" "inc/tactile/base/document/document_visitor.hpp" diff --git a/source/core/lib/inc/tactile/core/util/string_ops.hpp b/source/base/lib/inc/tactile/base/container/string.hpp similarity index 54% rename from source/core/lib/inc/tactile/core/util/string_ops.hpp rename to source/base/lib/inc/tactile/base/container/string.hpp index e3353b4eb..c72ab6111 100644 --- a/source/core/lib/inc/tactile/core/util/string_ops.hpp +++ b/source/base/lib/inc/tactile/base/container/string.hpp @@ -2,20 +2,21 @@ #pragma once +#include // find_if +#include // isspace +#include // locale #include // string #include // string_view -#include "tactile/base/prelude.hpp" #include "tactile/base/util/concepts.hpp" -namespace tactile::core { +namespace tactile { /** * Removes leading and trailing spaces from a given string. * * \note - * This function will only modify strings that have at least one non-space - * character. + * Only strings with at least one non-space character are modified. * * \param str The string to trim. * @@ -23,7 +24,28 @@ namespace tactile::core { * A trimmed string. */ [[nodiscard]] -auto trim_string(std::string_view str) -> std::string; +constexpr auto trim_string(const std::string_view str) -> std::string +{ + std::string trimmed {str}; + + const auto find_first_non_space = [](const auto begin, const auto end) { + return std::find_if(begin, end, [](const char ch) { + return !std::isspace(ch, std::locale::classic()); + }); + }; + + const auto left = find_first_non_space(trimmed.begin(), trimmed.end()); + if (left != trimmed.end()) { + trimmed.erase(trimmed.begin(), left); + } + + const auto right = find_first_non_space(trimmed.rbegin(), trimmed.rend()); + if (right != trimmed.rend()) { + trimmed.erase(right.base(), trimmed.end()); + } + + return trimmed; +} /** * Splits a string into a collection of tokens separated by a given character. @@ -32,15 +54,16 @@ auto trim_string(std::string_view str) -> std::string; * * \param str The full string. * \param separator The character to use as the separator. - * \param callback A callback invoked for each token in the string. The - * function will return immediately if the callback returns - * false. + * \param callback A callback invoked for each token in the string. The function will return + * immediately if this callback returns false. * * \return * True if the function completed without returning early; false otherwise. */ template T> -auto split_string(const std::string_view str, const char separator, const T& callback) -> bool +constexpr auto visit_tokens(const std::string_view str, + const char separator, + const T& callback) -> bool { std::size_t pos = 0; const auto str_length = str.size(); @@ -71,4 +94,4 @@ auto split_string(const std::string_view str, const char separator, const T& cal return true; } -} // namespace tactile::core +} // namespace tactile diff --git a/source/base/test/CMakeLists.txt b/source/base/test/CMakeLists.txt index c7e718254..b93757a4f 100644 --- a/source/base/test/CMakeLists.txt +++ b/source/base/test/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(tactile-base-test) target_sources(tactile-base-test PRIVATE "src/container/lookup_test.cpp" + "src/container/string_test.cpp" "src/io/int_parser_test.cpp" "src/io/tile_io_test.cpp" "src/meta/attribute_test.cpp" diff --git a/source/core/test/src/util/string_ops_test.cpp b/source/base/test/src/container/string_test.cpp similarity index 65% rename from source/core/test/src/util/string_ops_test.cpp rename to source/base/test/src/container/string_test.cpp index b1ddfbd5a..f383c716d 100644 --- a/source/core/test/src/util/string_ops_test.cpp +++ b/source/base/test/src/container/string_test.cpp @@ -1,18 +1,19 @@ // Copyright (C) 2024 Albin Johansson (GNU General Public License v3.0) -#include "tactile/core/util/string_ops.hpp" +#include "tactile/base/container/string.hpp" #include // vector #include -namespace tactile::core { +namespace tactile { +namespace { -/// \trace tactile::core::split_string -TEST(StringOps, SplitStringEmpty) +// tactile::visit_tokens +TEST(String, VisitTokensEmpty) { std::vector tokens {}; - split_string("", '!', [&tokens](const std::string_view token) { + visit_tokens("", '!', [&tokens](const std::string_view token) { tokens.emplace_back(token); return true; }); @@ -20,11 +21,11 @@ TEST(StringOps, SplitStringEmpty) EXPECT_EQ(tokens.size(), 0); } -/// \trace tactile::core::split_string -TEST(StringOps, SplitStringLetters) +// tactile::visit_tokens +TEST(String, VisitTokensLetters) { std::vector tokens {}; - split_string("a:b:c:d", ':', [&tokens](const std::string_view token) { + visit_tokens("a:b:c:d", ':', [&tokens](const std::string_view token) { tokens.emplace_back(token); return true; }); @@ -36,11 +37,11 @@ TEST(StringOps, SplitStringLetters) EXPECT_EQ(tokens.at(3), "d"); } -/// \trace tactile::core::split_string -TEST(StringOps, SplitStringNumbers) +// tactile::visit_tokens +TEST(String, VisitTokensNumbers) { std::vector tokens {}; - split_string("1 200 30 4000", ' ', [&tokens](const std::string_view token) { + visit_tokens("1 200 30 4000", ' ', [&tokens](const std::string_view token) { tokens.emplace_back(token); return true; }); @@ -52,11 +53,11 @@ TEST(StringOps, SplitStringNumbers) EXPECT_EQ(tokens.at(3), "4000"); } -/// \trace tactile::core::split_string -TEST(StringOps, SplitStringWithLeadingSeparator) +// tactile::visit_tokens +TEST(String, VisitTokensWithLeadingSeparator) { std::vector tokens {}; - split_string(".woah", '.', [&tokens](const std::string_view token) { + visit_tokens(".woah", '.', [&tokens](const std::string_view token) { tokens.emplace_back(token); return true; }); @@ -66,11 +67,11 @@ TEST(StringOps, SplitStringWithLeadingSeparator) EXPECT_EQ(tokens.at(1), "woah"); } -/// \trace tactile::core::split_string -TEST(StringOps, SplitStringWithTrailingSeparator) +// tactile::visit_tokens +TEST(String, VisitTokensWithTrailingSeparator) { std::vector tokens {}; - split_string("foobar!", '!', [&tokens](const std::string_view token) { + visit_tokens("foobar!", '!', [&tokens](const std::string_view token) { tokens.emplace_back(token); return true; }); @@ -79,11 +80,11 @@ TEST(StringOps, SplitStringWithTrailingSeparator) EXPECT_EQ(tokens.at(0), "foobar"); } -/// \trace tactile::core::split_string -TEST(StringOps, SplitStringWithEmptyTokens) +// tactile::visit_tokens +TEST(String, VisitTokensWithEmptyTokens) { std::vector tokens {}; - split_string("aaa::a:bb::c", ':', [&tokens](const std::string_view token) { + visit_tokens("aaa::a:bb::c", ':', [&tokens](const std::string_view token) { tokens.emplace_back(token); return true; }); @@ -97,8 +98,8 @@ TEST(StringOps, SplitStringWithEmptyTokens) EXPECT_EQ(tokens.at(5), "c"); } -/// \trace tactile::core::trim_string -TEST(StringOps, TrimString) +// tactile::trim_string +TEST(String, TrimString) { EXPECT_EQ(trim_string(" "), " "); EXPECT_EQ(trim_string(" "), " "); @@ -111,4 +112,5 @@ TEST(StringOps, TrimString) EXPECT_EQ(trim_string(" a b c d "), "a b c d"); } -} // namespace tactile::core +} // namespace +} // namespace tactile diff --git a/source/core/lib/CMakeLists.txt b/source/core/lib/CMakeLists.txt index 812bb4088..70af703ca 100644 --- a/source/core/lib/CMakeLists.txt +++ b/source/core/lib/CMakeLists.txt @@ -109,7 +109,6 @@ target_sources(tactile-core "src/ui/viewport.cpp" "src/ui/widget_manager.cpp" "src/util/string_conv.cpp" - "src/util/string_ops.cpp" "src/util/uuid.cpp" "src/tactile_app.cpp" @@ -232,7 +231,6 @@ target_sources(tactile-core "inc/tactile/core/ui/viewport.hpp" "inc/tactile/core/ui/widget_manager.hpp" "inc/tactile/core/util/string_conv.hpp" - "inc/tactile/core/util/string_ops.hpp" "inc/tactile/core/util/uuid.hpp" "inc/tactile/core/tactile_app.hpp" ) diff --git a/source/core/lib/src/io/ini.cpp b/source/core/lib/src/io/ini.cpp index a3071ab21..34c0d3696 100644 --- a/source/core/lib/src/io/ini.cpp +++ b/source/core/lib/src/io/ini.cpp @@ -8,10 +8,10 @@ #include // getline #include // move +#include "tactile/base/container/string.hpp" #include "tactile/core/debug/assert.hpp" #include "tactile/core/log/logger.hpp" #include "tactile/core/log/set_log_scope.hpp" -#include "tactile/core/util/string_ops.hpp" namespace tactile::core { namespace { diff --git a/source/core/lib/src/util/string_ops.cpp b/source/core/lib/src/util/string_ops.cpp deleted file mode 100644 index 3c2769d43..000000000 --- a/source/core/lib/src/util/string_ops.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2024 Albin Johansson (GNU General Public License v3.0) - -#include "tactile/core/util/string_ops.hpp" - -#include // find_if -#include // isspace -#include // locale - -namespace tactile::core { - -auto trim_string(const std::string_view str) -> std::string -{ - std::string copy {str}; - - const auto find_first_non_space = [](const auto begin, const auto end) { - return std::find_if(begin, end, [](const char ch) { - return !std::isspace(ch, std::locale::classic()); - }); - }; - - const auto left_iter = find_first_non_space(copy.begin(), copy.end()); - if (left_iter != copy.end()) { - copy.erase(copy.begin(), left_iter); - } - - const auto right_iter = find_first_non_space(copy.rbegin(), copy.rend()); - if (right_iter != copy.rend()) { - copy.erase(right_iter.base(), copy.end()); - } - - return copy; -} - -} // namespace tactile::core diff --git a/source/core/test/CMakeLists.txt b/source/core/test/CMakeLists.txt index 7526814ef..80442e312 100644 --- a/source/core/test/CMakeLists.txt +++ b/source/core/test/CMakeLists.txt @@ -53,7 +53,6 @@ target_sources(tactile-core-test "src/ui/imgui_compat_test.cpp" "src/ui/viewport_test.cpp" "src/util/string_conv_test.cpp" - "src/util/string_ops_test.cpp" "src/util/uuid_test.cpp" "src/ir_comparison.cpp" "src/main.cpp"