diff --git a/lib/message/mu-message.cc b/lib/message/mu-message.cc index 58102609..e5bd40c2 100644 --- a/lib/message/mu-message.cc +++ b/lib/message/mu-message.cc @@ -289,14 +289,14 @@ extract_tags(const MimeMessage& mime_msg) constexpr std::array, 3> tag_headers = {{ {"X-Label", ' '}, {"X-Keywords", ','}, {"Keywords", ' '} }}; - static const auto strip_rx{std::regex("^\\s+| +$|( )\\s+")}; std::vector tags; seq_for_each(tag_headers, [&](auto&& item) { if (auto&& hdr = mime_msg.header(item.first); hdr) { for (auto&& tagval : split(*hdr, item.second)) { - tags.emplace_back( - std::regex_replace(tagval, strip_rx, "$1")); + tagval.erase(0, tagval.find_first_not_of(' ')); + tagval.erase(tagval.find_last_not_of(' ')+1); + tags.emplace_back(std::move(tagval)); } } }); @@ -631,10 +631,10 @@ fill_document(Message::Private& priv) const auto path{doc.string_value(Field::Id::Path)}; const auto refs{mime_msg.references()}; - const auto& raw_message_id = mime_msg.message_id(); - const auto message_id = raw_message_id.has_value() && !raw_message_id->empty() - ? *raw_message_id - : fake_message_id(path); + const auto& raw_message_id = mime_msg.message_id(); + const auto message_id = raw_message_id.has_value() && !raw_message_id->empty() + ? *raw_message_id + : fake_message_id(path); process_message(mime_msg, path, priv); diff --git a/lib/mu-contacts-cache.cc b/lib/mu-contacts-cache.cc index c4c81468..cef0291b 100644 --- a/lib/mu-contacts-cache.cc +++ b/lib/mu-contacts-cache.cc @@ -25,10 +25,10 @@ #include #include #include -#include #include #include +#include #include using namespace Mu; @@ -59,8 +59,8 @@ struct ContactsCache::Private { ContactUMap contacts_; std::mutex mtx_; - const StringVec personal_plain_; - const std::vector personal_rx_; + const StringVec personal_plain_; + const std::vector personal_rx_; size_t dirty_; @@ -76,8 +76,8 @@ private: StringVec svec; std::copy_if(personal.begin(), personal.end(), std::back_inserter(svec), [&](auto&& p) { - return p.size() < 2 - || p.at(0) != '/' || p.at(p.length() - 1) != '/'; + return p.size() < 2 || p.at(0) != '/' || + p.at(p.length() - 1) != '/'; }); return svec; } @@ -89,18 +89,20 @@ private: * * @return */ - std::vector make_personal_rx(const StringVec& personal) const { - std::vector rxvec; + std::vector make_personal_rx(const StringVec& personal) const { + std::vector rxvec; for(auto&& p: personal) { if (p.size() < 2 || p[0] != '/' || p[p.length()- 1] != '/') continue; // a regex pattern. try { const auto rxstr{p.substr(1, p.length() - 2)}; - rxvec.emplace_back(std::regex( - rxstr, std::regex::basic | std::regex::optimize | - std::regex::icase)); - } catch (const std::regex_error& rex) { + auto opts = static_cast(G_REGEX_OPTIMIZE|G_REGEX_CASELESS); + auto rx = Regex::make(rxstr, opts); + if (!rx) + throw rx.error(); + rxvec.emplace_back(rx.value()); + } catch (const Error& rex) { g_warning("invalid personal address regexp '%s': %s", p.c_str(), rex.what()); @@ -328,8 +330,7 @@ ContactsCache::is_personal(const std::string& addr) const return true; for (auto&& rx : priv_->personal_rx_) { - std::smatch m; // perhaps cache addr in personal_plain_? - if (std::regex_match(addr, m, rx)) + if (rx.matches(addr)) return true; } diff --git a/lib/mu-parser.cc b/lib/mu-parser.cc index de6cc543..3349330a 100644 --- a/lib/mu-parser.cc +++ b/lib/mu-parser.cc @@ -19,12 +19,12 @@ #include "mu-parser.hh" #include -#include #include #include "mu-tokenizer.hh" #include "utils/mu-utils.hh" #include "utils/mu-error.hh" +#include "utils/mu-regex.hh" #include "message/mu-message.hh" using namespace Mu; @@ -64,7 +64,7 @@ struct Parser::Private { Private(const Store& store, Parser::Flags flags) : store_{store}, flags_{flags} {} std::vector process_regex(const std::string& field, - const std::regex& rx) const; + const Regex& rx) const; Mu::Tree term_1(Mu::Tokens& tokens, WarningVec& warnings) const; Mu::Tree term_2(Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const; @@ -194,7 +194,7 @@ process_range(const std::string& field_str, std::vector Parser::Private::process_regex(const std::string& field_str, - const std::regex& rx) const + const Regex& rx) const { const auto field_opt{field_from_name(field_str)}; if (!field_opt) @@ -204,7 +204,7 @@ Parser::Private::process_regex(const std::string& field_str, std::vector terms; store_.for_each_term(field_opt->id, [&](auto&& str) { auto val{str.c_str() + 1}; // strip off the Xapian prefix. - if (std::regex_search(val, rx)) + if (rx.matches(val)) terms.emplace_back(std::move(val)); return true; }); @@ -263,9 +263,11 @@ Parser::Private::regex(const FieldInfoVec& fields, try { Tree tree(Node{Node::Type::OpOr}); - const auto rx = std::regex(rxstr); + const auto rx = Regex::make(rxstr, G_REGEX_OPTIMIZE); + if (!rx) + throw rx.error(); for (const auto& field : fields) { - const auto terms = process_regex(field.field, rx); + const auto terms = process_regex(field.field, *rx); for (const auto& term : terms) { tree.add_child(Tree({Node::Type::ValueAtomic, FieldValue{field.id, term}})); diff --git a/lib/tests/bench-indexer.cc b/lib/tests/bench-indexer.cc index b83bd909..d2a2a180 100644 --- a/lib/tests/bench-indexer.cc +++ b/lib/tests/bench-indexer.cc @@ -21,10 +21,10 @@ #include #include #include -#include #include #include +#include #include #include "mu-maildir.hh" @@ -390,13 +390,15 @@ The archives can be found at: https://lists.cs.wisc.edu/archive/htcondor-users/ --===============0678627779074767862==--)"; - static std::string -message(const std::regex& rx, size_t id) +message(const Regex& rx, size_t id) { char buf[16]; ::snprintf(buf, sizeof(buf), "%zu", id); - return std::regex_replace(test_msg, rx, buf); + + return to_string_gchar( + g_regex_replace(rx, test_msg, -1, 0, buf, + G_REGEX_MATCH_DEFAULT, {})); } struct TestData { @@ -420,7 +422,7 @@ setup(const TestData& tdata) auto res = maildir_mkdir(mdir); g_assert(!!res); } - const auto rx = std::regex("@ID@"); + const auto rx = Regex::make("@ID@"); /* create messages */ for (size_t n = 0; n != tdata.num_messages; ++n) { auto mpath = format("%s/maildir-%zu/cur/msg-%zu:2,S", @@ -428,7 +430,7 @@ setup(const TestData& tdata) n % tdata.num_maildirs, n); std::ofstream stream(mpath); - auto msg = message(rx, n); + auto msg = message(*rx, n); stream.write(msg.c_str(), msg.size()); g_assert_true(stream.good()); } diff --git a/lib/utils/mu-utils.cc b/lib/utils/mu-utils.cc index 4a996dfb..356e5d8c 100644 --- a/lib/utils/mu-utils.cc +++ b/lib/utils/mu-utils.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -261,15 +260,6 @@ Mu::split(const std::string& str, char sepa) return vec; } -std::vector -Mu::split(const std::string& str, const std::regex& sepa_rx) -{ - std::sregex_token_iterator it(str.begin(), str.end(), sepa_rx, -1); - std::sregex_token_iterator end; - - return {it, end}; -} - std::string Mu::join(const std::vector& svec, const std::string& sepa) { diff --git a/lib/utils/mu-utils.hh b/lib/utils/mu-utils.hh index 176bc1b3..41c02faf 100644 --- a/lib/utils/mu-utils.hh +++ b/lib/utils/mu-utils.hh @@ -33,7 +33,6 @@ #include #include #include -#include #include "mu-utils-format.hh" #include "mu-option.hh" @@ -97,16 +96,6 @@ std::vector split(const std::string& str, const std::string& sepa); */ std::vector split(const std::string& str, char sepa); -/** - * Split a string in parts - * - * @param str a string - * @param sepa the separator regex - * - * @return the parts. - */ -std::vector split(const std::string& str, const std::regex& sepa_rx); - /** * Join the strings in svec into a string, separated by sepa * @@ -173,8 +162,6 @@ bool locale_workaround(); */ bool timezone_available(const std::string& tz); - - /** * Well-known runtime paths * diff --git a/lib/utils/tests/test-utils.cc b/lib/utils/tests/test-utils.cc index fcd9a333..a135a9a3 100644 --- a/lib/utils/tests/test-utils.cc +++ b/lib/utils/tests/test-utils.cc @@ -220,9 +220,6 @@ test_split() // char sepa assert_equal_svec(split("axbxc", 'x'), {"a", "b", "c"}); assert_equal_svec(split("axbxcx", 'x'), {"a", "b", "c", ""}); - - // rx sexp - assert_equal_svec(split("axbyc", std::regex("[xy]")), {"a", "b", "c"}); } static void diff --git a/mu/mu-cmd-extract.cc b/mu/mu-cmd-extract.cc index dd4fd872..1318f602 100644 --- a/mu/mu-cmd-extract.cc +++ b/mu/mu-cmd-extract.cc @@ -21,12 +21,11 @@ #include "mu-cmd.hh" #include "utils/mu-util.h" #include "utils/mu-utils.hh" +#include "utils/mu-regex.hh" #include -#include using namespace Mu; - static Result save_part(const Message::Part& part, size_t idx, const Options& opts) { @@ -73,12 +72,13 @@ save_parts(const std::string& path, const std::string& filename_rx, else if (seq_some(opts.extract.parts, [&](auto&& num){return num==partnum;})) return true; - else if (!filename_rx.empty() && part.raw_filename() && - std::regex_match(*part.raw_filename(), - std::regex{filename_rx})) - return true; - else - return false; + else if (!filename_rx.empty() && part.raw_filename()) { + if (auto rx = Regex::make(filename_rx); !rx) + throw rx.error(); + else if (rx->matches(*part.raw_filename())) + return true; + } + return false; }); if (!do_extract)