[gnome-builder/gnome-builder-3-20] tmpl: import recent template-glib



commit c20d762c53d6827fe30430d0235110ec094311ff
Author: Christian Hergert <chergert redhat com>
Date:   Sat May 14 13:10:56 2016 +0300

    tmpl: import recent template-glib
    
    This adds hooks for missing symbol lookups.

 contrib/tmpl/tmpl-scope.c |   77 +++++++++++++++++++++++++++++++++++----------
 contrib/tmpl/tmpl-scope.h |   29 +++++++++++------
 2 files changed, 79 insertions(+), 27 deletions(-)
---
diff --git a/contrib/tmpl/tmpl-scope.c b/contrib/tmpl/tmpl-scope.c
index f1c892a..a4a0792 100644
--- a/contrib/tmpl/tmpl-scope.c
+++ b/contrib/tmpl/tmpl-scope.c
@@ -21,9 +21,12 @@
 
 struct _TmplScope
 {
-  volatile gint  ref_count;
-  TmplScope     *parent;
-  GHashTable    *symbols;
+  volatile gint      ref_count;
+  TmplScope         *parent;
+  GHashTable        *symbols;
+  TmplScopeResolver  resolver;
+  gpointer           resolver_data;
+  GDestroyNotify     resolver_destroy;
 };
 
 G_DEFINE_BOXED_TYPE (TmplScope, tmpl_scope, tmpl_scope_ref, tmpl_scope_unref)
@@ -47,6 +50,10 @@ tmpl_scope_unref (TmplScope *self)
 
   if (g_atomic_int_dec_and_test (&self->ref_count))
     {
+      if (self->resolver_destroy)
+        g_clear_pointer (&self->resolver_data, self->resolver_destroy);
+      self->resolver = NULL;
+      self->resolver_destroy = NULL;
       g_clear_pointer (&self->symbols, g_hash_table_unref);
       g_clear_pointer (&self->parent, tmpl_scope_unref);
       g_slice_free (TmplScope, self);
@@ -99,6 +106,7 @@ tmpl_scope_get_full (TmplScope   *self,
                      gboolean     create)
 {
   TmplSymbol *symbol = NULL;
+  TmplScope *parent;
 
   g_return_val_if_fail (self != NULL, NULL);
 
@@ -110,17 +118,22 @@ tmpl_scope_get_full (TmplScope   *self,
     }
 
   /* Try to locate the symbol in a parent scope */
-  if (symbol == NULL)
+  for (parent = self->parent; parent != NULL; parent = parent->parent)
     {
-      TmplScope *parent;
+      if (parent->symbols != NULL)
+        {
+          if ((symbol = g_hash_table_lookup (parent->symbols, name)))
+            return symbol;
+        }
+    }
 
-      for (parent = self->parent; parent != NULL; parent = parent->parent)
+  /* Call our resolver helper to locate the symbol */
+  for (parent = self; parent != NULL; parent = parent->parent)
+    {
+      if (parent->resolver)
         {
-          if (parent->symbols != NULL)
-            {
-              if ((symbol = g_hash_table_lookup (parent->symbols, name)))
-                return symbol;
-            }
+          if (parent->resolver (parent, name, &symbol, parent->resolver_data) && symbol)
+            goto save_symbol;
         }
     }
 
@@ -128,15 +141,20 @@ tmpl_scope_get_full (TmplScope   *self,
     {
       /* Define the symbol in this scope */
       symbol = tmpl_symbol_new ();
-      if (self->symbols == NULL)
-        self->symbols = g_hash_table_new_full (g_str_hash,
-                                               g_str_equal,
-                                               g_free,
-                                               (GDestroyNotify)tmpl_symbol_unref);
-      g_hash_table_insert (self->symbols, g_strdup (name), symbol);
+      goto save_symbol;
     }
 
   return symbol;
+
+save_symbol:
+  if (self->symbols == NULL)
+    self->symbols = g_hash_table_new_full (g_str_hash,
+                                           g_str_equal,
+                                           g_free,
+                                           (GDestroyNotify)tmpl_symbol_unref);
+  g_hash_table_insert (self->symbols, g_strdup (name), symbol);
+
+  return symbol;
 }
 
 /**
@@ -166,3 +184,28 @@ tmpl_scope_peek (TmplScope   *self,
 {
   return tmpl_scope_get_full (self, name, FALSE);
 }
+
+void
+tmpl_scope_set_resolver (TmplScope         *self,
+                         TmplScopeResolver  resolver,
+                         gpointer           user_data,
+                         GDestroyNotify     destroy)
+{
+  g_return_if_fail (self != NULL);
+
+  if (resolver != self->resolver ||
+      user_data != self->resolver_data ||
+      destroy != self->resolver_destroy)
+    {
+      if (self->resolver && self->resolver_destroy && self->resolver_data)
+        {
+          g_clear_pointer (&self->resolver_data, self->resolver_destroy);
+          self->resolver_destroy = NULL;
+          self->resolver = NULL;
+        }
+
+      self->resolver = resolver;
+      self->resolver_data = user_data;
+      self->resolver_destroy = destroy;
+    }
+}
diff --git a/contrib/tmpl/tmpl-scope.h b/contrib/tmpl/tmpl-scope.h
index 60efd9a..12e1871 100644
--- a/contrib/tmpl/tmpl-scope.h
+++ b/contrib/tmpl/tmpl-scope.h
@@ -27,17 +27,26 @@
 
 G_BEGIN_DECLS
 
+typedef gboolean (*TmplScopeResolver) (TmplScope    *scope,
+                                       const gchar  *name,
+                                       TmplSymbol  **symbol,
+                                       gpointer      user_data);
+
 TmplScope  *tmpl_scope_new             (void);
-TmplScope  *tmpl_scope_new_with_parent (TmplScope   *parent);
-TmplScope  *tmpl_scope_ref             (TmplScope   *self);
-void        tmpl_scope_unref           (TmplScope   *self);
-TmplSymbol *tmpl_scope_peek            (TmplScope   *self,
-                                        const gchar *name);
-TmplSymbol *tmpl_scope_get             (TmplScope   *self,
-                                        const gchar *name);
-void        tmpl_scope_set             (TmplScope   *self,
-                                        const gchar *name,
-                                        TmplSymbol  *symbol);
+TmplScope  *tmpl_scope_new_with_parent (TmplScope         *parent);
+TmplScope  *tmpl_scope_ref             (TmplScope         *self);
+void        tmpl_scope_unref           (TmplScope         *self);
+TmplSymbol *tmpl_scope_peek            (TmplScope         *self,
+                                        const gchar       *name);
+TmplSymbol *tmpl_scope_get             (TmplScope         *self,
+                                        const gchar       *name);
+void        tmpl_scope_set             (TmplScope         *self,
+                                        const gchar       *name,
+                                        TmplSymbol        *symbol);
+void        tmpl_scope_set_resolver    (TmplScope         *self,
+                                        TmplScopeResolver  resolver,
+                                        gpointer           user_data,
+                                        GDestroyNotify     destroy);
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (TmplScope, tmpl_scope_unref)
 


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