[devhelp] Start to implement DhSearchContext internal class



commit cf2b1d23c65fefda98f3a03e8cf330358f7b5ae4
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Thu Jan 18 10:55:53 2018 +0100

    Start to implement DhSearchContext internal class

 docs/reference/Makefile.am |    1 +
 po/POTFILES.in             |    1 +
 src/Makefile.am            |    2 +
 src/dh-search-context.c    |  196 ++++++++++++++++++++++++++++++++++++++++++++
 src/dh-search-context.h    |   45 ++++++++++
 5 files changed, 245 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 7854955..f17ba5d 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -52,6 +52,7 @@ IGNORE_HFILES = \
        dh-error.h \
        dh-parser.h \
        dh-preferences.h \
+       dh-search-context.h \
        dh-settings.h \
        dh-util.h \
        dh-window.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 63e98df..a987008 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,6 +17,7 @@ src/dh-link.c
 src/dh-main.c
 src/dh-parser.c
 src/dh-preferences.ui
+src/dh-search-context.c
 src/dh-sidebar.c
 src/dh-util.c
 src/dh-window.c
diff --git a/src/Makefile.am b/src/Makefile.am
index db4918b..2873a8b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,6 +38,7 @@ libdevhelp_private_headers =          \
        dh-error.h                      \
        dh-parser.h                     \
        dh-preferences.h                \
+       dh-search-context.h             \
        dh-settings.h                   \
        dh-util.h                       \
        $(NULL)
@@ -46,6 +47,7 @@ libdevhelp_private_c_files =          \
        dh-error.c                      \
        dh-parser.c                     \
        dh-preferences.c                \
+       dh-search-context.c             \
        dh-settings.c                   \
        dh-util.c                       \
        $(NULL)
diff --git a/src/dh-search-context.c b/src/dh-search-context.c
new file mode 100644
index 0000000..03d5b36
--- /dev/null
+++ b/src/dh-search-context.c
@@ -0,0 +1,196 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2018 Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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 2 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/>.
+ */
+
+#include "dh-search-context.h"
+#include <string.h>
+
+struct _DhSearchContext {
+        gchar *book_id;
+        gchar *page_id;
+        GStrv keywords;
+};
+
+/* Process the input search string and extract:
+ *  - If "book:" prefix given, a book_id;
+ *  - If "page:" prefix given, a page_id;
+ *  - All remaining keywords.
+ *
+ * Returns TRUE if the extraction is successfull, FALSE if the @search_string is
+ * invalid.
+ */
+static gboolean
+process_search_string (DhSearchContext *search,
+                       const gchar     *search_string)
+{
+        gchar *processed = NULL;
+        GStrv tokens = NULL;
+        gint token_num;
+        gint keyword_num;
+        gboolean ret = TRUE;
+
+        g_assert (search->book_id == NULL);
+        g_assert (search->page_id == NULL);
+        g_assert (search->keywords == NULL);
+
+        /* First, remove all leading and trailing whitespaces in the search
+         * string.
+         */
+        processed = g_strdup (search_string);
+        g_strstrip (processed);
+
+        /* Also avoid words being separated by more than one whitespace, or
+         * g_strsplit() will give us empty strings.
+         */
+        {
+                gchar *aux;
+
+                aux = processed;
+                while ((aux = strchr (aux, ' ')) != NULL) {
+                        g_strchug (++aux);
+                }
+        }
+
+        /* If after all this we get an empty string, nothing else to do. */
+        if (processed[0] == '\0') {
+                ret = FALSE;
+                goto out;
+        }
+
+        /* Split the input string into tokens */
+        tokens = g_strsplit (processed, " ", 0);
+
+        /* Allocate output keywords */
+        search->keywords = g_new0 (gchar *, g_strv_length (tokens) + 1);
+        keyword_num = 0;
+
+        for (token_num = 0; tokens[token_num] != NULL; token_num++) {
+                const gchar *cur_token = tokens[token_num];
+                const gchar *prefix;
+                gint prefix_len;
+
+                /* Book prefix? */
+                prefix = "book:";
+                if (g_str_has_prefix (cur_token, prefix)) {
+                        prefix_len = strlen (prefix);
+
+                        /* If keyword given but no content, skip it. */
+                        if (cur_token[prefix_len] == '\0') {
+                                continue;
+                        }
+
+                        /* We got a second request of book, don't allow this. */
+                        if (search->book_id != NULL) {
+                                ret = FALSE;
+                                goto out;
+                        }
+
+                        search->book_id = g_strdup (cur_token + prefix_len);
+                        continue;
+                }
+
+                /* Page prefix? */
+                prefix = "page:";
+                if (g_str_has_prefix (cur_token, prefix)) {
+                        prefix_len = strlen (prefix);
+
+                        /* If keyword given but no content, skip it. */
+                        if (cur_token[prefix_len] == '\0') {
+                                continue;
+                        }
+
+                        /* We got a second request of page, don't allow this. */
+                        if (search->page_id != NULL) {
+                                ret = FALSE;
+                                goto out;
+                        }
+
+                        search->page_id = g_strdup (cur_token + prefix_len);
+                        continue;
+                }
+
+                /* Then, a new keyword to look for. */
+                search->keywords[keyword_num] = g_strdup (cur_token);
+                keyword_num++;
+        }
+
+        if (keyword_num == 0) {
+                g_free (search->keywords);
+                search->keywords = NULL;
+        }
+
+out:
+        g_free (processed);
+        g_strfreev (tokens);
+        return ret;
+}
+
+/* Returns: (transfer full) (nullable): a new #DhSearchContext, or %NULL if
+ * @search_string is invalid.
+ */
+DhSearchContext *
+_dh_search_context_new (const gchar *search_string)
+{
+        DhSearchContext *search;
+
+        g_return_val_if_fail (search_string != NULL, NULL);
+
+        search = g_new0 (DhSearchContext, 1);
+
+        if (!process_search_string (search, search_string)) {
+                _dh_search_context_free (search);
+                return NULL;
+        }
+
+        return search;
+}
+
+void
+_dh_search_context_free (DhSearchContext *search)
+{
+        if (search == NULL)
+                return;
+
+        g_free (search->book_id);
+        g_free (search->page_id);
+        g_strfreev (search->keywords);
+        g_free (search);
+}
+
+const gchar *
+_dh_search_context_get_book_id (DhSearchContext *search)
+{
+        g_return_val_if_fail (search != NULL, NULL);
+
+        return search->book_id;
+}
+
+const gchar *
+_dh_search_context_get_page_id (DhSearchContext *search)
+{
+        g_return_val_if_fail (search != NULL, NULL);
+
+        return search->page_id;
+}
+
+GStrv
+_dh_search_context_get_keywords (DhSearchContext *search)
+{
+        g_return_val_if_fail (search != NULL, NULL);
+
+        return search->keywords;
+}
diff --git a/src/dh-search-context.h b/src/dh-search-context.h
new file mode 100644
index 0000000..14fc34f
--- /dev/null
+++ b/src/dh-search-context.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2018 Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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 2 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 DH_SEARCH_CONTEXT_H
+#define DH_SEARCH_CONTEXT_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _DhSearchContext DhSearchContext;
+
+G_GNUC_INTERNAL
+DhSearchContext *       _dh_search_context_new                  (const gchar *search_string);
+
+G_GNUC_INTERNAL
+void                    _dh_search_context_free                 (DhSearchContext *search);
+
+G_GNUC_INTERNAL
+const gchar *           _dh_search_context_get_book_id          (DhSearchContext *search);
+
+G_GNUC_INTERNAL
+const gchar *           _dh_search_context_get_page_id          (DhSearchContext *search);
+
+G_GNUC_INTERNAL
+GStrv                   _dh_search_context_get_keywords         (DhSearchContext *search);
+
+G_END_DECLS
+
+#endif /* DH_SEARCH_CONTEXT_H */


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