tizen 2.4 release
[external/libjson-glib.git] / json-glib / json-generator.c
index c77830e..8eed152 100644 (file)
@@ -29,9 +29,7 @@
  * put it into a buffer or a file.
  */
 
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <stdlib.h>
 #include <string.h>
@@ -41,9 +39,6 @@
 #include "json-marshal.h"
 #include "json-generator.h"
 
-#define JSON_GENERATOR_GET_PRIVATE(obj) \
-        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_GENERATOR, JsonGeneratorPrivate))
-
 struct _JsonGeneratorPrivate
 {
   JsonNode *root;
@@ -61,13 +56,16 @@ enum
   PROP_PRETTY,
   PROP_INDENT,
   PROP_ROOT,
-  PROP_INDENT_CHAR
+  PROP_INDENT_CHAR,
+
+  PROP_LAST
 };
 
 static gchar *dump_value  (JsonGenerator *generator,
                            gint           level,
                            const gchar   *name,
-                           JsonNode      *node);
+                           JsonNode      *node,
+                           gsize         *length);
 static gchar *dump_array  (JsonGenerator *generator,
                            gint           level,
                            const gchar   *name,
@@ -79,45 +77,69 @@ static gchar *dump_object (JsonGenerator *generator,
                            JsonObject    *object,
                            gsize         *length);
 
-/* non-ASCII characters can't be escaped, otherwise UTF-8
- * chars will break, so we just pregenerate this table of
- * high characters and then we feed it to g_strescape()
- */
-static const char json_exceptions[] = {
-  0x7f,  0x80,  0x81,  0x82,  0x83,  0x84,  0x85,  0x86,
-  0x87,  0x88,  0x89,  0x8a,  0x8b,  0x8c,  0x8d,  0x8e,
-  0x8f,  0x90,  0x91,  0x92,  0x93,  0x94,  0x95,  0x96,
-  0x97,  0x98,  0x99,  0x9a,  0x9b,  0x9c,  0x9d,  0x9e,
-  0x9f,  0xa0,  0xa1,  0xa2,  0xa3,  0xa4,  0xa5,  0xa6,
-  0xa7,  0xa8,  0xa9,  0xaa,  0xab,  0xac,  0xad,  0xae,
-  0xaf,  0xb0,  0xb1,  0xb2,  0xb3,  0xb4,  0xb5,  0xb6,
-  0xb7,  0xb8,  0xb9,  0xba,  0xbb,  0xbc,  0xbd,  0xbe,
-  0xbf,  0xc0,  0xc1,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,
-  0xc7,  0xc8,  0xc9,  0xca,  0xcb,  0xcc,  0xcd,  0xce,
-  0xcf,  0xd0,  0xd1,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,
-  0xd7,  0xd8,  0xd9,  0xda,  0xdb,  0xdc,  0xdd,  0xde,
-  0xdf,  0xe0,  0xe1,  0xe2,  0xe3,  0xe4,  0xe5,  0xe6,
-  0xe7,  0xe8,  0xe9,  0xea,  0xeb,  0xec,  0xed,  0xee,
-  0xef,  0xf0,  0xf1,  0xf2,  0xf3,  0xf4,  0xf5,  0xf6,
-  0xf7,  0xf8,  0xf9,  0xfa,  0xfb,  0xfc,  0xfd,  0xfe,
-  0xff,
-  '\0'   /* g_strescape() expects a NUL-terminated string */
-};
+static GParamSpec *generator_props[PROP_LAST] = { NULL, };
 
-G_DEFINE_TYPE (JsonGenerator, json_generator, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_PRIVATE (JsonGenerator, json_generator, G_TYPE_OBJECT)
 
 static gchar *
 json_strescape (const gchar *str)
 {
-  return g_strescape (str, json_exceptions);
+  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++)
+    {
+      if (*p == '\\' || *p == '"')
+        {
+          g_string_append_c (output, '\\');
+          g_string_append_c (output, *p);
+        }
+      else if ((*p > 0 && *p < 0x1f) || *p == 0x7f)
+        {
+          switch (*p)
+            {
+            case '\b':
+              g_string_append (output, "\\b");
+              break;
+            case '\f':
+              g_string_append (output, "\\f");
+              break;
+            case '\n':
+              g_string_append (output, "\\n");
+              break;
+            case '\r':
+              g_string_append (output, "\\r");
+              break;
+            case '\t':
+              g_string_append (output, "\\t");
+              break;
+            default:
+              g_string_append_printf (output, "\\u00%02x", (guint)*p);
+              break;
+            }
+        }
+      else
+        {
+          g_string_append_c (output, *p);
+        }
+    }
+
+  return g_string_free (output, FALSE);
 }
 
 static void
 json_generator_finalize (GObject *gobject)
 {
-  JsonGeneratorPrivate *priv = JSON_GENERATOR_GET_PRIVATE (gobject);
+  JsonGeneratorPrivate *priv;
 
-  if (priv->root)
+  priv = json_generator_get_instance_private ((JsonGenerator *) gobject);
+  if (priv->root != NULL)
     json_node_free (priv->root);
 
   G_OBJECT_CLASS (json_generator_parent_class)->finalize (gobject);
@@ -129,23 +151,26 @@ json_generator_set_property (GObject      *gobject,
                              const GValue *value,
                              GParamSpec   *pspec)
 {
-  JsonGeneratorPrivate *priv = JSON_GENERATOR_GET_PRIVATE (gobject);
+  JsonGenerator *generator = JSON_GENERATOR (gobject);
 
   switch (prop_id)
     {
     case PROP_PRETTY:
-      priv->pretty = g_value_get_boolean (value);
+      json_generator_set_pretty (generator, g_value_get_boolean (value));
       break;
+
     case PROP_INDENT:
-      priv->indent = g_value_get_uint (value);
+      json_generator_set_indent (generator, g_value_get_uint (value));
       break;
+
     case PROP_INDENT_CHAR:
-      priv->indent_char = g_value_get_uint (value);
+      json_generator_set_indent_char (generator, g_value_get_uint (value));
       break;
+
     case PROP_ROOT:
-      json_generator_set_root (JSON_GENERATOR (gobject),
-                               g_value_get_boxed (value));
+      json_generator_set_root (generator, g_value_get_boxed (value));
       break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
       break;
@@ -158,7 +183,7 @@ json_generator_get_property (GObject    *gobject,
                              GValue     *value,
                              GParamSpec *pspec)
 {
-  JsonGeneratorPrivate *priv = JSON_GENERATOR_GET_PRIVATE (gobject);
+  JsonGeneratorPrivate *priv = JSON_GENERATOR (gobject)->priv;
 
   switch (prop_id)
     {
@@ -185,12 +210,6 @@ json_generator_class_init (JsonGeneratorClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  g_type_class_add_private (klass, sizeof (JsonGeneratorPrivate));
-
-  gobject_class->set_property = json_generator_set_property;
-  gobject_class->get_property = json_generator_get_property;
-  gobject_class->finalize = json_generator_finalize;
-
   /**
    * JsonGenerator:pretty:
    *
@@ -198,26 +217,26 @@ json_generator_class_init (JsonGeneratorClass *klass)
    * newlines. The indentation level can be controlled by using the
    * JsonGenerator:indent property
    */
-  g_object_class_install_property (gobject_class,
-                                   PROP_PRETTY,
-                                   g_param_spec_boolean ("pretty",
-                                                         "Pretty",
-                                                         "Pretty-print the output",
-                                                         FALSE,
-                                                         G_PARAM_READWRITE));
+  generator_props[PROP_PRETTY] =
+    g_param_spec_boolean ("pretty",
+                          "Pretty",
+                          "Pretty-print the output",
+                          FALSE,
+                          G_PARAM_READWRITE);
+
   /**
    * JsonGenerator:indent:
    *
    * Number of spaces to be used to indent when pretty printing.
    */
-  g_object_class_install_property (gobject_class,
-                                   PROP_INDENT,
-                                   g_param_spec_uint ("indent",
-                                                      "Indent",
-                                                      "Number of indentation spaces",
-                                                      0, G_MAXUINT,
-                                                      2,
-                                                      G_PARAM_READWRITE));
+  generator_props[PROP_INDENT] =
+    g_param_spec_uint ("indent",
+                       "Indent",
+                       "Number of indentation spaces",
+                       0, G_MAXUINT,
+                       2,
+                       G_PARAM_READWRITE);
+
   /**
    * JsonGenerator:root:
    *
@@ -226,13 +245,13 @@ json_generator_class_init (JsonGeneratorClass *klass)
    *
    * Since: 0.4
    */
-  g_object_class_install_property (gobject_class,
-                                   PROP_ROOT,
-                                   g_param_spec_boxed ("root",
-                                                       "Root",
-                                                       "Root of the JSON data tree",
-                                                       JSON_TYPE_NODE,
-                                                       G_PARAM_READWRITE));
+  generator_props[PROP_ROOT] =
+    g_param_spec_boxed ("root",
+                        "Root",
+                        "Root of the JSON data tree",
+                        JSON_TYPE_NODE,
+                        G_PARAM_READWRITE);
+
   /**
    * JsonGenerator:indent-char:
    *
@@ -240,21 +259,25 @@ json_generator_class_init (JsonGeneratorClass *klass)
    *
    * Since: 0.6
    */
-  g_object_class_install_property (gobject_class,
-                                   PROP_INDENT_CHAR,
-                                   g_param_spec_unichar ("indent-char",
-                                                         "Indent Char",
-                                                         "Character that should be used when indenting",
-                                                         ' ',
-                                                         G_PARAM_READWRITE));
+  generator_props[PROP_INDENT_CHAR] =
+    g_param_spec_unichar ("indent-char",
+                          "Indent Char",
+                          "Character that should be used when indenting",
+                          ' ',
+                          G_PARAM_READWRITE);
+
+  gobject_class->set_property = json_generator_set_property;
+  gobject_class->get_property = json_generator_get_property;
+  gobject_class->finalize = json_generator_finalize;
+  g_object_class_install_properties (gobject_class, PROP_LAST, generator_props);
 }
 
 static void
 json_generator_init (JsonGenerator *generator)
 {
-  JsonGeneratorPrivate *priv;
+  JsonGeneratorPrivate *priv = json_generator_get_instance_private (generator);
 
-  generator->priv = priv = JSON_GENERATOR_GET_PRIVATE (generator);
+  generator->priv = priv;
 
   priv->pretty = FALSE;
   priv->indent = 2;
@@ -265,12 +288,13 @@ static gchar *
 dump_value (JsonGenerator *generator,
             gint           level,
             const gchar   *name,
-            JsonNode      *node)
+            JsonNode      *node,
+            gsize         *length)
 {
   JsonGeneratorPrivate *priv = generator->priv;
   gboolean pretty = priv->pretty;
   guint indent = priv->indent;
-  GValue value = { 0, };
+  const JsonValue *value;
   GString *buffer;
 
   buffer = g_string_new ("");
@@ -283,47 +307,59 @@ dump_value (JsonGenerator *generator,
         g_string_append_c (buffer, priv->indent_char);
     }
 
-  if (name && name[0] != '\0')
-    g_string_append_printf (buffer, "\"%s\" : ", name);
+  if (name)
+    {
+      if (pretty)
+        g_string_append_printf (buffer, "\"%s\" : ", name);
+      else
+        g_string_append_printf (buffer, "\"%s\":", name);
+    }
 
-  json_node_get_value (node, &value);
+  value = node->data.value;
 
-  switch (G_VALUE_TYPE (&value))
+  switch (value->type)
     {
-    case G_TYPE_INT64:
-      g_string_append_printf (buffer, "%" G_GINT64_FORMAT, g_value_get_int64 (&value));
+    case JSON_VALUE_INT:
+      g_string_append_printf (buffer, "%" G_GINT64_FORMAT, json_value_get_int (value));
       break;
 
-    case G_TYPE_STRING:
+    case JSON_VALUE_STRING:
       {
         gchar *tmp;
 
-        tmp = json_strescape (g_value_get_string (&value));
-        g_string_append_printf (buffer, "\"%s\"", tmp);
+        tmp = json_strescape (json_value_get_string (value));
+        g_string_append_c (buffer, '"');
+        g_string_append (buffer, tmp);
+        g_string_append_c (buffer, '"');
 
         g_free (tmp);
       }
       break;
 
-    case G_TYPE_DOUBLE:
+    case JSON_VALUE_DOUBLE:
       {
-        gchar buf[65];
+        gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
 
-        g_ascii_formatd (buf, 65, "%g", g_value_get_double (&value));
-        g_string_append (buffer, buf);
+        g_string_append (buffer,
+                         g_ascii_dtostr (buf, sizeof (buf),
+                                         json_value_get_double (value)));
       }
       break;
 
-    case G_TYPE_BOOLEAN:
-      g_string_append_printf (buffer, "%s",
-                              g_value_get_boolean (&value) ? "true" : "false");
+    case JSON_VALUE_BOOLEAN:
+      g_string_append (buffer, json_value_get_boolean (value) ? "true" : "false");
+      break;
+
+    case JSON_VALUE_NULL:
+      g_string_append (buffer, "null");
       break;
 
     default:
       break;
     }
 
-  g_value_unset (&value);
+  if (length)
+    *length = buffer->len;
 
   return g_string_free (buffer, FALSE);
 }
@@ -350,15 +386,18 @@ dump_array (JsonGenerator *generator,
         g_string_append_c (buffer, priv->indent_char);
     }
 
-  if (name && name[0] != '\0')
-    g_string_append_printf (buffer, "\"%s\" : ", name);
+  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)
     g_string_append_c (buffer, '\n');
-  else
-    g_string_append_c (buffer, ' ');
 
   for (i = 0; i < array_len; i++)
     {
@@ -379,7 +418,7 @@ dump_array (JsonGenerator *generator,
           break;
 
         case JSON_NODE_VALUE:
-          value = dump_value (generator, sub_level, NULL, cur);
+          value = dump_value (generator, sub_level, NULL, cur, NULL);
           g_string_append (buffer, value);
           g_free (value);
           break;
@@ -402,8 +441,6 @@ dump_array (JsonGenerator *generator,
 
       if (pretty)
         g_string_append_c (buffer, '\n');
-      else
-        g_string_append_c (buffer, ' ');
     }
 
   if (pretty)
@@ -442,21 +479,25 @@ dump_object (JsonGenerator *generator,
         g_string_append_c (buffer, priv->indent_char);
     }
 
-  if (name && name[0] != '\0')
-    g_string_append_printf (buffer, "\"%s\" : ", name);
+  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)
     g_string_append_c (buffer, '\n');
-  else
-    g_string_append_c (buffer, ' ');
 
   members = json_object_get_members (object);
 
   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;
@@ -469,25 +510,29 @@ dump_object (JsonGenerator *generator,
             {
               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);
             }
-          g_string_append_printf (buffer, "\"%s\" : null", member_name);
           break;
 
         case JSON_NODE_VALUE:
-          value = dump_value (generator, sub_level, member_name, cur);
+          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, member_name,
+          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, member_name,
+          value = dump_object (generator, sub_level, escaped_name,
                                json_node_get_object (cur), NULL);
           g_string_append (buffer, value);
           g_free (value);
@@ -499,8 +544,8 @@ dump_object (JsonGenerator *generator,
 
       if (pretty)
         g_string_append_c (buffer, '\n');
-      else
-        g_string_append_c (buffer, ' ');
+
+      g_free (escaped_name);
     }
 
   g_list_free (members);
@@ -524,7 +569,7 @@ dump_object (JsonGenerator *generator,
  * 
  * Creates a new #JsonGenerator. You can use this object to generate a
  * JSON data stream starting from a data object model composed by
- * #JsonNode<!-- -->s.
+ * #JsonNodes.
  *
  * Return value: the newly created #JsonGenerator instance
  */
@@ -581,7 +626,7 @@ json_generator_to_data (JsonGenerator *generator,
       break;
 
     case JSON_NODE_VALUE:
-      retval = NULL;
+      retval = dump_value (generator, 0, NULL, root, length);
       break;
     }
 
@@ -619,6 +664,43 @@ json_generator_to_file (JsonGenerator  *generator,
 }
 
 /**
+ * json_generator_to_stream:
+ * @generator: a #JsonGenerator
+ * @stream: a #GOutputStream
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Outputs JSON data and streams it (synchronously) to @stream.
+ *
+ * Return value: %TRUE if the write operation was successful, and %FALSE
+ *   on failure. In case of error, the #GError will be filled accordingly
+ *
+ * Since: 0.12
+ */
+gboolean
+json_generator_to_stream (JsonGenerator  *generator,
+                          GOutputStream  *stream,
+                          GCancellable   *cancellable,
+                          GError        **error)
+{
+  gboolean retval;
+  gchar *buffer;
+  gsize len;
+
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+  g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return FALSE;
+
+  buffer = json_generator_to_data (generator, &len);
+  retval = g_output_stream_write (stream, buffer, len, cancellable, error);
+  g_free (buffer);
+
+  return retval;
+}
+
+/**
  * json_generator_set_root:
  * @generator: a #JsonGenerator
  * @node: a #JsonNode
@@ -626,8 +708,8 @@ json_generator_to_file (JsonGenerator  *generator,
  * Sets @node as the root of the JSON data stream to be serialized by
  * the #JsonGenerator.
  *
- * <note>The node is copied by the generator object, so it can be safely
- * freed after calling this function.</note>
+ * The passed @node is copied by the generator object, so it can be
+ * safely freed after calling this function.
  */
 void
 json_generator_set_root (JsonGenerator *generator,
@@ -635,12 +717,178 @@ json_generator_set_root (JsonGenerator *generator,
 {
   g_return_if_fail (JSON_IS_GENERATOR (generator));
 
-  if (generator->priv->root)
+  if (generator->priv->root == node)
+    return;
+
+  if (generator->priv->root != NULL)
     {
       json_node_free (generator->priv->root);
       generator->priv->root = NULL;
     }
 
-  if (node)
+  if (node != NULL)
     generator->priv->root = json_node_copy (node);
+
+  g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_ROOT]);
+}
+
+/**
+ * json_generator_get_root:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves a pointer to the root #JsonNode set using
+ * json_generator_set_root().
+ *
+ * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
+ *   is owned by the #JsonGenerator and it should not be freed
+ *
+ * Since: 0.14
+ */
+JsonNode *
+json_generator_get_root (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), NULL);
+
+  return generator->priv->root;
+}
+
+/**
+ * json_generator_set_pretty:
+ * @generator: a #JsonGenerator
+ * @is_pretty: whether the generated string should be pretty printed
+ *
+ * Sets whether the generated JSON should be pretty printed, using the
+ * indentation character specified in the #JsonGenerator:indent-char
+ * property and the spacing specified in #JsonGenerator:indent property.
+ *
+ * Since: 0.14
+ */
+void
+json_generator_set_pretty (JsonGenerator *generator,
+                           gboolean       is_pretty)
+{
+  JsonGeneratorPrivate *priv;
+
+  g_return_if_fail (JSON_IS_GENERATOR (generator));
+
+  priv = generator->priv;
+
+  is_pretty = !!is_pretty;
+
+  if (priv->pretty != is_pretty)
+    {
+      priv->pretty = is_pretty;
+
+      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_PRETTY]);
+    }
+}
+
+/**
+ * json_generator_get_pretty:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves the value set using json_generator_set_pretty().
+ *
+ * Return value: %TRUE if the generated JSON should be pretty-printed, and
+ *   %FALSE otherwise
+ *
+ * Since: 0.14
+ */
+gboolean
+json_generator_get_pretty (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+
+  return generator->priv->pretty;
+}
+
+/**
+ * json_generator_set_indent:
+ * @generator: a #JsonGenerator
+ * @indent_level: the number of repetitions of the indentation character
+ *   that should be applied when pretty printing
+ *
+ * Sets the number of repetitions for each indentation level.
+ *
+ * Since: 0.14
+ */
+void
+json_generator_set_indent (JsonGenerator *generator,
+                           guint          indent_level)
+{
+  JsonGeneratorPrivate *priv;
+
+  g_return_if_fail (JSON_IS_GENERATOR (generator));
+
+  priv = generator->priv;
+
+  if (priv->indent != indent_level)
+    {
+      priv->indent = indent_level;
+
+      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_INDENT]);
+    }
+}
+
+/**
+ * json_generator_get_indent:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves the value set using json_generator_set_indent().
+ *
+ * Return value: the number of repetitions per indentation level
+ *
+ * Since: 0.14
+ */
+guint
+json_generator_get_indent (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+
+  return generator->priv->indent;
+}
+
+/**
+ * json_generator_set_indent_char:
+ * @generator: a #JsonGenerator
+ * @indent_char: a Unicode character to be used when indenting
+ *
+ * Sets the character to be used when indenting
+ *
+ * Since: 0.14
+ */
+void
+json_generator_set_indent_char (JsonGenerator *generator,
+                                gunichar       indent_char)
+{
+  JsonGeneratorPrivate *priv;
+
+  g_return_if_fail (JSON_IS_GENERATOR (generator));
+
+  priv = generator->priv;
+
+  if (priv->indent_char != indent_char)
+    {
+      priv->indent_char = indent_char;
+
+      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_INDENT_CHAR]);
+    }
+}
+
+/**
+ * json_generator_get_indent_char:
+ * @generator: a #JsonGenerator
+ *
+ * Retrieves the value set using json_generator_set_indent_char().
+ *
+ * Return value: the character to be used when indenting
+ *
+ * Since: 0.14
+ */
+gunichar
+json_generator_get_indent_char (JsonGenerator *generator)
+{
+  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
+
+  return generator->priv->indent_char;
 }