[gnome-builder] tmpl: bump template-glib snapshot



commit 23adf3c6bd91e4f74947cc3c2f492dcd1a72a3de
Author: Christian Hergert <chergert redhat com>
Date:   Wed Oct 19 14:39:22 2016 -0700

    tmpl: bump template-glib snapshot

 contrib/tmpl/tmpl-expr-eval.c  |  308 +++++++++++++++++++++++++++++++++++++---
 contrib/tmpl/tmpl-expr-types.h |    1 +
 contrib/tmpl/tmpl-expr.c       |   12 ++
 contrib/tmpl/tmpl-expr.h       |    1 +
 contrib/tmpl/tmpl-iterator.c   |   27 +++-
 contrib/tmpl/tmpl-scope.c      |   90 ++++++++++--
 contrib/tmpl/tmpl-scope.h      |   15 ++
 contrib/tmpl/tmpl-template.c   |   14 ++-
 8 files changed, 431 insertions(+), 37 deletions(-)
---
diff --git a/contrib/tmpl/tmpl-expr-eval.c b/contrib/tmpl/tmpl-expr-eval.c
index 47aaaab..652499b 100644
--- a/contrib/tmpl/tmpl-expr-eval.c
+++ b/contrib/tmpl/tmpl-expr-eval.c
@@ -18,6 +18,7 @@
 
 #include <girepository.h>
 #include <math.h>
+#include <string.h>
 
 #include "tmpl-error.h"
 #include "tmpl-expr.h"
@@ -67,6 +68,14 @@ static gboolean builtin_repr                 (const GValue  *value,
 static gboolean builtin_sqrt                 (const GValue  *value,
                                               GValue        *return_value,
                                               GError       **error);
+static gboolean eq_enum_string               (const GValue  *left,
+                                              const GValue  *right,
+                                              GValue        *return_value,
+                                              GError       **error);
+static gboolean ne_enum_string               (const GValue  *left,
+                                              const GValue  *right,
+                                              GValue        *return_value,
+                                              GError       **error);
 
 static GHashTable *fast_dispatch;
 static BuiltinFunc builtin_funcs [] = {
@@ -85,8 +94,11 @@ build_hash (TmplExprType type,
             GType        left,
             GType        right)
 {
-  g_assert (!left || G_TYPE_IS_FUNDAMENTAL (left));
-  g_assert (!right || G_TYPE_IS_FUNDAMENTAL (right));
+  if (left && !G_TYPE_IS_FUNDAMENTAL (left))
+    return 0;
+
+  if (right && !G_TYPE_IS_FUNDAMENTAL (right))
+    return 0;
 
   return type | (left << 16) | (right << 24);
 }
@@ -132,6 +144,28 @@ throw_type_mismatch (GError       **error,
     return throw_type_mismatch (error, left, right, "invalid add"); \
   } G_STMT_END
 
+static FastDispatch
+find_dispatch_slow (TmplExprSimple *node,
+                    const GValue   *left,
+                    const GValue   *right)
+{
+  if (node->type == TMPL_EXPR_EQ)
+    {
+      if ((G_VALUE_HOLDS_STRING (left) && G_VALUE_HOLDS_ENUM (right)) ||
+          (G_VALUE_HOLDS_STRING (right) && G_VALUE_HOLDS_ENUM (left)))
+        return eq_enum_string;
+    }
+
+  if (node->type == TMPL_EXPR_NE)
+    {
+      if ((G_VALUE_HOLDS_STRING (left) && G_VALUE_HOLDS_ENUM (right)) ||
+          (G_VALUE_HOLDS_STRING (right) && G_VALUE_HOLDS_ENUM (left)))
+        return ne_enum_string;
+    }
+
+  return NULL;
+}
+
 static gboolean
 tmpl_expr_simple_eval (TmplExprSimple  *node,
                        TmplScope       *scope,
@@ -150,16 +184,23 @@ tmpl_expr_simple_eval (TmplExprSimple  *node,
       ((node->right == NULL) ||
        tmpl_expr_eval_internal (node->right, scope, &right, error)))
     {
-      FastDispatch dispatch;
+      FastDispatch dispatch = NULL;
       guint hash;
 
       hash = build_hash (node->type, G_VALUE_TYPE (&left), G_VALUE_TYPE (&right));
-      dispatch = g_hash_table_lookup (fast_dispatch, GINT_TO_POINTER (hash));
 
-      if (G_UNLIKELY (dispatch == NULL))
+      if (hash != 0)
+        dispatch = g_hash_table_lookup (fast_dispatch, GINT_TO_POINTER (hash));
+
+      if G_UNLIKELY (dispatch == NULL)
         {
-          throw_type_mismatch (error, &left, &right, "type mismatch");
-          goto cleanup;
+          dispatch = find_dispatch_slow (node, &left, &right);
+
+          if (dispatch == NULL)
+            {
+              throw_type_mismatch (error, &left, &right, "type mismatch");
+              goto cleanup;
+            }
         }
 
       ret = dispatch (&left, &right, return_value, error);
@@ -511,14 +552,46 @@ cleanup:
   TMPL_CLEAR_VALUE (&left);
   TMPL_CLEAR_VALUE (&right);
 
+  g_assert (ret == TRUE || (error == NULL || *error != NULL));
+
   return ret;
 }
 
+static gchar *
+make_title (const gchar *str)
+{
+  g_auto(GStrv) parts = NULL;
+  GString *ret;
+
+  g_assert (str != NULL);
+
+  ret = g_string_new (NULL);
+
+  for (; *str; str = g_utf8_next_char (str))
+    {
+      gunichar ch = g_utf8_get_char (str);
+
+      if (!g_unichar_isalnum (ch))
+        {
+          if (ret->len && ret->str[ret->len - 1] != ' ')
+            g_string_append_c (ret, ' ');
+          continue;
+        }
+
+      if (ret->len && ret->str[ret->len - 1] != ' ')
+        g_string_append_unichar (ret, ch);
+      else
+        g_string_append_unichar (ret, g_unichar_toupper (ch));
+    }
+
+  return g_string_free (ret, FALSE);
+}
+
 static gboolean
 tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
-                       TmplScope       *scope,
-                       GValue         *return_value,
-                       GError        **error)
+                        TmplScope       *scope,
+                        GValue          *return_value,
+                        GError         **error)
 {
   GValue left = G_VALUE_INIT;
   GValue right = G_VALUE_INIT;
@@ -543,6 +616,109 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
   if (!tmpl_expr_eval_internal (node->object, scope, &left, error))
     goto cleanup;
 
+  if (G_VALUE_HOLDS_STRING (&left))
+    {
+      const gchar *str = g_value_get_string (&left) ?: "";
+
+      /*
+       * TODO: This should be abstracted somewhere else rather than our G-I call.
+       *       Basically we are adding useful string functions like:
+       *
+       *       "foo".upper()
+       *       "foo".lower()
+       *       "foo".casefold()
+       *       "foo".reverse()
+       *       "foo".len()
+       *       "foo".title()
+       */
+      if (FALSE) {}
+      else if (g_str_equal (node->name, "upper"))
+        {
+          g_value_init (return_value, G_TYPE_STRING);
+          g_value_take_string (return_value, g_utf8_strup (str, -1));
+          ret = TRUE;
+        }
+      else if (g_str_equal (node->name, "lower"))
+        {
+          g_value_init (return_value, G_TYPE_STRING);
+          g_value_take_string (return_value, g_utf8_strdown (str, -1));
+          ret = TRUE;
+        }
+      else if (g_str_equal (node->name, "casefold"))
+        {
+          g_value_init (return_value, G_TYPE_STRING);
+          g_value_take_string (return_value, g_utf8_casefold (str, -1));
+          ret = TRUE;
+        }
+      else if (g_str_equal (node->name, "reverse"))
+        {
+          g_value_init (return_value, G_TYPE_STRING);
+          g_value_take_string (return_value, g_utf8_strreverse (str, -1));
+          ret = TRUE;
+        }
+      else if (g_str_equal (node->name, "len"))
+        {
+          g_value_init (return_value, G_TYPE_UINT);
+          g_value_set_uint (return_value, strlen (str));
+          ret = TRUE;
+        }
+      else if (g_str_equal (node->name, "space"))
+        {
+          gchar *space;
+          guint len = strlen (str);
+
+          g_value_init (return_value, G_TYPE_STRING);
+          space = g_malloc (len + 1);
+          memset (space, ' ', len);
+          space[len] = '\0';
+          g_value_take_string (return_value, space);
+          ret = TRUE;
+        }
+      else if (g_str_equal (node->name, "title"))
+        {
+          g_value_init (return_value, G_TYPE_STRING);
+          g_value_take_string (return_value, make_title (str));
+          ret = TRUE;
+        }
+      else
+        {
+          g_set_error (error,
+                       TMPL_ERROR,
+                       TMPL_ERROR_GI_FAILURE,
+                       "No such method %s for string",
+                       node->name);
+        }
+
+      goto cleanup;
+    }
+
+  if (G_VALUE_HOLDS_ENUM (&left))
+    {
+      if (FALSE) {}
+      else if (g_str_equal (node->name, "nick"))
+        {
+          GEnumClass *enum_class = g_type_class_peek (G_VALUE_TYPE (&left));
+          GEnumValue *enum_value = g_enum_get_value (enum_class, g_value_get_enum (&left));
+
+          g_value_init (return_value, G_TYPE_STRING);
+
+          if (enum_value != NULL)
+            g_value_set_static_string (return_value, enum_value->value_nick);
+
+          ret = TRUE;
+        }
+      else
+        {
+          g_set_error (error,
+                       TMPL_ERROR,
+                       TMPL_ERROR_GI_FAILURE,
+                       "No such method %s for enum",
+                       node->name);
+        }
+
+      goto cleanup;
+    }
+
   if (!G_VALUE_HOLDS_OBJECT (&left))
     {
       g_set_error (error,
@@ -569,6 +745,8 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
 
   while (g_type_is_a (type, G_TYPE_OBJECT))
     {
+      guint n_ifaces;
+
       base_info = g_irepository_find_by_gtype (repository, type);
 
       if (base_info == NULL)
@@ -585,6 +763,19 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
       if (function != NULL)
         break;
 
+      /* Maybe the function is found in an interface */
+      n_ifaces = g_object_info_get_n_interfaces ((GIObjectInfo *)base_info);
+      for (i = 0; function == NULL && i < n_ifaces; i++)
+        {
+          GIInterfaceInfo *iface_info;
+
+          iface_info = g_object_info_get_interface ((GIObjectInfo *)base_info, i);
+
+          function = g_interface_info_find_method (iface_info, node->name);
+        }
+      if (function != NULL)
+        break;
+
       type = g_type_parent (type);
     }
 
@@ -814,9 +1005,9 @@ cleanup:
 
 static gboolean
 tmpl_expr_require_eval (TmplExprRequire  *node,
-                       TmplScope        *scope,
-                       GValue          *return_value,
-                       GError         **error)
+                        TmplScope        *scope,
+                        GValue           *return_value,
+                        GError          **error)
 {
   GITypelib *typelib;
   TmplSymbol *symbol;
@@ -831,6 +1022,8 @@ tmpl_expr_require_eval (TmplExprRequire  *node,
                                    G_IREPOSITORY_LOAD_FLAG_LAZY,
                                    error);
 
+  g_assert (typelib != NULL || (error == NULL || *error != NULL));
+
   if (typelib == NULL)
     return FALSE;
 
@@ -888,8 +1081,7 @@ tmpl_expr_eval_internal (TmplExpr   *node,
       return TRUE;
 
     case TMPL_EXPR_STMT_LIST:
-      tmpl_expr_stmt_list_eval ((TmplExprSimple *)node, scope, return_value, error);
-      break;
+      return tmpl_expr_stmt_list_eval ((TmplExprSimple *)node, scope, return_value, error);
 
     case TMPL_EXPR_IF:
     case TMPL_EXPR_WHILE:
@@ -900,7 +1092,6 @@ tmpl_expr_eval_internal (TmplExpr   *node,
 
     case TMPL_EXPR_SYMBOL_ASSIGN:
       return tmpl_expr_symbol_assign_eval ((TmplExprSymbolAssign *)node, scope, return_value, error);
-      break;
 
     case TMPL_EXPR_FN_CALL:
       return tmpl_expr_fn_call_eval ((TmplExprFnCall *)node, scope, return_value, error);
@@ -920,6 +1111,26 @@ tmpl_expr_eval_internal (TmplExpr   *node,
     case TMPL_EXPR_REQUIRE:
       return tmpl_expr_require_eval ((TmplExprRequire *)node, scope, return_value, error);
 
+    case TMPL_EXPR_INVERT_BOOLEAN:
+      {
+        GValue tmp = G_VALUE_INIT;
+        gboolean ret;
+
+        ret = tmpl_expr_eval_internal (((TmplExprSimple *)node)->left, scope, &tmp, error);
+
+        if (ret)
+          {
+            g_value_init (return_value, G_TYPE_BOOLEAN);
+            g_value_set_boolean (return_value, !tmpl_value_as_boolean (&tmp));
+          }
+
+        TMPL_CLEAR_VALUE (&tmp);
+
+        g_assert (ret == TRUE || (error == NULL || *error != NULL));
+
+        return ret;
+      }
+
     default:
       break;
     }
@@ -1041,6 +1252,55 @@ ne_string_string (const GValue  *left,
   return TRUE;
 }
 
+static gboolean
+eq_enum_string (const GValue  *left,
+                const GValue  *right,
+                GValue        *return_value,
+                GError       **error)
+{
+  const gchar *str;
+  GEnumClass *klass;
+  const GEnumValue *val;
+  GType type;
+  gint eval;
+
+  if (G_VALUE_HOLDS_STRING (left))
+    {
+      str = g_value_get_string (left);
+      eval = g_value_get_enum (right);
+      type = G_VALUE_TYPE (right);
+    }
+  else
+    {
+      str = g_value_get_string (right);
+      eval = g_value_get_enum (left);
+      type = G_VALUE_TYPE (left);
+    }
+
+  klass = g_type_class_peek (type);
+  val = g_enum_get_value ((GEnumClass *)klass, eval);
+
+  g_value_init (return_value, G_TYPE_BOOLEAN);
+  g_value_set_boolean (return_value, 0 == g_strcmp0 (str, val->value_nick));
+
+  return TRUE;
+}
+
+static gboolean
+ne_enum_string (const GValue  *left,
+                const GValue  *right,
+                GValue        *return_value,
+                GError       **error)
+{
+  if (eq_enum_string (left, right, return_value, error))
+    {
+      g_value_set_boolean (return_value, !g_value_get_boolean (return_value));
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 #define SIMPLE_OP_FUNC(func_name, ret_type, set_func, get_left, op, get_right)  \
 static gboolean                                                                 \
 func_name (const GValue  *left,                                                 \
@@ -1065,6 +1325,10 @@ SIMPLE_OP_FUNC (gt_double_double,  G_TYPE_BOOLEAN, set_boolean, get_double, >,
 SIMPLE_OP_FUNC (eq_double_double,  G_TYPE_BOOLEAN, set_boolean, get_double, ==, get_double)
 SIMPLE_OP_FUNC (ne_double_double,  G_TYPE_BOOLEAN, set_boolean, get_double, !=, get_double)
 SIMPLE_OP_FUNC (gte_double_double, G_TYPE_BOOLEAN, set_boolean, get_double, >=, get_double)
+SIMPLE_OP_FUNC (eq_uint_double,    G_TYPE_BOOLEAN, set_boolean, get_uint,   ==, get_double)
+SIMPLE_OP_FUNC (eq_double_uint,    G_TYPE_BOOLEAN, set_boolean, get_double, ==, get_uint)
+SIMPLE_OP_FUNC (ne_uint_double,    G_TYPE_BOOLEAN, set_boolean, get_uint,   !=, get_double)
+SIMPLE_OP_FUNC (ne_double_uint,    G_TYPE_BOOLEAN, set_boolean, get_double, !=, get_uint)
 
 #undef SIMPLE_OP_FUNC
 
@@ -1092,6 +1356,10 @@ build_dispatch_table (void)
   ADD_DISPATCH_FUNC (TMPL_EXPR_LTE,         G_TYPE_DOUBLE, G_TYPE_DOUBLE, lte_double_double);
   ADD_DISPATCH_FUNC (TMPL_EXPR_GTE,         G_TYPE_DOUBLE, G_TYPE_DOUBLE, gte_double_double);
   ADD_DISPATCH_FUNC (TMPL_EXPR_EQ,          G_TYPE_DOUBLE, G_TYPE_DOUBLE, eq_double_double);
+  ADD_DISPATCH_FUNC (TMPL_EXPR_EQ,          G_TYPE_UINT,   G_TYPE_DOUBLE, eq_uint_double);
+  ADD_DISPATCH_FUNC (TMPL_EXPR_EQ,          G_TYPE_DOUBLE, G_TYPE_UINT,   eq_double_uint);
+  ADD_DISPATCH_FUNC (TMPL_EXPR_NE,          G_TYPE_UINT,   G_TYPE_DOUBLE, ne_uint_double);
+  ADD_DISPATCH_FUNC (TMPL_EXPR_NE,          G_TYPE_DOUBLE, G_TYPE_UINT,   ne_double_uint);
   ADD_DISPATCH_FUNC (TMPL_EXPR_MUL,         G_TYPE_STRING, G_TYPE_DOUBLE, mul_string_double);
   ADD_DISPATCH_FUNC (TMPL_EXPR_MUL,         G_TYPE_DOUBLE, G_TYPE_STRING, mul_double_string);
   ADD_DISPATCH_FUNC (TMPL_EXPR_EQ,          G_TYPE_STRING, G_TYPE_STRING, eq_string_string);
@@ -1108,6 +1376,8 @@ tmpl_expr_eval (TmplExpr   *node,
                 GValue     *return_value,
                 GError    **error)
 {
+  gboolean ret;
+
   g_return_val_if_fail (node != NULL, FALSE);
   g_return_val_if_fail (scope != NULL, FALSE);
   g_return_val_if_fail (return_value != NULL, FALSE);
@@ -1116,7 +1386,11 @@ tmpl_expr_eval (TmplExpr   *node,
   if (g_once_init_enter (&fast_dispatch))
     g_once_init_leave (&fast_dispatch, build_dispatch_table ());
 
-  return tmpl_expr_eval_internal (node, scope, return_value, error);
+  ret = tmpl_expr_eval_internal (node, scope, return_value, error);
+
+  g_assert (ret == TRUE || (error == NULL || *error != NULL));
+
+  return ret;
 }
 
 static gboolean
diff --git a/contrib/tmpl/tmpl-expr-types.h b/contrib/tmpl/tmpl-expr-types.h
index 250113b..0d4b1bb 100644
--- a/contrib/tmpl/tmpl-expr-types.h
+++ b/contrib/tmpl/tmpl-expr-types.h
@@ -72,6 +72,7 @@ typedef enum
   TMPL_EXPR_REQUIRE,
   TMPL_EXPR_AND,
   TMPL_EXPR_OR,
+  TMPL_EXPR_INVERT_BOOLEAN,
 } TmplExprType;
 
 typedef enum
diff --git a/contrib/tmpl/tmpl-expr.c b/contrib/tmpl/tmpl-expr.c
index f329bdb..228a882 100644
--- a/contrib/tmpl/tmpl-expr.c
+++ b/contrib/tmpl/tmpl-expr.c
@@ -83,6 +83,7 @@ tmpl_expr_destroy (TmplExpr *self)
     case TMPL_EXPR_USER_FN_CALL:
     case TMPL_EXPR_AND:
     case TMPL_EXPR_OR:
+    case TMPL_EXPR_INVERT_BOOLEAN:
       g_clear_pointer (&self->simple.left, tmpl_expr_unref);
       g_clear_pointer (&self->simple.right, tmpl_expr_unref);
       break;
@@ -210,6 +211,17 @@ tmpl_expr_new_simple (TmplExprType  type,
 }
 
 TmplExpr *
+tmpl_expr_new_invert_boolean (TmplExpr *left)
+{
+  TmplExprSimple *ret;
+
+  ret = tmpl_expr_new (TMPL_EXPR_INVERT_BOOLEAN);
+  ret->left = left;
+
+  return (TmplExpr *)ret;
+}
+
+TmplExpr *
 tmpl_expr_new_flow (TmplExprType  type,
                     TmplExpr     *condition,
                     TmplExpr     *primary,
diff --git a/contrib/tmpl/tmpl-expr.h b/contrib/tmpl/tmpl-expr.h
index d6e2826..1edeb6a 100644
--- a/contrib/tmpl/tmpl-expr.h
+++ b/contrib/tmpl/tmpl-expr.h
@@ -36,6 +36,7 @@ gboolean  tmpl_expr_eval              (TmplExpr         *expr,
                                        GValue           *return_value,
                                        GError          **error);
 TmplExpr *tmpl_expr_new_boolean       (gboolean          value);
+TmplExpr *tmpl_expr_new_invert_boolean(TmplExpr         *left);
 TmplExpr *tmpl_expr_new_getattr       (TmplExpr         *left,
                                        const gchar      *attr);
 TmplExpr *tmpl_expr_new_setattr       (TmplExpr         *left,
diff --git a/contrib/tmpl/tmpl-iterator.c b/contrib/tmpl/tmpl-iterator.c
index 1446d68..4c1c897 100644
--- a/contrib/tmpl/tmpl-iterator.c
+++ b/contrib/tmpl/tmpl-iterator.c
@@ -63,7 +63,10 @@ list_model_move_next (TmplIterator *iter)
   guint index = GPOINTER_TO_INT (iter->data1);
   guint n_items = GPOINTER_TO_INT (iter->data2);
 
-  if (++index < n_items)
+  index++;
+
+  /* We are 1 based indexing here */
+  if (index <= n_items)
     {
       iter->data1 = GINT_TO_POINTER (index);
       return TRUE;
@@ -79,14 +82,14 @@ list_model_get_value (TmplIterator *iter,
   guint index = GPOINTER_TO_INT (iter->data1);
   GObject *obj;
 
-  obj = g_list_model_get_item (iter->instance, index);
+  g_return_val_if_fail (index > 0, FALSE);
 
-  if (obj != NULL)
-    g_value_init (value, G_OBJECT_TYPE (obj));
-  else
-    g_value_init (value, G_TYPE_OBJECT);
+  obj = g_list_model_get_item (iter->instance, index - 1);
 
-  g_value_take_object (value, obj);
+  g_value_init (value, g_list_model_get_item_type (iter->instance));
+
+  if (obj != NULL)
+    g_value_take_object (value, obj);
 
   return TRUE;
 }
@@ -113,7 +116,17 @@ tmpl_iterator_init (TmplIterator *iter,
       iter->move_next = list_model_move_next;
       iter->get_value = list_model_get_value;
       iter->destroy = NULL;
+
+      if (iter->instance != NULL)
+        {
+          guint n_items;
+
+          n_items = g_list_model_get_n_items (iter->instance);
+          iter->data1 = GUINT_TO_POINTER (iter->data1);
+          iter->data2 = GUINT_TO_POINTER (n_items);
+        }
     }
+
   /* TODO: More iter types */
 }
 
diff --git a/contrib/tmpl/tmpl-scope.c b/contrib/tmpl/tmpl-scope.c
index a4a0792..f62e6c8 100644
--- a/contrib/tmpl/tmpl-scope.c
+++ b/contrib/tmpl/tmpl-scope.c
@@ -133,7 +133,8 @@ tmpl_scope_get_full (TmplScope   *self,
       if (parent->resolver)
         {
           if (parent->resolver (parent, name, &symbol, parent->resolver_data) && symbol)
-            goto save_symbol;
+            tmpl_scope_set (self, name, symbol);
+          return symbol;
         }
     }
 
@@ -141,20 +142,10 @@ tmpl_scope_get_full (TmplScope   *self,
     {
       /* Define the symbol in this scope */
       symbol = tmpl_symbol_new ();
-      goto save_symbol;
+      tmpl_scope_set (self, name, 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;
 }
 
 /**
@@ -172,6 +163,81 @@ tmpl_scope_get (TmplScope   *self,
 }
 
 /**
+ * tmpl_scope_set:
+ *
+ * If the symbol already exists, it will be overwritten.
+ *
+ * Parameter: (transfer none): #t
+ */
+void
+tmpl_scope_set (TmplScope   *self,
+                const gchar *name,
+                TmplSymbol  *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);
+}
+
+/**
+ * tmpl_scope_set_value:
+ */
+void
+tmpl_scope_set_value (TmplScope     *self,
+                       const gchar  *name,
+                       const GValue *symbol)
+{
+  tmpl_symbol_assign_value (tmpl_scope_get_full (self, name, TRUE), symbol);
+}
+
+/**
+ * tmpl_scope_set_boolean:
+ */
+void
+tmpl_scope_set_boolean (TmplScope  *self,
+                       const gchar *name,
+                       gboolean    symbol)
+{
+  tmpl_symbol_assign_boolean (tmpl_scope_get_full (self, name, TRUE), symbol);
+}
+
+/**
+ * tmpl_scope_set_double:
+ */
+void
+tmpl_scope_set_double (TmplScope   *self,
+                       const gchar *name,
+                       gdouble     symbol)
+{
+  tmpl_symbol_assign_double (tmpl_scope_get_full (self, name, TRUE), symbol);
+}
+
+/**
+ * tmpl_scope_set_object:
+ */
+void
+tmpl_scope_set_object (TmplScope   *self,
+                       const gchar *name,
+                       gpointer    symbol)
+{
+  tmpl_symbol_assign_object (tmpl_scope_get_full (self, name, TRUE), symbol);
+}
+
+/**
+ * tmpl_scope_set_string:
+ */
+void
+tmpl_scope_set_string (TmplScope   *self,
+                       const gchar *name,
+                       const gchar *symbol)
+{
+  tmpl_symbol_assign_string (tmpl_scope_get_full (self, name, TRUE), symbol);
+}
+
+/**
  * tmpl_scope_peek:
  *
  * If the symbol could not be found, %NULL is returned.
diff --git a/contrib/tmpl/tmpl-scope.h b/contrib/tmpl/tmpl-scope.h
index 12e1871..838fcf5 100644
--- a/contrib/tmpl/tmpl-scope.h
+++ b/contrib/tmpl/tmpl-scope.h
@@ -43,6 +43,21 @@ TmplSymbol *tmpl_scope_get             (TmplScope         *self,
 void        tmpl_scope_set             (TmplScope         *self,
                                         const gchar       *name,
                                         TmplSymbol        *symbol);
+void        tmpl_scope_set_value       (TmplScope         *self,
+                                        const gchar       *name,
+                                        const GValue      *symbol);
+void        tmpl_scope_set_boolean     (TmplScope         *self,
+                                        const gchar       *name,
+                                        gboolean          symbol);
+void        tmpl_scope_set_double      (TmplScope         *self,
+                                        const gchar       *name,
+                                        gdouble           symbol);
+void        tmpl_scope_set_string      (TmplScope         *self,
+                                        const gchar       *name,
+                                        const gchar       *symbol);
+void        tmpl_scope_set_object      (TmplScope         *self,
+                                        const gchar       *name,
+                                        gpointer          symbol);
 void        tmpl_scope_set_resolver    (TmplScope         *self,
                                         TmplScopeResolver  resolver,
                                         gpointer           user_data,
diff --git a/contrib/tmpl/tmpl-template.c b/contrib/tmpl/tmpl-template.c
index e666898..5ff2bb0 100644
--- a/contrib/tmpl/tmpl-template.c
+++ b/contrib/tmpl/tmpl-template.c
@@ -300,7 +300,7 @@ tmpl_template_expand_visitor (TmplNode *node,
   g_assert (TMPL_IS_NODE (node));
   g_assert (state != NULL);
 
-/* Short cirtcuit if an error occurred */
+  /* Short cirtcuit if an error occurred */
   if (state->result == FALSE)
     return;
 
@@ -395,6 +395,9 @@ tmpl_template_expand_visitor (TmplNode *node,
               TMPL_CLEAR_VALUE (&value);
 
               tmpl_node_visit_children (node, tmpl_template_expand_visitor, state);
+
+              if (state->result == FALSE)
+                break;
             }
 
           state->scope = old_scope;
@@ -477,6 +480,8 @@ tmpl_template_expand (TmplTemplate  *self,
   if (local_scope != NULL)
     tmpl_scope_unref (local_scope);
 
+  g_assert (state.result == TRUE || (state.error == NULL || *state.error != NULL));
+
   return state.result;
 }
 
@@ -509,6 +514,13 @@ tmpl_template_expand_string (TmplTemplate  *self,
 
     {
       g_object_unref (stream);
+
+      if (error != NULL && *error == NULL)
+        g_set_error (error,
+                     G_IO_ERROR,
+                     G_IO_ERROR_UNKNOWN,
+                     "An unknown error occurred while expanding the template");
+
       return NULL;
     }
 


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