mirror of https://github.com/djcb/mu.git
utils/mu-regex: add move constructor
This commit is contained in:
parent
f3bfdf5add
commit
6f69f5d482
|
@ -39,6 +39,24 @@ test_regex_match()
|
||||||
g_assert_false(rx->matches("axxxxxbqqc"));
|
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
|
static void
|
||||||
test_regex_replace()
|
test_regex_replace()
|
||||||
{
|
{
|
||||||
|
@ -54,6 +72,7 @@ try {
|
||||||
mu_test_init(&argc, &argv);
|
mu_test_init(&argc, &argv);
|
||||||
|
|
||||||
g_test_add_func("/regex/match", test_regex_match);
|
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);
|
g_test_add_func("/regex/replace", test_regex_replace);
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
#define MU_REGEX_HH__
|
#define MU_REGEX_HH__
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#
|
||||||
#include <utils/mu-result.hh>
|
#include <utils/mu-result.hh>
|
||||||
|
#include <utils/mu-utils.hh>
|
||||||
|
|
||||||
namespace Mu {
|
namespace Mu {
|
||||||
/**
|
/**
|
||||||
|
@ -50,19 +52,33 @@ struct Regex {
|
||||||
*/
|
*/
|
||||||
static Result<Regex> make(const std::string& ptrn,
|
static Result<Regex> make(const std::string& ptrn,
|
||||||
GRegexCompileFlags cflags = G_REGEX_DEFAULT,
|
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);
|
return Regex(ptrn.c_str(), cflags, mflags);
|
||||||
} catch (const Error& err) {
|
} catch (const Error& err) {
|
||||||
return Err(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
|
* DTOR
|
||||||
*/
|
*/
|
||||||
~Regex() {
|
~Regex() noexcept { g_clear_pointer(&rx_, g_regex_unref); }
|
||||||
if (rx_)
|
|
||||||
g_regex_unref(rx_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast to the the underlying GRegex*
|
* Cast to the the underlying GRegex*
|
||||||
|
@ -78,15 +94,6 @@ struct Regex {
|
||||||
*/
|
*/
|
||||||
operator bool() const noexcept { return !!rx_; }
|
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=
|
* operator=
|
||||||
*
|
*
|
||||||
|
@ -96,10 +103,25 @@ struct Regex {
|
||||||
*/
|
*/
|
||||||
Regex& operator=(const Regex& other) noexcept {
|
Regex& operator=(const Regex& other) noexcept {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
auto oldrx = rx_;
|
g_clear_pointer(&rx_, g_regex_unref);
|
||||||
rx_ = other.rx_ ? g_regex_ref(other.rx_): nullptr;
|
if (other.rx_)
|
||||||
if (oldrx)
|
rx_ = g_regex_ref(other.rx_);
|
||||||
g_regex_unref(oldrx);
|
}
|
||||||
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -108,14 +130,19 @@ struct Regex {
|
||||||
* Does this regexp match the given string? An unset Regex matches
|
* Does this regexp match the given string? An unset Regex matches
|
||||||
* nothing.
|
* nothing.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str string to test
|
||||||
* @param mflags
|
* @param mflags match flags
|
||||||
*
|
*
|
||||||
* @return true or false
|
* @return true or false
|
||||||
*/
|
*/
|
||||||
bool matches(const std::string& str,
|
bool matches(const std::string& str,
|
||||||
GRegexMatchFlags mflags=G_REGEX_MATCH_DEFAULT) const noexcept {
|
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, {})};
|
repl.c_str(), G_REGEX_MATCH_DEFAULT, {})};
|
||||||
if (!s)
|
if (!s)
|
||||||
throw Err(Error::Code::InvalidArgument, "error in Regex::replace");
|
throw Err(Error::Code::InvalidArgument, "error in Regex::replace");
|
||||||
std::string r{s};
|
return to_string_gchar(std::move(s));
|
||||||
g_free(s);
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GRegex* g_regex() const { return rx_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Regex(const char *ptrn, GRegexCompileFlags cflags, GRegexMatchFlags mflags) {
|
Regex(const char *ptrn, GRegexCompileFlags cflags, GRegexMatchFlags mflags) {
|
||||||
GError *err{};
|
GError *err{};
|
||||||
rx_ = g_regex_new(ptrn, cflags, mflags, &err);
|
if (rx_ = g_regex_new(ptrn, cflags, mflags, &err); !rx_)
|
||||||
if (!rx_)
|
throw Err(Error::Code::InvalidArgument, &err,
|
||||||
throw Err(Error::Code::InvalidArgument,
|
"invalid regexp: '{}'", ptrn);
|
||||||
"invalid regexp: '%s'", 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
|
} // namespace Mu
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue