[gnome-terminal] search: Use PCRE2 and JIT the regexes



commit fed45f7eb1abdf5d730547e32c0b609d299e6a78
Author: Christian Persch <chpe gnome org>
Date:   Wed Sep 30 16:53:41 2015 +0200

    search: Use PCRE2 and JIT the regexes
    
    Use VteRegex if PCRE2 support is enabled, and JIT the regexes which speeds
    up the matching.

 src/terminal-search-popover.c |   94 +++++++++++++++++++++++++++++++++--------
 src/terminal-search-popover.h |    7 +++-
 src/terminal-window.c         |   16 +++++++
 3 files changed, 98 insertions(+), 19 deletions(-)
---
diff --git a/src/terminal-search-popover.c b/src/terminal-search-popover.c
index 4f286ad..4585b2e 100644
--- a/src/terminal-search-popover.c
+++ b/src/terminal-search-popover.c
@@ -23,6 +23,10 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#ifdef WITH_PCRE2
+#include "terminal-pcre2.h"
+#endif
+
 #include "terminal-search-popover.h"
 #include "terminal-intl.h"
 #include "terminal-window.h"
@@ -61,8 +65,14 @@ struct _TerminalSearchPopoverPrivate
   gboolean search_text_changed;
 
   /* Cached regex */
+  gboolean regex_caseless;
+  gboolean regex_multiline;
+  char *regex_pattern;
+#ifdef WITH_PCRE2
+  VteRegex *regex;
+#else
   GRegex *regex;
-  GRegexCompileFlags regex_compile_flags;
+#endif
 };
 
 enum {
@@ -242,20 +252,18 @@ static void
 update_regex (TerminalSearchPopover *popover)
 {
   TerminalSearchPopoverPrivate *priv = PRIV (popover);
-  GRegexCompileFlags compile_flags;
   const char *search_text;
+  gboolean caseless, multiline = FALSE;
   gs_free char *pattern;
+  gs_free_error GError *error = NULL;
 
   search_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
 
-  compile_flags = G_REGEX_OPTIMIZE;
-
-  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->match_case_checkbutton)))
-    compile_flags |= G_REGEX_CASELESS;
+  caseless = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->match_case_checkbutton));
 
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->regex_checkbutton))) {
     pattern = g_strdup (search_text);
-    compile_flags |= G_REGEX_MULTILINE;
+    multiline = TRUE;
   } else {
     pattern = g_regex_escape_string (search_text, -1);
   }
@@ -267,20 +275,53 @@ update_regex (TerminalSearchPopover *popover)
     pattern = new_pattern;
   }
 
-  if (priv->regex != NULL &&
-      priv->regex_compile_flags == compile_flags &&
-      g_strcmp0 (pattern, g_regex_get_pattern (priv->regex)) == 0)
+  if (priv->regex_caseless == caseless &&
+      priv->regex_multiline == multiline &&
+      g_strcmp0 (priv->regex_pattern, pattern) == 0)
     return;
 
-  priv->regex_compile_flags = compile_flags;
-  if (priv->regex)
+  if (priv->regex) {
+#ifdef WITH_PCRE2
+    vte_regex_unref (priv->regex);
+#else
     g_regex_unref (priv->regex);
+#endif
+  }
+
+  g_clear_pointer (&priv->regex_pattern, g_free);
 
   /* FIXME: if comping the regex fails, show the error message somewhere */
-  if (search_text[0] != '\0')
-    priv->regex = g_regex_new (pattern, compile_flags, 0, NULL);
-  else
+  if (search_text[0] != '\0') {
+#ifdef WITH_PCRE2
+    guint32 compile_flags;
+
+    compile_flags = PCRE2_UTF | PCRE2_NO_UTF_CHECK;
+    if (caseless)
+      compile_flags |= PCRE2_CASELESS;
+    if (multiline)
+      compile_flags |= PCRE2_MULTILINE;
+
+    priv->regex = vte_regex_new (pattern, -1, compile_flags, &error);
+    if (priv->regex != NULL &&
+        (!vte_regex_jit (priv->regex, PCRE2_JIT_COMPLETE, NULL) ||
+         !vte_regex_jit (priv->regex, PCRE2_JIT_PARTIAL_SOFT, NULL))) {
+    }
+#else
+    GRegexCompileFlags compile_flags;
+
+    compile_flags = G_REGEX_OPTIMIZE;
+    if (caseless)
+      compile_flags |= G_REGEX_CASELESS;
+    if (multiline)
+      compile_flags |= G_REGEX_MULTILINE;
+
+    priv->regex = g_regex_new (pattern, compile_flags, 0, &error);
+#endif
+    if (priv->regex != NULL)
+      gs_transfer_out_value (&priv->regex_pattern, &pattern);
+  } else {
     priv->regex = NULL;
+  }
 
   update_sensitivity (popover);
 
@@ -321,6 +362,9 @@ terminal_search_popover_init (TerminalSearchPopover *popover)
   TerminalSearchPopoverPrivate *priv = PRIV (popover);
   GtkWidget *widget = GTK_WIDGET (popover);
 
+  priv->regex_pattern = 0;
+  priv->regex_caseless = priv->regex_multiline = FALSE;
+
   gtk_widget_init_template (widget);
 
   /* Make the search entry reasonably wide */
@@ -364,7 +408,6 @@ terminal_search_popover_init (TerminalSearchPopover *popover)
                           priv->revealer, "reveal-child",
                           G_BINDING_DEFAULT);
 
-  priv->regex = NULL;
   update_sensitivity (popover);
 
   g_signal_connect (priv->search_entry, "search-changed", G_CALLBACK (search_text_changed_cb), popover);
@@ -381,8 +424,15 @@ terminal_search_popover_finalize (GObject *object)
   TerminalSearchPopover *popover = TERMINAL_SEARCH_POPOVER (object);
   TerminalSearchPopoverPrivate *priv = PRIV (popover);
 
-  if (priv->regex)
-    g_regex_unref(priv->regex);
+  if (priv->regex) {
+#ifdef WITH_PCRE2
+    vte_regex_unref (priv->regex);
+#else
+    g_regex_unref (priv->regex);
+#endif
+  }
+
+  g_free (priv->regex_pattern);
 
   G_OBJECT_CLASS (terminal_search_popover_parent_class)->finalize (object);
 }
@@ -448,7 +498,11 @@ terminal_search_popover_class_init (TerminalSearchPopoverClass *klass)
 
   pspecs[PROP_REGEX] =
     g_param_spec_boxed ("regex", NULL, NULL,
+#ifdef WITH_PCRE2
+                        VTE_TYPE_REGEX,
+#else
                         G_TYPE_REGEX,
+#endif
                         G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
 
   pspecs[PROP_WRAP_AROUND] =
@@ -492,7 +546,11 @@ terminal_search_popover_new (GtkWidget *relative_to_widget)
  *
  * Returns: (transfer none): the search regex, or %NULL
  */
+#ifdef WITH_PCRE2
+VteRegex *
+#else
 GRegex *
+#endif
 terminal_search_popover_get_regex (TerminalSearchPopover *popover)
 {
   g_return_val_if_fail (TERMINAL_IS_SEARCH_POPOVER (popover), NULL);
diff --git a/src/terminal-search-popover.h b/src/terminal-search-popover.h
index 8998144..813f0f3 100644
--- a/src/terminal-search-popover.h
+++ b/src/terminal-search-popover.h
@@ -39,7 +39,12 @@ GType terminal_search_popover_get_type (void);
 
 TerminalSearchPopover *terminal_search_popover_new (GtkWidget *relative_to_widget);
 
-GRegex *terminal_search_popover_get_regex (TerminalSearchPopover *popover);
+#ifdef WITH_PCRE2
+VteRegex *
+#else
+GRegex *
+#endif
+          terminal_search_popover_get_regex (TerminalSearchPopover *popover);
 
 gboolean terminal_search_popover_get_wrap_around (TerminalSearchPopover *popover);
 
diff --git a/src/terminal-window.c b/src/terminal-window.c
index f673e99..1dfb500 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -888,13 +888,21 @@ search_popover_notify_regex_cb (TerminalSearchPopover *popover,
                                 TerminalWindow *window)
 {
   TerminalWindowPrivate *priv = window->priv;
+#ifdef WITH_PCRE2
+  VteRegex *regex;
+#else
   GRegex *regex;
+#endif
 
   if (G_UNLIKELY (priv->active_screen == NULL))
     return;
 
   regex = terminal_search_popover_get_regex (popover);
+#ifdef WITH_PCRE2
+  vte_terminal_search_set_regex (VTE_TERMINAL (priv->active_screen), regex, 0);
+#else
   vte_terminal_search_set_gregex (VTE_TERMINAL (priv->active_screen), regex, 0);
+#endif
 
   terminal_window_update_search_sensitivity (priv->active_screen, window);
 }
@@ -967,7 +975,11 @@ action_find_cb (GSimpleAction *action,
   } else if (g_str_equal (mode, "previous")) {
     vte_terminal_search_find_previous (VTE_TERMINAL (priv->active_screen));
   } else if (g_str_equal (mode, "clear")) {
+#ifdef WITH_PCRE2
+    vte_terminal_search_set_regex (VTE_TERMINAL (priv->active_screen), NULL, 0);
+#else
     vte_terminal_search_set_gregex (VTE_TERMINAL (priv->active_screen), NULL, 0);
+#endif
   } else
     return;
 }
@@ -1776,7 +1788,11 @@ terminal_window_update_search_sensitivity (TerminalScreen *screen,
   if (screen != priv->active_screen)
     return;
 
+#ifdef WITH_PCRE2
+  can_search = vte_terminal_search_get_regex (VTE_TERMINAL (screen)) != NULL;
+#else
   can_search = vte_terminal_search_get_gregex (VTE_TERMINAL (screen)) != NULL;
+#endif
 
   action = gtk_action_group_get_action (priv->action_group, "SearchFindNext");
   gtk_action_set_sensitive (action, can_search);


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