fmt: add more string_view versions of string functions

This commit is contained in:
Megamouse 2025-12-08 03:07:49 +01:00
parent c840c98e9e
commit 27f39d2ac0
36 changed files with 413 additions and 90 deletions

View file

@ -83,7 +83,8 @@ std::string fmt::win_error_to_string(unsigned long error, void* module_handle)
if (FormatMessageW((module_handle ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM) | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
module_handle, error, 0, reinterpret_cast<LPWSTR>(&message_buffer), 0, nullptr))
{
message = fmt::format("%s (0x%x)", fmt::trim(wchar_to_utf8(message_buffer), " \t\n\r\f\v"), error);
const std::string utf8 = wchar_to_utf8(message_buffer);
message = fmt::format("%s (0x%x)", fmt::trim_sv(utf8, " \t\n\r\f\v"), error);
}
else
{
@ -823,6 +824,50 @@ std::vector<std::string> fmt::split(std::string_view source, std::initializer_li
return result;
}
std::vector<std::string_view> fmt::split_sv(std::string_view source, std::initializer_list<std::string_view> separators, bool is_skip_empty)
{
std::vector<std::string_view> result;
for (usz index = 0; index < source.size();)
{
usz pos = -1;
usz sep_size = 0;
for (auto& separator : separators)
{
if (usz pos0 = source.find(separator, index); pos0 < pos)
{
pos = pos0;
sep_size = separator.size();
}
}
if (!sep_size)
{
result.emplace_back(&source[index], source.size() - index);
return result;
}
std::string_view piece = {&source[index], pos - index};
index = pos + sep_size;
if (piece.empty() && is_skip_empty)
{
continue;
}
result.emplace_back(std::move(piece));
}
if (result.empty() && !is_skip_empty)
{
result.emplace_back();
}
return result;
}
std::string fmt::trim(const std::string& source, std::string_view values)
{
const usz begin = source.find_first_not_of(values);
@ -838,6 +883,21 @@ std::string fmt::trim(const std::string& source, std::string_view values)
return source.substr(begin, end + 1 - begin);
}
std::string_view fmt::trim_sv(std::string_view source, std::string_view values)
{
const usz begin = source.find_first_not_of(values);
if (begin == source.npos)
return {};
const usz end = source.find_last_not_of(values);
if (end == source.npos)
return source.substr(begin);
return source.substr(begin, end + 1 - begin);
}
std::string fmt::trim_front(const std::string& source, std::string_view values)
{
const usz begin = source.find_first_not_of(values);
@ -848,12 +908,32 @@ std::string fmt::trim_front(const std::string& source, std::string_view values)
return source.substr(begin);
}
std::string_view fmt::trim_front_sv(std::string_view source, std::string_view values)
{
const usz begin = source.find_first_not_of(values);
if (begin == source.npos)
return {};
return source.substr(begin);
}
void fmt::trim_back(std::string& source, std::string_view values)
{
const usz index = source.find_last_not_of(values);
source.resize(index + 1);
}
std::string_view fmt::trim_back_sv(std::string_view source, std::string_view values)
{
const usz index = source.find_last_not_of(values);
if (index == std::string_view::npos)
return {};
source.remove_suffix(source.size() - (index + 1));
return source;
}
std::string fmt::to_upper(std::string_view string)
{
std::string result;

View file

@ -139,57 +139,90 @@ namespace fmt
// Splits the string into a vector of strings using the separators. The vector may contain empty strings unless is_skip_empty is true.
std::vector<std::string> split(std::string_view source, std::initializer_list<std::string_view> separators, bool is_skip_empty = true);
// Splits the string_view into a vector of string_views using the separators. The vector may contain empty string_views unless is_skip_empty is true.
std::vector<std::string_view> split_sv(std::string_view source, std::initializer_list<std::string_view> separators, bool is_skip_empty = true);
// Removes all preceding and trailing characters specified by 'values' from 'source'.
std::string trim(const std::string& source, std::string_view values = " \t");
// Removes all preceding and trailing characters specified by 'values' from 'source' and returns the result.
std::string_view trim_sv(std::string_view source, std::string_view values = " \t");
// Removes all preceding characters specified by 'values' from 'source'.
std::string trim_front(const std::string& source, std::string_view values = " \t");
// Removes all preceding characters specified by 'values' from 'source' and returns the result.
std::string_view trim_front_sv(std::string_view source, std::string_view values = " \t");
// Removes all trailing characters specified by 'values' from 'source'.
void trim_back(std::string& source, std::string_view values = " \t");
// Removes all trailing characters specified by 'values' from 'source' and returns the result.
std::string_view trim_back_sv(std::string_view source, std::string_view values = " \t");
template <typename T>
std::string merge(const T& source, const std::string& separator)
std::string merge(const T& source, std::string_view separator)
{
if (source.empty())
{
return {};
}
usz total = (source.size() - 1) * separator.size();
for (const auto& s : source)
{
total += s.size();
}
std::string result;
result.reserve(total);
auto it = source.begin();
auto end = source.end();
for (--end; it != end; ++it)
{
result += std::string{*it} + separator;
result.append(*it);
if (!separator.empty())
result.append(separator);
}
return result + std::string{source.back()};
return result.append(source.back());
}
template <typename T>
std::string merge(std::initializer_list<T> sources, const std::string& separator)
std::string merge(std::initializer_list<T> sources, std::string_view separator)
{
if (!sources.size())
{
return {};
}
usz total = (sources.size() - 1) * separator.size();
for (const auto& s : sources)
{
if (s.empty()) continue;
total += s.size() + (s.size() - 1) * separator.size();
}
std::string result;
result.reserve(total);
bool first = true;
for (const auto& v : sources)
{
if (first)
{
result = fmt::merge(v, separator);
first = false;
first = false;
}
else
else if (!separator.empty())
{
result += separator + fmt::merge(v, separator);
result.append(separator);
}
result.append(fmt::merge(v, separator));
}
return result;

View file

@ -27,9 +27,9 @@ void fmt_class_string<cheat_type>::format(std::string& out, u64 arg)
});
}
bool cheat_info::from_str(const std::string& cheat_line)
bool cheat_info::from_str(std::string_view cheat_line)
{
auto cheat_vec = fmt::split(cheat_line, {"@@@"}, false);
const auto cheat_vec = fmt::split(cheat_line, {"@@@"}, false);
s64 val64 = 0;
if (cheat_vec.size() != 5 || !try_to_int64(&val64, cheat_vec[2], 0, cheat_type_max - 1))

View file

@ -28,6 +28,6 @@ struct cheat_info
u32 offset{};
std::string red_script{};
bool from_str(const std::string& cheat_line);
bool from_str(std::string_view cheat_line);
std::string to_str() const;
};