From 0128db9e5cb057c34adaad7c25619107104707e0 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 22 Jan 2023 13:02:44 +0000 Subject: [PATCH] [Minor] Simplify string wrap algorithm Submitted by: @amishmm Closes: #4378 --- src/client/rspamc.cxx | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/src/client/rspamc.cxx b/src/client/rspamc.cxx index a2bf4c783..c725dcd90 100644 --- a/src/client/rspamc.cxx +++ b/src/client/rspamc.cxx @@ -831,41 +831,29 @@ rspamc_print_indented_line(FILE *out, std::string_view line) -> void { static_assert(maxlen > 0, "maxlen must be > 0"); static_assert(maxlen > indent, "maxlen must be more than indent"); + using namespace std::literals; + + constexpr const auto whitespace = " \f\n\r\t\v"sv; + constexpr const auto break_begin = " \f\n\r\t\v?.,;\"'<({[~!@#$%^&*+:-_=/\\|"sv; + constexpr const auto break_end = " \f\n\r\t\v?.,;\"']})>~!@#$%^&*+:-_=/\\|"sv; for (size_t pos = 0; pos < line.size(); ) { - /* - * First, find the longest sequence of words, delimited by space of punctuation, - * and adjust `maxlen` if needed - */ - auto split_len = pos ? (maxlen-indent) : maxlen; - auto word_len = 0ul; - auto suffix = line.substr(pos); - for (;;) { - auto delim_pos = suffix.find_first_of(" \t,;[]():"); - if (word_len + delim_pos + 1 < split_len && delim_pos != std::string_view::npos && delim_pos < suffix.size()) { - word_len += delim_pos + 1; - suffix = suffix.substr(delim_pos + 1); - } - else { - /* Check if we can include one last word */ - if (delim_pos == std::string_view::npos && word_len + suffix.size() < split_len) { - word_len += suffix.size(); - } - break; + auto len = pos ? (maxlen-indent) : maxlen; + auto s = line.substr(pos, len); + if (s.size() == len && // is string long enough? + (pos + s.size()) < line.size() && // reached EOL? + line.find_first_of(break_begin, pos + s.size()) != 0 // new word next? + ) { + auto wrap_at = s.find_last_of(break_end); + if (wrap_at != std::string_view::npos) { + s = line.substr(pos, wrap_at + 1); } } - - if (word_len > 0 && word_len < split_len && line.size() + pos > split_len) { - split_len = word_len; - } - - auto s = line.substr(pos, split_len); if (indent && pos) { fmt::print(out, "{:>{}}", " ", indent); } - fmt::print(out, "{}\n", s); - pos += s.size(); + pos = line.find_first_not_of(whitespace, pos + s.size()); //skip leading whitespace } } -- 2.39.5