| 593 | } |
| 594 | |
| 595 | PathMatcher::NodePtr PathMatcher::removeWalk( Node *node, const NameIterator &start, const NameIterator &end, bool shared, const bool prune, bool &removed ) |
| 596 | { |
| 597 | shared = shared || node->refCount() > 1; |
| 598 | NodePtr result; |
| 599 | |
| 600 | if( start == end ) |
| 601 | { |
| 602 | // we've found the end of the path we wish to remove. |
| 603 | if( prune ) |
| 604 | { |
| 605 | removed = writable( node, result, shared )->clearChildren(); |
| 606 | } |
| 607 | removed = removed || node->terminator; |
| 608 | writable( node, result, shared )->terminator = false; |
| 609 | /// \todo When we're pruning, we end up creating a new empty |
| 610 | /// node to return, just to signal to the caller that they |
| 611 | /// should erase the original child. We could use a single |
| 612 | /// shared instance for this return value instead of allocating |
| 613 | /// a new one with writable() all the time. |
| 614 | return result; |
| 615 | } |
| 616 | |
| 617 | Node::ChildMapIterator childIt = node->children.find( *start ); |
| 618 | if( childIt == node->children.end() ) |
| 619 | { |
| 620 | return result; |
| 621 | } |
| 622 | |
| 623 | Node *childNode = childIt->second.get(); |
| 624 | |
| 625 | NameIterator childStart = start; childStart++; |
| 626 | NodePtr newChild = removeWalk( childIt->second.get(), childStart, end, shared, prune, removed ); |
| 627 | |
| 628 | if( newChild && !newChild->isEmpty() ) |
| 629 | { |
| 630 | writable( node, result, shared )->children[childIt->first] = newChild; |
| 631 | } |
| 632 | else if( childNode->isEmpty() || ( newChild && newChild->isEmpty() ) ) |
| 633 | { |
| 634 | writable( node, result, shared )->children.erase( childIt->first ); |
| 635 | } |
| 636 | |
| 637 | return result; |
| 638 | } |
| 639 | |
| 640 | PathMatcher::NodePtr PathMatcher::addPathsWalk( Node *node, const Node *srcNode, bool shared, bool &added ) |
| 641 | { |