xml: support xsd:choices by allowing to rewind or advance after match or miss of a snippet
This commit is contained in:
parent
fda8ae9f85
commit
a27d1686b3
|
@ -49,7 +49,23 @@ typedef enum {
|
|||
SNIPPET_LIST_XMLNODES,
|
||||
SNIPPET_XMLNODE,
|
||||
SNIPPET_COLLECT_NAMESPACES,
|
||||
|
||||
SNIPPET_JUMP_OFFSET_SIGN = 1 << 19,
|
||||
SNIPPET_JUMP_OFFSET_SHIFT = 15,
|
||||
SNIPPET_JUMP_OFFSET_MASK = 0x0f << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_JUMP_1 = 1 << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_JUMP_2 = 2 << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_JUMP_3 = 3 << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_JUMP_4 = 4 << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_JUMP_5 = 5 << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_JUMP_6 = 6 << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_JUMP_7 = 7 << SNIPPET_JUMP_OFFSET_SHIFT,
|
||||
SNIPPET_BACK_1 = 1 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
|
||||
SNIPPET_BACK_2 = 2 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
|
||||
SNIPPET_BACK_3 = 3 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
|
||||
SNIPPET_BACK_4 = 4 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
|
||||
SNIPPET_BACK_5 = 5 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
|
||||
SNIPPET_BACK_6 = 6 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
|
||||
SNIPPET_BACK_7 = 7 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
|
||||
/* transformers for content transformation */
|
||||
SNIPPET_STRING = 1 << 0, /* default, can be omitted */
|
||||
SNIPPET_BOOLEAN = 1 << 20,
|
||||
|
@ -62,8 +78,16 @@ typedef enum {
|
|||
SNIPPET_KEEP_XMLNODE = 1 << 27, /* force keep xmlNode */
|
||||
SNIPPET_PRIVATE = 1 << 28, /* means that the offset is relative to a private extension */
|
||||
SNIPPET_MANDATORY = 1 << 29, /* means that the element cardinality is at least 1 */
|
||||
SNIPPET_JUMP_ON_MATCH = 1 << 30,
|
||||
SNIPPET_JUMP_ON_MISS = 1 << 31,
|
||||
SNIPPET_JUMP = SNIPPET_JUMP_ON_MISS | SNIPPET_JUMP_ON_MATCH,
|
||||
|
||||
} SnippetType;
|
||||
|
||||
#define SNIPPET_JUMP_OFFSET(type) ((type & SNIPPET_JUMP_OFFSET_SIGN) ? \
|
||||
(-(type & SNIPPET_JUMP_OFFSET_MASK) >> SNIPPET_JUMP_OFFSET_SHIFT) \
|
||||
: ((type & SNIPPET_JUMP_OFFSET_MASK) >> SNIPPET_JUMP_OFFSET_SHIFT))
|
||||
|
||||
typedef enum {
|
||||
NO_OPTION = 0,
|
||||
NO_SINGLE_REFERENCE = 1 /* SAML signature should contain a single reference,
|
||||
|
|
|
@ -1597,8 +1597,19 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
|||
gboolean match = FALSE;
|
||||
struct XmlSnippet *matched_snippet = NULL;
|
||||
|
||||
#define ADVANCE \
|
||||
snippet++; \
|
||||
#define ADVANCE_MATCH \
|
||||
if (snippet->type & SNIPPET_JUMP_ON_MATCH) { \
|
||||
snippet += (ptrdiff_t)SNIPPET_JUMP_OFFSET(snippet->type); \
|
||||
} else { \
|
||||
snippet++; \
|
||||
} \
|
||||
next_node_snippet(&class_iter, &snippet);
|
||||
#define ADVANCE_MISS \
|
||||
if (snippet->type & SNIPPET_JUMP_ON_MISS) { \
|
||||
snippet += (ptrdiff_t)SNIPPET_JUMP_OFFSET(snippet->type); \
|
||||
} else { \
|
||||
snippet++; \
|
||||
} \
|
||||
next_node_snippet(&class_iter, &snippet);
|
||||
#define ERROR \
|
||||
error("Element %s:%s cannot be parsed", \
|
||||
|
@ -1617,15 +1628,15 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
|||
g_type = G_TYPE_FROM_CLASS(class);
|
||||
value = SNIPPET_STRUCT_MEMBER_P(node, g_type, snippet);
|
||||
list = value;
|
||||
if (! multiple) {
|
||||
ADVANCE;
|
||||
if (! multiple || (snippet->type & SNIPPET_JUMP_ON_MATCH)) {
|
||||
ADVANCE_MATCH;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if (mandatory) {
|
||||
break;
|
||||
} else {
|
||||
ADVANCE;
|
||||
ADVANCE_MISS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2726,22 +2737,29 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, x
|
|||
|
||||
g_type = G_TYPE_FROM_CLASS(class);
|
||||
|
||||
for (snippet = snippets; snippet && snippet->name; snippet++) {
|
||||
snippet = snippets;
|
||||
while (snippet && snippet->name) {
|
||||
void *value = NULL;
|
||||
int int_value;
|
||||
gboolean bool_value;
|
||||
char *str;
|
||||
int int_value = 0;
|
||||
gboolean bool_value = FALSE;
|
||||
char *str = NULL;
|
||||
gboolean optional = snippet->type & SNIPPET_OPTIONAL;
|
||||
gboolean optional_neg = snippet->type & SNIPPET_OPTIONAL_NEG;
|
||||
gboolean multiple = is_snippet_multiple(snippet);
|
||||
|
||||
if (! snippet->offset && ! (snippet->type & SNIPPET_PRIVATE)) {
|
||||
continue;
|
||||
goto advance;
|
||||
}
|
||||
if (lasso_dump == FALSE && snippet->type & SNIPPET_LASSO_DUMP) {
|
||||
continue;
|
||||
goto advance;
|
||||
}
|
||||
if ((snippet->type & 0xff) == SNIPPET_ATTRIBUTE && (snippet->type & SNIPPET_ANY)) {
|
||||
snippet_any_attribute = snippet;
|
||||
goto advance;
|
||||
}
|
||||
/* special treatment for 1-* list of nodes, without we would serialize them twice */
|
||||
if (multiple && (snippet->type & SNIPPET_JUMP_ON_MATCH && SNIPPET_JUMP_OFFSET(snippet->type) > 0)) {
|
||||
snippet++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2749,22 +2767,22 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, x
|
|||
if (snippet->type & SNIPPET_INTEGER) {
|
||||
int_value = SNIPPET_STRUCT_MEMBER(int, node, g_type, snippet);
|
||||
if (int_value == 0 && optional) {
|
||||
continue;
|
||||
goto advance;
|
||||
}
|
||||
if (int_value == -1 && optional_neg) {
|
||||
continue;
|
||||
goto advance;
|
||||
}
|
||||
str = g_strdup_printf("%i", int_value);
|
||||
} else if (snippet->type & SNIPPET_BOOLEAN) {
|
||||
bool_value = SNIPPET_STRUCT_MEMBER(gboolean, node, g_type, snippet);
|
||||
if (bool_value == FALSE && optional) {
|
||||
continue;
|
||||
goto advance;
|
||||
}
|
||||
str = bool_value ? "true" : "false";
|
||||
} else {
|
||||
value = SNIPPET_STRUCT_MEMBER(void *, node, g_type, snippet);
|
||||
if (value == NULL) {
|
||||
continue;
|
||||
goto advance;
|
||||
}
|
||||
str = value;
|
||||
}
|
||||
|
@ -2847,6 +2865,14 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, x
|
|||
if (snippet->type & SNIPPET_INTEGER) {
|
||||
lasso_release(str);
|
||||
}
|
||||
advance:
|
||||
if ((snippet->type & SNIPPET_JUMP_ON_MATCH) && SNIPPET_JUMP_OFFSET(snippet->type) > 0 && value) {
|
||||
snippet += SNIPPET_JUMP_OFFSET(snippet->type);
|
||||
} else if (!value && (snippet->type & SNIPPET_JUMP_ON_MISS) && SNIPPET_JUMP_OFFSET(snippet->type) > 0 && value) {
|
||||
snippet += SNIPPET_JUMP_OFFSET(snippet->type);
|
||||
} else {
|
||||
snippet++;
|
||||
}
|
||||
}
|
||||
|
||||
if (snippet_any_attribute) {
|
||||
|
|
Loading…
Reference in New Issue