Coverage Report

Created: 2025-07-12 06:33

/src/json-glib/json-glib/json-generator.c
Line
Count
Source (jump to first uncovered line)
1
/* json-generator.c - JSON streams generator
2
 *
3
 * This file is part of JSON-GLib
4
 * Copyright (C) 2007  OpenedHand Ltd.
5
 * Copyright (C) 2009  Intel Corp.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author:
21
 *   Emmanuele Bassi  <ebassi@linux.intel.com>
22
 */
23
24
/**
25
 * JsonGenerator: 
26
 *
27
 * `JsonGenerator` provides an object for generating a JSON data stream
28
 * from a tree of [struct@Json.Node] instances, and put it into a buffer
29
 * or a file.
30
 */
31
32
#include "config.h"
33
34
#include <stdlib.h>
35
#include <string.h>
36
37
#include "json-types-private.h"
38
39
#include "json-generator.h"
40
41
struct _JsonGeneratorPrivate
42
{
43
  JsonNode *root;
44
45
  guint indent;
46
  gunichar indent_char;
47
48
  guint pretty : 1;
49
};
50
51
enum
52
{
53
  PROP_0,
54
55
  PROP_PRETTY,
56
  PROP_INDENT,
57
  PROP_ROOT,
58
  PROP_INDENT_CHAR,
59
60
  PROP_LAST
61
};
62
63
static void   dump_value  (GString       *buffer,
64
                           JsonNode      *node);
65
static void   dump_array  (JsonGenerator *generator,
66
                           GString       *buffer,
67
                           gint           level,
68
                           JsonArray     *array);
69
static void   dump_object (JsonGenerator *generator,
70
                           GString       *buffer,
71
                           gint           level,
72
                           JsonObject    *object);
73
74
static GParamSpec *generator_props[PROP_LAST] = { NULL, };
75
76
G_DEFINE_TYPE_WITH_PRIVATE (JsonGenerator, json_generator, G_TYPE_OBJECT)
77
78
static void
79
json_strescape (GString     *output,
80
                const gchar *str)
81
0
{
82
0
  const gchar *p;
83
0
  const gchar *end;
84
0
  gsize len;
85
86
0
  len = strlen (str);
87
0
  end = str + len;
88
89
0
  for (p = str; p < end; p++)
90
0
    {
91
0
      if (*p == '\\' || *p == '"')
92
0
        {
93
0
          g_string_append_c (output, '\\');
94
0
          g_string_append_c (output, *p);
95
0
        }
96
0
      else if ((*p > 0 && *p < 0x1f) || *p == 0x7f)
97
0
        {
98
0
          switch (*p)
99
0
            {
100
0
            case '\b':
101
0
              g_string_append (output, "\\b");
102
0
              break;
103
0
            case '\f':
104
0
              g_string_append (output, "\\f");
105
0
              break;
106
0
            case '\n':
107
0
              g_string_append (output, "\\n");
108
0
              break;
109
0
            case '\r':
110
0
              g_string_append (output, "\\r");
111
0
              break;
112
0
            case '\t':
113
0
              g_string_append (output, "\\t");
114
0
              break;
115
0
            default:
116
0
              g_string_append_printf (output, "\\u00%02x", (guint)*p);
117
0
              break;
118
0
            }
119
0
        }
120
0
      else
121
0
        {
122
0
          g_string_append_c (output, *p);
123
0
        }
124
0
    }
125
0
}
126
127
static void
128
json_generator_finalize (GObject *gobject)
129
0
{
130
0
  JsonGeneratorPrivate *priv;
131
132
0
  priv = json_generator_get_instance_private ((JsonGenerator *) gobject);
133
0
  if (priv->root != NULL)
134
0
    json_node_unref (priv->root);
135
136
0
  G_OBJECT_CLASS (json_generator_parent_class)->finalize (gobject);
137
0
}
138
139
static void
140
json_generator_set_property (GObject      *gobject,
141
                             guint         prop_id,
142
                             const GValue *value,
143
                             GParamSpec   *pspec)
144
0
{
145
0
  JsonGenerator *generator = JSON_GENERATOR (gobject);
146
147
0
  switch (prop_id)
148
0
    {
149
0
    case PROP_PRETTY:
150
0
      json_generator_set_pretty (generator, g_value_get_boolean (value));
151
0
      break;
152
153
0
    case PROP_INDENT:
154
0
      json_generator_set_indent (generator, g_value_get_uint (value));
155
0
      break;
156
157
0
    case PROP_INDENT_CHAR:
158
0
      json_generator_set_indent_char (generator, g_value_get_uint (value));
159
0
      break;
160
161
0
    case PROP_ROOT:
162
0
      json_generator_set_root (generator, g_value_get_boxed (value));
163
0
      break;
164
165
0
    default:
166
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
167
0
      break;
168
0
    }
169
0
}
170
171
static void
172
json_generator_get_property (GObject    *gobject,
173
                             guint       prop_id,
174
                             GValue     *value,
175
                             GParamSpec *pspec)
176
0
{
177
0
  JsonGeneratorPrivate *priv = JSON_GENERATOR (gobject)->priv;
178
179
0
  switch (prop_id)
180
0
    {
181
0
    case PROP_PRETTY:
182
0
      g_value_set_boolean (value, priv->pretty);
183
0
      break;
184
0
    case PROP_INDENT:
185
0
      g_value_set_uint (value, priv->indent);
186
0
      break;
187
0
    case PROP_INDENT_CHAR:
188
0
      g_value_set_uint (value, priv->indent_char);
189
0
      break;
190
0
    case PROP_ROOT:
191
0
      g_value_set_boxed (value, priv->root);
192
0
      break;
193
0
    default:
194
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
195
0
      break;
196
0
    }
197
0
}
198
199
static void
200
json_generator_class_init (JsonGeneratorClass *klass)
201
0
{
202
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
203
204
  /**
205
   * JsonGenerator:pretty: (attributes org.gtk.Property.get=json_generator_get_pretty org.gtk.Property.set=json_generator_set_pretty)
206
   *
207
   * Whether the output should be "pretty-printed", with indentation and
208
   * newlines.
209
   *
210
   * The indentation level can be controlled by using the
211
   * [property@Json.Generator:indent] property.
212
   */
213
0
  generator_props[PROP_PRETTY] =
214
0
    g_param_spec_boolean ("pretty",
215
0
                          "Pretty",
216
0
                          "Pretty-print the output",
217
0
                          FALSE,
218
0
                          G_PARAM_READWRITE);
219
220
  /**
221
   * JsonGenerator:indent: (attributes org.gtk.Property.get=json_generator_get_indent org.gtk.Property.set=json_generator_set_indent)
222
   *
223
   * Number of spaces to be used to indent when pretty printing.
224
   */
225
0
  generator_props[PROP_INDENT] =
226
0
    g_param_spec_uint ("indent",
227
0
                       "Indent",
228
0
                       "Number of indentation spaces",
229
0
                       0, G_MAXUINT,
230
0
                       2,
231
0
                       G_PARAM_READWRITE);
232
233
  /**
234
   * JsonGenerator:root: (attributes org.gtk.Property.get=json_generator_get_root org.gtk.Property.set=json_generator_set_root)
235
   *
236
   * The root node to be used when constructing a JSON data
237
   * stream.
238
   *
239
   * Since: 0.4
240
   */
241
0
  generator_props[PROP_ROOT] =
242
0
    g_param_spec_boxed ("root",
243
0
                        "Root",
244
0
                        "Root of the JSON data tree",
245
0
                        JSON_TYPE_NODE,
246
0
                        G_PARAM_READWRITE);
247
248
  /**
249
   * JsonGenerator:indent-char: (attributes org.gtk.Property.get=json_generator_get_indent_char org.gtk.Property.set=json_generator_set_indent_char)
250
   *
251
   * The character that should be used when indenting in pretty print.
252
   *
253
   * Since: 0.6
254
   */
255
0
  generator_props[PROP_INDENT_CHAR] =
256
0
    g_param_spec_unichar ("indent-char",
257
0
                          "Indent Char",
258
0
                          "Character that should be used when indenting",
259
0
                          ' ',
260
0
                          G_PARAM_READWRITE);
261
262
0
  gobject_class->set_property = json_generator_set_property;
263
0
  gobject_class->get_property = json_generator_get_property;
264
0
  gobject_class->finalize = json_generator_finalize;
265
0
  g_object_class_install_properties (gobject_class, PROP_LAST, generator_props);
266
0
}
267
268
static void
269
json_generator_init (JsonGenerator *generator)
270
0
{
271
0
  JsonGeneratorPrivate *priv = json_generator_get_instance_private (generator);
272
273
0
  generator->priv = priv;
274
275
0
  priv->pretty = FALSE;
276
0
  priv->indent = 2;
277
0
  priv->indent_char = ' ';
278
0
}
279
280
static void
281
dump_node (JsonGenerator *generator,
282
           GString       *buffer,
283
           gint           level,
284
           const gchar   *name,
285
           JsonNode      *node)
286
0
{
287
0
  JsonGeneratorPrivate *priv = generator->priv;
288
0
  gboolean pretty = priv->pretty;
289
0
  guint indent = priv->indent;
290
291
0
  if (pretty)
292
0
    {
293
0
      guint i;
294
295
0
      for (i = 0; i < (level * indent); i++)
296
0
        g_string_append_c (buffer, priv->indent_char);
297
0
    }
298
299
0
  if (name)
300
0
    {
301
0
      g_string_append_c (buffer, '"');
302
0
      json_strescape (buffer, name);
303
0
      g_string_append_c (buffer, '"');
304
305
0
      if (pretty)
306
0
        g_string_append (buffer, " : ");
307
0
      else
308
0
        g_string_append_c (buffer, ':');
309
0
    }
310
311
0
  switch (JSON_NODE_TYPE (node))
312
0
    {
313
0
    case JSON_NODE_NULL:
314
0
      g_string_append (buffer, "null");
315
0
      break;
316
317
0
    case JSON_NODE_VALUE:
318
0
      dump_value (buffer, node);
319
0
      break;
320
321
0
    case JSON_NODE_ARRAY:
322
0
      dump_array (generator, buffer, level,
323
0
                  json_node_get_array (node));
324
0
      break;
325
326
0
    case JSON_NODE_OBJECT:
327
0
      dump_object (generator, buffer, level,
328
0
                   json_node_get_object (node));
329
0
      break;
330
0
    }
331
0
}
332
333
static void
334
dump_value (GString  *buffer,
335
            JsonNode *node)
336
0
{
337
0
  const JsonValue *value;
338
339
0
  value = node->data.value;
340
341
0
  switch (value->type)
342
0
    {
343
0
    case JSON_VALUE_INT:
344
0
      g_string_append_printf (buffer, "%" G_GINT64_FORMAT, json_value_get_int (value));
345
0
      break;
346
347
0
    case JSON_VALUE_STRING:
348
0
      {
349
0
        g_string_append_c (buffer, '"');
350
0
        json_strescape (buffer, json_value_get_string (value));
351
0
        g_string_append_c (buffer, '"');
352
0
      }
353
0
      break;
354
355
0
    case JSON_VALUE_DOUBLE:
356
0
      {
357
0
        gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
358
359
0
        g_string_append (buffer,
360
0
                         g_ascii_dtostr (buf, sizeof (buf),
361
0
                                         json_value_get_double (value)));
362
  /* ensure doubles don't become ints */
363
        /* also make sure not to append .0 that results in invalid exponential notation
364
         * since the numbers should be decimal, a hex 'e' or "E" can not be mistaken
365
         */
366
0
  if (g_strstr_len (buf, G_ASCII_DTOSTR_BUF_SIZE, ".") == NULL &&
367
0
            g_strstr_len (buf, G_ASCII_DTOSTR_BUF_SIZE, "e") == NULL &&
368
0
            g_strstr_len (buf, G_ASCII_DTOSTR_BUF_SIZE, "E") == NULL)
369
0
    {
370
0
      g_string_append (buffer, ".0");
371
0
          }
372
0
      }
373
0
      break;
374
375
0
    case JSON_VALUE_BOOLEAN:
376
0
      g_string_append (buffer, json_value_get_boolean (value) ? "true" : "false");
377
0
      break;
378
379
0
    case JSON_VALUE_NULL:
380
0
      g_string_append (buffer, "null");
381
0
      break;
382
383
0
    default:
384
0
      break;
385
0
    }
386
0
}
387
388
static void
389
dump_array (JsonGenerator *generator,
390
            GString       *buffer,
391
            gint           level,
392
            JsonArray     *array)
393
0
{
394
0
  JsonGeneratorPrivate *priv = generator->priv;
395
0
  guint array_len = json_array_get_length (array);
396
0
  guint i;
397
0
  gboolean pretty = priv->pretty;
398
0
  guint indent = priv->indent;
399
400
0
  g_string_append_c (buffer, '[');
401
402
0
  if (array_len == 0)
403
0
    goto out;
404
405
0
  for (i = 0; i < array_len; i++)
406
0
    {
407
0
      JsonNode *cur = json_array_get_element (array, i);
408
409
0
      if (i == 0 && pretty)
410
0
        g_string_append_c (buffer, '\n');
411
412
0
      dump_node (generator, buffer, level + 1, NULL, cur);
413
414
0
      if ((i + 1) != array_len)
415
0
        g_string_append_c (buffer, ',');
416
417
0
      if (pretty)
418
0
        g_string_append_c (buffer, '\n');
419
0
    }
420
421
0
  if (pretty)
422
0
    {
423
0
      for (i = 0; i < (level * indent); i++)
424
0
        g_string_append_c (buffer, priv->indent_char);
425
0
    }
426
427
0
out:
428
0
  g_string_append_c (buffer, ']');
429
0
}
430
431
static void
432
dump_object (JsonGenerator *generator,
433
             GString       *buffer,
434
             gint           level,
435
             JsonObject    *object)
436
0
{
437
0
  JsonGeneratorPrivate *priv = generator->priv;
438
0
  GQueue *members;
439
0
  GList *l;
440
0
  gboolean pretty = priv->pretty;
441
0
  guint indent = priv->indent;
442
0
  guint i;
443
444
0
  g_string_append_c (buffer, '{');
445
446
0
  members = json_object_get_members_internal (object);
447
448
0
  for (l = members->head; l != NULL; l = l->next)
449
0
    {
450
0
      const gchar *member_name = l->data;
451
0
      JsonNode *cur = json_object_get_member (object, member_name);
452
453
0
      if (l->prev == NULL && pretty)
454
0
        g_string_append_c (buffer, '\n');
455
456
0
      dump_node (generator, buffer, level + 1, member_name, cur);
457
458
0
      if (l->next != NULL)
459
0
        g_string_append_c (buffer, ',');
460
461
0
      if (pretty)
462
0
        g_string_append_c (buffer, '\n');
463
0
    }
464
465
0
  if (pretty)
466
0
    {
467
0
      for (i = 0; i < (level * indent); i++)
468
0
        g_string_append_c (buffer, priv->indent_char);
469
0
    }
470
471
0
  g_string_append_c (buffer, '}');
472
0
}
473
474
/**
475
 * json_generator_new:
476
 * 
477
 * Creates a new `JsonGenerator`.
478
 *
479
 * You can use this object to generate a JSON data stream starting from a
480
 * data object model composed by [struct@Json.Node]s.
481
 *
482
 * Return value: the newly created generator instance
483
 */
484
JsonGenerator *
485
json_generator_new (void)
486
0
{
487
0
  return g_object_new (JSON_TYPE_GENERATOR, NULL);
488
0
}
489
490
/**
491
 * json_generator_to_gstring:
492
 * @generator: a generator
493
 * @string: a string buffer
494
 *
495
 * Generates a JSON data stream and appends it to the string buffer.
496
 *
497
 * Return value: (transfer none): the passed string, updated with
498
 *   the generated JSON data
499
 *
500
 * Since: 1.4
501
 */
502
GString *
503
json_generator_to_gstring (JsonGenerator *generator,
504
                           GString       *string)
505
0
{
506
0
  JsonNode *root;
507
508
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), NULL);
509
0
  g_return_val_if_fail (string != NULL, NULL);
510
511
0
  root = generator->priv->root;
512
0
  if (root != NULL)
513
0
    dump_node (generator, string, 0, NULL, root);
514
515
0
  return string;
516
0
}
517
518
/**
519
 * json_generator_to_data:
520
 * @generator: a generator
521
 * @length: (out) (optional): return location for the length of the returned
522
 *   buffer
523
 *
524
 * Generates a JSON data stream from @generator and returns it as a
525
 * buffer.
526
 *
527
 * Return value: (transfer full): a newly allocated string holding a JSON data stream
528
 */
529
gchar *
530
json_generator_to_data (JsonGenerator *generator,
531
                        gsize         *length)
532
0
{
533
0
  GString *string;
534
535
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), NULL);
536
537
0
  string = g_string_new ("");
538
0
  json_generator_to_gstring (generator, string);
539
540
0
  if (length)
541
0
    *length = string->len;
542
543
0
  return g_string_free (string, FALSE);
544
0
}
545
546
/**
547
 * json_generator_to_file:
548
 * @generator: a generator
549
 * @filename: (type filename): the path to the target file
550
 * @error: return location for a #GError, or %NULL
551
 *
552
 * Creates a JSON data stream and puts it inside `filename`, overwriting
553
 * the file's current contents.
554
 *
555
 * This operation is atomic, in the sense that the data is written to a
556
 * temporary file which is then renamed to the given `filename`.
557
 *
558
 * Return value: %TRUE if saving was successful.
559
 */
560
gboolean
561
json_generator_to_file (JsonGenerator  *generator,
562
                        const gchar    *filename,
563
                        GError        **error)
564
0
{
565
0
  gchar *buffer;
566
0
  gsize len;
567
0
  gboolean retval;
568
569
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
570
0
  g_return_val_if_fail (filename != NULL, FALSE);
571
572
0
  buffer = json_generator_to_data (generator, &len);
573
0
  retval = g_file_set_contents (filename, buffer, len, error);
574
0
  g_free (buffer);
575
576
0
  return retval;
577
0
}
578
579
/**
580
 * json_generator_to_stream:
581
 * @generator: a generator
582
 * @stream: the output stream used to write the JSON data
583
 * @cancellable: (nullable): a `GCancellable`
584
 * @error: return location for a #GError, or %NULL
585
 *
586
 * Outputs JSON data and writes it (synchronously) to the given stream.
587
 *
588
 * Return value: whether the write operation was successful
589
 *
590
 * Since: 0.12
591
 */
592
gboolean
593
json_generator_to_stream (JsonGenerator  *generator,
594
                          GOutputStream  *stream,
595
                          GCancellable   *cancellable,
596
                          GError        **error)
597
0
{
598
0
  gboolean retval;
599
0
  gchar *buffer;
600
0
  gsize len;
601
602
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
603
0
  g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
604
605
0
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
606
0
    return FALSE;
607
608
0
  buffer = json_generator_to_data (generator, &len);
609
0
  retval = g_output_stream_write (stream, buffer, len, cancellable, error);
610
0
  g_free (buffer);
611
612
0
  return retval;
613
0
}
614
615
/**
616
 * json_generator_set_root: (attributes org.gtk.Method.set_property=root)
617
 * @generator: a generator
618
 * @node: the root node
619
 *
620
 * Sets the root of the JSON data stream to be serialized by
621
 * the given generator.
622
 *
623
 * The passed `node` is copied by the generator object, so it can be
624
 * safely freed after calling this function.
625
 */
626
void
627
json_generator_set_root (JsonGenerator *generator,
628
                         JsonNode      *node)
629
0
{
630
0
  g_return_if_fail (JSON_IS_GENERATOR (generator));
631
632
0
  if (generator->priv->root == node)
633
0
    return;
634
635
0
  if (generator->priv->root != NULL)
636
0
    {
637
0
      json_node_unref (generator->priv->root);
638
0
      generator->priv->root = NULL;
639
0
    }
640
641
0
  if (node != NULL)
642
0
    generator->priv->root = json_node_copy (node);
643
644
0
  g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_ROOT]);
645
0
}
646
647
/**
648
 * json_generator_get_root: (attributes org.gtk.Method.get_property=root)
649
 * @generator: a generator
650
 *
651
 * Retrieves a pointer to the root node set using
652
 * [method@Json.Generator.set_root].
653
 *
654
 * Return value: (nullable) (transfer none): the root node
655
 *
656
 * Since: 0.14
657
 */
658
JsonNode *
659
json_generator_get_root (JsonGenerator *generator)
660
0
{
661
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), NULL);
662
663
0
  return generator->priv->root;
664
0
}
665
666
/**
667
 * json_generator_set_pretty: (attributes org.gtk.Method.set_property=pretty)
668
 * @generator: a generator
669
 * @is_pretty: whether the generated string should be pretty printed
670
 *
671
 * Sets whether the generated JSON should be pretty printed.
672
 *
673
 * Pretty printing will use indentation character specified in the
674
 * [property@Json.Generator:indent-char] property and the spacing
675
 * specified in the [property@Json.Generator:indent] property.
676
 *
677
 * Since: 0.14
678
 */
679
void
680
json_generator_set_pretty (JsonGenerator *generator,
681
                           gboolean       is_pretty)
682
0
{
683
0
  JsonGeneratorPrivate *priv;
684
685
0
  g_return_if_fail (JSON_IS_GENERATOR (generator));
686
687
0
  priv = generator->priv;
688
689
0
  is_pretty = !!is_pretty;
690
691
0
  if (priv->pretty != is_pretty)
692
0
    {
693
0
      priv->pretty = is_pretty;
694
695
0
      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_PRETTY]);
696
0
    }
697
0
}
698
699
/**
700
 * json_generator_get_pretty: (attributes org.gtk.Method.get_property=pretty)
701
 * @generator: a generator
702
 *
703
 * Retrieves the value set using [method@Json.Generator.set_pretty].
704
 *
705
 * Return value: `TRUE` if the generated JSON should be pretty-printed, and
706
 *   `FALSE` otherwise
707
 *
708
 * Since: 0.14
709
 */
710
gboolean
711
json_generator_get_pretty (JsonGenerator *generator)
712
0
{
713
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
714
715
0
  return generator->priv->pretty;
716
0
}
717
718
/**
719
 * json_generator_set_indent: (attributes org.gtk.Method.set_property=indent)
720
 * @generator: a generator
721
 * @indent_level: the number of repetitions of the indentation character
722
 *   that should be applied when pretty printing
723
 *
724
 * Sets the number of repetitions for each indentation level.
725
 *
726
 * Since: 0.14
727
 */
728
void
729
json_generator_set_indent (JsonGenerator *generator,
730
                           guint          indent_level)
731
0
{
732
0
  JsonGeneratorPrivate *priv;
733
734
0
  g_return_if_fail (JSON_IS_GENERATOR (generator));
735
736
0
  priv = generator->priv;
737
738
0
  if (priv->indent != indent_level)
739
0
    {
740
0
      priv->indent = indent_level;
741
742
0
      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_INDENT]);
743
0
    }
744
0
}
745
746
/**
747
 * json_generator_get_indent: (attributes org.gtk.Method.get_property=indent)
748
 * @generator: a generator
749
 *
750
 * Retrieves the value set using [method@Json.Generator.set_indent].
751
 *
752
 * Return value: the number of repetitions per indentation level
753
 *
754
 * Since: 0.14
755
 */
756
guint
757
json_generator_get_indent (JsonGenerator *generator)
758
0
{
759
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), 0);
760
761
0
  return generator->priv->indent;
762
0
}
763
764
/**
765
 * json_generator_set_indent_char: (attributes org.gtk.Method.set_property=indent-char)
766
 * @generator: a generator
767
 * @indent_char: a Unicode character to be used when indenting
768
 *
769
 * Sets the character to be used when indenting.
770
 *
771
 * Since: 0.14
772
 */
773
void
774
json_generator_set_indent_char (JsonGenerator *generator,
775
                                gunichar       indent_char)
776
0
{
777
0
  JsonGeneratorPrivate *priv;
778
779
0
  g_return_if_fail (JSON_IS_GENERATOR (generator));
780
781
0
  priv = generator->priv;
782
783
0
  if (priv->indent_char != indent_char)
784
0
    {
785
0
      priv->indent_char = indent_char;
786
787
0
      g_object_notify_by_pspec (G_OBJECT (generator), generator_props[PROP_INDENT_CHAR]);
788
0
    }
789
0
}
790
791
/**
792
 * json_generator_get_indent_char: (attributes org.gtk.Method.get_property=indent-char)
793
 * @generator: a generator
794
 *
795
 * Retrieves the value set using [method@Json.Generator.set_indent_char].
796
 *
797
 * Return value: the character to be used when indenting
798
 *
799
 * Since: 0.14
800
 */
801
gunichar
802
json_generator_get_indent_char (JsonGenerator *generator)
803
0
{
804
0
  g_return_val_if_fail (JSON_IS_GENERATOR (generator), FALSE);
805
806
0
  return generator->priv->indent_char;
807
0
}