Coverage Report

Created: 2026-01-09 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib-json/json-tree.c
Line
Count
Source
1
/* Copyright (c) 2017-2023 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
#include "llist.h"
5
#include "array.h"
6
#include "istream.h"
7
8
#include "json-tree.h"
9
10
struct json_tree_node_list {
11
  struct json_tree_node *head, *tail;
12
  unsigned int count;
13
};
14
15
struct json_tree_node {
16
  struct json_tree *tree;
17
  struct json_tree_node *parent, *prev, *next;
18
19
  struct json_node node;
20
};
21
22
struct json_tree {
23
  struct json_tree_node node;
24
25
  pool_t pool;
26
  int refcount;
27
28
  ARRAY_TYPE(json_tree) subtrees;
29
  ARRAY(struct istream *) istreams;
30
};
31
32
/*
33
 * Tree object
34
 */
35
36
struct json_tree *json_tree_create_pool(pool_t pool)
37
3.26k
{
38
3.26k
  struct json_tree *jtree;
39
40
3.26k
  pool_ref(pool);
41
42
3.26k
  jtree = p_new(pool, struct json_tree, 1);
43
3.26k
  jtree->refcount = 1;
44
3.26k
  jtree->pool = pool;
45
46
3.26k
  jtree->node.tree = jtree;
47
3.26k
  jtree->node.node.type = JSON_TYPE_NONE;
48
3.26k
  jtree->node.node.value.content_type = JSON_CONTENT_TYPE_NONE;
49
50
3.26k
  return jtree;
51
3.26k
}
52
53
struct json_tree *json_tree_create(void)
54
3.26k
{
55
3.26k
  struct json_tree *jtree;
56
3.26k
  pool_t pool;
57
58
3.26k
  pool = pool_alloconly_create("json tree", 1024);
59
3.26k
  jtree = json_tree_create_pool(pool);
60
3.26k
  pool_unref(&pool);
61
62
3.26k
  return jtree;
63
3.26k
}
64
65
void json_tree_ref(struct json_tree *jtree)
66
0
{
67
0
  i_assert(jtree->refcount > 0);
68
0
  jtree->refcount++;
69
0
}
70
71
void json_tree_unref(struct json_tree **_jtree)
72
3.26k
{
73
3.26k
  struct json_tree *jtree = *_jtree;
74
75
3.26k
  if (jtree == NULL)
76
0
    return;
77
3.26k
  *_jtree = NULL;
78
79
3.26k
  i_assert(jtree->refcount > 0);
80
3.26k
  if (--jtree->refcount > 0)
81
0
    return;
82
83
3.26k
  if (array_is_created(&jtree->subtrees)) {
84
0
    struct json_tree **subtree_idx;
85
0
    array_foreach_modifiable(&jtree->subtrees, subtree_idx)
86
0
      json_tree_unref(subtree_idx);
87
0
    array_free(&jtree->subtrees);
88
0
  }
89
3.26k
  if (array_is_created(&jtree->istreams)) {
90
0
    struct istream **istream_idx;
91
0
    array_foreach_modifiable(&jtree->istreams, istream_idx)
92
0
      i_stream_unref(istream_idx);
93
0
    array_free(&jtree->istreams);
94
0
  }
95
3.26k
  pool_unref(&jtree->pool);
96
3.26k
}
97
98
bool json_tree_is_object(const struct json_tree *jtree)
99
0
{
100
0
  return json_node_is_object(&jtree->node.node);
101
0
}
102
103
bool json_tree_is_array(const struct json_tree *jtree)
104
0
{
105
0
  return json_node_is_array(&jtree->node.node);
106
0
}
107
108
bool json_tree_is_string(const struct json_tree *jtree)
109
0
{
110
0
  return json_node_is_string(&jtree->node.node);
111
0
}
112
113
bool json_tree_is_number(const struct json_tree *jtree)
114
0
{
115
0
  return json_node_is_number(&jtree->node.node);
116
0
}
117
118
bool json_tree_is_true(const struct json_tree *jtree)
119
0
{
120
0
  return json_node_is_true(&jtree->node.node);
121
0
}
122
123
bool json_tree_is_false(const struct json_tree *jtree)
124
0
{
125
0
  return json_node_is_false(&jtree->node.node);
126
0
}
127
128
bool json_tree_is_boolean(const struct json_tree *jtree)
129
0
{
130
0
  return json_node_is_boolean(&jtree->node.node);
131
0
}
132
133
bool json_tree_is_null(const struct json_tree *jtree)
134
0
{
135
0
  return json_node_is_null(&jtree->node.node);
136
0
}
137
138
/*
139
 * Tree node
140
 */
141
142
static inline struct json_tree_node_list *
143
json_tree_node_create_list(struct json_tree_node *jtnode)
144
547k
{
145
547k
  i_assert(jtnode->node.type == JSON_TYPE_OBJECT ||
146
547k
    jtnode->node.type == JSON_TYPE_ARRAY);
147
547k
  i_assert(jtnode->node.value.content_type == JSON_CONTENT_TYPE_LIST);
148
547k
  if (jtnode->node.value.content.list == NULL) {
149
382k
    jtnode->node.value.content.list =
150
382k
      p_new(jtnode->tree->pool,
151
382k
            struct json_tree_node_list, 1);
152
382k
  }
153
547k
  return jtnode->node.value.content.list;
154
547k
}
155
156
struct json_tree_node *json_tree_get_root(struct json_tree *jtree)
157
3.26k
{
158
3.26k
  return &jtree->node;
159
3.26k
}
160
161
const struct json_tree_node *
162
json_tree_get_root_const(const struct json_tree *jtree)
163
0
{
164
0
  return &jtree->node;
165
0
}
166
167
static struct json_tree_node *
168
json_tree_node_create(struct json_tree_node *parent, const char *name)
169
549k
{
170
549k
  struct json_tree *jtree = parent->tree;
171
549k
  struct json_tree_node_list *list;
172
549k
  struct json_tree_node *jtnode;
173
174
549k
  i_assert(name != NULL || parent->node.type != JSON_TYPE_OBJECT);
175
176
549k
  if (parent == &jtree->node && parent->node.type == JSON_TYPE_NONE) {
177
    /* We're substituting the root (name is ignored) */
178
1.73k
    i_assert(parent->node.value.content_type ==
179
1.73k
       JSON_CONTENT_TYPE_NONE);
180
1.73k
    jtnode = &jtree->node;
181
1.73k
    i_zero(jtnode);
182
547k
  } else {
183
    /* We're creating a new node */
184
547k
    jtnode = p_new(jtree->pool, struct json_tree_node, 1);
185
547k
    jtnode->node.name = (name == NULL ?
186
506k
             NULL : p_strdup(jtree->pool, name));
187
547k
    jtnode->parent = parent;
188
547k
    list = json_tree_node_create_list(parent);
189
547k
    DLLIST2_APPEND(&list->head, &list->tail, jtnode);
190
547k
    list->count++;
191
547k
  }
192
193
549k
  jtnode->tree = jtree;
194
549k
  return jtnode;
195
549k
}
196
197
/* node */
198
199
struct json_tree_node *
200
json_tree_node_add(struct json_tree_node *parent,
201
       const struct json_node *jnode)
202
0
{
203
0
  return json_tree_node_add_value(parent, jnode->name, jnode->type,
204
0
          &jnode->value);
205
0
}
206
207
/* object, array */
208
209
struct json_tree_node *
210
json_tree_node_add_object(struct json_tree_node *parent, const char *name)
211
2.11k
{
212
2.11k
  struct json_tree_node *jtnode;
213
214
2.11k
  jtnode = json_tree_node_create(parent, name);
215
2.11k
  jtnode->node.type = JSON_TYPE_OBJECT;
216
2.11k
  jtnode->node.value.content_type = JSON_CONTENT_TYPE_LIST;
217
2.11k
  jtnode->node.value.content.list = NULL;
218
219
2.11k
  return jtnode;
220
2.11k
}
221
222
struct json_tree_node *
223
json_tree_node_add_array(struct json_tree_node *parent, const char *name)
224
387k
{
225
387k
  struct json_tree_node *jtnode;
226
227
387k
  jtnode = json_tree_node_create(parent, name);
228
387k
  jtnode->node.type = JSON_TYPE_ARRAY;
229
387k
  jtnode->node.value.content_type = JSON_CONTENT_TYPE_LIST;
230
387k
  jtnode->node.value.content.list = NULL;
231
232
387k
  return jtnode;
233
387k
}
234
235
/* value */
236
237
struct json_tree_node *
238
json_tree_node_add_value(struct json_tree_node *parent, const char *name,
239
       enum json_type type, const struct json_value *jvalue)
240
159k
{
241
159k
  struct json_tree *jtree = parent->tree;
242
159k
  struct json_tree_node *jtnode;
243
159k
  struct json_data *jdata;
244
159k
  unsigned char *data;
245
246
159k
  jtnode = json_tree_node_create(parent, name);
247
159k
  jtnode->node.type = type;
248
159k
  jtnode->node.value.content_type = jvalue->content_type;
249
159k
  switch (jvalue->content_type) {
250
1.48k
  case JSON_CONTENT_TYPE_NONE:
251
1.48k
    break;
252
0
  case JSON_CONTENT_TYPE_LIST:
253
    /* Equivalent to calling json_tree_node_add_array() or
254
       json_tree_node_add_object(); doesn't copy list */
255
0
    jtnode->node.value.content.list = NULL;
256
0
    break;
257
3.93k
  case JSON_CONTENT_TYPE_STRING:
258
3.93k
    jtnode->node.value.content.str =
259
3.93k
      p_strdup(jtree->pool, jvalue->content.str);
260
3.93k
    break;
261
0
  case JSON_CONTENT_TYPE_DATA:
262
0
    jdata = p_new(jtree->pool, struct json_data, 1);
263
0
    *jdata = *jvalue->content.data;
264
0
    data = p_malloc(jtree->pool, jdata->size + 1);
265
0
    jdata->data = memcpy(data, jdata->data, jdata->size);
266
0
    jtnode->node.value.content.data = jdata;
267
0
    break;
268
0
  case JSON_CONTENT_TYPE_STREAM:
269
0
    if (!array_is_created(&jtree->istreams))
270
0
      i_array_init(&jtree->istreams, 4);
271
0
    array_append(&jtree->istreams, &jvalue->content.stream, 1);
272
0
    jtnode->node.value.content.stream = jvalue->content.stream;
273
0
    i_stream_ref(jvalue->content.stream);
274
0
    break;
275
154k
  case JSON_CONTENT_TYPE_INTEGER:
276
154k
    jtnode->node.value.content.intnum = jvalue->content.intnum;
277
154k
    break;
278
0
  case JSON_CONTENT_TYPE_TREE:
279
0
    i_assert(jvalue->content.tree != jtree);
280
0
    if (!array_is_created(&jtree->subtrees))
281
0
      i_array_init(&jtree->subtrees, 4);
282
0
    array_append(&jtree->subtrees, &jvalue->content.tree, 1);
283
0
    jtnode->node.value.content.tree = jvalue->content.tree;
284
0
    json_tree_ref(jvalue->content.tree);
285
0
    break;
286
159k
  }
287
288
159k
  return jtnode;
289
159k
}
290
291
/* string */
292
293
struct json_tree_node *
294
json_tree_node_add_string(struct json_tree_node *parent, const char *name,
295
        const char *str)
296
0
{
297
0
  struct json_value jvalue;
298
299
0
  i_zero(&jvalue);
300
0
  jvalue.content_type = JSON_CONTENT_TYPE_STRING;
301
0
  jvalue.content.str = str;
302
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_STRING,
303
0
          &jvalue);
304
0
}
305
306
struct json_tree_node *
307
json_tree_node_add_data(struct json_tree_node *parent, const char *name,
308
      const unsigned char *data, size_t size)
309
0
{
310
0
  struct json_value jvalue;
311
0
  struct json_data jdata;
312
313
0
  i_zero(&data);
314
0
  jdata.data = data;
315
0
  jdata.size = size;
316
317
0
  i_zero(&jvalue);
318
0
  jvalue.content_type = JSON_CONTENT_TYPE_DATA;
319
0
  jvalue.content.data = &jdata;
320
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_STRING,
321
0
          &jvalue);
322
0
}
323
324
struct json_tree_node *
325
json_tree_node_add_string_stream(struct json_tree_node *parent,
326
         const char *name, struct istream *input)
327
0
{
328
0
  struct json_value jvalue;
329
330
0
  i_zero(&jvalue);
331
0
  jvalue.content_type = JSON_CONTENT_TYPE_STREAM;
332
0
  jvalue.content.stream = input;
333
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_STRING,
334
0
          &jvalue);
335
0
}
336
337
/* number */
338
339
struct json_tree_node *
340
json_tree_node_add_number_int(struct json_tree_node *parent, const char *name,
341
            uintmax_t num)
342
0
{
343
0
  struct json_value jvalue;
344
345
0
  i_zero(&jvalue);
346
0
  jvalue.content_type = JSON_CONTENT_TYPE_INTEGER;
347
0
  jvalue.content.intnum = num;
348
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_NUMBER,
349
0
          &jvalue);
350
0
}
351
352
struct json_tree_node *
353
json_tree_node_add_number_str(struct json_tree_node *parent, const char *name,
354
            const char *num)
355
0
{
356
0
  struct json_value jvalue;
357
358
0
  i_zero(&jvalue);
359
0
  jvalue.content_type = JSON_CONTENT_TYPE_STRING;
360
0
  jvalue.content.str = num;
361
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_NUMBER,
362
0
          &jvalue);
363
0
}
364
365
/* false, true */
366
367
struct json_tree_node *
368
json_tree_node_add_false(struct json_tree_node *parent, const char *name)
369
0
{
370
0
  struct json_value jvalue;
371
372
0
  i_zero(&jvalue);
373
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_FALSE,
374
0
          &jvalue);
375
0
}
376
377
struct json_tree_node *
378
json_tree_node_add_true(struct json_tree_node *parent, const char *name)
379
0
{
380
0
  struct json_value jvalue;
381
382
0
  i_zero(&jvalue);
383
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_TRUE,
384
0
          &jvalue);
385
0
}
386
387
struct json_tree_node *
388
json_tree_node_add_boolean(struct json_tree_node *parent, const char *name,
389
         bool val)
390
0
{
391
0
  struct json_value jvalue;
392
393
0
  i_zero(&jvalue);
394
0
  return json_tree_node_add_value(
395
0
    parent, name, (val ? JSON_TYPE_TRUE : JSON_TYPE_FALSE),
396
0
    &jvalue);
397
0
}
398
399
/* null */
400
401
struct json_tree_node *
402
json_tree_node_add_null(struct json_tree_node *parent, const char *name)
403
0
{
404
0
  struct json_value jvalue;
405
406
0
  i_zero(&jvalue);
407
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_NULL,
408
0
          &jvalue);
409
0
}
410
411
/* JSON-text */
412
413
struct json_tree_node *
414
json_tree_node_add_text(struct json_tree_node *parent, const char *name,
415
      const char *literal)
416
0
{
417
0
  struct json_value jvalue;
418
419
0
  i_zero(&jvalue);
420
0
  jvalue.content_type = JSON_CONTENT_TYPE_STRING;
421
0
  jvalue.content.str = literal;
422
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_TEXT, &jvalue);
423
0
}
424
425
struct json_tree_node *
426
json_tree_node_add_text_data(struct json_tree_node *parent, const char *name,
427
           const unsigned char *data, size_t size)
428
0
{
429
0
  struct json_value jvalue;
430
0
  struct json_data jdata;
431
432
0
  i_zero(&jdata);
433
0
  jdata.data = data;
434
0
  jdata.size = size;
435
436
0
  i_zero(&jvalue);
437
0
  jvalue.content_type = JSON_CONTENT_TYPE_DATA;
438
0
  jvalue.content.data = &jdata;
439
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_TEXT, &jvalue);
440
0
}
441
442
struct json_tree_node *
443
json_tree_node_add_subtree(struct json_tree_node *parent, const char *name,
444
         struct json_tree *tree)
445
0
{
446
0
  struct json_value jvalue;
447
448
0
  i_zero(&jvalue);
449
0
  jvalue.content_type = JSON_CONTENT_TYPE_TREE;
450
0
  jvalue.content.tree = tree;
451
0
  return json_tree_node_add_value(parent, name, JSON_TYPE_TEXT, &jvalue);
452
0
}
453
454
/*
455
 * Tree inspection
456
 */
457
458
enum json_type json_tree_node_get_type(const struct json_tree_node *jtnode)
459
0
{
460
0
  return jtnode->node.type;
461
0
}
462
463
const char *json_tree_node_get_name(const struct json_tree_node *jtnode)
464
0
{
465
0
  return jtnode->node.name;
466
0
}
467
468
struct json_tree *
469
json_tree_node_get_tree(struct json_tree_node *jtnode)
470
0
{
471
0
  return jtnode->tree;
472
0
}
473
474
const struct json_tree *
475
json_tree_node_get_tree_const(const struct json_tree_node *jtnode)
476
0
{
477
0
  return jtnode->tree;
478
0
}
479
480
bool json_tree_node_is_root(const struct json_tree_node *jtnode)
481
0
{
482
0
  return (json_tree_get_root(jtnode->tree) == jtnode);
483
0
}
484
485
bool json_tree_node_is_object(const struct json_tree_node *jtnode)
486
0
{
487
0
  return json_node_is_object(&jtnode->node);
488
0
}
489
490
bool json_tree_node_is_array(const struct json_tree_node *jtnode)
491
0
{
492
0
  return json_node_is_array(&jtnode->node);
493
0
}
494
495
bool json_tree_node_is_string(const struct json_tree_node *jtnode)
496
0
{
497
0
  return json_node_is_string(&jtnode->node);
498
0
}
499
500
bool json_tree_node_is_number(const struct json_tree_node *jtnode)
501
0
{
502
0
  return json_node_is_number(&jtnode->node);
503
0
}
504
505
bool json_tree_node_is_true(const struct json_tree_node *jtnode)
506
0
{
507
0
  return json_node_is_true(&jtnode->node);
508
0
}
509
510
bool json_tree_node_is_false(const struct json_tree_node *jtnode)
511
0
{
512
0
  return json_node_is_false(&jtnode->node);
513
0
}
514
515
bool json_tree_node_is_boolean(const struct json_tree_node *jtnode)
516
0
{
517
0
  return json_node_is_boolean(&jtnode->node);
518
0
}
519
520
bool json_tree_node_is_null(const struct json_tree_node *jtnode)
521
0
{
522
0
  return json_node_is_null(&jtnode->node);
523
0
}
524
525
const struct json_node *
526
json_tree_node_get(const struct json_tree_node *jtnode)
527
0
{
528
0
  return &jtnode->node;
529
0
}
530
531
struct json_tree_node *
532
json_tree_node_get_next(const struct json_tree_node *jtnode)
533
0
{
534
0
  return jtnode->next;
535
0
}
536
537
struct json_tree_node *
538
json_tree_node_get_parent(const struct json_tree_node *jtnode)
539
0
{
540
0
  return jtnode->parent;
541
0
}
542
543
struct json_tree_node *
544
json_tree_node_get_child(const struct json_tree_node *jtnode)
545
0
{
546
0
  i_assert(jtnode->node.value.content_type == JSON_CONTENT_TYPE_LIST);
547
0
  if (jtnode->node.value.content.list == NULL)
548
0
    return NULL;
549
0
  return jtnode->node.value.content.list->head;
550
0
}
551
552
unsigned int
553
json_tree_node_get_child_count(const struct json_tree_node *jtnode)
554
0
{
555
0
  i_assert(jtnode->node.value.content_type == JSON_CONTENT_TYPE_LIST);
556
0
  if (jtnode->node.value.content.list == NULL)
557
0
    return 0;
558
0
  return jtnode->node.value.content.list->count;
559
0
}
560
561
struct json_tree_node *
562
json_tree_node_get_member(const struct json_tree_node *jtnode,
563
        const char *name)
564
0
{
565
0
  struct json_tree_node *child;
566
567
0
  i_assert(json_node_is_object(&jtnode->node));
568
0
  i_assert(jtnode->node.value.content_type == JSON_CONTENT_TYPE_LIST);
569
570
0
  if (jtnode->node.value.content.list == NULL)
571
0
    return NULL;
572
573
0
  child = jtnode->node.value.content.list->head;
574
0
  while (child != NULL) {
575
0
    if (strcmp(child->node.name, name) == 0)
576
0
      return child;
577
0
    child = child->next;
578
0
  }
579
0
  return NULL;
580
0
}
581
582
struct json_tree_node *
583
json_tree_node_get_child_with(const struct json_tree_node *jtnode,
584
            const char *key, const char *value)
585
0
{
586
0
  struct json_tree_node *child;
587
588
0
  i_assert(jtnode->node.value.content_type == JSON_CONTENT_TYPE_LIST);
589
0
  if (jtnode->node.value.content.list == NULL)
590
0
    return NULL;
591
592
0
  child = jtnode->node.value.content.list->head;
593
0
  while (child != NULL) {
594
0
    struct json_tree_node *member;
595
596
0
    if (!json_node_is_object(&child->node))
597
0
      continue;
598
0
    member = json_tree_node_get_member(child, key);
599
0
    if (member == NULL)
600
0
      continue;
601
0
    if (!json_tree_node_is_string(member))
602
0
      continue;
603
0
    if (strcmp(json_tree_node_get_str(member), value) == 0)
604
0
      break;
605
606
0
    child = child->next;
607
0
  }
608
609
0
  return child;
610
0
}
611
612
/*
613
 * Walker
614
 */
615
616
struct json_tree_walker {
617
  const struct json_tree_node *root, *node;
618
  ARRAY_TYPE(json_tree_node_const) sub_nodes;
619
  unsigned int node_level;
620
621
  bool node_is_end:1;
622
};
623
624
struct json_tree_walker *
625
json_tree_walker_create_from_node(const struct json_tree_node *tree_node)
626
0
{
627
0
  struct json_tree_walker *twalker;
628
629
0
  i_assert(tree_node != NULL);
630
631
0
  twalker = i_new(struct json_tree_walker, 1);
632
0
  twalker->root = tree_node;
633
634
0
  return twalker;
635
0
}
636
637
struct json_tree_walker *
638
json_tree_walker_create(const struct json_tree *tree)
639
0
{
640
0
  i_assert(tree != NULL);
641
0
  return json_tree_walker_create_from_node(
642
0
    json_tree_get_root_const(tree));
643
0
}
644
645
void json_tree_walker_free(struct json_tree_walker **_twalker)
646
0
{
647
0
  struct json_tree_walker *twalker = *_twalker;
648
649
0
  if (twalker == NULL)
650
0
    return;
651
0
  *_twalker = NULL;
652
653
0
  array_free(&twalker->sub_nodes);
654
0
  i_free(twalker);
655
0
}
656
657
static const struct json_tree_node *
658
json_tree_walk_next(struct json_tree_walker *twalker, bool *is_end_r)
659
0
{
660
0
  const struct json_tree_node *tnode = twalker->node, *tnode_next;
661
662
0
  *is_end_r = FALSE;
663
664
0
  if (tnode == NULL) {
665
0
    i_assert(twalker->node_level == 0);
666
0
    twalker->node_level++;
667
0
    return twalker->root;
668
0
  }
669
670
0
  bool tnode_is_end = twalker->node_is_end;
671
0
  const struct json_node *node = &tnode->node;
672
673
0
  if (!json_node_is_singular(node) && !tnode_is_end) {
674
0
    tnode_next = json_tree_node_get_child(tnode);
675
0
    if (tnode_next != NULL) {
676
0
      twalker->node_level++;
677
0
      return tnode_next;
678
0
    }
679
0
    *is_end_r = TRUE;
680
0
    return tnode;
681
0
  }
682
683
0
  tnode_next = json_tree_node_get_next(tnode);
684
0
  if (tnode_next != NULL || twalker->node_level == 0)
685
0
    return tnode_next;
686
687
0
  twalker->node_level--;
688
0
  *is_end_r = TRUE;
689
0
  return json_tree_node_get_parent(tnode);
690
0
}
691
692
bool json_tree_walk(struct json_tree_walker *twalker, struct json_node *node_r)
693
0
{
694
0
  const struct json_tree_node *tnode_next;
695
0
  bool tnode_next_is_end;
696
697
0
  tnode_next = json_tree_walk_next(twalker, &tnode_next_is_end);
698
0
  if (tnode_next == NULL) {
699
0
    i_assert(twalker->node_level == 0);
700
0
    i_zero(node_r);
701
0
    twalker->node = twalker->root = NULL;
702
0
    twalker->node_is_end = TRUE;
703
0
    return FALSE;
704
0
  }
705
0
  if (json_tree_node_is_root(tnode_next) && twalker->node_level > 1) {
706
0
    const struct json_tree_node *tnode_sub = tnode_next;
707
708
    /* Returned to root of subtree */
709
0
    i_assert(tnode_next_is_end);
710
0
    i_assert(array_is_created(&twalker->sub_nodes));
711
0
    i_assert(array_count(&twalker->sub_nodes) > 0);
712
0
    tnode_next = *array_back(&twalker->sub_nodes);
713
0
    array_pop_back(&twalker->sub_nodes);
714
715
0
    i_zero(node_r);
716
0
    node_r->name = tnode_next->node.name;
717
0
    node_r->type = tnode_sub->node.type;
718
719
0
    twalker->node = tnode_next;
720
0
    twalker->node_is_end = TRUE;
721
0
    return TRUE;
722
0
  }
723
724
0
  const struct json_node *node_next = &tnode_next->node;
725
726
0
  if (tnode_next_is_end) {
727
0
    i_zero(node_r);
728
0
    node_r->name = node_next->name;
729
0
    node_r->type = node_next->type;
730
0
  } else if (node_next->type == JSON_TYPE_TEXT &&
731
0
       node_next->value.content_type == JSON_CONTENT_TYPE_TREE) {
732
0
    struct json_tree *tree = node_next->value.content.tree;
733
0
    const struct json_tree_node *tnode_sub;
734
735
    /* Descend into subtree */
736
0
    if (!array_is_created(&twalker->sub_nodes))
737
0
      i_array_init(&twalker->sub_nodes, 4);
738
0
    array_push_back(&twalker->sub_nodes, &tnode_next);
739
0
    tnode_sub = json_tree_get_root(tree);
740
0
    i_assert(tnode_sub != NULL);
741
0
    i_assert(tnode_sub->node.type != JSON_TYPE_NONE);
742
0
    *node_r = tnode_sub->node;
743
0
    node_r->name = node_next->name;
744
0
    tnode_next = tnode_sub;
745
0
  } else {
746
0
    *node_r = tnode_next->node;
747
0
  }
748
749
0
  twalker->node = tnode_next;
750
0
  twalker->node_is_end = tnode_next_is_end;
751
0
  return TRUE;
752
0
}