[gtksourceview/wip/chergert/snippets] more snippet parsing, use string chunks for infos



commit 89b1a465adfb43e2ecdea460f2d826af62a6e538
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jan 28 11:45:26 2020 -0800

    more snippet parsing, use string chunks for infos
    
    This helps us avoid creating objects up-front, and keep all the string
    data in contiguous memory (well to some degree).

 gtksourceview/gtksourcesnippetbundle-private.h  | 10 +++
 gtksourceview/gtksourcesnippetbundle.c          | 99 +++++++++++++++++++------
 gtksourceview/gtksourcesnippetmanager-private.h |  3 +
 gtksourceview/gtksourcesnippetmanager.c         | 27 ++++++-
 4 files changed, 115 insertions(+), 24 deletions(-)
---
diff --git a/gtksourceview/gtksourcesnippetbundle-private.h b/gtksourceview/gtksourcesnippetbundle-private.h
index 9d957fb0..0b1e0d75 100644
--- a/gtksourceview/gtksourcesnippetbundle-private.h
+++ b/gtksourceview/gtksourcesnippetbundle-private.h
@@ -26,6 +26,16 @@
 
 G_BEGIN_DECLS
 
+typedef struct
+{
+       const gchar *group;
+       const gchar *name;
+       const gchar *trigger;
+       const gchar *language;
+       const gchar *description;
+       const gchar *text;
+} GtkSourceSnippetInfo;
+
 #define GTK_SOURCE_TYPE_SNIPPET_BUNDLE (_gtk_source_snippet_bundle_get_type())
 
 G_DECLARE_FINAL_TYPE (GtkSourceSnippetBundle, _gtk_source_snippet_bundle, GTK_SOURCE, SNIPPET_BUNDLE, 
GObject)
diff --git a/gtksourceview/gtksourcesnippetbundle.c b/gtksourceview/gtksourcesnippetbundle.c
index 408f369a..24ac6e08 100644
--- a/gtksourceview/gtksourcesnippetbundle.c
+++ b/gtksourceview/gtksourcesnippetbundle.c
@@ -19,22 +19,26 @@
 
 #include "config.h"
 
+#include "gtksourcesnippet.h"
 #include "gtksourcesnippetbundle-private.h"
-#include "gtksourcesnippetmanager.h"
+#include "gtksourcesnippetmanager-private.h"
 
 struct _GtkSourceSnippetBundle
 {
        GObject  parent_instance;
+       GArray  *infos;
 };
 
 typedef struct
 {
+       GtkSourceSnippetManager *manager;
        GtkSourceSnippetBundle  *self;
        gchar                   *group;
        gchar                   *name;
        gchar                   *description;
        gchar                   *trigger;
        gchar                  **languages;
+       GString                 *text;
 } ParseState;
 
 G_DEFINE_TYPE (GtkSourceSnippetBundle, _gtk_source_snippet_bundle, G_TYPE_OBJECT)
@@ -42,6 +46,10 @@ G_DEFINE_TYPE (GtkSourceSnippetBundle, _gtk_source_snippet_bundle, G_TYPE_OBJECT
 static void
 gtk_source_snippet_bundle_finalize (GObject *object)
 {
+       GtkSourceSnippetBundle *self = (GtkSourceSnippetBundle *)object;
+
+       g_clear_pointer (&self->infos, g_array_unref);
+
        G_OBJECT_CLASS (_gtk_source_snippet_bundle_parent_class)->finalize (object);
 }
 
@@ -56,6 +64,23 @@ _gtk_source_snippet_bundle_class_init (GtkSourceSnippetBundleClass *klass)
 static void
 _gtk_source_snippet_bundle_init (GtkSourceSnippetBundle *self)
 {
+       self->infos = g_array_new (FALSE, FALSE, sizeof (GtkSourceSnippetInfo));
+}
+
+static void
+gtk_source_snippet_bundle_add (GtkSourceSnippetBundle     *self,
+                               const GtkSourceSnippetInfo *info)
+{
+       g_assert (GTK_SOURCE_IS_SNIPPET_BUNDLE (self));
+       g_assert (info != NULL);
+
+       /* If there is no name, and no trigger, then there is no way to
+        * instantiate the snippet. Just ignore it.
+        */
+       if (info->name != NULL || info->trigger != NULL)
+       {
+               g_array_append_vals (self->infos, info, 1);
+       }
 }
 
 static void
@@ -66,14 +91,12 @@ text_and_cdata (GMarkupParseContext  *context,
                 GError              **error)
 {
        ParseState *state = user_data;
-       gchar *copy;
 
        g_assert (state != NULL);
        g_assert (GTK_SOURCE_IS_SNIPPET_BUNDLE (state->self));
 
-       copy = g_strndup (text, text_len);
-       g_print ("%s", copy);
-       g_free (copy);
+       g_string_truncate (state->text, 0);
+       g_string_append_len (state->text, text, text_len);
 }
 
 static const GMarkupParser text_parser = {
@@ -118,8 +141,8 @@ elements_start_element (GMarkupParseContext  *context,
                g_set_error (error,
                             G_MARKUP_ERROR,
                             G_MARKUP_ERROR_UNKNOWN_ELEMENT,
-                            "Element %s not supported",
-                            element_name);
+                            "Element %s not supported",
+                            element_name);
        }
 }
 
@@ -132,9 +155,31 @@ elements_end_element (GMarkupParseContext  *context,
        ParseState *state = user_data;
 
        g_assert (state != NULL);
+       g_assert (GTK_SOURCE_IS_SNIPPET_MANAGER (state->manager));
        g_assert (GTK_SOURCE_IS_SNIPPET_BUNDLE (state->self));
        g_assert (element_name != NULL);
 
+       if (g_strcmp0 (element_name, "text") == 0 &&
+           state->languages != NULL &&
+           state->languages[0] != NULL)
+       {
+               GtkSourceSnippetInfo info;
+
+               info.group = _gtk_source_snippet_manager_intern (state->manager, state->group);
+               info.name = _gtk_source_snippet_manager_intern (state->manager, state->name);
+               info.description = _gtk_source_snippet_manager_intern (state->manager, state->description);
+               info.trigger = _gtk_source_snippet_manager_intern (state->manager, state->trigger);
+               info.text = _gtk_source_snippet_manager_intern (state->manager, state->text->str);
+
+               for (guint i = 0; state->languages[i]; i++)
+               {
+                       info.language = _gtk_source_snippet_manager_intern (state->manager, 
state->languages[i]);
+
+                       gtk_source_snippet_bundle_add (state->self, &info);
+               }
+
+       }
+
        g_clear_pointer (&state->languages, g_strfreev);
 
        g_markup_parse_context_pop (context);
@@ -167,8 +212,8 @@ snippet_start_element (GMarkupParseContext  *context,
                g_set_error (error,
                             G_MARKUP_ERROR,
                             G_MARKUP_ERROR_UNKNOWN_ELEMENT,
-                            "Element %s not supported",
-                            element_name);
+                            "Element %s not supported",
+                            element_name);
                return;
        }
 
@@ -253,8 +298,8 @@ snippets_start_element (GMarkupParseContext  *context,
                g_set_error (error,
                             G_MARKUP_ERROR,
                             G_MARKUP_ERROR_UNKNOWN_ELEMENT,
-                            "Element %s not supported",
-                            element_name);
+                            "Element %s not supported",
+                            element_name);
                return;
        }
 
@@ -295,8 +340,9 @@ static const GMarkupParser snippets_parser = {
 };
 
 static gboolean
-gtk_source_snippet_bundle_parse (GtkSourceSnippetBundle *self,
-                                 const gchar            *path)
+gtk_source_snippet_bundle_parse (GtkSourceSnippetBundle  *self,
+                                 GtkSourceSnippetManager *manager,
+                                 const gchar             *path)
 {
        gchar *contents = NULL;
        gsize length = 0;
@@ -308,7 +354,11 @@ gtk_source_snippet_bundle_parse (GtkSourceSnippetBundle *self,
        if (g_file_get_contents (path, &contents, &length, NULL))
        {
                GMarkupParseContext *context;
-               ParseState state = { .self = self };
+               ParseState state = {0};
+
+               state.self = self;
+               state.manager = manager;
+               state.text = g_string_new (NULL);
 
                context = g_markup_parse_context_new (&snippets_parser,
                                                      (G_MARKUP_TREAT_CDATA_AS_TEXT |
@@ -322,9 +372,19 @@ gtk_source_snippet_bundle_parse (GtkSourceSnippetBundle *self,
                g_clear_pointer (&state.name, g_free);
                g_clear_pointer (&state.trigger, g_free);
                g_clear_pointer (&state.group, g_free);
+               g_string_free (state.text, TRUE);
 
                g_markup_parse_context_free (context);
                g_free (contents);
+
+#if 0
+               for (guint i = 0; i < self->infos->len; i++)
+               {
+                       GtkSourceSnippetInfo *info = &g_array_index (self->infos, GtkSourceSnippetInfo, i);
+                       g_print ("group=%s name=%s language=%s trigger=%s\n",
+                                info->group, info->name, info->language, info->trigger);
+               }
+#endif
        }
 
        return ret;
@@ -341,13 +401,10 @@ _gtk_source_snippet_bundle_new_from_file (const gchar             *path,
 
        self = g_object_new (GTK_SOURCE_TYPE_SNIPPET_BUNDLE, NULL);
 
-       if (gtk_source_snippet_bundle_parse (self, path))
-       {
-               return g_steal_pointer (&self);
-       }
-       else
+       if (!gtk_source_snippet_bundle_parse (self, manager, path))
        {
-               g_object_unref (self);
-               return NULL;
+               g_clear_object (&self);
        }
+
+       return g_steal_pointer (&self);
 }
diff --git a/gtksourceview/gtksourcesnippetmanager-private.h b/gtksourceview/gtksourcesnippetmanager-private.h
index 7a0f86d3..fd569639 100644
--- a/gtksourceview/gtksourcesnippetmanager-private.h
+++ b/gtksourceview/gtksourcesnippetmanager-private.h
@@ -25,5 +25,8 @@ G_BEGIN_DECLS
 
 G_GNUC_INTERNAL
 GtkSourceSnippetManager *_gtk_source_snippet_manager_peek_default (void);
+G_GNUC_INTERNAL
+const gchar             *_gtk_source_snippet_manager_intern       (GtkSourceSnippetManager *manager,
+                                                                   const gchar             *str);
 
 G_END_DECLS
diff --git a/gtksourceview/gtksourcesnippetmanager.c b/gtksourceview/gtksourcesnippetmanager.c
index b1e5c7d3..886ee37b 100644
--- a/gtksourceview/gtksourcesnippetmanager.c
+++ b/gtksourceview/gtksourcesnippetmanager.c
@@ -47,9 +47,10 @@
 
 struct _GtkSourceSnippetManager
 {
-       GObject     parent_instance;
-       gchar     **snippet_dirs;
-       GPtrArray  *bundles;
+       GObject        parent_instance;
+       GStringChunk  *strings;
+       gchar        **snippet_dirs;
+       GPtrArray     *bundles;
 };
 
 enum {
@@ -70,6 +71,7 @@ gtk_source_snippet_manager_finalize (GObject *object)
 
        g_clear_pointer (&self->bundles, g_ptr_array_unref);
        g_clear_pointer (&self->snippet_dirs, g_strfreev);
+       g_clear_pointer (&self->strings, g_string_chunk_free);
 
        G_OBJECT_CLASS (gtk_source_snippet_manager_parent_class)->finalize (object);
 }
@@ -179,6 +181,25 @@ _gtk_source_snippet_manager_peek_default (void)
        return default_instance;
 }
 
+const gchar *
+_gtk_source_snippet_manager_intern (GtkSourceSnippetManager *self,
+                                    const gchar             *str)
+{
+       g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_MANAGER (self), NULL);
+
+       if (str == NULL)
+       {
+               return NULL;
+       }
+
+       if (self->strings == NULL)
+       {
+               self->strings = g_string_chunk_new (4096*2);
+       }
+
+       return g_string_chunk_insert_const (self->strings, str);
+}
+
 /**
  * gtk_source_snippet_manager_set_search_path:
  * @self: a #GtkSourceSnippetManager


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