Update tree to 3.1

see http://tree.phi-sci.com/download.html
This commit is contained in:
King_DuckZ 2016-10-31 19:41:50 +01:00
parent 8d2f7085c4
commit 09b41f6d0c
34 changed files with 333 additions and 29 deletions

View file

@ -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

View file

@ -1,2 +1,3 @@
a.out
*~
doxygen

View file

@ -1,3 +1,22 @@
2015-05-06 Kasper Peeters <kasper.peeters@phi-sci.com>
* Released 3.1
* Added asserts in 'subtree' in order to warn users about
constructing empty subtrees.
2014-12-25 Kasper Peeters <kasper.peeters@phi-sci.com>
* Released 3.0
* Added move constructor and move_out, move_in, move_in_as_nth_child.
2013-09-02 Kasper Peeters <kasper.peeters@aei.mpg.de>
* Released 2.9
* Added 'pre_order_iterator::next_skip_children()'.
2011-08-23 Kasper Peeters <kasper.peeters@aei.mpg.de>
* Brown paper bag release 2.81.

View file

@ -1,5 +1,5 @@
RELEASE=2.8
RELEASE=3.1
HTML=${HOME}/public_html/
.PHONY: doc tarball

View file

@ -76,7 +76,7 @@
and all other things referred to on this page) is contained in the
tarball</div>
<div class="filename">
<a href="tree-2.8.tar.gz">tree-2.8.tar.gz</a>
<a href="tree-2.81.tar.gz">tree-2.81.tar.gz</a>
</div>
<div class="text">
Feel free to copy the header <a href="tree.hh">tree.hh</a>

View file

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

Before

Width:  |  Height:  |  Size: 782 B

After

Width:  |  Height:  |  Size: 782 B

View file

Before

Width:  |  Height:  |  Size: 881 B

After

Width:  |  Height:  |  Size: 881 B

View file

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View file

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

Before

Width:  |  Height:  |  Size: 888 KiB

After

Width:  |  Height:  |  Size: 888 KiB

View file

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 141 KiB

View file

@ -1,3 +1,4 @@
*.o
*.res
test1
test2

View file

@ -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

View file

@ -1,3 +1,5 @@
#include <iostream>
#include "tree.hh"
#include "tree_util.hh"

111
lib/tree-3.1/src/test2.cc Normal file
View file

@ -0,0 +1,111 @@
#include <iostream>
#include "tree.hh"
#include "tree_util.hh"
tree<std::string> test_move_constructor()
{
tree<std::string> mtree;
tree<std::string>::iterator it = mtree.set_head("top");
mtree.append_child(it, "one");
mtree.append_child(it, "two");
mtree.append_child(it, "three");
tree<std::string> 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<std::string> test_move_out()
{
tree<std::string> mtree;
tree<std::string>::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<std::string>& other)
{
tree<std::string> mtree;
tree<std::string>::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<std::string> mtree, other;
tree<std::string>::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<std::string>& other)
{
tree<std::string> mtree;
tree<std::string>::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<std::string> res = test_move_constructor();
std::cout << "res:" << std::endl;
kptree::print_tree_bracketed(res);
// Move out.
tree<std::string> 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;
}
}

View file

@ -365,14 +365,8 @@ int main(int argc, char **argv)
++li;
}
// tree<std::string> testfixed;
// testfixed.insert(testfixed.begin(), "one");
// testfixed.insert(testfixed.begin(), "two");
// testfixed.insert(testfixed.begin(), "three");
// tree<std::string>::fixed_depth_iterator fit=testfixed.begin();
// while(testfixed.is_valid(fit)) {
// std::cout << *fit << std::endl;
// ++fit;
// }
// test_move_constructor();
}
}

View file

@ -1,18 +1,16 @@
// STL-like templated tree class.
//
// Copyright (C) 2001-2011 Kasper Peeters <kasper@phi-sci.com>
// Copyright (C) 2001-2014 Kasper Peeters <kasper@phi-sci.com>
// 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<T, tree_node_allocator>&);
tree(const tree<T, tree_node_allocator>&); // copy constructor
tree(tree<T, tree_node_allocator>&&); // move constructor
~tree();
tree<T,tree_node_allocator>& operator=(const tree<T, tree_node_allocator>&);
tree<T,tree_node_allocator>& operator=(const tree<T, tree_node_allocator>&); // copy assignment
tree<T,tree_node_allocator>& operator=(tree<T, tree_node_allocator>&&); // 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<typename iter> static iter parent(iter);
/// Return iterator to the previous sibling of a node.
template<typename iter> iter previous_sibling(iter) const;
template<typename iter> static iter previous_sibling(iter);
/// Return iterator to the next sibling of a node.
template<typename iter> iter next_sibling(iter) const;
template<typename iter> static iter next_sibling(iter);
/// Return iterator to the next node at a given depth.
template<typename iter> 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<typename iter> iter insert_subtree(iter position, const iterator_base& subtree);
/// Insert node as next sibling of node pointed to by position.
template<typename iter> 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<typename iter> 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<typename iter> iter move_in(iter, tree&);
/// As above, but now make the tree a child of the indicated node.
template<typename iter> iter move_in_below(iter, tree&);
/// As above, but now make the tree the nth child of the indicated node (if possible).
template<typename iter> 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<T, tree_node_allocator>::tree(const T& x)
set_head(x);
}
template <class T, class tree_node_allocator>
tree<T, tree_node_allocator>::tree(tree<T, tree_node_allocator>&& 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 <class T, class tree_node_allocator>
tree<T, tree_node_allocator>::tree(const iterator_base& other)
{
@ -533,6 +558,20 @@ tree<T,tree_node_allocator>& tree<T, tree_node_allocator>::operator=(const tree<
return *this;
}
template <class T, class tree_node_allocator>
tree<T,tree_node_allocator>& tree<T, tree_node_allocator>::operator=(tree<T, tree_node_allocator>&& 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 <class T, class tree_node_allocator>
tree<T, tree_node_allocator>::tree(const tree<T, tree_node_allocator>& other)
{
@ -770,7 +809,7 @@ iter tree<T, tree_node_allocator>::parent(iter position)
template <class T, class tree_node_allocator>
template <typename iter>
iter tree<T, tree_node_allocator>::previous_sibling(iter position) const
iter tree<T, tree_node_allocator>::previous_sibling(iter position)
{
assert(position.node!=0);
iter ret(position);
@ -780,7 +819,7 @@ iter tree<T, tree_node_allocator>::previous_sibling(iter position) const
template <class T, class tree_node_allocator>
template <typename iter>
iter tree<T, tree_node_allocator>::next_sibling(iter position) const
iter tree<T, tree_node_allocator>::next_sibling(iter position)
{
assert(position.node!=0);
iter ret(position);
@ -1477,6 +1516,126 @@ template <typename iter> iter tree<T, tree_node_allocator>::move_ontop(iter targ
return src;
}
template <class T, class tree_node_allocator>
tree<T, tree_node_allocator> tree<T, tree_node_allocator>::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 <class T, class tree_node_allocator>
template<typename iter> iter tree<T, tree_node_allocator>::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 <class T, class tree_node_allocator>
template<typename iter> iter tree<T, tree_node_allocator>::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 <class T, class tree_node_allocator>
void tree<T, tree_node_allocator>::merge(sibling_iterator to1, sibling_iterator to2,
sibling_iterator from1, sibling_iterator from2,
@ -1617,6 +1776,8 @@ bool tree<T, tree_node_allocator>::equal_subtree(const iter& one_, const iter& t
template <class T, class tree_node_allocator>
tree<T, tree_node_allocator> tree<T, tree_node_allocator>::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<T, tree_node_allocator> tree<T, tree_node_allocator>::subtree(sibling_itera
template <class T, class tree_node_allocator>
void tree<T, tree_node_allocator>::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<T, tree_node_allocator>::pre_order_iterator tree<T, tree_node_allo
return copy;
}
template <class T, class tree_node_allocator>
typename tree<T, tree_node_allocator>::pre_order_iterator& tree<T, tree_node_allocator>::pre_order_iterator::next_skip_children()
{
(*this).skip_children();
(*this)++;
return *this;
}
template <class T, class tree_node_allocator>
typename tree<T, tree_node_allocator>::pre_order_iterator tree<T, tree_node_allocator>::pre_order_iterator::operator--(int)
{