tree.cpp (64502B)
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