[json-glib] core: Avoid json_object_get_members()



commit d78ad648942637fb9212d1d93670509d4c7f687b
Author: Garrett Regier <garrettregier gmail com>
Date:   Thu Oct 20 19:44:09 2016 -0700

    core: Avoid json_object_get_members()
    
    Use JsonObject's private members_ordered
    GQueue instead. This avoids a g_list_copy().
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773504

 json-glib/json-generator.c     |    9 ++++-----
 json-glib/json-gobject.c       |   21 ++++++++-------------
 json-glib/json-gvariant.c      |   20 +++++++-------------
 json-glib/json-object.c        |    9 +++++++++
 json-glib/json-path.c          |   14 ++++++--------
 json-glib/json-reader.c        |   23 ++++++++++-------------
 json-glib/json-types-private.h |    3 +++
 7 files changed, 47 insertions(+), 52 deletions(-)
---
diff --git a/json-glib/json-generator.c b/json-glib/json-generator.c
index 6a9aff4..0afe881 100644
--- a/json-glib/json-generator.c
+++ b/json-glib/json-generator.c
@@ -426,7 +426,8 @@ dump_object (JsonGenerator *generator,
              JsonObject    *object)
 {
   JsonGeneratorPrivate *priv = generator->priv;
-  GList *members, *l;
+  GQueue *members;
+  GList *l;
   gboolean pretty = priv->pretty;
   guint indent = priv->indent;
   guint i;
@@ -436,9 +437,9 @@ dump_object (JsonGenerator *generator,
   if (pretty)
     g_string_append_c (buffer, '\n');
 
-  members = json_object_get_members (object);
+  members = json_object_get_members_internal (object);
 
-  for (l = members; l != NULL; l = l->next)
+  for (l = members->head; l != NULL; l = l->next)
     {
       const gchar *member_name = l->data;
       JsonNode *cur = json_object_get_member (object, member_name);
@@ -452,8 +453,6 @@ dump_object (JsonGenerator *generator,
         g_string_append_c (buffer, '\n');
     }
 
-  g_list_free (members);
-
   if (pretty)
     {
       for (i = 0; i < (level * indent); i++)
diff --git a/json-glib/json-gobject.c b/json-glib/json-gobject.c
index 923f0e1..abfbb8b 100644
--- a/json-glib/json-gobject.c
+++ b/json-glib/json-gobject.c
@@ -183,7 +183,9 @@ json_gobject_new (GType       gtype,
   gboolean find_property;
   gboolean deserialize_property;
   gboolean set_property;
-  GList *members, *members_left, *l;
+  GQueue *members;
+  GList *l;
+  GQueue members_left = G_QUEUE_INIT;
   guint n_members;
   GObjectClass *klass;
   GObject *retval;
@@ -193,8 +195,7 @@ json_gobject_new (GType       gtype,
   klass = g_type_class_ref (gtype);
 
   n_members = json_object_get_size (object);
-  members = json_object_get_members (object);
-  members_left = NULL;
+  members = json_object_get_members_internal (object);
 
   /* first pass: construct-only properties; here we cannot use Serializable
    * because we don't have an instance yet; we use the default implementation
@@ -204,7 +205,7 @@ json_gobject_new (GType       gtype,
    */
   construct_params = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_members);
 
-  for (l = members; l != NULL; l = l->next)
+  for (l = members->head; l != NULL; l = l->next)
     {
       const gchar *member_name = l->data;
       GParamSpec *pspec;
@@ -244,7 +245,7 @@ json_gobject_new (GType       gtype,
         }
 
     next_member:
-      members_left = g_list_prepend (members_left, l->data);
+      g_queue_push_tail (&members_left, l->data);
     }
 
   retval = g_object_newv (gtype,
@@ -261,12 +262,6 @@ json_gobject_new (GType       gtype,
     }
 
   g_array_free (construct_params, TRUE);
-  g_list_free (members);
-
-  /* we use g_list_prepend() above, but we want to maintain
-   * the ordering of json_object_get_members() here
-   */
-  members = g_list_reverse (members_left);
 
   /* do the Serializable type check once */
   if (g_type_is_a (gtype, JSON_TYPE_SERIALIZABLE))
@@ -286,7 +281,7 @@ json_gobject_new (GType       gtype,
 
   g_object_freeze_notify (retval);
 
-  for (l = members; l != NULL; l = l->next)
+  for (l = members_left.head; l != NULL; l = l->next)
     {
       const gchar *member_name = l->data;
       GParamSpec *pspec;
@@ -347,7 +342,7 @@ json_gobject_new (GType       gtype,
       g_value_unset (&value);
     }
 
-  g_list_free (members);
+  g_queue_clear (&members_left);
 
   g_object_thaw_notify (retval);
 
diff --git a/json-glib/json-gvariant.c b/json-glib/json-gvariant.c
index 58694de..8185cac 100644
--- a/json-glib/json-gvariant.c
+++ b/json-glib/json-gvariant.c
@@ -31,6 +31,7 @@
 
 #include "json-generator.h"
 #include "json-parser.h"
+#include "json-types-private.h"
 
 /**
  * SECTION:json-gvariant
@@ -947,8 +948,7 @@ json_to_gvariant_dict_entry (JsonNode     *json_node,
   gchar *value_signature;
   const gchar *tmp_signature;
 
-  GList *member;
-
+  GQueue *members;
   const gchar *json_member;
   JsonNode *json_value;
   GVariant *variant_member;
@@ -970,9 +970,8 @@ json_to_gvariant_dict_entry (JsonNode     *json_node,
                               &key_signature,
                               &value_signature);
 
-  member = json_object_get_members (obj);
-
-  json_member = (const gchar *) member->data;
+  members = json_object_get_members_internal (obj);
+  json_member = (const gchar *) members->head->data;
   variant_member = gvariant_simple_from_string (json_member,
                                                 key_signature[0],
                                                 error);
@@ -998,7 +997,6 @@ json_to_gvariant_dict_entry (JsonNode     *json_node,
         }
     }
 
-  g_list_free (member);
   g_free (value_signature);
   g_free (key_signature);
   g_free (entry_signature);
@@ -1026,7 +1024,7 @@ json_to_gvariant_dictionary (JsonNode     *json_node,
   const gchar *tmp_signature;
 
   GVariantBuilder *builder;
-  GList *members;
+  GQueue *members;
   GList *member;
 
   obj = json_node_get_object (json_node);
@@ -1043,10 +1041,9 @@ json_to_gvariant_dictionary (JsonNode     *json_node,
 
   builder = g_variant_builder_new (G_VARIANT_TYPE (dict_signature));
 
-  members = json_object_get_members (obj);
+  members = json_object_get_members_internal (obj);
 
-  member = members;
-  while (member != NULL)
+  for (member = members->head; member != NULL; member = member->next)
     {
       const gchar *json_member;
       JsonNode *json_value;
@@ -1082,15 +1079,12 @@ json_to_gvariant_dictionary (JsonNode     *json_node,
           roll_back = TRUE;
           break;
         }
-
-      member = member->next;
     }
 
   if (! roll_back)
     variant = g_variant_builder_end (builder);
 
   g_variant_builder_unref (builder);
-  g_list_free (members);
   g_free (value_signature);
   g_free (key_signature);
   g_free (entry_signature);
diff --git a/json-glib/json-object.c b/json-glib/json-object.c
index b6c08a5..29b9401 100644
--- a/json-glib/json-object.c
+++ b/json-glib/json-object.c
@@ -487,6 +487,15 @@ json_object_get_members (JsonObject *object)
   return g_list_copy (object->members_ordered.head);
 }
 
+
+GQueue *
+json_object_get_members_internal (JsonObject *object)
+{
+  g_return_val_if_fail (object != NULL, NULL);
+
+  return &object->members_ordered;
+}
+
 /**
  * json_object_get_values:
  * @object: a #JsonObject
diff --git a/json-glib/json-path.c b/json-glib/json-path.c
index dd04d58..fe6e7b1 100644
--- a/json-glib/json-path.c
+++ b/json-glib/json-path.c
@@ -755,10 +755,10 @@ walk_path_node (GList      *path,
           case JSON_NODE_OBJECT:
             {
               JsonObject *object = json_node_get_object (root);
-              GList *members, *l;
+              GQueue *members = json_object_get_members_internal (object);
+              GList *l;
 
-              members = json_object_get_members (object);
-              for (l = members; l != NULL; l = l->next)
+              for (l = members->head; l != NULL; l = l->next)
                 {
                   JsonNode *m = json_object_get_member (object, l->data);
 
@@ -774,7 +774,6 @@ walk_path_node (GList      *path,
                       walk_path_node (path, m, results);
                     }
                 }
-              g_list_free (members);
             }
             break;
 
@@ -815,10 +814,10 @@ walk_path_node (GList      *path,
       if (JSON_NODE_HOLDS_OBJECT (root))
         {
           JsonObject *object = json_node_get_object (root);
-          GList *members, *l;
+          GQueue *members = json_object_get_members_internal (object);
+          GList *l;
 
-          members = json_object_get_members (object);
-          for (l = members; l != NULL; l = l->next)
+          for (l = members->head; l != NULL; l = l->next)
             {
               JsonNode *member = json_object_get_member (object, l->data);
 
@@ -830,7 +829,6 @@ walk_path_node (GList      *path,
                   json_array_add_element (results, json_node_copy (member));
                 }
             }
-          g_list_free (members);
         }
       else
         json_array_add_element (results, json_node_copy (root));
diff --git a/json-glib/json-reader.c b/json-glib/json-reader.c
index b12734f..f371dd9 100644
--- a/json-glib/json-reader.c
+++ b/json-glib/json-reader.c
@@ -495,7 +495,7 @@ json_reader_read_element (JsonReader *reader,
     case JSON_NODE_OBJECT:
       {
         JsonObject *object = json_node_get_object (priv->current_node);
-        GList *members;
+        GQueue *members;
         const gchar *name;
 
         if (index_ >= json_object_get_size (object))
@@ -506,13 +506,11 @@ json_reader_read_element (JsonReader *reader,
 
         priv->previous_node = priv->current_node;
 
-        members = json_object_get_members (object);
-        name = g_list_nth_data (members, index_);
+        members = json_object_get_members_internal (object);
+        name = g_queue_peek_nth (members, index_);
 
         priv->current_node = json_object_get_member (object, name);
         g_ptr_array_add (priv->members, g_strdup (name));
-
-        g_list_free (members);
       }
       break;
 
@@ -737,7 +735,9 @@ gchar **
 json_reader_list_members (JsonReader *reader)
 {
   JsonReaderPrivate *priv;
-  GList *members, *l;
+  JsonObject *object;
+  GQueue *members;
+  GList *l;
   gchar **retval;
   gint i;
 
@@ -760,18 +760,15 @@ json_reader_list_members (JsonReader *reader)
       return NULL;
     }
 
-  members = json_object_get_members (json_node_get_object (priv->current_node));
-  if (members == NULL)
-    return NULL;
+  object = json_node_get_object (priv->current_node);
+  members = json_object_get_members_internal (object);
 
-  retval = g_new (gchar*, g_list_length (members) + 1);
-  for (l = members, i = 0; l != NULL; l = l->next, i += 1)
+  retval = g_new (gchar*, g_queue_get_length (members) + 1);
+  for (l = members->head, i = 0; l != NULL; l = l->next, i += 1)
     retval[i] = g_strdup (l->data);
 
   retval[i] = NULL;
 
-  g_list_free (members);
-
   return retval;
 }
 
diff --git a/json-glib/json-types-private.h b/json-glib/json-types-private.h
index fc7646b..bc29e80 100644
--- a/json-glib/json-types-private.h
+++ b/json-glib/json-types-private.h
@@ -124,6 +124,9 @@ G_GNUC_INTERNAL
 const gchar *   json_value_type_get_name        (JsonValueType    value_type);
 
 G_GNUC_INTERNAL
+GQueue *        json_object_get_members_internal (JsonObject     *object);
+
+G_GNUC_INTERNAL
 GType           json_value_type                 (const JsonValue *value);
 
 G_GNUC_INTERNAL


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