00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00041
00042
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;
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
00172
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
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
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
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
00207 ~ntree()
00208 {
00209 s_alloc.destroy(m_node);
00210 s_alloc.deallocate(m_node, 1);
00211 }
00212
00213
00214
00215
00216
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
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
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
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
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
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
00277
00278 bool is_root() const { return m_node->m_stem_node == 0; }
00279
00280
00281
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
00293
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
00305
00306 branch_container const& branches() const { return *m_node; }
00307
00308
00309 branch_container& branches() { return *m_node; }
00310
00311
00312 reference value() { return m_node->m_value; }
00313
00314 const_reference value() const { return m_node->m_value; }
00315
00316
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
00324
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