grim/gplate

propagate from branch 'org.guifications.misc.gplate.template_cleanup' (head 360b8727b364d289c837bab577bccc2366239da5)
to branch 'org.guifications.misc.gplate' (head 11f9b09dd583815ede9e224c2d0a2f9d9304d1f9)
--- a/ChangeLog Fri Oct 10 23:17:45 2008 -0500
+++ b/ChangeLog Sun Jan 04 02:02:57 2009 -0600
@@ -1,3 +1,6 @@
+Version 0.0.3 ??/??/????:
+ * Added an iterator to GPlateObjectVariable
+
Version 0.0.2 09/20/2008:
* Fixed the bug where a default tag that didn't start with a word rendered
an empty string
--- a/README Fri Oct 10 23:17:45 2008 -0500
+++ b/README Sun Jan 04 02:02:57 2009 -0600
@@ -6,4 +6,7 @@
that are already using glib.
The idea behind gplate is to be extendable by the applications using it so that
-it can fit whatever you needs may arise.
+it can fit whatever you needs may arise. You can customize the tags and the
+functions bound to them. You can also create easily your own functions and
+variables.
+
--- a/autogen.sh Fri Oct 10 23:17:45 2008 -0500
+++ b/autogen.sh Sun Jan 04 02:02:57 2009 -0600
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (C) 2007-2008 Gary Kramlich <grim@reaperworld.com>
+# Copyright (C) 2008 Gary Kramlich <grim@reaperworld.com>
#
# 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
@@ -32,6 +32,7 @@
# AUTOHEADER_FLAGS - command line arguments to pass to autoheader
# AUTOMAKE_FLAGS - command line arguments to pass to automake flags
# CONFIGURE_FLAGS - command line arguments to pass to configure
+# GTKDOCIZE_FLAGS - command line arguments to pass to gtkdocize
# INTLTOOLIZE_FLAGS - command line arguments to pass to intltoolize
# LIBTOOLIZE_FLAGS - command line arguments to pass to libtoolize
#
@@ -95,7 +96,7 @@
BIN=`which ${CMD}`
if [ x"${BIN}" = x"" ] ; then
- echo "not found.\n"
+ echo "not found."
echo "${CMD} is required to build ${PACKAGE}!"
exit 1;
fi
@@ -107,7 +108,7 @@
CMD=$1
shift
- OUTPUT=`mktemp .autogen-XXXXXX`
+ OUTPUT=`mktemp autogen-XXXXXX`
# we have to stash ${@} into a variable, otherwise printf has "issues" if
# ${@} was expanded from a variable. Fortunately, this let's us clean up
@@ -182,6 +183,6 @@
###############################################################################
# Run configure
###############################################################################
-echo "running './configure ${CONFIGURE_FLAGS} $@'"
+echo "running ./configure ${CONFIGURE_FLAGS} $@"
./configure ${CONFIGURE_FLAGS} $@
--- a/configure.ac Fri Oct 10 23:17:45 2008 -0500
+++ b/configure.ac Sun Jan 04 02:02:57 2009 -0600
@@ -14,7 +14,7 @@
dnl ################################################################
GPLATE_MAJOR_VERSION=0
GPLATE_MINOR_VERSION=0
-GPLATE_MICRO_VERSION=2
+GPLATE_MICRO_VERSION=3
GPLATE_DEVEL_VERSION=0
GPLATE_VERSION=$GPLATE_MAJOR_VERSION.$GPLATE_MINOR_VERSION.$GPLATE_MICRO_VERSION
@@ -108,13 +108,15 @@
dnl #######################################################################
dnl # Look for the C compiler
dnl #######################################################################
-AC_MSG_CHECKING([useful C based html templating library so I don't have to write one])
+AC_MSG_CHECKING([useful C based templating library so I don't have to write one])
AC_MSG_RESULT(no)
CFLAGS_save="$CFLAGS"
AC_PROG_CC
CFLAGS="$CFLAGS_save"
-AC_ARG_ENABLE(debug, [ --enable-debug compile with debugging support],,enable_debug=no)
+AC_ARG_ENABLE(debug,
+ AC_HELP_STRING([--enable-debug],[compile with debugging support])
+ ,,enable_debug=no)
if test x"$enable_debug" = x"yes" ; then
AC_DEFINE(DEBUG, 1, [Define if debugging is enabled.])
@@ -128,7 +130,9 @@
dnl #######################################################################
dnl # do we want to build the tests?
dnl #######################################################################
-AC_ARG_ENABLE(tests, [ --enable-tests build test programs],,enable_tests=no)
+AC_ARG_ENABLE(tests,
+ AC_HELP_STRING([--enable-tests],[build test programs])
+ ,,enable_tests=no)
CHECK_CFLAGS=
CHECK_LIBS=
--- a/gplate/functions/gplate-for-function.c Fri Oct 10 23:17:45 2008 -0500
+++ b/gplate/functions/gplate-for-function.c Sun Jan 04 02:02:57 2009 -0600
@@ -26,6 +26,7 @@
#include <gplate/gplate-iterator.h>
#include <gplate/gplate-tag.h>
#include <gplate/gplate-variable.h>
+#include <gplate/tags/gplate-code-tag.h>
#define SYNTAX_REGEX "^(.+)\\s+in\\s+(.+)$"
@@ -116,8 +117,8 @@
iter = gplate_collection_get_iterator(collection);
while(gplate_iterator_has_next(iter)) {
GPlateCollection *tc = GPLATE_COLLECTION(tplate);
- GPlateTag *tag = NULL;
GPlateVariable *var = NULL;
+ gchar *output = NULL;
guint count = 1;
gboolean ret = FALSE;
@@ -130,21 +131,10 @@
ret = gplate_collection_add_variable_with_name(tc, iter_name, var);
/* iterate through the tokens */
- while((tag = gplate_template_next_tag(tplate))) {
- const gchar *contents = NULL;
- gchar *output = NULL;
-
- contents = gplate_tag_get_contents(tag);
-
- if(contents && g_utf8_collate(contents, "endfor") == 0)
- break;
-
- output = gplate_template_render_tag(tplate, tag);
-
- g_string_append_printf(str, "%s", output);
-
- count++;
- }
+ output = gplate_template_render_until(tplate, &count,
+ GPLATE_TYPE_CODE_TAG, "endfor",
+ NULL);
+ g_string_append_printf(str, "%s", output);
if(gplate_iterator_has_next(iter))
gplate_template_nth_previous_tag(tplate, count);
--- a/gplate/gplate-template.c Fri Oct 10 23:17:45 2008 -0500
+++ b/gplate/gplate-template.c Sun Jan 04 02:02:57 2009 -0600
@@ -56,6 +56,11 @@
GList *current_token;
} GPlateTemplatePrivate;
+typedef struct {
+ GType type;
+ gchar *contents;
+} GPlateTemplateTagData;
+
/******************************************************************************
* Globals
*****************************************************************************/
@@ -140,16 +145,11 @@
return ret;
}
-typedef struct {
- const gchar *contents;
- GType type;
-} GPlateTemplateFindTagData;
-
static void
gplate_template_find_tag_helper(GType tag, const gchar *prefix,
const gchar *suffix, gpointer d)
{
- GPlateTemplateFindTagData *data = (GPlateTemplateFindTagData *)d;
+ GPlateTemplateTagData *data = (GPlateTemplateTagData *)d;
gchar *pattern = NULL;
/* if our tag info doesn't have a prefix or a suffix, we drop out. */
@@ -173,8 +173,8 @@
}
static GType
-gplate_template_find_tag(GPlateTemplate *tplate, const gchar *contents) {
- GPlateTemplateFindTagData d;
+gplate_template_find_tag(GPlateTemplate *tplate, gchar *contents) {
+ GPlateTemplateTagData d;
d.contents = contents;
d.type = G_TYPE_INVALID;
@@ -701,6 +701,114 @@
}
/**
+ * gplate_template_render_until:
+ * @tplate: The #GPlateTemplate
+ * @ntags: A return address for the number of tags that were rendered
+ * @Varargs: A NULL terminated list of #GType, content pairs.
+ *
+ * Renders the tags in a template from the current point until it a tag is
+ * found that is the correct type and has the same contents as one of the
+ * #GType, content pairs.
+ *
+ *
+ */
+gchar *
+gplate_template_render_until(GPlateTemplate *tplate, guint *ntags, ...) {
+ GPlateTag *tag = NULL;
+ GList *l = NULL;
+ GString *str = NULL;
+ GQueue *queue = NULL;
+ GType type = G_TYPE_INVALID;
+ gchar *ret = NULL;
+ guint count = 0;
+ gboolean backup = FALSE;
+ va_list args;
+
+ g_return_val_if_fail(GPLATE_IS_TEMPLATE(tplate), NULL);
+
+ str = g_string_new("");
+
+ queue = g_queue_new();
+
+ /* store all of the content/tag pairs */
+ va_start(args, ntags);
+ while((type = va_arg(args, gsize)) != G_TYPE_INVALID) {
+ GPlateTemplateTagData *td = NULL;
+ gchar *contents = NULL;
+
+ td = g_new(GPlateTemplateTagData, 1);
+
+ contents = va_arg(args, gchar *);
+ td->contents = contents ? g_strdup(contents) : NULL;
+
+ td->type = type;
+
+ g_queue_push_tail(queue, td);
+ }
+ va_end(args);
+
+ /* now iterate the tags */
+ while((tag = gplate_template_next_tag(tplate))) {
+ GPlateTemplateTagData ctd;
+ gboolean stop = FALSE;
+
+ ctd.contents = gplate_tag_get_contents(tag);
+ ctd.type = G_OBJECT_TYPE(tag);
+
+ /* run through our list of TagData's to stop on */
+ for(l = queue->head; l; l = l->next) {
+ GPlateTemplateTagData *td = (GPlateTemplateTagData *)l->data;
+
+ if(ctd.type == td->type &&
+ g_utf8_collate(ctd.contents, td->contents) == 0)
+ {
+ stop = TRUE;
+ backup = TRUE;
+ }
+ }
+
+ g_free(ctd.contents);
+
+ if(stop) {
+ count++;
+ break;
+ }
+
+ g_string_append_printf(str, "%s",
+ gplate_template_render_tag(tplate, tag));
+
+ count++;
+ }
+
+ /* now clean everything up... */
+ for(l = queue->head; l; l = l->next) {
+ GPlateTemplateTagData *td = (GPlateTemplateTagData *)l->data;
+
+ g_free(td->contents);
+ g_free(td);
+ }
+
+ g_queue_free(queue);
+
+ ret = str->str;
+ g_string_free(str, FALSE);
+
+ /* if backup is set, we back up to the tag which caused us to stop. In
+ * other words, the tag stack will currently be at the tag after the one
+ * we stopped at, but we want to be on the one that we stopped on.
+ */
+ if(backup) {
+ gplate_template_previous_tag(tplate);
+ count--;
+ }
+
+ if(ntags)
+ *ntags = count;
+
+ return ret;
+}
+
+/**
* gplate_template_first_tag:
* @tplate: The #GPlateTemplate.
*
@@ -772,7 +880,7 @@
*
* Moves the tag stack forward one tag and returns it.
*
- * Return Value: The previous tag or NULL.
+ * Return Value: The next tag or NULL.
*/
GPlateTag *
gplate_template_next_tag(GPlateTemplate *tplate) {
@@ -876,7 +984,7 @@
klass->insert_tags(tplate, tags);
}
-gchar *
+static gchar *
gplate_template_render_token(GPlateTemplate *tplate, const gchar *contents,
GType tag, GError **error)
{
--- a/gplate/gplate-template.h Fri Oct 10 23:17:45 2008 -0500
+++ b/gplate/gplate-template.h Sun Jan 04 02:02:57 2009 -0600
@@ -76,6 +76,8 @@
gchar *gplate_template_render(GPlateTemplate *tplate, const gchar *tplate_string, GError **error);
gchar *gplate_template_render_file(GPlateTemplate *tplate, const gchar *filename, GError **error);
+gchar *gplate_template_render_until(GPlateTemplate *tplate, guint *ntags, ...);
+
GPlateTag *gplate_template_first_tag(GPlateTemplate *tplate);
GPlateTag *gplate_template_last_tag(GPlateTemplate *tplate);
GPlateTag *gplate_template_current_tag(GPlateTemplate *tplate);
--- a/gplate/variables/gplate-object-variable.c Fri Oct 10 23:17:45 2008 -0500
+++ b/gplate/variables/gplate-object-variable.c Sun Jan 04 02:02:57 2009 -0600
@@ -29,6 +29,11 @@
#define GPLATE_OBJECT_VARIABLE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GPLATE_TYPE_OBJECT_VARIABLE, GPlateObjectVariablePrivate))
+#define GPLATE_TYPE_OBJECT_VARIABLE_ITERATOR (gplate_object_variable_iterator_get_gtype())
+#define GPLATE_OBJECT_VARIABLE_ITERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GPLATE_TYPE_OBJECT_VARIABLE_ITERATOR, GPlateObjectVariableIterator))
+
+static GType gplate_object_variable_iterator_get_gtype(void);
+
/******************************************************************************
* Enums
*****************************************************************************/
@@ -45,23 +50,219 @@
GObject *object;
} GPlateObjectVariablePrivate;
+typedef struct {
+ GObject gparent;
+
+ GPlateObjectVariable *objvar;
+
+ gboolean inited;
+
+ GParamSpec **elements;
+ guint current;
+ guint total;
+} GPlateObjectVariableIterator;
+
+typedef struct {
+ GObjectClass gparent;
+} GPlateObjectVariableIteratorClass;
+
/******************************************************************************
* Globals
*****************************************************************************/
static GObjectClass *parent_class = NULL;
+static GObjectClass *iterator_parent_class = NULL;
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static GPlateVariable *
+gplate_variable_from_paramspec(GObject *obj, GParamSpec *pspec) {
+ GPlateVariable *variable = NULL;
+ GValue value = { 0, };
+ const gchar *name = NULL;
+
+ /* initialize our value to the type of the pspec */
+ g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+ name = g_param_spec_get_name(pspec);
+ g_object_get_property(obj, name, &value);
+
+ switch(G_PARAM_SPEC_VALUE_TYPE(pspec)) {
+ case G_TYPE_STRING:
+ variable =
+ gplate_variable_new_from_string(name,
+ g_value_get_string(&value));
+ break;
+ case G_TYPE_INT:
+ variable =
+ gplate_variable_new_from_integer(name,
+ g_value_get_int(&value));
+ break;
+ case G_TYPE_FLOAT:
+ variable =
+ gplate_variable_new_from_float(name,
+ g_value_get_float(&value));
+ break;
+ case G_TYPE_DOUBLE:
+ variable =
+ gplate_variable_new_from_double(name,
+ g_value_get_double(&value));
+ break;
+ case G_TYPE_OBJECT:
+ variable = gplate_object_variable_new_from_object(name,
+ g_value_get_object(&value));
+ break;
+ default:
+ variable = NULL;
+ break;
+ }
+
+ return variable;
+}
/******************************************************************************
- * Interface Stuff
+ * Iterator Interface Stuff
+ *****************************************************************************/
+static gboolean
+gplate_object_variable_iterator_has_next(const GPlateIterator *iter) {
+ GPlateObjectVariableIterator *realiter =
+ GPLATE_OBJECT_VARIABLE_ITERATOR(iter);
+
+ if(realiter->inited)
+ return (realiter->current < realiter->total - 1);
+ else
+ return (realiter->elements != NULL);
+
+ return FALSE;
+}
+
+static GPlateVariable *
+gplate_object_variable_iterator_next(GPlateIterator *iter) {
+ GPlateObjectVariableIterator *realiter = NULL;
+ GObject *obj = NULL;
+ GParamSpec *pspec = NULL;
+
+ realiter = GPLATE_OBJECT_VARIABLE_ITERATOR(iter);
+
+ if(!realiter->inited) {
+ realiter->current = 0;
+ realiter->inited = TRUE;
+ } else {
+ realiter->current++;
+ }
+
+ if(realiter->current >= realiter->total)
+ return NULL;
+
+ pspec = realiter->elements[realiter->current];
+
+ obj = gplate_object_variable_get_object(realiter->objvar);
+
+ return gplate_variable_from_paramspec(obj, pspec);
+}
+
+static void
+gplate_object_variable_iterator_iface_init(GPlateIteratorIface *iface) {
+ iface->has_next = gplate_object_variable_iterator_has_next;
+ iface->next = gplate_object_variable_iterator_next;
+}
+
+/******************************************************************************
+ * Iterator Object Stuff
+ *****************************************************************************/
+static void
+gplate_object_variable_iterator_finalize(GObject *obj) {
+ GPlateObjectVariableIterator *iter = GPLATE_OBJECT_VARIABLE_ITERATOR(obj);
+
+ g_object_unref(iter->objvar);
+ g_free(iter->elements);
+
+ G_OBJECT_CLASS(iterator_parent_class)->finalize(obj);
+}
+
+static void
+gplate_object_variable_iterator_class_init(
+ GPlateObjectVariableIteratorClass *klass)
+{
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ iterator_parent_class = g_type_class_peek_parent(klass);
+
+ obj_class->finalize = gplate_object_variable_iterator_finalize;
+}
+
+/******************************************************************************
+ * Iterator API
+ *****************************************************************************/
+static GType
+gplate_object_variable_iterator_get_gtype(void) {
+ static GType type = 0;
+
+ if(G_UNLIKELY(type == 0)) {
+ static const GTypeInfo info = {
+ sizeof(GPlateObjectVariableIteratorClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)gplate_object_variable_iterator_class_init,
+ NULL,
+ NULL,
+ sizeof(GPlateObjectVariableIterator),
+ 0,
+ NULL,
+ };
+
+ static const GInterfaceInfo iterator_info = {
+ (GInterfaceInitFunc)gplate_object_variable_iterator_iface_init,
+ NULL,
+ NULL,
+ };
+
+ type = g_type_register_static(G_TYPE_OBJECT,
+ "GPlateObjectVariableIterator",
+ &info, 0);
+
+ g_type_add_interface_static(type, GPLATE_TYPE_ITERATOR,
+ &iterator_info);
+ }
+
+ return type;
+}
+
+static GPlateIterator *
+gplate_object_variable_iterator_new(GPlateObjectVariable *objvar) {
+ GPlateIterator *iter = NULL;
+ GPlateObjectVariableIterator *realiter = NULL;
+ GPlateObjectVariablePrivate *priv = NULL;
+ GObjectClass *klass = NULL;
+
+ iter = g_object_new(GPLATE_TYPE_OBJECT_VARIABLE_ITERATOR, NULL);
+
+ realiter = GPLATE_OBJECT_VARIABLE_ITERATOR(iter);
+
+ realiter->objvar = g_object_ref(objvar);
+
+ priv = GPLATE_OBJECT_VARIABLE_GET_PRIVATE(objvar);
+
+ klass = G_OBJECT_GET_CLASS(priv->object);
+ realiter->elements = g_object_class_list_properties(klass,
+ &realiter->total);
+
+ realiter->current = 0;
+ realiter->inited = FALSE;
+
+ return iter;
+}
+
+/******************************************************************************
+ * Collection Interface Stuff
*****************************************************************************/
static GPlateVariable *
gplate_object_variable_find_variable(const GPlateCollection *collection,
const gchar *name)
{
GPlateObjectVariablePrivate *priv = NULL;
- GPlateVariable *variable = NULL;
GParamSpec *pspec = NULL;
GObjectClass *obj_class = NULL;
- GValue val = { 0, };
gchar *aname = NULL, *dot = NULL;
g_return_val_if_fail(name, NULL);
@@ -94,48 +295,24 @@
if(!G_IS_PARAM_SPEC(pspec))
return NULL;
- /* We know the type early, so we'll initialize our value to that type */
- g_value_init(&val, G_PARAM_SPEC_VALUE_TYPE(pspec));
+ /* now we have the value, so let's create our variable */
+ return gplate_variable_from_paramspec(priv->object, pspec);
+}
- /* now we have the value, so let's create our variable */
- switch(G_PARAM_SPEC_VALUE_TYPE(pspec)) {
- case G_TYPE_STRING:
- variable =
- gplate_variable_new_from_string(g_param_spec_get_name(pspec),
- g_value_get_string(&val));
- break;
- case G_TYPE_INT:
- variable =
- gplate_variable_new_from_integer(g_param_spec_get_name(pspec),
- g_value_get_int(&val));
- break;
- case G_TYPE_FLOAT:
- variable =
- gplate_variable_new_from_float(g_param_spec_get_name(pspec),
- g_value_get_float(&val));
- break;
- case G_TYPE_DOUBLE:
- variable =
- gplate_variable_new_from_double(g_param_spec_get_name(pspec),
- g_value_get_double(&val));
- break;
- case G_TYPE_OBJECT:
- variable = gplate_object_variable_new_from_object(
- g_param_spec_get_name(pspec),
- g_value_get_object(&val));
- break;
- default:
- variable = NULL;
- break;
- }
-
- return variable;
+static GPlateIterator *
+gplate_object_variable_get_iterator(GPlateCollection *collection) {
+ GPlateObjectVariable *objvar = GPLATE_OBJECT_VARIABLE(collection);
+
+ return gplate_object_variable_iterator_new(objvar);
}
static void
gplate_object_variable_collection_init(GPlateCollectionIface *iface) {
iface->find_variable = gplate_object_variable_find_variable;
iface->add_variable_with_name = NULL;
+ iface->remove_variable = NULL;
+ iface->remove_all = NULL;
+ iface->get_iterator = gplate_object_variable_get_iterator;
}
/******************************************************************************
--- a/tests/test-dictionary-variable.c Fri Oct 10 23:17:45 2008 -0500
+++ b/tests/test-dictionary-variable.c Sun Jan 04 02:02:57 2009 -0600
@@ -193,6 +193,7 @@
{ "ten", "10" },
{ "three", "3" },
{ "two", "2" },
+ { NULL, NULL },
};
iterator_test(vd);