[vte/wip/regex-builtins: 1/3] regex: Make regex a C++ class



commit 0e22309d9cec3972da1543377b66d40f7507d71a
Author: Christian Persch <chpe src gnome org>
Date:   Wed May 8 17:35:07 2019 +0200

    regex: Make regex a C++ class
    
    Make regex a C++ class and the public VteRegex only a wrapper.

 .dir-locals.el          |   4 +
 src/meson.build         |   7 +-
 src/regex.cc            | 238 +++++++++++++++++++++++++++++++++++++++
 src/regex.hh            |  83 ++++++++++++++
 src/vtegtk.cc           |  18 +--
 src/vtepcre2.h          |   9 +-
 src/vteregex.cc         | 292 ++++++++----------------------------------------
 src/vteregexinternal.hh |  21 ++--
 8 files changed, 400 insertions(+), 272 deletions(-)
---
diff --git a/.dir-locals.el b/.dir-locals.el
index 46a2b10f..b611d45c 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -13,3 +13,7 @@
               (c-basic-offset . 2)
               (tab-width . 2)
               (show-trailing-whitespace . t))))
+
+(defun my-c-setup ()
+   (c-set-offset 'innamespace [0]))
+(add-hook 'c++-mode-hook 'my-c-setup)
diff --git a/src/meson.build b/src/meson.build
index 4dc6a86b..2ce7d6e2 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -49,12 +49,17 @@ parser_sources = files(
   'parser.hh',
 )
 
+regex_sources = files(
+  'regex.cc',
+  'regex.hh'
+)
+
 utf8_sources = files(
   'utf8.cc',
   'utf8.hh',
 )
 
-libvte_common_sources = debug_sources + modes_sources + parser_sources + utf8_sources + files(
+libvte_common_sources = debug_sources + modes_sources + parser_sources + regex_sources + utf8_sources + 
files(
   'attr.hh',
   'buffer.h',
   'caps.hh',
diff --git a/src/regex.cc b/src/regex.cc
new file mode 100644
index 00000000..5be07a46
--- /dev/null
+++ b/src/regex.cc
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2015, 2019 Christian Persch
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "regex.hh"
+#include "vte/vteenums.h"
+#include "vte/vteregex.h"
+
+
+#include <cassert>
+
+namespace vte {
+
+namespace base {
+
+static bool
+set_gerror_from_pcre_error(int errcode,
+                           GError **error)
+{
+        PCRE2_UCHAR8 buf[128];
+        int n = pcre2_get_error_message_8(errcode, buf, sizeof(buf));
+        assert(n >= 0);
+        g_set_error_literal(error, VTE_REGEX_ERROR, errcode, (char const*)buf);
+        return false;
+}
+
+Regex*
+Regex::ref() noexcept
+{
+        g_atomic_int_inc(&m_refcount);
+        return this;
+}
+
+void
+Regex::unref() noexcept
+{
+        if (g_atomic_int_dec_and_test(&m_refcount))
+                delete this;
+}
+
+bool
+Regex::check_pcre_config_unicode(GError** error)
+{
+        /* Check library compatibility */
+        guint32 v;
+        int r = pcre2_config_8(PCRE2_CONFIG_UNICODE, &v);
+        if (r != 0 || v != 1) {
+                g_set_error(error, VTE_REGEX_ERROR, VTE_REGEX_ERROR_INCOMPATIBLE,
+                            "PCRE2 library was built without unicode support");
+                return false;
+        }
+
+        return true;
+}
+
+bool
+Regex::check_pcre_config_jit(void)
+{
+        static bool warned = false;
+
+        char s[256];
+        int r = pcre2_config_8(PCRE2_CONFIG_JITTARGET, &s);
+        if (r == PCRE2_ERROR_BADOPTION && !warned) {
+                g_printerr("PCRE2 library was built without JIT support\n");
+                warned = true;
+        }
+
+        return r >= 1;
+}
+
+Regex*
+Regex::compile(Regex::Purpose purpose,
+               char const* pattern,
+               ssize_t pattern_length,
+               uint32_t flags,
+               GError** error)
+{
+
+        assert(pattern != nullptr || pattern_length == 0);
+        assert(error == nullptr || *error == nullptr);
+
+        if (!check_pcre_config_unicode(error))
+                return nullptr;
+
+        int errcode;
+        PCRE2_SIZE erroffset;
+        auto code = pcre2_compile_8((PCRE2_SPTR8)pattern,
+                                    pattern_length >= 0 ? pattern_length : PCRE2_ZERO_TERMINATED,
+                                    (uint32_t)flags |
+                                    PCRE2_UTF |
+                                    (flags & PCRE2_UTF ? PCRE2_NO_UTF_CHECK : 0) |
+                                    PCRE2_NEVER_BACKSLASH_C |
+                                    PCRE2_USE_OFFSET_LIMIT,
+                                    &errcode, &erroffset,
+                                    nullptr);
+
+        if (code == nullptr) {
+                set_gerror_from_pcre_error(errcode, error);
+                g_prefix_error(error, "Failed to compile pattern to regex at offset %" G_GSIZE_FORMAT ":",
+                               erroffset);
+                return nullptr;
+        }
+
+        return new Regex{code, purpose};
+}
+
+/*
+ * Regex::jit:
+ * @flags: JIT flags
+ *
+ * If the platform supports JITing, JIT compiles the regex.
+ *
+ * Returns: %true if JITing succeeded (or PCRE2 was built without
+ *   JIT support), or %false with @error filled in
+ */
+bool
+Regex::jit(uint32_t flags,
+           GError** error)
+{
+        if (!check_pcre_config_jit())
+                return TRUE;
+
+        int r = pcre2_jit_compile_8(code(), flags);
+        if (r < 0)
+                return set_gerror_from_pcre_error(r, error);
+
+        return true;
+}
+
+/*
+ * Regex::jited:
+ *
+ * Note: We can't tell if the regex has been JITed for a particular mode,
+ * just if it has been JITed at all.
+ *
+ * Returns: %true iff the regex has been JITed
+ */
+bool
+Regex::jited() const noexcept
+{
+        PCRE2_SIZE s;
+        int r = pcre2_pattern_info_8(code(), PCRE2_INFO_JITSIZE, &s);
+
+        return r == 0 && s != 0;
+}
+
+/*
+ * Regex::has_compile_flags:
+ * @flags:
+ *
+ * Returns: true if the compile flags include all of @flags.
+ */
+bool
+Regex::has_compile_flags(uint32_t flags) const noexcept
+{
+        uint32_t v;
+        int r = pcre2_pattern_info_8(code(), PCRE2_INFO_ARGOPTIONS, &v);
+
+        return r == 0 ? ((v & flags) == flags) : false;
+}
+
+/*
+ * Regex::substitute:
+ * @subject: the subject string
+ * @replacement: the replacement string
+ * @flags: PCRE2 match flags
+ * @error: (nullable): return location for a #GError, or %NULL
+ *
+ * See man:pcre2api(3) on pcre2_substitute() for more information.
+ *
+ * Returns: (transfer full): the substituted string, or %NULL
+ *   if an error occurred
+ */
+char*
+Regex::substitute(char const* subject,
+                  char const* replacement,
+                  uint32_t flags,
+                  GError** error) const noexcept
+{
+        assert(subject != nullptr);
+        assert(replacement != nullptr);
+        assert (!(flags & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH));
+
+        uint8_t outbuf[2048];
+        PCRE2_SIZE outlen = sizeof(outbuf);
+        int r = pcre2_substitute_8(code(),
+                                   (PCRE2_SPTR8)subject, PCRE2_ZERO_TERMINATED,
+                                   0 /* start offset */,
+                                   flags | PCRE2_SUBSTITUTE_OVERFLOW_LENGTH,
+                                   nullptr /* match data */,
+                                   nullptr /* match context */,
+                                   (PCRE2_SPTR8)replacement, PCRE2_ZERO_TERMINATED,
+                                   (PCRE2_UCHAR8*)outbuf, &outlen);
+
+        if (r >= 0)
+                return g_strndup((char*)outbuf, outlen);
+
+        if (r == PCRE2_ERROR_NOMEMORY) {
+                /* The buffer was not large enough; allocated a buffer of the
+                 * required size and try again. Note that @outlen as returned
+                 * from pcre2_substitute_8() above includes the trailing \0.
+                 */
+                uint8_t *outbuf2 = (uint8_t*)g_malloc(outlen);
+                r = pcre2_substitute_8(code(),
+                                       (PCRE2_SPTR8)subject, PCRE2_ZERO_TERMINATED,
+                                       0 /* start offset */,
+                                       flags | PCRE2_SUBSTITUTE_OVERFLOW_LENGTH,
+                                       nullptr /* match data */,
+                                       nullptr /* match context */,
+                                       (PCRE2_SPTR8)replacement, PCRE2_ZERO_TERMINATED,
+                                       (PCRE2_UCHAR8*)outbuf2, &outlen);
+                if (r >= 0)
+                        return (char*)outbuf2;
+
+                g_free(outbuf2);
+       }
+
+        set_gerror_from_pcre_error(r, error);
+        return nullptr;
+}
+
+} // namespace base
+} // namespace vte
diff --git a/src/regex.hh b/src/regex.hh
new file mode 100644
index 00000000..4cb92a04
--- /dev/null
+++ b/src/regex.hh
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2015, 2019 Christian Persch
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <glib.h>
+
+#include "vtepcre2.h"
+
+namespace vte {
+
+namespace base {
+
+class Regex {
+public:
+        enum class Purpose {
+               eMatch,
+               eSearch,
+        };
+
+        static bool check_pcre_config_unicode(GError** error);
+        static bool check_pcre_config_jit(void);
+        static Regex* compile(Purpose purpose,
+                              char const* pattern,
+                              ssize_t pattern_length,
+                              uint32_t flags,
+                              GError** error);
+
+private:
+        mutable volatile int m_refcount{1};
+        std::unique_ptr<pcre2_code_8, decltype(&pcre2_code_free_8)> m_code;
+        Purpose m_purpose;
+
+public:
+        Regex(pcre2_code_8* code,
+              Purpose purpose) noexcept :
+                m_code{code, &pcre2_code_free_8},
+                m_purpose{purpose}
+        { }
+
+        Regex(Regex const&) = delete;
+        Regex(Regex&&) = delete;
+        Regex operator=(Regex const&) = delete;
+        Regex operator=(Regex&&) = delete;
+
+        Regex* ref() noexcept;
+        void unref() noexcept;
+
+        pcre2_code_8* code() const noexcept { return m_code.get(); }
+        constexpr inline bool has_purpose(Purpose purpose) const noexcept { return m_purpose == purpose; }
+        bool has_compile_flags(uint32_t flags ) const noexcept;
+
+        bool jit(uint32_t flags,
+                 GError** error) noexcept;
+
+        bool jited() const noexcept;
+
+        char* substitute(char const* subject,
+                         char const* replacement,
+                         uint32_t flags,
+                         GError** error) const noexcept;
+
+}; // class Regex
+
+} // namespace base
+
+} // namespace vte
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index c47a5c4a..bbaac158 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -1925,8 +1925,8 @@ vte_terminal_match_add_gregex(VteTerminal *terminal,
 {
         g_return_val_if_fail(gregex != NULL, -1);
 
-        auto regex = _vte_regex_new_gregex(VteRegexPurpose::match, gregex);
-        if (regex == NULL)
+        auto regex = _vte_regex_new_gregex(vte::base::Regex::Purpose::eMatch, gregex);
+        if (regex == nullptr)
                 return -1;
 
         auto rv = vte_terminal_match_add_regex(terminal, regex,
@@ -1958,8 +1958,8 @@ vte_terminal_match_add_regex(VteTerminal *terminal,
 
        g_return_val_if_fail(VTE_IS_TERMINAL(terminal), -1);
        g_return_val_if_fail(regex != NULL, -1);
-        g_return_val_if_fail(_vte_regex_has_purpose(regex, VteRegexPurpose::match), -1);
-        g_warn_if_fail(_vte_regex_get_compile_flags(regex) & PCRE2_MULTILINE);
+        g_return_val_if_fail(_vte_regex_has_purpose(regex, vte::base::Regex::Purpose::eMatch), -1);
+        g_warn_if_fail(_vte_regex_has_multiline_compile_flag(regex));
 
         auto impl = IMPL(terminal);
 
@@ -2084,8 +2084,8 @@ vte_terminal_event_check_regex_simple(VteTerminal *terminal,
         g_return_val_if_fail(event != NULL, FALSE);
         g_return_val_if_fail(regexes != NULL || n_regexes == 0, FALSE);
         for (gsize i = 0; i < n_regexes; i++) {
-                g_return_val_if_fail(_vte_regex_has_purpose(regexes[i], VteRegexPurpose::match), -1);
-                g_warn_if_fail(_vte_regex_get_compile_flags(regexes[i]) & PCRE2_MULTILINE);
+                g_return_val_if_fail(_vte_regex_has_purpose(regexes[i], vte::base::Regex::Purpose::eMatch), 
-1);
+                g_warn_if_fail(_vte_regex_has_multiline_compile_flag(regexes[i]));
         }
         g_return_val_if_fail(matches != NULL, FALSE);
 
@@ -2263,8 +2263,8 @@ vte_terminal_search_set_regex (VteTerminal *terminal,
                                guint32      flags)
 {
         g_return_if_fail(VTE_IS_TERMINAL(terminal));
-        g_return_if_fail(regex == nullptr || _vte_regex_has_purpose(regex, VteRegexPurpose::search));
-        g_warn_if_fail(regex == nullptr || _vte_regex_get_compile_flags(regex) & PCRE2_MULTILINE);
+        g_return_if_fail(regex == nullptr || _vte_regex_has_purpose(regex, 
vte::base::Regex::Purpose::eSearch));
+        g_warn_if_fail(regex == nullptr || _vte_regex_has_multiline_compile_flag(regex));
 
         IMPL(terminal)->search_set_regex(regex, flags);
 }
@@ -2303,7 +2303,7 @@ vte_terminal_search_set_gregex (VteTerminal *terminal,
 {
         VteRegex *regex = nullptr;
         if (gregex)
-                regex = _vte_regex_new_gregex(VteRegexPurpose::search, gregex);
+                regex = _vte_regex_new_gregex(vte::base::Regex::Purpose::eSearch, gregex);
 
         vte_terminal_search_set_regex(terminal, regex,
                                       _vte_regex_translate_gregex_match_flags(gflags));
diff --git a/src/vtepcre2.h b/src/vtepcre2.h
index ddca5ff6..1094edf0 100644
--- a/src/vtepcre2.h
+++ b/src/vtepcre2.h
@@ -19,9 +19,10 @@
 
 #define PCRE2_CODE_UNIT_WIDTH 0
 #include <pcre2.h>
+#include <cstdint>
 
 /* Assert compatibility of PCRE2 and GLib types */
-G_STATIC_ASSERT(sizeof(PCRE2_UCHAR8) == sizeof (guint8));
-G_STATIC_ASSERT(sizeof(PCRE2_SIZE) == sizeof (gsize));
-G_STATIC_ASSERT(PCRE2_UNSET == (gsize)-1);
-G_STATIC_ASSERT(PCRE2_ZERO_TERMINATED == (gsize)-1);
+static_assert(sizeof(PCRE2_UCHAR8) == sizeof (uint8_t), "PCRE2_UCHAR2 has wrong size");
+static_assert(sizeof(PCRE2_SIZE) == sizeof (size_t), "PCRE2_SIZE has wrong size");
+static_assert(PCRE2_UNSET == (size_t)-1, "PCRE2_UNSET has wrong value");
+static_assert(PCRE2_ZERO_TERMINATED == (size_t)-1, "PCRE2_ZERO_TERMINATED has wrong value");
diff --git a/src/vteregex.cc b/src/vteregex.cc
index b06e5e7d..75f33e7b 100644
--- a/src/vteregex.cc
+++ b/src/vteregex.cc
@@ -29,17 +29,11 @@
 #include "vteregex.h"
 #include "vtepcre2.h"
 
+#include "regex.hh"
 #include "vteregexinternal.hh"
 
-struct _VteRegex {
-        volatile int ref_count;
-        VteRegexPurpose purpose;
-        pcre2_code_8 *code;
-};
-
-#define DEFAULT_COMPILE_OPTIONS (PCRE2_UTF)
-#define JIT_OPTIONS (PCRE2_JIT_COMPLETE)
-#define DEFAULT_MATCH_OPTIONS (0)
+#define WRAPPER(impl) (reinterpret_cast<VteRegex*>(impl))
+#define IMPL(wrapper) (reinterpret_cast<vte::base::Regex*>(wrapper))
 
 /* GRegex translation */
 
@@ -68,41 +62,7 @@ translate_flags(FlagTranslation const* const table,
         *pflagsptr = pflags;
 }
 
-/* internal */
-
-static VteRegex *
-regex_new(pcre2_code_8 *code,
-          VteRegexPurpose purpose)
-{
-        VteRegex *regex;
-
-        regex = g_slice_new(VteRegex);
-        regex->ref_count = 1;
-        regex->purpose = purpose;
-        regex->code = code;
-
-        return regex;
-}
-
-static void
-regex_free(VteRegex *regex)
-{
-        pcre2_code_free_8(regex->code);
-        g_slice_free(VteRegex, regex);
-}
-
-static gboolean
-set_gerror_from_pcre_error(int errcode,
-                           GError **error)
-{
-        PCRE2_UCHAR8 buf[128];
-        int n;
-
-        n = pcre2_get_error_message_8(errcode, buf, sizeof (buf));
-        g_assert(n >= 0);
-        g_set_error_literal(error, VTE_REGEX_ERROR, errcode, (const char*)buf);
-        return FALSE;
-}
+/* Type registration */
 
 #pragma GCC diagnostic push
 #if defined(__GNUC__) && !defined(__clang__)
@@ -125,11 +85,9 @@ G_DEFINE_QUARK(vte-regex-error, vte_regex_error)
 VteRegex *
 vte_regex_ref(VteRegex *regex)
 {
-        g_return_val_if_fail (regex, NULL);
-
-        g_atomic_int_inc (&regex->ref_count);
+        g_return_val_if_fail(regex != nullptr, nullptr);
 
-        return regex;
+        return WRAPPER(IMPL(regex)->ref());
 }
 
 /**
@@ -142,86 +100,26 @@ vte_regex_ref(VteRegex *regex)
  * Returns: %NULL
  */
 VteRegex *
-vte_regex_unref(VteRegex *regex)
-{
-        g_return_val_if_fail (regex, NULL);
-
-        if (g_atomic_int_dec_and_test (&regex->ref_count))
-                regex_free (regex);
-
-        return NULL;
-}
-
-static gboolean
-check_pcre_config_unicode(GError** error)
+vte_regex_unref(VteRegex* regex)
 {
-        /* Check library compatibility */
-        guint32 v;
-        int r = pcre2_config_8(PCRE2_CONFIG_UNICODE, &v);
-        if (r != 0 || v != 1) {
-                g_set_error(error, VTE_REGEX_ERROR, VTE_REGEX_ERROR_INCOMPATIBLE,
-                            "PCRE2 library was built without unicode support");
-                return FALSE;
-        }
+        g_return_val_if_fail(regex != nullptr, nullptr);
 
-        return TRUE;
+        IMPL(regex)->unref();
+        return nullptr;
 }
 
-static gboolean
-check_pcre_config_jit(void)
+static VteRegex*
+vte_regex_new(vte::base::Regex::Purpose purpose,
+              char const* pattern,
+              ssize_t pattern_length,
+              uint32_t flags,
+              GError** error)
 {
-        static gboolean warned = FALSE;
-
-        char s[256];
-        int r = pcre2_config_8(PCRE2_CONFIG_JITTARGET, &s);
-        if (r == PCRE2_ERROR_BADOPTION && !warned) {
-                g_printerr("PCRE2 library was built without JIT support\n");
-                warned = TRUE;
-        }
-
-        return r >= 1;
+        return WRAPPER(vte::base::Regex::compile(purpose, pattern, pattern_length, flags, error));
 }
 
-static VteRegex *
-vte_regex_new(VteRegexPurpose purpose,
-              const char *pattern,
-              gssize      pattern_length,
-              guint32     flags,
-              GError    **error)
-{
-        pcre2_code_8 *code;
-        int errcode;
-        PCRE2_SIZE erroffset;
-
-        g_return_val_if_fail(pattern != NULL, NULL);
-        g_return_val_if_fail(pattern_length >= -1, NULL);
-        g_return_val_if_fail(error == NULL || *error == NULL, NULL);
-
-        if (!check_pcre_config_unicode(error))
-                return FALSE;
-
-        code = pcre2_compile_8((PCRE2_SPTR8)pattern,
-                               pattern_length >= 0 ? pattern_length : PCRE2_ZERO_TERMINATED,
-                               (uint32_t)flags |
-                               PCRE2_UTF |
-                               (flags & PCRE2_UTF ? PCRE2_NO_UTF_CHECK : 0) |
-                               PCRE2_NEVER_BACKSLASH_C |
-                               PCRE2_USE_OFFSET_LIMIT,
-                               &errcode, &erroffset,
-                               NULL);
-
-        if (code == nullptr) {
-                set_gerror_from_pcre_error(errcode, error);
-                g_prefix_error(error, "Failed to compile pattern to regex at offset %" G_GSIZE_FORMAT ":",
-                               erroffset);
-                return NULL;
-        }
-
-        return regex_new(code, purpose);
-}
-
-VteRegex *
-_vte_regex_new_gregex(VteRegexPurpose purpose,
+VteRegex*
+_vte_regex_new_gregex(vte::base::Regex::Purpose purpose,
                       GRegex *gregex)
 {
         g_return_val_if_fail(gregex != NULL, NULL);
@@ -250,9 +148,9 @@ _vte_regex_new_gregex(VteRegexPurpose purpose,
                 g_warning("Incompatible GRegex compile flags left untranslated: %08x", gflags);
         }
 
-        GError *err = nullptr;
+        GError* err = nullptr;
         auto regex = vte_regex_new(purpose, g_regex_get_pattern(gregex), -1, pflags, &err);
-        if (regex == NULL) {
+        if (regex == nullptr) {
                 g_warning("Failed to translated GRegex: %s", err->message);
                 g_error_free(err);
         }
@@ -306,7 +204,7 @@ vte_regex_new_for_match(const char *pattern,
                         guint32     flags,
                         GError    **error)
 {
-        return vte_regex_new(VteRegexPurpose::match,
+        return vte_regex_new(vte::base::Regex::Purpose::eMatch,
                              pattern, pattern_length,
                              flags,
                              error);
@@ -337,62 +235,12 @@ vte_regex_new_for_search(const char *pattern,
                          guint32     flags,
                          GError    **error)
 {
-        return vte_regex_new(VteRegexPurpose::search,
+        return vte_regex_new(vte::base::Regex::Purpose::eSearch,
                              pattern, pattern_length,
                              flags,
                              error);
 }
 
-#if 0
-/*
- * vte_regex_new_pcre:
- * @code: a #pcre2_code_8
- *
- * Creates a new #VteRegex for @code. @code must have been compiled with
- * %PCRE2_UTF and %PCRE2_NEVER_BACKSLASH_C.
- *
- * Returns: (transfer full): a newly created #VteRegex, or %NULL if VTE
- *   was not compiled with PCRE2 support.
- */
-VteRegex *
-vte_regex_new_pcre(pcre2_code_8 *code,
-                   GError      **error)
-{
-        guint32 flags;
-
-        g_return_val_if_fail(code != NULL, NULL);
-        g_return_val_if_fail(error == NULL || *error == NULL, NULL);
-
-        pcre2_pattern_info_8(code, PCRE2_INFO_ALLOPTIONS, &flags);
-        g_return_val_if_fail(flags & PCRE2_UTF, NULL);
-        g_return_val_if_fail(flags & PCRE2_NEVER_BACKSLASH_C, NULL);
-
-        return regex_new(code);
-}
-#endif
-
-gboolean
-_vte_regex_has_purpose(VteRegex *regex,
-                       VteRegexPurpose purpose)
-{
-        return regex->purpose == purpose;
-}
-
-/*
- * _vte_regex_get_pcre:
- * @regex: a #VteRegex
- *
- *
- * Returns: the #pcre2_code_8 from @regex
- */
-const pcre2_code_8 *
-_vte_regex_get_pcre(VteRegex const* regex)
-{
-        g_return_val_if_fail(regex != NULL, NULL);
-
-        return regex->code;
-}
-
 /**
  * vte_regex_jit:
  * @regex: a #VteRegex
@@ -407,55 +255,42 @@ vte_regex_jit(VteRegex *regex,
               guint     flags,
               GError  **error)
 {
-        int r;
-
-        g_return_val_if_fail(regex != NULL, FALSE);
+        g_return_val_if_fail(regex != nullptr, false);
 
-        if (!check_pcre_config_jit())
-                return TRUE;
+        return IMPL(regex)->jit(flags, error);
+}
 
-        r = pcre2_jit_compile_8(regex->code, flags);
-        if (r < 0)
-                return set_gerror_from_pcre_error(r, error);
+bool
+_vte_regex_has_purpose(VteRegex *regex,
+                       vte::base::Regex::Purpose purpose)
+{
+        g_return_val_if_fail(regex != nullptr, false);
 
-        return TRUE;
+        return IMPL(regex)->has_purpose(purpose);
 }
 
-/*
- * _vte_regex_get_jited:
- *
- * Note: We can't tell if the regex has been JITed for a particular mode,
- * just if it has been JITed at all.
- *
- * Returns: %TRUE iff the regex has been JITed
- */
-gboolean
-_vte_regex_get_jited(VteRegex *regex)
+const pcre2_code_8 *
+_vte_regex_get_pcre(VteRegex* regex)
 {
-        PCRE2_SIZE s;
-        int r;
+        g_return_val_if_fail(regex != nullptr, nullptr);
 
-        g_return_val_if_fail(regex != NULL, FALSE);
+        return IMPL(regex)->code();
+}
 
-        r = pcre2_pattern_info_8(regex->code, PCRE2_INFO_JITSIZE, &s);
+bool
+_vte_regex_get_jited(VteRegex *regex)
+{
+        g_return_val_if_fail(regex != nullptr, false);
 
-        return r == 0 && s != 0;
+        return IMPL(regex)->jited();
 }
 
-/*
- * _vte_regex_get_compile_flags:
- *
- * Returns: the PCRE2 flags used to compile @regex
- */
-guint32
-_vte_regex_get_compile_flags(VteRegex *regex)
+bool
+_vte_regex_has_multiline_compile_flag(VteRegex *regex)
 {
         g_return_val_if_fail(regex != nullptr, 0);
 
-        uint32_t v;
-        int r = pcre2_pattern_info_8(regex->code, PCRE2_INFO_ARGOPTIONS, &v);
-
-        return r == 0 ? v : 0u;
+        return IMPL(regex)->has_compile_flags(PCRE2_MULTILINE);
 }
 
 /**
@@ -485,40 +320,5 @@ vte_regex_substitute(VteRegex *regex,
         g_return_val_if_fail(replacement != nullptr, nullptr);
         g_return_val_if_fail (!(flags & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH), nullptr);
 
-        uint8_t outbuf[2048];
-        PCRE2_SIZE outlen = sizeof(outbuf);
-        int r = pcre2_substitute_8(_vte_regex_get_pcre(regex),
-                                   (PCRE2_SPTR8)subject, PCRE2_ZERO_TERMINATED,
-                                   0 /* start offset */,
-                                   flags | PCRE2_SUBSTITUTE_OVERFLOW_LENGTH,
-                                   nullptr /* match data */,
-                                   nullptr /* match context */,
-                                   (PCRE2_SPTR8)replacement, PCRE2_ZERO_TERMINATED,
-                                   (PCRE2_UCHAR8*)outbuf, &outlen);
-
-        if (r >= 0)
-                return g_strndup((char*)outbuf, outlen);
-
-        if (r == PCRE2_ERROR_NOMEMORY) {
-                /* The buffer was not large enough; allocated a buffer of the
-                 * required size and try again. Note that @outlen as returned
-                 * from pcre2_substitute_8() above includes the trailing \0.
-                 */
-                uint8_t *outbuf2 = (uint8_t*)g_malloc(outlen);
-                r = pcre2_substitute_8(_vte_regex_get_pcre(regex),
-                                       (PCRE2_SPTR8)subject, PCRE2_ZERO_TERMINATED,
-                                       0 /* start offset */,
-                                       flags | PCRE2_SUBSTITUTE_OVERFLOW_LENGTH,
-                                       nullptr /* match data */,
-                                       nullptr /* match context */,
-                                       (PCRE2_SPTR8)replacement, PCRE2_ZERO_TERMINATED,
-                                       (PCRE2_UCHAR8*)outbuf2, &outlen);
-                if (r >= 0)
-                        return (char*)outbuf2;
-
-                g_free(outbuf2);
-       }
-
-        set_gerror_from_pcre_error(r, error);
-        return nullptr;
+        return IMPL(regex)->substitute(subject, replacement, flags, error);
 }
diff --git a/src/vteregexinternal.hh b/src/vteregexinternal.hh
index 1b4a78fd..d5b744ec 100644
--- a/src/vteregexinternal.hh
+++ b/src/vteregexinternal.hh
@@ -17,22 +17,19 @@
 
 #pragma once
 
-enum class VteRegexPurpose {
-        match,
-        search
-};
+#include "regex.hh"
 
-gboolean _vte_regex_has_purpose(VteRegex *regex,
-                                VteRegexPurpose purpose);
+bool _vte_regex_has_purpose(VteRegex* regex,
+                            vte::base::Regex::Purpose purpose);
 
-gboolean _vte_regex_get_jited(VteRegex *regex);
+bool _vte_regex_get_jited(VteRegex* regex);
 
-guint32 _vte_regex_get_compile_flags (VteRegex *regex);
+bool _vte_regex_has_multiline_compile_flag(VteRegex* regex);
 
-const pcre2_code_8 *_vte_regex_get_pcre (VteRegex const* regex);
+const pcre2_code_8 *_vte_regex_get_pcre(VteRegex* regex);
 
 /* GRegex translation */
-VteRegex *_vte_regex_new_gregex(VteRegexPurpose purpose,
-                                GRegex *gregex);
+VteRegex* _vte_regex_new_gregex(vte::base::Regex::Purpose purpose,
+                                GRegex* gregex);
 
-guint32 _vte_regex_translate_gregex_match_flags(GRegexMatchFlags flags);
+uint32_t _vte_regex_translate_gregex_match_flags(GRegexMatchFlags flags);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]