tree_test.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. //
  2. // Boost.Pointer Container
  3. //
  4. // Copyright Thorsten Ottosen 2003-2005. Use, modification and
  5. // distribution is subject to the Boost Software License, Version
  6. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // For more information, see http://www.boost.org/libs/ptr_container/
  10. //
  11. #include "test_data.hpp"
  12. #include <boost/ptr_container/ptr_vector.hpp>
  13. #include <boost/utility.hpp>
  14. #include <boost/lexical_cast.hpp>
  15. #include <algorithm>
  16. #include <iostream>
  17. #include <cstddef>
  18. #include <string>
  19. using namespace std;
  20. using namespace boost;
  21. class node;
  22. class tree
  23. {
  24. typedef ptr_vector<node> nodes_t;
  25. nodes_t nodes;
  26. protected:
  27. void swap( tree& r )
  28. { nodes.swap( r.nodes ); }
  29. public:
  30. typedef nodes_t::iterator iterator;
  31. typedef nodes_t::const_iterator const_iterator;
  32. public:
  33. void add_child( node* n );
  34. void remove( iterator n );
  35. void write_tree( ostream& os ) const;
  36. size_t size() const;
  37. node& child( size_t idx );
  38. const node& child( size_t idx ) const;
  39. iterator child_begin();
  40. const_iterator child_begin() const;
  41. iterator child_end();
  42. const_iterator child_end() const;
  43. iterator find( const string& match );
  44. };
  45. class node : noncopyable
  46. {
  47. virtual size_t do_node_size() const = 0;
  48. virtual string do_description() const = 0;
  49. virtual void do_write_value( ostream& os ) const = 0;
  50. public:
  51. virtual ~node() { }
  52. size_t node_size() const { return do_node_size(); }
  53. string description() const { return do_description(); }
  54. void write_value( ostream& os ) const { do_write_value( os ); }
  55. };
  56. class inner_node : public node, public tree
  57. {
  58. string name;
  59. virtual size_t do_node_size() const
  60. {
  61. return tree::size();
  62. }
  63. virtual string do_description() const
  64. {
  65. return lexical_cast<string>( name );
  66. }
  67. virtual void do_write_value( ostream& os ) const
  68. {
  69. os << " inner node: " << name;
  70. }
  71. void swap( inner_node& r )
  72. {
  73. name.swap( r.name );
  74. tree::swap( r );
  75. }
  76. public:
  77. inner_node() : name("inner node")
  78. { }
  79. inner_node( const string& r ) : name(r)
  80. { }
  81. inner_node* release()
  82. {
  83. inner_node* ptr( new inner_node );
  84. ptr->swap( *this );
  85. return ptr;
  86. }
  87. };
  88. template< class T >
  89. class leaf : public node
  90. {
  91. T data;
  92. virtual size_t do_node_size() const
  93. {
  94. return 1;
  95. }
  96. virtual string do_description() const
  97. {
  98. return lexical_cast<string>( data );
  99. }
  100. virtual void do_write_value( ostream& os ) const
  101. {
  102. os << " leaf: " << data;
  103. }
  104. public:
  105. leaf() : data( T() )
  106. { }
  107. leaf( const T& r ) : data(r)
  108. { }
  109. void set_data( const T& r )
  110. { data = r; }
  111. };
  112. /////////////////////////////////////////////////////////////////////////
  113. // tree implementation
  114. /////////////////////////////////////////////////////////////////////////
  115. inline void tree::add_child( node* n )
  116. {
  117. nodes.push_back( n );
  118. }
  119. inline void tree::remove( iterator n )
  120. {
  121. BOOST_ASSERT( n != nodes.end() );
  122. nodes.erase( n );
  123. }
  124. void tree::write_tree( ostream& os ) const
  125. {
  126. for( const_iterator i = nodes.begin(),
  127. e = nodes.end();
  128. i != e; ++i )
  129. {
  130. i->write_value( os );
  131. if( const inner_node* p = dynamic_cast<const inner_node*>( &*i ) )
  132. p->write_tree( os );
  133. }
  134. }
  135. size_t tree::size() const
  136. {
  137. size_t res = 1;
  138. for( const_iterator i = nodes.begin(),
  139. e = nodes.end();
  140. i != e; ++i )
  141. {
  142. res += i->node_size();
  143. }
  144. return res;
  145. }
  146. inline node& tree::child( size_t idx )
  147. {
  148. return nodes[idx];
  149. }
  150. inline const node& tree::child( size_t idx ) const
  151. {
  152. return nodes[idx];
  153. }
  154. inline tree::iterator tree::child_begin()
  155. {
  156. return nodes.begin();
  157. }
  158. inline tree::const_iterator tree::child_begin() const
  159. {
  160. return nodes.begin();
  161. }
  162. inline tree::iterator tree::child_end()
  163. {
  164. return nodes.end();
  165. }
  166. inline tree::const_iterator tree::child_end() const
  167. {
  168. return nodes.end();
  169. }
  170. tree::iterator tree::find( const string& match )
  171. {
  172. for( iterator i = nodes.begin(),
  173. e = nodes.end();
  174. i != e; ++i )
  175. {
  176. if( i->description() == match )
  177. return i;
  178. if( inner_node* p = dynamic_cast<inner_node*>( &*i ) )
  179. {
  180. iterator j = p->find( match );
  181. if( j != p->child_end() )
  182. return j;
  183. }
  184. }
  185. return child_end();
  186. }
  187. /////////////////////////////////////////////////////////////////////////
  188. // test case
  189. /////////////////////////////////////////////////////////////////////////
  190. void test_tree()
  191. {
  192. tree root;
  193. BOOST_CHECK_EQUAL( root.size(), 1u );
  194. inner_node node1( "node 1" );
  195. node1.add_child( new leaf<string>( "leaf 1" ) );
  196. node1.add_child( new leaf<int>( 42 ) );
  197. inner_node node2( "node 2" );
  198. node2.add_child( new leaf<float>( 42.0f ) );
  199. node2.add_child( new leaf<string>( "leaf 4" ) );
  200. root.add_child( node1.release() );
  201. BOOST_CHECK_EQUAL( root.size(), 4u );
  202. root.add_child( node2.release() );
  203. root.add_child( new inner_node( "node 3" ) );
  204. BOOST_CHECK_EQUAL( root.size(), 8u );
  205. root.add_child( new leaf<string>( "leaf 5" ) );
  206. BOOST_CHECK_EQUAL( root.size(), 9u );
  207. root.write_tree( cout );
  208. tree::iterator a_leaf = root.find( "42" );
  209. BOOST_CHECK_EQUAL( a_leaf->description(), "42" );
  210. leaf<int>& the_leaf = dynamic_cast< leaf<int>& >( *a_leaf );
  211. the_leaf.set_data( 2*42 );
  212. BOOST_CHECK_EQUAL( a_leaf->description(), "84" );
  213. }
  214. #include <boost/test/unit_test.hpp>
  215. using boost::unit_test::test_suite;
  216. test_suite* init_unit_test_suite( int argc, char* argv[] )
  217. {
  218. test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" );
  219. test->add( BOOST_TEST_CASE( &test_tree ) );
  220. return test;
  221. }