| 4424 | } |
| 4425 | |
| 4426 | PUGI__FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) |
| 4427 | { |
| 4428 | xml_allocator& alloc = get_allocator(dn); |
| 4429 | xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0; |
| 4430 | |
| 4431 | node_copy_contents(dn, sn, shared_alloc); |
| 4432 | |
| 4433 | xml_node_struct* dit = dn; |
| 4434 | xml_node_struct* sit = sn->first_child; |
| 4435 | |
| 4436 | while (sit && sit != sn) |
| 4437 | { |
| 4438 | // loop invariant: dit is inside the subtree rooted at dn |
| 4439 | assert(dit); |
| 4440 | |
| 4441 | // when a tree is copied into one of the descendants, we need to skip that subtree to avoid an infinite loop |
| 4442 | if (sit != dn) |
| 4443 | { |
| 4444 | xml_node_struct* copy = append_new_node(dit, alloc, PUGI__NODETYPE(sit)); |
| 4445 | |
| 4446 | if (copy) |
| 4447 | { |
| 4448 | node_copy_contents(copy, sit, shared_alloc); |
| 4449 | |
| 4450 | if (sit->first_child) |
| 4451 | { |
| 4452 | dit = copy; |
| 4453 | sit = sit->first_child; |
| 4454 | continue; |
| 4455 | } |
| 4456 | } |
| 4457 | } |
| 4458 | |
| 4459 | // continue to the next node |
| 4460 | do |
| 4461 | { |
| 4462 | if (sit->next_sibling) |
| 4463 | { |
| 4464 | sit = sit->next_sibling; |
| 4465 | break; |
| 4466 | } |
| 4467 | |
| 4468 | sit = sit->parent; |
| 4469 | dit = dit->parent; |
| 4470 | |
| 4471 | // loop invariant: dit is inside the subtree rooted at dn while sit is inside sn |
| 4472 | assert(sit == sn || dit); |
| 4473 | } |
| 4474 | while (sit != sn); |
| 4475 | } |
| 4476 | |
| 4477 | assert(!sit || dit == dn->parent); |
| 4478 | } |
| 4479 | |
| 4480 | PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) |
| 4481 | { |
no test coverage detected