From 6f69f5d48259975ed0524d153fee3d1dbd615c5e Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 11 Jul 2023 00:30:23 +0300 Subject: [PATCH] utils/mu-regex: add move constructor --- lib/utils/mu-regex.cc | 19 +++++++++ lib/utils/mu-regex.hh | 94 ++++++++++++++++++++++++++++++------------- 2 files changed, 84 insertions(+), 29 deletions(-) diff --git a/lib/utils/mu-regex.cc b/lib/utils/mu-regex.cc index ebb5d42d..9ba3cc69 100644 --- a/lib/utils/mu-regex.cc +++ b/lib/utils/mu-regex.cc @@ -39,6 +39,24 @@ test_regex_match() g_assert_false(rx->matches("axxxxxbqqc")); } + +static void +test_regex_match2() +{ + Regex rx; + { + + std::string foo = "h.llo"; + rx = unwrap(Regex::make(foo.c_str())); + } + + std::string hei = "hei"; + + g_assert_true(rx.matches("hallo")); + g_assert_false(rx.matches(hei)); +} + + static void test_regex_replace() { @@ -54,6 +72,7 @@ try { mu_test_init(&argc, &argv); g_test_add_func("/regex/match", test_regex_match); + g_test_add_func("/regex/match2", test_regex_match2); g_test_add_func("/regex/replace", test_regex_replace); return g_test_run(); diff --git a/lib/utils/mu-regex.hh b/lib/utils/mu-regex.hh index e5519689..409c7d3a 100644 --- a/lib/utils/mu-regex.hh +++ b/lib/utils/mu-regex.hh @@ -20,7 +20,9 @@ #define MU_REGEX_HH__ #include +# #include +#include namespace Mu { /** @@ -50,19 +52,33 @@ struct Regex { */ static Result make(const std::string& ptrn, GRegexCompileFlags cflags = G_REGEX_DEFAULT, - GRegexMatchFlags mflags = G_REGEX_MATCH_DEFAULT) noexcept try { + GRegexMatchFlags mflags = G_REGEX_MATCH_DEFAULT) + noexcept try { return Regex(ptrn.c_str(), cflags, mflags); } catch (const Error& err) { return Err(err); } + + /** + * Copy CTOR + * + * @param other some other Regex + */ + Regex(const Regex& other) noexcept: rx_{} { *this = other; } + + /** + * Move CTOR + * + * @param other some other Regex + */ + Regex(Regex&& other) noexcept: rx_{} { *this = std::move(other); } + + /** * DTOR */ - ~Regex() { - if (rx_) - g_regex_unref(rx_); - } + ~Regex() noexcept { g_clear_pointer(&rx_, g_regex_unref); } /** * Cast to the the underlying GRegex* @@ -78,15 +94,6 @@ struct Regex { */ operator bool() const noexcept { return !!rx_; } - // No need for a move CTOR, copying is cheap (GRegex is ref-counted) - - /** - * Copy CTOR - * - * @param other some other Regex - */ - Regex(const Regex& other) noexcept { *this = other; } - /** * operator= * @@ -96,10 +103,25 @@ struct Regex { */ Regex& operator=(const Regex& other) noexcept { if (this != &other) { - auto oldrx = rx_; - rx_ = other.rx_ ? g_regex_ref(other.rx_): nullptr; - if (oldrx) - g_regex_unref(oldrx); + g_clear_pointer(&rx_, g_regex_unref); + if (other.rx_) + rx_ = g_regex_ref(other.rx_); + } + return *this; + } + + /** + * operator= + * + * @param other move some other object to this one + * + * @return *this + */ + Regex& operator=(Regex&& other) noexcept { + if (this != &other) { + g_clear_pointer(&rx_, g_regex_unref); + rx_ = other.rx_; + other.rx_ = nullptr; } return *this; } @@ -108,14 +130,19 @@ struct Regex { * Does this regexp match the given string? An unset Regex matches * nothing. * - * @param str - * @param mflags + * @param str string to test + * @param mflags match flags * * @return true or false */ bool matches(const std::string& str, GRegexMatchFlags mflags=G_REGEX_MATCH_DEFAULT) const noexcept { - return rx_ ? g_regex_match(rx_, str.c_str(), mflags, {}) : false; + if (!rx_) + return false; + else + return g_regex_match(rx_, str.c_str(), mflags, nullptr); + // strangely, valgrind reports some memory error related to + // the str.c_str(). It *seems* like a false alarm. } /** @@ -132,22 +159,31 @@ struct Regex { repl.c_str(), G_REGEX_MATCH_DEFAULT, {})}; if (!s) throw Err(Error::Code::InvalidArgument, "error in Regex::replace"); - std::string r{s}; - g_free(s); - return r; + return to_string_gchar(std::move(s)); } + const GRegex* g_regex() const { return rx_; } + private: Regex(const char *ptrn, GRegexCompileFlags cflags, GRegexMatchFlags mflags) { GError *err{}; - rx_ = g_regex_new(ptrn, cflags, mflags, &err); - if (!rx_) - throw Err(Error::Code::InvalidArgument, - "invalid regexp: '%s'", ptrn); + if (rx_ = g_regex_new(ptrn, cflags, mflags, &err); !rx_) + throw Err(Error::Code::InvalidArgument, &err, + "invalid regexp: '{}'", ptrn); } - GRegex *rx_{}; + + GRegex *rx_; }; +static inline std::string format_as(const Regex& rx) { + if (auto&& grx{rx.g_regex()}; !grx) + return "//"; + else + return mu_format("/{}/", g_regex_get_pattern(grx)); + +} + + } // namespace Mu