[libdazzle] pattern-spec: add DzlPatternSpec
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdazzle] pattern-spec: add DzlPatternSpec
- Date: Tue, 6 Jun 2017 01:42:19 +0000 (UTC)
commit 62080ddd7af2a2d8ac5abd1fba3b2b0bc92ccd31
Author: Christian Hergert <chergert redhat com>
Date: Mon Jun 5 18:40:22 2017 -0700
pattern-spec: add DzlPatternSpec
This is useful for more advanced searching than GPatternSpec can provide.
src/dazzle.h | 1 +
src/meson.build | 2 +
src/search/dzl-pattern-spec.c | 172 +++++++++++++++++++++++++++++++++++++++++
src/search/dzl-pattern-spec.h | 42 ++++++++++
4 files changed, 217 insertions(+), 0 deletions(-)
---
diff --git a/src/dazzle.h b/src/dazzle.h
index 6868bb9..83a2768 100644
--- a/src/dazzle.h
+++ b/src/dazzle.h
@@ -74,6 +74,7 @@ G_BEGIN_DECLS
#include "search/dzl-fuzzy-index-match.h"
#include "search/dzl-fuzzy-mutable-index.h"
#include "search/dzl-levenshtein.h"
+#include "search/dzl-pattern-spec.h"
#include "search/dzl-trie.h"
#include "settings/dzl-settings-sandwich.h"
#include "shortcuts/dzl-shortcut-accel-dialog.h"
diff --git a/src/meson.build b/src/meson.build
index 38599d4..dbc5543 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -79,6 +79,7 @@ libdazzle_public_headers = [
'search/dzl-fuzzy-index.h',
'search/dzl-fuzzy-mutable-index.h',
'search/dzl-levenshtein.h',
+ 'search/dzl-pattern-spec.h',
'search/dzl-trie.h',
'settings/dzl-settings-sandwich.h',
@@ -202,6 +203,7 @@ libdazzle_public_sources = [
'search/dzl-fuzzy-index.c',
'search/dzl-fuzzy-mutable-index.c',
'search/dzl-levenshtein.c',
+ 'search/dzl-pattern-spec.c',
'search/dzl-trie.c',
'settings/dzl-settings-sandwich.c',
diff --git a/src/search/dzl-pattern-spec.c b/src/search/dzl-pattern-spec.c
new file mode 100644
index 0000000..a29383f
--- /dev/null
+++ b/src/search/dzl-pattern-spec.c
@@ -0,0 +1,172 @@
+/* dzl-pattern-spec.c
+ *
+ * Copyright (C) 2015-2017 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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/>.
+ */
+
+#define G_LOG_DOMAIN "dzl-pattern-spec"
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <string.h>
+
+#include "dzl-pattern-spec.h"
+
+G_DEFINE_BOXED_TYPE (DzlPatternSpec, dzl_pattern_spec, dzl_pattern_spec_ref, dzl_pattern_spec_unref)
+
+/**
+ * SECTION:dzl-pattern-spec
+ * @title: DzlPatternSpec
+ * @short_description: Simple glob-like searching
+ *
+ * This works similar to #GPatternSpec except the query syntax is different.
+ * It tries to mtach word boundaries, but with matching partial words up
+ * to those boundaries. For example, "gtk widg" would match "gtk_widget_show".
+ * Word boundaries include '_' and ' '. If any character is uppercase, then
+ * case sensitivity is used.
+ */
+
+struct _DzlPatternSpec
+{
+ volatile gint ref_count;
+ gchar *needle;
+ gchar **parts;
+ guint case_sensitive : 1;
+};
+
+DzlPatternSpec *
+dzl_pattern_spec_new (const gchar *needle)
+{
+ DzlPatternSpec *self;
+ const gchar *tmp;
+
+ g_return_val_if_fail (needle, NULL);
+
+ self = g_new0 (DzlPatternSpec, 1);
+ self->ref_count = 1;
+ self->needle = g_strdup (needle);
+ self->parts = g_strsplit (needle, " ", 0);
+ self->case_sensitive = FALSE;
+
+ for (tmp = needle; *tmp; tmp = g_utf8_next_char (tmp))
+ {
+ if (g_unichar_isupper (g_utf8_get_char (tmp)))
+ {
+ self->case_sensitive = TRUE;
+ break;
+ }
+ }
+
+ return self;
+}
+
+const gchar *
+dzl_pattern_spec_get_text (DzlPatternSpec *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return self->needle;
+}
+
+static void
+dzl_pattern_spec_free (DzlPatternSpec *self)
+{
+ g_strfreev (self->parts);
+ g_free (self->needle);
+ g_free (self);
+}
+
+static inline gboolean
+is_word_break (gunichar ch)
+{
+ return (ch == ' ' || ch == '_' || ch == '-');
+}
+
+static const gchar *
+next_word_start (const gchar *haystack)
+{
+ for (; *haystack; haystack = g_utf8_next_char (haystack))
+ {
+ gunichar ch = g_utf8_get_char (haystack);
+
+ if (is_word_break (ch))
+ break;
+ }
+
+ for (; *haystack; haystack = g_utf8_next_char (haystack))
+ {
+ gunichar ch = g_utf8_get_char (haystack);
+
+ if (is_word_break (ch))
+ continue;
+
+ break;
+ }
+
+ g_return_val_if_fail (*haystack == '\0' || !is_word_break (*haystack), NULL);
+
+ return haystack;
+}
+
+gboolean
+dzl_pattern_spec_match (DzlPatternSpec *self,
+ const gchar *haystack)
+{
+ gsize i;
+
+ g_return_val_if_fail (self, FALSE);
+ g_return_val_if_fail (haystack, FALSE);
+
+ for (i = 0; (haystack != NULL) && self->parts [i]; i++)
+ {
+ if (self->parts [i][0] == '\0')
+ continue;
+
+ if (self->case_sensitive)
+ haystack = strstr (haystack, self->parts [i]);
+ else
+ haystack = strcasestr (haystack, self->parts [i]);
+
+ if (haystack == NULL)
+ return FALSE;
+
+ if (self->parts [i + 1] != NULL)
+ haystack = next_word_start (haystack + strlen (self->parts [i]));
+ }
+
+ return TRUE;
+}
+
+DzlPatternSpec *
+dzl_pattern_spec_ref (DzlPatternSpec *self)
+{
+ g_return_val_if_fail (self, NULL);
+ g_return_val_if_fail (self->ref_count > 0, NULL);
+
+ g_atomic_int_inc (&self->ref_count);
+
+ return self;
+}
+
+void
+dzl_pattern_spec_unref (DzlPatternSpec *self)
+{
+ g_return_if_fail (self);
+ g_return_if_fail (self->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&self->ref_count))
+ dzl_pattern_spec_free (self);
+}
diff --git a/src/search/dzl-pattern-spec.h b/src/search/dzl-pattern-spec.h
new file mode 100644
index 0000000..0849ad6
--- /dev/null
+++ b/src/search/dzl-pattern-spec.h
@@ -0,0 +1,42 @@
+/* dzl-pattern-spec.h
+ *
+ * Copyright (C) 2015-2017 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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/>.
+ */
+
+#ifndef DZL_MATCH_PATTERN_H
+#define DZL_MATCH_PATTERN_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _DzlPatternSpec DzlPatternSpec;
+
+#define DZL_TYPE_PATTERN_SPEC (dzl_pattern_spec_get_type())
+
+GType dzl_pattern_spec_get_type (void);
+DzlPatternSpec *dzl_pattern_spec_new (const gchar *keywords);
+DzlPatternSpec *dzl_pattern_spec_ref (DzlPatternSpec *self);
+void dzl_pattern_spec_unref (DzlPatternSpec *self);
+gboolean dzl_pattern_spec_match (DzlPatternSpec *self,
+ const gchar *haystack);
+const gchar *dzl_pattern_spec_get_text (DzlPatternSpec *self);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (DzlPatternSpec, dzl_pattern_spec_unref)
+
+G_END_DECLS
+
+#endif /* DZL_MATCH_PATTERN_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]