From a569bda44579f64fa2676063848c6d2a8c5f7b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Gallou=C3=ABt?= Date: Wed, 18 Feb 2026 08:03:01 +0100 Subject: [PATCH] common : make small string helpers as inline functions (#19693) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also use string_view when it make sense and fix some corner cases. Signed-off-by: Adrien Gallouët --- common/common.cpp | 28 ------------------------- common/common.h | 53 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/common/common.cpp b/common/common.cpp index 32487ddc61..75116ed6f3 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -452,34 +452,6 @@ void string_replace_all(std::string & s, const std::string & search, const std:: s = std::move(builder); } -bool string_ends_with(const std::string_view & str, const std::string_view & suffix) { - return str.size() >= suffix.size() && str.compare(str.size()-suffix.size(), suffix.size(), suffix) == 0; -} - -bool string_remove_suffix(std::string & str, const std::string_view & suffix) { - bool has_suffix = string_ends_with(str, suffix); - if (has_suffix) { - str = str.substr(0, str.size() - suffix.size()); - } - return has_suffix; -} - -size_t string_find_partial_stop(const std::string_view & str, const std::string_view & stop) { - if (!str.empty() && !stop.empty()) { - const char text_last_char = str.back(); - for (int64_t char_index = stop.size() - 1; char_index >= 0; char_index--) { - if (stop[char_index] == text_last_char) { - const auto current_partial = stop.substr(0, char_index + 1); - if (string_ends_with(str, current_partial)) { - return str.size() - char_index - 1; - } - } - } - } - - return std::string::npos; -} - std::string regex_escape(const std::string & s) { static const std::regex special_chars("[.^$|()*+?\\[\\]{}\\\\]"); return std::regex_replace(s, special_chars, "\\$&"); diff --git a/common/common.h b/common/common.h index 6410248377..a4c431172d 100644 --- a/common/common.h +++ b/common/common.h @@ -670,30 +670,55 @@ static std::vector string_split(const std::string & str, char delim) { } template<> -inline std::vector string_split(const std::string & input, char separator) +inline std::vector string_split(const std::string & str, char delim) { std::vector parts; size_t begin_pos = 0; - size_t separator_pos = input.find(separator); - while (separator_pos != std::string::npos) { - std::string part = input.substr(begin_pos, separator_pos - begin_pos); + size_t delim_pos = str.find(delim); + while (delim_pos != std::string::npos) { + std::string part = str.substr(begin_pos, delim_pos - begin_pos); parts.emplace_back(part); - begin_pos = separator_pos + 1; - separator_pos = input.find(separator, begin_pos); + begin_pos = delim_pos + 1; + delim_pos = str.find(delim, begin_pos); } - parts.emplace_back(input.substr(begin_pos, separator_pos - begin_pos)); + parts.emplace_back(str.substr(begin_pos)); return parts; } -inline bool string_starts_with(const std::string & str, - const std::string & prefix) { // While we wait for C++20's std::string::starts_with... - return str.rfind(prefix, 0) == 0; +// remove when moving to c++20 +inline bool string_starts_with(std::string_view str, std::string_view prefix) { + return str.size() >= prefix.size() && + str.compare(0, prefix.size(), prefix) == 0; } -// While we wait for C++20's std::string::ends_with... -bool string_ends_with(const std::string_view & str, const std::string_view & suffix); -bool string_remove_suffix(std::string & str, const std::string_view & suffix); -size_t string_find_partial_stop(const std::string_view & str, const std::string_view & stop); +// remove when moving to c++20 +inline bool string_ends_with(std::string_view str, std::string_view suffix) { + return str.size() >= suffix.size() && + str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +inline bool string_remove_suffix(std::string & str, std::string_view suffix) { + if (string_ends_with(str, suffix)) { + str.resize(str.size() - suffix.size()); + return true; + } + return false; +} + +inline size_t string_find_partial_stop(std::string_view str, std::string_view stop) { + if (!str.empty() && !stop.empty()) { + const size_t max_len = std::min(str.size(), stop.size()); + const char last_char = str.back(); + for (size_t len = max_len; len > 0; --len) { + if (stop[len - 1] == last_char) { + if (string_ends_with(str, stop.substr(0, len))) { + return str.size() - len; + } + } + } + } + return std::string::npos; +} bool string_parse_kv_override(const char * data, std::vector & overrides); void string_process_escapes(std::string & input);