/* * regex.cpp * * Copyright (C) 2004-2016 by Yevgen Muntyan * * This file is part of medit. medit is free software; you can * redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public * License along with medit. If not, see . */ #include "moocpp/regex.h" #include "mooutils/mooutils-messages.h" #include namespace g { Regex::Regex(GRegex* p) : m_p(p) { } Regex::~Regex() { g_regex_unref(m_p); } Regex::Regex(Regex&& other) : m_p(other.m_p) { other.m_p = nullptr; } Regex& Regex::operator=(Regex&& other) { std::swap(m_p, other.m_p); return *this; } bool Regex::is_valid() const { return m_p != nullptr; } Regex::operator bool() const { return m_p != nullptr; } Regex Regex::compile(const char* pattern, CompileFlags compile_options, MatchFlags match_options, GError** error) { GRegex* p = g_regex_new(pattern, GRegexCompileFlags(compile_options), GRegexMatchFlags(match_options), error); return Regex{p}; } const char* Regex::get_pattern() const { return g_regex_get_pattern(m_p); } int Regex::get_max_backref() const { return g_regex_get_max_backref(m_p); } int Regex::get_capture_count() const { return g_regex_get_capture_count(m_p); } bool Regex::get_has_cr_or_lf() const { return g_regex_get_has_cr_or_lf(m_p); } int Regex::get_max_lookbehind() const { return g_regex_get_max_lookbehind(m_p); } int Regex::get_string_number(const char *name) const { return g_regex_get_string_number(m_p, name); } gstr Regex::escape_string(const char* string, int length) { return gstr::take(g_regex_escape_string(string, length)); } gstr Regex::escape_nul(const char* string, int length) { return gstr::take(g_regex_escape_nul(string, length)); } Regex::CompileFlags Regex::get_compile_flags() const { return CompileFlags(g_regex_get_compile_flags(m_p)); } Regex::MatchFlags Regex::get_match_flags() const { return MatchFlags(g_regex_get_match_flags(m_p)); } bool Regex::match(const char *pattern, const char *string, CompileFlags compile_options, MatchFlags match_options) { return g_regex_match_simple(pattern, string, GRegexCompileFlags(compile_options), GRegexMatchFlags(match_options)); } MatchInfo Regex::match(const char* string, MatchFlags match_options) const { return match(string, -1, 0, match_options, nullptr); } MatchInfo Regex::match(const gstr& string, MatchFlags match_options) const { return match(string.get(), match_options); } MatchInfo Regex::match(const char* string, ssize_t string_len, int start_position, MatchFlags match_options, GError** error) const { GMatchInfo* match_info = nullptr; if (!g_regex_match_full(m_p, string, string_len, start_position, GRegexMatchFlags(match_options), &match_info, error)) return MatchInfo(*this); return MatchInfo(*this, match_info, true); } MatchInfo Regex::match_all(const char* string, MatchFlags match_options) const { return match_all(string, -1, 0, match_options, nullptr); } MatchInfo Regex::match_all(const char* string, ssize_t string_len, int start_position, MatchFlags match_options, GError** error) const { GMatchInfo* match_info = nullptr; if (!g_regex_match_all_full(m_p, string, string_len, start_position, GRegexMatchFlags(match_options), &match_info, error)) return MatchInfo(*this); return MatchInfo(*this, match_info, true); } std::vector Regex::split(const char* pattern, const char* string, CompileFlags compile_options, MatchFlags match_options) { return gstr::take(g_regex_split_simple(pattern, string, GRegexCompileFlags(compile_options), GRegexMatchFlags(match_options))); } std::vector Regex::split(const char* string, MatchFlags match_options) const { return gstr::take(g_regex_split(m_p, string, GRegexMatchFlags(match_options))); } std::vector Regex::split(const char* string, ssize_t string_len, int start_position, MatchFlags match_options, int max_tokens, GError** error) const { return gstr::take(g_regex_split_full(m_p, string, string_len, start_position, GRegexMatchFlags(match_options), max_tokens, error)); } gstr Regex::replace(const char* string, const char* replacement, MatchFlags match_options) const { return replace(string, -1, 0, replacement, match_options, nullptr); } gstr Regex::replace(const char* string, ssize_t string_len, int start_position, const char* replacement, MatchFlags match_options, GError** error) const { return gstr::take(g_regex_replace(m_p, string, string_len, start_position, replacement, GRegexMatchFlags(match_options), error)); } gstr Regex::replace_literal(const char* string, const char* replacement, MatchFlags match_options) const { return replace_literal(string, -1, 0, replacement, match_options, nullptr); } gstr Regex::replace_literal(const char* string, ssize_t string_len, int start_position, const char* replacement, MatchFlags match_options, GError** error) const { return gstr::take(g_regex_replace_literal(m_p, string, string_len, start_position, replacement, GRegexMatchFlags(match_options), error)); } namespace { using EvalFunc = std::function; struct EvalFuncData { const Regex& regex; const EvalFunc& func; EvalFuncData(const Regex& regex, const EvalFunc& func) : regex(regex) , func(func) { } EvalFuncData(const EvalFuncData&) = delete; EvalFuncData& operator=(const EvalFuncData&) = delete; }; static gboolean eval_func(const GMatchInfo* match_info, GString* result, gpointer user_data) { EvalFuncData* data = reinterpret_cast(user_data); gstr replacement; MatchInfo mi(data->regex, const_cast(match_info), false); bool retval = data->func(mi, replacement); if (!replacement.empty()) g_string_append(result, replacement.get()); return retval; } } gstr Regex::replace_eval(const char* string, ssize_t string_len, int start_position, MatchFlags match_options, const std::function& eval, GError** error) const { EvalFuncData data(*this, eval); return gstr::take(g_regex_replace_eval(m_p, string, string_len, start_position, GRegexMatchFlags(match_options), eval_func, &data, error)); } bool Regex::check_replacement(const char* replacement, bool& has_references, GError** error) { gboolean c_has_references; bool retval = g_regex_check_replacement(replacement, &c_has_references, error); has_references = c_has_references; return retval; } MatchInfo::MatchInfo(const Regex& regex) : MatchInfo(regex, nullptr, false) { } MatchInfo::MatchInfo(const Regex& regex, GMatchInfo* p, bool take_ownership) : m_regex(regex) , m_p(p) , m_own(take_ownership) { moo_assert(m_p || !m_own); } MatchInfo::~MatchInfo() { if (m_own) g_match_info_free(m_p); } MatchInfo::MatchInfo(MatchInfo&& other) : m_regex(other.m_regex) , m_p(other.m_p) , m_own(other.m_own) { other.m_own = false; } MatchInfo& MatchInfo::operator=(MatchInfo&& other) { std::swap(m_regex, other.m_regex); std::swap(m_p, other.m_p); std::swap(m_own, other.m_own); return *this; } bool MatchInfo::is_match() const { return m_p != nullptr; } MatchInfo::operator bool() const { return is_match(); } const Regex& MatchInfo::get_regex() const { return m_regex; } const char* MatchInfo::get_string() const { g_return_val_if_fail(m_p != nullptr, nullptr); return g_match_info_get_string(m_p); } bool MatchInfo::next(GError** error) { g_return_val_if_fail(m_own, false); return g_match_info_next(m_p, error); } bool MatchInfo::matches() const { return g_match_info_matches(m_p); } int MatchInfo::get_match_count() const { return g_match_info_get_match_count(m_p); } bool MatchInfo::is_partial_match() const { return g_match_info_is_partial_match(m_p); } gstr MatchInfo::expand_references(const char* string_to_expand, GError** error) const { return gstr::take(g_match_info_expand_references(m_p, string_to_expand, error)); } gstr MatchInfo::fetch(int match_num) const { return gstr::take(g_match_info_fetch(m_p, match_num)); } bool MatchInfo::fetch_pos(int match_num, int& start_pos, int& end_pos) const { return g_match_info_fetch_pos(m_p, match_num, &start_pos, &end_pos); } gstr MatchInfo::fetch_named(const char* name) const { return gstr::take(g_match_info_fetch_named(m_p, name)); } bool MatchInfo::fetch_named_pos(const char* name, int& start_pos, int& end_pos) const { return g_match_info_fetch_named_pos(m_p, name, &start_pos, &end_pos); } gstrvec MatchInfo::fetch_all() const { return gstr::take(g_match_info_fetch_all(m_p)); } } // namespace g