[glib] resources: compiler: Allow stripping blanks from xml data
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] resources: compiler: Allow stripping blanks from xml data
- Date: Wed, 25 Jan 2012 13:48:25 +0000 (UTC)
commit 45783c5927f32cae965c67db14adb8422373d345
Author: Christian Persch <chpe gnome org>
Date: Sat Jan 14 22:34:15 2012 +0100
resources: compiler: Allow stripping blanks from xml data
It's hardly useful to bloat the resource data with blanks intended only
for human readability, so add a preprocessing option that uses xmllint --noblanks
to strip these.
Bug #667929.
docs/reference/gio/glib-compile-resources.xml | 14 +++
gio/glib-compile-resources.c | 111 +++++++++++++++++++++++--
gio/gresource.c | 10 ++-
gio/tests/test.gresource.xml | 1 +
4 files changed, 129 insertions(+), 7 deletions(-)
---
diff --git a/docs/reference/gio/glib-compile-resources.xml b/docs/reference/gio/glib-compile-resources.xml
index 4bcfaa2..c3f6466 100644
--- a/docs/reference/gio/glib-compile-resources.xml
+++ b/docs/reference/gio/glib-compile-resources.xml
@@ -95,6 +95,20 @@ at initialization and uninitialization time.
</variablelist>
</refsect2>
+
+<refsect2><title>Environment Variables</title>
+<variablelist>
+
+<varlistentry>
+<term><envar>XMLLINT</envar></term>
+<listitem><para>
+The full path to the xmllint executable. This is used to preprocess resources with the
+<literal>xml-stripblanks</literal> preprocessing option. If this environment variable is not
+set, xmllint is searched in the <envar>PATH</envar>.
+</para></listitem>
+</varlistentry>
+</refsect2>
+
</refsect1>
<refsect1><title>See also</title>
</refsect1>
diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c
index 5b9b24e..4709bf5 100644
--- a/gio/glib-compile-resources.c
+++ b/gio/glib-compile-resources.c
@@ -21,6 +21,7 @@
#include "config.h"
+#include <glib.h>
#include <gstdio.h>
#include <gi18n.h>
#include <gioenums.h>
@@ -28,6 +29,10 @@
#include <string.h>
#include <stdio.h>
#include <locale.h>
+#include <errno.h>
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
#include <gio/gmemoryoutputstream.h>
#include <gio/gzlibcompressor.h>
@@ -58,11 +63,13 @@ typedef struct
/* per file */
char *alias;
gboolean compressed;
+ char *preproc_options;
GString *string; /* non-NULL when accepting text */
} ParseState;
-gchar *sourcedir = NULL;
+static gchar *sourcedir = NULL;
+static gchar *xmllint = NULL;
static void
file_data_free (FileData *data)
@@ -115,7 +122,8 @@ start_element (GMarkupParseContext *context,
if (strcmp (element_name, "file") == 0)
{
COLLECT (OPTIONAL | STRDUP, "alias", &state->alias,
- OPTIONAL | BOOL, "compressed", &state->compressed);
+ OPTIONAL | BOOL, "compressed", &state->compressed,
+ OPTIONAL | STRDUP, "preprocess", &state->preproc_options);
state->string = g_string_new ("");
return;
}
@@ -179,6 +187,7 @@ end_element (GMarkupParseContext *context,
gchar *file, *real_file;
gchar *key;
FileData *data;
+ char *tmp_file;
file = state->string->str;
key = file;
@@ -205,13 +214,88 @@ end_element (GMarkupParseContext *context,
else
real_file = g_strdup (file);
+ tmp_file = NULL;
+ if (state->preproc_options)
+ {
+ gchar **options;
+ guint i;
+ gboolean xml_stripblanks = FALSE;
+
+ options = g_strsplit (state->preproc_options, ",", -1);
+
+ for (i = 0; options[i]; i++)
+ {
+ if (!strcmp (options[i], "xml-stripblanks"))
+ xml_stripblanks = TRUE;
+ else
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ _("Unknown proprocessing options \"%s\""), options[i]);
+ g_strfreev (options);
+ goto cleanup;
+ }
+ }
+ g_strfreev (options);
+
+ if (xml_stripblanks && xmllint != NULL)
+ {
+ gchar *argv[8];
+ int status, fd, argc;
+
+ tmp_file = g_strdup ("resource-XXXXXXXX");
+ if ((fd = g_mkstemp (tmp_file)) == -1)
+ {
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+ _("Failed to create temp file: %s"),
+ g_strerror (errsv));
+ g_free (tmp_file);
+ tmp_file = NULL;
+ goto cleanup;
+ }
+ close (fd);
+
+ argc = 0;
+ argv[argc++] = (gchar *) xmllint;
+ argv[argc++] = "--nonet";
+ argv[argc++] = "--noent";
+ argv[argc++] = "--noblanks";
+ argv[argc++] = "--output";
+ argv[argc++] = tmp_file;
+ argv[argc++] = real_file;
+ argv[argc++] = NULL;
+ g_assert (argc <= G_N_ELEMENTS (argv));
+
+ if (!g_spawn_sync (NULL /* cwd */, argv, NULL /* envv */,
+ G_SPAWN_STDOUT_TO_DEV_NULL |
+ G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, NULL, NULL, &status, &my_error))
+ {
+ g_propagate_error (error, my_error);
+ goto cleanup;
+ }
+#ifdef HAVE_SYS_WAIT_H
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error processing input file with xmllint"));
+ goto cleanup;
+ }
+#endif
+
+ g_free (real_file);
+ real_file = g_strdup (tmp_file);
+ }
+ }
+
if (!g_file_get_contents (real_file, &data->content, &data->size, &my_error))
{
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
_("Error reading file %s: %s"),
real_file, my_error->message);
g_clear_error (&my_error);
- return;
+ goto cleanup;
}
/* Include zero termination in content_size for uncompressed files (but not in size) */
data->content_size = data->size + 1;
@@ -230,7 +314,7 @@ end_element (GMarkupParseContext *context,
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
_("Error compressing file %s"),
real_file);
- return;
+ goto cleanup;
}
g_free (data->content);
@@ -244,16 +328,24 @@ end_element (GMarkupParseContext *context,
data->flags |= G_RESOURCE_FLAGS_COMPRESSED;
}
- g_free (real_file);
-
g_hash_table_insert (state->table, key, data);
+ cleanup:
/* Cleanup */
g_free (state->alias);
state->alias = NULL;
g_string_free (state->string, TRUE);
state->string = NULL;
+ g_free (state->preproc_options);
+ state->preproc_options = NULL;
+
+ g_free (real_file);
+ if (tmp_file)
+ {
+ unlink (tmp_file);
+ g_free (tmp_file);
+ }
}
}
@@ -449,6 +541,12 @@ main (int argc, char **argv)
if (sourcedir == NULL)
sourcedir = "";
+ xmllint = g_strdup (g_getenv ("XMLLINT"));
+ if (xmllint == NULL)
+ xmllint = g_find_program_in_path ("xmllint");
+ if (xmllint == NULL)
+ g_printerr ("XMLLINT not set and xmllint not found in path; skipping xml preprocessing.\n");
+
if (target == NULL)
{
char *dirname = g_path_get_dirname (srcfile);
@@ -694,6 +792,7 @@ main (int argc, char **argv)
g_free (binary_target);
g_free (target);
g_hash_table_destroy (table);
+ g_free (xmllint);
return 0;
}
diff --git a/gio/gresource.c b/gio/gresource.c
index f985bd2..4c5b1f2 100644
--- a/gio/gresource.c
+++ b/gio/gresource.c
@@ -62,6 +62,14 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
* in a compressed form, but will be automatically uncompressed when the resource is used. This
* is very useful e.g. for larger text files that are parsed once (or rarely) and then thrown away.
*
+ * Resource files can also be marked to be preprocessed, by setting the value of the
+ * <literal>preprocess</literal> attribute to a comma-separated list of preprocessing options.
+ * The only option currently supported is
+ * <literal>xml-stripblanks</literal> which will use <literal>xmllint</literal> to strip
+ * ignorable whitespace from the xml file. For this to work, the <envar>XMLLINT</envar>
+ * environment variable must be set to the full path to the xmllint executable;
+ * otherwise the preprocessing step is skipped.
+ *
* Resource bundles are created by the <link linkend="glib-compile-schemas">glib-compile-resources</link> program
* which takes an xml file that describes the bundle, and a set of files that the xml references. These
* are combined into a binary resource bundle.
@@ -73,7 +81,7 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
* <gresource prefix="/org/gtk/Example">
* <file>data/splashscreen.png</file>
* <file compressed="true">dialog.ui</file>
- * <file>menumarkup.xml</file>
+ * <file preprocess="xml-stripblanks">menumarkup.xml</file>
* </gresource>
* </gresources>
* ]]></programlisting></example>
diff --git a/gio/tests/test.gresource.xml b/gio/tests/test.gresource.xml
index d66d08a..15361e6 100644
--- a/gio/tests/test.gresource.xml
+++ b/gio/tests/test.gresource.xml
@@ -2,6 +2,7 @@
<gresources>
<gresource>
<file compressed="true">test1.txt</file>
+ <file preprocess="xml-stripblanks">test.gresource.xml</file>
</gresource>
<gresource prefix="/a_prefix">
<file alias="test2-alias.txt">test2.txt</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]