[librsvg/rustification] RsvgNode: don't keep the node's element name in this struct while parsing



commit b2c5f373d12fa0c93f941aab22e6bb8076bf3bee
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Nov 17 07:25:40 2016 -0600

    RsvgNode: don't keep the node's element name in this struct while parsing
    
    While an RsvgHandle is parsing, it keeps a stack with the name of the
    current XML element.  However, it kept the element name as part of the
    RsvgNode structure.  The name pointers are only valid while the
    xmlParserCtxtPtr is alive; after that, node->name contains a dangling
    pointer (fortunately unused).
    
    Instead of burdening RsvgNode with maintaining the parsing stack, we now
    keep this stack in RsvgHandlePrivate instead.

 rsvg-base.c    |   50 ++++++++++++++++++++++++++++++++++++++++++--------
 rsvg-gobject.c |    1 +
 rsvg-private.h |    6 +++++-
 3 files changed, 48 insertions(+), 9 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 275b08e..9119b62 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -208,6 +208,36 @@ register_node_in_defs (RsvgHandle *ctx, RsvgNode *node, RsvgPropertyBag *atts)
     }
 }
 
+static void
+push_element_name (RsvgHandle *ctx, const char *name)
+{
+    /* libxml holds on to the name while parsing; we won't dup the name here */
+    ctx->priv->element_name_stack = g_slist_prepend (ctx->priv->element_name_stack, (void *) name);
+}
+
+static gboolean
+topmost_element_name_is (RsvgHandle *ctx, const char *name)
+{
+    if (ctx->priv->element_name_stack) {
+        const char *name_in_stack = ctx->priv->element_name_stack->data;
+
+        return strcmp (name, name_in_stack) == 0;
+    } else
+        return FALSE;
+}
+
+static void
+pop_element_name (RsvgHandle *ctx)
+{
+    ctx->priv->element_name_stack = g_slist_delete_link (ctx->priv->element_name_stack, 
ctx->priv->element_name_stack);
+}
+
+static void
+free_element_name_stack (RsvgHandle *ctx)
+{
+    g_slist_free (ctx->priv->element_name_stack);
+    ctx->priv->element_name_stack = NULL;
+}
 
 static void
 rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag * atts)
@@ -331,9 +361,10 @@ rsvg_standard_element_start (RsvgHandle * ctx, const char *name, RsvgPropertyBag
 
     if (newnode) {
         g_assert (RSVG_NODE_TYPE (newnode) != RSVG_NODE_TYPE_INVALID);
-        newnode->name = (char *) name; /* libxml will keep this while parsing */
         newnode->parent = ctx->priv->currentnode;
 
+        push_element_name (ctx, name);
+
         add_node_to_handle (ctx, newnode);
         register_node_in_defs (ctx, newnode, atts);
         rsvg_node_set_atts (newnode, ctx, atts);
@@ -725,32 +756,33 @@ rsvg_start_element (void *data, const xmlChar * name, const xmlChar ** atts)
 }
 
 static void
-rsvg_end_element (void *data, const xmlChar * name)
+rsvg_end_element (void *data, const xmlChar * xmlname)
 {
     RsvgHandle *ctx = (RsvgHandle *) data;
+    const char *name = (const char *) xmlname;
 
     if (ctx->priv->handler_nest > 0 && ctx->priv->handler != NULL) {
         if (ctx->priv->handler->end_element != NULL)
-            ctx->priv->handler->end_element (ctx->priv->handler, (const char *) name);
+            ctx->priv->handler->end_element (ctx->priv->handler, name);
         ctx->priv->handler_nest--;
     } else {
         const char *tempname;
-        for (tempname = (const char *) name; *tempname != '\0'; tempname++)
+        for (tempname = name; *tempname != '\0'; tempname++)
             if (*tempname == ':')
-                name = (const xmlChar *) (tempname + 1);
+                name = tempname + 1;
 
         if (ctx->priv->handler != NULL) {
             ctx->priv->handler->free (ctx->priv->handler);
             ctx->priv->handler = NULL;
         }
 
-        if (ctx->priv->currentnode &&
-            !strcmp ((const char *) name, ctx->priv->currentnode->name)) {
+        if (ctx->priv->currentnode && topmost_element_name_is (ctx, name)) {
             ctx->priv->currentnode = ctx->priv->currentnode->parent;
+            pop_element_name (ctx);
         }
 
         /* FIXMEchpe: shouldn't this check that currentnode == treebase or sth like that? */
-        if (ctx->priv->treebase && !strcmp ((const char *)name, "svg"))
+        if (ctx->priv->treebase && !strcmp (name, "svg"))
             _rsvg_node_svg_apply_atts ((RsvgNodeSvg *)ctx->priv->treebase, ctx);
     }
 }
@@ -1244,6 +1276,8 @@ rsvg_handle_close_impl (RsvgHandle * handle, GError ** error)
         xmlFreeDoc (xml_doc);
     }
 
+    free_element_name_stack (handle);
+
     handle->priv->finished = TRUE;
     handle->priv->error = NULL;
 
diff --git a/rsvg-gobject.c b/rsvg-gobject.c
index 94886fd..65f11d0 100644
--- a/rsvg-gobject.c
+++ b/rsvg-gobject.c
@@ -86,6 +86,7 @@ rsvg_handle_init (RsvgHandle * self)
     self->priv->ctxt = NULL;
     self->priv->currentnode = NULL;
     self->priv->treebase = NULL;
+    self->priv->element_name_stack = NULL;
 
     self->priv->finished = 0;
     self->priv->data_input_stream = NULL;
diff --git a/rsvg-private.h b/rsvg-private.h
index c750496..cda6f03 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -141,6 +141,11 @@ struct RsvgHandlePrivate {
        file is converted into at the end */
     RsvgNode *treebase;
 
+    /* Stack of element names while parsing; used to know when to stop parsing
+     * the current element.
+     */
+    GSList *element_name_stack;
+
     GHashTable *css_props;
 
     /* not a handler stack. each nested handler keeps
@@ -328,7 +333,6 @@ struct _RsvgNode {
     RsvgNode *parent;
     GPtrArray *children;
     RsvgNodeType type;
-    const char *name; /* owned by the xmlContext, invalid after parsing! */
     void (*free) (RsvgNode * self);
     void (*draw) (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate);
     void (*set_atts) (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag *);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]