/** enc-templ.c - XML encoder template, used in code generation ** Copyright (c) 2006-2007 Symlabs (symlabs@symlabs.com), All Rights Reserved. ** Author: Sampo Kellomaki (sampo@iki.fi) ** This is confidential unpublished proprietary source code of the author. ** NO WARRANTY, not even implied warranties. Contains trade secrets. ** Distribution prohibited unless authorized in writing. ** Licensed under Apache License 2.0, see file COPYING. ** $Id: enc-templ.c,v 1.27 2007-10-05 22:24:28 sampo Exp $ ** ** 30.5.2006, created, Sampo Kellomaki (sampo@iki.fi) ** 6.8.2006, factored data structure walking to aux-templ.c --Sampo ** 8.8.2006, reworked namespace handling --Sampo ** 26.8.2006, some CSE --Sampo ** 23.9.2006, added WO logic --Sampo ** 30.9.2007, improvements to WO encoding --Sampo ** ** N.B: wo=wire order (needed for exc-c14n), so=schema order ** N.B2: This template is meant to be processed by pd/xsd2sg.pl. Beware ** of special markers that xsd2sg.pl expects to find and understand. **/ #ifdef EL_NAME #undef EL_NAME #endif #ifdef EL_STRUCT #undef EL_STRUCT #endif #ifdef EL_NS #undef EL_NS #endif #ifdef EL_TAG #undef EL_TAG #endif #define EL_NAME ELNAME #define EL_STRUCT ELSTRUCT #define EL_NS ELNS #define EL_TAG ELTAG #ifndef MAYBE_UNUSED #define MAYBE_UNUSED /* May appear as unused variable, but is needed by some generated code. */ #endif #if 0 #define ENC_LEN_DEBUG(x,tag,len) D("x=%p tag(%s) len=%d",(x),(tag),(len)) #define ENC_LEN_DEBUG_BASE char* enc_base = p #else #define ENC_LEN_DEBUG(x,tag,len) #define ENC_LEN_DEBUG_BASE #endif /* FUNC(TXLEN_SO_ELNAME) */ /* Compute length of an element (and its subelements). The XML attributes * and elements are processed in schema order. */ /* Called by: */ int TXLEN_SO_ELNAME(struct zx_ctx* c, struct ELSTRUCT* x SIMPLELENNS) { struct zx_ns_s* pop_seen = 0; struct zx_elem_s* se MAYBE_UNUSED; #if 1 /* NORMALMODE */ /* *** in simple_elem case should output ns prefix from ns node. */ int len = sizeof("")-1; if (c->inc_ns_len) len += zx_len_inc_ns(c, &pop_seen); XMLNS_SO_LEN; ATTRS_SO_LEN; #else /* root node has no begin tag */ int len = 0; #endif ELEMS_SO_LEN; len += zx_len_so_common(c, &x->gg); zx_pop_seen(pop_seen); ENC_LEN_DEBUG(x, "ELNSCELTAG", len); return len; } /* FUNC(TXLEN_WO_ELNAME) */ /* Compute length of an element (and its subelements). The XML attributes * and elements are processed in wire order and no assumptions * are made about namespace prefixes. */ /* Called by: */ int TXLEN_WO_ELNAME(struct zx_ctx* c, struct ELSTRUCT* x SIMPLELEN) { struct zx_ns_s* pop_seen = 0; struct zx_elem_s* se MAYBE_UNUSED; #if 1 /* NORMALMODE */ int len = 1 + sizeof("ELTAG")-1 + 1 + 2 + sizeof("ELTAG")-1 + 1; if (x->gg.g.ns && x->gg.g.ns->prefix_len) len += (x->gg.g.ns->prefix_len + 1) * 2; if (c->inc_ns_len) len += zx_len_inc_ns(c, &pop_seen); XMLNS_WO_LEN; ATTRS_WO_LEN; #else /* root node has no begin tag */ int len = 0; #endif ELEMS_WO_LEN; len += zx_len_wo_common(c, &x->gg); zx_pop_seen(pop_seen); ENC_LEN_DEBUG(x, "ELNSCELTAG", len); return len; } /* FUNC(TXENC_SO_ELNAME) */ /* Render element into string. The XML attributes and elements are * processed in schema order. This is what you generally want for * rendering new data structure to a string. The wo pointers are not used. */ /* Called by: */ char* TXENC_SO_ELNAME(struct zx_ctx* c, struct ELSTRUCT* x, char* p SIMPLETAGLENNS) { struct zx_elem_s* se MAYBE_UNUSED; ENC_LEN_DEBUG_BASE; #if 1 /* NORMALMODE */ struct zx_ns_s* pop_seen = 0; /* *** in simple_elem case should output ns prefix from ns node. */ ZX_OUT_TAG(p, "inc_ns) p = zx_enc_inc_ns(c, p, &pop_seen); XMLNS_SO_ENC; ATTRS_SO_ENC; p = zx_enc_unknown_attrs(p, x->gg.any_attr); #else /* root node has no begin tag */ #endif ELEMS_SO_ENC; p = zx_enc_so_unknown_elems_and_content(c, p, &x->gg); #if 1 /* NORMALMODE */ ZX_OUT_CLOSE_TAG(p, ""); zx_pop_seen(pop_seen); #else /* root node has no end tag either */ #endif ENC_LEN_DEBUG(x, "ELNSCELTAG", p-enc_base); return p; } /* FUNC(TXENC_WO_ELNAME) */ /* Render element into string. The XML attributes and elements are * processed in wire order by chasing wo pointers. This is what you want for * validating signatures on other people's XML documents. */ /* Called by: */ char* TXENC_WO_ELNAME(struct zx_ctx* c, struct ELSTRUCT* x, char* p SIMPLETAGLEN) { struct zx_elem_s* kid; ENC_LEN_DEBUG_BASE; #if 1 /* NORMALMODE */ struct zx_ns_s* pop_seen = 0; char* q; char* qq; ZX_OUT_CH(p, '<'); q = p; if (x->gg.g.ns && x->gg.g.ns->prefix_len) { ZX_OUT_MEM(p, x->gg.g.ns->prefix, x->gg.g.ns->prefix_len); ZX_OUT_CH(p, ':'); } ZX_OUT_MEM(p, "ELTAG", sizeof("ELTAG")-1); qq = p; /* *** sort the namespaces */ if (c->inc_ns) zx_add_inc_ns(c, &pop_seen); XMLNS_WO_ENC; p = zx_enc_seen(p, pop_seen); ATTRS_WO_ENC; p = zx_enc_unknown_attrs(p, x->gg.any_attr); #else /* root node has no begin tag */ #endif for (kid = x->gg.kids; kid; kid = ((struct zx_elem_s*)(kid->g.wo))) p = TXENC_WO_any_elem(c, kid, p); #if 1 /* NORMALMODE */ ZX_OUT_CH(p, '<'); ZX_OUT_CH(p, '/'); ZX_OUT_MEM(p, q, qq-q); ZX_OUT_CH(p, '>'); zx_pop_seen(pop_seen); #else /* root node has no end tag either */ #endif ENC_LEN_DEBUG(x, "ELNSCELTAG", p-enc_base); return p; } /* FUNC(TXEASY_ENC_SO_ELNAME) */ /* Called by: */ struct zx_str* TXEASY_ENC_SO_ELNAME(struct zx_ctx* c, struct ELSTRUCT* x SIMPLETAGLENNS) { int len; char* buf; c->ns_tab = ZX_ALLOC(c, sizeof(TXns_tab)); memcpy(c->ns_tab, TXns_tab, sizeof(TXns_tab)); len = TXLEN_SO_ELNAME(c, x SIMPLELENNSARG); buf = ZX_ALLOC(c, len+1); return zx_easy_enc_common(c, TXENC_SO_ELNAME(c, x, buf SIMPLETAGLENNSARG), buf, len); } /* FUNC(TXEASY_ENC_WO_ELNAME) */ /* Called by: */ struct zx_str* TXEASY_ENC_WO_ELNAME(struct zx_ctx* c, struct ELSTRUCT* x SIMPLETAGLEN) { int len; char* buf; c->ns_tab = ZX_ALLOC(c, sizeof(TXns_tab)); memcpy(c->ns_tab, TXns_tab, sizeof(TXns_tab)); len = TXLEN_WO_ELNAME(c, x SIMPLELENARG); buf = ZX_ALLOC(c, len+1); return zx_easy_enc_common(c, TXENC_WO_ELNAME(c, x, buf SIMPLETAGLENARG), buf, len); } #if 1 /* ENC_WO_SUBTEMPL */ /* FUNC(TXENC_WO_any_elem) */ /* Called by: */ int TXLEN_WO_any_elem(struct zx_ctx* c, struct zx_elem_s* x) { int len; //struct zx_elem_s* kid; switch (x->g.tok) { ANYELEM_WO_LEN; case ZX_TOK_NOT_FOUND: len = 1 + ZX_ANY_EL(x)->name_len + 1 + 2 + ZX_ANY_EL(x)->name_len + 1; if (x->g.ns && x->g.ns->prefix_len) len += (x->g.ns->prefix_len + 1) * 2; len += zx_len_wo_common(c, x); return len; case ZX_TOK_DATA: return ((struct zx_str*)x)->len; break; default: NEVER("Impossible token(%d)", x->g.tok); } return 0; } /* FUNC(TXENC_WO_any_elem) */ /* Called by: */ char* TXENC_WO_any_elem(struct zx_ctx* c, struct zx_elem_s* x, char* p) { struct zx_ns_s* pop_seen = 0; struct zx_elem_s* kid; switch (x->g.tok) { ANYELEM_WO_ENC; case ZX_TOK_NOT_FOUND: pop_seen = 0; ZX_OUT_CH(p, '<'); if (x->g.ns && x->g.ns->prefix_len) { ZX_OUT_MEM(p, x->g.ns->prefix, x->g.ns->prefix_len); ZX_OUT_CH(p, ':'); } ZX_OUT_MEM(p, ZX_ANY_EL(x)->name, ZX_ANY_EL(x)->name_len); zx_add_xmlns_if_not_seen(c, x->g.ns, &pop_seen); /* *** xmlns specs */ p = zx_enc_seen(p, pop_seen); p = zx_enc_unknown_attrs(p, ZX_ANY_EL(x)->gg.any_attr); for (kid = x->kids; kid; kid = ((struct zx_elem_s*)(kid->g.wo))) p = TXENC_WO_any_elem(c, kid, p); ZX_OUT_CH(p, '<'); ZX_OUT_CH(p, '/'); if (x->g.ns && x->g.ns->prefix_len) { ZX_OUT_MEM(p, x->g.ns->prefix, x->g.ns->prefix_len); ZX_OUT_CH(p, ':'); } ZX_OUT_MEM(p, ZX_ANY_EL(x)->name, ZX_ANY_EL(x)->name_len); ZX_OUT_CH(p, '>'); zx_pop_seen(pop_seen); break; case ZX_TOK_DATA: ZX_OUT_STR(p, x); break; default: NEVER("Impossible token(%d)", x->g.tok); } return p; } /* FUNC(TXEASY_ENC_WO_any_elem) */ /* Called by: */ struct zx_str* TXEASY_ENC_WO_any_elem(struct zx_ctx* c, struct zx_elem_s* x) { int len = TXLEN_WO_any_elem(c, x); char* buf = ZX_ALLOC(c, len+1); return zx_easy_enc_common(c, TXENC_WO_any_elem(c, x, buf), buf, len); } #endif /* EOF */