summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2017-11-27 15:53:00 +0000
committerPhilip Withnall <withnall@endlessm.com>2017-11-27 19:03:48 +0000
commita9c5cbb9788f187470c44d1bc5231cdf249ac8e0 (patch)
tree195e2a015abd5f87ef672ec14d137fc85ae49e46
parent83cce228f50227e3425ba734782c925cdf491fbb (diff)
downloadlibgdata-a9c5cbb9788f187470c44d1bc5231cdf249ac8e0.tar.gz
core: Add a GDataParser flag for ignoring erroneous child elements
In some situations, it makes sense to ignore child elements if they fail to parse properly, rather than propagating that error up to the parent. See the following commit for an example of such a situation. https://bugzilla.gnome.org/show_bug.cgi?id=790671
-rw-r--r--gdata/gdata-parser.c16
-rw-r--r--gdata/gdata-parser.h4
2 files changed, 18 insertions, 2 deletions
diff --git a/gdata/gdata-parser.c b/gdata/gdata-parser.c
index a43c2ecf..987cb17c 100644
--- a/gdata/gdata-parser.c
+++ b/gdata/gdata-parser.c
@@ -633,6 +633,9 @@ gdata_parser_object_from_element_setter (xmlNode *element, const gchar *element_
{
GDataParsable *parsable, *parent_parsable;
GDataParserSetterFunc setter;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (!(options & P_REQUIRED) || !(options & P_IGNORE_ERROR), FALSE);
/* We're lax on the types so that we don't have to do loads of casting when calling the function, which makes the parsing code more legible */
setter = (GDataParserSetterFunc) _setter;
@@ -643,9 +646,20 @@ gdata_parser_object_from_element_setter (xmlNode *element, const gchar *element_
return FALSE;
/* Get the object and check for instantiation failure */
- parsable = _gdata_parsable_new_from_xml_node (object_type, element->doc, element, NULL, error);
+ parsable = _gdata_parsable_new_from_xml_node (object_type, element->doc, element, NULL, &local_error);
+ g_assert ((parsable == NULL) == (local_error != NULL));
+
if (options & P_REQUIRED && parsable == NULL) {
/* The error has already been set by _gdata_parsable_new_from_xml_node() */
+ g_propagate_error (error, g_steal_pointer (&local_error));
+ *success = FALSE;
+ return TRUE;
+ } else if ((options & P_IGNORE_ERROR) && parsable == NULL) {
+ g_clear_error (&local_error);
+ *success = TRUE;
+ return TRUE;
+ } else if (local_error != NULL) {
+ g_propagate_error (error, g_steal_pointer (&local_error));
*success = FALSE;
return TRUE;
}
diff --git a/gdata/gdata-parser.h b/gdata/gdata-parser.h
index bc7a15a7..0eddf13b 100644
--- a/gdata/gdata-parser.h
+++ b/gdata/gdata-parser.h
@@ -57,6 +57,7 @@ gboolean gdata_parser_int64_from_iso8601 (const gchar *date, gint64 *_time);
* this only applies to gdata_parser_string_from_element()
* @P_DEFAULT: if the element content is %NULL or empty, return an empty value instead of erroring (this is mutually exclusive with %P_REQUIRED
* and %P_NON_EMPTY)
+ * @P_IGNORE_ERROR: ignore any error when the parse fails; can be used to skip empty values (this is mutually exclusive with %P_REQUIRED)
*
* Parsing options to be passed in a bitwise fashion to gdata_parser_string_from_element() or gdata_parser_object_from_element().
* Their names aren't namespaced as they aren't public, and brevity is important, since they're used frequently in the parsing code.
@@ -68,7 +69,8 @@ typedef enum {
P_NO_DUPES = 1 << 0,
P_REQUIRED = 1 << 1,
P_NON_EMPTY = 1 << 2,
- P_DEFAULT = 1 << 3
+ P_DEFAULT = 1 << 3,
+ P_IGNORE_ERROR = 1 << 4
} GDataParserOptions;
typedef void (*GDataParserSetterFunc) (GDataParsable *parent_parsable, GDataParsable *parsable);