Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/gen/ntree.h

Go to the documentation of this file.
00001 //  Copyright (C) 2002  Petter Urkedal
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: ntree.h,v 1.3 2002/08/24 13:58:38 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_GEN_NTREE_H
00031 #define MORE_GEN_NTREE_H
00032 
00033 #include <more/gen/memory.h>
00034 #include <list>
00035 
00036 
00037 namespace more {
00038 namespace gen {
00039 
00040   /** \class ntree ntree.h more/gen/ntree.h
00041    ** An general tree.  This is a alternative to the nary_tree, and
00042    ** this should work better with mutating algorithms. */
00043   template< typename T,
00044             template<typename X, typename A>
00045                 class BranchContainer = std::list,
00046             typename Allocator = gen::allocator<T> >
00047   struct ntree
00048   {
00049       typedef Allocator allocator_type;
00050       typedef typename allocator_type::value_type value_type;
00051       typedef typename allocator_type::reference reference;
00052       typedef typename allocator_type::const_reference const_reference;
00053       typedef typename allocator_type::pointer pointer;
00054       typedef typename allocator_type::size_type size_type;
00055 
00056     private:
00057       typedef typename allocator_type::rebind<ntree>::other
00058               ntree_allocator_type;
00059       typedef BranchContainer<ntree, ntree_allocator_type> internal_branch_cont;
00060     public:
00061 
00062     private:
00063       class swapper;
00064 
00065       struct node
00066       {
00067           typedef typename internal_branch_cont::iterator
00068                   iterator;
00069           typedef typename internal_branch_cont::const_iterator
00070                   const_iterator;
00071 
00072         public:
00073           node()
00074               : m_stem_node(0) {}
00075 
00076         private:
00077           explicit node(node* stem)
00078               : m_stem_node(stem) {}
00079 
00080           node(node* stem, value_type const& x)
00081               : m_stem_node(stem),
00082                 m_value(x) {}
00083 
00084         public:
00085           node(node const& x)
00086               : m_branches(x.m_branches),
00087                 m_stem_node(0),
00088                 m_value(x.m_value)
00089           {
00090               for (iterator it = m_branches.begin();
00091                    it != m_branches.end(); ++it)
00092                   it->m_node->m_stem_node = this;
00093           }
00094 
00095         public:
00096           iterator begin() { return m_branches.begin(); }
00097           iterator end() { return m_branches.end(); }
00098 
00099           const_iterator begin() const
00100           { return m_branches.begin(); }
00101 
00102           const_iterator end() const
00103           { return m_branches.end(); }
00104 
00105           bool empty() const { return m_branches.empty(); }
00106 
00107           iterator
00108           insert(iterator it, const_reference x)
00109           {
00110               ntree t(x);
00111               iterator it_ins = m_branches.insert(it, t);
00112               it_ins->m_stem_node = this;
00113               return it_ins;
00114           }
00115 
00116           iterator
00117           erase(iterator it)
00118           {
00119               return m_branches.erase(it);
00120           }
00121 
00122           iterator
00123           erase(iterator it, iterator it_end)
00124           {
00125               return m_branches.erase(it);
00126           }
00127 
00128           void
00129           clear()
00130           {
00131               m_branches.clear();
00132           }
00133 
00134           void
00135           push_front(const_reference x)
00136           {
00137               ntree t(x);
00138               m_branches.push_front(t);
00139               m_branches.front().m_node->m_stem_node = this;
00140           }
00141 
00142           void
00143           push_back(const_reference x)
00144           {
00145               ntree t(x);
00146               m_branches.push_back(t);
00147               m_branches.back().m_node->m_stem_node = this;
00148           }
00149 
00150           ntree& front() { return m_branches.front(); }
00151           ntree& back() { return m_branches.back(); }
00152 
00153         private:
00154           internal_branch_cont m_branches;
00155           node* m_stem_node;
00156           value_type m_value;
00157           ntree* m_owner;  // handled by ntree
00158 
00159           friend class ntree;
00160           friend class swapper;
00161       };
00162 
00163       typedef typename allocator_type::rebind<node>::other
00164               node_allocator_type;
00165 
00166     public:
00167       typedef node branch_container;
00168       typedef typename branch_container::iterator branch_iterator;
00169       typedef typename branch_container::const_iterator branch_const_iterator;
00170 
00171       /** Construct a tree with a default constructed root node
00172        ** only. */
00173       ntree()
00174           : m_node(s_alloc.allocate(1))
00175       {
00176           s_alloc.construct(m_node);
00177           m_node->m_owner = this;
00178       }
00179 
00180       /** Construct a tree with only a root node of value \a x. */
00181       explicit ntree(const_reference x)
00182           : m_node(s_alloc.allocate(1))
00183       {
00184           s_alloc.construct(m_node);
00185           m_node->m_value = x;
00186           m_node->m_owner = this;
00187       }
00188 
00189       /** Construct a deep copy of \a t. */
00190       ntree(ntree const& t)
00191           : m_node(s_alloc.allocate(1))
00192       {
00193           s_alloc.construct(m_node, *t.m_node);
00194           m_node->m_owner = this;
00195       }
00196 
00197       /** Assign a deep copy of \a t. */
00198       ntree& operator=(ntree const& t)
00199       {
00200           s_alloc.destroy(m_node);
00201           s_alloc.construct(m_node, *t.m_node);
00202           m_node->m_owner = this;
00203           return *this;
00204       }
00205 
00206       /** Destruct. */
00207       ~ntree()
00208       {
00209           s_alloc.destroy(m_node);
00210           s_alloc.deallocate(m_node, 1);
00211       }
00212 
00213       /** A class which can be used to move all nodes of a tree to
00214        ** another tree without copying.  This class can be used as a
00215        ** return type in place of \c ntree itself to avoid redundant
00216        ** copying.  */
00217       struct swapper
00218       {
00219           swapper()
00220               : m_node(s_alloc.allocate(1))
00221           {
00222               s_alloc.construct(m_node);
00223               m_node->m_owner = 0;
00224           }
00225 
00226           /** Take the nodes of \a t and replace them with none. */
00227           swapper(ntree& t)
00228               : m_node(s_alloc.allocate(1))
00229           {
00230               s_alloc.construct(m_node);
00231               m_node->m_owner = &t;
00232               std::swap(m_node, t.m_node);
00233               m_node->m_owner = 0;
00234           }
00235 
00236           /** Swap the nodes with those of \a t. */
00237           swapper& operator=(swapper& t)
00238           {
00239               m_node->m_owner = &t;
00240               std::swap(m_node, t.m_node);
00241               m_node->m_owner = 0;
00242               return *this;
00243           }
00244 
00245           /** Destroy the nodes. */
00246           ~swapper()
00247           {
00248               s_alloc.destroy(m_node);
00249           }
00250 
00251           friend class ntree;
00252 
00253         private:
00254           mutable node* m_node;
00255       };
00256 
00257       /** Take the nodes of \a sw and replace them with none. */
00258       ntree(swapper const& sw)
00259           : m_node(s_alloc.allocate(1))
00260       {
00261           s_alloc.construct(m_node);
00262           m_node->m_owner = 0;
00263           std::swap(m_node, sw.m_node);
00264           m_node->m_owner = this;
00265       }
00266 
00267       /** Swap nodes with \a sw. */
00268       ntree& operator=(swapper const& sw)
00269       {
00270           m_node->m_owner = 0;
00271           std::swap(m_node, sw.m_node);
00272           m_node->m_owner = this;
00273           return *this;
00274       }
00275 
00276       /** Return true if this tree's top node is the root of the whole
00277        ** tree. */
00278       bool is_root() const { return m_node->m_stem_node == 0; }
00279 
00280       /** Return the tree of which this is a subtree.
00281        ** \pre The top node is not the root. */
00282       ntree& stem()
00283       {
00284 #  ifndef MORE_NDEBUG
00285           if (is_root())
00286               throw std::logic_error("more::gen::ntree: "
00287                                      "Requested stem of the root.");
00288 #  endif
00289           return *m_node->m_stem_node->m_owner;
00290       }
00291 
00292       /** Return the tree of which this is a subtree.
00293        ** \pre The top node is not the root. */
00294       ntree const& stem() const
00295       {
00296 #  ifndef MORE_NDEBUG
00297           if (is_root())
00298               throw std::logic_error("more::gen::ntree: "
00299                                      "Requested stem of the root.");
00300 #  endif
00301           return *m_node->m_stem_node->m_owner;
00302       }
00303 
00304       /** Return a container of the immediate branches.  The container
00305        ** has \c begin() and \c end() methods.  */
00306       branch_container const& branches() const { return *m_node; }
00307       /** Return a container of the immediate branches.  The container
00308        ** has \c begin() and \c end() methods. */
00309       branch_container& branches() { return *m_node; }
00310 
00311       /** Return the value of the topmost node. */
00312       reference value() { return m_node->m_value; }
00313       /** Return the value of the topmost node. */
00314       const_reference value() const { return m_node->m_value; }
00315 
00316       /** Return the result of a deep comparison with \c rhs. */
00317       bool operator==(ntree const& rhs) const
00318       {
00319           return m_node->m_value == rhs.m_node->m_value
00320               && m_node->m_branches == m_node->m_branches;
00321       }
00322 
00323       /** Clear all branches and set the root value to a default
00324        ** constructed instance of \c value_type. */
00325       void clear()
00326       {
00327           m_node->m_branches.clear();
00328           m_node->m_value = value_type();
00329       }
00330 
00331     private:
00332       node* m_node;
00333 
00334       static node_allocator_type s_alloc;
00335   };
00336 
00337   template< typename T,
00338             template<typename X, typename A>
00339                 class BranchContainer = std::list,
00340             typename Allocator = gen::allocator<T> >
00341   typename ntree<T, BranchContainer, Allocator>::node_allocator_type
00342       ntree<T, BranchContainer, Allocator>::s_alloc;
00343 
00344 
00345 }}
00346 
00347 #endif

Generated on Sat Sep 7 19:11:13 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.