X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw-xml%2Fparse.c;h=65e556b602a0d5ae7c666ab743f31ed012694ddc;hb=f34afdacbff65c53002646c3081b037ae440f4bb;hp=2ddfa2b8fac52106e6169b9afa66a8423d40ee6b;hpb=e16fbdbeaeefc2b01ad1ed71d63ed98530bcbae5;p=libucw.git diff --git a/ucw-xml/parse.c b/ucw-xml/parse.c index 2ddfa2b8..65e556b6 100644 --- a/ucw-xml/parse.c +++ b/ucw-xml/parse.c @@ -54,6 +54,80 @@ xml_parse_eq(struct xml_context *ctx) xml_parse_white(ctx, 0); } +/*** Memory management ***/ + +void *xml_do_push(struct xml_context *ctx, uint size) +{ + /* Saves ctx->stack and ctx->flags state */ + struct mempool_state state; + mp_save(ctx->stack, &state); + struct xml_stack *s = mp_alloc(ctx->stack, size); + s->state = state; + s->flags = ctx->flags; + s->next = ctx->stack_list; + ctx->stack_list = s; + return s; +} + +void xml_do_pop(struct xml_context *ctx, struct xml_stack *s) +{ + /* Restore ctx->stack and ctx->flags state */ + ctx->stack_list = s->next; + ctx->flags = s->flags; + mp_restore(ctx->stack, &s->state); +} + +struct xml_node *xml_push_dom(struct xml_context *ctx, struct mempool_state *state) +{ + /* Create a new DOM node */ + TRACE(ctx, "push_dom"); + struct xml_dom_stack *s = xml_do_push(ctx, sizeof(*s)); + if (state) + s->state = *state; + else + mp_save(ctx->pool, &s->state); + struct xml_node *n = mp_alloc(ctx->pool, sizeof(*n)); + n->user = NULL; + if (n->parent = ctx->node) + clist_add_tail(&n->parent->sons, &n->n); + return ctx->node = n; +} + +void xml_pop_dom(struct xml_context *ctx, uint free) +{ + /* Leave DOM subtree */ + TRACE(ctx, "pop_dom"); + ASSERT(ctx->node); + struct xml_node *p = ctx->node->parent; + struct xml_dom_stack *s = (void *)ctx->stack_list; + if (free) + { + /* See xml_pop_element() for cleanup of attribute hash table */ + if (p) + clist_remove(&ctx->node->n); + mp_restore(ctx->pool, &s->state); + } + ctx->node = p; + xml_do_pop(ctx, &s->stack); +} + +/*** Basics ***/ + +uint xml_parse_white(struct xml_context *ctx, uint mandatory) +{ + /* mandatory=1 -> S ::= (#x20 | #x9 | #xD | #xA)+ + * mandatory=0 -> S? */ + uint cnt = 0; + while (xml_peek_cat(ctx) & XML_CHAR_WHITE) + { + xml_skip_char(ctx); + cnt++; + } + if (unlikely(mandatory && !cnt)) + xml_fatal_expected_white(ctx); + return cnt; +} + /*** Names and nmtokens ***/ static char * @@ -387,7 +461,7 @@ xml_spout_chars(struct fastbuf *fb) } } -static inline uint +static uint xml_end_chars(struct xml_context *ctx, char **out) { struct fastbuf *fb = &ctx->chars; @@ -402,7 +476,7 @@ xml_end_chars(struct xml_context *ctx, char **out) return len; } -static inline uint +static uint xml_report_chars(struct xml_context *ctx, char **out) { struct fastbuf *fb = &ctx->chars; @@ -416,7 +490,7 @@ xml_report_chars(struct xml_context *ctx, char **out) return len; } -static inline uint +static uint xml_flush_chars(struct xml_context *ctx) { char *text, *rtext; @@ -447,14 +521,14 @@ xml_flush_chars(struct xml_context *ctx) return len; } -static inline void +static void xml_pop_chars(struct xml_context *ctx) { xml_pop_dom(ctx, !(ctx->flags & XML_ALLOC_CHARS)); TRACE(ctx, "pop_chars"); } -static inline void +static void xml_append_chars(struct xml_context *ctx) { TRACE(ctx, "append_chars"); @@ -850,7 +924,7 @@ xml_parse_etag(struct xml_context *ctx) if (xml_get_char(ctx) != '>') { recover: - xml_error(ctx, "Invalid ETag, expected ", e->name); + xml_error(ctx, "Invalid ETag, expected ", xml_node_qname(ctx, e)); while (xml_get_char(ctx) != '>'); } xml_dec(ctx);