[json-glib] generator: Avoid multiple buffer allocations
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [json-glib] generator: Avoid multiple buffer allocations
- Date: Sat, 18 Mar 2017 18:29:49 +0000 (UTC)
commit 87ee7241c62af4e6d696da784a87427b1073e5cb
Author: Garrett Regier <garrettregier gmail com>
Date: Thu Oct 20 19:21:32 2016 -0700
generator: Avoid multiple buffer allocations
Instead share a single GString in all
dump functions.
https://bugzilla.gnome.org/show_bug.cgi?id=773504
json-glib/json-generator.c | 254 ++++++++++++--------------------------------
1 files changed, 67 insertions(+), 187 deletions(-)
---
diff --git a/json-glib/json-generator.c b/json-glib/json-generator.c
index 879f3be..d1a0894 100644
--- a/json-glib/json-generator.c
+++ b/json-glib/json-generator.c
@@ -60,37 +60,32 @@ enum
PROP_LAST
};
-static gchar *dump_value (JsonGenerator *generator,
+static void dump_value (GString *buffer,
gint level,
- const gchar *name,
- JsonNode *node,
- gsize *length);
-static gchar *dump_array (JsonGenerator *generator,
+ JsonNode *node);
+static void dump_array (JsonGenerator *generator,
+ GString *buffer,
gint level,
- const gchar *name,
- JsonArray *array,
- gsize *length);
-static gchar *dump_object (JsonGenerator *generator,
+ JsonArray *array);
+static void dump_object (JsonGenerator *generator,
+ GString *buffer,
gint level,
- const gchar *name,
- JsonObject *object,
- gsize *length);
+ JsonObject *object);
static GParamSpec *generator_props[PROP_LAST] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE (JsonGenerator, json_generator, G_TYPE_OBJECT)
-static gchar *
-json_strescape (const gchar *str)
+static void
+json_strescape (GString *output,
+ const gchar *str)
{
const gchar *p;
const gchar *end;
- GString *output;
gsize len;
len = strlen (str);
end = str + len;
- output = g_string_sized_new (len);
for (p = str; p < end; p++)
{
@@ -128,8 +123,6 @@ json_strescape (const gchar *str)
g_string_append_c (output, *p);
}
}
-
- return g_string_free (output, FALSE);
}
static void
@@ -283,20 +276,16 @@ json_generator_init (JsonGenerator *generator)
priv->indent_char = ' ';
}
-static gchar *
-dump_value (JsonGenerator *generator,
- gint level,
- const gchar *name,
- JsonNode *node,
- gsize *length)
+static void
+dump_node (JsonGenerator *generator,
+ GString *buffer,
+ gint level,
+ const gchar *name,
+ JsonNode *node)
{
JsonGeneratorPrivate *priv = generator->priv;
gboolean pretty = priv->pretty;
guint indent = priv->indent;
- const JsonValue *value;
- GString *buffer;
-
- buffer = g_string_new ("");
if (pretty)
{
@@ -308,12 +297,45 @@ dump_value (JsonGenerator *generator,
if (name)
{
+ g_string_append_c (buffer, '"');
+ json_strescape (buffer, name);
+ g_string_append_c (buffer, '"');
+
if (pretty)
- g_string_append_printf (buffer, "\"%s\" : ", name);
+ g_string_append (buffer, " : ");
else
- g_string_append_printf (buffer, "\"%s\":", name);
+ g_string_append_c (buffer, ':');
}
+ switch (JSON_NODE_TYPE (node))
+ {
+ case JSON_NODE_NULL:
+ g_string_append (buffer, "null");
+ break;
+
+ case JSON_NODE_VALUE:
+ dump_value (buffer, level, node);
+ break;
+
+ case JSON_NODE_ARRAY:
+ dump_array (generator, buffer, level,
+ json_node_get_array (node));
+ break;
+
+ case JSON_NODE_OBJECT:
+ dump_object (generator, buffer, level,
+ json_node_get_object (node));
+ break;
+ }
+}
+
+static void
+dump_value (GString *buffer,
+ gint level,
+ JsonNode *node)
+{
+ const JsonValue *value;
+
value = node->data.value;
switch (value->type)
@@ -324,14 +346,9 @@ dump_value (JsonGenerator *generator,
case JSON_VALUE_STRING:
{
- gchar *tmp;
-
- tmp = json_strescape (json_value_get_string (value));
g_string_append_c (buffer, '"');
- g_string_append (buffer, tmp);
+ json_strescape (buffer, json_value_get_string (value));
g_string_append_c (buffer, '"');
-
- g_free (tmp);
}
break;
@@ -361,43 +378,20 @@ dump_value (JsonGenerator *generator,
default:
break;
}
-
- if (length)
- *length = buffer->len;
-
- return g_string_free (buffer, FALSE);
}
-static gchar *
+static void
dump_array (JsonGenerator *generator,
+ GString *buffer,
gint level,
- const gchar *name,
- JsonArray *array,
- gsize *length)
+ JsonArray *array)
{
JsonGeneratorPrivate *priv = generator->priv;
guint array_len = json_array_get_length (array);
guint i;
- GString *buffer;
gboolean pretty = priv->pretty;
guint indent = priv->indent;
- buffer = g_string_new ("");
-
- if (pretty)
- {
- for (i = 0; i < (level * indent); i++)
- g_string_append_c (buffer, priv->indent_char);
- }
-
- if (name)
- {
- if (pretty)
- g_string_append_printf (buffer, "\"%s\" : ", name);
- else
- g_string_append_printf (buffer, "\"%s\":", name);
- }
-
g_string_append_c (buffer, '[');
if (pretty)
@@ -406,39 +400,8 @@ dump_array (JsonGenerator *generator,
for (i = 0; i < array_len; i++)
{
JsonNode *cur = json_array_get_element (array, i);
- guint sub_level = level + 1;
- guint j;
- gchar *value;
- switch (JSON_NODE_TYPE (cur))
- {
- case JSON_NODE_NULL:
- if (pretty)
- {
- for (j = 0; j < (sub_level * indent); j++)
- g_string_append_c (buffer, priv->indent_char);
- }
- g_string_append (buffer, "null");
- break;
-
- case JSON_NODE_VALUE:
- value = dump_value (generator, sub_level, NULL, cur, NULL);
- g_string_append (buffer, value);
- g_free (value);
- break;
-
- case JSON_NODE_ARRAY:
- value = dump_array (generator, sub_level, NULL, json_node_get_array (cur), NULL);
- g_string_append (buffer, value);
- g_free (value);
- break;
-
- case JSON_NODE_OBJECT:
- value = dump_object (generator, sub_level, NULL, json_node_get_object (cur), NULL);
- g_string_append (buffer, value);
- g_free (value);
- break;
- }
+ dump_node (generator, buffer, level + 1, NULL, cur);
if ((i + 1) != array_len)
g_string_append_c (buffer, ',');
@@ -454,43 +417,20 @@ dump_array (JsonGenerator *generator,
}
g_string_append_c (buffer, ']');
-
- if (length)
- *length = buffer->len;
-
- return g_string_free (buffer, FALSE);
}
-static gchar *
+static void
dump_object (JsonGenerator *generator,
+ GString *buffer,
gint level,
- const gchar *name,
- JsonObject *object,
- gsize *length)
+ JsonObject *object)
{
JsonGeneratorPrivate *priv = generator->priv;
GList *members, *l;
- GString *buffer;
gboolean pretty = priv->pretty;
guint indent = priv->indent;
guint i;
- buffer = g_string_new ("");
-
- if (pretty)
- {
- for (i = 0; i < (level * indent); i++)
- g_string_append_c (buffer, priv->indent_char);
- }
-
- if (name)
- {
- if (pretty)
- g_string_append_printf (buffer, "\"%s\" : ", name);
- else
- g_string_append_printf (buffer, "\"%s\":", name);
- }
-
g_string_append_c (buffer, '{');
if (pretty)
@@ -501,55 +441,15 @@ dump_object (JsonGenerator *generator,
for (l = members; l != NULL; l = l->next)
{
const gchar *member_name = l->data;
- gchar *escaped_name = json_strescape (member_name);
JsonNode *cur = json_object_get_member (object, member_name);
- guint sub_level = level + 1;
- guint j;
- gchar *value;
- switch (JSON_NODE_TYPE (cur))
- {
- case JSON_NODE_NULL:
- if (pretty)
- {
- for (j = 0; j < (sub_level * indent); j++)
- g_string_append_c (buffer, priv->indent_char);
- g_string_append_printf (buffer, "\"%s\" : null", escaped_name);
- }
- else
- {
- g_string_append_printf (buffer, "\"%s\":null", escaped_name);
- }
- break;
-
- case JSON_NODE_VALUE:
- value = dump_value (generator, sub_level, escaped_name, cur, NULL);
- g_string_append (buffer, value);
- g_free (value);
- break;
-
- case JSON_NODE_ARRAY:
- value = dump_array (generator, sub_level, escaped_name,
- json_node_get_array (cur), NULL);
- g_string_append (buffer, value);
- g_free (value);
- break;
-
- case JSON_NODE_OBJECT:
- value = dump_object (generator, sub_level, escaped_name,
- json_node_get_object (cur), NULL);
- g_string_append (buffer, value);
- g_free (value);
- break;
- }
+ dump_node (generator, buffer, level + 1, member_name, cur);
if (l->next != NULL)
g_string_append_c (buffer, ',');
if (pretty)
g_string_append_c (buffer, '\n');
-
- g_free (escaped_name);
}
g_list_free (members);
@@ -561,11 +461,6 @@ dump_object (JsonGenerator *generator,
}
g_string_append_c (buffer, '}');
-
- if (length)
- *length = buffer->len;
-
- return g_string_free (buffer, FALSE);
}
/**
@@ -600,7 +495,7 @@ json_generator_to_data (JsonGenerator *generator,
gsize *length)
{
JsonNode *root;
- gchar *retval = NULL;
+ GString *string;
g_return_val_if_fail (JSON_IS_GENERATOR (generator), NULL);
@@ -613,28 +508,13 @@ json_generator_to_data (JsonGenerator *generator,
return NULL;
}
- switch (JSON_NODE_TYPE (root))
- {
- case JSON_NODE_ARRAY:
- retval = dump_array (generator, 0, NULL, json_node_get_array (root), length);
- break;
+ string = g_string_new ("");
+ dump_node (generator, string, 0, NULL, root);
- case JSON_NODE_OBJECT:
- retval = dump_object (generator, 0, NULL, json_node_get_object (root), length);
- break;
-
- case JSON_NODE_NULL:
- retval = g_strdup ("null");
- if (length)
- *length = 4;
- break;
-
- case JSON_NODE_VALUE:
- retval = dump_value (generator, 0, NULL, root, length);
- break;
- }
+ if (length)
+ *length = string->len;
- return retval;
+ return g_string_free (string, FALSE);
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]