Blame SOURCES/0001-xml-support-xsd-choices-by-allowing-to-rewind-or-adv.patch

39524d
From a27d1686b387a045607b5f0802001ea8863342cb Mon Sep 17 00:00:00 2001
39524d
From: Benjamin Dauvergne <bdauvergne@entrouvert.com>
39524d
Date: Sat, 7 Jun 2014 09:29:58 +0200
39524d
Subject: [PATCH 1/2] xml: support xsd:choices by allowing to rewind or advance
39524d
 after match or miss of a snippet
39524d
39524d
---
39524d
 lasso/xml/private.h | 26 ++++++++++++++++++++++++-
39524d
 lasso/xml/xml.c     | 56 +++++++++++++++++++++++++++++++++++++++--------------
39524d
 2 files changed, 66 insertions(+), 16 deletions(-)
39524d
39524d
diff --git a/lasso/xml/private.h b/lasso/xml/private.h
39524d
index 450ec2644112d6a6931de21eea8b6d10441b90fb..f1b0e94b58eef79501b9264c4da96b8cb049b548 100644
39524d
--- a/lasso/xml/private.h
39524d
+++ b/lasso/xml/private.h
39524d
@@ -49,7 +49,23 @@ typedef enum {
39524d
 	SNIPPET_LIST_XMLNODES,
39524d
 	SNIPPET_XMLNODE,
39524d
 	SNIPPET_COLLECT_NAMESPACES,
39524d
-
39524d
+	SNIPPET_JUMP_OFFSET_SIGN = 1 << 19,
39524d
+	SNIPPET_JUMP_OFFSET_SHIFT = 15,
39524d
+	SNIPPET_JUMP_OFFSET_MASK = 0x0f << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_JUMP_1 = 1 << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_JUMP_2 = 2 << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_JUMP_3 = 3 << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_JUMP_4 = 4 << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_JUMP_5 = 5 << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_JUMP_6 = 6 << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_JUMP_7 = 7 << SNIPPET_JUMP_OFFSET_SHIFT,
39524d
+	SNIPPET_BACK_1 = 1 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
39524d
+	SNIPPET_BACK_2 = 2 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
39524d
+	SNIPPET_BACK_3 = 3 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
39524d
+	SNIPPET_BACK_4 = 4 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
39524d
+	SNIPPET_BACK_5 = 5 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
39524d
+	SNIPPET_BACK_6 = 6 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
39524d
+	SNIPPET_BACK_7 = 7 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
39524d
 	/* transformers for content transformation */
39524d
 	SNIPPET_STRING  = 1 << 0, /* default, can be omitted */
39524d
 	SNIPPET_BOOLEAN = 1 << 20,
39524d
@@ -62,8 +78,16 @@ typedef enum {
39524d
 	SNIPPET_KEEP_XMLNODE = 1 << 27, /* force keep xmlNode */
39524d
 	SNIPPET_PRIVATE = 1 << 28, /* means that the offset is relative to a private extension */
39524d
 	SNIPPET_MANDATORY = 1 << 29, /* means that the element cardinality is at least 1 */
39524d
+	SNIPPET_JUMP_ON_MATCH = 1 << 30,
39524d
+	SNIPPET_JUMP_ON_MISS = 1 << 31,
39524d
+	SNIPPET_JUMP = SNIPPET_JUMP_ON_MISS | SNIPPET_JUMP_ON_MATCH,
39524d
+
39524d
 } SnippetType;
39524d
 
39524d
+#define SNIPPET_JUMP_OFFSET(type) ((type & SNIPPET_JUMP_OFFSET_SIGN) ? \
39524d
+		                      (-(type & SNIPPET_JUMP_OFFSET_MASK) >> SNIPPET_JUMP_OFFSET_SHIFT) \
39524d
+		                    : ((type & SNIPPET_JUMP_OFFSET_MASK) >> SNIPPET_JUMP_OFFSET_SHIFT))
39524d
+
39524d
 typedef enum {
39524d
 	NO_OPTION = 0,
39524d
 	NO_SINGLE_REFERENCE = 1 /* SAML signature should contain a single reference,
39524d
diff --git a/lasso/xml/xml.c b/lasso/xml/xml.c
39524d
index 7ffa2d27e37b8a5e1798db0812f0c90470f80454..436dcc198beddf7069c7de591786f55dde19c840 100644
39524d
--- a/lasso/xml/xml.c
39524d
+++ b/lasso/xml/xml.c
39524d
@@ -1597,8 +1597,19 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
39524d
 			gboolean match = FALSE;
39524d
 			struct XmlSnippet *matched_snippet = NULL;
39524d
 
39524d
-#define ADVANCE \
39524d
-				snippet++; \
39524d
+#define ADVANCE_MATCH \
39524d
+				if (snippet->type & SNIPPET_JUMP_ON_MATCH) { \
39524d
+					snippet += (ptrdiff_t)SNIPPET_JUMP_OFFSET(snippet->type); \
39524d
+				}  else { \
39524d
+					snippet++; \
39524d
+				} \
39524d
+				next_node_snippet(&class_iter, &snippet);
39524d
+#define ADVANCE_MISS \
39524d
+				if (snippet->type & SNIPPET_JUMP_ON_MISS) { \
39524d
+					snippet += (ptrdiff_t)SNIPPET_JUMP_OFFSET(snippet->type); \
39524d
+				}  else { \
39524d
+					snippet++; \
39524d
+				} \
39524d
 				next_node_snippet(&class_iter, &snippet);
39524d
 #define ERROR \
39524d
 				error("Element %s:%s cannot be parsed", \
39524d
@@ -1617,15 +1628,15 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
39524d
 					g_type = G_TYPE_FROM_CLASS(class);
39524d
 					value = SNIPPET_STRUCT_MEMBER_P(node, g_type, snippet);
39524d
 					list = value;
39524d
-					if (! multiple) {
39524d
-						ADVANCE;
39524d
+					if (! multiple || (snippet->type & SNIPPET_JUMP_ON_MATCH)) {
39524d
+						ADVANCE_MATCH;
39524d
 					}
39524d
 					break;
39524d
 				} else {
39524d
 					if (mandatory) {
39524d
 						break;
39524d
 					} else {
39524d
-						ADVANCE;
39524d
+						ADVANCE_MISS;
39524d
 					}
39524d
 				}
39524d
 			}
39524d
@@ -2726,22 +2737,29 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, x
39524d
 
39524d
 	g_type = G_TYPE_FROM_CLASS(class);
39524d
 
39524d
-	for (snippet = snippets; snippet && snippet->name; snippet++) {
39524d
+	snippet = snippets;
39524d
+	while (snippet && snippet->name) {
39524d
 		void *value = NULL;
39524d
-		int int_value;
39524d
-		gboolean bool_value;
39524d
-		char *str;
39524d
+		int int_value = 0;
39524d
+		gboolean bool_value = FALSE;
39524d
+		char *str = NULL;
39524d
 		gboolean optional = snippet->type & SNIPPET_OPTIONAL;
39524d
 		gboolean optional_neg = snippet->type & SNIPPET_OPTIONAL_NEG;
39524d
+		gboolean multiple = is_snippet_multiple(snippet);
39524d
 
39524d
 		if (! snippet->offset && ! (snippet->type & SNIPPET_PRIVATE)) {
39524d
-			continue;
39524d
+			goto advance;
39524d
 		}
39524d
 		if (lasso_dump == FALSE && snippet->type & SNIPPET_LASSO_DUMP) {
39524d
-			continue;
39524d
+			goto advance;
39524d
 		}
39524d
 		if ((snippet->type & 0xff) == SNIPPET_ATTRIBUTE && (snippet->type & SNIPPET_ANY)) {
39524d
 			snippet_any_attribute = snippet;
39524d
+			goto advance;
39524d
+		}
39524d
+		/* special treatment for 1-* list of nodes, without we would serialize them twice */
39524d
+		if (multiple && (snippet->type & SNIPPET_JUMP_ON_MATCH && SNIPPET_JUMP_OFFSET(snippet->type) > 0)) {
39524d
+			snippet++;
39524d
 			continue;
39524d
 		}
39524d
 
39524d
@@ -2749,22 +2767,22 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, x
39524d
 		if (snippet->type & SNIPPET_INTEGER) {
39524d
 			int_value = SNIPPET_STRUCT_MEMBER(int, node, g_type, snippet);
39524d
 			if (int_value == 0 && optional) {
39524d
-				continue;
39524d
+				goto advance;
39524d
 			}
39524d
 			if (int_value == -1 && optional_neg) {
39524d
-				continue;
39524d
+				goto advance;
39524d
 			}
39524d
 			str = g_strdup_printf("%i", int_value);
39524d
 		} else if (snippet->type & SNIPPET_BOOLEAN) {
39524d
 			bool_value = SNIPPET_STRUCT_MEMBER(gboolean, node, g_type, snippet);
39524d
 			if (bool_value == FALSE  && optional) {
39524d
-				continue;
39524d
+				goto advance;
39524d
 			}
39524d
 			str = bool_value ? "true" : "false";
39524d
 		} else {
39524d
 			value = SNIPPET_STRUCT_MEMBER(void *, node, g_type, snippet);
39524d
 			if (value == NULL) {
39524d
-				continue;
39524d
+				goto advance;
39524d
 			}
39524d
 			str = value;
39524d
 		}
39524d
@@ -2847,6 +2865,14 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, x
39524d
 		if (snippet->type & SNIPPET_INTEGER) {
39524d
 			lasso_release(str);
39524d
 		}
39524d
+	advance:
39524d
+		if ((snippet->type & SNIPPET_JUMP_ON_MATCH) && SNIPPET_JUMP_OFFSET(snippet->type) > 0 && value) {
39524d
+			snippet += SNIPPET_JUMP_OFFSET(snippet->type);
39524d
+		} else if (!value && (snippet->type & SNIPPET_JUMP_ON_MISS) && SNIPPET_JUMP_OFFSET(snippet->type) > 0 && value) {
39524d
+			snippet += SNIPPET_JUMP_OFFSET(snippet->type);
39524d
+		} else {
39524d
+			snippet++;
39524d
+		}
39524d
 	}
39524d
 
39524d
 	if (snippet_any_attribute) {
39524d
-- 
39524d
2.1.0
39524d