diff --git a/CMakeLists.txt b/CMakeLists.txt index 82e2367..db886c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,7 @@ include_directories(SYSTEM ${SDL2_INCLUDE_DIR} ${PNG_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - lib/tree-2.81/src + lib/tree-3.1/src ) include_directories( src diff --git a/lib/tree-2.81/.gitignore b/lib/tree-3.1/.gitignore similarity index 64% rename from lib/tree-2.81/.gitignore rename to lib/tree-3.1/.gitignore index 428bdc9..b64f8e6 100644 --- a/lib/tree-2.81/.gitignore +++ b/lib/tree-3.1/.gitignore @@ -1,2 +1,3 @@ +a.out *~ doxygen diff --git a/lib/tree-2.81/ChangeLog b/lib/tree-3.1/ChangeLog similarity index 96% rename from lib/tree-2.81/ChangeLog rename to lib/tree-3.1/ChangeLog index 9b05100..3067534 100644 --- a/lib/tree-2.81/ChangeLog +++ b/lib/tree-3.1/ChangeLog @@ -1,3 +1,22 @@ +2015-05-06 Kasper Peeters + + * Released 3.1 + + * Added asserts in 'subtree' in order to warn users about + constructing empty subtrees. + +2014-12-25 Kasper Peeters + + * Released 3.0 + + * Added move constructor and move_out, move_in, move_in_as_nth_child. + +2013-09-02 Kasper Peeters + + * Released 2.9 + + * Added 'pre_order_iterator::next_skip_children()'. + 2011-08-23 Kasper Peeters * Brown paper bag release 2.81. diff --git a/lib/tree-2.81/Makefile b/lib/tree-3.1/Makefile similarity index 98% rename from lib/tree-2.81/Makefile rename to lib/tree-3.1/Makefile index ee30472..7604ef8 100644 --- a/lib/tree-2.81/Makefile +++ b/lib/tree-3.1/Makefile @@ -1,5 +1,5 @@ -RELEASE=2.8 +RELEASE=3.1 HTML=${HOME}/public_html/ .PHONY: doc tarball diff --git a/lib/tree-2.81/doc/documentation.html b/lib/tree-3.1/doc/documentation.html similarity index 100% rename from lib/tree-2.81/doc/documentation.html rename to lib/tree-3.1/doc/documentation.html diff --git a/lib/tree-2.81/doc/download.html b/lib/tree-3.1/doc/download.html similarity index 99% rename from lib/tree-2.81/doc/download.html rename to lib/tree-3.1/doc/download.html index 4bb45a7..e121fc3 100644 --- a/lib/tree-2.81/doc/download.html +++ b/lib/tree-3.1/doc/download.html @@ -76,7 +76,7 @@ and all other things referred to on this page) is contained in the tarball
Feel free to copy the header tree.hh diff --git a/lib/tree-2.81/doc/doxygen_tree.config b/lib/tree-3.1/doc/doxygen_tree.config similarity index 100% rename from lib/tree-2.81/doc/doxygen_tree.config rename to lib/tree-3.1/doc/doxygen_tree.config diff --git a/lib/tree-2.81/doc/favicon.ico b/lib/tree-3.1/doc/favicon.ico similarity index 100% rename from lib/tree-2.81/doc/favicon.ico rename to lib/tree-3.1/doc/favicon.ico diff --git a/lib/tree-2.81/doc/favicon.png b/lib/tree-3.1/doc/favicon.png similarity index 100% rename from lib/tree-2.81/doc/favicon.png rename to lib/tree-3.1/doc/favicon.png diff --git a/lib/tree-2.81/doc/filler.png b/lib/tree-3.1/doc/filler.png similarity index 100% rename from lib/tree-2.81/doc/filler.png rename to lib/tree-3.1/doc/filler.png diff --git a/lib/tree-2.81/doc/index.html b/lib/tree-3.1/doc/index.html similarity index 100% rename from lib/tree-2.81/doc/index.html rename to lib/tree-3.1/doc/index.html diff --git a/lib/tree-2.81/doc/projects.html b/lib/tree-3.1/doc/projects.html similarity index 100% rename from lib/tree-2.81/doc/projects.html rename to lib/tree-3.1/doc/projects.html diff --git a/lib/tree-2.81/doc/structure.png b/lib/tree-3.1/doc/structure.png similarity index 100% rename from lib/tree-2.81/doc/structure.png rename to lib/tree-3.1/doc/structure.png diff --git a/lib/tree-2.81/doc/structure.svg b/lib/tree-3.1/doc/structure.svg similarity index 100% rename from lib/tree-2.81/doc/structure.svg rename to lib/tree-3.1/doc/structure.svg diff --git a/lib/tree-2.81/doc/tree.css b/lib/tree-3.1/doc/tree.css similarity index 100% rename from lib/tree-2.81/doc/tree.css rename to lib/tree-3.1/doc/tree.css diff --git a/lib/tree-2.81/doc/tree.jpg b/lib/tree-3.1/doc/tree.jpg similarity index 100% rename from lib/tree-2.81/doc/tree.jpg rename to lib/tree-3.1/doc/tree.jpg diff --git a/lib/tree-2.81/doc/tree.png b/lib/tree-3.1/doc/tree.png similarity index 100% rename from lib/tree-2.81/doc/tree.png rename to lib/tree-3.1/doc/tree.png diff --git a/lib/tree-2.81/doc/tree.tex b/lib/tree-3.1/doc/tree.tex similarity index 100% rename from lib/tree-2.81/doc/tree.tex rename to lib/tree-3.1/doc/tree.tex diff --git a/lib/tree-2.81/doc/tree2.png b/lib/tree-3.1/doc/tree2.png similarity index 100% rename from lib/tree-2.81/doc/tree2.png rename to lib/tree-3.1/doc/tree2.png diff --git a/lib/tree-2.81/doc/treefig.eps b/lib/tree-3.1/doc/treefig.eps similarity index 100% rename from lib/tree-2.81/doc/treefig.eps rename to lib/tree-3.1/doc/treefig.eps diff --git a/lib/tree-2.81/doc/treefig.fig b/lib/tree-3.1/doc/treefig.fig similarity index 100% rename from lib/tree-2.81/doc/treefig.fig rename to lib/tree-3.1/doc/treefig.fig diff --git a/lib/tree-2.81/doc/treefig.pdf b/lib/tree-3.1/doc/treefig.pdf similarity index 100% rename from lib/tree-2.81/doc/treefig.pdf rename to lib/tree-3.1/doc/treefig.pdf diff --git a/lib/tree-2.81/src/.gitignore b/lib/tree-3.1/src/.gitignore similarity index 72% rename from lib/tree-2.81/src/.gitignore rename to lib/tree-3.1/src/.gitignore index f0ef4c3..4c71a9a 100644 --- a/lib/tree-2.81/src/.gitignore +++ b/lib/tree-3.1/src/.gitignore @@ -1,3 +1,4 @@ *.o *.res test1 +test2 diff --git a/lib/tree-2.81/src/Makefile b/lib/tree-3.1/src/Makefile similarity index 61% rename from lib/tree-2.81/src/Makefile rename to lib/tree-3.1/src/Makefile index 7d1aba7..08dbdfa 100644 --- a/lib/tree-2.81/src/Makefile +++ b/lib/tree-3.1/src/Makefile @@ -1,10 +1,15 @@ -%.o: %.cc - g++ -c -I. $^ +all: test1 test2 + +%.o: %.cc + g++ -g -c -Wall -O2 -std=c++11 -I. $^ test1: test1.o g++ -o test1 test1.o +test2: test2.o + g++ -o test2 test2.o + run_tests: test1 test1.req ./test1 > test1.res @diff test1.res test1.req diff --git a/lib/tree-2.81/src/simple tree.hpp b/lib/tree-3.1/src/simple tree.hpp similarity index 100% rename from lib/tree-2.81/src/simple tree.hpp rename to lib/tree-3.1/src/simple tree.hpp diff --git a/lib/tree-2.81/src/test1.cc b/lib/tree-3.1/src/test1.cc similarity index 94% rename from lib/tree-2.81/src/test1.cc rename to lib/tree-3.1/src/test1.cc index 5bb2fdf..3f6151f 100644 --- a/lib/tree-2.81/src/test1.cc +++ b/lib/tree-3.1/src/test1.cc @@ -1,3 +1,5 @@ + +#include #include "tree.hh" #include "tree_util.hh" diff --git a/lib/tree-2.81/src/test1.req b/lib/tree-3.1/src/test1.req similarity index 100% rename from lib/tree-2.81/src/test1.req rename to lib/tree-3.1/src/test1.req diff --git a/lib/tree-3.1/src/test2.cc b/lib/tree-3.1/src/test2.cc new file mode 100644 index 0000000..62e3d71 --- /dev/null +++ b/lib/tree-3.1/src/test2.cc @@ -0,0 +1,111 @@ + +#include +#include "tree.hh" +#include "tree_util.hh" + +tree test_move_constructor() + { + tree mtree; + tree::iterator it = mtree.set_head("top"); + mtree.append_child(it, "one"); + mtree.append_child(it, "two"); + mtree.append_child(it, "three"); + + tree ctree(std::move(mtree)); + + std::cout << "ctree:" << std::endl; + kptree::print_tree_bracketed(ctree); + std::cout << "\nmtree:" << std::endl; + kptree::print_tree_bracketed(mtree); + + return ctree; + } + +tree test_move_out() + { + tree mtree; + tree::iterator it = mtree.set_head("top"); + mtree.append_child(it, "one"); + auto it2 = mtree.append_child(it, "two"); + mtree.append_child(it, "three"); + mtree.append_child(it2, "four"); + mtree.append_child(it2, "five"); + + auto ret = mtree.move_out(it2); + ret.debug_verify_consistency(); + return ret; + } + +void test_move_in(tree& other) + { + tree mtree; + tree::iterator it = mtree.set_head("top"); + mtree.append_child(it, "one"); + auto it3=mtree.append_child(it, "three"); + + mtree.move_in(it3, other); + mtree.debug_verify_consistency(); + kptree::print_tree_bracketed(mtree); + std::cout << "\n"; + } + +void test_move_in_as_nth_child(int n) + { + tree mtree, other; + tree::iterator it = mtree.set_head("top"); + mtree.append_child(it, "one"); + mtree.append_child(it, "three"); + + auto ot1 = other.set_head("hi"); + other.insert_after(ot1, "second"); + other.append_child(ot1, "1"); + other.append_child(ot1, "2"); + + mtree.move_in_as_nth_child(it, n, other); + mtree.debug_verify_consistency(); + kptree::print_tree_bracketed(mtree); + std::cout << "\n"; + } + +void test_move_below(tree& other) + { + tree mtree; + tree::iterator it = mtree.set_head("top"); + mtree.append_child(it, "one"); + auto it3=mtree.append_child(it, "three"); + + mtree.move_in(it3, other); + kptree::print_tree_bracketed(mtree); + } + + +int main(int argc, char **argv) + { + // Move constructor. + tree res = test_move_constructor(); + std::cout << "res:" << std::endl; + kptree::print_tree_bracketed(res); + + // Move out. + tree res2 = test_move_out(); + std::cout << "\nres2:" << std::endl; + kptree::print_tree_bracketed(res2); + std::cout << std::endl; + + // Move in. + test_move_in(res2); + std::cout << "\n"; + kptree::print_tree_bracketed(res2); + std::cout << "\n"; + + // Move in as nth child. + test_move_in_as_nth_child(0); + test_move_in_as_nth_child(1); + test_move_in_as_nth_child(2); + try { + test_move_in_as_nth_child(3); + } + catch(const std::range_error& ex) { + std::cout << ex.what() << std::endl; + } + } diff --git a/lib/tree-2.81/src/test_tree.cc b/lib/tree-3.1/src/test_tree.cc similarity index 97% rename from lib/tree-2.81/src/test_tree.cc rename to lib/tree-3.1/src/test_tree.cc index 6f1bf1c..1386c14 100644 --- a/lib/tree-2.81/src/test_tree.cc +++ b/lib/tree-3.1/src/test_tree.cc @@ -365,14 +365,8 @@ int main(int argc, char **argv) ++li; } -// tree testfixed; -// testfixed.insert(testfixed.begin(), "one"); -// testfixed.insert(testfixed.begin(), "two"); -// testfixed.insert(testfixed.begin(), "three"); -// tree::fixed_depth_iterator fit=testfixed.begin(); -// while(testfixed.is_valid(fit)) { -// std::cout << *fit << std::endl; -// ++fit; -// } +// test_move_constructor(); + } } + diff --git a/lib/tree-2.81/src/test_tree.output b/lib/tree-3.1/src/test_tree.output similarity index 100% rename from lib/tree-2.81/src/test_tree.output rename to lib/tree-3.1/src/test_tree.output diff --git a/lib/tree-2.81/src/tree.hh b/lib/tree-3.1/src/tree.hh similarity index 93% rename from lib/tree-2.81/src/tree.hh rename to lib/tree-3.1/src/tree.hh index b2f3005..0e82f16 100644 --- a/lib/tree-2.81/src/tree.hh +++ b/lib/tree-3.1/src/tree.hh @@ -1,18 +1,16 @@ // STL-like templated tree class. // -// Copyright (C) 2001-2011 Kasper Peeters +// Copyright (C) 2001-2014 Kasper Peeters // Distributed under the GNU General Public License version 3. // -// When used together with the htmlcxx library to create -// HTML::Node template instances, the GNU Lesser General Public -// version 2 applies. Special permission to use tree.hh under -// the LGPL for other projects can be requested from the author. +// Special permission to use tree.hh under the conditions of a +// different license can be requested from the author. /** \mainpage tree.hh \author Kasper Peeters - \version 2.81 - \date 23-Aug-2011 + \version 3.1 + \date 06-May-2015 \see http://tree.phi-sci.com/ \see http://tree.phi-sci.com/ChangeLog @@ -77,12 +75,14 @@ class tree { class sibling_iterator; class leaf_iterator; - tree(); - tree(const T&); + tree(); // empty constructor + tree(const T&); // constructor setting given element as head tree(const iterator_base&); - tree(const tree&); + tree(const tree&); // copy constructor + tree(tree&&); // move constructor ~tree(); - tree& operator=(const tree&); + tree& operator=(const tree&); // copy assignment + tree& operator=(tree&&); // move assignment /// Base class for iterators, only pointers stored, no traversal logic. #ifdef __SGI_STL_PORT @@ -134,6 +134,8 @@ class tree { pre_order_iterator operator--(int); pre_order_iterator& operator+=(unsigned int); pre_order_iterator& operator-=(unsigned int); + + pre_order_iterator& next_skip_children(); }; /// Depth-first iterator, first accessing the children, then the node itself. @@ -275,9 +277,9 @@ class tree { /// Return iterator to the parent of a node. template static iter parent(iter); /// Return iterator to the previous sibling of a node. - template iter previous_sibling(iter) const; + template static iter previous_sibling(iter); /// Return iterator to the next sibling of a node. - template iter next_sibling(iter) const; + template static iter next_sibling(iter); /// Return iterator to the next node at a given depth. template iter next_at_same_depth(iter) const; @@ -308,6 +310,7 @@ class tree { /// Specialisation of previous member. sibling_iterator insert(sibling_iterator position, const T& x); /// Insert node (with children) pointed to by subtree as previous sibling of node pointed to by position. + /// Does not change the subtree itself (use move_in or move_in_below for that). template iter insert_subtree(iter position, const iterator_base& subtree); /// Insert node as next sibling of node pointed to by position. template iter insert_after(iter position, const T& x); @@ -340,6 +343,16 @@ class tree { /// Move 'source' node (plus its children) to become the node at 'target' (erasing the node at 'target'). template iter move_ontop(iter target, iter source); + /// Extract the subtree starting at the indicated node, removing it from the original tree. + tree move_out(iterator); + /// Inverse of take_out: inserts the given tree as previous sibling of indicated node by a + /// move operation, that is, the given tree becomes empty. Returns iterator to the top node. + template iter move_in(iter, tree&); + /// As above, but now make the tree a child of the indicated node. + template iter move_in_below(iter, tree&); + /// As above, but now make the tree the nth child of the indicated node (if possible). + template iter move_in_as_nth_child(iter, size_t, tree&); + /// Merge with other tree, creating new branches and leaves only if they are not already present. void merge(sibling_iterator, sibling_iterator, sibling_iterator, sibling_iterator, bool duplicate_leaves=false); @@ -486,6 +499,18 @@ tree::tree(const T& x) set_head(x); } +template +tree::tree(tree&& x) + { + head_initialise_(); + head->next_sibling=x.head->next_sibling; + feet->prev_sibling=x.head->prev_sibling; + x.head->next_sibling->prev_sibling=head; + x.feet->prev_sibling->next_sibling=feet; + x.head->next_sibling=x.feet; + x.feet->prev_sibling=x.head; + } + template tree::tree(const iterator_base& other) { @@ -533,6 +558,20 @@ tree& tree::operator=(const tree< return *this; } +template +tree& tree::operator=(tree&& x) + { + if(this != &x) { + head->next_sibling=x.head->next_sibling; + feet->prev_sibling=x.head->prev_sibling; + x.head->next_sibling->prev_sibling=head; + x.feet->prev_sibling->next_sibling=feet; + x.head->next_sibling=x.feet; + x.feet->prev_sibling=x.head; + } + return *this; + } + template tree::tree(const tree& other) { @@ -770,7 +809,7 @@ iter tree::parent(iter position) template template -iter tree::previous_sibling(iter position) const +iter tree::previous_sibling(iter position) { assert(position.node!=0); iter ret(position); @@ -780,7 +819,7 @@ iter tree::previous_sibling(iter position) const template template -iter tree::next_sibling(iter position) const +iter tree::next_sibling(iter position) { assert(position.node!=0); iter ret(position); @@ -1477,6 +1516,126 @@ template iter tree::move_ontop(iter targ return src; } + +template +tree tree::move_out(iterator source) + { + tree ret; + + // Move source node into the 'ret' tree. + ret.head->next_sibling = source.node; + ret.feet->prev_sibling = source.node; + source.node->parent=0; + + // Close the links in the current tree. + if(source.node->prev_sibling!=0) + source.node->prev_sibling->next_sibling = source.node->next_sibling; + + if(source.node->next_sibling!=0) + source.node->next_sibling->prev_sibling = source.node->prev_sibling; + + // Fix source prev/next links. + source.node->prev_sibling = ret.head; + source.node->next_sibling = ret.feet; + + return ret; // A good compiler will move this, not copy. + } + +template +template iter tree::move_in(iter loc, tree& other) + { + if(other.head->next_sibling==other.feet) return loc; // other tree is empty + + tree_node *other_first_head = other.head->next_sibling; + tree_node *other_last_head = other.feet->prev_sibling; + + sibling_iterator prev(loc); + --prev; + + prev.node->next_sibling = other_first_head; + loc.node->prev_sibling = other_last_head; + other_first_head->prev_sibling = prev.node; + other_last_head->next_sibling = loc.node; + + // Adjust parent pointers. + tree_node *walk=other_first_head; + while(true) { + walk->parent=loc.node->parent; + if(walk==other_last_head) + break; + walk=walk->next_sibling; + } + + // Close other tree. + other.head->next_sibling=other.feet; + other.feet->prev_sibling=other.head; + + return other_first_head; + } + +template +template iter tree::move_in_as_nth_child(iter loc, size_t n, tree& other) + { + if(other.head->next_sibling==other.feet) return loc; // other tree is empty + + tree_node *other_first_head = other.head->next_sibling; + tree_node *other_last_head = other.feet->prev_sibling; + + if(n==0) { + if(loc.node->first_child==0) { + loc.node->first_child=other_first_head; + loc.node->last_child=other_last_head; + other_last_head->next_sibling=0; + other_first_head->prev_sibling=0; + } + else { + loc.node->first_child->prev_sibling=other_last_head; + other_last_head->next_sibling=loc.node->first_child; + loc.node->first_child=other_first_head; + other_first_head->prev_sibling=0; + } + } + else { + --n; + tree_node *walk = loc.node->first_child; + while(true) { + if(walk==0) + throw std::range_error("tree: move_in_as_nth_child position " + +std::to_string(n+1) + +" out of range; only " + +std::to_string(number_of_children(loc)) + +" child nodes present"); + if(n==0) + break; + --n; + walk = walk->next_sibling; + } + if(walk->next_sibling==0) + loc.node->last_child=other_last_head; + else + walk->next_sibling->prev_sibling=other_last_head; + other_last_head->next_sibling=walk->next_sibling; + walk->next_sibling=other_first_head; + other_first_head->prev_sibling=walk; + } + + // Adjust parent pointers. + tree_node *walk=other_first_head; + while(true) { + walk->parent=loc.node; + if(walk==other_last_head) + break; + walk=walk->next_sibling; + } + + // Close other tree. + other.head->next_sibling=other.feet; + other.feet->prev_sibling=other.head; + + return other_first_head; + } + + template void tree::merge(sibling_iterator to1, sibling_iterator to2, sibling_iterator from1, sibling_iterator from2, @@ -1617,6 +1776,8 @@ bool tree::equal_subtree(const iter& one_, const iter& t template tree tree::subtree(sibling_iterator from, sibling_iterator to) const { + assert(from!=to); // if from==to, the range is empty, hence no tree to return. + tree tmp; tmp.set_head(value_type()); tmp.replace(tmp.begin(), tmp.end(), from, to); @@ -1626,6 +1787,8 @@ tree tree::subtree(sibling_itera template void tree::subtree(tree& tmp, sibling_iterator from, sibling_iterator to) const { + assert(from!=to); // if from==to, the range is empty, hence no tree to return. + tmp.set_head(value_type()); tmp.replace(tmp.begin(), tmp.end(), from, to); } @@ -2160,6 +2323,14 @@ typename tree::pre_order_iterator tree +typename tree::pre_order_iterator& tree::pre_order_iterator::next_skip_children() + { + (*this).skip_children(); + (*this)++; + return *this; + } + template typename tree::pre_order_iterator tree::pre_order_iterator::operator--(int) { diff --git a/lib/tree-2.81/src/tree_example.cc b/lib/tree-3.1/src/tree_example.cc similarity index 100% rename from lib/tree-2.81/src/tree_example.cc rename to lib/tree-3.1/src/tree_example.cc diff --git a/lib/tree-2.81/src/tree_util.hh b/lib/tree-3.1/src/tree_util.hh similarity index 100% rename from lib/tree-2.81/src/tree_util.hh rename to lib/tree-3.1/src/tree_util.hh diff --git a/lib/tree-2.81/src/xinlin.hh b/lib/tree-3.1/src/xinlin.hh similarity index 100% rename from lib/tree-2.81/src/xinlin.hh rename to lib/tree-3.1/src/xinlin.hh