StringUtil: Add SplitStringIntoArray function template.

This commit is contained in:
Jordan Woyak
2026-02-06 20:14:26 -06:00
parent 84b136c994
commit 97ad5ad1a1
2 changed files with 50 additions and 0 deletions

View File

@@ -12,6 +12,7 @@
#include <iomanip>
#include <limits>
#include <locale>
#include <ranges>
#include <span>
#include <sstream>
#include <string>
@@ -182,6 +183,32 @@ std::from_chars_result FromChars(std::string_view sv, std::floating_point auto&
std::vector<std::string> SplitString(const std::string& str, char delim);
// Returns `nullopt` if subject does not contain exactly (Count - 1) delim.
template <std::size_t Count>
requires(Count > 1)
std::optional<std::array<std::string_view, Count>> SplitStringIntoArray(std::string_view subject,
char delim)
{
std::optional<std::array<std::string_view, Count>> result;
result.emplace();
std::size_t index = 0;
for (auto&& item : subject | std::views::split(delim))
{
// Too many delim.
if (index == Count)
return std::nullopt;
(*result)[index++] = std::string_view{item};
}
// Too few delim.
if (index != Count)
return std::nullopt;
return result;
}
// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"
// This requires forward slashes to be used for the path separators, even on Windows.
bool SplitPath(std::string_view full_path, std::string* path, std::string* filename,

View File

@@ -259,6 +259,29 @@ TEST(StringUtil, CaseInsensitiveContains_OverlappingMatches)
EXPECT_TRUE(Common::CaseInsensitiveContains("ababababa", "bABa"));
}
TEST(StringUtil, SplitStringIntoArray)
{
constexpr auto subject0 = "";
EXPECT_FALSE(SplitStringIntoArray<2>(subject0, '.').has_value());
constexpr auto subject1 = "hello";
EXPECT_FALSE(SplitStringIntoArray<2>(subject1, '.').has_value());
constexpr auto subject2 = "hello.world";
const auto split2 = SplitStringIntoArray<2>(subject2, '.');
EXPECT_TRUE(split2.has_value() && split2->at(1) == "world");
EXPECT_FALSE(SplitStringIntoArray<3>(subject2, '.').has_value());
constexpr auto subject3 = "hello.universe.";
EXPECT_FALSE(SplitStringIntoArray<2>(subject3, '.').has_value());
const auto split3 = SplitStringIntoArray<3>(subject3, '.');
EXPECT_TRUE(split3.has_value() && split3->at(2) == "");
EXPECT_FALSE(SplitStringIntoArray<4>(subject3, '.').has_value());
constexpr auto subject4 = "=";
EXPECT_TRUE(SplitStringIntoArray<2>(subject4, '=').has_value());
}
TEST(StringUtil, CharacterEncodingConversion)
{
// wstring