[glib] gmarkup: Add g_markup_collect_known_attributes()
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] gmarkup: Add g_markup_collect_known_attributes()
- Date: Fri, 17 Aug 2012 03:41:27 +0000 (UTC)
commit 8d40389d15544bdc612989157f80380badce52f7
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Aug 16 23:40:08 2012 -0400
gmarkup: Add g_markup_collect_known_attributes()
Add a variant of g_markup_collect_attributes() which will
ignore unknown attributes (such as those from different XML
namespaces) when parsing markup, rather than returning
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE as g_markup_collect_attributes()
does.
Patch by Philip Withnall,
https://bugzilla.gnome.org/show_bug.cgi?id=665634
docs/reference/glib/glib-sections.txt | 1 +
glib/glib.symbols | 1 +
glib/gmarkup.c | 218 ++++++++++++++++++++++-----------
glib/gmarkup.h | 9 ++
glib/tests/markup-collect.c | 125 +++++++++++++-------
5 files changed, 242 insertions(+), 112 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index dacacbb..4c0071c 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -1125,6 +1125,7 @@ g_markup_parse_context_pop
<SUBSECTION>
GMarkupCollectType
g_markup_collect_attributes
+g_markup_collect_known_attributes
<SUBSECTION Private>
g_markup_error_quark
</SECTION>
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 0490b66..dbd9246 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -683,6 +683,7 @@ g_markup_parse_context_pop
g_markup_printf_escaped
g_markup_vprintf_escaped
g_markup_collect_attributes
+g_markup_collect_known_attributes
g_free
g_clear_pointer
g_malloc
diff --git a/glib/gmarkup.c b/glib/gmarkup.c
index b0c28a9..4fda725 100644
--- a/glib/gmarkup.c
+++ b/glib/gmarkup.c
@@ -2549,84 +2549,39 @@ g_markup_parse_boolean (const char *string,
* is set depending on what value type is used
*
* A mixed enumerated type and flags field. You must specify one type
- * (string, strdup, boolean, tristate). Additionally, you may optionally
+ * (string, strdup, boolean, tristate). Additionally, you may optionally
* bitwise OR the type with the flag %G_MARKUP_COLLECT_OPTIONAL.
*
* It is likely that this enum will be extended in the future to
* support other types.
*/
-/**
- * g_markup_collect_attributes:
- * @element_name: the current tag name
- * @attribute_names: the attribute names
- * @attribute_values: the attribute values
- * @error: a pointer to a #GError or %NULL
- * @first_type: the #GMarkupCollectType of the first attribute
- * @first_attr: the name of the first attribute
- * @...: a pointer to the storage location of the first attribute
- * (or %NULL), followed by more types names and pointers, ending
- * with %G_MARKUP_COLLECT_INVALID
- *
- * Collects the attributes of the element from the data passed to the
- * #GMarkupParser start_element function, dealing with common error
- * conditions and supporting boolean values.
- *
- * This utility function is not required to write a parser but can save
- * a lot of typing.
- *
- * The @element_name, @attribute_names, @attribute_values and @error
- * parameters passed to the start_element callback should be passed
- * unmodified to this function.
- *
- * Following these arguments is a list of "supported" attributes to collect.
- * It is an error to specify multiple attributes with the same name. If any
- * attribute not in the list appears in the @attribute_names array then an
- * unknown attribute error will result.
- *
- * The #GMarkupCollectType field allows specifying the type of collection
- * to perform and if a given attribute must appear or is optional.
- *
- * The attribute name is simply the name of the attribute to collect.
- *
- * The pointer should be of the appropriate type (see the descriptions
- * under #GMarkupCollectType) and may be %NULL in case a particular
- * attribute is to be allowed but ignored.
- *
- * This function deals with issuing errors for missing attributes
- * (of type %G_MARKUP_ERROR_MISSING_ATTRIBUTE), unknown attributes
- * (of type %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE) and duplicate
- * attributes (of type %G_MARKUP_ERROR_INVALID_CONTENT) as well
- * as parse errors for boolean-valued attributes (again of type
- * %G_MARKUP_ERROR_INVALID_CONTENT). In all of these cases %FALSE
- * will be returned and @error will be set as appropriate.
- *
- * Return value: %TRUE if successful
- *
- * Since: 2.16
- **/
-gboolean
-g_markup_collect_attributes (const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- GError **error,
- GMarkupCollectType first_type,
- const gchar *first_attr,
- ...)
+static gboolean
+_g_markup_collect_attributesv (const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gboolean reject_unknown_attributes,
+ GError **error,
+ GMarkupCollectType first_type,
+ const gchar *first_attr,
+ va_list ap)
{
GMarkupCollectType type;
const gchar *attr;
guint64 collected;
int written;
- va_list ap;
int i;
+ va_list ap2;
type = first_type;
attr = first_attr;
collected = 0;
written = 0;
- va_start (ap, first_attr);
+ /* Take a copy of the va_list so that we can iterate back over it in case of
+ * errors. */
+ va_copy (ap2, ap);
+
while (type != G_MARKUP_COLLECT_INVALID)
{
gboolean mandatory;
@@ -2671,7 +2626,6 @@ g_markup_collect_attributes (const gchar *element_name,
"element '%s' requires attribute '%s'",
element_name, attr);
- va_end (ap);
goto failure;
}
@@ -2729,7 +2683,6 @@ g_markup_collect_attributes (const gchar *element_name,
"cannot be parsed as a boolean value",
element_name, attr, value);
- va_end (ap);
goto failure;
}
}
@@ -2744,7 +2697,6 @@ g_markup_collect_attributes (const gchar *element_name,
attr = va_arg (ap, const char *);
written++;
}
- va_end (ap);
/* ensure we collected all the arguments */
for (i = 0; attribute_names[i]; i++)
@@ -2765,19 +2717,22 @@ g_markup_collect_attributes (const gchar *element_name,
break;
/* j is now the first occurrence of attribute_names[i] */
- if (i == j)
+ if (i == j && reject_unknown_attributes)
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
"attribute '%s' invalid for element '%s'",
attribute_names[i], element_name);
- else
+ else if (i != j)
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
"attribute '%s' given multiple times for element '%s'",
attribute_names[i], element_name);
+ else
+ continue; /* accepting unknown attributes */
goto failure;
}
+ va_end (ap2);
return TRUE;
@@ -2786,12 +2741,11 @@ failure:
type = first_type;
attr = first_attr;
- va_start (ap, first_attr);
while (type != G_MARKUP_COLLECT_INVALID)
{
gpointer ptr;
- ptr = va_arg (ap, gpointer);
+ ptr = va_arg (ap2, gpointer);
if (ptr != NULL)
{
@@ -2815,10 +2769,134 @@ failure:
}
}
- type = va_arg (ap, GMarkupCollectType);
- attr = va_arg (ap, const char *);
+ type = va_arg (ap2, GMarkupCollectType);
+ attr = va_arg (ap2, const char *);
}
- va_end (ap);
+ va_end (ap2);
return FALSE;
}
+
+/**
+ * g_markup_collect_attributes:
+ * @element_name: the current tag name
+ * @attribute_names: the attribute names
+ * @attribute_values: the attribute values
+ * @error: a pointer to a #GError or %NULL
+ * @first_type: the #GMarkupCollectType of the first attribute
+ * @first_attr: the name of the first attribute
+ * @...: a pointer to the storage location of the first attribute
+ * (or %NULL), followed by more types names and pointers, ending
+ * with %G_MARKUP_COLLECT_INVALID
+ *
+ * Collects the attributes of the element from the data passed to the
+ * #GMarkupParser start_element function, dealing with common error
+ * conditions and supporting boolean values.
+ *
+ * This utility function is not required to write a parser but can save
+ * a lot of typing.
+ *
+ * The @element_name, @attribute_names, @attribute_values and @error
+ * parameters passed to the start_element callback should be passed
+ * unmodified to this function.
+ *
+ * Following these arguments is a list of "supported" attributes to collect.
+ * It is an error to specify multiple attributes with the same name. If any
+ * attribute not in the list appears in the @attribute_names array then an
+ * unknown attribute error will result.
+ *
+ * The #GMarkupCollectType field allows specifying the type of collection
+ * to perform and if a given attribute must appear or is optional.
+ *
+ * The attribute name is simply the name of the attribute to collect.
+ *
+ * The pointer should be of the appropriate type (see the descriptions
+ * under #GMarkupCollectType) and may be %NULL in case a particular
+ * attribute is to be allowed but ignored.
+ *
+ * This function deals with issuing errors for missing attributes
+ * (of type %G_MARKUP_ERROR_MISSING_ATTRIBUTE), unknown attributes
+ * (of type %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE) and duplicate
+ * attributes (of type %G_MARKUP_ERROR_INVALID_CONTENT) as well
+ * as parse errors for boolean-valued attributes (again of type
+ * %G_MARKUP_ERROR_INVALID_CONTENT). In all of these cases %FALSE
+ * will be returned and @error will be set as appropriate.
+ *
+ * Return value: %TRUE if successful
+ *
+ * Since: 2.16
+ **/
+gboolean
+g_markup_collect_attributes (const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ GError **error,
+ GMarkupCollectType first_type,
+ const gchar *first_attr,
+ ...)
+{
+ gboolean retval;
+ va_list ap;
+
+ va_start (ap, first_attr);
+ retval = _g_markup_collect_attributesv (element_name,
+ attribute_names, attribute_values,
+ TRUE, error,
+ first_type, first_attr,
+ ap);
+ va_end (ap);
+
+ return retval;
+}
+
+/**
+ * g_markup_collect_known_attributes:
+ * @element_name: the current tag name
+ * @attribute_names: (array zero-terminated=1): the attribute names
+ * @attribute_values: (array zero-terminated=1): the attribute values
+ * @error: (allow-none): a pointer to a #GError or %NULL
+ * @first_type: the #GMarkupCollectType of the first attribute
+ * @first_attr: the name of the first attribute
+ * @...: a pointer to the storage location of the first attribute
+ * (or %NULL), followed by more types names and pointers, ending
+ * with %G_MARKUP_COLLECT_INVALID
+ *
+ * Collects the attributes of the element from the data passed to the
+ * #GMarkupParser start_element function, dealing with common error
+ * conditions and supporting boolean values.
+ *
+ * This is a more relaxed version of g_markup_collect_attributes(), which
+ * ignores attributes found in @attribute_names but not listed in @first_attr
+ * or @...; by comparison g_markup_collect_attributes() will return
+ * %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE instead. Otherwise, this function behaves
+ * identically.
+ *
+ * This is intended for situations where the markup being parsed may use
+ * extensions in other namespaces and thus contain extra, unknown, attributes.
+ *
+ * Return value: %TRUE if successful
+ *
+ * Since: 2.34
+ */
+gboolean
+g_markup_collect_known_attributes (const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ GError **error,
+ GMarkupCollectType first_type,
+ const gchar *first_attr,
+ ...)
+{
+ gboolean retval;
+ va_list ap;
+
+ va_start (ap, first_attr);
+ retval = _g_markup_collect_attributesv (element_name,
+ attribute_names, attribute_values,
+ FALSE, error,
+ first_type, first_attr,
+ ap);
+ va_end (ap);
+
+ return retval;
+}
diff --git a/glib/gmarkup.h b/glib/gmarkup.h
index a8865da..ee4ee8c 100644
--- a/glib/gmarkup.h
+++ b/glib/gmarkup.h
@@ -233,6 +233,15 @@ gboolean g_markup_collect_attributes (const gchar *element_name,
const gchar *first_attr,
...);
+GLIB_AVAILABLE_IN_2_34
+gboolean g_markup_collect_known_attributes (const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ GError **error,
+ GMarkupCollectType first_type,
+ const gchar *first_attr,
+ ...);
+
G_END_DECLS
#endif /* __G_MARKUP_H__ */
diff --git a/glib/tests/markup-collect.c b/glib/tests/markup-collect.c
index 3b2e2bd..65cc67b 100644
--- a/glib/tests/markup-collect.c
+++ b/glib/tests/markup-collect.c
@@ -1,11 +1,11 @@
-/*
+/*
* Copyright  2007 Ryan Lortie
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
- *
+ *
* See the included COPYING file for more information.
*/
@@ -13,6 +13,19 @@
#include <string.h>
#include <glib.h>
+enum test_type
+{
+ COLLECT_ATTRIBUTES = 0,
+ COLLECT_KNOWN_ATTRIBUTES,
+ MAX_TEST_TYPE
+};
+
+struct test_data
+{
+ enum test_type test_type;
+ GString *string;
+};
+
static void
start (GMarkupParseContext *context,
const char *element_name,
@@ -21,13 +34,26 @@ start (GMarkupParseContext *context,
gpointer user_data,
GError **error)
{
- GString *string = user_data;
+ struct test_data *data = user_data;
gboolean result;
-#define collect(...) \
- g_markup_collect_attributes (element_name, attribute_names, \
- attribute_values, error, __VA_ARGS__, \
- G_MARKUP_COLLECT_INVALID)
+#define collect(...) G_STMT_START { \
+ if (data->test_type == COLLECT_ATTRIBUTES) \
+ { \
+ result = \
+ g_markup_collect_attributes (element_name, attribute_names, \
+ attribute_values, error, __VA_ARGS__, \
+ G_MARKUP_COLLECT_INVALID); \
+ } \
+ else \
+ { \
+ result = \
+ g_markup_collect_known_attributes (element_name, attribute_names, \
+ attribute_values, error, \
+ __VA_ARGS__, \
+ G_MARKUP_COLLECT_INVALID); \
+ } \
+ } G_STMT_END
#define BOOL G_MARKUP_COLLECT_BOOLEAN
#define OPTBOOL G_MARKUP_COLLECT_BOOLEAN | G_MARKUP_COLLECT_OPTIONAL
#define TRI G_MARKUP_COLLECT_TRISTATE
@@ -41,9 +67,9 @@ start (GMarkupParseContext *context,
{
gboolean mb = 2, ob = 2, tri = 2;
- result = collect (BOOL, "mb", &mb,
- OPTBOOL, "ob", &ob,
- TRI, "tri", &tri);
+ collect (BOOL, "mb", &mb,
+ OPTBOOL, "ob", &ob,
+ TRI, "tri", &tri);
g_assert (result ||
(mb == FALSE && ob == FALSE && tri != TRUE && tri != FALSE));
@@ -51,7 +77,7 @@ start (GMarkupParseContext *context,
if (tri != FALSE && tri != TRUE)
tri = -1;
- g_string_append_printf (string, "<bool(%d) %d %d %d>",
+ g_string_append_printf (data->string, "<bool(%d) %d %d %d>",
result, mb, ob, tri);
}
@@ -60,15 +86,15 @@ start (GMarkupParseContext *context,
const char *cm, *co;
char *am, *ao;
- result = collect (STR, "cm", &cm,
- STRDUP, "am", &am,
- OPTDUP, "ao", &ao,
- OPTSTR, "co", &co);
+ collect (STR, "cm", &cm,
+ STRDUP, "am", &am,
+ OPTDUP, "ao", &ao,
+ OPTSTR, "co", &co);
g_assert (result ||
(cm == NULL && am == NULL && ao == NULL && co == NULL));
- g_string_append_printf (string, "<str(%d) %s %s %s %s>",
+ g_string_append_printf (data->string, "<str(%d) %s %s %s %s>",
result, n (cm), n (am), n (ao), n (co));
g_free (am);
@@ -140,34 +166,49 @@ static void
test_collect (gconstpointer d)
{
const struct test *test = d;
+ enum test_type t;
- GMarkupParseContext *ctx;
- GError *error = NULL;
- GString *string;
- gboolean result;
-
- string = g_string_new ("");
- ctx = g_markup_parse_context_new (&parser, 0, string, NULL);
- result = g_markup_parse_context_parse (ctx,
- test->document,
- -1, &error);
- if (result)
- result = g_markup_parse_context_end_parse (ctx, &error);
-
- if (result)
+ for (t = 0; t < MAX_TEST_TYPE; t++)
{
- g_assert_no_error (error);
- g_assert_cmpint (test->error_code, ==, 0);
- g_assert_cmpstr (test->result, ==, string->str);
+ GMarkupParseContext *ctx;
+ GError *error = NULL;
+ gboolean result;
+ struct test_data data;
+
+ data.test_type = t;
+ data.string = g_string_new ("");
+
+ ctx = g_markup_parse_context_new (&parser, 0, &data, NULL);
+ result = g_markup_parse_context_parse (ctx,
+ test->document,
+ -1, &error);
+ if (result)
+ result = g_markup_parse_context_end_parse (ctx, &error);
+
+ if (result &&
+ !(t == COLLECT_KNOWN_ATTRIBUTES &&
+ test->error_code == G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE))
+ {
+ /* Normal test */
+ g_assert_no_error (error);
+ g_assert_cmpint (test->error_code, ==, 0);
+ g_assert_cmpstr (test->result, ==, data.string->str);
+ }
+ else if (result)
+ {
+ /* Test expecting UNKNOWN_ATTRIBUTE, and we're parsing with
+ * collect_known_attributes(). */
+ g_assert_no_error (error);
+ }
+ else
+ {
+ g_assert_error (error, G_MARKUP_ERROR, test->error_code);
+ }
+
+ g_markup_parse_context_free (ctx);
+ g_string_free (data.string, TRUE);
+ g_clear_error (&error);
}
- else
- {
- g_assert_error (error, G_MARKUP_ERROR, test->error_code);
- }
-
- g_markup_parse_context_free (ctx);
- g_string_free (string, TRUE);
- g_clear_error (&error);
}
#define XML "<element a='1' b='2' c='3'/>"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]