Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/rapidyaml/src/c4/yml/tree.cpp
4262 views
1
#include "c4/yml/tree.hpp"
2
#include "c4/yml/detail/parser_dbg.hpp"
3
#include "c4/yml/node.hpp"
4
#include "c4/yml/detail/stack.hpp"
5
6
7
C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4296/*expression is always 'boolean_value'*/)
8
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
9
C4_SUPPRESS_WARNING_GCC("-Wtype-limits")
10
11
namespace c4 {
12
namespace yml {
13
14
15
csubstr normalize_tag(csubstr tag)
16
{
17
YamlTag_e t = to_tag(tag);
18
if(t != TAG_NONE)
19
return from_tag(t);
20
if(tag.begins_with("!<"))
21
tag = tag.sub(1);
22
if(tag.begins_with("<!"))
23
return tag;
24
return tag;
25
}
26
27
csubstr normalize_tag_long(csubstr tag)
28
{
29
YamlTag_e t = to_tag(tag);
30
if(t != TAG_NONE)
31
return from_tag_long(t);
32
if(tag.begins_with("!<"))
33
tag = tag.sub(1);
34
if(tag.begins_with("<!"))
35
return tag;
36
return tag;
37
}
38
39
YamlTag_e to_tag(csubstr tag)
40
{
41
if(tag.begins_with("!<"))
42
tag = tag.sub(1);
43
if(tag.begins_with("!!"))
44
tag = tag.sub(2);
45
else if(tag.begins_with('!'))
46
return TAG_NONE;
47
else if(tag.begins_with("tag:yaml.org,2002:"))
48
{
49
RYML_ASSERT(csubstr("tag:yaml.org,2002:").len == 18);
50
tag = tag.sub(18);
51
}
52
else if(tag.begins_with("<tag:yaml.org,2002:"))
53
{
54
RYML_ASSERT(csubstr("<tag:yaml.org,2002:").len == 19);
55
tag = tag.sub(19);
56
if(!tag.len)
57
return TAG_NONE;
58
tag = tag.offs(0, 1);
59
}
60
61
if(tag == "map")
62
return TAG_MAP;
63
else if(tag == "omap")
64
return TAG_OMAP;
65
else if(tag == "pairs")
66
return TAG_PAIRS;
67
else if(tag == "set")
68
return TAG_SET;
69
else if(tag == "seq")
70
return TAG_SEQ;
71
else if(tag == "binary")
72
return TAG_BINARY;
73
else if(tag == "bool")
74
return TAG_BOOL;
75
else if(tag == "float")
76
return TAG_FLOAT;
77
else if(tag == "int")
78
return TAG_INT;
79
else if(tag == "merge")
80
return TAG_MERGE;
81
else if(tag == "null")
82
return TAG_NULL;
83
else if(tag == "str")
84
return TAG_STR;
85
else if(tag == "timestamp")
86
return TAG_TIMESTAMP;
87
else if(tag == "value")
88
return TAG_VALUE;
89
90
return TAG_NONE;
91
}
92
93
csubstr from_tag_long(YamlTag_e tag)
94
{
95
switch(tag)
96
{
97
case TAG_MAP:
98
return {"<tag:yaml.org,2002:map>"};
99
case TAG_OMAP:
100
return {"<tag:yaml.org,2002:omap>"};
101
case TAG_PAIRS:
102
return {"<tag:yaml.org,2002:pairs>"};
103
case TAG_SET:
104
return {"<tag:yaml.org,2002:set>"};
105
case TAG_SEQ:
106
return {"<tag:yaml.org,2002:seq>"};
107
case TAG_BINARY:
108
return {"<tag:yaml.org,2002:binary>"};
109
case TAG_BOOL:
110
return {"<tag:yaml.org,2002:bool>"};
111
case TAG_FLOAT:
112
return {"<tag:yaml.org,2002:float>"};
113
case TAG_INT:
114
return {"<tag:yaml.org,2002:int>"};
115
case TAG_MERGE:
116
return {"<tag:yaml.org,2002:merge>"};
117
case TAG_NULL:
118
return {"<tag:yaml.org,2002:null>"};
119
case TAG_STR:
120
return {"<tag:yaml.org,2002:str>"};
121
case TAG_TIMESTAMP:
122
return {"<tag:yaml.org,2002:timestamp>"};
123
case TAG_VALUE:
124
return {"<tag:yaml.org,2002:value>"};
125
case TAG_YAML:
126
return {"<tag:yaml.org,2002:yaml>"};
127
case TAG_NONE:
128
return {""};
129
}
130
return {""};
131
}
132
133
csubstr from_tag(YamlTag_e tag)
134
{
135
switch(tag)
136
{
137
case TAG_MAP:
138
return {"!!map"};
139
case TAG_OMAP:
140
return {"!!omap"};
141
case TAG_PAIRS:
142
return {"!!pairs"};
143
case TAG_SET:
144
return {"!!set"};
145
case TAG_SEQ:
146
return {"!!seq"};
147
case TAG_BINARY:
148
return {"!!binary"};
149
case TAG_BOOL:
150
return {"!!bool"};
151
case TAG_FLOAT:
152
return {"!!float"};
153
case TAG_INT:
154
return {"!!int"};
155
case TAG_MERGE:
156
return {"!!merge"};
157
case TAG_NULL:
158
return {"!!null"};
159
case TAG_STR:
160
return {"!!str"};
161
case TAG_TIMESTAMP:
162
return {"!!timestamp"};
163
case TAG_VALUE:
164
return {"!!value"};
165
case TAG_YAML:
166
return {"!!yaml"};
167
case TAG_NONE:
168
return {""};
169
}
170
return {""};
171
}
172
173
174
//-----------------------------------------------------------------------------
175
//-----------------------------------------------------------------------------
176
//-----------------------------------------------------------------------------
177
178
const char* NodeType::type_str(NodeType_e ty)
179
{
180
switch(ty & _TYMASK)
181
{
182
case KEYVAL:
183
return "KEYVAL";
184
case KEY:
185
return "KEY";
186
case VAL:
187
return "VAL";
188
case MAP:
189
return "MAP";
190
case SEQ:
191
return "SEQ";
192
case KEYMAP:
193
return "KEYMAP";
194
case KEYSEQ:
195
return "KEYSEQ";
196
case DOCSEQ:
197
return "DOCSEQ";
198
case DOCMAP:
199
return "DOCMAP";
200
case DOCVAL:
201
return "DOCVAL";
202
case DOC:
203
return "DOC";
204
case STREAM:
205
return "STREAM";
206
case NOTYPE:
207
return "NOTYPE";
208
default:
209
if((ty & KEYVAL) == KEYVAL)
210
return "KEYVAL***";
211
if((ty & KEYMAP) == KEYMAP)
212
return "KEYMAP***";
213
if((ty & KEYSEQ) == KEYSEQ)
214
return "KEYSEQ***";
215
if((ty & DOCSEQ) == DOCSEQ)
216
return "DOCSEQ***";
217
if((ty & DOCMAP) == DOCMAP)
218
return "DOCMAP***";
219
if((ty & DOCVAL) == DOCVAL)
220
return "DOCVAL***";
221
if(ty & KEY)
222
return "KEY***";
223
if(ty & VAL)
224
return "VAL***";
225
if(ty & MAP)
226
return "MAP***";
227
if(ty & SEQ)
228
return "SEQ***";
229
if(ty & DOC)
230
return "DOC***";
231
return "(unk)";
232
}
233
}
234
235
236
//-----------------------------------------------------------------------------
237
//-----------------------------------------------------------------------------
238
//-----------------------------------------------------------------------------
239
240
NodeRef Tree::rootref()
241
{
242
return NodeRef(this, root_id());
243
}
244
ConstNodeRef Tree::rootref() const
245
{
246
return ConstNodeRef(this, root_id());
247
}
248
249
ConstNodeRef Tree::crootref()
250
{
251
return ConstNodeRef(this, root_id());
252
}
253
ConstNodeRef Tree::crootref() const
254
{
255
return ConstNodeRef(this, root_id());
256
}
257
258
NodeRef Tree::ref(size_t id)
259
{
260
_RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size);
261
return NodeRef(this, id);
262
}
263
ConstNodeRef Tree::ref(size_t id) const
264
{
265
_RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size);
266
return ConstNodeRef(this, id);
267
}
268
269
ConstNodeRef Tree::cref(size_t id)
270
{
271
_RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size);
272
return ConstNodeRef(this, id);
273
}
274
ConstNodeRef Tree::cref(size_t id) const
275
{
276
_RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size);
277
return ConstNodeRef(this, id);
278
}
279
280
NodeRef Tree::operator[] (csubstr key)
281
{
282
return rootref()[key];
283
}
284
ConstNodeRef Tree::operator[] (csubstr key) const
285
{
286
return rootref()[key];
287
}
288
289
NodeRef Tree::operator[] (size_t i)
290
{
291
return rootref()[i];
292
}
293
ConstNodeRef Tree::operator[] (size_t i) const
294
{
295
return rootref()[i];
296
}
297
298
NodeRef Tree::docref(size_t i)
299
{
300
return ref(doc(i));
301
}
302
ConstNodeRef Tree::docref(size_t i) const
303
{
304
return cref(doc(i));
305
}
306
307
308
//-----------------------------------------------------------------------------
309
Tree::Tree(Callbacks const& cb)
310
: m_buf(nullptr)
311
, m_cap(0)
312
, m_size(0)
313
, m_free_head(NONE)
314
, m_free_tail(NONE)
315
, m_arena()
316
, m_arena_pos(0)
317
, m_callbacks(cb)
318
{
319
}
320
321
Tree::Tree(size_t node_capacity, size_t arena_capacity, Callbacks const& cb)
322
: Tree(cb)
323
{
324
reserve(node_capacity);
325
reserve_arena(arena_capacity);
326
}
327
328
Tree::~Tree()
329
{
330
_free();
331
}
332
333
334
Tree::Tree(Tree const& that) noexcept : Tree(that.m_callbacks)
335
{
336
_copy(that);
337
}
338
339
Tree& Tree::operator= (Tree const& that) noexcept
340
{
341
_free();
342
m_callbacks = that.m_callbacks;
343
_copy(that);
344
return *this;
345
}
346
347
Tree::Tree(Tree && that) noexcept : Tree(that.m_callbacks)
348
{
349
_move(that);
350
}
351
352
Tree& Tree::operator= (Tree && that) noexcept
353
{
354
_free();
355
m_callbacks = that.m_callbacks;
356
_move(that);
357
return *this;
358
}
359
360
void Tree::_free()
361
{
362
if(m_buf)
363
{
364
_RYML_CB_ASSERT(m_callbacks, m_cap > 0);
365
_RYML_CB_FREE(m_callbacks, m_buf, NodeData, m_cap);
366
}
367
if(m_arena.str)
368
{
369
_RYML_CB_ASSERT(m_callbacks, m_arena.len > 0);
370
_RYML_CB_FREE(m_callbacks, m_arena.str, char, m_arena.len);
371
}
372
_clear();
373
}
374
375
376
C4_SUPPRESS_WARNING_GCC_PUSH
377
#if defined(__GNUC__) && __GNUC__>= 8
378
C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wclass-memaccess") // error: ‘void* memset(void*, int, size_t)’ clearing an object of type ‘class c4::yml::Tree’ with no trivial copy-assignment; use assignment or value-initialization instead
379
#endif
380
381
void Tree::_clear()
382
{
383
m_buf = nullptr;
384
m_cap = 0;
385
m_size = 0;
386
m_free_head = 0;
387
m_free_tail = 0;
388
m_arena = {};
389
m_arena_pos = 0;
390
for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)
391
m_tag_directives[i] = {};
392
}
393
394
void Tree::_copy(Tree const& that)
395
{
396
_RYML_CB_ASSERT(m_callbacks, m_buf == nullptr);
397
_RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr);
398
_RYML_CB_ASSERT(m_callbacks, m_arena.len == 0);
399
m_buf = _RYML_CB_ALLOC_HINT(m_callbacks, NodeData, that.m_cap, that.m_buf);
400
memcpy(m_buf, that.m_buf, that.m_cap * sizeof(NodeData));
401
m_cap = that.m_cap;
402
m_size = that.m_size;
403
m_free_head = that.m_free_head;
404
m_free_tail = that.m_free_tail;
405
m_arena_pos = that.m_arena_pos;
406
m_arena = that.m_arena;
407
if(that.m_arena.str)
408
{
409
_RYML_CB_ASSERT(m_callbacks, that.m_arena.len > 0);
410
substr arena;
411
arena.str = _RYML_CB_ALLOC_HINT(m_callbacks, char, that.m_arena.len, that.m_arena.str);
412
arena.len = that.m_arena.len;
413
_relocate(arena); // does a memcpy of the arena and updates nodes using the old arena
414
m_arena = arena;
415
}
416
for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)
417
m_tag_directives[i] = that.m_tag_directives[i];
418
}
419
420
void Tree::_move(Tree & that)
421
{
422
_RYML_CB_ASSERT(m_callbacks, m_buf == nullptr);
423
_RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr);
424
_RYML_CB_ASSERT(m_callbacks, m_arena.len == 0);
425
m_buf = that.m_buf;
426
m_cap = that.m_cap;
427
m_size = that.m_size;
428
m_free_head = that.m_free_head;
429
m_free_tail = that.m_free_tail;
430
m_arena = that.m_arena;
431
m_arena_pos = that.m_arena_pos;
432
for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)
433
m_tag_directives[i] = that.m_tag_directives[i];
434
that._clear();
435
}
436
437
void Tree::_relocate(substr next_arena)
438
{
439
_RYML_CB_ASSERT(m_callbacks, next_arena.not_empty());
440
_RYML_CB_ASSERT(m_callbacks, next_arena.len >= m_arena.len);
441
memcpy(next_arena.str, m_arena.str, m_arena_pos);
442
for(NodeData *C4_RESTRICT n = m_buf, *e = m_buf + m_cap; n != e; ++n)
443
{
444
if(in_arena(n->m_key.scalar))
445
n->m_key.scalar = _relocated(n->m_key.scalar, next_arena);
446
if(in_arena(n->m_key.tag))
447
n->m_key.tag = _relocated(n->m_key.tag, next_arena);
448
if(in_arena(n->m_key.anchor))
449
n->m_key.anchor = _relocated(n->m_key.anchor, next_arena);
450
if(in_arena(n->m_val.scalar))
451
n->m_val.scalar = _relocated(n->m_val.scalar, next_arena);
452
if(in_arena(n->m_val.tag))
453
n->m_val.tag = _relocated(n->m_val.tag, next_arena);
454
if(in_arena(n->m_val.anchor))
455
n->m_val.anchor = _relocated(n->m_val.anchor, next_arena);
456
}
457
for(TagDirective &C4_RESTRICT td : m_tag_directives)
458
{
459
if(in_arena(td.prefix))
460
td.prefix = _relocated(td.prefix, next_arena);
461
if(in_arena(td.handle))
462
td.handle = _relocated(td.handle, next_arena);
463
}
464
}
465
466
467
//-----------------------------------------------------------------------------
468
void Tree::reserve(size_t cap)
469
{
470
if(cap > m_cap)
471
{
472
NodeData *buf = _RYML_CB_ALLOC_HINT(m_callbacks, NodeData, cap, m_buf);
473
if(m_buf)
474
{
475
memcpy(buf, m_buf, m_cap * sizeof(NodeData));
476
_RYML_CB_FREE(m_callbacks, m_buf, NodeData, m_cap);
477
}
478
size_t first = m_cap, del = cap - m_cap;
479
m_cap = cap;
480
m_buf = buf;
481
_clear_range(first, del);
482
if(m_free_head != NONE)
483
{
484
_RYML_CB_ASSERT(m_callbacks, m_buf != nullptr);
485
_RYML_CB_ASSERT(m_callbacks, m_free_tail != NONE);
486
m_buf[m_free_tail].m_next_sibling = first;
487
m_buf[first].m_prev_sibling = m_free_tail;
488
m_free_tail = cap-1;
489
}
490
else
491
{
492
_RYML_CB_ASSERT(m_callbacks, m_free_tail == NONE);
493
m_free_head = first;
494
m_free_tail = cap-1;
495
}
496
_RYML_CB_ASSERT(m_callbacks, m_free_head == NONE || (m_free_head >= 0 && m_free_head < cap));
497
_RYML_CB_ASSERT(m_callbacks, m_free_tail == NONE || (m_free_tail >= 0 && m_free_tail < cap));
498
499
if( ! m_size)
500
_claim_root();
501
}
502
}
503
504
505
//-----------------------------------------------------------------------------
506
void Tree::clear()
507
{
508
_clear_range(0, m_cap);
509
m_size = 0;
510
if(m_buf)
511
{
512
_RYML_CB_ASSERT(m_callbacks, m_cap >= 0);
513
m_free_head = 0;
514
m_free_tail = m_cap-1;
515
_claim_root();
516
}
517
else
518
{
519
m_free_head = NONE;
520
m_free_tail = NONE;
521
}
522
for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)
523
m_tag_directives[i] = {};
524
}
525
526
void Tree::_claim_root()
527
{
528
size_t r = _claim();
529
_RYML_CB_ASSERT(m_callbacks, r == 0);
530
_set_hierarchy(r, NONE, NONE);
531
}
532
533
534
//-----------------------------------------------------------------------------
535
void Tree::_clear_range(size_t first, size_t num)
536
{
537
if(num == 0)
538
return; // prevent overflow when subtracting
539
_RYML_CB_ASSERT(m_callbacks, first >= 0 && first + num <= m_cap);
540
memset(m_buf + first, 0, num * sizeof(NodeData)); // TODO we should not need this
541
for(size_t i = first, e = first + num; i < e; ++i)
542
{
543
_clear(i);
544
NodeData *n = m_buf + i;
545
n->m_prev_sibling = i - 1;
546
n->m_next_sibling = i + 1;
547
}
548
m_buf[first + num - 1].m_next_sibling = NONE;
549
}
550
551
C4_SUPPRESS_WARNING_GCC_POP
552
553
554
//-----------------------------------------------------------------------------
555
void Tree::_release(size_t i)
556
{
557
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
558
559
_rem_hierarchy(i);
560
_free_list_add(i);
561
_clear(i);
562
563
--m_size;
564
}
565
566
//-----------------------------------------------------------------------------
567
// add to the front of the free list
568
void Tree::_free_list_add(size_t i)
569
{
570
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
571
NodeData &C4_RESTRICT w = m_buf[i];
572
573
w.m_parent = NONE;
574
w.m_next_sibling = m_free_head;
575
w.m_prev_sibling = NONE;
576
if(m_free_head != NONE)
577
m_buf[m_free_head].m_prev_sibling = i;
578
m_free_head = i;
579
if(m_free_tail == NONE)
580
m_free_tail = m_free_head;
581
}
582
583
void Tree::_free_list_rem(size_t i)
584
{
585
if(m_free_head == i)
586
m_free_head = _p(i)->m_next_sibling;
587
_rem_hierarchy(i);
588
}
589
590
//-----------------------------------------------------------------------------
591
size_t Tree::_claim()
592
{
593
if(m_free_head == NONE || m_buf == nullptr)
594
{
595
size_t sz = 2 * m_cap;
596
sz = sz ? sz : 16;
597
reserve(sz);
598
_RYML_CB_ASSERT(m_callbacks, m_free_head != NONE);
599
}
600
601
_RYML_CB_ASSERT(m_callbacks, m_size < m_cap);
602
_RYML_CB_ASSERT(m_callbacks, m_free_head >= 0 && m_free_head < m_cap);
603
604
size_t ichild = m_free_head;
605
NodeData *child = m_buf + ichild;
606
607
++m_size;
608
m_free_head = child->m_next_sibling;
609
if(m_free_head == NONE)
610
{
611
m_free_tail = NONE;
612
_RYML_CB_ASSERT(m_callbacks, m_size == m_cap);
613
}
614
615
_clear(ichild);
616
617
return ichild;
618
}
619
620
//-----------------------------------------------------------------------------
621
622
C4_SUPPRESS_WARNING_GCC_PUSH
623
C4_SUPPRESS_WARNING_CLANG_PUSH
624
C4_SUPPRESS_WARNING_CLANG("-Wnull-dereference")
625
#if defined(__GNUC__) && (__GNUC__ >= 6)
626
C4_SUPPRESS_WARNING_GCC("-Wnull-dereference")
627
#endif
628
629
void Tree::_set_hierarchy(size_t ichild, size_t iparent, size_t iprev_sibling)
630
{
631
_RYML_CB_ASSERT(m_callbacks, iparent == NONE || (iparent >= 0 && iparent < m_cap));
632
_RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE || (iprev_sibling >= 0 && iprev_sibling < m_cap));
633
634
NodeData *C4_RESTRICT child = get(ichild);
635
636
child->m_parent = iparent;
637
child->m_prev_sibling = NONE;
638
child->m_next_sibling = NONE;
639
640
if(iparent == NONE)
641
{
642
_RYML_CB_ASSERT(m_callbacks, ichild == 0);
643
_RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE);
644
}
645
646
if(iparent == NONE)
647
return;
648
649
size_t inext_sibling = iprev_sibling != NONE ? next_sibling(iprev_sibling) : first_child(iparent);
650
NodeData *C4_RESTRICT parent = get(iparent);
651
NodeData *C4_RESTRICT psib = get(iprev_sibling);
652
NodeData *C4_RESTRICT nsib = get(inext_sibling);
653
654
if(psib)
655
{
656
_RYML_CB_ASSERT(m_callbacks, next_sibling(iprev_sibling) == id(nsib));
657
child->m_prev_sibling = id(psib);
658
psib->m_next_sibling = id(child);
659
_RYML_CB_ASSERT(m_callbacks, psib->m_prev_sibling != psib->m_next_sibling || psib->m_prev_sibling == NONE);
660
}
661
662
if(nsib)
663
{
664
_RYML_CB_ASSERT(m_callbacks, prev_sibling(inext_sibling) == id(psib));
665
child->m_next_sibling = id(nsib);
666
nsib->m_prev_sibling = id(child);
667
_RYML_CB_ASSERT(m_callbacks, nsib->m_prev_sibling != nsib->m_next_sibling || nsib->m_prev_sibling == NONE);
668
}
669
670
if(parent->m_first_child == NONE)
671
{
672
_RYML_CB_ASSERT(m_callbacks, parent->m_last_child == NONE);
673
parent->m_first_child = id(child);
674
parent->m_last_child = id(child);
675
}
676
else
677
{
678
if(child->m_next_sibling == parent->m_first_child)
679
parent->m_first_child = id(child);
680
681
if(child->m_prev_sibling == parent->m_last_child)
682
parent->m_last_child = id(child);
683
}
684
}
685
686
C4_SUPPRESS_WARNING_GCC_POP
687
C4_SUPPRESS_WARNING_CLANG_POP
688
689
690
//-----------------------------------------------------------------------------
691
void Tree::_rem_hierarchy(size_t i)
692
{
693
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
694
695
NodeData &C4_RESTRICT w = m_buf[i];
696
697
// remove from the parent
698
if(w.m_parent != NONE)
699
{
700
NodeData &C4_RESTRICT p = m_buf[w.m_parent];
701
if(p.m_first_child == i)
702
{
703
p.m_first_child = w.m_next_sibling;
704
}
705
if(p.m_last_child == i)
706
{
707
p.m_last_child = w.m_prev_sibling;
708
}
709
}
710
711
// remove from the used list
712
if(w.m_prev_sibling != NONE)
713
{
714
NodeData *C4_RESTRICT prev = get(w.m_prev_sibling);
715
prev->m_next_sibling = w.m_next_sibling;
716
}
717
if(w.m_next_sibling != NONE)
718
{
719
NodeData *C4_RESTRICT next = get(w.m_next_sibling);
720
next->m_prev_sibling = w.m_prev_sibling;
721
}
722
}
723
724
//-----------------------------------------------------------------------------
725
void Tree::reorder()
726
{
727
size_t r = root_id();
728
_do_reorder(&r, 0);
729
}
730
731
//-----------------------------------------------------------------------------
732
size_t Tree::_do_reorder(size_t *node, size_t count)
733
{
734
// swap this node if it's not in place
735
if(*node != count)
736
{
737
_swap(*node, count);
738
*node = count;
739
}
740
++count; // bump the count from this node
741
742
// now descend in the hierarchy
743
for(size_t i = first_child(*node); i != NONE; i = next_sibling(i))
744
{
745
// this child may have been relocated to a different index,
746
// so get an updated version
747
count = _do_reorder(&i, count);
748
}
749
return count;
750
}
751
752
//-----------------------------------------------------------------------------
753
void Tree::_swap(size_t n_, size_t m_)
754
{
755
_RYML_CB_ASSERT(m_callbacks, (parent(n_) != NONE) || type(n_) == NOTYPE);
756
_RYML_CB_ASSERT(m_callbacks, (parent(m_) != NONE) || type(m_) == NOTYPE);
757
NodeType tn = type(n_);
758
NodeType tm = type(m_);
759
if(tn != NOTYPE && tm != NOTYPE)
760
{
761
_swap_props(n_, m_);
762
_swap_hierarchy(n_, m_);
763
}
764
else if(tn == NOTYPE && tm != NOTYPE)
765
{
766
_copy_props(n_, m_);
767
_free_list_rem(n_);
768
_copy_hierarchy(n_, m_);
769
_clear(m_);
770
_free_list_add(m_);
771
}
772
else if(tn != NOTYPE && tm == NOTYPE)
773
{
774
_copy_props(m_, n_);
775
_free_list_rem(m_);
776
_copy_hierarchy(m_, n_);
777
_clear(n_);
778
_free_list_add(n_);
779
}
780
else
781
{
782
C4_NEVER_REACH();
783
}
784
}
785
786
//-----------------------------------------------------------------------------
787
void Tree::_swap_hierarchy(size_t ia, size_t ib)
788
{
789
if(ia == ib) return;
790
791
for(size_t i = first_child(ia); i != NONE; i = next_sibling(i))
792
{
793
if(i == ib || i == ia)
794
continue;
795
_p(i)->m_parent = ib;
796
}
797
798
for(size_t i = first_child(ib); i != NONE; i = next_sibling(i))
799
{
800
if(i == ib || i == ia)
801
continue;
802
_p(i)->m_parent = ia;
803
}
804
805
auto & C4_RESTRICT a = *_p(ia);
806
auto & C4_RESTRICT b = *_p(ib);
807
auto & C4_RESTRICT pa = *_p(a.m_parent);
808
auto & C4_RESTRICT pb = *_p(b.m_parent);
809
810
if(&pa == &pb)
811
{
812
if((pa.m_first_child == ib && pa.m_last_child == ia)
813
||
814
(pa.m_first_child == ia && pa.m_last_child == ib))
815
{
816
std::swap(pa.m_first_child, pa.m_last_child);
817
}
818
else
819
{
820
bool changed = false;
821
if(pa.m_first_child == ia)
822
{
823
pa.m_first_child = ib;
824
changed = true;
825
}
826
if(pa.m_last_child == ia)
827
{
828
pa.m_last_child = ib;
829
changed = true;
830
}
831
if(pb.m_first_child == ib && !changed)
832
{
833
pb.m_first_child = ia;
834
}
835
if(pb.m_last_child == ib && !changed)
836
{
837
pb.m_last_child = ia;
838
}
839
}
840
}
841
else
842
{
843
if(pa.m_first_child == ia)
844
pa.m_first_child = ib;
845
if(pa.m_last_child == ia)
846
pa.m_last_child = ib;
847
if(pb.m_first_child == ib)
848
pb.m_first_child = ia;
849
if(pb.m_last_child == ib)
850
pb.m_last_child = ia;
851
}
852
std::swap(a.m_first_child , b.m_first_child);
853
std::swap(a.m_last_child , b.m_last_child);
854
855
if(a.m_prev_sibling != ib && b.m_prev_sibling != ia &&
856
a.m_next_sibling != ib && b.m_next_sibling != ia)
857
{
858
if(a.m_prev_sibling != NONE && a.m_prev_sibling != ib)
859
_p(a.m_prev_sibling)->m_next_sibling = ib;
860
if(a.m_next_sibling != NONE && a.m_next_sibling != ib)
861
_p(a.m_next_sibling)->m_prev_sibling = ib;
862
if(b.m_prev_sibling != NONE && b.m_prev_sibling != ia)
863
_p(b.m_prev_sibling)->m_next_sibling = ia;
864
if(b.m_next_sibling != NONE && b.m_next_sibling != ia)
865
_p(b.m_next_sibling)->m_prev_sibling = ia;
866
std::swap(a.m_prev_sibling, b.m_prev_sibling);
867
std::swap(a.m_next_sibling, b.m_next_sibling);
868
}
869
else
870
{
871
if(a.m_next_sibling == ib) // n will go after m
872
{
873
_RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling == ia);
874
if(a.m_prev_sibling != NONE)
875
{
876
_RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ib);
877
_p(a.m_prev_sibling)->m_next_sibling = ib;
878
}
879
if(b.m_next_sibling != NONE)
880
{
881
_RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ia);
882
_p(b.m_next_sibling)->m_prev_sibling = ia;
883
}
884
size_t ns = b.m_next_sibling;
885
b.m_prev_sibling = a.m_prev_sibling;
886
b.m_next_sibling = ia;
887
a.m_prev_sibling = ib;
888
a.m_next_sibling = ns;
889
}
890
else if(a.m_prev_sibling == ib) // m will go after n
891
{
892
_RYML_CB_ASSERT(m_callbacks, b.m_next_sibling == ia);
893
if(b.m_prev_sibling != NONE)
894
{
895
_RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ia);
896
_p(b.m_prev_sibling)->m_next_sibling = ia;
897
}
898
if(a.m_next_sibling != NONE)
899
{
900
_RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ib);
901
_p(a.m_next_sibling)->m_prev_sibling = ib;
902
}
903
size_t ns = b.m_prev_sibling;
904
a.m_prev_sibling = b.m_prev_sibling;
905
a.m_next_sibling = ib;
906
b.m_prev_sibling = ia;
907
b.m_next_sibling = ns;
908
}
909
else
910
{
911
C4_NEVER_REACH();
912
}
913
}
914
_RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ia);
915
_RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ia);
916
_RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ib);
917
_RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ib);
918
919
if(a.m_parent != ib && b.m_parent != ia)
920
{
921
std::swap(a.m_parent, b.m_parent);
922
}
923
else
924
{
925
if(a.m_parent == ib && b.m_parent != ia)
926
{
927
a.m_parent = b.m_parent;
928
b.m_parent = ia;
929
}
930
else if(a.m_parent != ib && b.m_parent == ia)
931
{
932
b.m_parent = a.m_parent;
933
a.m_parent = ib;
934
}
935
else
936
{
937
C4_NEVER_REACH();
938
}
939
}
940
}
941
942
//-----------------------------------------------------------------------------
943
void Tree::_copy_hierarchy(size_t dst_, size_t src_)
944
{
945
auto const& C4_RESTRICT src = *_p(src_);
946
auto & C4_RESTRICT dst = *_p(dst_);
947
auto & C4_RESTRICT prt = *_p(src.m_parent);
948
for(size_t i = src.m_first_child; i != NONE; i = next_sibling(i))
949
{
950
_p(i)->m_parent = dst_;
951
}
952
if(src.m_prev_sibling != NONE)
953
{
954
_p(src.m_prev_sibling)->m_next_sibling = dst_;
955
}
956
if(src.m_next_sibling != NONE)
957
{
958
_p(src.m_next_sibling)->m_prev_sibling = dst_;
959
}
960
if(prt.m_first_child == src_)
961
{
962
prt.m_first_child = dst_;
963
}
964
if(prt.m_last_child == src_)
965
{
966
prt.m_last_child = dst_;
967
}
968
dst.m_parent = src.m_parent;
969
dst.m_first_child = src.m_first_child;
970
dst.m_last_child = src.m_last_child;
971
dst.m_prev_sibling = src.m_prev_sibling;
972
dst.m_next_sibling = src.m_next_sibling;
973
}
974
975
//-----------------------------------------------------------------------------
976
void Tree::_swap_props(size_t n_, size_t m_)
977
{
978
NodeData &C4_RESTRICT n = *_p(n_);
979
NodeData &C4_RESTRICT m = *_p(m_);
980
std::swap(n.m_type, m.m_type);
981
std::swap(n.m_key, m.m_key);
982
std::swap(n.m_val, m.m_val);
983
}
984
985
//-----------------------------------------------------------------------------
986
void Tree::move(size_t node, size_t after)
987
{
988
_RYML_CB_ASSERT(m_callbacks, node != NONE);
989
_RYML_CB_ASSERT(m_callbacks, node != after);
990
_RYML_CB_ASSERT(m_callbacks, ! is_root(node));
991
_RYML_CB_ASSERT(m_callbacks, (after == NONE) || (has_sibling(node, after) && has_sibling(after, node)));
992
993
_rem_hierarchy(node);
994
_set_hierarchy(node, parent(node), after);
995
}
996
997
//-----------------------------------------------------------------------------
998
999
void Tree::move(size_t node, size_t new_parent, size_t after)
1000
{
1001
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1002
_RYML_CB_ASSERT(m_callbacks, node != after);
1003
_RYML_CB_ASSERT(m_callbacks, new_parent != NONE);
1004
_RYML_CB_ASSERT(m_callbacks, new_parent != node);
1005
_RYML_CB_ASSERT(m_callbacks, new_parent != after);
1006
_RYML_CB_ASSERT(m_callbacks, ! is_root(node));
1007
1008
_rem_hierarchy(node);
1009
_set_hierarchy(node, new_parent, after);
1010
}
1011
1012
size_t Tree::move(Tree *src, size_t node, size_t new_parent, size_t after)
1013
{
1014
_RYML_CB_ASSERT(m_callbacks, src != nullptr);
1015
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1016
_RYML_CB_ASSERT(m_callbacks, new_parent != NONE);
1017
_RYML_CB_ASSERT(m_callbacks, new_parent != after);
1018
1019
size_t dup = duplicate(src, node, new_parent, after);
1020
src->remove(node);
1021
return dup;
1022
}
1023
1024
void Tree::set_root_as_stream()
1025
{
1026
size_t root = root_id();
1027
if(is_stream(root))
1028
return;
1029
// don't use _add_flags() because it's checked and will fail
1030
if(!has_children(root))
1031
{
1032
if(is_val(root))
1033
{
1034
_p(root)->m_type.add(SEQ);
1035
size_t next_doc = append_child(root);
1036
_copy_props_wo_key(next_doc, root);
1037
_p(next_doc)->m_type.add(DOC);
1038
_p(next_doc)->m_type.rem(SEQ);
1039
}
1040
_p(root)->m_type = STREAM;
1041
return;
1042
}
1043
_RYML_CB_ASSERT(m_callbacks, !has_key(root));
1044
size_t next_doc = append_child(root);
1045
_copy_props_wo_key(next_doc, root);
1046
_add_flags(next_doc, DOC);
1047
for(size_t prev = NONE, ch = first_child(root), next = next_sibling(ch); ch != NONE; )
1048
{
1049
if(ch == next_doc)
1050
break;
1051
move(ch, next_doc, prev);
1052
prev = ch;
1053
ch = next;
1054
next = next_sibling(next);
1055
}
1056
_p(root)->m_type = STREAM;
1057
}
1058
1059
1060
//-----------------------------------------------------------------------------
1061
void Tree::remove_children(size_t node)
1062
{
1063
_RYML_CB_ASSERT(m_callbacks, get(node) != nullptr);
1064
size_t ich = get(node)->m_first_child;
1065
while(ich != NONE)
1066
{
1067
remove_children(ich);
1068
_RYML_CB_ASSERT(m_callbacks, get(ich) != nullptr);
1069
size_t next = get(ich)->m_next_sibling;
1070
_release(ich);
1071
if(ich == get(node)->m_last_child)
1072
break;
1073
ich = next;
1074
}
1075
}
1076
1077
bool Tree::change_type(size_t node, NodeType type)
1078
{
1079
_RYML_CB_ASSERT(m_callbacks, type.is_val() || type.is_map() || type.is_seq());
1080
_RYML_CB_ASSERT(m_callbacks, type.is_val() + type.is_map() + type.is_seq() == 1);
1081
_RYML_CB_ASSERT(m_callbacks, type.has_key() == has_key(node) || (has_key(node) && !type.has_key()));
1082
NodeData *d = _p(node);
1083
if(type.is_map() && is_map(node))
1084
return false;
1085
else if(type.is_seq() && is_seq(node))
1086
return false;
1087
else if(type.is_val() && is_val(node))
1088
return false;
1089
d->m_type = (d->m_type & (~(MAP|SEQ|VAL))) | type;
1090
remove_children(node);
1091
return true;
1092
}
1093
1094
1095
//-----------------------------------------------------------------------------
1096
size_t Tree::duplicate(size_t node, size_t parent, size_t after)
1097
{
1098
return duplicate(this, node, parent, after);
1099
}
1100
1101
size_t Tree::duplicate(Tree const* src, size_t node, size_t parent, size_t after)
1102
{
1103
_RYML_CB_ASSERT(m_callbacks, src != nullptr);
1104
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1105
_RYML_CB_ASSERT(m_callbacks, parent != NONE);
1106
_RYML_CB_ASSERT(m_callbacks, ! src->is_root(node));
1107
1108
size_t copy = _claim();
1109
1110
_copy_props(copy, src, node);
1111
_set_hierarchy(copy, parent, after);
1112
duplicate_children(src, node, copy, NONE);
1113
1114
return copy;
1115
}
1116
1117
//-----------------------------------------------------------------------------
1118
size_t Tree::duplicate_children(size_t node, size_t parent, size_t after)
1119
{
1120
return duplicate_children(this, node, parent, after);
1121
}
1122
1123
size_t Tree::duplicate_children(Tree const* src, size_t node, size_t parent, size_t after)
1124
{
1125
_RYML_CB_ASSERT(m_callbacks, src != nullptr);
1126
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1127
_RYML_CB_ASSERT(m_callbacks, parent != NONE);
1128
_RYML_CB_ASSERT(m_callbacks, after == NONE || has_child(parent, after));
1129
1130
size_t prev = after;
1131
for(size_t i = src->first_child(node); i != NONE; i = src->next_sibling(i))
1132
{
1133
prev = duplicate(src, i, parent, prev);
1134
}
1135
1136
return prev;
1137
}
1138
1139
//-----------------------------------------------------------------------------
1140
void Tree::duplicate_contents(size_t node, size_t where)
1141
{
1142
duplicate_contents(this, node, where);
1143
}
1144
1145
void Tree::duplicate_contents(Tree const *src, size_t node, size_t where)
1146
{
1147
_RYML_CB_ASSERT(m_callbacks, src != nullptr);
1148
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1149
_RYML_CB_ASSERT(m_callbacks, where != NONE);
1150
_copy_props_wo_key(where, src, node);
1151
duplicate_children(src, node, where, last_child(where));
1152
}
1153
1154
//-----------------------------------------------------------------------------
1155
size_t Tree::duplicate_children_no_rep(size_t node, size_t parent, size_t after)
1156
{
1157
return duplicate_children_no_rep(this, node, parent, after);
1158
}
1159
1160
size_t Tree::duplicate_children_no_rep(Tree const *src, size_t node, size_t parent, size_t after)
1161
{
1162
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1163
_RYML_CB_ASSERT(m_callbacks, parent != NONE);
1164
_RYML_CB_ASSERT(m_callbacks, after == NONE || has_child(parent, after));
1165
1166
// don't loop using pointers as there may be a relocation
1167
1168
// find the position where "after" is
1169
size_t after_pos = NONE;
1170
if(after != NONE)
1171
{
1172
for(size_t i = first_child(parent), icount = 0; i != NONE; ++icount, i = next_sibling(i))
1173
{
1174
if(i == after)
1175
{
1176
after_pos = icount;
1177
break;
1178
}
1179
}
1180
_RYML_CB_ASSERT(m_callbacks, after_pos != NONE);
1181
}
1182
1183
// for each child to be duplicated...
1184
size_t prev = after;
1185
for(size_t i = src->first_child(node); i != NONE; i = src->next_sibling(i))
1186
{
1187
if(is_seq(parent))
1188
{
1189
prev = duplicate(i, parent, prev);
1190
}
1191
else
1192
{
1193
_RYML_CB_ASSERT(m_callbacks, is_map(parent));
1194
// does the parent already have a node with key equal to that of the current duplicate?
1195
size_t rep = NONE, rep_pos = NONE;
1196
for(size_t j = first_child(parent), jcount = 0; j != NONE; ++jcount, j = next_sibling(j))
1197
{
1198
if(key(j) == key(i))
1199
{
1200
rep = j;
1201
rep_pos = jcount;
1202
break;
1203
}
1204
}
1205
if(rep == NONE) // there is no repetition; just duplicate
1206
{
1207
prev = duplicate(src, i, parent, prev);
1208
}
1209
else // yes, there is a repetition
1210
{
1211
if(after_pos != NONE && rep_pos < after_pos)
1212
{
1213
// rep is located before the node which will be inserted,
1214
// and will be overridden by the duplicate. So replace it.
1215
remove(rep);
1216
prev = duplicate(src, i, parent, prev);
1217
}
1218
else if(prev == NONE)
1219
{
1220
// first iteration with prev = after = NONE and repetition
1221
prev = rep;
1222
}
1223
else if(rep != prev)
1224
{
1225
// rep is located after the node which will be inserted
1226
// and overrides it. So move the rep into this node's place.
1227
move(rep, prev);
1228
prev = rep;
1229
}
1230
} // there's a repetition
1231
}
1232
}
1233
1234
return prev;
1235
}
1236
1237
1238
//-----------------------------------------------------------------------------
1239
1240
void Tree::merge_with(Tree const *src, size_t src_node, size_t dst_node)
1241
{
1242
_RYML_CB_ASSERT(m_callbacks, src != nullptr);
1243
if(src_node == NONE)
1244
src_node = src->root_id();
1245
if(dst_node == NONE)
1246
dst_node = root_id();
1247
_RYML_CB_ASSERT(m_callbacks, src->has_val(src_node) || src->is_seq(src_node) || src->is_map(src_node));
1248
1249
if(src->has_val(src_node))
1250
{
1251
if( ! has_val(dst_node))
1252
{
1253
if(has_children(dst_node))
1254
remove_children(dst_node);
1255
}
1256
if(src->is_keyval(src_node))
1257
_copy_props(dst_node, src, src_node);
1258
else if(src->is_val(src_node))
1259
_copy_props_wo_key(dst_node, src, src_node);
1260
else
1261
C4_NEVER_REACH();
1262
}
1263
else if(src->is_seq(src_node))
1264
{
1265
if( ! is_seq(dst_node))
1266
{
1267
if(has_children(dst_node))
1268
remove_children(dst_node);
1269
_clear_type(dst_node);
1270
if(src->has_key(src_node))
1271
to_seq(dst_node, src->key(src_node));
1272
else
1273
to_seq(dst_node);
1274
}
1275
for(size_t sch = src->first_child(src_node); sch != NONE; sch = src->next_sibling(sch))
1276
{
1277
size_t dch = append_child(dst_node);
1278
_copy_props_wo_key(dch, src, sch);
1279
merge_with(src, sch, dch);
1280
}
1281
}
1282
else if(src->is_map(src_node))
1283
{
1284
if( ! is_map(dst_node))
1285
{
1286
if(has_children(dst_node))
1287
remove_children(dst_node);
1288
_clear_type(dst_node);
1289
if(src->has_key(src_node))
1290
to_map(dst_node, src->key(src_node));
1291
else
1292
to_map(dst_node);
1293
}
1294
for(size_t sch = src->first_child(src_node); sch != NONE; sch = src->next_sibling(sch))
1295
{
1296
size_t dch = find_child(dst_node, src->key(sch));
1297
if(dch == NONE)
1298
{
1299
dch = append_child(dst_node);
1300
_copy_props(dch, src, sch);
1301
}
1302
merge_with(src, sch, dch);
1303
}
1304
}
1305
else
1306
{
1307
C4_NEVER_REACH();
1308
}
1309
}
1310
1311
1312
//-----------------------------------------------------------------------------
1313
1314
namespace detail {
1315
/** @todo make this part of the public API, refactoring as appropriate
1316
* to be able to use the same resolver to handle multiple trees (one
1317
* at a time) */
1318
struct ReferenceResolver
1319
{
1320
struct refdata
1321
{
1322
NodeType type;
1323
size_t node;
1324
size_t prev_anchor;
1325
size_t target;
1326
size_t parent_ref;
1327
size_t parent_ref_sibling;
1328
};
1329
1330
Tree *t;
1331
/** from the specs: "an alias node refers to the most recent
1332
* node in the serialization having the specified anchor". So
1333
* we need to start looking upward from ref nodes.
1334
*
1335
* @see http://yaml.org/spec/1.2/spec.html#id2765878 */
1336
stack<refdata> refs;
1337
1338
ReferenceResolver(Tree *t_) : t(t_), refs(t_->callbacks())
1339
{
1340
resolve();
1341
}
1342
1343
void store_anchors_and_refs()
1344
{
1345
// minimize (re-)allocations by counting first
1346
size_t num_anchors_and_refs = count_anchors_and_refs(t->root_id());
1347
if(!num_anchors_and_refs)
1348
return;
1349
refs.reserve(num_anchors_and_refs);
1350
1351
// now descend through the hierarchy
1352
_store_anchors_and_refs(t->root_id());
1353
1354
// finally connect the reference list
1355
size_t prev_anchor = npos;
1356
size_t count = 0;
1357
for(auto &rd : refs)
1358
{
1359
rd.prev_anchor = prev_anchor;
1360
if(rd.type.is_anchor())
1361
prev_anchor = count;
1362
++count;
1363
}
1364
}
1365
1366
size_t count_anchors_and_refs(size_t n)
1367
{
1368
size_t c = 0;
1369
c += t->has_key_anchor(n);
1370
c += t->has_val_anchor(n);
1371
c += t->is_key_ref(n);
1372
c += t->is_val_ref(n);
1373
for(size_t ch = t->first_child(n); ch != NONE; ch = t->next_sibling(ch))
1374
c += count_anchors_and_refs(ch);
1375
return c;
1376
}
1377
1378
void _store_anchors_and_refs(size_t n)
1379
{
1380
if(t->is_key_ref(n) || t->is_val_ref(n) || (t->has_key(n) && t->key(n) == "<<"))
1381
{
1382
if(t->is_seq(n))
1383
{
1384
// for merging multiple inheritance targets
1385
// <<: [ *CENTER, *BIG ]
1386
for(size_t ich = t->first_child(n); ich != NONE; ich = t->next_sibling(ich))
1387
{
1388
RYML_ASSERT(t->num_children(ich) == 0);
1389
refs.push({VALREF, ich, npos, npos, n, t->next_sibling(n)});
1390
}
1391
return;
1392
}
1393
if(t->is_key_ref(n) && t->key(n) != "<<") // insert key refs BEFORE inserting val refs
1394
{
1395
RYML_CHECK((!t->has_key(n)) || t->key(n).ends_with(t->key_ref(n)));
1396
refs.push({KEYREF, n, npos, npos, NONE, NONE});
1397
}
1398
if(t->is_val_ref(n))
1399
{
1400
RYML_CHECK((!t->has_val(n)) || t->val(n).ends_with(t->val_ref(n)));
1401
refs.push({VALREF, n, npos, npos, NONE, NONE});
1402
}
1403
}
1404
if(t->has_key_anchor(n))
1405
{
1406
RYML_CHECK(t->has_key(n));
1407
refs.push({KEYANCH, n, npos, npos, NONE, NONE});
1408
}
1409
if(t->has_val_anchor(n))
1410
{
1411
RYML_CHECK(t->has_val(n) || t->is_container(n));
1412
refs.push({VALANCH, n, npos, npos, NONE, NONE});
1413
}
1414
for(size_t ch = t->first_child(n); ch != NONE; ch = t->next_sibling(ch))
1415
{
1416
_store_anchors_and_refs(ch);
1417
}
1418
}
1419
1420
size_t lookup_(refdata *C4_RESTRICT ra)
1421
{
1422
RYML_ASSERT(ra->type.is_key_ref() || ra->type.is_val_ref());
1423
RYML_ASSERT(ra->type.is_key_ref() != ra->type.is_val_ref());
1424
csubstr refname;
1425
if(ra->type.is_val_ref())
1426
{
1427
refname = t->val_ref(ra->node);
1428
}
1429
else
1430
{
1431
RYML_ASSERT(ra->type.is_key_ref());
1432
refname = t->key_ref(ra->node);
1433
}
1434
while(ra->prev_anchor != npos)
1435
{
1436
ra = &refs[ra->prev_anchor];
1437
if(t->has_anchor(ra->node, refname))
1438
return ra->node;
1439
}
1440
1441
#ifndef RYML_ERRMSG_SIZE
1442
#define RYML_ERRMSG_SIZE 1024
1443
#endif
1444
1445
char errmsg[RYML_ERRMSG_SIZE];
1446
snprintf(errmsg, RYML_ERRMSG_SIZE, "anchor does not exist: '%.*s'",
1447
static_cast<int>(refname.size()), refname.data());
1448
c4::yml::error(errmsg);
1449
return NONE;
1450
}
1451
1452
void resolve()
1453
{
1454
store_anchors_and_refs();
1455
if(refs.empty())
1456
return;
1457
1458
/* from the specs: "an alias node refers to the most recent
1459
* node in the serialization having the specified anchor". So
1460
* we need to start looking upward from ref nodes.
1461
*
1462
* @see http://yaml.org/spec/1.2/spec.html#id2765878 */
1463
for(size_t i = 0, e = refs.size(); i < e; ++i)
1464
{
1465
auto &C4_RESTRICT rd = refs.top(i);
1466
if( ! rd.type.is_ref())
1467
continue;
1468
rd.target = lookup_(&rd);
1469
}
1470
}
1471
1472
}; // ReferenceResolver
1473
} // namespace detail
1474
1475
void Tree::resolve()
1476
{
1477
if(m_size == 0)
1478
return;
1479
1480
detail::ReferenceResolver rr(this);
1481
1482
// insert the resolved references
1483
size_t prev_parent_ref = NONE;
1484
size_t prev_parent_ref_after = NONE;
1485
for(auto const& C4_RESTRICT rd : rr.refs)
1486
{
1487
if( ! rd.type.is_ref())
1488
continue;
1489
if(rd.parent_ref != NONE)
1490
{
1491
_RYML_CB_ASSERT(m_callbacks, is_seq(rd.parent_ref));
1492
size_t after, p = parent(rd.parent_ref);
1493
if(prev_parent_ref != rd.parent_ref)
1494
{
1495
after = rd.parent_ref;//prev_sibling(rd.parent_ref_sibling);
1496
prev_parent_ref_after = after;
1497
}
1498
else
1499
{
1500
after = prev_parent_ref_after;
1501
}
1502
prev_parent_ref = rd.parent_ref;
1503
prev_parent_ref_after = duplicate_children_no_rep(rd.target, p, after);
1504
remove(rd.node);
1505
}
1506
else
1507
{
1508
if(has_key(rd.node) && is_key_ref(rd.node) && key(rd.node) == "<<")
1509
{
1510
_RYML_CB_ASSERT(m_callbacks, is_keyval(rd.node));
1511
size_t p = parent(rd.node);
1512
size_t after = prev_sibling(rd.node);
1513
duplicate_children_no_rep(rd.target, p, after);
1514
remove(rd.node);
1515
}
1516
else if(rd.type.is_key_ref())
1517
{
1518
_RYML_CB_ASSERT(m_callbacks, is_key_ref(rd.node));
1519
_RYML_CB_ASSERT(m_callbacks, has_key_anchor(rd.target) || has_val_anchor(rd.target));
1520
if(has_val_anchor(rd.target) && val_anchor(rd.target) == key_ref(rd.node))
1521
{
1522
_RYML_CB_CHECK(m_callbacks, !is_container(rd.target));
1523
_RYML_CB_CHECK(m_callbacks, has_val(rd.target));
1524
_p(rd.node)->m_key.scalar = val(rd.target);
1525
_add_flags(rd.node, KEY);
1526
}
1527
else
1528
{
1529
_RYML_CB_CHECK(m_callbacks, key_anchor(rd.target) == key_ref(rd.node));
1530
_p(rd.node)->m_key.scalar = key(rd.target);
1531
_add_flags(rd.node, VAL);
1532
}
1533
}
1534
else
1535
{
1536
_RYML_CB_ASSERT(m_callbacks, rd.type.is_val_ref());
1537
if(has_key_anchor(rd.target) && key_anchor(rd.target) == val_ref(rd.node))
1538
{
1539
_RYML_CB_CHECK(m_callbacks, !is_container(rd.target));
1540
_RYML_CB_CHECK(m_callbacks, has_val(rd.target));
1541
_p(rd.node)->m_val.scalar = key(rd.target);
1542
_add_flags(rd.node, VAL);
1543
}
1544
else
1545
{
1546
duplicate_contents(rd.target, rd.node);
1547
}
1548
}
1549
}
1550
}
1551
1552
// clear anchors and refs
1553
for(auto const& C4_RESTRICT ar : rr.refs)
1554
{
1555
rem_anchor_ref(ar.node);
1556
if(ar.parent_ref != NONE)
1557
if(type(ar.parent_ref) != NOTYPE)
1558
remove(ar.parent_ref);
1559
}
1560
1561
}
1562
1563
//-----------------------------------------------------------------------------
1564
1565
size_t Tree::num_children(size_t node) const
1566
{
1567
size_t count = 0;
1568
for(size_t i = first_child(node); i != NONE; i = next_sibling(i))
1569
++count;
1570
return count;
1571
}
1572
1573
size_t Tree::child(size_t node, size_t pos) const
1574
{
1575
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1576
size_t count = 0;
1577
for(size_t i = first_child(node); i != NONE; i = next_sibling(i))
1578
{
1579
if(count++ == pos)
1580
return i;
1581
}
1582
return NONE;
1583
}
1584
1585
size_t Tree::child_pos(size_t node, size_t ch) const
1586
{
1587
size_t count = 0;
1588
for(size_t i = first_child(node); i != NONE; i = next_sibling(i))
1589
{
1590
if(i == ch)
1591
return count;
1592
++count;
1593
}
1594
return npos;
1595
}
1596
1597
#if defined(__clang__)
1598
# pragma clang diagnostic push
1599
# pragma GCC diagnostic ignored "-Wnull-dereference"
1600
#elif defined(__GNUC__)
1601
# pragma GCC diagnostic push
1602
# if __GNUC__ >= 6
1603
# pragma GCC diagnostic ignored "-Wnull-dereference"
1604
# endif
1605
#endif
1606
1607
size_t Tree::find_child(size_t node, csubstr const& name) const
1608
{
1609
_RYML_CB_ASSERT(m_callbacks, node != NONE);
1610
_RYML_CB_ASSERT(m_callbacks, is_map(node));
1611
if(get(node)->m_first_child == NONE)
1612
{
1613
_RYML_CB_ASSERT(m_callbacks, _p(node)->m_last_child == NONE);
1614
return NONE;
1615
}
1616
else
1617
{
1618
_RYML_CB_ASSERT(m_callbacks, _p(node)->m_last_child != NONE);
1619
}
1620
for(size_t i = first_child(node); i != NONE; i = next_sibling(i))
1621
{
1622
if(_p(i)->m_key.scalar == name)
1623
{
1624
return i;
1625
}
1626
}
1627
return NONE;
1628
}
1629
1630
#if defined(__clang__)
1631
# pragma clang diagnostic pop
1632
#elif defined(__GNUC__)
1633
# pragma GCC diagnostic pop
1634
#endif
1635
1636
1637
//-----------------------------------------------------------------------------
1638
1639
void Tree::to_val(size_t node, csubstr val, type_bits more_flags)
1640
{
1641
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1642
_RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || ! parent_is_map(node));
1643
_set_flags(node, VAL|more_flags);
1644
_p(node)->m_key.clear();
1645
_p(node)->m_val = val;
1646
}
1647
1648
void Tree::to_keyval(size_t node, csubstr key, csubstr val, type_bits more_flags)
1649
{
1650
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1651
_RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node));
1652
_set_flags(node, KEYVAL|more_flags);
1653
_p(node)->m_key = key;
1654
_p(node)->m_val = val;
1655
}
1656
1657
void Tree::to_map(size_t node, type_bits more_flags)
1658
{
1659
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1660
_RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || ! parent_is_map(node)); // parent must not have children with keys
1661
_set_flags(node, MAP|more_flags);
1662
_p(node)->m_key.clear();
1663
_p(node)->m_val.clear();
1664
}
1665
1666
void Tree::to_map(size_t node, csubstr key, type_bits more_flags)
1667
{
1668
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1669
_RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node));
1670
_set_flags(node, KEY|MAP|more_flags);
1671
_p(node)->m_key = key;
1672
_p(node)->m_val.clear();
1673
}
1674
1675
void Tree::to_seq(size_t node, type_bits more_flags)
1676
{
1677
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1678
_RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_seq(node));
1679
_set_flags(node, SEQ|more_flags);
1680
_p(node)->m_key.clear();
1681
_p(node)->m_val.clear();
1682
}
1683
1684
void Tree::to_seq(size_t node, csubstr key, type_bits more_flags)
1685
{
1686
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1687
_RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node));
1688
_set_flags(node, KEY|SEQ|more_flags);
1689
_p(node)->m_key = key;
1690
_p(node)->m_val.clear();
1691
}
1692
1693
void Tree::to_doc(size_t node, type_bits more_flags)
1694
{
1695
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1696
_set_flags(node, DOC|more_flags);
1697
_p(node)->m_key.clear();
1698
_p(node)->m_val.clear();
1699
}
1700
1701
void Tree::to_stream(size_t node, type_bits more_flags)
1702
{
1703
_RYML_CB_ASSERT(m_callbacks, ! has_children(node));
1704
_set_flags(node, STREAM|more_flags);
1705
_p(node)->m_key.clear();
1706
_p(node)->m_val.clear();
1707
}
1708
1709
1710
//-----------------------------------------------------------------------------
1711
size_t Tree::num_tag_directives() const
1712
{
1713
// this assumes we have a very small number of tag directives
1714
for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i)
1715
if(m_tag_directives[i].handle.empty())
1716
return i;
1717
return RYML_MAX_TAG_DIRECTIVES;
1718
}
1719
1720
void Tree::clear_tag_directives()
1721
{
1722
for(TagDirective &td : m_tag_directives)
1723
td = {};
1724
}
1725
1726
size_t Tree::add_tag_directive(TagDirective const& td)
1727
{
1728
_RYML_CB_CHECK(m_callbacks, !td.handle.empty());
1729
_RYML_CB_CHECK(m_callbacks, !td.prefix.empty());
1730
_RYML_CB_ASSERT(m_callbacks, td.handle.begins_with('!'));
1731
_RYML_CB_ASSERT(m_callbacks, td.handle.ends_with('!'));
1732
// https://yaml.org/spec/1.2.2/#rule-ns-word-char
1733
_RYML_CB_ASSERT(m_callbacks, td.handle == '!' || td.handle == "!!" || td.handle.trim('!').first_not_of("01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-") == npos);
1734
size_t pos = num_tag_directives();
1735
_RYML_CB_CHECK(m_callbacks, pos < RYML_MAX_TAG_DIRECTIVES);
1736
m_tag_directives[pos] = td;
1737
return pos;
1738
}
1739
1740
size_t Tree::resolve_tag(substr output, csubstr tag, size_t node_id) const
1741
{
1742
// lookup from the end. We want to find the first directive that
1743
// matches the tag and has a target node id leq than the given
1744
// node_id.
1745
for(size_t i = RYML_MAX_TAG_DIRECTIVES-1; i != (size_t)-1; --i)
1746
{
1747
auto const& td = m_tag_directives[i];
1748
if(td.handle.empty())
1749
continue;
1750
if(tag.begins_with(td.handle) && td.next_node_id <= node_id)
1751
{
1752
_RYML_CB_ASSERT(m_callbacks, tag.len >= td.handle.len);
1753
csubstr rest = tag.sub(td.handle.len);
1754
size_t len = 1u + td.prefix.len + rest.len + 1u;
1755
size_t numpc = rest.count('%');
1756
if(numpc == 0)
1757
{
1758
if(len <= output.len)
1759
{
1760
output.str[0] = '<';
1761
memcpy(1u + output.str, td.prefix.str, td.prefix.len);
1762
memcpy(1u + output.str + td.prefix.len, rest.str, rest.len);
1763
output.str[1u + td.prefix.len + rest.len] = '>';
1764
}
1765
}
1766
else
1767
{
1768
// need to decode URI % sequences
1769
size_t pos = rest.find('%');
1770
_RYML_CB_ASSERT(m_callbacks, pos != npos);
1771
do {
1772
size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1);
1773
if(next == npos)
1774
next = rest.len;
1775
_RYML_CB_CHECK(m_callbacks, pos+1 < next);
1776
_RYML_CB_CHECK(m_callbacks, pos+1 + 2 <= next);
1777
size_t delta = next - (pos+1);
1778
len -= delta;
1779
pos = rest.find('%', pos+1);
1780
} while(pos != npos);
1781
if(len <= output.len)
1782
{
1783
size_t prev = 0, wpos = 0;
1784
auto appendstr = [&](csubstr s) { memcpy(output.str + wpos, s.str, s.len); wpos += s.len; };
1785
auto appendchar = [&](char c) { output.str[wpos++] = c; };
1786
appendchar('<');
1787
appendstr(td.prefix);
1788
pos = rest.find('%');
1789
_RYML_CB_ASSERT(m_callbacks, pos != npos);
1790
do {
1791
size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1);
1792
if(next == npos)
1793
next = rest.len;
1794
_RYML_CB_CHECK(m_callbacks, pos+1 < next);
1795
_RYML_CB_CHECK(m_callbacks, pos+1 + 2 <= next);
1796
uint8_t val;
1797
if(C4_UNLIKELY(!read_hex(rest.range(pos+1, next), &val) || val > 127))
1798
_RYML_CB_ERR(m_callbacks, "invalid URI character");
1799
appendstr(rest.range(prev, pos));
1800
appendchar((char)val);
1801
prev = next;
1802
pos = rest.find('%', pos+1);
1803
} while(pos != npos);
1804
_RYML_CB_ASSERT(m_callbacks, pos == npos);
1805
_RYML_CB_ASSERT(m_callbacks, prev > 0);
1806
_RYML_CB_ASSERT(m_callbacks, rest.len >= prev);
1807
appendstr(rest.sub(prev));
1808
appendchar('>');
1809
_RYML_CB_ASSERT(m_callbacks, wpos == len);
1810
}
1811
}
1812
return len;
1813
}
1814
}
1815
return 0; // return 0 to signal that the tag is local and cannot be resolved
1816
}
1817
1818
namespace {
1819
csubstr _transform_tag(Tree *t, csubstr tag, size_t node)
1820
{
1821
size_t required_size = t->resolve_tag(substr{}, tag, node);
1822
if(!required_size)
1823
return tag;
1824
const char *prev_arena = t->arena().str;
1825
substr buf = t->alloc_arena(required_size);
1826
_RYML_CB_ASSERT(t->m_callbacks, t->arena().str == prev_arena);
1827
size_t actual_size = t->resolve_tag(buf, tag, node);
1828
_RYML_CB_ASSERT(t->m_callbacks, actual_size <= required_size);
1829
return buf.first(actual_size);
1830
}
1831
void _resolve_tags(Tree *t, size_t node)
1832
{
1833
for(size_t child = t->first_child(node); child != NONE; child = t->next_sibling(child))
1834
{
1835
if(t->has_key(child) && t->has_key_tag(child))
1836
t->set_key_tag(child, _transform_tag(t, t->key_tag(child), child));
1837
if(t->has_val(child) && t->has_val_tag(child))
1838
t->set_val_tag(child, _transform_tag(t, t->val_tag(child), child));
1839
_resolve_tags(t, child);
1840
}
1841
}
1842
size_t _count_resolved_tags_size(Tree const* t, size_t node)
1843
{
1844
size_t sz = 0;
1845
for(size_t child = t->first_child(node); child != NONE; child = t->next_sibling(child))
1846
{
1847
if(t->has_key(child) && t->has_key_tag(child))
1848
sz += t->resolve_tag(substr{}, t->key_tag(child), child);
1849
if(t->has_val(child) && t->has_val_tag(child))
1850
sz += t->resolve_tag(substr{}, t->val_tag(child), child);
1851
sz += _count_resolved_tags_size(t, child);
1852
}
1853
return sz;
1854
}
1855
} // namespace
1856
1857
void Tree::resolve_tags()
1858
{
1859
if(empty())
1860
return;
1861
if(num_tag_directives() == 0)
1862
return;
1863
size_t needed_size = _count_resolved_tags_size(this, root_id());
1864
if(needed_size)
1865
reserve_arena(arena_size() + needed_size);
1866
_resolve_tags(this, root_id());
1867
}
1868
1869
1870
//-----------------------------------------------------------------------------
1871
1872
csubstr Tree::lookup_result::resolved() const
1873
{
1874
csubstr p = path.first(path_pos);
1875
if(p.ends_with('.'))
1876
p = p.first(p.len-1);
1877
return p;
1878
}
1879
1880
csubstr Tree::lookup_result::unresolved() const
1881
{
1882
return path.sub(path_pos);
1883
}
1884
1885
void Tree::_advance(lookup_result *r, size_t more) const
1886
{
1887
r->path_pos += more;
1888
if(r->path.sub(r->path_pos).begins_with('.'))
1889
++r->path_pos;
1890
}
1891
1892
Tree::lookup_result Tree::lookup_path(csubstr path, size_t start) const
1893
{
1894
if(start == NONE)
1895
start = root_id();
1896
lookup_result r(path, start);
1897
if(path.empty())
1898
return r;
1899
_lookup_path(&r);
1900
if(r.target == NONE && r.closest == start)
1901
r.closest = NONE;
1902
return r;
1903
}
1904
1905
size_t Tree::lookup_path_or_modify(csubstr default_value, csubstr path, size_t start)
1906
{
1907
size_t target = _lookup_path_or_create(path, start);
1908
if(parent_is_map(target))
1909
to_keyval(target, key(target), default_value);
1910
else
1911
to_val(target, default_value);
1912
return target;
1913
}
1914
1915
size_t Tree::lookup_path_or_modify(Tree const *src, size_t src_node, csubstr path, size_t start)
1916
{
1917
size_t target = _lookup_path_or_create(path, start);
1918
merge_with(src, src_node, target);
1919
return target;
1920
}
1921
1922
size_t Tree::_lookup_path_or_create(csubstr path, size_t start)
1923
{
1924
if(start == NONE)
1925
start = root_id();
1926
lookup_result r(path, start);
1927
_lookup_path(&r);
1928
if(r.target != NONE)
1929
{
1930
C4_ASSERT(r.unresolved().empty());
1931
return r.target;
1932
}
1933
_lookup_path_modify(&r);
1934
return r.target;
1935
}
1936
1937
void Tree::_lookup_path(lookup_result *r) const
1938
{
1939
C4_ASSERT( ! r->unresolved().empty());
1940
_lookup_path_token parent{"", type(r->closest)};
1941
size_t node;
1942
do
1943
{
1944
node = _next_node(r, &parent);
1945
if(node != NONE)
1946
r->closest = node;
1947
if(r->unresolved().empty())
1948
{
1949
r->target = node;
1950
return;
1951
}
1952
} while(node != NONE);
1953
}
1954
1955
void Tree::_lookup_path_modify(lookup_result *r)
1956
{
1957
C4_ASSERT( ! r->unresolved().empty());
1958
_lookup_path_token parent{"", type(r->closest)};
1959
size_t node;
1960
do
1961
{
1962
node = _next_node_modify(r, &parent);
1963
if(node != NONE)
1964
r->closest = node;
1965
if(r->unresolved().empty())
1966
{
1967
r->target = node;
1968
return;
1969
}
1970
} while(node != NONE);
1971
}
1972
1973
size_t Tree::_next_node(lookup_result * r, _lookup_path_token *parent) const
1974
{
1975
_lookup_path_token token = _next_token(r, *parent);
1976
if( ! token)
1977
return NONE;
1978
1979
size_t node = NONE;
1980
csubstr prev = token.value;
1981
if(token.type == MAP || token.type == SEQ)
1982
{
1983
_RYML_CB_ASSERT(m_callbacks, !token.value.begins_with('['));
1984
//_RYML_CB_ASSERT(m_callbacks, is_container(r->closest) || r->closest == NONE);
1985
_RYML_CB_ASSERT(m_callbacks, is_map(r->closest));
1986
node = find_child(r->closest, token.value);
1987
}
1988
else if(token.type == KEYVAL)
1989
{
1990
_RYML_CB_ASSERT(m_callbacks, r->unresolved().empty());
1991
if(is_map(r->closest))
1992
node = find_child(r->closest, token.value);
1993
}
1994
else if(token.type == KEY)
1995
{
1996
_RYML_CB_ASSERT(m_callbacks, token.value.begins_with('[') && token.value.ends_with(']'));
1997
token.value = token.value.offs(1, 1).trim(' ');
1998
size_t idx = 0;
1999
_RYML_CB_CHECK(m_callbacks, from_chars(token.value, &idx));
2000
node = child(r->closest, idx);
2001
}
2002
else
2003
{
2004
C4_NEVER_REACH();
2005
}
2006
2007
if(node != NONE)
2008
{
2009
*parent = token;
2010
}
2011
else
2012
{
2013
csubstr p = r->path.sub(r->path_pos > 0 ? r->path_pos - 1 : r->path_pos);
2014
r->path_pos -= prev.len;
2015
if(p.begins_with('.'))
2016
r->path_pos -= 1u;
2017
}
2018
2019
return node;
2020
}
2021
2022
size_t Tree::_next_node_modify(lookup_result * r, _lookup_path_token *parent)
2023
{
2024
_lookup_path_token token = _next_token(r, *parent);
2025
if( ! token)
2026
return NONE;
2027
2028
size_t node = NONE;
2029
if(token.type == MAP || token.type == SEQ)
2030
{
2031
_RYML_CB_ASSERT(m_callbacks, !token.value.begins_with('['));
2032
//_RYML_CB_ASSERT(m_callbacks, is_container(r->closest) || r->closest == NONE);
2033
if( ! is_container(r->closest))
2034
{
2035
if(has_key(r->closest))
2036
to_map(r->closest, key(r->closest));
2037
else
2038
to_map(r->closest);
2039
}
2040
else
2041
{
2042
if(is_map(r->closest))
2043
node = find_child(r->closest, token.value);
2044
else
2045
{
2046
size_t pos = NONE;
2047
_RYML_CB_CHECK(m_callbacks, c4::atox(token.value, &pos));
2048
_RYML_CB_ASSERT(m_callbacks, pos != NONE);
2049
node = child(r->closest, pos);
2050
}
2051
}
2052
if(node == NONE)
2053
{
2054
_RYML_CB_ASSERT(m_callbacks, is_map(r->closest));
2055
node = append_child(r->closest);
2056
NodeData *n = _p(node);
2057
n->m_key.scalar = token.value;
2058
n->m_type.add(KEY);
2059
}
2060
}
2061
else if(token.type == KEYVAL)
2062
{
2063
_RYML_CB_ASSERT(m_callbacks, r->unresolved().empty());
2064
if(is_map(r->closest))
2065
{
2066
node = find_child(r->closest, token.value);
2067
if(node == NONE)
2068
node = append_child(r->closest);
2069
}
2070
else
2071
{
2072
_RYML_CB_ASSERT(m_callbacks, !is_seq(r->closest));
2073
_add_flags(r->closest, MAP);
2074
node = append_child(r->closest);
2075
}
2076
NodeData *n = _p(node);
2077
n->m_key.scalar = token.value;
2078
n->m_val.scalar = "";
2079
n->m_type.add(KEYVAL);
2080
}
2081
else if(token.type == KEY)
2082
{
2083
_RYML_CB_ASSERT(m_callbacks, token.value.begins_with('[') && token.value.ends_with(']'));
2084
token.value = token.value.offs(1, 1).trim(' ');
2085
size_t idx;
2086
if( ! from_chars(token.value, &idx))
2087
return NONE;
2088
if( ! is_container(r->closest))
2089
{
2090
if(has_key(r->closest))
2091
{
2092
csubstr k = key(r->closest);
2093
_clear_type(r->closest);
2094
to_seq(r->closest, k);
2095
}
2096
else
2097
{
2098
_clear_type(r->closest);
2099
to_seq(r->closest);
2100
}
2101
}
2102
_RYML_CB_ASSERT(m_callbacks, is_container(r->closest));
2103
node = child(r->closest, idx);
2104
if(node == NONE)
2105
{
2106
_RYML_CB_ASSERT(m_callbacks, num_children(r->closest) <= idx);
2107
for(size_t i = num_children(r->closest); i <= idx; ++i)
2108
{
2109
node = append_child(r->closest);
2110
if(i < idx)
2111
{
2112
if(is_map(r->closest))
2113
to_keyval(node, /*"~"*/{}, /*"~"*/{});
2114
else if(is_seq(r->closest))
2115
to_val(node, /*"~"*/{});
2116
}
2117
}
2118
}
2119
}
2120
else
2121
{
2122
C4_NEVER_REACH();
2123
}
2124
2125
_RYML_CB_ASSERT(m_callbacks, node != NONE);
2126
*parent = token;
2127
return node;
2128
}
2129
2130
/** types of tokens:
2131
* - seeing "map." ---> "map"/MAP
2132
* - finishing "scalar" ---> "scalar"/KEYVAL
2133
* - seeing "seq[n]" ---> "seq"/SEQ (--> "[n]"/KEY)
2134
* - seeing "[n]" ---> "[n]"/KEY
2135
*/
2136
Tree::_lookup_path_token Tree::_next_token(lookup_result *r, _lookup_path_token const& parent) const
2137
{
2138
csubstr unres = r->unresolved();
2139
if(unres.empty())
2140
return {};
2141
2142
// is it an indexation like [0], [1], etc?
2143
if(unres.begins_with('['))
2144
{
2145
size_t pos = unres.find(']');
2146
if(pos == csubstr::npos)
2147
return {};
2148
csubstr idx = unres.first(pos + 1);
2149
_advance(r, pos + 1);
2150
return {idx, KEY};
2151
}
2152
2153
// no. so it must be a name
2154
size_t pos = unres.first_of(".[");
2155
if(pos == csubstr::npos)
2156
{
2157
_advance(r, unres.len);
2158
NodeType t;
2159
if(( ! parent) || parent.type.is_seq())
2160
return {unres, VAL};
2161
return {unres, KEYVAL};
2162
}
2163
2164
// it's either a map or a seq
2165
_RYML_CB_ASSERT(m_callbacks, unres[pos] == '.' || unres[pos] == '[');
2166
if(unres[pos] == '.')
2167
{
2168
_RYML_CB_ASSERT(m_callbacks, pos != 0);
2169
_advance(r, pos + 1);
2170
return {unres.first(pos), MAP};
2171
}
2172
2173
_RYML_CB_ASSERT(m_callbacks, unres[pos] == '[');
2174
_advance(r, pos);
2175
return {unres.first(pos), SEQ};
2176
}
2177
2178
2179
} // namespace ryml
2180
} // namespace c4
2181
2182
2183
C4_SUPPRESS_WARNING_GCC_CLANG_POP
2184
C4_SUPPRESS_WARNING_MSVC_POP
2185
2186