builderparser: Don't exit too early on nested custom tags
authorAlexander Mikhaylenko <alexm@gnome.org>
Tue, 28 Feb 2023 10:25:42 +0000 (14:25 +0400)
committerAlexander Mikhaylenko <alexm@gnome.org>
Tue, 28 Feb 2023 10:46:14 +0000 (14:46 +0400)
Currently nested custom tags work only as long as the element names differ
from the root one. If it's same, for example:

<condition type="any">
  <condition type="max-width">600</condition>
  <condition type="max-height">600</condition>
</condition>

then it will fail. Meanwhile the same tags wrapped into <conditions> would
work.

The problem is that custom tag parsing is considered finished as soon as we
encounter a closing tag with the same element name. So instead, track the
nesting level.

gtk/gtkbuilderparser.c
gtk/gtkbuilderprivate.h

index 9658ea226ec30382417d77e085a3021d42ff302d..1d2d0b3d0b5190b407904c56d2445aaddcfa118e 100644 (file)
@@ -1608,6 +1608,7 @@ create_subparser (GObject       *object,
   subparser->object = object;
   subparser->child = child;
   subparser->tagname = g_strdup (element_name);
+  subparser->level = 1;
   subparser->start = element_name;
   subparser->parser = g_memdup2 (parser, sizeof (GtkBuildableParser));
   subparser->data = user_data;
@@ -1638,6 +1639,8 @@ subparser_start (GtkBuildableParseContext  *context,
 
   if (subparser->start)
     {
+      subparser->level++;
+
       if (subparser->parser->start_element)
         subparser->parser->start_element (context,
                                           element_name, names, values,
@@ -1653,6 +1656,8 @@ subparser_end (GtkBuildableParseContext  *context,
                ParserData                *data,
                GError                   **error)
 {
+  data->subparser->level--;
+
   if (data->subparser->parser->end_element)
     data->subparser->parser->end_element (context, element_name,
                                           data->subparser->data, error);
@@ -1660,9 +1665,11 @@ subparser_end (GtkBuildableParseContext  *context,
   if (*error)
     return;
 
-  if (strcmp (data->subparser->start, element_name) != 0)
+  if (data->subparser->level > 0)
     return;
 
+  g_assert (strcmp (data->subparser->start, element_name) == 0);
+
   gtk_buildable_custom_tag_end (GTK_BUILDABLE (data->subparser->object),
                                 data->builder,
                                 data->subparser->child,
index 21ceca77c0a7c48d0079931902dede79f2de8d50..20b874c843d1e7885581bac2b27d7111d6a75f5d 100644 (file)
@@ -165,6 +165,7 @@ struct _GtkBuildableParseContext {
 typedef struct {
   GtkBuildableParser *parser;
   char *tagname;
+  int level;
   const char *start;
   gpointer data;
   GObject *object;