Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

node_tree.hpp

Go to the documentation of this file.
00001 #ifndef s11n_util_NODE_UTIL_HPP_INCLUDED
00002 #define s11n_util_NODE_UTIL_HPP_INCLUDED 1
00003 
00004 #include <map>
00005 #include <list>
00006 #include <s11n.net/s11n/traits.hpp>
00007 
00008 namespace s11n {
00009 
00010 /**
00011    The s11n::util namespace encapsulates some utility code
00012    for client-side use alongside the s11n framework.
00013 */
00014 namespace util {
00015 
00016         /**
00017            100% experimental. node_tree provides an interface for
00018            manipulating child/parent relationships in a tree of data
00019            nodes.
00020 
00021            NodeT must usable via s11n::node_traits&lt;NodeT&gt;.
00022         */
00023         template <typename NodeT>
00024         class node_tree
00025         {
00026         public:
00027                 typedef NodeT node_type;
00028                 typedef ::s11n::node_traits< node_type > traits_type;
00029 
00030                 /**
00031                    Ownership of node does not change, and root should
00032                    outlive this object, or at least live until
00033                    clime_tree() is called with another root.
00034 
00035                    root may be 0.
00036                 */
00037                 explicit node_tree( node_type * root ) : m_root(root), m_count(0)
00038                 {
00039                         this->climb_tree( root );
00040                 }
00041 
00042                 node_tree() : m_root(0), m_count(0)
00043                 {}
00044 
00045                 ~node_tree() {}
00046 
00047 
00048                 typedef typename traits_type::child_list_type list_type;
00049 
00050 
00051                 /**
00052                    Maps relations of parens to children in node tree,
00053                    using the given root node. Returns the cumulative
00054                    number of nodes traversed.
00055 
00056                    Ownership of node does not change, so node must
00057                    outlive this object or, if it is destroyed first,
00058                    climb_tree() must be called with another node
00059                    before any other API of this class is called.
00060 
00061                    If node == 0 then this object's data is cleared and
00062                    0 is returned.
00063 
00064                    The second parameter is for internal use: never
00065                    pass a value, or pass 0 if you must pass something.
00066                  */
00067                 size_t climb_tree( node_type * node, size_t internal_use = 0 )
00068                 {
00069                         if( 0 == internal_use ) // first iteration: clear state
00070                         {
00071                                 this->m_count = 0;
00072                                 this->m_root = node;
00073                                 this->m_rmap.clear();
00074                                 if( node ) this->m_rmap[node] = 0;
00075                         }
00076                         if( ! node ) return 0;
00077 
00078                         ++this->m_count;
00079                         list_type & chlist = traits_type::children(*node);
00080                         typename list_type::iterator it = chlist.begin(),
00081                                 et = chlist.end();
00082                         for( ; et != it; ++it )
00083                         {
00084                                 this->m_rmap[(*it)] = node;
00085                                 this->climb_tree( (*it), 1 + internal_use );
00086                         }
00087                         return this->m_count;
00088                 }
00089 
00090                 /**
00091                    Returns the parent node of node, of 0 if no parent
00092                    was mapped by climb_tree().
00093 
00094                    The caller does not own the pointer: it is owned by
00095                    it's own parent. If it has no parent, then "someone
00096                    else" is assumed to have ownership of it (whoever
00097                    gave it to this object, presumably).
00098                 */
00099                 node_type * parent_of( node_type & node )
00100                 {
00101                         typename reverse_map_type::iterator it = this->m_rmap.find( &node );
00102                         if( it == this->m_rmap.end() ) return 0;
00103                         return (*it).second;
00104                 }
00105 
00106                 /**
00107                    A convenience wrapper around
00108                    traits_type::children(node).
00109                 */
00110                 list_type & children_of( node_type & node )
00111                 {
00112                         return traits_type::children(node);
00113                 }
00114 
00115                 /**
00116                    Removes the given node from the tree. If it returns true,
00117                    the caller owns node, otherwise ownership is unchanged.
00118 
00119                 */
00120                 bool take_node( node_type * node )
00121                 {
00122                         typename reverse_map_type::iterator rit = this->m_rmap.find( node );
00123                         if( rit == this->m_rmap.end() ) return false;
00124                         node_type * p = (*rit).second;
00125                         if( p )
00126                         {
00127                                 // take node from parent's list...
00128                                 typename list_type::iterator it = traits_type::children(*p).begin(),
00129                                         et = traits_type::children(*p).end();
00130                                 for( ; et != it; ++it )
00131                                 {
00132                                         if( (*it) == node )
00133                                         {
00134                                                 traits_type::children(*p).erase( it );
00135                                                 break;
00136                                         }
00137                                 }
00138                         }
00139 
00140                         this->m_rmap.erase(rit);
00141                         if( node == this->root() )
00142                         {
00143                                 this->m_root = 0;
00144                         }
00145                         return true;
00146                 }
00147 
00148 
00149                 /**
00150                    Reparents node n to parent node newp.
00151 
00152                    Both n and newp are assumed to be under root().
00153 
00154                    n may not be root() and neither n nor newp may be
00155                    0.
00156 
00157                    Returns true on success, false on error.
00158 
00159                    If this function returns false then ownership is
00160                    unchanged and there are no side effects. If it
00161                    returns true, ownership of n *typically* moves to
00162                    newp. That is, newp will delete n when newp is
00163                    destroyed. More specifically, that depends on
00164                    node_type's implementation, but s11n::data_node and
00165                    s11n::s11n_node both work that way.
00166                 */
00167                 bool reparent( node_type * n, node_type * newp )
00168                 {
00169                         if( (!n) || (!newp) || (!this->root()) || (this->root() == n) )
00170                         {
00171                                 return false;
00172                         }
00173                         if( ! this->take_child( n ) )
00174                         {
00175                                 return false;
00176                         }
00177                         traits_type::children(*newp).push_back( n );
00178                         this->m_rmap[n] = newp;
00179                         traits_type::children(*newp).push_back( n );
00180                         return true;
00181                 }
00182 
00183                 /**
00184                    Returns this object's root node. Ownership is not
00185                    changed.
00186                 */
00187                 node_type * root() { return this->m_root; }
00188 
00189                 /**
00190                    Clears this object's data and sets it's root() node
00191                    to 0. This object does not own root() and therefor
00192                    does not delete it.
00193                 */
00194                 void clear()
00195                 {
00196                         this->m_rmap.clear();
00197                         this->m_root = 0;
00198                 }
00199 
00200         private:
00201                 typedef std::map< node_type *, node_type * > reverse_map_type; // children to parens
00202                 reverse_map_type m_rmap;
00203                 node_type * m_root;
00204                 size_t m_count;
00205         };
00206 
00207 } } // namespace util
00208 
00209 
00210 #endif // s11n_util_NODE_UTIL_HPP_INCLUDED

Generated on Fri Nov 25 17:19:29 2005 for libs11n-1.2.0 by  doxygen 1.4.4