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

Generated on Sun Dec 18 18:38:03 2005 for libs11n-1.2.2 by  doxygen 1.4.4