| 617 | } |
| 618 | |
| 619 | bool FileContent::diffTree(NodeId root, const FileContent* oFc, NodeId oroot, |
| 620 | std::string* diff_out) const { |
| 621 | diff_out->clear(); |
| 622 | |
| 623 | const VObject& current1 = Object(root); |
| 624 | NodeId id1 = current1.m_child; |
| 625 | if (!id1) id1 = current1.m_sibling; |
| 626 | |
| 627 | const VObject& current2 = oFc->Object(oroot); |
| 628 | NodeId id2 = current2.m_child; |
| 629 | if (!id2) id2 = current2.m_sibling; |
| 630 | |
| 631 | if ((id1 && (!id2)) || ((!id1) && id2)) return true; |
| 632 | |
| 633 | std::stack<NodeId> stack1; |
| 634 | std::stack<NodeId> stack2; |
| 635 | stack1.emplace(id1); |
| 636 | stack2.emplace(id2); |
| 637 | while (!stack1.empty()) { |
| 638 | if (stack2.empty()) return true; |
| 639 | id1 = stack1.top(); |
| 640 | id2 = stack2.top(); |
| 641 | stack1.pop(); |
| 642 | stack2.pop(); |
| 643 | |
| 644 | const VObject& current1 = Object(id1); |
| 645 | const VObject& current2 = oFc->Object(id2); |
| 646 | |
| 647 | if (current1.m_type != current2.m_type) return true; |
| 648 | if ((current1.m_name || current2.m_name) && (Name(id1) != oFc->Name(id2))) { |
| 649 | return true; |
| 650 | } |
| 651 | |
| 652 | if (current1.m_sibling) stack1.emplace(current1.m_sibling); |
| 653 | if (current1.m_child) stack1.emplace(current1.m_child); |
| 654 | if (current2.m_sibling) stack2.emplace(current2.m_sibling); |
| 655 | if (current2.m_child) stack2.emplace(current2.m_child); |
| 656 | } |
| 657 | return !stack2.empty(); |
| 658 | } |
| 659 | |
| 660 | void FileContent::addDesignElement(std::string_view name, DesignElement* elem) { |
| 661 | m_elements.emplace_back(elem); |