commit 95499e3d7739056c86fccfe8e8a79365f3728882 Author: King_DuckZ Date: Mon Oct 24 00:48:30 2016 +0200 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a49039 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +compile_commands.json +.ycm_extra_conf.py diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5faa891 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/vectorwrapper"] + path = lib/vectorwrapper + url = ../vectorwrapper/.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f009c33 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,97 @@ +cmake_minimum_required(VERSION 3.2) +project(mycurry CXX) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/include") + +include(TargetArch) +include(FindPkgConfig) + +set(common_gcc_flags "-Wall -Wextra -pedantic") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${common_gcc_flags}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${common_gcc_flags}") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${common_gcc_flags}") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${common_gcc_flags}") + +option(CURRY_FORCE_OPENGLES "Try to chose the openGL ES renderer if available. Enable this on Raspberry Pi" OFF) +option(CURRY_RASPBERRY_PI "Compile for Raspberry Pi" OFF) + +target_architecture(TARGET_ARCH) +message (STATUS "Target architecture: ${TARGET_ARCH}") + +if (TARGET_ARCH MATCHES "^x86_64$") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -msse3") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -msse3") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -msse3") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -msse3") +endif (TARGET_ARCH MATCHES "^x86_64$") + +if (CURRY_FORCE_OPENGLES OR CURRY_RASPBERRY_PI) + add_definitions(-DFORCE_OPENGLES) + if (CURRY_RASPBERRY_PI) + add_definitions(-DRASPBERRY_PI) + endif(CURRY_RASPBERRY_PI) +endif (CURRY_FORCE_OPENGLES OR CURRY_RASPBERRY_PI) + +PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2) +find_package(PNG REQUIRED) +find_package(Boost 1.55.0 REQUIRED) + +if (CURRY_RASPBERRY_PI) + message(STATUS "Will build for Raspberry Pi") + include_directories(SYSTEM + /opt/vc/include + /opt/vc/include/interface/vcos/pthreads + /opt/vc/include/interface/vmcs_host/linux + ) + link_directories( + /opt/vc/lib + ) +endif (CURRY_RASPBERRY_PI) + +add_executable(${PROJECT_NAME} + src/main.cpp + src/sdlmain.cpp + src/ingamescene.cpp + src/sizenotifiable.cpp + src/sizeratio.cpp +) + +target_include_directories(${PROJECT_NAME} SYSTEM + PRIVATE ${SDL2_INCLUDE_DIR} + PRIVATE ${PNG_INCLUDE_DIRS} + PRIVATE ${Boost_INCLUDE_DIRS} + PRIVATE lib/tree-2.81/src +) +target_include_directories(${PROJECT_NAME} + PRIVATE src + PRIVATE lib/vectorwrapper/include +) + +target_link_libraries(${PROJECT_NAME} + PRIVATE ${SDL2_LIBRARIES} + PRIVATE ${PNG_LIBRARIES} +) + +if (CURRY_RASPBERRY_PI) + target_link_libraries(${PROJECT_NAME} + PRIVATE bcm_host + ) +endif(CURRY_RASPBERRY_PI) + +target_compile_features(${PROJECT_NAME} + PRIVATE cxx_nullptr + PRIVATE cxx_range_for + PRIVATE cxx_lambdas + PRIVATE cxx_decltype_auto + PRIVATE cxx_defaulted_functions + PRIVATE cxx_deleted_functions + PRIVATE cxx_auto_type + PRIVATE cxx_defaulted_move_initializers + PRIVATE cxx_noexcept + PRIVATE cxx_rvalue_references +) + +target_compile_definitions(${PROJECT_NAME} + PRIVATE ${PNG_DEFINITIONS} +) + diff --git a/cmake/include/TargetArch.cmake b/cmake/include/TargetArch.cmake new file mode 100644 index 0000000..3761e4d --- /dev/null +++ b/cmake/include/TargetArch.cmake @@ -0,0 +1,134 @@ +# Based on the Qt 5 processor detection code, so should be very accurate +# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h +# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64) + +# Regarding POWER/PowerPC, just as is noted in the Qt source, +# "There are many more known variants/revisions that we do not handle/detect." + +set(archdetect_c_code " +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) + #if defined(__ARM_ARCH_7__) \\ + || defined(__ARM_ARCH_7A__) \\ + || defined(__ARM_ARCH_7R__) \\ + || defined(__ARM_ARCH_7M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) + #error cmake_ARCH armv7 + #elif defined(__ARM_ARCH_6__) \\ + || defined(__ARM_ARCH_6J__) \\ + || defined(__ARM_ARCH_6T2__) \\ + || defined(__ARM_ARCH_6Z__) \\ + || defined(__ARM_ARCH_6K__) \\ + || defined(__ARM_ARCH_6ZK__) \\ + || defined(__ARM_ARCH_6M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) + #error cmake_ARCH armv6 + #elif defined(__ARM_ARCH_5TEJ__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) + #error cmake_ARCH armv5 + #else + #error cmake_ARCH arm + #endif +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) + #error cmake_ARCH i386 +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) + #error cmake_ARCH x86_64 +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) + #error cmake_ARCH ia64 +#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\ + || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\ + || defined(_M_MPPC) || defined(_M_PPC) + #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) + #error cmake_ARCH ppc64 + #else + #error cmake_ARCH ppc + #endif +#endif + +#error cmake_ARCH unknown +") + +# Set ppc_support to TRUE before including this file or ppc and ppc64 +# will be treated as invalid architectures since they are no longer supported by Apple + +function(target_architecture output_var) + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + # On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set + # First let's normalize the order of the values + + # Note that it's not possible to compile PowerPC applications if you are using + # the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we + # disable it by default + # See this page for more information: + # http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4 + + # Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime. + # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise. + + foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) + if("${osx_arch}" STREQUAL "ppc" AND ppc_support) + set(osx_arch_ppc TRUE) + elseif("${osx_arch}" STREQUAL "i386") + set(osx_arch_i386 TRUE) + elseif("${osx_arch}" STREQUAL "x86_64") + set(osx_arch_x86_64 TRUE) + elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support) + set(osx_arch_ppc64 TRUE) + else() + message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}") + endif() + endforeach() + + # Now add all the architectures in our normalized order + if(osx_arch_ppc) + list(APPEND ARCH ppc) + endif() + + if(osx_arch_i386) + list(APPEND ARCH i386) + endif() + + if(osx_arch_x86_64) + list(APPEND ARCH x86_64) + endif() + + if(osx_arch_ppc64) + list(APPEND ARCH ppc64) + endif() + else() + file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}") + + enable_language(C) + + # Detect the architecture in a rather creative way... + # This compiles a small C program which is a series of ifdefs that selects a + # particular #error preprocessor directive whose message string contains the + # target architecture. The program will always fail to compile (both because + # file is not a valid C program, and obviously because of the presence of the + # #error preprocessor directives... but by exploiting the preprocessor in this + # way, we can detect the correct target architecture even when cross-compiling, + # since the program itself never needs to be run (only the compiler/preprocessor) + try_run( + run_result_unused + compile_result_unused + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/arch.c" + COMPILE_OUTPUT_VARIABLE ARCH + CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} + ) + + # Parse the architecture name from the compiler output + string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}") + + # Get rid of the value marker leaving just the architecture name + string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}") + + # If we are compiling with an unknown architecture this variable should + # already be set to "unknown" but in the case that it's empty (i.e. due + # to a typo in the code), then set it to unknown + if (NOT ARCH) + set(ARCH unknown) + endif() + endif() + + set(${output_var} "${ARCH}" PARENT_SCOPE) +endfunction() diff --git a/lib/tree-2.81/ChangeLog b/lib/tree-2.81/ChangeLog new file mode 100644 index 0000000..9b05100 --- /dev/null +++ b/lib/tree-2.81/ChangeLog @@ -0,0 +1,391 @@ +2011-08-23 Kasper Peeters + + * Brown paper bag release 2.81. + +2011-08-23 Kasper Peeters + + * Released 2.8 + + * License updated. + +2010-12-24 Kasper Peeters + + * Added a number of asserts to trip when passing invalid iterators + to append_child/prepend_child members. + +2010-03-24 Kasper Peeters + + * Released 2.70 + + * Fixed handling of std::allocator to make it more likely to work + on non-GNU platforms. + +2009-12-28 Kasper Peeters + + * Fixed the operator= return type and handled self-assignment + (thanks to Xinlin Cao for the fix). + +2009-05-05 Kasper Peeters + + * Released 2.65 + + * Added skip_children(bool), fixed post-increment/decrement + operators to not refer to 'n' anymore. + +2009-04-03 Kasper Peeters + + * Added a sibling member for quick access to the n-th sibling + (thanks to Adam Connell for sending the patch). + +2009-03-06 Kasper Peeters + + * Fixed an old bug in compare_nodes (pointed out to me in 2005 but + never fixed properly...) + +2008-08-28 Kasper Peeters + + * Released 2.62 + + * Changed the behaviour of max_depth() so that it returns -1 for + an empty tree, instead of bailing out with an error (strictly + speaking max_depth should be undefined...). + +2008-08-26 Kasper Peeters + + * Released 2.61 + + * Fixed a bug in max_depth() which would fail on trees with more + than one head node (thanks to Marc Noirot for pointing this out). + +2008-08-23 Kasper Peeters + + * Released 2.60 + + * Fixed several problems with fixed_depth iterators: iterating + beyond the top node now disabled and operator-- fixed. + +2008-07-25 Kasper Peeters + + * Made 'child()' static. + +2008-07-20 Kasper Peeters + + * Released 2.54 + + * Changed size() members to return size_t instead of unsigned int. + + * Changed behaviour of operator++ for leaf_iterator so that it can + be used in situations where new leaves get added during iteration. + +2008-06-30 Kasper Peeters + + * Released 2.52 + + * Made depth member function static so it can be used independent + of an actual tree, and added a version with two iterators to + measure depths relative to a different node. + +2008-02-28 Kasper Peeters + + * Released 2.51 + + * Added a top node to leaf_iterators, so that they can be + instructed to iterate only over the leaves of a given node. + +2007-10-19 Kasper Peeters + + * Released 2.4. + +2007-10-18 Kasper Peeters + + * Added max_depth() members. + + * Fixed a bug in begin_fixed() which would fail on + + A + / \ + B C + / \ + D E + / \ + F G + + when asked for the first node at depth 3 from 'A' (since it + failed to go back up the tree from 'D'). + +2007-08-21 Kasper Peeters + + * Released 2.31. + + * Added GPL version 3 licensing as an option. + +2007-01-19 Kasper Peeters + + * Fixed a bug in "replace" which appeared when trying to replace a + head node (it tried to access the parent). + +2006-11-29 Kasper Peeters + + * Release 2.3. + + Fixed a bug in number_of_siblings which only counted siblings in + one direction (thanks to Fanzhe Cui for pointing this out). + +2006-08-20 Kasper Peeters + + * Released 2.2. + + * Added operator== and operator!= for fixed_depth_iterator. + +2006-08-07 Kasper Peeters + + * Released 2.1. + + * Added leaf iterators, code contributed by Peter Wienemann. + + * Fixed a bug in is_valid (thanks to Antonio Morillas). 1.131. + +2006-07-19 Kasper Peeters + + * Fixed bugs in move_before and move_after which would show up + when the node was already in the right place. 1.130. + +2006-03-02 Kasper Peeters + + * Added the "wrap" member function. + +2006-03-01 Kasper Peeters + + * Added a simple queue-based breadth-first iterator. + +2006-01-31 Kasper Peeters + + * Fixed move_before to work when the target is a sibling_iterator + pointing to the end of a range of siblings. + +2005-11-20 Kasper Peeters + + * Added move_after, which for some mysterious reason was + missing. Thanks to Dennis Jones for pointing this out. + + * Fixed a bug in operator++ for post_order iterators + (skip_children could remain set if no next sibling present). + Thanks to Ohad for pointing out the bug. + +2005-10-12 Kasper Peeters + + * Fixed a bug in the 'sort' member which takes a Comparator + function object (thanks to Robin Taylor for the patch). + +2005-09-14 Kasper Peeters + + * Doxygen documentation added, plus a new web page. + +2004-11-05 Kasper Peeters + + * Fixed a bug which shows up when inserting nodes at the top of + the tree (thanks to Matthias Bernt for pointing me to this one). + +2004-07-21 Kasper Peeters + + * Fixed kp::destructor -> destructor. + + * Moved body of 'compare_nodes::operator()' into the class + declaration in order to satisfy buggy Borland compilers (and stop + regular email messages about this problem). + + * Fixed a completely buggy number_of_siblings() (thanks to Caleb + Epstein for the patch). + +2004-02-04 Kasper Peeters + + * Released 1.106 + + * Fixed a bug in insert(sibling_iterator, const T&) (thanks to + Maxim Yegorushkin for the patch). + +2003-11-21 Kasper Peeters + + * Put some things in a namespace to avoid clashes with other + libraries. + +2003-10-13 Kasper Peeters + + * Released 1.102. + + * Fixed return type of postincrement/decrement operators (thanks + to Yevhen Tymokhin for pointing this out). + +2003-09-18 Kasper Peeters + + * Fixes for standard compliance, as required to compile with + gcc 3.4 and later. + +2003-08-12 Kasper Peeters + + * Added 'empty' member (patch by Michael Vogt). + +2003-08-01 + + * Released 1.95 + + * Fixed two bugs in sort (which were corrupting the tree); thanks + to Michael Vogt for informing me about the problem. + +2003-07-17 + + * Added a hack to enable compilation with STLport. + +2003-07-11 + + * Released 1.90 + + * Added postfix increment and decrement operators; thanks to + Claudio Andreatta for sending the patch. + + * Fixed a bug in reparent(iter pos, iter from). Thanks to Claudio + Andreatta for fixing this. + +2003-06-25 Kasper Peeters + + * Many bug fixes for fixed depth iterators, thanks to Ruben + Niederhagen for pointing out several problems (a few still exist, + see the 'TODO' part of tree.hh). + +2003-04-17 Kasper Peeters + + * Released 1.85 + + * Corrected return type of operator++ and friends. + + * Added preliminary support for 'fixed_depth_iterator' to iterate + over children at a given level. Not quite finished yet, sorry. + +2003-03-24 Kasper Peeters + + * Released 1.83 + + * Changed return type of 'child' member function to be a sibling + iterator instead of a reference to the actual node (sorry for the + incompatibility with previous versions). Change also propagated to + tree_msvc.hh. + +2003-02-07 + + * Released 1.80 + + * Fixed another bug in sort (thanks to Tony Cook for fixing this + bug). + +2003-01-29 Kasper Peeters + + * Released 1.78. + + * Fixed a bug in sort, which resulted in a corrupt tree (thanks to + Michael Vogt for fixing this bug). + +2003-01-07 Kasper Peeters + + * Released 1.75 and msvc version 1.72 + + * Fixed a wrongly specialised 'insert' method for + sibling_iterators (thanks to Tony Cook for pointing this out). + +2002-11-15 Kasper Peeters + + * Released 1.72 + + * Fixed a bug in 'index' when called on nodes at the top level of + the tree (thanks to David Zajic for the bug report). Be warned + that the top level is a bit special at the moment; the end + sibling_iterator is ill-defined for siblings there (to be fixed in + a future version). + +2002-10-31 Kasper Peeters + + * Released 1.70. + + * Finished the merge algorithm, updated the documentation with + examples about its use, and added a test-case to the test_tree.cc + program. + + * Fixed a bug in pre_order_iterator::operator--. + +2002-10-20 Kasper Peeters + + * Released 1.66. + +2002-10-15 Kasper Peeters + + * Code for post_order_iterator implemented. + +2002-10-13 Kasper Peeters + + * Rewrote large parts of the code to allow for multiple iterator + types, such as pre_order_iterator (which was the previous iterator + type), post_order_iterator and so on. This required small changes + to the interface, the most visible one being + + - insert(iterator, iterator) for the insertion of a subtree + is now called insert_subtree(iterator, iterator). + + Apologies if this breaks your code. + +2002-10-11 Kasper Peeters + + * Removed '(void)' type declarations in favour of the C++ standard + empty brackets '()'. + +2002-10-10 Kasper Peeters + + * Added 'index' in response to a discussion on the Boost mailing + list. + +2002-10-03 Kasper Peeters + + * reparent(iterator,sibling_iterator,sibling_iterator) now accepts + an empty range, in which case it does nothing (request by Jos de + Laender). + + * Fixed a bug in the iterator(sibling_iterator) constructor + (thanks to Jos de Laender for pointing this out). + +2002-09-04 Kasper Peeters + + * Fixed a bug in insert_after (thanks to Carl Blanchette for the + patch). + +2002-08-29 Kasper Peeters + + * The problem in test_tree of the previous item was actually do to + tree::end(iterator) returning the end of the tree, not the end of + the current sibling list. Fixed now, released 1.55. + +2002-08-26 Kasper Peeters + + * Released 1.54. + + * Printing a single-node tree in test_tree would result in a + segfault; more robust now (thanks to Yutaka Sato for the bug + report). + +2002-05-07 Kasper Peeters + + * Fixed a bug in "sort" which would remove duplicate nodes altogether. + +2002-03-24 Kasper Peeters + + * Added "append_child" without child argument, to add empty child + node. + +2002-05-04 Kasper Peeters + + * Released 1.45. + + * Removed restriction of having only a single node at the top of + the tree (associated with this, the top nodes should now be inserted + with "insert", not with "append_child"). + + * Fixes for ISO compatibility (now works with gcc-3.1). Thanks to + Olivier Verdier. + diff --git a/lib/tree-2.81/Makefile b/lib/tree-2.81/Makefile new file mode 100644 index 0000000..ee30472 --- /dev/null +++ b/lib/tree-2.81/Makefile @@ -0,0 +1,27 @@ + +RELEASE=2.8 +HTML=${HOME}/public_html/ + +.PHONY: doc tarball + +tarball: + git archive --format=tar --prefix=tree-${RELEASE}/ HEAD | gzip > ${HOME}/tmp/tree-${RELEASE}.tar.gz + +site: tarball doc + install -d ${HTML}/tree + install -d ${HTML}/tree/doxygen/html + install doc/index.html doc/tree.css doc/tree.jpg ChangeLog ${HTML}/tree + install src/test_tree.cc src/test_tree.output src/tree_example.cc src/tree.hh src/tree_util.hh ${HTML}/tree + install doxygen/html/* ${HTML}/tree/doxygen/html + install ${HOME}/tmp/tree-${RELEASE}.tar.gz ${HTML}/tree + install ${HOME}/tmp/kt_temp/kt_temp_tree/tree.pdf ${HTML}/tree + +upload: + rsync -avz ${HTML}/tree/ zmaya:tree + +doc: + (cd doc; kt -f tree.tex) + doxygen doc/doxygen_tree.config + +test_tree: test_tree.o + g++ -o test_tree test_tree.o diff --git a/lib/tree-2.81/doc/documentation.html b/lib/tree-2.81/doc/documentation.html new file mode 100644 index 0000000..59d3226 --- /dev/null +++ b/lib/tree-2.81/doc/documentation.html @@ -0,0 +1,220 @@ + + + + + + + +tree.hh: an STL-like C++ tree class, documentation + + + +
+
+
+ +Bookmark and Share + +
+
+ [background image] +
+
+

tree.hh: an STL-like C++ tree class

+

+ Kasper Peeters, kasper.peeters (at) phi-sci.com +

+
+
+ + + + + +
+ + + +

Data structure overview

+ +
The data structure of the tree class is depicted + below (see the documentation for more detailed information). + Each node contains a pointer to the first and last child element, + and each child contains pointers to its previous and next sibling: + [structure
+		  diagram] +
+ +
+ Iterators come in various types. The normal iterator iterates depth-first + over all nodes. The beginning and end of the tree can be obtained by using the + begin() and end() members. The other type of iterator + only iterates over the nodes at one given depth (ie. over all siblings). One + typically uses these iterators to iterate over all children of a node, in which + case the [begin,end) range can be obtained by calling begin(iterator) + and end(iterator).
+ +
Iterators can be converted from one type to the other; this includes the `end' + iterators (all intervals are as usual closed at the beginning and open + at the end).
+ +

Sample program

+ +
+ Here is a small sample program to illustrate + how tree.hh is used in practise. + +
+
#include <algorithm>
+#include <string>
+#include <iostream>
+#include "tree.hh"
+
+using namespace std;
+
+int main(int, char **)
+   {
+   tree<string> tr;
+   tree<string>::iterator top, one, two, loc, banana;
+   
+   top=tr.begin();
+   one=tr.insert(top, "one");
+   two=tr.append_child(one, "two");
+   tr.append_child(two, "apple");
+   banana=tr.append_child(two, "banana");
+   tr.append_child(banana,"cherry");
+   tr.append_child(two, "peach");
+   tr.append_child(one,"three");
+   
+   loc=find(tr.begin(), tr.end(), "two");
+   if(loc!=tr.end()) {
+   tree<string>::sibling_iterator sib=tr.begin(loc);
+   while(sib!=tr.end(loc)) {
+     cout << (*sib) << endl;
+     ++sib;
+     }
+   cout << endl;
+   tree<string>::iterator sib2=tr.begin(loc);
+   tree<string>::iterator end2=tr.end(loc);
+   while(sib2!=end2) {
+     for(int i=0; i<tr.depth(sib2)-2; ++i) 
+        cout << " ";
+     cout << (*sib2) << endl;
+     ++sib2;
+     }
+   }
+}
+
+ The output of this program is +
+
apple
+banana
+peach
+
+apple
+banana
+ cherry
+peach
+
+ Note that this example only has one element at the + top of the tree (in this case that is the node containing "one") but + it is possible to have an arbitary number of such elements (then the + tree is more like a "bush"). Observe the way in which the two types of + iterators work. The first block of output, obtained using the + sibling_iterator, only displays the children directly below "two". The + second block iterates over all children at any depth below "two". In + the second output block, the depth member has been used + to determine the distance of a given node to the root of the + tree. +
+ +

API documentation

+ +
+ Documentation is available in the form of + a pdf file. This file is also available + in the tarball as a LaTeX file. Further information can be + obtained by reading the test program (included in the + distribution). Also look at the simple + example below. +
+ +
+ The most complete documentation of the interface is always + available in the doxygen + generated documentation. +
+
+ +
+ +

+ + Valid XHTML 1.0 Strict +

+ + + + + + + + +
+ + + diff --git a/lib/tree-2.81/doc/download.html b/lib/tree-2.81/doc/download.html new file mode 100644 index 0000000..4bb45a7 --- /dev/null +++ b/lib/tree-2.81/doc/download.html @@ -0,0 +1,175 @@ + + + + + + + +tree.hh: an STL-like C++ tree class, download + + + +
+
+
+ +Bookmark and Share + +
+
+ [background image] +
+
+

tree.hh: an STL-like C++ tree class

+

+ Kasper Peeters, kasper.peeters (at) phi-sci.com +

+
+
+ + + + + +
+ + + +

Download

+ +
Everything (the header file, examples, documentation + and all other things referred to on this page) is contained in the + tarball
+ +
+ Feel free to copy the header tree.hh + (which is all you need code-wise) into your own source + directory as long as you respect the license (see above). +
+ +
+ The list of changes can be found in the ChangeLog. +
+ +
+ There is a small utility + library tree_util.hh originally + written by Linda Buisman. This library contains a number of + functions to output a tree as text, to aid in debugging your + project. +
+ +
The current version works with GNU gcc 3.x and + higher, Borland C++ builder and Microsoft Visual C++ 7.1 and + higher (I no longer support older versions of Visual C++). It is + compatible with STLport (though older versions may not work + correctly, best to upgrade to something fairly recent). +
+ +
The library is available for free, but if it + helps you a lot, why not consider a small donation? + + Your contribution is greatly appreciated! +
+ + +

Installation

+ +
+ No installation is required as the tree.hh library is + contained in the single header file tree.hh. Just copy it into + your source directory (and upgrade it from the master site + when a new version becomes available). +
+ +
+ +
+ +

+ + Valid XHTML 1.0 Strict +

+ + + + + + + + +
+ + + diff --git a/lib/tree-2.81/doc/doxygen_tree.config b/lib/tree-2.81/doc/doxygen_tree.config new file mode 100644 index 0000000..5095e07 --- /dev/null +++ b/lib/tree-2.81/doc/doxygen_tree.config @@ -0,0 +1,270 @@ +# Doxyfile 1.4.4 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = tree +PROJECT_NUMBER = "release 2.0" +OUTPUT_DIRECTORY = doxygen +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = src/tree.hh +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/lib/tree-2.81/doc/favicon.ico b/lib/tree-2.81/doc/favicon.ico new file mode 100644 index 0000000..4eb6ffe Binary files /dev/null and b/lib/tree-2.81/doc/favicon.ico differ diff --git a/lib/tree-2.81/doc/favicon.png b/lib/tree-2.81/doc/favicon.png new file mode 100644 index 0000000..69d16b3 Binary files /dev/null and b/lib/tree-2.81/doc/favicon.png differ diff --git a/lib/tree-2.81/doc/filler.png b/lib/tree-2.81/doc/filler.png new file mode 100644 index 0000000..548e1e4 Binary files /dev/null and b/lib/tree-2.81/doc/filler.png differ diff --git a/lib/tree-2.81/doc/index.html b/lib/tree-2.81/doc/index.html new file mode 100644 index 0000000..f807fa2 --- /dev/null +++ b/lib/tree-2.81/doc/index.html @@ -0,0 +1,205 @@ + + + + + + + +tree.hh: an STL-like C++ tree class + + + +
+
+
+ +Bookmark and Share + +
+
+ + + + + +
+
+ [background image] +
+
+

tree.hh: an STL-like C++ tree class

+

+ Kasper Peeters, kasper.peeters (at) phi-sci.com +

+
+
+ + + + + +
+ + + +

Overview

+ +
+ The tree.hh library for C++ provides an STL-like container class + for n-ary trees, templated over the data stored at the nodes. Various + types of iterators are provided (post-order, pre-order, and + others). Where possible the access methods are compatible with the STL + or alternative algorithms are available. The library is available + under the terms of the GNU General Public License version 2 or + 3 (see below).
+ +
Documentation is available in the form of + a pdf file. See + the documentation page for + more details and sample programs. +
+ +
The tree.hh library is meant for generic n-ary + trees. For binary trees, AVL trees, quad trees and other data + structures, you may want to look elsewhere.
+ +
The library is available for free, but if it + helps you a lot, why not consider a small donation? + + Your contribution is greatly appreciated! +
+ +
+ I have considered this class for inclusion in Boost. However, + there are many ways to implement a tree container, and there + is no good way to simultaneously satisfy everyone who would + use it. See the discussion on the Boost mailing list in + 2002 + and 2009. +
+ +

License

+ +
In principle, the tree.hh code is + available under the terms of the GNU General Public + License 2 + or 3. However, + if you would like to use tree.hh under different + conditions, contact me and we will work something out.
+ +
+ This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, + see http://www.gnu.org/licenses/. +
+ +
If you use tree.hh, + please satisfy my curiosity and write me a small email with + a bit of explanation of your software and the role of my tree + class in it.
+ +
+ +
+ +

+ + Valid XHTML 1.0 Strict +

+ + + + + + + + +
+ + + diff --git a/lib/tree-2.81/doc/projects.html b/lib/tree-2.81/doc/projects.html new file mode 100644 index 0000000..03af4d5 --- /dev/null +++ b/lib/tree-2.81/doc/projects.html @@ -0,0 +1,162 @@ + + + + + + + +tree.hh: an STL-like C++ tree class, projects using tree.hh + + + +
+
+
+ +Bookmark and Share + +
+
+ [background image] +
+
+

tree.hh: an STL-like C++ tree class

+

+ Kasper Peeters, kasper.peeters (at) phi-sci.com +

+
+
+ + + + + +
+ + + +

Projects using tree.hh

+ +
The tree.hh library is used in various projects: +
+
Cadabra
+
A field-theory motivated approach to symbolic computer + algebra.
+
Gnash
+
Gnash is a GNU Flash movie player. Previously, it was only + possible to play flash movies with proprietary software. While there + are some other free flash players, none support anything beyond SWF + v4. Gnash is based on GameSWF, and supports many SWF v7 features.
+
htmlcxx
+
A simple non-validating css1 and html parser for C++.
+
Principles of Compiler Design
+
A course in compiler design at the Simon Fraser University, Canada.
+
liborigin
+
A library for reading OriginLab OPJ project files, which is used + by QtiPlot + and LabPlot, two + applications for data analysis and visualisation.
+
EChem++
+
A project realizing the idea of a Problem Solving Environment + (PSE) in the field of computational electrochemistry. Computer + controlled experimental measurements, numerical simulation and + analysis of electrochemical processes will be combined under a common + user interface.
+
LZCS
+
A semistructured document transformation tool. LZCS compresses + structured documents taking advantage of the redundant information + that can appear in the structure. The main idea is that frequently + repeated subtrees may exist and these can be replaced by a backward + reference to their first occurance. See the accompanying + paper for more details.
+
libOFX
+
A parser and an API designed to allow applications to very easily support OFX + command responses, usually provided by financial institutions for + statement downloads.
+
A genetic programming project
+
See this paper for + more information.
+
FreeLing
+
The FreeLing package consists of a library providing language analysis services (such as morfological analysis, date recognition, PoS tagging, etc.)
+
+ Let me know about your project when you are using + tree.hh, so that I can add it to the list.
+
+ +
+ +

+ + Valid XHTML 1.0 Strict +

+ + + + + + + + +
+ + + diff --git a/lib/tree-2.81/doc/structure.png b/lib/tree-2.81/doc/structure.png new file mode 100644 index 0000000..fbad024 Binary files /dev/null and b/lib/tree-2.81/doc/structure.png differ diff --git a/lib/tree-2.81/doc/structure.svg b/lib/tree-2.81/doc/structure.svg new file mode 100644 index 0000000..8a2bf21 --- /dev/null +++ b/lib/tree-2.81/doc/structure.svg @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + head 1 + + + + head 2 + + + + + node + + + + node + + + + node + + + next sibling + previous sibling + + + first child + + + + last child + + + + + + + head n + + + + + node + + + + node + + + + node + + + + + + + + depth + + + diff --git a/lib/tree-2.81/doc/tree.css b/lib/tree-2.81/doc/tree.css new file mode 100644 index 0000000..03b84c8 --- /dev/null +++ b/lib/tree-2.81/doc/tree.css @@ -0,0 +1,171 @@ + +body { + font: 10pt "Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, sans-serif; +} +div#container { + min-width: 700px; + margin-left: 20px; + margin-right: 20px; + margin-top: 20px; + margin-bottom: 30px; + background: #f0f0f0; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -moz-box-shadow: 1px 1px 9px #888; + padding: 5px 15px 5px 15px; +} +div#titletxt { + margin: -150px 0 30px 240px; + height: 70px; +} +div#filler { + width: 100%; + height: 160px; + background: url("filler.png"); + padding: 0; + margin: 0; + margin-top: 5px; + -moz-box-shadow: 1px 1px 5px #888; +} +img#treeimg { + margin-top: 0; +} + +/* Donations */ + +form#donate { + text-align: center; + margin-top: 1ex; + margin-bottom: 1ex; +} + +/* Layout containers */ + +div#linkbar { + margin-right: 135px; + display: inline; +} +div#main { + margin-right: 135px; + display: inline; +} +div#sidebar { + margin-top: 16px; + float: right; + display: inline; + width: 125px; + margin-left: 10px; +} +div#flush { + clear: both; +} + + +/* Title color/style */ + +#title h1 { + font-size: 30px; + color: #b00000; +} +#title h2 { + font-size: 11pt; + font-weight: normal; + color: black; + border-bottom: 0px; +} + +/* Menu */ + +ul#menubar { + margin-top: 0px; + margin-bottom: 35px; + margin-right: 2ex; + text-align: right; +} + +#menubar li { + display: inline; + background: #b00000; + color: white; + font-weight: bold; + padding: .5ex 1ex .5ex 1ex; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -moz-box-shadow: 1px 1px 9px #888; +} +#menubar li:hover { + background: #009000; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -moz-box-shadow: 1px 1px 6px #888; +} + +#menubar a { + text-decoration: none; + color: white; +} + +/* Main color/style */ + +div#share { + position: absolute; + right: 50px; + top: 36px; +} +div#plusone { + position: absolute; + left: 50px; + top: 36px; +} + +#main h2 { + margin-top: 2ex; + margin-right: 135px; + display: block; + background: #b00000; + color: white; + padding-left: 1ex; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -moz-box-shadow: 1px 1px 9px #888; +} +div.text { + margin-left: 120px; + margin-bottom: 2ex; + margin-right: 145px; +} +div.license { + margin-left: 140px; + margin-bottom: 2ex; + margin-right: 155px; +} +div.filename { + margin-left: 200px; + margin-bottom: 1ex; +} +img.structure { + margin-top: 1ex; + margin-bottom: 1ex; + margin-left: 3ex; +} +dd { + margin-bottom: 2ex; +} + +img { + border-style: none; +} + +/* Code listing */ + +div.code { + margin: 1ex; + width: 90%; + border: dotted 1px black; + background: #f8f8f8; + font-size: 8pt; + padding: 1ex; +} +.code pre { + white-space: pre-wrap; +} diff --git a/lib/tree-2.81/doc/tree.jpg b/lib/tree-2.81/doc/tree.jpg new file mode 100644 index 0000000..d6f58f7 Binary files /dev/null and b/lib/tree-2.81/doc/tree.jpg differ diff --git a/lib/tree-2.81/doc/tree.png b/lib/tree-2.81/doc/tree.png new file mode 100644 index 0000000..04fa420 Binary files /dev/null and b/lib/tree-2.81/doc/tree.png differ diff --git a/lib/tree-2.81/doc/tree.tex b/lib/tree-2.81/doc/tree.tex new file mode 100644 index 0000000..4ba233d --- /dev/null +++ b/lib/tree-2.81/doc/tree.tex @@ -0,0 +1,388 @@ +\documentclass[11pt]{kasper} +% +% If you do not have 'kasper.cls', see +% http://www.damtp.cam.ac.uk/user/kp229/texstuff . + +\usepackage{makeidx} +\usepackage{verbatim} +\usepackage{relsize} +\makeindex +%\newcommand{\toindex}[1]{#1\index{#1}} + +\newcommand{\member}[1]{{\tt #1}\index{#1}} +%\newcommand{\member}[1]{{\tt #1}} + +\def\mystrut{\vbox to 8.5pt{}\vtop to 3.5pt{}} +\def\V{\hskip10pt\vrule\hskip10pt} +\def\T{\hskip10pt\vrule\vrule height2.5pt depth -2.1pt width 10pt} +\def\L{\hskip10pt\vrule height 8.5pt depth -2.1pt + \vrule height2.5pt depth -2.1pt width 10pt} +\def\N{\hskip10pt\phantom{\vrule}\hskip10pt} +\def\hw{\hskip-1000pt plus 1fil} + +% to test: insert before end of subtree + +\begin{document} +\title{{\tt tree.hh} documentation} +\author{Kasper Peeters} +\email{kasper.peeters@gmail.com} +\maketitle +\begin{abstract} +The {\tt tree.hh} library for C++ provides an STL-like container class +for n-ary trees, templated over the data stored at the nodes. Various +types of iterators are provided (post-order, pre-order, and +others). Where possible the access methods are compatible with the STL +or alternative algorithms are available. The library is available +under the terms of the GNU General Public License.\\[3ex] +Code and examples available at: {\tt http://tree.phi-sci.com/}\\[3ex] +{\bf This documentation is not yet entirely complete. Refer to the {\tt +tree.hh} header file for a full list of member functions.} +\end{abstract} +\vfill +\maketoc +\eject + +\begin{sectionunit} +\title{Overview} +\maketitle +\begin{sectionunit} +\title{The container class} +\maketitle +The tree class of {\tt tree.hh} is a templated container class in the +spirit of the STL. It organises data in the form of a so-called n-ary +tree. This is a tree in which every node is connected to an arbitrary +number of child nodes. Nodes at the same level of the tree are called +``siblings'', while nodes that are below a given node are called its +``children''. At the top of the tree, there is a set of nodes which +are characterised by the fact that they do not have any parents. The +collection of these nodes is called the ``head'' of the tree. See +figure~\ref{f:overview} for a pictorial illustration of this +structure (90 degrees rotated for convenience). +\begin{figure}[th] +\begin{center} +\includegraphics[width=.5\textwidth]{treefig} +\caption{Overview of the tree structure. The elements at the top of +the tree (here displayed at the left for convenience) are in the +``head'' (there can be more than one such element). Every node is +linked to its children using the ``first child'' and ``last child'' +links. In addition, all nodes on a given level are doubly-linked using +the ``previous sibling'' and ``next sibling'' links. The ``depth'' of +a given node refers to the horizontal distance from the head nodes.} +\label{f:overview} +\end{center} +\end{figure} + +The tree class is templated over the data objects stored at the nodes; +just like you can have a {\tt vector} you can now have a +{\tt tree}. Many STL algorithms work on this data structure, +and where necessary alternatives have been provided. +\medskip + +\end{sectionunit} +\begin{sectionunit} +\title{Iterators} +\maketitle + +The essential difference between a container with the structure of a +tree and the STL containers is that the latter are ``linear''. While +the STL containers thus only have essentially one way in which one can +iterate over their elements, this is not true for trees. The {\tt +tree.hh} library provides (at present) four different iteration +schemes. To describe them, consider the following tree: +\begin{equation*} +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + root \hw\cr + \T A \cr + \V \T B \cr + \V \L C \cr + \L D \cr + \N \T E \cr + \N \L F \cr}} +\end{equation*} +The three iteration types and the resulting order in which nodes are +visited are tabulated below: +\begin{center} +\begin{tabular}{llll} +pre-order (default) & ``element before children'' & +\member{pre\_order\_iterator} & root A B C D E F \\ +post-order & ``element after children'' & +\member{post\_order\_iterator} & B C A E F D root \\ +breadth-first & & +\member{breadth\_first\_iterator} & root A D B C E F \\ +sibling & ``only siblings'' & +\member{sibling\_iterator} & (for ex.) A D \\ +fixed-depth & & +\member{fixed\_depth\_iterator} & (for ex.) A D \\ +leaf & & +\member{leaf\_iterator} & B C E F +\end{tabular} +\end{center} +The pre-order ones are the default iterators, and therefore also known +under the name of {\tt iterator}. Sibling iterators and fixed-depth +iterators iterate only over the nodes at a given depth of the +tree. The former restrict themselves to the child nodes of one given +node, while the latter iterates over all child nodes at the given +depth. Finally, leaf iterators iterate over all leafs (bottom-most) +nodes of the tree. + +There are copy constructors that will convert iterators of the +various types into each other. The post- and pre-order iterators are +both also known as ``depth-first'', in contrast to the +``breadth-first'' iterator. + +The begin and end iterators of a tree can be obtained using +\member{begin()} and \member{end()} (for pre-order iterators) or +alternatively \member{begin\_post()} and \member{end\_post()} (for +post-order iterators) and \member{begin\_leaf()} and +\member{end\_leaf()} (for leaf iterators). Similarly, the begin and +end sibling iterators can be obtained by calling +\member{begin(iterator)} and \member{end(iterator)}. The range of +children of a given node can also be obtained directly from an +iterator, by using the {\tt iterator::begin()} and {\tt +iterator::end()} member functions. + +If you want to (temporarily) make an iterator not go into the child +subtree, call the member function \member{skip\_children}. This will only +keep effect for a single increment or decrement of the +iterator. Finally, whether or not an iterator is actually pointing at +a node (i.e.~is not an ``end'' iterator) can be tested using the +\member{is\_valid(iterator)} member of the tree class. + +\end{sectionunit} +\end{sectionunit} + +\begin{sectionunit} +\title{Basic operations} +\maketitle +\begin{description} +\item[Initialising] There are two nontrivial constructors. One which takes +a single node element as argument. It constructs a tree with this node +begin the sole node in the head (in other words, it is a combination +of a trivial constructor together with a \member{set\_head} call). +The other non-trivial constructor takes an iterator, and copies the +subtree starting at that node into the newly created tree (useful for +constructing new tree objects given by subtrees of existing trees). + +\item[Tree traversal] Besides the \member{operator++} and +\member{operator--} members for step-wise traversal through the tree, +it is also possible to use the \member{operator+=} and \member{operator-=} +member functions to make more than one step at the same time (though +these are linear time, not amortized constant). The result of stepping +beyond the end of the tree or stepping beyond the end of a sibling +range (for sibling iterators) is undefined. + +The parent of a given node can be reached by calling the \member{parent} +member of the tree object, giving it an iterator pointing to the node. + +If you know the number of children of a given node, you can get direct +access to the $n$th child by using the \member{child} member +function. Note that the value of the index is not checked and should +therefore always be valid. + +\item[Appending child nodes] Nodes can be added as children of a given +node using the \member{append\_child} member function. + +\item[Inserting nodes] Nodes can be inserted at the same depth as a +given other node using the \member{insert} and \member{insert\_after} +members functions. This is also how you insert the first node into a +tree. +\end{description} +\end{sectionunit} + +\begin{sectionunit} +\title{Other algorithms} +\maketitle +\begin{sectionunit} +\title{Non-mutating algorithms} +\maketitle +\begin{description} +\item[Counting nodes] The total number of nodes of a tree can be +obtained using the \member{size} member function, while the number of +children of a given node can be obtained with a call to +\member{number\_of\_children(iterator)}. Similarly, the number of +nodes at a given depth (the number of siblings of a given node) can be +obtained using the \member{number\_of\_siblings} member function. +\item[Determining depth] The \member{depth()} member function returns the +distance of a node to the root. +\item[Accessing siblings by their index] See the next item. +\item[Determining index in a sibling range] In order to determine the +index of a node in the range of siblings to which it belongs, use the +\member{index(sibling\_iterator)} member function. The first sibling node +has index 0. The reverse of this function (obtaining a sibling node +given its index in the range of siblings) is called +\member{child(const iterator\_base\&, unsigned int)}. +\item[Comparing trees] While the STL \member{equal} algorithm can be used +to compare the values of the nodes in two different trees, it does not +know about the structure of the tree. If you want the comparison to +take this into account, use the \member{equal(iterator, iterator, +iterator, BinaryPredicate)} call of the tree class. As an addition to +the STL algorithm, the length of the first range does not have to be +equal to the length of the range pointed to by the second iterator. + +There is also an \member{equal\_subtree} algorithm which takes only +two iterators, pointing to the (single-node) heads of two +subtrees. +\end{description} +\end{sectionunit} + +\begin{sectionunit} +\title{Mutating algorithms} +\maketitle +\begin{description} +\item[Erasing nodes and subtrees] In order to remove a node including +its children from the tree, use the \member{erase(iterator)} call. If you +just want to erase the children, but not the node itself, use the +\member{erase\_children(iterator)} call. + +\item[Replacing individual nodes or subtrees] + +\item[Flattening subtrees] The procedure of moving all children of a +given node to be siblings of that node is called ``flattening''; it +acts as +\begin{equation*} +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + apple \hw\cr + \T banana\cr + \V \T pear \cr + \V \T strawberry \cr + \V \L cherry \cr + \L grape\cr}}\quad\rightarrow\quad +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + apple \hw\cr + \T banana\cr + \T pear \cr + \T strawberry \cr + \T cherry \cr + \L grape\cr}} +\end{equation*} +% \begin{screen} +% apple apple +% banana banana +% pear -> pear +% strawberry strawberry +% cherry cherry +% grape grape +% \end{screen} +when the tree is flattened at the ``banana'' node. + +\item[Moving or exchanging subtrees] Simple exchange of one sibling node with the +next one is done through the member function \member{swap(sibling\_iterator)}. The +iterator remains valid and remains pointing to the moved subtree. + +More complicated move operations are the \member{move\_ontop}, +\member{move\_before} and \member{move\_after} ones. These all take +two iterators, a source and a target. The member +\member{move\_ontop(target, source)} removes the `target' node and +all its children, and replaces it with the `source' node and its +children. The `source' subtree is removed from its original location. +The other two move members do a similar thing, differing only in the +node which is to be replaced. + +\item[Extracting subtrees] You can create a new tree object +filled with the data of a subtree of the original tree. This is +analogous to the extraction of a substring of a string. The relevant +member function is \member{subtree(sibling\_iterator, +sibling\_iterator)} which takes a range of siblings as argument. +There is also a slight variation of this member, which does not return +a tree object but instead populates one that is passed as an argument +(useful if you want to call this on a tree object subclassed from +{\tt tree}. + +\item[Sorting] The standard STL sort algorithm is not very useful for +trees, because it only exchanges values, not nodes. Applying it to a +tree would mean that the structure of the tree remains unmodified, +only node values get moved around (not their subtrees). + +Therefore, the {\tt tree} class has its own sort member. It comes in +two forms, just like the STL sort, namely +\begin{screen} +void sort(sibling_iterator from, sibling_iterator to, bool deep=false); + +template +void sort(sibling_iterator from, sibling_iterator to, + StrictWeakOrdering comp, bool deep=false); +\end{screen} +The result of a call to either of these is that the nodes in the range +described by the two iterators get sorted. If the boolean {\tt deep} +is true, the subtrees of all these nodes will get sorted as well (and +so one can sort the entire tree in one call). As in the STL, you can +use the second form of this function to pass your own comparison +class. + +If the nodes to which the two iterators point are not in the same +sibling range (i.e.~not at the same depth in the tree), the result is undefined. + +\item[Merging] One way in which one might think of indicating the +position where new nodes are to be inserted, is to give the path that +leads to the insertion point. For instance, given the tree +\begin{equation*} +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + apple \hw\cr + \T banana\cr + \V \T pear \cr + \V \T strawberry \cr + \V \L cherry \cr + \L grape\cr}} +\end{equation*} +one could imagine using the sub-tree +\begin{equation*} +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + apple \hw\cr + \L banana\cr + \N \T coconut \cr + \N \L raspberry \cr}} +\end{equation*} +to indicate that the nodes ``coconut'' and ``raspberry'' are to be +inserted as new children of the ``banana'' node. In {\tt tree.hh} this +process is called \emph{tree merging}. It can do the simple addition +of children as above, but actually handles the generic case too: as +an example consider the merge +\begin{equation*} +\text{\tt merge}\left[ +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + apple \hw\cr + \T banana\cr + \V \T pear \cr + \V \T strawberry \cr + \V \L cherry \cr + \T grape\cr + blueberry \cr}}\quad, \quad +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + apple \hw\cr + \T banana\cr + \V \T coconut \cr + \V \L raspberry \cr + \T tangerine \cr + \V \L plum\cr + blueberry \cr + \N \L orange \cr}}\right]\quad\rightarrow\quad +\vcenter{\offinterlineskip +\halign{&#\mystrut\hfil\cr + apple \hw\cr + \T banana\cr + \V \T pear\cr + \V \T strawberry\cr + \V \T cherry\cr + \V \T coconut \cr + \V \L raspberry \cr + \T grape\cr + \T tangerine \cr + \V \L plum\cr + blueberry \cr + \N \L orange \cr}} +\end{equation*} +As is clear from the above, the arguments to \member{merge} are two +sibling ranges. +\end{description} +\end{sectionunit} +\end{sectionunit} + +\printindex +\end{document} diff --git a/lib/tree-2.81/doc/tree2.png b/lib/tree-2.81/doc/tree2.png new file mode 100644 index 0000000..9dd31b0 Binary files /dev/null and b/lib/tree-2.81/doc/tree2.png differ diff --git a/lib/tree-2.81/doc/treefig.eps b/lib/tree-2.81/doc/treefig.eps new file mode 100644 index 0000000..c813732 --- /dev/null +++ b/lib/tree-2.81/doc/treefig.eps @@ -0,0 +1,190 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: tree.eps +%%Creator: fig2dev Version 3.2 Patchlevel 0-beta3 +%%CreationDate: Fri May 3 12:41:08 2002 +%%For: kp229@church.amtp.cam.ac.uk (Kasper Peeters) +%%Orientation: Portrait +%%BoundingBox: 0 0 324 252 +%%Pages: 0 +%%BeginSetup +%%EndSetup +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +-126.0 342.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def +%%EndProlog + +$F2psBegin +10 setmiterlimit +n -1000 6700 m -1000 -1000 l 8494 -1000 l 8494 6700 l cp clip + 0.06000 0.06000 sc +% Polyline +7.500 slw +gs clippath +4380 3828 m 4350 3948 l 4320 3828 l 4320 3990 l 4380 3990 l cp +4320 3222 m 4350 3102 l 4380 3222 l 4380 3060 l 4320 3060 l cp +clip +n 4350 3075 m 4350 3975 l gs col0 s gr gr + +% arrowhead +n 4320 3222 m 4350 3102 l 4380 3222 l 4350 3222 l 4320 3222 l cp gs 0.00 setgray ef gr col0 s +% arrowhead +n 4380 3828 m 4350 3948 l 4320 3828 l 4350 3828 l 4380 3828 l cp gs 0.00 setgray ef gr col0 s +% Polyline + [60] 0 sd +n 4350 4350 m 4350 5475 l gs col0 s gr [] 0 sd +% Polyline +gs clippath +4021 5328 m 4039 5450 l 3966 5351 l 4028 5500 l 4083 5477 l cp +clip +n 2550 1875 m 4050 5475 l gs col0 s gr gr + +% arrowhead +n 4021 5328 m 4039 5450 l 3966 5351 l 3993 5339 l 4021 5328 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +4380 2628 m 4350 2748 l 4320 2628 l 4320 2790 l 4380 2790 l cp +4320 2022 m 4350 1902 l 4380 2022 l 4380 1860 l 4320 1860 l cp +clip +n 4350 1875 m 4350 2775 l gs col0 s gr gr + +% arrowhead +n 4320 2022 m 4350 1902 l 4380 2022 l 4350 2022 l 4320 2022 l cp gs 0.00 setgray ef gr col0 s +% arrowhead +n 4380 2628 m 4350 2748 l 4320 2628 l 4350 2628 l 4380 2628 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +3903 1695 m 4023 1725 l 3903 1755 l 4065 1755 l 4065 1695 l cp +clip +n 2550 1725 m 4050 1725 l gs col0 s gr gr + +% arrowhead +n 3903 1695 m 4023 1725 l 3903 1755 l 3903 1725 l 3903 1695 l cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +6828 1695 m 6948 1725 l 6828 1755 l 6990 1755 l 6990 1695 l cp +clip +n 4725 1725 m 6975 1725 l gs col0 s gr gr + +% arrowhead +n 6828 1695 m 6948 1725 l 6828 1755 l 6828 1725 l 6828 1695 l cp gs 0.00 setgray ef gr col0 s +% Polyline + [60] 0 sd +n 7275 1950 m 7275 2625 l gs col0 s gr [] 0 sd +/Times-Roman ff 180.00 scf sf +2100 1800 m +gs 1 -1 sc (head) col0 sh gr +/Times-Roman ff 180.00 scf sf +4200 1800 m +gs 1 -1 sc (node) col0 sh gr +/Times-Roman ff 180.00 scf sf +4200 3000 m +gs 1 -1 sc (node) col0 sh gr +/Times-Roman ff 180.00 scf sf +4200 4200 m +gs 1 -1 sc (node) col0 sh gr +/Times-Roman ff 180.00 scf sf +4200 5700 m +gs 1 -1 sc (node) col0 sh gr +/Times-Roman ff 180.00 scf sf +4575 2250 m +gs 1 -1 sc (next sibling) col0 sh gr +/Times-Roman ff 180.00 scf sf +4575 2475 m +gs 1 -1 sc (prev sibling) col0 sh gr +/Times-Roman ff 180.00 scf sf +4575 3450 m +gs 1 -1 sc (next sibling) col0 sh gr +/Times-Roman ff 180.00 scf sf +4575 3675 m +gs 1 -1 sc (prev sibling) col0 sh gr +/Times-Roman ff 180.00 scf sf +5850 1650 m +gs 1 -1 sc (first child) col0 sh gr +/Times-Roman ff 180.00 scf sf +2925 1650 m +gs 1 -1 sc (first child) col0 sh gr +/Times-Roman ff 180.00 scf sf +7125 1800 m +gs 1 -1 sc (node) col0 sh gr +/Times-Roman ff 180.00 scf sf +7125 2925 m +gs 1 -1 sc (node) col0 sh gr +/Times-Roman ff 180.00 scf sf +2550 3900 m +gs 1 -1 sc (last child) col0 sh gr +$F2psEnd +rs diff --git a/lib/tree-2.81/doc/treefig.fig b/lib/tree-2.81/doc/treefig.fig new file mode 100644 index 0000000..f506563 --- /dev/null +++ b/lib/tree-2.81/doc/treefig.fig @@ -0,0 +1,44 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2 + 1 1 1.00 60.00 120.00 + 1 1 1.00 60.00 120.00 + 4350 3075 4350 3975 +2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 2 + 4350 4350 4350 5475 +2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2550 1875 4050 5475 +2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2 + 1 1 1.00 60.00 120.00 + 1 1 1.00 60.00 120.00 + 4350 1875 4350 2775 +2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2550 1725 4050 1725 +2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4725 1725 6975 1725 +2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 2 + 7275 1950 7275 2625 +4 0 0 0 0 0 12 0.0000 0 135 360 2100 1800 head\001 +4 0 0 0 0 0 12 0.0000 4 135 360 4200 1800 node\001 +4 0 0 0 0 0 12 0.0000 4 135 360 4200 3000 node\001 +4 0 0 0 0 0 12 0.0000 4 135 360 4200 4200 node\001 +4 0 0 0 0 0 12 0.0000 4 135 360 4200 5700 node\001 +4 0 0 0 0 0 12 0.0000 4 180 870 4575 2250 next sibling\001 +4 0 0 0 0 0 12 0.0000 4 180 870 4575 2475 prev sibling\001 +4 0 0 0 0 0 12 0.0000 4 180 870 4575 3450 next sibling\001 +4 0 0 0 0 0 12 0.0000 4 180 870 4575 3675 prev sibling\001 +4 0 0 0 0 0 12 0.0000 4 135 720 5850 1650 first child\001 +4 0 0 0 0 0 12 0.0000 4 135 720 2925 1650 first child\001 +4 0 0 0 0 0 12 0.0000 4 135 360 7125 1800 node\001 +4 0 0 0 0 0 12 0.0000 4 135 360 7125 2925 node\001 +4 0 0 0 0 0 12 0.0000 4 135 690 2550 3900 last child\001 diff --git a/lib/tree-2.81/doc/treefig.pdf b/lib/tree-2.81/doc/treefig.pdf new file mode 100644 index 0000000..547b9e4 --- /dev/null +++ b/lib/tree-2.81/doc/treefig.pdf @@ -0,0 +1,71 @@ +%PDF-1.3 +%Çì¢ +6 0 obj +<> +stream +xœ­UKÓ0¾ûWøÖ©YÏø}]‰—…H‡¥MPZØí +øùŒ_‰³©©h¤zÆóøÆó°E\„/¯›{b·<±{"?±°{ Ô(øÀ$ª9ˆŽ4Ž l´AjÁAh n Nb‘N ‰t°Jt—%Ê™Æ>´vÄÍ$+œvjô—èŽðž©Fó_ŃÕSDR“ÖÇx² ·qÒØþíqƒŽ‚X’²I3‚_k`?siø*Û6:£*=46†c‰Œl%!HÀ™ðM¬èpzÀ$s>0Ræ„Ô•CKPècáÀ΋u[*5! ˜Æ¤&˺ÿËc·4±@NÕ¥´¶.e’ΪipQT]ˆh«.̲ÂI1N¦Ï NÉŠHŸœ 'Í׃s…ƒip.KÙ¤Y ÎrÓÅUB(!c7éÐå(]Èb‘IccûX?§ƒÍÙæy ²«ª —VšuA®t°43褙pÐ 7áYÂA/Õœ>—™x¿çÔ Gýwj VšUj®uð궕tES#ë¥HSw¥HŸèöŽ¯o^6~×Ò+ìiƒÜµ{–gàkÑú¡R@˜Š·vÓí¶oÚo è¼Ý²›ã÷í.ìXäíûÌ®ÆÕ‹z‘ΈÂ&ÃÝï~ê¿ýñ1º”$ Ê?žw?GÁŠÑ —ög«ê[Cû€¤³ïŸO/|ÓõC |M× IÄ95_ûÙ©Œ-àék´¡Në)µ‡w-¿§^øöÌÐcendstream +endobj +7 0 obj +588 +endobj +10 0 obj +<> +endobj +11 0 obj +<> +endobj +5 0 obj +<> +/Contents 6 0 R +>> +endobj +3 0 obj +<< /Type /Pages /Kids [ +5 0 R +] /Count 1 +>> +endobj +1 0 obj +<> +endobj +4 0 obj +<> +endobj +9 0 obj +<> +endobj +8 0 obj +<> +endobj +2 0 obj +<>endobj +xref +0 12 +0000000000 65535 f +0000000971 00000 n +0000001222 00000 n +0000000912 00000 n +0000001019 00000 n +0000000752 00000 n +0000000015 00000 n +0000000673 00000 n +0000001161 00000 n +0000001088 00000 n +0000000692 00000 n +0000000722 00000 n +trailer +<< /Size 12 /Root 1 0 R /Info 2 0 R +>> +startxref +1274 +%%EOF diff --git a/lib/tree-2.81/src/.gitignore b/lib/tree-2.81/src/.gitignore new file mode 100644 index 0000000..f0ef4c3 --- /dev/null +++ b/lib/tree-2.81/src/.gitignore @@ -0,0 +1,3 @@ +*.o +*.res +test1 diff --git a/lib/tree-2.81/src/Makefile b/lib/tree-2.81/src/Makefile new file mode 100644 index 0000000..7d1aba7 --- /dev/null +++ b/lib/tree-2.81/src/Makefile @@ -0,0 +1,14 @@ + +%.o: %.cc + g++ -c -I. $^ + +test1: test1.o + g++ -o test1 test1.o + +run_tests: test1 test1.req + ./test1 > test1.res + @diff test1.res test1.req + @echo "*** All tests OK ***" + +clean: + rm -f *.o *~ *.res diff --git a/lib/tree-2.81/src/simple tree.hpp b/lib/tree-2.81/src/simple tree.hpp new file mode 100644 index 0000000..5c7b54c --- /dev/null +++ b/lib/tree-2.81/src/simple tree.hpp @@ -0,0 +1,1560 @@ +// Another STL-like templated tree class. +// Revised by: Xinlin Cao(xinlincao@gmail.com) +// Revised from Kasper Peeters's implementation.(http://www.aei.mpg.de/~peekas/tree/),Kasper Peeters +//Compared to Kasper's implementation, the modifications are the following: +//# removed sibling iterator +//# added children iterator +//# removed a lot of member functions from tree and iterators +//# changed set_head() to set_root() +//# added root() member function +//# added reparent_roo() member function +//# changed implementation of operator = () +//# changed some member functions about getting iterators +//# tested all member functions +//# removed implicit conversion between different iterators +//# removed depth iterator +//# change some parameters of some functions, such as append_child, isnert_xxx, move_xxx and so on. + +// This version of tree is simpler than old one. It is robust and easy for using and understanding. +// Distributed under the GNU General Public License version 3, + + +/** + +The tree.hh library for C++ provides an STL-like container class +for n-ary trees, templated over the data stored at the +nodes. Various types of iterators are provided (post-order, +pre-order, and others). Where possible the access methods are +compatible with the STL or alternative algorithms are +available. +*/ + +#ifndef tree_hh_ +#define tree_hh_ + +#include +#include +#include +#include +#include +#include +#include + +// HP-style construct/destroy have gone from the standard, +// so here is a copy. + +namespace kp { + + template + void constructor(T1* p, T2& val) + { + new ((void *) p) T1(val); + } + + template + void constructor(T1* p) + { + new ((void *) p) T1; + } + + template + void destructor(T1* p) + { + p->~T1(); + } + +} + +/// A node in the tree, combining links to other nodes as well as the actual data. +template +class tree_node_ { // size: 5*4=20 bytes (on 32 bit arch), can be reduced by 8. +public: + tree_node_ *parent; + tree_node_ *first_child, *last_child; + tree_node_ *prev_sibling, *next_sibling; + T data; +}; // __attribute__((packed)); + +template > > +class tree { +protected: + typedef tree_node_ tree_node; +public: + /// Value of the data stored at a node. + typedef T value_type; + + class iterator_base; + class pre_order_iterator; + class post_order_iterator; + class children_iterator; + class leaf_iterator; + + tree(); + tree(const T&); + tree(const tree&); + ~tree(); + tree& operator=(const tree&); + + /// Base class for iterators, only pointers stored, no traversal logic. +#ifdef __SGI_STL_PORT + class iterator_base : public stlport::bidirectional_iterator { +#else + class iterator_base { +#endif + public: + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + iterator_base(); + iterator_base(tree_node *); + + T& operator*() const; + T* operator->() const; + + /// Number of children of the node pointed to by the iterator. + unsigned int number_of_children() const; + + children_iterator begin_children_iterator() const; + children_iterator end_children_iterator() const; + + tree_node *node; + }; + + /// Depth-first iterator, first accessing the node, then its children. + class pre_order_iterator : public iterator_base { + public: + pre_order_iterator(); + pre_order_iterator(tree_node *); + + bool operator==(const pre_order_iterator&) const; + bool operator!=(const pre_order_iterator&) const; + pre_order_iterator& operator++(); + pre_order_iterator& operator--(); + pre_order_iterator operator++(int); + pre_order_iterator operator--(int); + pre_order_iterator& operator+=(unsigned int); + pre_order_iterator& operator-=(unsigned int); + }; + + /// Depth-first iterator, first accessing the children, then the node itself. + class post_order_iterator : public iterator_base { + public: + post_order_iterator(); + post_order_iterator(tree_node *); + + bool operator==(const post_order_iterator&) const; + bool operator!=(const post_order_iterator&) const; + post_order_iterator& operator++(); + post_order_iterator& operator--(); + post_order_iterator operator++(int); + post_order_iterator operator--(int); + post_order_iterator& operator+=(unsigned int); + post_order_iterator& operator-=(unsigned int); + + /// Set iterator to the first child as deep as possible down the tree. + void descend_all(); + }; + + /// Breadth-first iterator, using a queue + class breadth_first_queued_iterator : public iterator_base { + public: + breadth_first_queued_iterator(); + breadth_first_queued_iterator(tree_node *); + + bool operator==(const breadth_first_queued_iterator&) const; + bool operator!=(const breadth_first_queued_iterator&) const; + breadth_first_queued_iterator& operator++(); + breadth_first_queued_iterator operator++(int); + breadth_first_queued_iterator& operator+=(unsigned int); + + private: + std::queue traversal_queue; + }; + + /// Iterator which traverses only the nodes which are siblings of each other. + class children_iterator : public iterator_base { + public: + children_iterator(); + children_iterator(tree_node *); + + bool operator==(const children_iterator&) const; + bool operator!=(const children_iterator&) const; + children_iterator& operator++(); + children_iterator& operator--(); + children_iterator operator++(int); + children_iterator operator--(int); + children_iterator& operator+=(unsigned int); + children_iterator& operator-=(unsigned int); + + tree_node *range_first() const; + tree_node *range_last() const; + tree_node *parent_; + private: + void set_parent_(); + }; + + /// Iterator which traverses only the leaves. + class leaf_iterator : public iterator_base { + public: + leaf_iterator(); + leaf_iterator(tree_node *, tree_node *top); + + bool operator==(const leaf_iterator&) const; + bool operator!=(const leaf_iterator&) const; + leaf_iterator& operator++(); + leaf_iterator& operator--(); + leaf_iterator operator++(int); + leaf_iterator operator--(int); + leaf_iterator& operator+=(unsigned int); + leaf_iterator& operator-=(unsigned int); + private: + tree_node *top_node; + }; + + /// Return iterator to the beginning of the tree. + inline pre_order_iterator root() const; + + /// Return iterator to the beginning of the tree. + inline pre_order_iterator begin_pre_order_iterator(const iterator_base&) const; + /// Return iterator to the end of the tree. + inline pre_order_iterator end_pre_order_iterator(const iterator_base&) const; + /// Return post-order iterator to the beginning of the tree. + post_order_iterator begin_post_order_iterator(const iterator_base&) const; + /// Return post-order end iterator of the tree. + post_order_iterator end_post_order_iterator(const iterator_base&) const; + + + /// Return breadth-first iterator based on a iterator. + breadth_first_queued_iterator begin_breadth_first_iterator(const iterator_base&) const; + /// Return breadth-first end iterator. + breadth_first_queued_iterator end_breadth_first_iterator(const iterator_base&) const; + + + /// Return children iterator to the first child of given node. + children_iterator begin_children_iterator(const iterator_base&) const; + /// Return children end iterator for children of given node. + children_iterator end_children_iterator(const iterator_base&) const; + + /// Return leaf iterator to the first leaf of the subtree at the given node. + leaf_iterator begin_leaf_iterator(const iterator_base& top) const; + /// Return leaf end iterator for the subtree at the given node. + leaf_iterator end_leaf_iterator(const iterator_base& top) const; + + /// Return iterator to the parent of a node. + pre_order_iterator parent(const iterator_base&); + /// Return iterator to the previous sibling of a node. + pre_order_iterator previous_sibling(const iterator_base&) const; + /// Return iterator to the next sibling of a node. + pre_order_iterator next_sibling(const iterator_base&) const; + + /// Erase all nodes of the tree. + void clear(); + /// Erase element at position pointed to by iterator, return incremented iterator. + template iter erase(iter); + /// Erase all children of the node pointed to by iterator. + void erase_children(const iterator_base&); + + + /// Short-hand to insert_before topmost node in otherwise empty tree. + pre_order_iterator set_root(const T& x); + + /// Insert node as last/first child of node pointed to by position. + pre_order_iterator append_child(const iterator_base& position, const T& x); + pre_order_iterator prepend_child(const iterator_base& position, const T& x); + + /// Insert node as previous sibling of node pointed to by position. + pre_order_iterator insert_before(iterator_base& position, const T& x); + /// Insert node as next sibling of node pointed to by position. + pre_order_iterator insert_after(const iterator_base& position, const T& x); + + /// set the data on position to be x. + pre_order_iterator modify_data(const iterator_base& position, const T& x); + + ///set X as the new head of the tree, the old head will be a child of new head. + pre_order_iterator reparent_root(const T& x); + + /// Move 'source' node (plus its children) to become the next sibling of 'target'. + pre_order_iterator move_after(const iterator_base& target, const iterator_base& source); + /// Move 'source' node (plus its children) to become the previous sibling of 'target'. + pre_order_iterator move_before(const iterator_base& target, const iterator_base& source); + + /// Count the total number of nodes. + size_t size() const; + /// Count the total number of nodes below the indicated node (plus one). + size_t size(const iterator_base&) const; + /// Check if tree is empty. + bool empty() const; + /// Compute the depth to the root or to a fixed other iterator. + int depth(const iterator_base&); + int depth(const iterator_base&, const iterator_base&); + /// Determine the maximal depth of the tree. An empty tree has max_depth=-1. + int max_depth() const; + /// Determine the maximal depth of the tree with top node at the given position. + int max_depth(const iterator_base&) const; + /// Count the number of children of node at position. + unsigned int number_of_children(const iterator_base&); + /// Determine whether the iterator is an 'end' iterator and thus not actually pointing to a node. + bool is_valid(const iterator_base&) const; + + /// Comparator class for iterators (compares pointer values; why doesn't this work automatically?) + class iterator_base_less { + public: + bool operator()(const typename tree::iterator_base& one, + const typename tree::iterator_base& two) const + { + return one.node < two.node; + } + }; + tree_node *head, *feet; // head/feet are always dummy; if an iterator points to them it is invalid +private: + tree_node_allocator alloc_; + void head_initialise_(); + //copy the data from other.src to this.dst + void construct_children_nodes_helper_(const pre_order_iterator& dst, const tree& other, const pre_order_iterator& src); + void copy_(const tree& other); + + /// Comparator class for two nodes of a tree (used for sorting and searching). + template + class compare_nodes { + public: + compare_nodes(StrictWeakOrdering comp) : comp_(comp) {}; + + bool operator()(const tree_node *a, const tree_node *b) + { + return comp_(a->data, b->data); + } + private: + StrictWeakOrdering comp_; + }; +}; + + + +// Tree + +template +tree::tree() +{ + head_initialise_(); +} + +template +tree::tree(const T& x) +{ + head_initialise_(); + set_root(x); +} + +template +tree::~tree() +{ + clear(); + alloc_.deallocate(head,1); + alloc_.deallocate(feet,1); +} + +template +void tree::head_initialise_() +{ + + head = alloc_.allocate(1,0); // MSVC does not have default second argument + feet = alloc_.allocate(1,0); + + head->parent=0; + head->first_child=0; + head->last_child=0; + head->prev_sibling=0; //head; + head->next_sibling=feet; //head; + + feet->parent=0; + feet->first_child=0; + feet->last_child=0; + feet->prev_sibling=head; + feet->next_sibling=0; +} + +template +tree& tree::operator=(const tree& other) +{ + if (this != &other) + { + copy_(other); + } + return (*this); +} + +template +tree::tree(const tree& other) +{ + head_initialise_(); + copy_(other); +} + +template +void tree::construct_children_nodes_helper_(const pre_order_iterator& dst, const tree& other, const pre_order_iterator& src) +{ + + children_iterator childIter = other.begin_children_iterator(src); + for(; childIter != other.end_children_iterator(other.root()); ++childIter) + { + pre_order_iterator new_dst = append_child(dst,(*childIter)); + pre_order_iterator new_src = other.begin_pre_order_iterator(childIter); + construct_children_nodes_helper_(new_dst, other, new_src); + } +} + + +template +void tree::copy_(const tree& other) +{ + //check self + if (this == &other) + { + assert(0); + return; + } + clear(); + + + set_root(*other.root()); + construct_children_nodes_helper_(this->root(), other, other.root()); +} + +template +void tree::clear() +{ + if(head) + { + while(head->next_sibling!=feet) + { + erase(pre_order_iterator(head->next_sibling)); + } + } +} + +template +void tree::erase_children(const iterator_base& it) +{ + // std::cout << "erase_children " << it.node << std::endl; + if(it.node==0) return; + + tree_node *cur=it.node->first_child; + tree_node *prev=0; + + while(cur!=0) { + prev=cur; + cur=cur->next_sibling; + erase_children(pre_order_iterator(prev)); + kp::destructor(&prev->data); + alloc_.deallocate(prev,1); + } + it.node->first_child=0; + it.node->last_child=0; + // std::cout << "exit" << std::endl; +} + +template +template +iter tree::erase(iter it) +{ +#define CXL_IMP 0 +#if CXL_IMP + tree_node *cur=it.node; + assert(cur!=head); + iter ret=it; + ++ret; + + + children_iterator childIter = this->begin_children_iterator(it); + children_iterator childIterNext; + while(childIter != this->end_children_iterator(it)) + { + childIterNext = ++childIter; + erase(childIter); + childIter = childIterNext; + } + + + // + // + if(cur->prev_sibling==0) { + cur->parent->first_child=cur->next_sibling; + } + else { + cur->prev_sibling->next_sibling=cur->next_sibling; + } + + if(cur->next_sibling==0) { + cur->parent->last_child=cur->prev_sibling; + } + else { + cur->next_sibling->prev_sibling=cur->prev_sibling; + } + + kp::destructor(&cur->data); + alloc_.deallocate(cur,1); + return ret; +#else + tree_node *cur=it.node; + assert(cur!=head); + iter ret=it; + ++ret; + + + erase_children(it); + + + // + // + if(cur->prev_sibling==0) { + cur->parent->first_child=cur->next_sibling; + } + else { + cur->prev_sibling->next_sibling=cur->next_sibling; + } + + if(cur->next_sibling==0) { + cur->parent->last_child=cur->prev_sibling; + } + else { + cur->next_sibling->prev_sibling=cur->prev_sibling; + } + + kp::destructor(&cur->data); + alloc_.deallocate(cur,1); + return ret; +#endif +} + +template +typename tree::pre_order_iterator tree::root() const +{ + + return pre_order_iterator(head->next_sibling); +} + + +template +typename tree::pre_order_iterator tree::begin_pre_order_iterator(const iterator_base& pos) const +{ + + return pre_order_iterator(pos.node); +} + +template +typename tree::pre_order_iterator tree::end_pre_order_iterator(const iterator_base& pos) const +{ + + return pre_order_iterator(pos.node->next_sibling); +} + + +template +typename tree::breadth_first_queued_iterator tree::begin_breadth_first_iterator(const iterator_base& pos) const +{ + + return breadth_first_queued_iterator(pos.node); +} + +template +typename tree::breadth_first_queued_iterator tree::end_breadth_first_iterator(const iterator_base& pos) const +{ + + return breadth_first_queued_iterator(); +} + + +template +typename tree::post_order_iterator tree::begin_post_order_iterator(const iterator_base& pos) const +{ + + tree_node *tmp=pos.node; + if(tmp!=feet) { + while(tmp->first_child) + tmp=tmp->first_child; + } + return post_order_iterator(tmp); +} + +template +typename tree::post_order_iterator tree::end_post_order_iterator(const iterator_base& pos) const +{ + + return post_order_iterator(pos.node->next_sibling); +} + + +template +typename tree::children_iterator tree::begin_children_iterator(const iterator_base& pos) const +{ + + assert(pos.node!=0); + if(pos.node->first_child==0) { + return end_children_iterator(pos); + } + return pos.node->first_child; +} + +template +typename tree::children_iterator tree::end_children_iterator(const iterator_base& pos) const +{ + + + children_iterator ret(0); + ret.parent_=pos.node; + return ret; +} + +template +typename tree::leaf_iterator tree::begin_leaf_iterator(const iterator_base& top) const +{ + + tree_node *tmp=top.node; + while(tmp->first_child) + tmp=tmp->first_child; + return leaf_iterator(tmp, top.node); +} + +template +typename tree::leaf_iterator tree::end_leaf_iterator(const iterator_base& top) const +{ + + return leaf_iterator(top.node, top.node); +} + +template +typename tree::pre_order_iterator tree::parent(const iterator_base& position) +{ + + assert(position.node!=0); + return pre_order_iterator(position.node->parent); +} + +template +typename tree::pre_order_iterator tree::previous_sibling(const iterator_base& position) const +{ + + assert(position.node!=0); + pre_order_iterator ret(position); + ret.node=position.node->prev_sibling; + return ret; +} + +template +typename tree::pre_order_iterator tree::next_sibling(const iterator_base& position) const +{ + + assert(position.node!=0); + pre_order_iterator ret(position); + ret.node=position.node->next_sibling; + return ret; +} + +template +typename tree::pre_order_iterator tree::append_child(const iterator_base& position, const T& x) +{ + // If your program fails here you probably used 'append_child' to add the top + // node to an empty tree. From version 1.45 the top element should be added + // using 'insert_before'. See the documentation for further information, and sorry about + // the API change. + assert(position.node!=head); + assert(position.node); + + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->last_child!=0) { + position.node->last_child->next_sibling=tmp; + } + else { + position.node->first_child=tmp; + } + tmp->prev_sibling=position.node->last_child; + position.node->last_child=tmp; + tmp->next_sibling=0; + return pre_order_iterator(tmp); +} + +template +typename tree::pre_order_iterator tree::prepend_child(const iterator_base& position, const T& x) +{ + assert(position.node!=head); + assert(position.node); + + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->first_child!=0) { + position.node->first_child->prev_sibling=tmp; + } + else { + position.node->last_child=tmp; + } + tmp->next_sibling=position.node->first_child; + position.node->first_child=tmp; + tmp->prev_sibling=0; + return pre_order_iterator(tmp); +} + + +template +typename tree::pre_order_iterator tree::set_root(const T& x) +{ + assert(head->next_sibling==feet); + + return insert_before(pre_order_iterator(feet), x); +} + +template +typename tree::pre_order_iterator tree::insert_before(iterator_base& position, const T& x) +{ + if(position.node==0) { + position.node=feet; // Backward compatibility: when calling insert_before on a null node, + // insert_before before the feet. + } + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->next_sibling=position.node; + tmp->prev_sibling=position.node->prev_sibling; + position.node->prev_sibling=tmp; + + if(tmp->prev_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->first_child=tmp; + } + else + { + tmp->prev_sibling->next_sibling=tmp; + } + return pre_order_iterator(tmp); +} + + +template +typename tree::pre_order_iterator tree::insert_after(const iterator_base& position, const T& x) +{ + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->prev_sibling=position.node; + tmp->next_sibling=position.node->next_sibling; + position.node->next_sibling=tmp; + + if(tmp->next_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->last_child=tmp; + } + else { + tmp->next_sibling->prev_sibling=tmp; + } + return pre_order_iterator(tmp); +} + + +template +typename tree::pre_order_iterator tree::modify_data(const iterator_base& position, const T& x) +{ + kp::destructor(&position.node->data); + kp::constructor(&position.node->data, x); + return position; +} + +///set X as the new head of the tree, the old head will be a child of new head. +template +typename tree::pre_order_iterator tree::reparent_root(const T& x) +{ + if(head->next_sibling == feet) + { + return this->set_root(x); + } + else + { + //remember the old head + tree_node *old_head_node = head->next_sibling; + + //create a new head + insert_before(pre_order_iterator(feet), x); + + //change the tree head + tree_node *new_head_node = head->next_sibling->next_sibling; + head->next_sibling = new_head_node; + + //change the new head + new_head_node->first_child = old_head_node; + new_head_node->last_child = old_head_node; + new_head_node->next_sibling = feet; + new_head_node->prev_sibling = head; + + //change the feet + feet->prev_sibling = new_head_node; + + //change the old head + old_head_node->next_sibling = 0; + old_head_node->prev_sibling = 0; + old_head_node->parent = new_head_node; + + return begin_pre_order_iterator(root()); + } +} + +template +typename tree::pre_order_iterator tree::move_after(const iterator_base& target, const iterator_base& source) +{ + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return this->begin_pre_order_iterator(source); + if(dst->next_sibling) + if(dst->next_sibling==src) // already in the right spot + return this->begin_pre_order_iterator(source); + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst->next_sibling!=0) dst->next_sibling->prev_sibling=src; + else dst->parent->last_child=src; + src->next_sibling=dst->next_sibling; + dst->next_sibling=src; + src->prev_sibling=dst; + src->parent=dst->parent; + return pre_order_iterator(src); +} + +template +typename tree::pre_order_iterator tree::move_before(const iterator_base& target, const iterator_base& source) +{ + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return this->begin_pre_order_iterator(source); + if(dst->prev_sibling) + if(dst->prev_sibling==src) // already in the right spot + return this->begin_pre_order_iterator(source); + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst->prev_sibling!=0) dst->prev_sibling->next_sibling=src; + else dst->parent->first_child=src; + src->prev_sibling=dst->prev_sibling; + dst->prev_sibling=src; + src->next_sibling=dst; + src->parent=dst->parent; + return pre_order_iterator(src); +} + + +template +size_t tree::size() const +{ + size_t i=0; + pre_order_iterator it=begin_pre_order_iterator(), eit=end_pre_order_iterator(); + while(it!=eit) { + ++i; + ++it; + } + return i; +} + +template +size_t tree::size(const iterator_base& top) const +{ + size_t i=0; + pre_order_iterator it=top, eit=top; + ++eit; + while(it!=eit) { + ++i; + ++it; + } + return i; +} + +template +bool tree::empty() const +{ + pre_order_iterator it=begin_pre_order_iterator(), eit=end_pre_order_iterator(); + return (it==eit); +} + +template +int tree::depth(const iterator_base& it) +{ + tree_node* pos=it.node; + assert(pos!=0); + int ret=0; + while(pos->parent!=0) { + pos=pos->parent; + ++ret; + } + return ret; +} + +template +int tree::depth(const iterator_base& it, const iterator_base& root) +{ + tree_node* pos=it.node; + assert(pos!=0); + int ret=0; + while(pos->parent!=0 && pos!=root.node) { + pos=pos->parent; + ++ret; + } + return ret; +} + +template +int tree::max_depth() const +{ + int maxd=-1; + for(tree_node *it = head->next_sibling; it!=feet; it=it->next_sibling) + { + + maxd=std::max(maxd, max_depth(it)); + } + + return maxd; +} + + +template +int tree::max_depth(const iterator_base& pos) const +{ + + tree_node *tmp=pos.node; + + if(tmp==0 || tmp==head || tmp==feet) return -1; + + int curdepth=0, maxdepth=0; + while(true) { // try to walk the bottom of the tree + while(tmp->first_child==0) + { + if(tmp==pos.node) return maxdepth; + if(tmp->next_sibling==0) + { + // try to walk up and then right again + do { + tmp=tmp->parent; + if(tmp==0) return maxdepth; + --curdepth; + } while(tmp->next_sibling==0); + } + + + + if(tmp==pos.node) return maxdepth; + tmp=tmp->next_sibling; + } + + tmp=tmp->first_child; + ++curdepth; + maxdepth=std::max(curdepth, maxdepth); + } +} + +template +unsigned int tree::number_of_children(const iterator_base& it) +{ + tree_node *pos=it.node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; + // while(pos!=it.node->last_child) { + // ++ret; + // pos=pos->next_sibling; + // } + while((pos=pos->next_sibling)) + ++ret; + return ret; +} + +template +bool tree::is_valid(const iterator_base& it) const +{ + if(it.node==0 || it.node==feet || it.node==head) return false; + else return true; +} + +// Iterator base + +template +tree::iterator_base::iterator_base() +: node(0) +{ +} + +template +tree::iterator_base::iterator_base(tree_node *tn) +: node(tn) +{ +} + +template +T& tree::iterator_base::operator*() const +{ + return node->data; +} + +template +T* tree::iterator_base::operator->() const +{ + return &(node->data); +} + +template +bool tree::post_order_iterator::operator!=(const post_order_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::post_order_iterator::operator==(const post_order_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +bool tree::pre_order_iterator::operator!=(const pre_order_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::pre_order_iterator::operator==(const pre_order_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +bool tree::children_iterator::operator!=(const children_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::children_iterator::operator==(const children_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +bool tree::leaf_iterator::operator!=(const leaf_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::leaf_iterator::operator==(const leaf_iterator& other) const +{ + if(other.node==this->node && other.top_node==this->top_node) return true; + else return false; +} + + +template +typename tree::children_iterator tree::iterator_base::begin_children_iterator() const +{ + if(node->first_child==0) + return end_children_iterator(); + + children_iterator ret(node->first_child); + ret.parent_=this->node; + return ret; +} + +template +typename tree::children_iterator tree::iterator_base::end_children_iterator() const +{ + children_iterator ret(0); + ret.parent_=node; + return ret; +} + +template +unsigned int tree::iterator_base::number_of_children() const +{ + tree_node *pos=node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; + while(pos!=node->last_child) { + ++ret; + pos=pos->next_sibling; + } + return ret; +} + + + +// Pre-order iterator + +template +tree::pre_order_iterator::pre_order_iterator() +: iterator_base(0) +{ +} + +template +tree::pre_order_iterator::pre_order_iterator(tree_node *tn) +: iterator_base(tn) +{ +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator++() +{ + assert(this->node!=0); + if(this->node->first_child != 0) { + this->node=this->node->first_child; + } + else { + while(this->node->next_sibling==0) { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + this->node=this->node->next_sibling; + } + return *this; + + +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator--() +{ + assert(this->node!=0); + if(this->node->prev_sibling) { + this->node=this->node->prev_sibling; + while(this->node->last_child) + this->node=this->node->last_child; + } + else { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + return *this; + + +} + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator++(int) +{ + pre_order_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator--(int) +{ + pre_order_iterator copy = *this; + --(*this); + return copy; +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + + + +// Post-order iterator + +template +tree::post_order_iterator::post_order_iterator() +: iterator_base(0) +{ +} + +template +tree::post_order_iterator::post_order_iterator(tree_node *tn) +: iterator_base(tn) +{ +} + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator++() +{ + assert(this->node!=0); + if(this->node->next_sibling==0) { + this->node=this->node->parent; + } + else { + this->node=this->node->next_sibling; + while(this->node->first_child) + this->node=this->node->first_child; + } + return *this; + +} + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator--() +{ + assert(this->node!=0); + if(this->node->last_child==0) + { + + while(this->node->prev_sibling==0) + { + this->node=this->node->parent; + } + this->node=this->node->prev_sibling; + } + else + { + this->node=this->node->last_child; + } + return *this; + +} + +template +typename tree::post_order_iterator tree::post_order_iterator::operator++(int) +{ + post_order_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::post_order_iterator tree::post_order_iterator::operator--(int) +{ + post_order_iterator copy = *this; + --(*this); + return copy; +} + + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + +template +void tree::post_order_iterator::descend_all() +{ + assert(this->node!=0); + while(this->node->first_child) + this->node=this->node->first_child; +} + + +// Breadth-first iterator + +template +tree::breadth_first_queued_iterator::breadth_first_queued_iterator() +: iterator_base() +{ +} + +template +tree::breadth_first_queued_iterator::breadth_first_queued_iterator(tree_node *tn) +: iterator_base(tn) +{ + traversal_queue.push(tn); +} + +template +bool tree::breadth_first_queued_iterator::operator!=(const breadth_first_queued_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::breadth_first_queued_iterator::operator==(const breadth_first_queued_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator++() +{ + assert(this->node!=0); + + // Add child nodes and pop current node + children_iterator sib=this->begin_children_iterator(); + while(sib!=this->end_children_iterator()) { + traversal_queue.push(sib.node); + ++sib; + } + traversal_queue.pop(); + if(traversal_queue.size()>0) + this->node=traversal_queue.front(); + else + this->node=0; + return (*this); +} + +template +typename tree::breadth_first_queued_iterator tree::breadth_first_queued_iterator::operator++(int) +{ + breadth_first_queued_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +// Sibling iterator + +template +tree::children_iterator::children_iterator() +: iterator_base() +{ + set_parent_(); +} + +template +tree::children_iterator::children_iterator(tree_node *tn) +: iterator_base(tn) +{ + set_parent_(); +} + +template +void tree::children_iterator::set_parent_() +{ + parent_=0; + if(this->node==0) return; + if(this->node->parent!=0) + parent_=this->node->parent; +} + +template +typename tree::children_iterator& tree::children_iterator::operator++() +{ + if(this->node) + this->node=this->node->next_sibling; + return *this; +} + +template +typename tree::children_iterator& tree::children_iterator::operator--() +{ + if(this->node) this->node=this->node->prev_sibling; + else { + assert(parent_); + this->node=parent_->last_child; + } + return *this; +} + +template +typename tree::children_iterator tree::children_iterator::operator++(int) +{ + children_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::children_iterator tree::children_iterator::operator--(int) +{ + children_iterator copy = *this; + --(*this); + return copy; +} + +template +typename tree::children_iterator& tree::children_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::children_iterator& tree::children_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + +template +typename tree::tree_node *tree::children_iterator::range_first() const +{ + tree_node *tmp=parent_->first_child; + return tmp; +} + +template +typename tree::tree_node *tree::children_iterator::range_last() const +{ + return parent_->last_child; +} + +// Leaf iterator + +template +tree::leaf_iterator::leaf_iterator() +: iterator_base(0), top_node(0) +{ +} + +template +tree::leaf_iterator::leaf_iterator(tree_node *tn, tree_node *top) +: iterator_base(tn), top_node(top) +{ +} + + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator++() +{ + assert(this->node!=0); + if(this->node->first_child!=0) { // current node is no longer leaf (children got added) + while(this->node->first_child) + this->node=this->node->first_child; + } + else { + while(this->node->next_sibling==0) { + if (this->node->parent==0) return *this; + this->node=this->node->parent; + if (top_node != 0 && this->node==top_node) return *this; + } + this->node=this->node->next_sibling; + while(this->node->first_child) + this->node=this->node->first_child; + } + return *this; + +} + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator--() +{ + assert(this->node!=0); + while (this->node->prev_sibling==0) { + if (this->node->parent==0) return *this; + this->node=this->node->parent; + if (top_node !=0 && this->node==top_node) return *this; + } + this->node=this->node->prev_sibling; + while(this->node->last_child) + this->node=this->node->last_child; + return *this; +} + +template +typename tree::leaf_iterator tree::leaf_iterator::operator++(int) +{ + leaf_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::leaf_iterator tree::leaf_iterator::operator--(int) +{ + leaf_iterator copy = *this; + --(*this); + return copy; +} + + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + +#endif diff --git a/lib/tree-2.81/src/test1.cc b/lib/tree-2.81/src/test1.cc new file mode 100644 index 0000000..5bb2fdf --- /dev/null +++ b/lib/tree-2.81/src/test1.cc @@ -0,0 +1,18 @@ +#include "tree.hh" +#include "tree_util.hh" + +int main(int, char **) + { + tree tr; + + tr.insert(tr.begin(), 1); + tree::iterator i2 = tr.insert(tr.end(), 2); + tree::iterator i3 = tr.insert(tr.end(), 3); + tr.append_child(i2, 21); + tr.append_child(i3, 31); + tree::iterator i4 = tr.insert(tr.end(), 4); + + kptree::print_tree_bracketed(tr, std::cout); + + std::cout << std::endl; + } diff --git a/lib/tree-2.81/src/test1.req b/lib/tree-2.81/src/test1.req new file mode 100644 index 0000000..e2e3a45 --- /dev/null +++ b/lib/tree-2.81/src/test1.req @@ -0,0 +1,4 @@ +1 +2(21) +3(31) +4 diff --git a/lib/tree-2.81/src/test_tree.cc b/lib/tree-2.81/src/test_tree.cc new file mode 100644 index 0000000..6f1bf1c --- /dev/null +++ b/lib/tree-2.81/src/test_tree.cc @@ -0,0 +1,378 @@ +/* + + STL-like templated tree class; test program. + Copyright (C) 2001-2009 Kasper Peeters + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include "tree.hh" +#include "tree_util.hh" + +#include +#include +#include +#include +#include +#include +#include + +/* + + Simple test program for the tree.hh class library. Run it and see + what happens. Or, if you want to see that it does not leak memory, + run it like + + ./test_tree 10000 >/dev/null + + or some other large number and have 'top' running in a different + shell. This will run the tests 10000 times, creating and destroying + the trees for every iteration of the loop. + + */ + +bool truefunc(std::string& one, std::string& two) + { +// std::cout << "comparing " << one << "==" << two << std::endl; + return true; + } + +void print_tree(const tree& tr, tree::pre_order_iterator it, tree::pre_order_iterator end) + { + if(!tr.is_valid(it)) return; + int rootdepth=tr.depth(it); + std::cout << "-----" << std::endl; + while(it!=end) { + for(int i=0; i& tr, tree::post_order_iterator it, tree::post_order_iterator end) + { + int rootdepth=tr.depth(it); + std::cout << "-----" << std::endl; + while(it!=end) { + for(int i=0; i& tr, tree::pre_order_iterator it, tree::pre_order_iterator end) + { + --it; + int rootdepth=0;//tr.depth(it); + std::cout << "-----" << std::endl; + while(1==1) { + for(int i=0; i& tr, tree::post_order_iterator it, tree::post_order_iterator end) + { + --it; + int rootdepth=0;//tr.depth(it); + std::cout << "-----" << std::endl; + while(1==1) { + for(int i=0; i1) + maxloop=atoi(argv[1]); + + for(unsigned int j=0; j tr9; + tr9.set_head("hi"); + tr9.insert(tr9.begin().begin(), "0"); + tr9.insert(tr9.begin().begin(), "1"); + print_tree(tr9, tr9.begin(), tr9.end()); + + + tree tr; + tree::pre_order_iterator html, body, h1, h3, bh1, mv1; + + std::cout << "empty tree to begin with:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + + html=tr.insert(tr.begin(), "html"); + tr.insert(html,"extra"); +// tr.insert(html,"zextra2"); + body=tr.append_child(html, "body"); + h1 =tr.append_child(body, "h1"); + std::cout << tr.index(h1) << std::endl; + bh1 =tr.insert(h1,"before h1"); + tr.append_child(h1, "some text"); + tree::sibling_iterator more_text=tr.append_child(body, "more text"); + + std::cout << " 'more text' is sibling " << tr.index(more_text) << " in its sibling range" << std::endl; + + std::cout << "filled tree:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + + std::cout << "filled tree, post-order traversal:" << std::endl; + print_tree_post(tr, tr.begin_post(), tr.end_post()); + + tr.swap(bh1); + std::cout << "swapped elements:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + tr.swap(h1); + std::cout << "swapped back:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + + tree copytree(h1); + std::cout << "copied tree:" << std::endl; + print_tree(copytree, copytree.begin(), copytree.end()); + + // Now test the STL algorithms + std::cout << "result of search for h1 and kasper:" << std::endl; + tree::pre_order_iterator it; + it=std::find(tr.begin(),tr.end(),std::string("h1")); + if(it!=tr.end()) print_tree(tr, it, tr.next_sibling(it)); + else std::cout << "h1 not found" << std::endl; + it=std::find(tr.begin(),tr.end(), std::string("kasper")); + if(it!=tr.end()) print_tree(tr, it, tr.next_sibling(it)); + else std::cout << "kasper not found" << std::endl; + std::cout << std::endl; + + // remove the h1, replace it with new subtree + tree replacement; + h3 =replacement.insert(replacement.begin(), "h3"); + replacement.append_child(h3, "text in h3"); + std::cout << "replacement tree:" << std::endl; + print_tree(replacement, replacement.begin(), replacement.end()); + print_tree(tr, tr.begin(), tr.end()); + h1=tr.replace(tree::sibling_iterator(h1), tr.next_sibling(h1), + tree::sibling_iterator(h3), tr.next_sibling(h3)); + std::cout << "filled tree with replacement done:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + + // replace h3 node while keeping children + h1=tr.replace(h1, ""); + print_tree(tr, tr.begin(), tr.end()); + + // add a sibling to the head + tr.insert_after(h1, "more"); + + // Copy object. + tree tr2=tr; + print_tree(tr2, tr2.begin(), tr2.end()); + tree tr3(tr); + + // reparent "before h1" to h3 node + tr.reparent(h1, bh1, tr.next_sibling(bh1)); + std::cout << "moved content:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + + // iterate over children only + tree::sibling_iterator ch=tr.begin(h1); + std::cout << "children of h1:" << std::endl; + while(ch!=tr.end(h1)) { + std::cout << (*ch) << std::endl; + ++ch; + } + std::cout << std::endl; + + // flatten the h3 node + tr.flatten(h1); + std::cout << "flattened (at h3) tree:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + + // Erase the subtree of tr below body. + tr.erase_children(body); + std::cout << "children of body erased:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + it=std::find(tr.begin(),tr.end(),"h1"); + if(it!=tr.end()) print_tree(tr, it, tr.next_sibling(it)); + else std::cout << "h1 not found" << std::endl; + + // Erase everything + tr.erase(tr.begin()); + std::cout << "erased tree:" << std::endl; + print_tree(tr, tr.begin(), tr.end()); + + // The copies are deep, ie. all nodes have been copied. + std::cout << "copies still exist:" << std::endl; + print_tree(tr2, tr2.begin(), tr2.end()); + print_tree(tr3, tr3.begin(), tr3.end()); + + // Test comparison + std::cout << "testing comparison functions:" << std::endl; + std::cout << std::equal(tr2.begin(), tr2.end(), tr3.begin(), std::equal_to()) + << " (should be 1)" << std::endl; + // modify content but not structure + tree::pre_order_iterator fl3=tr3.begin(); + fl3+=4; // pointing to "" node + std::cout << (*fl3) << std::endl; + std::string tmpfl3=(*fl3); + (*fl3)="modified"; + std::cout << std::equal(tr2.begin(), tr2.end(), tr3.begin(), std::equal_to()) + << " (should be 0)" << std::endl; + std::cout << tr2.equal(tr2.begin(), tr2.end(), tr3.begin(), std::equal_to()) + << " (should be 0)" << std::endl; + std::cout << tr2.equal(tr2.begin(), tr2.end(), tr3.begin(), truefunc) + << " (should be 1)" << std::endl; + // modify tr3 structure (but not content) + (*fl3)=tmpfl3; + tr3.flatten(fl3); + std::cout << "tree flattened, test again" << std::endl; + print_tree(tr3, tr3.begin(), tr3.end()); + + // Test comparison again + std::cout << tr2.equal(tr2.begin(), tr2.end(), tr3.begin(), std::equal_to()) + << " (should be 0)" << std::endl; + std::cout << std::equal(tr2.begin(), tr2.end(), tr3.begin(), std::equal_to()) + << " (should be 1)" << std::endl; + // Change content + (*fl3)="modified"; + // Test comparison again + std::cout << std::equal(tr2.begin(), tr2.end(), tr3.begin(), std::equal_to()) + << " (should be 0)" << std::endl; + std::cout << tr2.equal(tr2.begin(), tr2.end(), tr3.begin(), std::equal_to()) + << " (should be 0)" << std::endl; + + // Testing sort. First add a subtree to one leaf + tree::pre_order_iterator txx3=tr3.begin(); + txx3+=5; + tr3.append_child(txx3,"ccc"); + tr3.append_child(txx3,"bbb"); + tr3.append_child(txx3,"bbb"); + tr3.append_child(txx3,"aaa"); + std::less comp; + tree::pre_order_iterator bdy=tr3.begin(); + bdy+=2; + assert(tr.is_valid(bdy)); + std::cout << "unsorted subtree:" << std::endl; + print_tree(tr3, tr3.begin(), tr3.end()); + tree::sibling_iterator sortit1=tr3.begin(bdy), sortit2=tr3.begin(bdy); + sortit1+=2; + sortit2+=4; + assert(tr.is_valid(sortit1)); + assert(tr.is_valid(sortit2)); + std::cout << "partially sorted subtree: (" + << "sorted from " << (*sortit1) << " to " + << (*sortit2) << ", excluding the last element)" << std::endl; + + + mv1=tr3.begin(); + ++mv1; + tr3.sort(sortit1, sortit2); + print_tree(tr3, tr3.begin(), tr3.end()); + tr3.sort(tr3.begin(bdy), tr3.end(bdy), comp, true); // false: no sorting of subtrees +// Sorting the entire tree, level by level, is much simpler: +// tr3.sort(tr3.begin(), tr3.end(), true); + std::cout << "sorted subtree:" << std::endl; + print_tree(tr3, tr3.begin(), tr3.end()); + + // Michael's problem +// std::cout << mv1.node << ", " << tr3.feet << ", " << tr3.feet->prev_sibling << std::endl; +// std::cout << mv1.node->next_sibling << ", " << tr3.feet->prev_sibling << ", " << tr3.end().node << std::endl; +// tr3.sort(tr3.begin(), tr3.end(), true); +// std::cout << mv1.node << ", " << tr3.feet << ", " << tr3.feet->prev_sibling << std::endl; +// std::cout << mv1.node->next_sibling << ", " << tr3.feet->prev_sibling << ", " << tr3.end().node << std::endl; +// print_tree(tr3, tr3.begin(), tr3.end()); +// tr3.sort(tr3.begin(), tr3.end(), true); +// std::cout << mv1.node << ", " << tr3.feet << ", " << tr3.feet->prev_sibling << std::endl; +// std::cout << mv1.node->next_sibling << ", " << tr3.feet->prev_sibling << ", " << tr3.end().node << std::endl; +// print_tree(tr3, tr3.begin(), tr3.end()); +// return 1; + + // Test merge algorithm. + std::cout << "test merge" << std::endl; + tree mtree; + tree::pre_order_iterator mt1, mt2, mt3; + mt1=mtree.insert(mtree.begin(),"html"); + mt2=mtree.append_child(mt1,"head"); + mt3=mtree.append_child(mt1,"body"); +// Adding it without head having any children tests whether we can +// insert at the end of an empty list of children. + mtree.append_child(mt2,"title"); + mtree.append_child(mt3,"h1"); + mtree.append_child(mt3,"h1"); + + tree mtBree; + tree::pre_order_iterator mtB1, mtB2; + mtB1=mtBree.insert(mtBree.begin(),"head"); + mtB2=mtBree.append_child(mtB1,"another title"); + print_tree(mtree, mtree.begin(), mtree.end()); + print_tree(mtBree, mtBree.begin(), mtBree.end()); + + mtree.merge(mtree.begin(), mtree.end(), mtBree.begin(), mtBree.end(), true); + print_tree(mtree, mtree.begin(), mtree.end()); + mtree.merge(mtree.begin(mtree.begin()), mtree.end(mtree.begin()), mtBree.begin(), mtBree.end(), true); + print_tree(mtree, mtree.begin(), mtree.end()); + + // Print tree in reverse (test operator--) + print_tree_rev(mtree, mtree.end(), mtree.begin()); + print_tree_rev_post(mtree, mtree.end_post(), mtree.begin_post()); + + // Breadth-first + tree bft; + tree::iterator bfB,bfC,bfD; + bft.set_head("A"); + bfB=bft.append_child(bft.begin(), "B"); + bfC=bft.append_child(bft.begin(), "C"); + bfD=bft.append_child(bft.begin(), "D"); + bft.append_child(bfB, "E"); + bft.append_child(bfB, "F"); + bft.append_child(bfC, "G"); + bft.append_child(bfC, "H"); + bft.append_child(bfD, "I"); + tree::breadth_first_queued_iterator bfq=bft.begin_breadth_first(); + while(bfq!=bft.end_breadth_first()) { + std::cout << *bfq << std::endl; + ++bfq; + } + + print_tree(bft, bft.begin(), bft.end()); + bft.wrap(bfD, "wrap"); + print_tree(bft, bft.begin(), bft.end()); + + tree::leaf_iterator li=tr.begin_leaf(bfC); + while(li!=tr.end_leaf(bfC)) { + std::cout << *li << std::endl; + ++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; +// } + } + } diff --git a/lib/tree-2.81/src/test_tree.output b/lib/tree-2.81/src/test_tree.output new file mode 100644 index 0000000..f6b0848 --- /dev/null +++ b/lib/tree-2.81/src/test_tree.output @@ -0,0 +1,311 @@ +empty tree to begin with: +0 + 'more text' is sibling 2 in its sibling range +filled tree: +----- +extra +html + body + before h1 + h1 + some text + more text +----- +filled tree, post-order traversal: +----- +extra + before h1 + some text + h1 + more text + body +html +----- +swapped elements: +----- +extra +html + body + h1 + some text + before h1 + more text +----- +swapped back: +----- +extra +html + body + before h1 + h1 + some text + more text +----- +copied tree: +----- +h1 + some text +----- +result of search for h1 and kasper: +----- +h1 + some text +----- +kasper not found + +replacement tree: +----- +h3 + text in h3 +----- +----- +extra +html + body + before h1 + h1 + some text + more text +----- +filled tree with replacement done: +----- +extra +html + body + before h1 + h3 + text in h3 + more text +----- +----- +extra +html + body + before h1 + + text in h3 + more text +----- +----- +extra +html + body + before h1 + + text in h3 + more + more text +----- +moved content: +----- +extra +html + body + + text in h3 + before h1 + more + more text +----- +children of h1: +text in h3 +before h1 + +flattened (at h3) tree: +----- +extra +html + body + + text in h3 + before h1 + more + more text +----- +children of body erased: +----- +extra +html + body +----- +h1 not found +erased tree: +----- +html + body +----- +copies still exist: +----- +extra +html + body + before h1 + + text in h3 + more + more text +----- +----- +extra +html + body + before h1 + + text in h3 + more + more text +----- +testing comparison functions: +1 (should be 1) + +0 (should be 0) +0 (should be 0) +1 (should be 1) +tree flattened, test again +----- +extra +html + body + before h1 + + text in h3 + more + more text +----- +0 (should be 0) +1 (should be 1) +0 (should be 0) +0 (should be 0) +unsorted subtree: +----- +extra +html + body + before h1 + modified + text in h3 + ccc + bbb + bbb + aaa + more + more text +----- +partially sorted subtree: (sorted from text in h3 to more text, excluding the last element) +----- +extra +html + body + before h1 + modified + more + text in h3 + ccc + bbb + bbb + aaa + more text +----- +sorted subtree: +----- +extra +html + body + before h1 + modified + more + more text + text in h3 + aaa + bbb + bbb + ccc +----- +test merge +----- +html + head + title + body + h1 + h1 +----- +----- +head + another title +----- +----- +html + head + title + body + h1 + h1 +head + another title +----- +----- +html + head + title + another title + body + h1 + h1 +head + another title +----- +----- + another title +head + h1 + h1 + body + another title + title + head +html +----- +----- +head + another title +html + body + h1 + h1 + head + another title + title +----- +A +B +C +D +E +F +G +H +I +----- +A + B + E + F + C + G + H + D + I +----- +----- +A + B + E + F + C + G + H + wrap + D + I +----- diff --git a/lib/tree-2.81/src/tree.hh b/lib/tree-2.81/src/tree.hh new file mode 100644 index 0000000..b2f3005 --- /dev/null +++ b/lib/tree-2.81/src/tree.hh @@ -0,0 +1,2786 @@ + +// STL-like templated tree class. +// +// Copyright (C) 2001-2011 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. + +/** \mainpage tree.hh + \author Kasper Peeters + \version 2.81 + \date 23-Aug-2011 + \see http://tree.phi-sci.com/ + \see http://tree.phi-sci.com/ChangeLog + + The tree.hh library for C++ provides an STL-like container class + for n-ary trees, templated over the data stored at the + nodes. Various types of iterators are provided (post-order, + pre-order, and others). Where possible the access methods are + compatible with the STL or alternative algorithms are + available. +*/ + + +#ifndef tree_hh_ +#define tree_hh_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/// A node in the tree, combining links to other nodes as well as the actual data. +template +class tree_node_ { // size: 5*4=20 bytes (on 32 bit arch), can be reduced by 8. + public: + tree_node_(); + tree_node_(const T&); + + tree_node_ *parent; + tree_node_ *first_child, *last_child; + tree_node_ *prev_sibling, *next_sibling; + T data; +}; // __attribute__((packed)); + +template +tree_node_::tree_node_() + : parent(0), first_child(0), last_child(0), prev_sibling(0), next_sibling(0) + { + } + +template +tree_node_::tree_node_(const T& val) + : parent(0), first_child(0), last_child(0), prev_sibling(0), next_sibling(0), data(val) + { + } + +template > > +class tree { + protected: + typedef tree_node_ tree_node; + public: + /// Value of the data stored at a node. + typedef T value_type; + + class iterator_base; + class pre_order_iterator; + class post_order_iterator; + class sibling_iterator; + class leaf_iterator; + + tree(); + tree(const T&); + tree(const iterator_base&); + tree(const tree&); + ~tree(); + tree& operator=(const tree&); + + /// Base class for iterators, only pointers stored, no traversal logic. +#ifdef __SGI_STL_PORT + class iterator_base : public stlport::bidirectional_iterator { +#else + class iterator_base { +#endif + public: + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + iterator_base(); + iterator_base(tree_node *); + + T& operator*() const; + T* operator->() const; + + /// When called, the next increment/decrement skips children of this node. + void skip_children(); + void skip_children(bool skip); + /// Number of children of the node pointed to by the iterator. + unsigned int number_of_children() const; + + sibling_iterator begin() const; + sibling_iterator end() const; + + tree_node *node; + protected: + bool skip_current_children_; + }; + + /// Depth-first iterator, first accessing the node, then its children. + class pre_order_iterator : public iterator_base { + public: + pre_order_iterator(); + pre_order_iterator(tree_node *); + pre_order_iterator(const iterator_base&); + pre_order_iterator(const sibling_iterator&); + + bool operator==(const pre_order_iterator&) const; + bool operator!=(const pre_order_iterator&) const; + pre_order_iterator& operator++(); + pre_order_iterator& operator--(); + pre_order_iterator operator++(int); + pre_order_iterator operator--(int); + pre_order_iterator& operator+=(unsigned int); + pre_order_iterator& operator-=(unsigned int); + }; + + /// Depth-first iterator, first accessing the children, then the node itself. + class post_order_iterator : public iterator_base { + public: + post_order_iterator(); + post_order_iterator(tree_node *); + post_order_iterator(const iterator_base&); + post_order_iterator(const sibling_iterator&); + + bool operator==(const post_order_iterator&) const; + bool operator!=(const post_order_iterator&) const; + post_order_iterator& operator++(); + post_order_iterator& operator--(); + post_order_iterator operator++(int); + post_order_iterator operator--(int); + post_order_iterator& operator+=(unsigned int); + post_order_iterator& operator-=(unsigned int); + + /// Set iterator to the first child as deep as possible down the tree. + void descend_all(); + }; + + /// Breadth-first iterator, using a queue + class breadth_first_queued_iterator : public iterator_base { + public: + breadth_first_queued_iterator(); + breadth_first_queued_iterator(tree_node *); + breadth_first_queued_iterator(const iterator_base&); + + bool operator==(const breadth_first_queued_iterator&) const; + bool operator!=(const breadth_first_queued_iterator&) const; + breadth_first_queued_iterator& operator++(); + breadth_first_queued_iterator operator++(int); + breadth_first_queued_iterator& operator+=(unsigned int); + + private: + std::queue traversal_queue; + }; + + /// The default iterator types throughout the tree class. + typedef pre_order_iterator iterator; + typedef breadth_first_queued_iterator breadth_first_iterator; + + /// Iterator which traverses only the nodes at a given depth from the root. + class fixed_depth_iterator : public iterator_base { + public: + fixed_depth_iterator(); + fixed_depth_iterator(tree_node *); + fixed_depth_iterator(const iterator_base&); + fixed_depth_iterator(const sibling_iterator&); + fixed_depth_iterator(const fixed_depth_iterator&); + + bool operator==(const fixed_depth_iterator&) const; + bool operator!=(const fixed_depth_iterator&) const; + fixed_depth_iterator& operator++(); + fixed_depth_iterator& operator--(); + fixed_depth_iterator operator++(int); + fixed_depth_iterator operator--(int); + fixed_depth_iterator& operator+=(unsigned int); + fixed_depth_iterator& operator-=(unsigned int); + + tree_node *top_node; + }; + + /// Iterator which traverses only the nodes which are siblings of each other. + class sibling_iterator : public iterator_base { + public: + sibling_iterator(); + sibling_iterator(tree_node *); + sibling_iterator(const sibling_iterator&); + sibling_iterator(const iterator_base&); + + bool operator==(const sibling_iterator&) const; + bool operator!=(const sibling_iterator&) const; + sibling_iterator& operator++(); + sibling_iterator& operator--(); + sibling_iterator operator++(int); + sibling_iterator operator--(int); + sibling_iterator& operator+=(unsigned int); + sibling_iterator& operator-=(unsigned int); + + tree_node *range_first() const; + tree_node *range_last() const; + tree_node *parent_; + private: + void set_parent_(); + }; + + /// Iterator which traverses only the leaves. + class leaf_iterator : public iterator_base { + public: + leaf_iterator(); + leaf_iterator(tree_node *, tree_node *top=0); + leaf_iterator(const sibling_iterator&); + leaf_iterator(const iterator_base&); + + bool operator==(const leaf_iterator&) const; + bool operator!=(const leaf_iterator&) const; + leaf_iterator& operator++(); + leaf_iterator& operator--(); + leaf_iterator operator++(int); + leaf_iterator operator--(int); + leaf_iterator& operator+=(unsigned int); + leaf_iterator& operator-=(unsigned int); + private: + tree_node *top_node; + }; + + /// Return iterator to the beginning of the tree. + inline pre_order_iterator begin() const; + /// Return iterator to the end of the tree. + inline pre_order_iterator end() const; + /// Return post-order iterator to the beginning of the tree. + post_order_iterator begin_post() const; + /// Return post-order end iterator of the tree. + post_order_iterator end_post() const; + /// Return fixed-depth iterator to the first node at a given depth from the given iterator. + fixed_depth_iterator begin_fixed(const iterator_base&, unsigned int) const; + /// Return fixed-depth end iterator. + fixed_depth_iterator end_fixed(const iterator_base&, unsigned int) const; + /// Return breadth-first iterator to the first node at a given depth. + breadth_first_queued_iterator begin_breadth_first() const; + /// Return breadth-first end iterator. + breadth_first_queued_iterator end_breadth_first() const; + /// Return sibling iterator to the first child of given node. + sibling_iterator begin(const iterator_base&) const; + /// Return sibling end iterator for children of given node. + sibling_iterator end(const iterator_base&) const; + /// Return leaf iterator to the first leaf of the tree. + leaf_iterator begin_leaf() const; + /// Return leaf end iterator for entire tree. + leaf_iterator end_leaf() const; + /// Return leaf iterator to the first leaf of the subtree at the given node. + leaf_iterator begin_leaf(const iterator_base& top) const; + /// Return leaf end iterator for the subtree at the given node. + leaf_iterator end_leaf(const iterator_base& top) const; + + /// 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; + /// Return iterator to the next sibling of a node. + template iter next_sibling(iter) const; + /// Return iterator to the next node at a given depth. + template iter next_at_same_depth(iter) const; + + /// Erase all nodes of the tree. + void clear(); + /// Erase element at position pointed to by iterator, return incremented iterator. + template iter erase(iter); + /// Erase all children of the node pointed to by iterator. + void erase_children(const iterator_base&); + + /// Insert empty node as last/first child of node pointed to by position. + template iter append_child(iter position); + template iter prepend_child(iter position); + /// Insert node as last/first child of node pointed to by position. + template iter append_child(iter position, const T& x); + template iter prepend_child(iter position, const T& x); + /// Append the node (plus its children) at other_position as last/first child of position. + template iter append_child(iter position, iter other_position); + template iter prepend_child(iter position, iter other_position); + /// Append the nodes in the from-to range (plus their children) as last/first children of position. + template iter append_children(iter position, sibling_iterator from, sibling_iterator to); + template iter prepend_children(iter position, sibling_iterator from, sibling_iterator to); + + /// Short-hand to insert topmost node in otherwise empty tree. + pre_order_iterator set_head(const T& x); + /// Insert node as previous sibling of node pointed to by position. + template iter insert(iter position, const T& x); + /// 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. + 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); + /// Insert node (with children) pointed to by subtree as next sibling of node pointed to by position. + template iter insert_subtree_after(iter position, const iterator_base& subtree); + + /// Replace node at 'position' with other node (keeping same children); 'position' becomes invalid. + template iter replace(iter position, const T& x); + /// Replace node at 'position' with subtree starting at 'from' (do not erase subtree at 'from'); see above. + template iter replace(iter position, const iterator_base& from); + /// Replace string of siblings (plus their children) with copy of a new string (with children); see above + sibling_iterator replace(sibling_iterator orig_begin, sibling_iterator orig_end, + sibling_iterator new_begin, sibling_iterator new_end); + + /// Move all children of node at 'position' to be siblings, returns position. + template iter flatten(iter position); + /// Move nodes in range to be children of 'position'. + template iter reparent(iter position, sibling_iterator begin, sibling_iterator end); + /// Move all child nodes of 'from' to be children of 'position'. + template iter reparent(iter position, iter from); + + /// Replace node with a new node, making the old node a child of the new node. + template iter wrap(iter position, const T& x); + + /// Move 'source' node (plus its children) to become the next sibling of 'target'. + template iter move_after(iter target, iter source); + /// Move 'source' node (plus its children) to become the previous sibling of 'target'. + template iter move_before(iter target, iter source); + sibling_iterator move_before(sibling_iterator target, sibling_iterator source); + /// 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); + + /// 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); + /// Sort (std::sort only moves values of nodes, this one moves children as well). + void sort(sibling_iterator from, sibling_iterator to, bool deep=false); + template + void sort(sibling_iterator from, sibling_iterator to, StrictWeakOrdering comp, bool deep=false); + /// Compare two ranges of nodes (compares nodes as well as tree structure). + template + bool equal(const iter& one, const iter& two, const iter& three) const; + template + bool equal(const iter& one, const iter& two, const iter& three, BinaryPredicate) const; + template + bool equal_subtree(const iter& one, const iter& two) const; + template + bool equal_subtree(const iter& one, const iter& two, BinaryPredicate) const; + /// Extract a new tree formed by the range of siblings plus all their children. + tree subtree(sibling_iterator from, sibling_iterator to) const; + void subtree(tree&, sibling_iterator from, sibling_iterator to) const; + /// Exchange the node (plus subtree) with its sibling node (do nothing if no sibling present). + void swap(sibling_iterator it); + /// Exchange two nodes (plus subtrees) + void swap(iterator, iterator); + + /// Count the total number of nodes. + size_t size() const; + /// Count the total number of nodes below the indicated node (plus one). + size_t size(const iterator_base&) const; + /// Check if tree is empty. + bool empty() const; + /// Compute the depth to the root or to a fixed other iterator. + static int depth(const iterator_base&); + static int depth(const iterator_base&, const iterator_base&); + /// Determine the maximal depth of the tree. An empty tree has max_depth=-1. + int max_depth() const; + /// Determine the maximal depth of the tree with top node at the given position. + int max_depth(const iterator_base&) const; + /// Count the number of children of node at position. + static unsigned int number_of_children(const iterator_base&); + /// Count the number of siblings (left and right) of node at iterator. Total nodes at this level is +1. + unsigned int number_of_siblings(const iterator_base&) const; + /// Determine whether node at position is in the subtrees with root in the range. + bool is_in_subtree(const iterator_base& position, const iterator_base& begin, + const iterator_base& end) const; + /// Determine whether the iterator is an 'end' iterator and thus not actually pointing to a node. + bool is_valid(const iterator_base&) const; + /// Find the lowest common ancestor of two nodes, that is, the deepest node such that + /// both nodes are descendants of it. + iterator lowest_common_ancestor(const iterator_base&, const iterator_base &) const; + + /// Determine the index of a node in the range of siblings to which it belongs. + unsigned int index(sibling_iterator it) const; + /// Inverse of 'index': return the n-th child of the node at position. + static sibling_iterator child(const iterator_base& position, unsigned int); + /// Return iterator to the sibling indicated by index + sibling_iterator sibling(const iterator_base& position, unsigned int); + + /// For debugging only: verify internal consistency by inspecting all pointers in the tree + /// (which will also trigger a valgrind error in case something got corrupted). + void debug_verify_consistency() const; + + /// Comparator class for iterators (compares pointer values; why doesn't this work automatically?) + class iterator_base_less { + public: + bool operator()(const typename tree::iterator_base& one, + const typename tree::iterator_base& two) const + { + return one.node < two.node; + } + }; + tree_node *head, *feet; // head/feet are always dummy; if an iterator points to them it is invalid + private: + tree_node_allocator alloc_; + void head_initialise_(); + void copy_(const tree& other); + + /// Comparator class for two nodes of a tree (used for sorting and searching). + template + class compare_nodes { + public: + compare_nodes(StrictWeakOrdering comp) : comp_(comp) {}; + + bool operator()(const tree_node *a, const tree_node *b) + { + return comp_(a->data, b->data); + } + private: + StrictWeakOrdering comp_; + }; +}; + +//template +//class iterator_base_less { +// public: +// bool operator()(const typename tree::iterator_base& one, +// const typename tree::iterator_base& two) const +// { +// txtout << "operatorclass<" << one.node < two.node << std::endl; +// return one.node < two.node; +// } +//}; + +// template +// bool operator<(const typename tree::iterator& one, +// const typename tree::iterator& two) +// { +// txtout << "operator< " << one.node < two.node << std::endl; +// if(one.node < two.node) return true; +// return false; +// } +// +// template +// bool operator==(const typename tree::iterator& one, +// const typename tree::iterator& two) +// { +// txtout << "operator== " << one.node == two.node << std::endl; +// if(one.node == two.node) return true; +// return false; +// } +// +// template +// bool operator>(const typename tree::iterator_base& one, +// const typename tree::iterator_base& two) +// { +// txtout << "operator> " << one.node < two.node << std::endl; +// if(one.node > two.node) return true; +// return false; +// } + + + +// Tree + +template +tree::tree() + { + head_initialise_(); + } + +template +tree::tree(const T& x) + { + head_initialise_(); + set_head(x); + } + +template +tree::tree(const iterator_base& other) + { + head_initialise_(); + set_head((*other)); + replace(begin(), other); + } + +template +tree::~tree() + { + clear(); + alloc_.destroy(head); + alloc_.destroy(feet); + alloc_.deallocate(head,1); + alloc_.deallocate(feet,1); + } + +template +void tree::head_initialise_() + { + head = alloc_.allocate(1,0); // MSVC does not have default second argument + feet = alloc_.allocate(1,0); + alloc_.construct(head, tree_node_()); + alloc_.construct(feet, tree_node_()); + + head->parent=0; + head->first_child=0; + head->last_child=0; + head->prev_sibling=0; //head; + head->next_sibling=feet; //head; + + feet->parent=0; + feet->first_child=0; + feet->last_child=0; + feet->prev_sibling=head; + feet->next_sibling=0; + } + +template +tree& tree::operator=(const tree& other) + { + if(this != &other) + copy_(other); + return *this; + } + +template +tree::tree(const tree& other) + { + head_initialise_(); + copy_(other); + } + +template +void tree::copy_(const tree& other) + { + clear(); + pre_order_iterator it=other.begin(), to=begin(); + while(it!=other.end()) { + to=insert(to, (*it)); + it.skip_children(); + ++it; + } + to=begin(); + it=other.begin(); + while(it!=other.end()) { + to=replace(to, it); + to.skip_children(); + it.skip_children(); + ++to; + ++it; + } + } + +template +void tree::clear() + { + if(head) + while(head->next_sibling!=feet) + erase(pre_order_iterator(head->next_sibling)); + } + +template +void tree::erase_children(const iterator_base& it) + { +// std::cout << "erase_children " << it.node << std::endl; + if(it.node==0) return; + + tree_node *cur=it.node->first_child; + tree_node *prev=0; + + while(cur!=0) { + prev=cur; + cur=cur->next_sibling; + erase_children(pre_order_iterator(prev)); +// kp::destructor(&prev->data); + alloc_.destroy(prev); + alloc_.deallocate(prev,1); + } + it.node->first_child=0; + it.node->last_child=0; +// std::cout << "exit" << std::endl; + } + +template +template +iter tree::erase(iter it) + { + tree_node *cur=it.node; + assert(cur!=head); + iter ret=it; + ret.skip_children(); + ++ret; + erase_children(it); + if(cur->prev_sibling==0) { + cur->parent->first_child=cur->next_sibling; + } + else { + cur->prev_sibling->next_sibling=cur->next_sibling; + } + if(cur->next_sibling==0) { + cur->parent->last_child=cur->prev_sibling; + } + else { + cur->next_sibling->prev_sibling=cur->prev_sibling; + } + +// kp::destructor(&cur->data); + alloc_.destroy(cur); + alloc_.deallocate(cur,1); + return ret; + } + +template +typename tree::pre_order_iterator tree::begin() const + { + return pre_order_iterator(head->next_sibling); + } + +template +typename tree::pre_order_iterator tree::end() const + { + return pre_order_iterator(feet); + } + +template +typename tree::breadth_first_queued_iterator tree::begin_breadth_first() const + { + return breadth_first_queued_iterator(head->next_sibling); + } + +template +typename tree::breadth_first_queued_iterator tree::end_breadth_first() const + { + return breadth_first_queued_iterator(); + } + +template +typename tree::post_order_iterator tree::begin_post() const + { + tree_node *tmp=head->next_sibling; + if(tmp!=feet) { + while(tmp->first_child) + tmp=tmp->first_child; + } + return post_order_iterator(tmp); + } + +template +typename tree::post_order_iterator tree::end_post() const + { + return post_order_iterator(feet); + } + +template +typename tree::fixed_depth_iterator tree::begin_fixed(const iterator_base& pos, unsigned int dp) const + { + typename tree::fixed_depth_iterator ret; + ret.top_node=pos.node; + + tree_node *tmp=pos.node; + unsigned int curdepth=0; + while(curdepthfirst_child==0) { + if(tmp->next_sibling==0) { + // try to walk up and then right again + do { + if(tmp==ret.top_node) + throw std::range_error("tree: begin_fixed out of range"); + tmp=tmp->parent; + if(tmp==0) + throw std::range_error("tree: begin_fixed out of range"); + --curdepth; + } while(tmp->next_sibling==0); + } + tmp=tmp->next_sibling; + } + tmp=tmp->first_child; + ++curdepth; + } + + ret.node=tmp; + return ret; + } + +template +typename tree::fixed_depth_iterator tree::end_fixed(const iterator_base& pos, unsigned int dp) const + { + assert(1==0); // FIXME: not correct yet: use is_valid() as a temporary workaround + tree_node *tmp=pos.node; + unsigned int curdepth=1; + while(curdepthfirst_child==0) { + tmp=tmp->next_sibling; + if(tmp==0) + throw std::range_error("tree: end_fixed out of range"); + } + tmp=tmp->first_child; + ++curdepth; + } + return tmp; + } + +template +typename tree::sibling_iterator tree::begin(const iterator_base& pos) const + { + assert(pos.node!=0); + if(pos.node->first_child==0) { + return end(pos); + } + return pos.node->first_child; + } + +template +typename tree::sibling_iterator tree::end(const iterator_base& pos) const + { + sibling_iterator ret(0); + ret.parent_=pos.node; + return ret; + } + +template +typename tree::leaf_iterator tree::begin_leaf() const + { + tree_node *tmp=head->next_sibling; + if(tmp!=feet) { + while(tmp->first_child) + tmp=tmp->first_child; + } + return leaf_iterator(tmp); + } + +template +typename tree::leaf_iterator tree::end_leaf() const + { + return leaf_iterator(feet); + } + +template +typename tree::leaf_iterator tree::begin_leaf(const iterator_base& top) const + { + tree_node *tmp=top.node; + while(tmp->first_child) + tmp=tmp->first_child; + return leaf_iterator(tmp, top.node); + } + +template +typename tree::leaf_iterator tree::end_leaf(const iterator_base& top) const + { + return leaf_iterator(top.node, top.node); + } + +template +template +iter tree::parent(iter position) + { + assert(position.node!=0); + return iter(position.node->parent); + } + +template +template +iter tree::previous_sibling(iter position) const + { + assert(position.node!=0); + iter ret(position); + ret.node=position.node->prev_sibling; + return ret; + } + +template +template +iter tree::next_sibling(iter position) const + { + assert(position.node!=0); + iter ret(position); + ret.node=position.node->next_sibling; + return ret; + } + +template +template +iter tree::next_at_same_depth(iter position) const + { + // We make use of a temporary fixed_depth iterator to implement this. + + typename tree::fixed_depth_iterator tmp(position.node); + + ++tmp; + return iter(tmp); + +// assert(position.node!=0); +// iter ret(position); +// +// if(position.node->next_sibling) { +// ret.node=position.node->next_sibling; +// } +// else { +// int relative_depth=0; +// upper: +// do { +// ret.node=ret.node->parent; +// if(ret.node==0) return ret; +// --relative_depth; +// } while(ret.node->next_sibling==0); +// lower: +// ret.node=ret.node->next_sibling; +// while(ret.node->first_child==0) { +// if(ret.node->next_sibling==0) +// goto upper; +// ret.node=ret.node->next_sibling; +// if(ret.node==0) return ret; +// } +// while(relative_depth<0 && ret.node->first_child!=0) { +// ret.node=ret.node->first_child; +// ++relative_depth; +// } +// if(relative_depth<0) { +// if(ret.node->next_sibling==0) goto upper; +// else goto lower; +// } +// } +// return ret; + } + +template +template +iter tree::append_child(iter position) + { + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + tree_node *tmp=alloc_.allocate(1,0); + alloc_.construct(tmp, tree_node_()); +// kp::constructor(&tmp->data); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->last_child!=0) { + position.node->last_child->next_sibling=tmp; + } + else { + position.node->first_child=tmp; + } + tmp->prev_sibling=position.node->last_child; + position.node->last_child=tmp; + tmp->next_sibling=0; + return tmp; + } + +template +template +iter tree::prepend_child(iter position) + { + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + tree_node *tmp=alloc_.allocate(1,0); + alloc_.construct(tmp, tree_node_()); +// kp::constructor(&tmp->data); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->first_child!=0) { + position.node->first_child->prev_sibling=tmp; + } + else { + position.node->last_child=tmp; + } + tmp->next_sibling=position.node->first_child; + position.node->prev_child=tmp; + tmp->prev_sibling=0; + return tmp; + } + +template +template +iter tree::append_child(iter position, const T& x) + { + // If your program fails here you probably used 'append_child' to add the top + // node to an empty tree. From version 1.45 the top element should be added + // using 'insert'. See the documentation for further information, and sorry about + // the API change. + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + tree_node* tmp = alloc_.allocate(1,0); + alloc_.construct(tmp, x); +// kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->last_child!=0) { + position.node->last_child->next_sibling=tmp; + } + else { + position.node->first_child=tmp; + } + tmp->prev_sibling=position.node->last_child; + position.node->last_child=tmp; + tmp->next_sibling=0; + return tmp; + } + +template +template +iter tree::prepend_child(iter position, const T& x) + { + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + tree_node* tmp = alloc_.allocate(1,0); + alloc_.construct(tmp, x); +// kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->first_child!=0) { + position.node->first_child->prev_sibling=tmp; + } + else { + position.node->last_child=tmp; + } + tmp->next_sibling=position.node->first_child; + position.node->first_child=tmp; + tmp->prev_sibling=0; + return tmp; + } + +template +template +iter tree::append_child(iter position, iter other) + { + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + sibling_iterator aargh=append_child(position, value_type()); + return replace(aargh, other); + } + +template +template +iter tree::prepend_child(iter position, iter other) + { + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + sibling_iterator aargh=prepend_child(position, value_type()); + return replace(aargh, other); + } + +template +template +iter tree::append_children(iter position, sibling_iterator from, sibling_iterator to) + { + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + iter ret=from; + + while(from!=to) { + insert_subtree(position.end(), from); + ++from; + } + return ret; + } + +template +template +iter tree::prepend_children(iter position, sibling_iterator from, sibling_iterator to) + { + assert(position.node!=head); + assert(position.node!=feet); + assert(position.node); + + iter ret=from; + + while(from!=to) { + insert_subtree(position.begin(), from); + ++from; + } + return ret; + } + +template +typename tree::pre_order_iterator tree::set_head(const T& x) + { + assert(head->next_sibling==feet); + return insert(iterator(feet), x); + } + +template +template +iter tree::insert(iter position, const T& x) + { + if(position.node==0) { + position.node=feet; // Backward compatibility: when calling insert on a null node, + // insert before the feet. + } + tree_node* tmp = alloc_.allocate(1,0); + alloc_.construct(tmp, x); +// kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->next_sibling=position.node; + tmp->prev_sibling=position.node->prev_sibling; + position.node->prev_sibling=tmp; + + if(tmp->prev_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->first_child=tmp; + } + else + tmp->prev_sibling->next_sibling=tmp; + return tmp; + } + +template +typename tree::sibling_iterator tree::insert(sibling_iterator position, const T& x) + { + tree_node* tmp = alloc_.allocate(1,0); + alloc_.construct(tmp, x); +// kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->next_sibling=position.node; + if(position.node==0) { // iterator points to end of a subtree + tmp->parent=position.parent_; + tmp->prev_sibling=position.range_last(); + tmp->parent->last_child=tmp; + } + else { + tmp->parent=position.node->parent; + tmp->prev_sibling=position.node->prev_sibling; + position.node->prev_sibling=tmp; + } + + if(tmp->prev_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->first_child=tmp; + } + else + tmp->prev_sibling->next_sibling=tmp; + return tmp; + } + +template +template +iter tree::insert_after(iter position, const T& x) + { + tree_node* tmp = alloc_.allocate(1,0); + alloc_.construct(tmp, x); +// kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->prev_sibling=position.node; + tmp->next_sibling=position.node->next_sibling; + position.node->next_sibling=tmp; + + if(tmp->next_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->last_child=tmp; + } + else { + tmp->next_sibling->prev_sibling=tmp; + } + return tmp; + } + +template +template +iter tree::insert_subtree(iter position, const iterator_base& subtree) + { + // insert dummy + iter it=insert(position, value_type()); + // replace dummy with subtree + return replace(it, subtree); + } + +template +template +iter tree::insert_subtree_after(iter position, const iterator_base& subtree) + { + // insert dummy + iter it=insert_after(position, value_type()); + // replace dummy with subtree + return replace(it, subtree); + } + +// template +// template +// iter tree::insert_subtree(sibling_iterator position, iter subtree) +// { +// // insert dummy +// iter it(insert(position, value_type())); +// // replace dummy with subtree +// return replace(it, subtree); +// } + +template +template +iter tree::replace(iter position, const T& x) + { +// kp::destructor(&position.node->data); +// kp::constructor(&position.node->data, x); + position.node->data=x; +// alloc_.destroy(position.node); +// alloc_.construct(position.node, x); + return position; + } + +template +template +iter tree::replace(iter position, const iterator_base& from) + { + assert(position.node!=head); + tree_node *current_from=from.node; + tree_node *start_from=from.node; + tree_node *current_to =position.node; + + // replace the node at position with head of the replacement tree at from +// std::cout << "warning!" << position.node << std::endl; + erase_children(position); +// std::cout << "no warning!" << std::endl; + tree_node* tmp = alloc_.allocate(1,0); + alloc_.construct(tmp, (*from)); +// kp::constructor(&tmp->data, (*from)); + tmp->first_child=0; + tmp->last_child=0; + if(current_to->prev_sibling==0) { + if(current_to->parent!=0) + current_to->parent->first_child=tmp; + } + else { + current_to->prev_sibling->next_sibling=tmp; + } + tmp->prev_sibling=current_to->prev_sibling; + if(current_to->next_sibling==0) { + if(current_to->parent!=0) + current_to->parent->last_child=tmp; + } + else { + current_to->next_sibling->prev_sibling=tmp; + } + tmp->next_sibling=current_to->next_sibling; + tmp->parent=current_to->parent; +// kp::destructor(¤t_to->data); + alloc_.destroy(current_to); + alloc_.deallocate(current_to,1); + current_to=tmp; + + // only at this stage can we fix 'last' + tree_node *last=from.node->next_sibling; + + pre_order_iterator toit=tmp; + // copy all children + do { + assert(current_from!=0); + if(current_from->first_child != 0) { + current_from=current_from->first_child; + toit=append_child(toit, current_from->data); + } + else { + while(current_from->next_sibling==0 && current_from!=start_from) { + current_from=current_from->parent; + toit=parent(toit); + assert(current_from!=0); + } + current_from=current_from->next_sibling; + if(current_from!=last) { + toit=append_child(parent(toit), current_from->data); + } + } + } while(current_from!=last); + + return current_to; + } + +template +typename tree::sibling_iterator tree::replace( + sibling_iterator orig_begin, + sibling_iterator orig_end, + sibling_iterator new_begin, + sibling_iterator new_end) + { + tree_node *orig_first=orig_begin.node; + tree_node *new_first=new_begin.node; + tree_node *orig_last=orig_first; + while((++orig_begin)!=orig_end) + orig_last=orig_last->next_sibling; + tree_node *new_last=new_first; + while((++new_begin)!=new_end) + new_last=new_last->next_sibling; + + // insert all siblings in new_first..new_last before orig_first + bool first=true; + pre_order_iterator ret; + while(1==1) { + pre_order_iterator tt=insert_subtree(pre_order_iterator(orig_first), pre_order_iterator(new_first)); + if(first) { + ret=tt; + first=false; + } + if(new_first==new_last) + break; + new_first=new_first->next_sibling; + } + + // erase old range of siblings + bool last=false; + tree_node *next=orig_first; + while(1==1) { + if(next==orig_last) + last=true; + next=next->next_sibling; + erase((pre_order_iterator)orig_first); + if(last) + break; + orig_first=next; + } + return ret; + } + +template +template +iter tree::flatten(iter position) + { + if(position.node->first_child==0) + return position; + + tree_node *tmp=position.node->first_child; + while(tmp) { + tmp->parent=position.node->parent; + tmp=tmp->next_sibling; + } + if(position.node->next_sibling) { + position.node->last_child->next_sibling=position.node->next_sibling; + position.node->next_sibling->prev_sibling=position.node->last_child; + } + else { + position.node->parent->last_child=position.node->last_child; + } + position.node->next_sibling=position.node->first_child; + position.node->next_sibling->prev_sibling=position.node; + position.node->first_child=0; + position.node->last_child=0; + + return position; + } + + +template +template +iter tree::reparent(iter position, sibling_iterator begin, sibling_iterator end) + { + tree_node *first=begin.node; + tree_node *last=first; + + assert(first!=position.node); + + if(begin==end) return begin; + // determine last node + while((++begin)!=end) { + last=last->next_sibling; + } + // move subtree + if(first->prev_sibling==0) { + first->parent->first_child=last->next_sibling; + } + else { + first->prev_sibling->next_sibling=last->next_sibling; + } + if(last->next_sibling==0) { + last->parent->last_child=first->prev_sibling; + } + else { + last->next_sibling->prev_sibling=first->prev_sibling; + } + if(position.node->first_child==0) { + position.node->first_child=first; + position.node->last_child=last; + first->prev_sibling=0; + } + else { + position.node->last_child->next_sibling=first; + first->prev_sibling=position.node->last_child; + position.node->last_child=last; + } + last->next_sibling=0; + + tree_node *pos=first; + for(;;) { + pos->parent=position.node; + if(pos==last) break; + pos=pos->next_sibling; + } + + return first; + } + +template +template iter tree::reparent(iter position, iter from) + { + if(from.node->first_child==0) return position; + return reparent(position, from.node->first_child, end(from)); + } + +template +template iter tree::wrap(iter position, const T& x) + { + assert(position.node!=0); + sibling_iterator fr=position, to=position; + ++to; + iter ret = insert(position, x); + reparent(ret, fr, to); + return ret; + } + +template +template iter tree::move_after(iter target, iter source) + { + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return source; + if(dst->next_sibling) + if(dst->next_sibling==src) // already in the right spot + return source; + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst->next_sibling!=0) dst->next_sibling->prev_sibling=src; + else dst->parent->last_child=src; + src->next_sibling=dst->next_sibling; + dst->next_sibling=src; + src->prev_sibling=dst; + src->parent=dst->parent; + return src; + } + +template +template iter tree::move_before(iter target, iter source) + { + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return source; + if(dst->prev_sibling) + if(dst->prev_sibling==src) // already in the right spot + return source; + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst->prev_sibling!=0) dst->prev_sibling->next_sibling=src; + else dst->parent->first_child=src; + src->prev_sibling=dst->prev_sibling; + dst->prev_sibling=src; + src->next_sibling=dst; + src->parent=dst->parent; + return src; + } + +// specialisation for sibling_iterators +template +typename tree::sibling_iterator tree::move_before(sibling_iterator target, + sibling_iterator source) + { + tree_node *dst=target.node; + tree_node *src=source.node; + tree_node *dst_prev_sibling; + if(dst==0) { // must then be an end iterator + dst_prev_sibling=target.parent_->last_child; + assert(dst_prev_sibling); + } + else dst_prev_sibling=dst->prev_sibling; + assert(src); + + if(dst==src) return source; + if(dst_prev_sibling) + if(dst_prev_sibling==src) // already in the right spot + return source; + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst_prev_sibling!=0) dst_prev_sibling->next_sibling=src; + else target.parent_->first_child=src; + src->prev_sibling=dst_prev_sibling; + if(dst) { + dst->prev_sibling=src; + src->parent=dst->parent; + } + src->next_sibling=dst; + return src; + } + +template +template iter tree::move_ontop(iter target, iter source) + { + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return source; + +// if(dst==src->prev_sibling) { +// +// } + + // remember connection points + tree_node *b_prev_sibling=dst->prev_sibling; + tree_node *b_next_sibling=dst->next_sibling; + tree_node *b_parent=dst->parent; + + // remove target + erase(target); + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(b_prev_sibling!=0) b_prev_sibling->next_sibling=src; + else b_parent->first_child=src; + if(b_next_sibling!=0) b_next_sibling->prev_sibling=src; + else b_parent->last_child=src; + src->prev_sibling=b_prev_sibling; + src->next_sibling=b_next_sibling; + src->parent=b_parent; + return src; + } + +template +void tree::merge(sibling_iterator to1, sibling_iterator to2, + sibling_iterator from1, sibling_iterator from2, + bool duplicate_leaves) + { + sibling_iterator fnd; + while(from1!=from2) { + if((fnd=std::find(to1, to2, (*from1))) != to2) { // element found + if(from1.begin()==from1.end()) { // full depth reached + if(duplicate_leaves) + append_child(parent(to1), (*from1)); + } + else { // descend further + merge(fnd.begin(), fnd.end(), from1.begin(), from1.end(), duplicate_leaves); + } + } + else { // element missing + insert_subtree(to2, from1); + } + ++from1; + } + } + + +template +void tree::sort(sibling_iterator from, sibling_iterator to, bool deep) + { + std::less comp; + sort(from, to, comp, deep); + } + +template +template +void tree::sort(sibling_iterator from, sibling_iterator to, + StrictWeakOrdering comp, bool deep) + { + if(from==to) return; + // make list of sorted nodes + // CHECK: if multiset stores equivalent nodes in the order in which they + // are inserted, then this routine should be called 'stable_sort'. + std::multiset > nodes(comp); + sibling_iterator it=from, it2=to; + while(it != to) { + nodes.insert(it.node); + ++it; + } + // reassemble + --it2; + + // prev and next are the nodes before and after the sorted range + tree_node *prev=from.node->prev_sibling; + tree_node *next=it2.node->next_sibling; + typename std::multiset >::iterator nit=nodes.begin(), eit=nodes.end(); + if(prev==0) { + if((*nit)->parent!=0) // to catch "sorting the head" situations, when there is no parent + (*nit)->parent->first_child=(*nit); + } + else prev->next_sibling=(*nit); + + --eit; + while(nit!=eit) { + (*nit)->prev_sibling=prev; + if(prev) + prev->next_sibling=(*nit); + prev=(*nit); + ++nit; + } + // prev now points to the last-but-one node in the sorted range + if(prev) + prev->next_sibling=(*eit); + + // eit points to the last node in the sorted range. + (*eit)->next_sibling=next; + (*eit)->prev_sibling=prev; // missed in the loop above + if(next==0) { + if((*eit)->parent!=0) // to catch "sorting the head" situations, when there is no parent + (*eit)->parent->last_child=(*eit); + } + else next->prev_sibling=(*eit); + + if(deep) { // sort the children of each node too + sibling_iterator bcs(*nodes.begin()); + sibling_iterator ecs(*eit); + ++ecs; + while(bcs!=ecs) { + sort(begin(bcs), end(bcs), comp, deep); + ++bcs; + } + } + } + +template +template +bool tree::equal(const iter& one_, const iter& two, const iter& three_) const + { + std::equal_to comp; + return equal(one_, two, three_, comp); + } + +template +template +bool tree::equal_subtree(const iter& one_, const iter& two_) const + { + std::equal_to comp; + return equal_subtree(one_, two_, comp); + } + +template +template +bool tree::equal(const iter& one_, const iter& two, const iter& three_, BinaryPredicate fun) const + { + pre_order_iterator one(one_), three(three_); + +// if(one==two && is_valid(three) && three.number_of_children()!=0) +// return false; + while(one!=two && is_valid(three)) { + if(!fun(*one,*three)) + return false; + if(one.number_of_children()!=three.number_of_children()) + return false; + ++one; + ++three; + } + return true; + } + +template +template +bool tree::equal_subtree(const iter& one_, const iter& two_, BinaryPredicate fun) const + { + pre_order_iterator one(one_), two(two_); + + if(!fun(*one,*two)) return false; + if(number_of_children(one)!=number_of_children(two)) return false; + return equal(begin(one),end(one),begin(two),fun); + } + +template +tree tree::subtree(sibling_iterator from, sibling_iterator to) const + { + tree tmp; + tmp.set_head(value_type()); + tmp.replace(tmp.begin(), tmp.end(), from, to); + return tmp; + } + +template +void tree::subtree(tree& tmp, sibling_iterator from, sibling_iterator to) const + { + tmp.set_head(value_type()); + tmp.replace(tmp.begin(), tmp.end(), from, to); + } + +template +size_t tree::size() const + { + size_t i=0; + pre_order_iterator it=begin(), eit=end(); + while(it!=eit) { + ++i; + ++it; + } + return i; + } + +template +size_t tree::size(const iterator_base& top) const + { + size_t i=0; + pre_order_iterator it=top, eit=top; + eit.skip_children(); + ++eit; + while(it!=eit) { + ++i; + ++it; + } + return i; + } + +template +bool tree::empty() const + { + pre_order_iterator it=begin(), eit=end(); + return (it==eit); + } + +template +int tree::depth(const iterator_base& it) + { + tree_node* pos=it.node; + assert(pos!=0); + int ret=0; + while(pos->parent!=0) { + pos=pos->parent; + ++ret; + } + return ret; + } + +template +int tree::depth(const iterator_base& it, const iterator_base& root) + { + tree_node* pos=it.node; + assert(pos!=0); + int ret=0; + while(pos->parent!=0 && pos!=root.node) { + pos=pos->parent; + ++ret; + } + return ret; + } + +template +int tree::max_depth() const + { + int maxd=-1; + for(tree_node *it = head->next_sibling; it!=feet; it=it->next_sibling) + maxd=std::max(maxd, max_depth(it)); + + return maxd; + } + + +template +int tree::max_depth(const iterator_base& pos) const + { + tree_node *tmp=pos.node; + + if(tmp==0 || tmp==head || tmp==feet) return -1; + + int curdepth=0, maxdepth=0; + while(true) { // try to walk the bottom of the tree + while(tmp->first_child==0) { + if(tmp==pos.node) return maxdepth; + if(tmp->next_sibling==0) { + // try to walk up and then right again + do { + tmp=tmp->parent; + if(tmp==0) return maxdepth; + --curdepth; + } while(tmp->next_sibling==0); + } + if(tmp==pos.node) return maxdepth; + tmp=tmp->next_sibling; + } + tmp=tmp->first_child; + ++curdepth; + maxdepth=std::max(curdepth, maxdepth); + } + } + +template +unsigned int tree::number_of_children(const iterator_base& it) + { + tree_node *pos=it.node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; +// while(pos!=it.node->last_child) { +// ++ret; +// pos=pos->next_sibling; +// } + while((pos=pos->next_sibling)) + ++ret; + return ret; + } + +template +unsigned int tree::number_of_siblings(const iterator_base& it) const + { + tree_node *pos=it.node; + unsigned int ret=0; + // count forward + while(pos->next_sibling && + pos->next_sibling!=head && + pos->next_sibling!=feet) { + ++ret; + pos=pos->next_sibling; + } + // count backward + pos=it.node; + while(pos->prev_sibling && + pos->prev_sibling!=head && + pos->prev_sibling!=feet) { + ++ret; + pos=pos->prev_sibling; + } + + return ret; + } + +template +void tree::swap(sibling_iterator it) + { + tree_node *nxt=it.node->next_sibling; + if(nxt) { + if(it.node->prev_sibling) + it.node->prev_sibling->next_sibling=nxt; + else + it.node->parent->first_child=nxt; + nxt->prev_sibling=it.node->prev_sibling; + tree_node *nxtnxt=nxt->next_sibling; + if(nxtnxt) + nxtnxt->prev_sibling=it.node; + else + it.node->parent->last_child=it.node; + nxt->next_sibling=it.node; + it.node->prev_sibling=nxt; + it.node->next_sibling=nxtnxt; + } + } + +template +void tree::swap(iterator one, iterator two) + { + // if one and two are adjacent siblings, use the sibling swap + if(one.node->next_sibling==two.node) swap(one); + else if(two.node->next_sibling==one.node) swap(two); + else { + tree_node *nxt1=one.node->next_sibling; + tree_node *nxt2=two.node->next_sibling; + tree_node *pre1=one.node->prev_sibling; + tree_node *pre2=two.node->prev_sibling; + tree_node *par1=one.node->parent; + tree_node *par2=two.node->parent; + + // reconnect + one.node->parent=par2; + one.node->next_sibling=nxt2; + if(nxt2) nxt2->prev_sibling=one.node; + else par2->last_child=one.node; + one.node->prev_sibling=pre2; + if(pre2) pre2->next_sibling=one.node; + else par2->first_child=one.node; + + two.node->parent=par1; + two.node->next_sibling=nxt1; + if(nxt1) nxt1->prev_sibling=two.node; + else par1->last_child=two.node; + two.node->prev_sibling=pre1; + if(pre1) pre1->next_sibling=two.node; + else par1->first_child=two.node; + } + } + +// template +// tree::iterator tree::find_subtree( +// sibling_iterator subfrom, sibling_iterator subto, iterator from, iterator to, +// BinaryPredicate fun) const +// { +// assert(1==0); // this routine is not finished yet. +// while(from!=to) { +// if(fun(*subfrom, *from)) { +// +// } +// } +// return to; +// } + +template +bool tree::is_in_subtree(const iterator_base& it, const iterator_base& begin, + const iterator_base& end) const + { + // FIXME: this should be optimised. + pre_order_iterator tmp=begin; + while(tmp!=end) { + if(tmp==it) return true; + ++tmp; + } + return false; + } + +template +bool tree::is_valid(const iterator_base& it) const + { + if(it.node==0 || it.node==feet || it.node==head) return false; + else return true; + } + +template +typename tree::iterator tree::lowest_common_ancestor( + const iterator_base& one, const iterator_base& two) const + { + std::set parents; + + // Walk up from 'one' storing all parents. + iterator walk=one; + do { + walk=parent(walk); + parents.insert(walk); + } while( is_valid(parent(walk)) ); + + // Walk up from 'two' until we encounter a node in parents. + walk=two; + do { + walk=parent(walk); + if(parents.find(walk) != parents.end()) break; + } while( is_valid(parent(walk)) ); + + return walk; + } + +template +unsigned int tree::index(sibling_iterator it) const + { + unsigned int ind=0; + if(it.node->parent==0) { + while(it.node->prev_sibling!=head) { + it.node=it.node->prev_sibling; + ++ind; + } + } + else { + while(it.node->prev_sibling!=0) { + it.node=it.node->prev_sibling; + ++ind; + } + } + return ind; + } + +template +typename tree::sibling_iterator tree::sibling(const iterator_base& it, unsigned int num) + { + tree_node *tmp; + if(it.node->parent==0) { + tmp=head->next_sibling; + while(num) { + tmp = tmp->next_sibling; + --num; + } + } + else { + tmp=it.node->parent->first_child; + while(num) { + assert(tmp!=0); + tmp = tmp->next_sibling; + --num; + } + } + return tmp; + } + +template +void tree::debug_verify_consistency() const + { + iterator it=begin(); + while(it!=end()) { + if(it.node->parent!=0) { + if(it.node->prev_sibling==0) + assert(it.node->parent->first_child==it.node); + else + assert(it.node->prev_sibling->next_sibling==it.node); + if(it.node->next_sibling==0) + assert(it.node->parent->last_child==it.node); + else + assert(it.node->next_sibling->prev_sibling==it.node); + } + ++it; + } + } + +template +typename tree::sibling_iterator tree::child(const iterator_base& it, unsigned int num) + { + tree_node *tmp=it.node->first_child; + while(num--) { + assert(tmp!=0); + tmp=tmp->next_sibling; + } + return tmp; + } + + + + +// Iterator base + +template +tree::iterator_base::iterator_base() + : node(0), skip_current_children_(false) + { + } + +template +tree::iterator_base::iterator_base(tree_node *tn) + : node(tn), skip_current_children_(false) + { + } + +template +T& tree::iterator_base::operator*() const + { + return node->data; + } + +template +T* tree::iterator_base::operator->() const + { + return &(node->data); + } + +template +bool tree::post_order_iterator::operator!=(const post_order_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::post_order_iterator::operator==(const post_order_iterator& other) const + { + if(other.node==this->node) return true; + else return false; + } + +template +bool tree::pre_order_iterator::operator!=(const pre_order_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::pre_order_iterator::operator==(const pre_order_iterator& other) const + { + if(other.node==this->node) return true; + else return false; + } + +template +bool tree::sibling_iterator::operator!=(const sibling_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::sibling_iterator::operator==(const sibling_iterator& other) const + { + if(other.node==this->node) return true; + else return false; + } + +template +bool tree::leaf_iterator::operator!=(const leaf_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::leaf_iterator::operator==(const leaf_iterator& other) const + { + if(other.node==this->node && other.top_node==this->top_node) return true; + else return false; + } + +template +typename tree::sibling_iterator tree::iterator_base::begin() const + { + if(node->first_child==0) + return end(); + + sibling_iterator ret(node->first_child); + ret.parent_=this->node; + return ret; + } + +template +typename tree::sibling_iterator tree::iterator_base::end() const + { + sibling_iterator ret(0); + ret.parent_=node; + return ret; + } + +template +void tree::iterator_base::skip_children() + { + skip_current_children_=true; + } + +template +void tree::iterator_base::skip_children(bool skip) + { + skip_current_children_=skip; + } + +template +unsigned int tree::iterator_base::number_of_children() const + { + tree_node *pos=node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; + while(pos!=node->last_child) { + ++ret; + pos=pos->next_sibling; + } + return ret; + } + + + +// Pre-order iterator + +template +tree::pre_order_iterator::pre_order_iterator() + : iterator_base(0) + { + } + +template +tree::pre_order_iterator::pre_order_iterator(tree_node *tn) + : iterator_base(tn) + { + } + +template +tree::pre_order_iterator::pre_order_iterator(const iterator_base &other) + : iterator_base(other.node) + { + } + +template +tree::pre_order_iterator::pre_order_iterator(const sibling_iterator& other) + : iterator_base(other.node) + { + if(this->node==0) { + if(other.range_last()!=0) + this->node=other.range_last(); + else + this->node=other.parent_; + this->skip_children(); + ++(*this); + } + } + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator++() + { + assert(this->node!=0); + if(!this->skip_current_children_ && this->node->first_child != 0) { + this->node=this->node->first_child; + } + else { + this->skip_current_children_=false; + while(this->node->next_sibling==0) { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + this->node=this->node->next_sibling; + } + return *this; + } + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator--() + { + assert(this->node!=0); + if(this->node->prev_sibling) { + this->node=this->node->prev_sibling; + while(this->node->last_child) + this->node=this->node->last_child; + } + else { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + return *this; +} + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator++(int) + { + pre_order_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator--(int) +{ + pre_order_iterator copy = *this; + --(*this); + return copy; +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --num; + } + return (*this); + } + + + +// Post-order iterator + +template +tree::post_order_iterator::post_order_iterator() + : iterator_base(0) + { + } + +template +tree::post_order_iterator::post_order_iterator(tree_node *tn) + : iterator_base(tn) + { + } + +template +tree::post_order_iterator::post_order_iterator(const iterator_base &other) + : iterator_base(other.node) + { + } + +template +tree::post_order_iterator::post_order_iterator(const sibling_iterator& other) + : iterator_base(other.node) + { + if(this->node==0) { + if(other.range_last()!=0) + this->node=other.range_last(); + else + this->node=other.parent_; + this->skip_children(); + ++(*this); + } + } + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator++() + { + assert(this->node!=0); + if(this->node->next_sibling==0) { + this->node=this->node->parent; + this->skip_current_children_=false; + } + else { + this->node=this->node->next_sibling; + if(this->skip_current_children_) { + this->skip_current_children_=false; + } + else { + while(this->node->first_child) + this->node=this->node->first_child; + } + } + return *this; + } + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator--() + { + assert(this->node!=0); + if(this->skip_current_children_ || this->node->last_child==0) { + this->skip_current_children_=false; + while(this->node->prev_sibling==0) + this->node=this->node->parent; + this->node=this->node->prev_sibling; + } + else { + this->node=this->node->last_child; + } + return *this; + } + +template +typename tree::post_order_iterator tree::post_order_iterator::operator++(int) + { + post_order_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::post_order_iterator tree::post_order_iterator::operator--(int) + { + post_order_iterator copy = *this; + --(*this); + return copy; + } + + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --num; + } + return (*this); + } + +template +void tree::post_order_iterator::descend_all() + { + assert(this->node!=0); + while(this->node->first_child) + this->node=this->node->first_child; + } + + +// Breadth-first iterator + +template +tree::breadth_first_queued_iterator::breadth_first_queued_iterator() + : iterator_base() + { + } + +template +tree::breadth_first_queued_iterator::breadth_first_queued_iterator(tree_node *tn) + : iterator_base(tn) + { + traversal_queue.push(tn); + } + +template +tree::breadth_first_queued_iterator::breadth_first_queued_iterator(const iterator_base& other) + : iterator_base(other.node) + { + traversal_queue.push(other.node); + } + +template +bool tree::breadth_first_queued_iterator::operator!=(const breadth_first_queued_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::breadth_first_queued_iterator::operator==(const breadth_first_queued_iterator& other) const + { + if(other.node==this->node) return true; + else return false; + } + +template +typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator++() + { + assert(this->node!=0); + + // Add child nodes and pop current node + sibling_iterator sib=this->begin(); + while(sib!=this->end()) { + traversal_queue.push(sib.node); + ++sib; + } + traversal_queue.pop(); + if(traversal_queue.size()>0) + this->node=traversal_queue.front(); + else + this->node=0; + return (*this); + } + +template +typename tree::breadth_first_queued_iterator tree::breadth_first_queued_iterator::operator++(int) + { + breadth_first_queued_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + + + +// Fixed depth iterator + +template +tree::fixed_depth_iterator::fixed_depth_iterator() + : iterator_base() + { + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(tree_node *tn) + : iterator_base(tn), top_node(0) + { + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(const iterator_base& other) + : iterator_base(other.node), top_node(0) + { + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(const sibling_iterator& other) + : iterator_base(other.node), top_node(0) + { + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(const fixed_depth_iterator& other) + : iterator_base(other.node), top_node(other.top_node) + { + } + +template +bool tree::fixed_depth_iterator::operator==(const fixed_depth_iterator& other) const + { + if(other.node==this->node && other.top_node==top_node) return true; + else return false; + } + +template +bool tree::fixed_depth_iterator::operator!=(const fixed_depth_iterator& other) const + { + if(other.node!=this->node || other.top_node!=top_node) return true; + else return false; + } + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator++() + { + assert(this->node!=0); + + if(this->node->next_sibling) { + this->node=this->node->next_sibling; + } + else { + int relative_depth=0; + upper: + do { + if(this->node==this->top_node) { + this->node=0; // FIXME: return a proper fixed_depth end iterator once implemented + return *this; + } + this->node=this->node->parent; + if(this->node==0) return *this; + --relative_depth; + } while(this->node->next_sibling==0); + lower: + this->node=this->node->next_sibling; + while(this->node->first_child==0) { + if(this->node->next_sibling==0) + goto upper; + this->node=this->node->next_sibling; + if(this->node==0) return *this; + } + while(relative_depth<0 && this->node->first_child!=0) { + this->node=this->node->first_child; + ++relative_depth; + } + if(relative_depth<0) { + if(this->node->next_sibling==0) goto upper; + else goto lower; + } + } + return *this; + } + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator--() + { + assert(this->node!=0); + + if(this->node->prev_sibling) { + this->node=this->node->prev_sibling; + } + else { + int relative_depth=0; + upper: + do { + if(this->node==this->top_node) { + this->node=0; + return *this; + } + this->node=this->node->parent; + if(this->node==0) return *this; + --relative_depth; + } while(this->node->prev_sibling==0); + lower: + this->node=this->node->prev_sibling; + while(this->node->last_child==0) { + if(this->node->prev_sibling==0) + goto upper; + this->node=this->node->prev_sibling; + if(this->node==0) return *this; + } + while(relative_depth<0 && this->node->last_child!=0) { + this->node=this->node->last_child; + ++relative_depth; + } + if(relative_depth<0) { + if(this->node->prev_sibling==0) goto upper; + else goto lower; + } + } + return *this; + +// +// +// assert(this->node!=0); +// if(this->node->prev_sibling!=0) { +// this->node=this->node->prev_sibling; +// assert(this->node!=0); +// if(this->node->parent==0 && this->node->prev_sibling==0) // head element +// this->node=0; +// } +// else { +// tree_node *par=this->node->parent; +// do { +// par=par->prev_sibling; +// if(par==0) { // FIXME: need to keep track of this! +// this->node=0; +// return *this; +// } +// } while(par->last_child==0); +// this->node=par->last_child; +// } +// return *this; + } + +template +typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator++(int) + { + fixed_depth_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator--(int) + { + fixed_depth_iterator copy = *this; + --(*this); + return copy; + } + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --(num); + } + return (*this); + } + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --(num); + } + return *this; + } + + +// Sibling iterator + +template +tree::sibling_iterator::sibling_iterator() + : iterator_base() + { + set_parent_(); + } + +template +tree::sibling_iterator::sibling_iterator(tree_node *tn) + : iterator_base(tn) + { + set_parent_(); + } + +template +tree::sibling_iterator::sibling_iterator(const iterator_base& other) + : iterator_base(other.node) + { + set_parent_(); + } + +template +tree::sibling_iterator::sibling_iterator(const sibling_iterator& other) + : iterator_base(other), parent_(other.parent_) + { + } + +template +void tree::sibling_iterator::set_parent_() + { + parent_=0; + if(this->node==0) return; + if(this->node->parent!=0) + parent_=this->node->parent; + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator++() + { + if(this->node) + this->node=this->node->next_sibling; + return *this; + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator--() + { + if(this->node) this->node=this->node->prev_sibling; + else { + assert(parent_); + this->node=parent_->last_child; + } + return *this; +} + +template +typename tree::sibling_iterator tree::sibling_iterator::operator++(int) + { + sibling_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::sibling_iterator tree::sibling_iterator::operator--(int) + { + sibling_iterator copy = *this; + --(*this); + return copy; + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --num; + } + return (*this); + } + +template +typename tree::tree_node *tree::sibling_iterator::range_first() const + { + tree_node *tmp=parent_->first_child; + return tmp; + } + +template +typename tree::tree_node *tree::sibling_iterator::range_last() const + { + return parent_->last_child; + } + +// Leaf iterator + +template +tree::leaf_iterator::leaf_iterator() + : iterator_base(0), top_node(0) + { + } + +template +tree::leaf_iterator::leaf_iterator(tree_node *tn, tree_node *top) + : iterator_base(tn), top_node(top) + { + } + +template +tree::leaf_iterator::leaf_iterator(const iterator_base &other) + : iterator_base(other.node), top_node(0) + { + } + +template +tree::leaf_iterator::leaf_iterator(const sibling_iterator& other) + : iterator_base(other.node), top_node(0) + { + if(this->node==0) { + if(other.range_last()!=0) + this->node=other.range_last(); + else + this->node=other.parent_; + ++(*this); + } + } + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator++() + { + assert(this->node!=0); + if(this->node->first_child!=0) { // current node is no longer leaf (children got added) + while(this->node->first_child) + this->node=this->node->first_child; + } + else { + while(this->node->next_sibling==0) { + if (this->node->parent==0) return *this; + this->node=this->node->parent; + if (top_node != 0 && this->node==top_node) return *this; + } + this->node=this->node->next_sibling; + while(this->node->first_child) + this->node=this->node->first_child; + } + return *this; + } + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator--() + { + assert(this->node!=0); + while (this->node->prev_sibling==0) { + if (this->node->parent==0) return *this; + this->node=this->node->parent; + if (top_node !=0 && this->node==top_node) return *this; + } + this->node=this->node->prev_sibling; + while(this->node->last_child) + this->node=this->node->last_child; + return *this; + } + +template +typename tree::leaf_iterator tree::leaf_iterator::operator++(int) + { + leaf_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::leaf_iterator tree::leaf_iterator::operator--(int) + { + leaf_iterator copy = *this; + --(*this); + return copy; + } + + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --num; + } + return (*this); + } + +#endif + +// Local variables: +// default-tab-width: 3 +// End: diff --git a/lib/tree-2.81/src/tree_example.cc b/lib/tree-2.81/src/tree_example.cc new file mode 100644 index 0000000..d351f51 --- /dev/null +++ b/lib/tree-2.81/src/tree_example.cc @@ -0,0 +1,59 @@ +/* + + Cadabra: a field-theory motivated computer algebra system. + Copyright (C) 2001-2009 Kasper Peeters + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include +#include +#include +#include "tree.hh" + +using namespace std; + +int main(int, char **) + { + tree tr; + tree::iterator top, one, two, loc, banana; + + top=tr.begin(); + one=tr.insert(top, "one"); + two=tr.append_child(one, "two"); + tr.append_child(two, "apple"); + banana=tr.append_child(two, "banana"); + tr.append_child(banana,"cherry"); + tr.append_child(two, "peach"); + tr.append_child(one,"three"); + + loc=find(tr.begin(), tr.end(), "two"); + if(loc!=tr.end()) { + tree::sibling_iterator sib=tr.begin(loc); + while(sib!=tr.end(loc)) { + cout << (*sib) << endl; + ++sib; + } + cout << endl; + tree::iterator sib2=tr.begin(loc); + tree::iterator end2=tr.end(loc); + while(sib2!=end2) { + for(int i=0; i + + (At the moment this only contains a printing utility, thanks to Linda + Buisman ) + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#ifndef tree_util_hh_ +#define tree_util_hh_ + +#include +#include "tree.hh" + +namespace kptree { + +template +void print_tree_bracketed(const tree& t, std::ostream& str=std::cout); + +template +void print_subtree_bracketed(const tree& t, typename tree::iterator iRoot, + std::ostream& str=std::cout); + + + +// Iterate over all roots (the head) and print each one on a new line +// by calling printSingleRoot. + +template +void print_tree_bracketed(const tree& t, std::ostream& str) + { + int headCount = t.number_of_siblings(t.begin()); + int headNum = 0; + for(typename tree::sibling_iterator iRoots = t.begin(); iRoots != t.end(); ++iRoots, ++headNum) { + print_subtree_bracketed(t,iRoots,str); + if (headNum != headCount) { + str << std::endl; + } + } + } + + +// Print everything under this root in a flat, bracketed structure. + +template +void print_subtree_bracketed(const tree& t, typename tree::iterator iRoot, std::ostream& str) + { + if(t.empty()) return; + if (t.number_of_children(iRoot) == 0) { + str << *iRoot; + } + else { + // parent + str << *iRoot; + str << "("; + // child1, ..., childn + int siblingCount = t.number_of_siblings(t.begin(iRoot)); + int siblingNum; + typename tree::sibling_iterator iChildren; + for (iChildren = t.begin(iRoot), siblingNum = 0; iChildren != t.end(iRoot); ++iChildren, ++siblingNum) { + // recursively print child + print_subtree_bracketed(t,iChildren,str); + // comma after every child except the last one + if (siblingNum != siblingCount ) { + str << ", "; + } + } + str << ")"; + } + } + +} + +#endif diff --git a/lib/tree-2.81/src/xinlin.hh b/lib/tree-2.81/src/xinlin.hh new file mode 100644 index 0000000..f8db036 --- /dev/null +++ b/lib/tree-2.81/src/xinlin.hh @@ -0,0 +1,1579 @@ +// STL-like templated tree class. +// Revised by: Xinlin Cao(xinlincao@gmail.com) +// Revised from Kasper Peeters's implementation.(http://www.aei.mpg.de/~peekas/tree/) +// +//# removed sibling iterator +//# added children iterator +//# removed a lot of member functions from tree and iterators +//# changed set_head() to set_root() +//# added root() member function +//# added reparent_roo() member function +//# changed implementation of operator = () +//# changed some member functions about getting iterators +//# tested all member functions +//# removed implicit conversion between different iterators +//# removed depth iterator +// This version of tree is simpler than old one. It is robust and easy for using and understanding. +// Copyright (C) 2001-2009 Kasper Peeters +// Distributed under the GNU General Public License version 3, +// (eventually to be changed to the Boost Software License). + +/** \mainpage tree.hh +\author Kasper Peeters +\version 2.65 +\date 03-Apr-2009 +\see http://www.aei.mpg.de/~peekas/tree/ +\see http://www.aei.mpg.de/~peekas/tree/ChangeLog + +The tree.hh library for C++ provides an STL-like container class +for n-ary trees, templated over the data stored at the +nodes. Various types of iterators are provided (post-order, +pre-order, and others). Where possible the access methods are +compatible with the STL or alternative algorithms are +available. +*/ + +#ifndef tree_hh_ +#define tree_hh_ + +#include +#include +#include +#include +#include +#include +#include + +// HP-style construct/destroy have gone from the standard, +// so here is a copy. + +namespace kp { + + template + void constructor(T1* p, T2& val) + { + new ((void *) p) T1(val); + } + + template + void constructor(T1* p) + { + new ((void *) p) T1; + } + + template + void destructor(T1* p) + { + p->~T1(); + } + +} + +/// A node in the tree, combining links to other nodes as well as the actual data. +template +class tree_node_ { // size: 5*4=20 bytes (on 32 bit arch), can be reduced by 8. +public: + tree_node_ *parent; + tree_node_ *first_child, *last_child; + tree_node_ *prev_sibling, *next_sibling; + T data; +}; // __attribute__((packed)); + +template > > +class tree { +protected: + typedef tree_node_ tree_node; +public: + /// Value of the data stored at a node. + typedef T value_type; + + class iterator_base; + class pre_order_iterator; + class post_order_iterator; + class children_iterator; + class leaf_iterator; + + tree(); + tree(const T&); + tree(const tree&); + ~tree(); + tree& operator=(const tree&); + + /// Base class for iterators, only pointers stored, no traversal logic. +#ifdef __SGI_STL_PORT + class iterator_base : public stlport::bidirectional_iterator { +#else + class iterator_base { +#endif + public: + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + iterator_base(); + iterator_base(tree_node *); + + T& operator*() const; + T* operator->() const; + + /// Number of children of the node pointed to by the iterator. + unsigned int number_of_children() const; + + children_iterator begin_children_iterator() const; + children_iterator end_children_iterator() const; + + tree_node *node; + }; + + /// Depth-first iterator, first accessing the node, then its children. + class pre_order_iterator : public iterator_base { + public: + pre_order_iterator(); + pre_order_iterator(tree_node *); + + bool operator==(const pre_order_iterator&) const; + bool operator!=(const pre_order_iterator&) const; + pre_order_iterator& operator++(); + pre_order_iterator& operator--(); + pre_order_iterator operator++(int); + pre_order_iterator operator--(int); + pre_order_iterator& operator+=(unsigned int); + pre_order_iterator& operator-=(unsigned int); + }; + + /// Depth-first iterator, first accessing the children, then the node itself. + class post_order_iterator : public iterator_base { + public: + post_order_iterator(); + post_order_iterator(tree_node *); + + bool operator==(const post_order_iterator&) const; + bool operator!=(const post_order_iterator&) const; + post_order_iterator& operator++(); + post_order_iterator& operator--(); + post_order_iterator operator++(int); + post_order_iterator operator--(int); + post_order_iterator& operator+=(unsigned int); + post_order_iterator& operator-=(unsigned int); + + /// Set iterator to the first child as deep as possible down the tree. + void descend_all(); + }; + + /// Breadth-first iterator, using a queue + class breadth_first_queued_iterator : public iterator_base { + public: + breadth_first_queued_iterator(); + breadth_first_queued_iterator(tree_node *); + + bool operator==(const breadth_first_queued_iterator&) const; + bool operator!=(const breadth_first_queued_iterator&) const; + breadth_first_queued_iterator& operator++(); + breadth_first_queued_iterator operator++(int); + breadth_first_queued_iterator& operator+=(unsigned int); + + private: + std::queue traversal_queue; + }; + + /// Iterator which traverses only the nodes which are siblings of each other. + class children_iterator : public iterator_base { + public: + children_iterator(); + children_iterator(tree_node *); + + bool operator==(const children_iterator&) const; + bool operator!=(const children_iterator&) const; + children_iterator& operator++(); + children_iterator& operator--(); + children_iterator operator++(int); + children_iterator operator--(int); + children_iterator& operator+=(unsigned int); + children_iterator& operator-=(unsigned int); + + tree_node *range_first() const; + tree_node *range_last() const; + tree_node *parent_; + private: + void set_parent_(); + }; + + /// Iterator which traverses only the leaves. + class leaf_iterator : public iterator_base { + public: + leaf_iterator(); + leaf_iterator(tree_node *, tree_node *top=0); + + bool operator==(const leaf_iterator&) const; + bool operator!=(const leaf_iterator&) const; + leaf_iterator& operator++(); + leaf_iterator& operator--(); + leaf_iterator operator++(int); + leaf_iterator operator--(int); + leaf_iterator& operator+=(unsigned int); + leaf_iterator& operator-=(unsigned int); + private: + tree_node *top_node; + }; + + /// Return iterator to the beginning of the tree. + inline pre_order_iterator root() const; + + /// Return iterator to the beginning of the tree. + inline pre_order_iterator begin_pre_order_iterator(const iterator_base&) const; + /// Return iterator to the end of the tree. + inline pre_order_iterator end_pre_order_iterator(const iterator_base&) const; + /// Return post-order iterator to the beginning of the tree. + post_order_iterator begin_post_order_iterator(const iterator_base&) const; + /// Return post-order end iterator of the tree. + post_order_iterator end_post_order_iterator(const iterator_base&) const; + + + /// Return breadth-first iterator based on a iterator. + breadth_first_queued_iterator begin_breadth_first_iterator(const iterator_base&) const; + /// Return breadth-first end iterator. + breadth_first_queued_iterator end_breadth_first_iterator(const iterator_base&) const; + + + /// Return children iterator to the first child of given node. + children_iterator begin_children_iterator(const iterator_base&) const; + /// Return children end iterator for children of given node. + children_iterator end_children_iterator(const iterator_base&) const; + + /// Return leaf iterator to the first leaf of the subtree at the given node. + leaf_iterator begin_leaf_iterator(const iterator_base& top) const; + /// Return leaf end iterator for the subtree at the given node. + leaf_iterator end_leaf_iterator(const iterator_base& top) const; + + /// 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; + /// Return iterator to the next sibling of a node. + template iter next_sibling(iter) const; + + /// Erase all nodes of the tree. + void clear(); + /// Erase element at position pointed to by iterator, return incremented iterator. + template iter erase(iter); + /// Erase all children of the node pointed to by iterator. + void erase_children(const iterator_base&); + + + /// Short-hand to insert_before topmost node in otherwise empty tree. + pre_order_iterator set_root(const T& x); + + /// Insert node as last/first child of node pointed to by position. + template iter append_child(iter position, const T& x); + template iter prepend_child(iter position, const T& x); + + /// Insert node as previous sibling of node pointed to by position. + template iter insert_before(iter position, const T& x); + /// Insert node as next sibling of node pointed to by position. + template iter insert_after(iter position, const T& x); + + /// Replace node at 'position' with other node (keeping same children); 'position' becomes invalid. + template iter replace(iter position, const T& x); + /// Replace node at 'position' with subtree starting at 'from' (do not erase subtree at 'from'); see above. + template iter replace(iter position, const iterator_base& from); + + ///set X as the new head of the tree, the old head will be a child of new head. + pre_order_iterator reparent_root(const T& x); + + /// Move 'source' node (plus its children) to become the next sibling of 'target'. + template iter move_after(iter target, iter source); + /// Move 'source' node (plus its children) to become the previous sibling of 'target'. + template iter move_before(iter target, iter source); + + /// Count the total number of nodes. + size_t size() const; + /// Count the total number of nodes below the indicated node (plus one). + size_t size(const iterator_base&) const; + /// Check if tree is empty. + bool empty() const; + /// Compute the depth to the root or to a fixed other iterator. + static int depth(const iterator_base&); + static int depth(const iterator_base&, const iterator_base&); + /// Determine the maximal depth of the tree. An empty tree has max_depth=-1. + int max_depth() const; + /// Determine the maximal depth of the tree with top node at the given position. + int max_depth(const iterator_base&) const; + /// Count the number of children of node at position. + static unsigned int number_of_children(const iterator_base&); + /// Determine whether the iterator is an 'end' iterator and thus not actually pointing to a node. + bool is_valid(const iterator_base&) const; + + /// Determine the index of a node in the range of siblings to which it belongs. + unsigned int index(children_iterator it) const; + /// Inverse of 'index': return the n-th child of the node at position. + static children_iterator child(const iterator_base& position, unsigned int); + + /// Comparator class for iterators (compares pointer values; why doesn't this work automatically?) + class iterator_base_less { + public: + bool operator()(const typename tree::iterator_base& one, + const typename tree::iterator_base& two) const + { + return one.node < two.node; + } + }; + tree_node *head, *feet; // head/feet are always dummy; if an iterator points to them it is invalid +private: + tree_node_allocator alloc_; + void head_initialise_(); + void copy_(const tree& other); + + /// Comparator class for two nodes of a tree (used for sorting and searching). + template + class compare_nodes { + public: + compare_nodes(StrictWeakOrdering comp) : comp_(comp) {}; + + bool operator()(const tree_node *a, const tree_node *b) + { + return comp_(a->data, b->data); + } + private: + StrictWeakOrdering comp_; + }; +}; + + + +// Tree + +template +tree::tree() +{ + head_initialise_(); +} + +template +tree::tree(const T& x) +{ + head_initialise_(); + set_root(x); +} + +template +tree::~tree() +{ + clear(); + alloc_.deallocate(head,1); + alloc_.deallocate(feet,1); +} + +template +void tree::head_initialise_() +{ + head = alloc_.allocate(1,0); // MSVC does not have default second argument + feet = alloc_.allocate(1,0); + + head->parent=0; + head->first_child=0; + head->last_child=0; + head->prev_sibling=0; //head; + head->next_sibling=feet; //head; + + feet->parent=0; + feet->first_child=0; + feet->last_child=0; + feet->prev_sibling=head; + feet->next_sibling=0; +} + +template +tree& tree::operator=(const tree& other) +{ + if (this != &other) + { + copy_(other); + } + return (*this); +} + +template +tree::tree(const tree& other) +{ + head_initialise_(); + copy_(other); +} + +template +void tree::copy_(const tree& other) +{ + //check self + if (this == &other) + { + return; + } + clear(); + pre_order_iterator it=other.begin_pre_order_iterator(other.root()), to=begin_pre_order_iterator(root()); + while(it!=other.end_pre_order_iterator(other.root())) { + to=insert_before(to, (*it)); + ++it; + } + to=begin_pre_order_iterator(root()); + it=other.begin_pre_order_iterator(other.root()); + while(it!=other.end_pre_order_iterator(other.root())) { + to=replace(to, it); + ++to; + ++it; + } +} + +template +void tree::clear() +{ + if(head) + while(head->next_sibling!=feet) + erase(pre_order_iterator(head->next_sibling)); +} + +template +void tree::erase_children(const iterator_base& it) +{ + // std::cout << "erase_children " << it.node << std::endl; + if(it.node==0) return; + + tree_node *cur=it.node->first_child; + tree_node *prev=0; + + while(cur!=0) { + prev=cur; + cur=cur->next_sibling; + erase_children(pre_order_iterator(prev)); + kp::destructor(&prev->data); + alloc_.deallocate(prev,1); + } + it.node->first_child=0; + it.node->last_child=0; + // std::cout << "exit" << std::endl; +} + +template +template +iter tree::erase(iter it) +{ + tree_node *cur=it.node; + assert(cur!=head); + iter ret=it; + ++ret; + erase_children(it); + if(cur->prev_sibling==0) { + cur->parent->first_child=cur->next_sibling; + } + else { + cur->prev_sibling->next_sibling=cur->next_sibling; + } + if(cur->next_sibling==0) { + cur->parent->last_child=cur->prev_sibling; + } + else { + cur->next_sibling->prev_sibling=cur->prev_sibling; + } + + kp::destructor(&cur->data); + alloc_.deallocate(cur,1); + return ret; +} + +template +typename tree::pre_order_iterator tree::root() const +{ + return pre_order_iterator(head->next_sibling); +} + + +template +typename tree::pre_order_iterator tree::begin_pre_order_iterator(const iterator_base& pos) const +{ + return pre_order_iterator(pos.node); +} + +template +typename tree::pre_order_iterator tree::end_pre_order_iterator(const iterator_base& pos) const +{ + return pre_order_iterator(pos.node->next_sibling); +} + + + +template +typename tree::breadth_first_queued_iterator tree::begin_breadth_first_iterator(const iterator_base& pos) const +{ + return breadth_first_queued_iterator(pos.node); +} + +template +typename tree::breadth_first_queued_iterator tree::end_breadth_first_iterator(const iterator_base& pos) const +{ + return breadth_first_queued_iterator(); +} + + +template +typename tree::post_order_iterator tree::begin_post_order_iterator(const iterator_base& pos) const +{ + tree_node *tmp=pos.node; + if(tmp!=feet) { + while(tmp->first_child) + tmp=tmp->first_child; + } + return post_order_iterator(tmp); +} + +template +typename tree::post_order_iterator tree::end_post_order_iterator(const iterator_base& pos) const +{ + return post_order_iterator(pos.node->next_sibling); +} + + +template +typename tree::children_iterator tree::begin_children_iterator(const iterator_base& pos) const +{ + assert(pos.node!=0); + if(pos.node->first_child==0) { + return end_children_iterator(pos); + } + return pos.node->first_child; +} + +template +typename tree::children_iterator tree::end_children_iterator(const iterator_base& pos) const +{ + children_iterator ret(0); + ret.parent_=pos.node; + return ret; +} + +template +typename tree::leaf_iterator tree::begin_leaf_iterator(const iterator_base& top) const +{ + tree_node *tmp=top.node; + while(tmp->first_child) + tmp=tmp->first_child; + return leaf_iterator(tmp, top.node); +} + +template +typename tree::leaf_iterator tree::end_leaf_iterator(const iterator_base& top) const +{ + return leaf_iterator(top.node, top.node); +} + +template +template +iter tree::parent(iter position) +{ + assert(position.node!=0); + return iter(position.node->parent); +} + +template +template +iter tree::previous_sibling(iter position) const +{ + assert(position.node!=0); + iter ret(position); + ret.node=position.node->prev_sibling; + return ret; +} + +template +template +iter tree::next_sibling(iter position) const +{ + assert(position.node!=0); + iter ret(position); + ret.node=position.node->next_sibling; + return ret; +} + +template +template +iter tree::append_child(iter position, const T& x) +{ + // If your program fails here you probably used 'append_child' to add the top + // node to an empty tree. From version 1.45 the top element should be added + // using 'insert_before'. See the documentation for further information, and sorry about + // the API change. + assert(position.node!=head); + assert(position.node); + + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->last_child!=0) { + position.node->last_child->next_sibling=tmp; + } + else { + position.node->first_child=tmp; + } + tmp->prev_sibling=position.node->last_child; + position.node->last_child=tmp; + tmp->next_sibling=0; + return tmp; +} + +template +template +iter tree::prepend_child(iter position, const T& x) +{ + assert(position.node!=head); + assert(position.node); + + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->first_child!=0) { + position.node->first_child->prev_sibling=tmp; + } + else { + position.node->last_child=tmp; + } + tmp->next_sibling=position.node->first_child; + position.node->first_child=tmp; + tmp->prev_sibling=0; + return tmp; +} + + +template +typename tree::pre_order_iterator tree::set_root(const T& x) +{ + assert(head->next_sibling==feet); + return insert_before(pre_order_iterator(feet), x); +} + +template +template +iter tree::insert_before(iter position, const T& x) +{ + if(position.node==0) { + position.node=feet; // Backward compatibility: when calling insert_before on a null node, + // insert_before before the feet. + } + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->next_sibling=position.node; + tmp->prev_sibling=position.node->prev_sibling; + position.node->prev_sibling=tmp; + + if(tmp->prev_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->first_child=tmp; + } + else + tmp->prev_sibling->next_sibling=tmp; + return tmp; +} + + +template +template +iter tree::insert_after(iter position, const T& x) +{ + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->prev_sibling=position.node; + tmp->next_sibling=position.node->next_sibling; + position.node->next_sibling=tmp; + + if(tmp->next_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->last_child=tmp; + } + else { + tmp->next_sibling->prev_sibling=tmp; + } + return tmp; +} + + +template +template +iter tree::replace(iter position, const T& x) +{ + kp::destructor(&position.node->data); + kp::constructor(&position.node->data, x); + return position; +} + +template +template +iter tree::replace(iter position, const iterator_base& from) +{ + assert(position.node!=head); + tree_node *current_from=from.node; + tree_node *start_from=from.node; + tree_node *current_to =position.node; + + // replace the node at position with head of the replacement tree at from + // std::cout << "warning!" << position.node << std::endl; + erase_children(position); + // std::cout << "no warning!" << std::endl; + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, (*from)); + tmp->first_child=0; + tmp->last_child=0; + if(current_to->prev_sibling==0) { + if(current_to->parent!=0) + current_to->parent->first_child=tmp; + } + else { + current_to->prev_sibling->next_sibling=tmp; + } + tmp->prev_sibling=current_to->prev_sibling; + if(current_to->next_sibling==0) { + if(current_to->parent!=0) + current_to->parent->last_child=tmp; + } + else { + current_to->next_sibling->prev_sibling=tmp; + } + tmp->next_sibling=current_to->next_sibling; + tmp->parent=current_to->parent; + kp::destructor(¤t_to->data); + alloc_.deallocate(current_to,1); + current_to=tmp; + + // only at this stage can we fix 'last' + tree_node *last=from.node->next_sibling; + + pre_order_iterator toit=tmp; + // copy all children + do { + assert(current_from!=0); + if(current_from->first_child != 0) { + current_from=current_from->first_child; + toit=append_child(toit, current_from->data); + } + else { + while(current_from->next_sibling==0 && current_from!=start_from) { + current_from=current_from->parent; + toit=parent(toit); + assert(current_from!=0); + } + current_from=current_from->next_sibling; + if(current_from!=last) { + toit=append_child(parent(toit), current_from->data); + } + } + } while(current_from!=last); + + return current_to; +} + + +///set X as the new head of the tree, the old head will be a child of new head. +template +typename tree::pre_order_iterator tree::reparent_root(const T& x) +{ + if(head->next_sibling == feet->prev_sibling) + { + return this->set_root(x); + } + else + { + //remember the old head + tree_node *old_head_node = head->next_sibling; + + //create a new head + insert_before(pre_order_iterator(feet), x); + + //change the tree head + tree_node *new_head_node = head->next_sibling->next_sibling; + head->next_sibling = new_head_node; + + //change the new head + new_head_node->first_child = old_head_node; + new_head_node->last_child = old_head_node; + new_head_node->next_sibling = feet; + new_head_node->prev_sibling = head; + + //change the feet + feet->prev_sibling = new_head_node; + + //change the old head + old_head_node->next_sibling = 0; + old_head_node->prev_sibling = 0; + old_head_node->parent = new_head_node; + + return begin_pre_order_iterator(root()); + } +} + +template +template iter tree::move_after(iter target, iter source) +{ + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return source; + if(dst->next_sibling) + if(dst->next_sibling==src) // already in the right spot + return source; + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst->next_sibling!=0) dst->next_sibling->prev_sibling=src; + else dst->parent->last_child=src; + src->next_sibling=dst->next_sibling; + dst->next_sibling=src; + src->prev_sibling=dst; + src->parent=dst->parent; + return src; +} + +template +template iter tree::move_before(iter target, iter source) +{ + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return source; + if(dst->prev_sibling) + if(dst->prev_sibling==src) // already in the right spot + return source; + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst->prev_sibling!=0) dst->prev_sibling->next_sibling=src; + else dst->parent->first_child=src; + src->prev_sibling=dst->prev_sibling; + dst->prev_sibling=src; + src->next_sibling=dst; + src->parent=dst->parent; + return src; +} + + +template +size_t tree::size() const +{ + size_t i=0; + pre_order_iterator it=begin_pre_order_iterator(), eit=end_pre_order_iterator(); + while(it!=eit) { + ++i; + ++it; + } + return i; +} + +template +size_t tree::size(const iterator_base& top) const +{ + size_t i=0; + pre_order_iterator it=top, eit=top; + ++eit; + while(it!=eit) { + ++i; + ++it; + } + return i; +} + +template +bool tree::empty() const +{ + pre_order_iterator it=begin_pre_order_iterator(), eit=end_pre_order_iterator(); + return (it==eit); +} + +template +int tree::depth(const iterator_base& it) +{ + tree_node* pos=it.node; + assert(pos!=0); + int ret=0; + while(pos->parent!=0) { + pos=pos->parent; + ++ret; + } + return ret; +} + +template +int tree::depth(const iterator_base& it, const iterator_base& root) +{ + tree_node* pos=it.node; + assert(pos!=0); + int ret=0; + while(pos->parent!=0 && pos!=root.node) { + pos=pos->parent; + ++ret; + } + return ret; +} + +template +int tree::max_depth() const +{ + int maxd=-1; + for(tree_node *it = head->next_sibling; it!=feet; it=it->next_sibling) + maxd=std::max(maxd, max_depth(it)); + + return maxd; +} + + +template +int tree::max_depth(const iterator_base& pos) const +{ + tree_node *tmp=pos.node; + + if(tmp==0 || tmp==head || tmp==feet) return -1; + + int curdepth=0, maxdepth=0; + while(true) { // try to walk the bottom of the tree + while(tmp->first_child==0) { + if(tmp==pos.node) return maxdepth; + if(tmp->next_sibling==0) { + // try to walk up and then right again + do { + tmp=tmp->parent; + if(tmp==0) return maxdepth; + --curdepth; + } while(tmp->next_sibling==0); + } + if(tmp==pos.node) return maxdepth; + tmp=tmp->next_sibling; + } + tmp=tmp->first_child; + ++curdepth; + maxdepth=std::max(curdepth, maxdepth); + } +} + +template +unsigned int tree::number_of_children(const iterator_base& it) +{ + tree_node *pos=it.node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; + // while(pos!=it.node->last_child) { + // ++ret; + // pos=pos->next_sibling; + // } + while((pos=pos->next_sibling)) + ++ret; + return ret; +} + +template +bool tree::is_valid(const iterator_base& it) const +{ + if(it.node==0 || it.node==feet || it.node==head) return false; + else return true; +} + +template +unsigned int tree::index(children_iterator it) const +{ + unsigned int ind=0; + if(it.node->parent==0) { + while(it.node->prev_sibling!=head) { + it.node=it.node->prev_sibling; + ++ind; + } + } + else { + while(it.node->prev_sibling!=0) { + it.node=it.node->prev_sibling; + ++ind; + } + } + return ind; +} + +template +typename tree::children_iterator tree::child(const iterator_base& it, unsigned int num) +{ + tree_node *tmp=it.node->first_child; + while(num--) { + assert(tmp!=0); + tmp=tmp->next_sibling; + } + return tmp; +} + + + + +// Iterator base + +template +tree::iterator_base::iterator_base() +: node(0) +{ +} + +template +tree::iterator_base::iterator_base(tree_node *tn) +: node(tn) +{ +} + +template +T& tree::iterator_base::operator*() const +{ + return node->data; +} + +template +T* tree::iterator_base::operator->() const +{ + return &(node->data); +} + +template +bool tree::post_order_iterator::operator!=(const post_order_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::post_order_iterator::operator==(const post_order_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +bool tree::pre_order_iterator::operator!=(const pre_order_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::pre_order_iterator::operator==(const pre_order_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +bool tree::children_iterator::operator!=(const children_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::children_iterator::operator==(const children_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +bool tree::leaf_iterator::operator!=(const leaf_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::leaf_iterator::operator==(const leaf_iterator& other) const +{ + if(other.node==this->node && other.top_node==this->top_node) return true; + else return false; +} + +template +typename tree::children_iterator tree::iterator_base::begin_children_iterator() const +{ + if(node->first_child==0) + return end_children_iterator(); + + children_iterator ret(node->first_child); + ret.parent_=this->node; + return ret; +} + +template +typename tree::children_iterator tree::iterator_base::end_children_iterator() const +{ + children_iterator ret(0); + ret.parent_=node; + return ret; +} + +template +unsigned int tree::iterator_base::number_of_children() const +{ + tree_node *pos=node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; + while(pos!=node->last_child) { + ++ret; + pos=pos->next_sibling; + } + return ret; +} + + + +// Pre-order iterator + +template +tree::pre_order_iterator::pre_order_iterator() +: iterator_base(0) +{ +} + +template +tree::pre_order_iterator::pre_order_iterator(tree_node *tn) +: iterator_base(tn) +{ +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator++() +{ + assert(this->node!=0); + if(this->node->first_child != 0) { + this->node=this->node->first_child; + } + else { + while(this->node->next_sibling==0) { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + this->node=this->node->next_sibling; + } + return *this; +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator--() +{ + assert(this->node!=0); + if(this->node->prev_sibling) { + this->node=this->node->prev_sibling; + while(this->node->last_child) + this->node=this->node->last_child; + } + else { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + return *this; +} + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator++(int) +{ + pre_order_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator--(int) +{ + pre_order_iterator copy = *this; + --(*this); + return copy; +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + + + +// Post-order iterator + +template +tree::post_order_iterator::post_order_iterator() +: iterator_base(0) +{ +} + +template +tree::post_order_iterator::post_order_iterator(tree_node *tn) +: iterator_base(tn) +{ +} + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator++() +{ + assert(this->node!=0); + if(this->node->next_sibling==0) { + this->node=this->node->parent; + } + else { + this->node=this->node->next_sibling; + while(this->node->first_child) + this->node=this->node->first_child; + } + return *this; +} + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator--() +{ + assert(this->node!=0); + if(this->skip_current_children_ || this->node->last_child==0) { + this->skip_current_children_=false; + while(this->node->prev_sibling==0) + this->node=this->node->parent; + this->node=this->node->prev_sibling; + } + else { + this->node=this->node->last_child; + } + return *this; +} + +template +typename tree::post_order_iterator tree::post_order_iterator::operator++(int) +{ + post_order_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::post_order_iterator tree::post_order_iterator::operator--(int) +{ + post_order_iterator copy = *this; + --(*this); + return copy; +} + + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + +template +void tree::post_order_iterator::descend_all() +{ + assert(this->node!=0); + while(this->node->first_child) + this->node=this->node->first_child; +} + + +// Breadth-first iterator + +template +tree::breadth_first_queued_iterator::breadth_first_queued_iterator() +: iterator_base() +{ +} + +template +tree::breadth_first_queued_iterator::breadth_first_queued_iterator(tree_node *tn) +: iterator_base(tn) +{ + traversal_queue.push(tn); +} + +template +bool tree::breadth_first_queued_iterator::operator!=(const breadth_first_queued_iterator& other) const +{ + if(other.node!=this->node) return true; + else return false; +} + +template +bool tree::breadth_first_queued_iterator::operator==(const breadth_first_queued_iterator& other) const +{ + if(other.node==this->node) return true; + else return false; +} + +template +typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator++() +{ + assert(this->node!=0); + + // Add child nodes and pop current node + children_iterator sib=this->begin_children_iterator(); + while(sib!=this->end_children_iterator()) { + traversal_queue.push(sib.node); + ++sib; + } + traversal_queue.pop(); + if(traversal_queue.size()>0) + this->node=traversal_queue.front(); + else + this->node=0; + return (*this); +} + +template +typename tree::breadth_first_queued_iterator tree::breadth_first_queued_iterator::operator++(int) +{ + breadth_first_queued_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::breadth_first_queued_iterator& tree::breadth_first_queued_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +// Sibling iterator + +template +tree::children_iterator::children_iterator() +: iterator_base() +{ + set_parent_(); +} + +template +tree::children_iterator::children_iterator(tree_node *tn) +: iterator_base(tn) +{ + set_parent_(); +} + +template +void tree::children_iterator::set_parent_() +{ + parent_=0; + if(this->node==0) return; + if(this->node->parent!=0) + parent_=this->node->parent; +} + +template +typename tree::children_iterator& tree::children_iterator::operator++() +{ + if(this->node) + this->node=this->node->next_sibling; + return *this; +} + +template +typename tree::children_iterator& tree::children_iterator::operator--() +{ + if(this->node) this->node=this->node->prev_sibling; + else { + assert(parent_); + this->node=parent_->last_child; + } + return *this; +} + +template +typename tree::children_iterator tree::children_iterator::operator++(int) +{ + children_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::children_iterator tree::children_iterator::operator--(int) +{ + children_iterator copy = *this; + --(*this); + return copy; +} + +template +typename tree::children_iterator& tree::children_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::children_iterator& tree::children_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + +template +typename tree::tree_node *tree::children_iterator::range_first() const +{ + tree_node *tmp=parent_->first_child; + return tmp; +} + +template +typename tree::tree_node *tree::children_iterator::range_last() const +{ + return parent_->last_child; +} + +// Leaf iterator + +template +tree::leaf_iterator::leaf_iterator() +: iterator_base(0), top_node(0) +{ +} + +template +tree::leaf_iterator::leaf_iterator(tree_node *tn, tree_node *top) +: iterator_base(tn), top_node(top) +{ +} + + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator++() +{ + assert(this->node!=0); + if(this->node->first_child!=0) { // current node is no longer leaf (children got added) + while(this->node->first_child) + this->node=this->node->first_child; + } + else { + while(this->node->next_sibling==0) { + if (this->node->parent==0) return *this; + this->node=this->node->parent; + if (top_node != 0 && this->node==top_node) return *this; + } + this->node=this->node->next_sibling; + while(this->node->first_child) + this->node=this->node->first_child; + } + return *this; +} + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator--() +{ + assert(this->node!=0); + while (this->node->prev_sibling==0) { + if (this->node->parent==0) return *this; + this->node=this->node->parent; + if (top_node !=0 && this->node==top_node) return *this; + } + this->node=this->node->prev_sibling; + while(this->node->last_child) + this->node=this->node->last_child; + return *this; +} + +template +typename tree::leaf_iterator tree::leaf_iterator::operator++(int) +{ + leaf_iterator copy = *this; + ++(*this); + return copy; +} + +template +typename tree::leaf_iterator tree::leaf_iterator::operator--(int) +{ + leaf_iterator copy = *this; + --(*this); + return copy; +} + + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator+=(unsigned int num) +{ + while(num>0) { + ++(*this); + --num; + } + return (*this); +} + +template +typename tree::leaf_iterator& tree::leaf_iterator::operator-=(unsigned int num) +{ + while(num>0) { + --(*this); + --num; + } + return (*this); +} + +#endif diff --git a/lib/vectorwrapper b/lib/vectorwrapper new file mode 160000 index 0000000..39c58ca --- /dev/null +++ b/lib/vectorwrapper @@ -0,0 +1 @@ +Subproject commit 39c58ca4aba6066de440408a2086248fdb867446 diff --git a/src/compatibility.h b/src/compatibility.h new file mode 100644 index 0000000..ad115f0 --- /dev/null +++ b/src/compatibility.h @@ -0,0 +1,58 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . + +*/ + +#ifndef id45CDD1DAEF4F42968E3C89F68FDDA9BC +#define id45CDD1DAEF4F42968E3C89F68FDDA9BC + +#if defined(__GNUC__) +# if defined(__clang__) +# if !defined(__has_attribute) + //Fall back to version number comparing +# else +# if __has_attribute(flatten) +# define a_flatten __attribute__((flatten)) +# else +# define a_flatten +# endif +# if __has_attribute(always_inline) +# define a_always_inline __attribute__((always_inline)) +# else +# define a_always_inline +# endif +# if __has_attribute(pure) +# define a_pure __attribute__((pure)) +# else +# define a_pure +# endif +# endif +# else + //Fix here if you get warnings about unsupported attributes on your compiler +# define a_flatten __attribute__((flatten)) +# define a_always_inline __attribute__((always_inline)) +# define a_pure __attribute__((pure)) +# endif +#else +# warning "Unsupported compiler, please fill this section or file a bug" +# define a_flatten +# define a_always_inline +# define a_pure +#endif + +#endif diff --git a/src/gamescenebase.hpp b/src/gamescenebase.hpp new file mode 100644 index 0000000..8b244b0 --- /dev/null +++ b/src/gamescenebase.hpp @@ -0,0 +1,13 @@ +#pragma once + +namespace curry { + class GameSceneBase { + public: + virtual ~GameSceneBase() noexcept = default; + + virtual void prepare() = 0; + virtual void exec() = 0; + virtual bool wants_to_quit() const = 0; + virtual void destroy() noexcept = 0; + }; +} //namespace curry diff --git a/src/ingamescene.cpp b/src/ingamescene.cpp new file mode 100644 index 0000000..8ba27bf --- /dev/null +++ b/src/ingamescene.cpp @@ -0,0 +1,27 @@ +#include "ingamescene.hpp" +#include + +namespace curry { + IngameScene::IngameScene (cloonel::SDLMain* parSDLMain) : + m_sdlmain(parSDLMain) + { + } + + IngameScene::~IngameScene() noexcept = default; + + void IngameScene::prepare() { + std::cout << "game prepare\n"; + } + + void IngameScene::exec() { + std::cout << "game exec\n"; + } + + bool IngameScene::wants_to_quit() const { + return true; + } + + void IngameScene::destroy() noexcept { + std::cout << "game destroy\n"; + } +} //namespace curry diff --git a/src/ingamescene.hpp b/src/ingamescene.hpp new file mode 100644 index 0000000..7bc5a31 --- /dev/null +++ b/src/ingamescene.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "gamescenebase.hpp" + +namespace cloonel { + class SDLMain; +} //namespace cloonel + +namespace curry { + class IngameScene : public GameSceneBase { + public: + explicit IngameScene (cloonel::SDLMain* parSDLMain); + virtual ~IngameScene() noexcept; + + virtual void prepare() override; + virtual void exec() override; + virtual bool wants_to_quit() const override; + virtual void destroy() noexcept override; + + private: + cloonel::SDLMain* m_sdlmain; + }; +} //namespace curry diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..15b6b99 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,48 @@ +#include "sdlmain.hpp" +#include "gamescenebase.hpp" +#include "ingamescene.hpp" +#include +#include +#include + +namespace { + const uint16_t DEF_WIN_WIDTH = 640; + const uint16_t DEF_WIN_HEIGHT = 480; + const uint16_t REFERENCE_WIDTH = 800; + const uint16_t REFERENCE_HEIGHT = 600; + const char GameName[] = "MyCurry"; + + void run_main_loop (curry::GameSceneBase& parGame) { + parGame.prepare(); + do { + parGame.exec(); + } while (not parGame.wants_to_quit()); + parGame.destroy(); + } +} //unnamed namespace + +int main() { + cloonel::SDLMain sdl_main( + GameName, + cloonel::ushort2(DEF_WIN_WIDTH, DEF_WIN_HEIGHT), + cloonel::ushort2(REFERENCE_WIDTH, REFERENCE_HEIGHT) + ); + + int ret_val = 0; + try { + sdl_main.Init(); + std::cout << "Using renderer \"" << sdl_main.GetRendererName() << "\" "; + std::cout << "and video driver \"" << sdl_main.GetVideoDriverName() << "\"\n"; + + curry::IngameScene game(&sdl_main); + run_main_loop(game); + } + catch (const std::runtime_error& e) { + std::cerr << "Error during SDL2 initialization:\n"; + std::cerr << e.what() << std::endl; + ret_val = 1; + } + + std::cout << "Quitting now" << std::endl; + return ret_val;; +} diff --git a/src/observersmanager.hpp b/src/observersmanager.hpp new file mode 100644 index 0000000..926c532 --- /dev/null +++ b/src/observersmanager.hpp @@ -0,0 +1,180 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#ifndef idF5E41734950640CDA3C949E0D3A9A30D +#define idF5E41734950640CDA3C949E0D3A9A30D + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (WITH_VERBOSE_OBS_MANAGER) && defined(__GNUC__) && __GNUC__ >= 2 && !defined(NDEBUG) +# define OBS_MANAGER_LOG +#endif + +#if defined(OBS_MANAGER_LOG) +# include +#endif + +namespace cloonel { + template + class ObserversManager { + public: + typedef size_t TicketType; + + private: + struct TicketedWrapper { + TicketedWrapper ( void ) = default; + TicketedWrapper ( T parItem, TicketType parTicket ) : + itm(parItem), + ticket(parTicket) + { + } + + T itm; + TicketType ticket; + + bool operator== ( const TicketedWrapper& parOther ) const { return parOther.ticket == ticket; } + bool operator== ( TicketType parOther ) const { return parOther == ticket; } + }; + static T& TicketedWrapperToItm ( TicketedWrapper& parWrapper ) { return parWrapper.itm; } + + typedef tree TreeType; + typedef typename tree::iterator TreeIteratorType; + + public: + enum { + Ticket_Null = 0 + }; + typedef boost::transform_iterator, TreeIteratorType> iterator; + + ObserversManager ( void ); + ~ObserversManager ( void ) noexcept; + + TicketType Add ( T parObserver, TicketType parParent=Ticket_Null ); + void Remove ( TicketType parTicket ) noexcept; + void RemoveAll ( void ) noexcept; + void Update ( TicketType parTicket, T parObserver ); + std::size_t size ( void ) const { return m_tree.size(); } + iterator begin ( void ) { return iterator(m_tree.begin(), &TicketedWrapperToItm); } + iterator end ( void ) { return iterator(m_tree.end(), &TicketedWrapperToItm); } + void CopyObservers ( std::unordered_set& parOut ); + + private: + TreeIteratorType GetByTicket_AssertPresent ( TicketType parTicket ); + + TreeType m_tree; + TicketType m_nextTicket; + }; + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + ObserversManager::ObserversManager() : + m_nextTicket(1) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + ObserversManager::~ObserversManager() noexcept { + assert(m_tree.empty()); + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + typename ObserversManager::TicketType ObserversManager::Add (T parObserver, TicketType parParent) { + const auto currTicket = m_nextTicket; + if (Ticket_Null == parParent) + m_tree.insert(m_tree.begin(), TicketedWrapper(parObserver, currTicket)); + else + m_tree.append_child(GetByTicket_AssertPresent(parParent), TicketedWrapper(parObserver, currTicket)); + +#if defined(OBS_MANAGER_LOG) + std::cout << __PRETTY_FUNCTION__ << " registering " << currTicket << " as a child of " << parParent << "\n"; +#endif + ++m_nextTicket; + return currTicket; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void ObserversManager::Remove (TicketType parTicket) noexcept { + auto deleme = GetByTicket_AssertPresent(parTicket); +#if defined(OBS_MANAGER_LOG) + for (auto it(deleme); it != m_tree.end(); ++it) { + std::cout << __PRETTY_FUNCTION__ << " unregistering " << it->ticket << "\n"; + } +#endif + m_tree.erase(deleme); + if (parTicket == m_nextTicket - 1) + --m_nextTicket; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void ObserversManager::RemoveAll() noexcept { + if (not m_tree.empty()) { + for (typename TreeType::sibling_iterator it(m_tree.begin()), itEND(m_tree.end()); it != itEND; ++it) { + const TicketType ticket = it->ticket; + this->Remove(ticket); + } + assert(m_tree.empty()); + } + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void ObserversManager::Update (TicketType parTicket, T parObserver) { + std::swap(GetByTicket_AssertPresent(parTicket)->itm, parObserver); + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + typename ObserversManager::TreeIteratorType ObserversManager::GetByTicket_AssertPresent (TicketType parTicket) { + auto ret = std::find(m_tree.begin(), m_tree.end(), parTicket); + assert(m_tree.end() != ret); + return ret; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void ObserversManager::CopyObservers (std::unordered_set& parOut) { + for (const auto& itm : m_tree) { + parOut.insert(itm.itm); + } + } +} //namespace cloonel + +#if defined(OBS_MANAGER_LOG) +# undef OBS_MANAGER_LOG +#endif +#endif diff --git a/src/sdlmain.cpp b/src/sdlmain.cpp new file mode 100644 index 0000000..2d0d9df --- /dev/null +++ b/src/sdlmain.cpp @@ -0,0 +1,236 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#include "sdlmain.hpp" +#include "observersmanager.hpp" +#include "sizenotifiable.hpp" +#include "sizeratio.hpp" +#include +#include +#include +#include +#include +#include + +#if defined(RASPBERRY_PI) +#include +#endif + +namespace cloonel { + namespace { + ///---------------------------------------------------------------------- + ///---------------------------------------------------------------------- + std::pair GetRenderingDriver() { + typedef std::pair RetPairType; + + const int count = SDL_GetNumRenderDrivers(); + int opengles = -1; + int opengles2 = -1; + int opengl = -1; + SDL_RendererInfo info; + for (int z = 0; z < count; ++z) { + const int ret = SDL_GetRenderDriverInfo(z, &info); + if (0 == ret) { + if (std::strcmp("opengles", info.name) == 0) + opengles = z; + else if (std::strcmp("opengles2", info.name) == 0) + opengles2 = z; + else if (std::strcmp("opengl", info.name) == 0) + opengl = z; + } + } +#if !defined(FORCE_OPENGLES) + if (opengl > -1) + return RetPairType(opengl, "opengl"); +#endif + if (opengles2 > -1) + return RetPairType(opengles2, "opengles2"); + if (opengles > -1) + return RetPairType(opengles, "opengles"); +#if defined(FORCE_OPENGLES) + if (opengl > -1) + return RetPairType(opengl, "opengl"); +#endif + + return RetPairType(-1, "default"); + } + } //unnamed namespace + + struct SDLMain::LocalData { + SDL_Window* window; + SDL_Renderer* renderer; + SizeRatio sizeratio; + ObserversManager resChangeNotifList; + bool initialized; +#if defined(RASPBERRY_PI) + bool bcmInitialized; +#endif + }; + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + SDLMain::SDLMain (const char* parGameName, ushort2 parRes, ushort2 parReferenceRes) : + m_gameName(parGameName), + m_localData(new LocalData) + { + m_localData->sizeratio.SetOriginal(static_cast(parReferenceRes), static_cast(parRes)); + m_localData->initialized = false; +#if defined(RASPBERRY_PI) + m_localData->bcmInitialized = false; +#endif + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + SDLMain::~SDLMain() noexcept { + ClearIFN(*m_localData); +#if defined(RASPBERRY_PI) + assert(not m_localData->bcmInitialized); +#endif + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + void SDLMain::Init() { + if (not m_localData->initialized) + InitSDL(*m_localData); + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + void SDLMain::InitSDL (LocalData& parInitSDL) { +#if defined(RASPBERRY_PI) + assert(not parInitSDL.bcmInitialized); + bcm_host_init(); + parInitSDL.bcmInitialized = true; +#endif + + parInitSDL.window = nullptr; + parInitSDL.renderer = nullptr; + parInitSDL.initialized = false; + + if (SDL_Init(SDL_INIT_EVERYTHING) == -1) + throw std::runtime_error(SDL_GetError()); + parInitSDL.initialized = true; + +#if defined(FORCE_OPENGLES) + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); +#endif + + const float2 wh(m_localData->sizeratio.Resolution()); + SDL_Window* const win = SDL_CreateWindow(m_gameName.c_str(), 100, 100, static_cast(wh.x()), static_cast(wh.y()), SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + if (!win) + throw std::runtime_error(SDL_GetError()); + parInitSDL.window = win; + + const auto rendererDriver = GetRenderingDriver(); + m_rendererName = rendererDriver.second; + SDL_Renderer* const renderer = SDL_CreateRenderer(win, rendererDriver.first, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!renderer) + throw std::runtime_error(SDL_GetError()); + parInitSDL.renderer = renderer; + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + void SDLMain::ClearIFN (LocalData& parInitSDL) noexcept { + if (parInitSDL.renderer) + SDL_DestroyRenderer(parInitSDL.renderer); + if (parInitSDL.window) + SDL_DestroyWindow(parInitSDL.window); + if (parInitSDL.initialized) { + parInitSDL.initialized = false; + SDL_Quit(); + } +#if defined(RASPBERRY_PI) + if (parInitSDL.bcmInitialized) { + parInitSDL.bcmInitialized = false; + bcm_host_deinit(); + } +#endif + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + SDL_Renderer* SDLMain::GetRenderer() { + if (m_localData->initialized) + return m_localData->renderer; + else + return nullptr; + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + void SDLMain::SetResolution (ushort2 parRes) { + m_localData->sizeratio.UpdateResolution(static_cast(parRes)); + { + SDL_Renderer* const renderer = GetRenderer(); + assert(renderer); + const int retVal = SDL_RenderSetLogicalSize(renderer, parRes.x(), parRes.y()); + if (retVal) { + std::ostringstream oss; + oss << "Error setting logical size to renderer to " << parRes.x() << "x" << parRes.y() << ": " << SDL_GetError(); + throw std::runtime_error(oss.str()); + } + + const SDL_Rect area = { 0, 0, parRes.x(), parRes.y() }; + const int retValViewport = SDL_RenderSetViewport(renderer, &area); + if (retValViewport) { + std::ostringstream oss; + oss << "Error setting viewport to renderer to " << parRes.x() << "x" << parRes.y() << ": " << SDL_GetError(); + throw std::runtime_error(oss.str()); + } + } + + for (auto currNotifiable : m_localData->resChangeNotifList) { + currNotifiable->NotifyResChanged(m_localData->sizeratio); + } + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + size_t SDLMain::RegisterForResChange (SizeNotifiableBase* parNotif) { + parNotif->NotifyResChanged(m_localData->sizeratio); + return m_localData->resChangeNotifList.Add(parNotif); + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + void SDLMain::UnregisterForResChange (size_t parID) noexcept { + m_localData->resChangeNotifList.Remove(parID); + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + void SDLMain::SwapRegisteredForResChange (size_t parID, SizeNotifiableBase* parNotif) { + m_localData->resChangeNotifList.Update(parID, parNotif); + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + ushort2 SDLMain::WidthHeight() const noexcept { + return static_cast(m_localData->sizeratio.Resolution()); + } + + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + std::string SDLMain::GetVideoDriverName() const { + return std::string(SDL_GetCurrentVideoDriver()); + } +} //namespace cloonel diff --git a/src/sdlmain.hpp b/src/sdlmain.hpp new file mode 100644 index 0000000..dc05b8c --- /dev/null +++ b/src/sdlmain.hpp @@ -0,0 +1,60 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#ifndef id8E7A054DAC9040B887F2620EFD229EE8 +#define id8E7A054DAC9040B887F2620EFD229EE8 + +#include "vector.hpp" +#include +#include + +struct SDL_Renderer; + +namespace cloonel { + class SizeNotifiableBase; + + class SDLMain { + public: + SDLMain ( const char* parGameName, ushort2 parRes, ushort2 parReferenceRes ); + ~SDLMain ( void ) noexcept; + + void Init ( void ); + SDL_Renderer* GetRenderer ( void ); + ushort2 WidthHeight ( void ) const noexcept; + + void SetResolution ( ushort2 parRes ); + size_t RegisterForResChange ( SizeNotifiableBase* parNotif ); + void UnregisterForResChange ( size_t parID ) noexcept; + void SwapRegisteredForResChange ( size_t parID, SizeNotifiableBase* parNotif ); + const std::string& GetRendererName ( void ) const { return m_rendererName; } + std::string GetVideoDriverName ( void ) const; + + private: + struct LocalData; + + void InitSDL ( LocalData& parData ); + void ClearIFN ( LocalData& parData ) noexcept; + + const std::string m_gameName; + std::string m_rendererName; + std::unique_ptr m_localData; + }; +} //namespace cloonel + +#endif diff --git a/src/sizenotifiable.cpp b/src/sizenotifiable.cpp new file mode 100644 index 0000000..ac08df8 --- /dev/null +++ b/src/sizenotifiable.cpp @@ -0,0 +1,59 @@ +#include "sizenotifiable.hpp" +#include "sizeratio.hpp" +#include "sdlmain.hpp" +#include +#include + +namespace cloonel { + namespace implem { + } //namespace implem + + namespace regbehaviours { + ///---------------------------------------------------------------------- + ///---------------------------------------------------------------------- + void AutoRegister::Register (SizeNotifiableBase* parNotifiable) { + assert(m_sdlmain); +#if !defined(NDEBUG) + assert(not m_registered); + m_registered = true; +#endif + m_id = m_sdlmain->RegisterForResChange(parNotifiable); + } + + ///---------------------------------------------------------------------- + ///---------------------------------------------------------------------- + void AutoRegister::Unregister() noexcept { +#if !defined(NDEBUG) + assert(m_registered or not m_sdlmain); + m_registered = false; +#endif + if (m_sdlmain) { + m_sdlmain->UnregisterForResChange(m_id); + } + } + + ///---------------------------------------------------------------------- + ///---------------------------------------------------------------------- + AutoRegister::AutoRegister (AutoRegister&& parOther, SizeNotifiableBase* parSwapTo) : + m_sdlmain(nullptr), + m_id(0) +#if !defined(NDEBUG) + , m_registered(false) +#endif + { + std::swap(m_sdlmain, parOther.m_sdlmain); + std::swap(m_id, parOther.m_id); +#if !defined(NDEBUG) + std::swap(m_registered, parOther.m_registered); +#endif + assert(m_sdlmain); + m_sdlmain->SwapRegisteredForResChange(m_id, parSwapTo); + } + } //namespace regbehaviours + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + void SizeNotifiableBase::NotifyResChanged (const SizeRatio& parSize) { + m_scaleRatio = parSize.Ratio(); + } +} //namespace cloonel diff --git a/src/sizenotifiable.hpp b/src/sizenotifiable.hpp new file mode 100644 index 0000000..132cf34 --- /dev/null +++ b/src/sizenotifiable.hpp @@ -0,0 +1,128 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#ifndef id78906DE4FB0D43219CD3F0D9C620FC06 +#define id78906DE4FB0D43219CD3F0D9C620FC06 + +#include "vector.hpp" +#include +#include + +namespace cloonel { + class SizeRatio; + class SDLMain; + class SizeNotifiableBase; + + namespace regbehaviours { + class DontRegister { + public: + enum { SDLMAIN_NEEDED = false }; + + DontRegister ( void ) = default; + DontRegister ( DontRegister&&, SizeNotifiableBase* ) { } + ~DontRegister ( void ) noexcept = default; + + void Register ( SizeNotifiableBase* ) const noexcept { return; } + void Unregister ( void ) const noexcept { return; } + }; + + class AutoRegister { + public: + enum { SDLMAIN_NEEDED = true }; + + AutoRegister ( AutoRegister&& parOther, SizeNotifiableBase* parSwapTo ); + explicit AutoRegister ( SDLMain* parMain ) : + m_sdlmain(parMain) +#if !defined(NDEBUG) + , m_registered(false) +#endif + { + } + ~AutoRegister ( void ) noexcept = default; + + void Register ( SizeNotifiableBase* parNotifiable ); + void Unregister ( void ) noexcept; + + private: + SDLMain* m_sdlmain; + size_t m_id; +#if !defined(NDEBUG) + bool m_registered; +#endif + }; + } //namespace regbehaviours + + class SizeNotifiableBase { + protected: + SizeNotifiableBase ( void ) = default; + SizeNotifiableBase ( const SizeNotifiableBase& ) = default; + virtual ~SizeNotifiableBase ( void ) noexcept = default; + SizeNotifiableBase& operator= ( const SizeNotifiableBase& ) = delete; + + public: + virtual void NotifyResChanged ( const SizeRatio& parSize ); + const float2& Ratio ( void ) const noexcept { return m_scaleRatio; } + + private: + float2 m_scaleRatio; + }; + + template + class SizeNotifiable; + + template + class SizeNotifiable : private RegisterBehaviour, public SizeNotifiableBase { + static_assert(RegisterBehaviour::SDLMAIN_NEEDED == false, "SdlMainNeeded mismatches expected value"); + public: + SizeNotifiable ( const SizeNotifiable& ) = delete; + SizeNotifiable ( SizeNotifiable&& parOther ) : + RegisterBehaviour(std::move(parOther), this), + SizeNotifiableBase(parOther) + { + } + SizeNotifiable ( void ) { + this->Register(this); + } + virtual ~SizeNotifiable ( void ) noexcept { + this->Unregister(); + } + }; + + template + class SizeNotifiable : private RegisterBehaviour, public SizeNotifiableBase { + static_assert(RegisterBehaviour::SDLMAIN_NEEDED == true, "SdlMainNeeded mismatches expected value"); + public: + SizeNotifiable ( const SizeNotifiable& ) = delete; + SizeNotifiable ( SizeNotifiable&& parOther ) : + RegisterBehaviour(std::move(parOther), this), + SizeNotifiableBase(parOther) + { + } + explicit SizeNotifiable ( SDLMain* parSdlMain ) : + RegisterBehaviour(parSdlMain) + { + this->Register(this); + } + virtual ~SizeNotifiable ( void ) noexcept { + this->Unregister(); + } + }; +} //namespace cloonel + +#endif diff --git a/src/sizeratio.cpp b/src/sizeratio.cpp new file mode 100644 index 0000000..36a83ad --- /dev/null +++ b/src/sizeratio.cpp @@ -0,0 +1,47 @@ +#include "sizeratio.hpp" +#include "compatibility.h" + +namespace cloonel { + namespace { + float2 CalculateRatio ( float2 parOriginal, float2 parResolution ) a_pure; + + ///---------------------------------------------------------------------- + ///---------------------------------------------------------------------- + float2 CalculateRatio (float2 parOriginal, float2 parResolution) { + return parResolution / parOriginal; + } + } //unnamed namespace + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + SizeRatio::SizeRatio (const float2& parOriginal) : + m_original(parOriginal), + m_size(parOriginal), + m_ratio(1.0f) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + SizeRatio::SizeRatio (const float2& parOriginal, const float2& parSize) : + m_original(parOriginal), + m_size(parSize), + m_ratio(CalculateRatio(parOriginal, parSize)) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + void SizeRatio::SetOriginal (const float2& parOriginal, const float2& parRes) { + m_original = parOriginal; + m_size = parRes; + m_ratio = CalculateRatio(parOriginal, parRes); + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + void SizeRatio::UpdateResolution (const float2& parNewRes) { + m_size = parNewRes; + m_ratio = CalculateRatio(m_original, parNewRes); + } +} //namespace cloonel diff --git a/src/sizeratio.hpp b/src/sizeratio.hpp new file mode 100644 index 0000000..6e0cc4f --- /dev/null +++ b/src/sizeratio.hpp @@ -0,0 +1,45 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#ifndef id3098F08C14B84E3C8CE169CBA05C9C86 +#define id3098F08C14B84E3C8CE169CBA05C9C86 + +#include "vector.hpp" + +namespace cloonel { + class SizeRatio { + public: + SizeRatio ( void ) = default; + explicit SizeRatio ( const float2& parOriginal ); + SizeRatio ( const float2& parOriginal, const float2& parSize ); + ~SizeRatio ( void ) noexcept = default; + + const float2& Ratio ( void ) const noexcept { return m_ratio; } + const float2& Resolution ( void ) const noexcept { return m_size; } + void SetOriginal ( const float2& parOriginal, const float2& parRes ); + void UpdateResolution ( const float2& parNewRes ); + + private: + float2 m_original; + float2 m_size; + float2 m_ratio; + }; +} //namespace cloonel + +#endif diff --git a/src/vector.hpp b/src/vector.hpp new file mode 100644 index 0000000..3078b1b --- /dev/null +++ b/src/vector.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "vectorwrapper/vectorwrapper.hpp" +#include +#include + +namespace vwr { + template <> + struct VectorWrapperInfo> { + enum { + dimensions = 2 + }; + + typedef float scalar_type; + typedef std::array vector_type; + + static scalar_type& get_at (size_t parIndex, vector_type& parVector) { + return parVector[parIndex]; + } + }; + + template <> + struct VectorWrapperInfo> { + enum { + dimensions = 2 + }; + + typedef uint16_t scalar_type; + typedef std::array vector_type; + + static scalar_type& get_at (size_t parIndex, vector_type& parVector) { + return parVector[parIndex]; + } + }; +} //namespace vwr + +namespace curry { + using vec2f = vwr::Vec>; +} //namespace curry + +//make stuff from CloonelJump compile happily +namespace cloonel { + using ushort2 = vwr::Vec>; + using float2 = vwr::Vec>; +} //namespace cloonel