[json-glib] reader: Maintain a stack of member names



commit 1f6668a9534c01523361075dad290c0dc49d7623
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sat Dec 20 23:22:09 2014 +0000

    reader: Maintain a stack of member names
    
    This fixes the case where, with nested objects, we call:
        json_reader_read_member (reader, "outer");
        // json_reader_get_member_name (reader) == "outer"
    
        json_reader_read_member (reader, "inner");
        // json_reader_get_member_name (reader) == "inner"
        // do something useful
        json_reader_end_member (reader);
    but at the end, the following assertion no longer holds:
        // json_reader_get_member_name (reader) == "outer"
    even though the JsonReader state should have been reset after ending the
    inner node.
    
    Fix it by maintaining a stack of member names. This works with both
    json_reader_read_member() and json_reader_read_element(). Updates to the
    unit tests are included.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=741824

 json-glib/json-reader.c  |   29 ++++++++++++++++-------------
 json-glib/tests/reader.c |   13 +++++++++++++
 2 files changed, 29 insertions(+), 13 deletions(-)
---
diff --git a/json-glib/json-reader.c b/json-glib/json-reader.c
index 67b67a5..85455a3 100644
--- a/json-glib/json-reader.c
+++ b/json-glib/json-reader.c
@@ -86,7 +86,8 @@ struct _JsonReaderPrivate
   JsonNode *current_node;
   JsonNode *previous_node;
 
-  gchar *current_member;
+  /* Stack of member names. */
+  GPtrArray *members;
 
   GError *error;
 };
@@ -117,7 +118,8 @@ json_reader_finalize (GObject *gobject)
   if (priv->error != NULL)
     g_clear_error (&priv->error);
 
-  g_free (priv->current_member);
+  if (priv->members != NULL)
+    g_ptr_array_unref (priv->members);
 
   G_OBJECT_CLASS (json_reader_parent_class)->finalize (gobject);
 }
@@ -189,6 +191,7 @@ static void
 json_reader_init (JsonReader *self)
 {
   self->priv = json_reader_get_instance_private (self);
+  self->priv->members = g_ptr_array_new_with_free_func (g_free);
 }
 
 /**
@@ -487,13 +490,12 @@ json_reader_read_element (JsonReader *reader,
                                         index_);
 
         priv->previous_node = priv->current_node;
-        g_free (priv->current_member);
 
         members = json_object_get_members (object);
         name = g_list_nth_data (members, index_);
 
         priv->current_node = json_object_get_member (object, name);
-        priv->current_member = g_strdup (name);
+        g_ptr_array_add (priv->members, g_strdup (name));
 
         g_list_free (members);
       }
@@ -536,8 +538,8 @@ json_reader_end_element (JsonReader *reader)
   else
     tmp = NULL;
 
-  g_free (priv->current_member);
-  priv->current_member = NULL;
+  if (json_node_get_node_type (priv->previous_node) == JSON_NODE_OBJECT)
+    g_ptr_array_remove_index (priv->members, priv->members->len - 1);
 
   priv->current_node = priv->previous_node;
   priv->previous_node = tmp;
@@ -648,11 +650,9 @@ json_reader_read_member (JsonReader  *reader,
                                     "object at the current position."),
                                   member_name);
 
-  g_free (priv->current_member);
-
   priv->previous_node = priv->current_node;
   priv->current_node = json_object_get_member (object, member_name);
-  priv->current_member = g_strdup (member_name);
+  g_ptr_array_add (priv->members, g_strdup (member_name));
 
   return TRUE;
 }
@@ -686,8 +686,7 @@ json_reader_end_member (JsonReader *reader)
   else
     tmp = NULL;
 
-  g_free (priv->current_member);
-  priv->current_member = NULL;
+  g_ptr_array_remove_index (priv->members, priv->members->len - 1);
 
   priv->current_node = priv->previous_node;
   priv->previous_node = tmp;
@@ -1032,8 +1031,12 @@ json_reader_get_member_name (JsonReader *reader)
     {
       json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
                              _("No node available at the current position"));
-      return FALSE;
+      return NULL;
     }
 
-  return reader->priv->current_member;
+  if (reader->priv->members->len == 0)
+    return NULL;
+
+  return g_ptr_array_index (reader->priv->members,
+                            reader->priv->members->len - 1);
 }
diff --git a/json-glib/tests/reader.c b/json-glib/tests/reader.c
index 19f58c9..79f50e2 100644
--- a/json-glib/tests/reader.c
+++ b/json-glib/tests/reader.c
@@ -153,24 +153,37 @@ test_reader_level (void)
 
   /* Grab the list */
   g_assert (json_reader_read_member (reader, "list"));
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, "list");
 
   members = json_reader_list_members (reader);
   g_assert (members != NULL);
   g_strfreev (members);
 
   g_assert (json_reader_read_member (reader, "181195771"));
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, "181195771");
 
   g_assert (!json_reader_read_member (reader, "resolved_url"));
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, NULL);
   g_assert (json_reader_get_error (reader) != NULL);
   json_reader_end_member (reader);
 
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, "181195771");
+
   g_assert (json_reader_read_member (reader, "given_url"));
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, "given_url");
   g_assert_cmpstr (json_reader_get_string_value (reader), ==, "http://www.gnome.org/json-glib-test";);
   json_reader_end_member (reader);
 
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, "181195771");
+
   json_reader_end_member (reader);
 
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, "list");
+
   json_reader_end_member (reader);
+
+  g_assert_cmpstr (json_reader_get_member_name (reader), ==, NULL);
+
   g_clear_object (&reader);
   g_clear_object (&parser);
 }


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