libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/tree.hpp
Go to the documentation of this file.
00001 
00012 /*
00013  *  Copyright (C) 2008, 2009 Juan Pedro BolĂ­var Puente
00014  *  
00015  *  This program is free software: you can redistribute it and/or modify
00016  *  it under the terms of the GNU General Public License as published by
00017  *  the Free Software Foundation, either version 3 of the License, or
00018  *  (at your option) any later version.
00019  *
00020  *  This program is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *  GNU General Public License for more details.
00024  *
00025  *  You should have received a copy of the GNU General Public License
00026  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00027  *
00028  */
00029 
00030 #ifndef PSYNTH_TREE_H
00031 #define PSYNTH_TREE_H
00032 
00033 #include <map>
00034 #include <unordered_map>
00035 #include <typeinfo>
00036 
00037 #include <psynth/base/iterator.hpp>
00038 #include <psynth/base/pointer.hpp>
00039 #include <psynth/base/exception.hpp>
00040 #include <psynth/base/threads.hpp>
00041 
00042 namespace psynth
00043 {
00044 namespace base
00045 {
00046 
00051 template <typename Key>
00052 struct tree_node_traits
00053 {
00055     typedef typename Key::value_type value_type;
00056 
00058     static const value_type separator = value_type ();
00059 };
00060 
00061 template <>
00062 struct tree_node_traits<std::string>
00063 {
00064     typedef char value_type;
00065     static const char separator = '.';
00066 };
00067 
00071 PSYNTH_DECLARE_ERROR(error, tree_node_error);
00072 
00097 template <class Node,
00098           class Key = std::string,
00099           class Traits = tree_node_traits<Key>,
00100           class ThreadingPolicy = PSYNTH_DEFAULT_THREADING <Node> >
00101 class tree_node
00102 {   
00103 public:
00107     typedef std::unique_ptr<Node> node_ptr;
00108     
00112     typedef ptr_iterator<map_iterator<Key, node_ptr > > iterator;
00113 
00117     typedef ptr_const_iterator<map_const_iterator<Key, std::unique_ptr<Node> > >
00118     const_iterator;
00119 
00123     typedef Traits traits;
00124     
00126     tree_node () :
00127         _parent(NULL), _isinit(false)
00128     {
00129     };
00130 
00132     ~tree_node ();
00133 
00138     iterator begin ()
00139     {
00140         return _childs.begin();
00141     }
00142 
00147     const_iterator begin () const
00148     {
00149         return _childs.begin ();
00150     }
00151     
00156     iterator end ()
00157     {
00158         return _childs.end ();
00159     }
00160 
00165     const_iterator end () const
00166     {
00167         return _childs.end ();
00168     }
00169     
00174     const Node* parent () const
00175     {
00176         tree_lock lock (this);
00177         return _parent;
00178     }
00179 
00184     Node* parent ()
00185     {
00186         tree_lock lock (this);
00187         return _parent;
00188     }
00189     
00193     const Key& name () const
00194     {
00195         tree_lock lock (this);
00196         return _name;
00197     }
00198    
00203     iterator find_child (const Key& name)
00204     {
00205         tree_lock lock (this);
00206         return _childs.find (name);
00207     }
00208  
00213     const_iterator find_child (const Key& name) const
00214     {
00215         tree_lock lock (this);
00216         return _childs.find (name);
00217     }
00218 
00226     node_ptr detach (const Key& name)
00227     {
00228         tree_lock lock (this);
00229         return detach (_childs.find (name));
00230     }
00231 
00236     iterator remove_child (const Key& name)
00237     {
00238         tree_lock lock (this);
00239         return remove_child (_childs.find (name));
00240     }
00241 
00249     bool attach (const Key& name, node_ptr node);
00250     
00259     node_ptr detach (iterator iter);
00260     
00264     Key path_name () const;
00265     
00271     iterator remove_child (iterator iter);
00272 
00276     void clear_childs ();
00277     
00283     Node& child (const Key& name);
00284 
00290     Node& existing_child (const Key& name);
00291 
00292 
00298     const Node& existing_child (const Key& name) const;
00299     
00304     Node& path (const Key& name);
00305     
00311     Node& existing_path (const Key& name);
00312 
00318     const Node& existing_path (const Key& name) const;
00319 
00320 protected:    
00321     virtual void on_new_child (Node& node) {}
00322     virtual void on_remove_child (Node& node) {}
00323     virtual void on_init () {}
00324     virtual void on_uninit () {}
00325     
00326 private:
00327     typedef std::map<Key, std::unique_ptr<Node>> child_map;
00328 
00329     child_map   _childs;
00330     Node*       _parent;
00331     Key         _name;
00332     bool        _isinit;
00333 
00334     template <typename InputIterator>
00335     static void find_base (InputIterator& base_b, InputIterator& base_e);
00336 
00337     const Node&
00338     existing_path (typename Key::const_iterator begin,
00339                        typename Key::const_iterator end) const;
00340 
00341     Node&
00342     existing_path (typename Key::const_iterator begin,
00343                        typename Key::const_iterator end);
00344 
00345     Node& path (typename Key::const_iterator begin,
00346                     typename Key::const_iterator end);
00347     
00348     void path_name (Key& prefix) const;
00349 
00350     bool is_init() const
00351     {
00352         return _isinit;
00353     }
00354 
00355     void init (const Key& name, Node* parent)
00356     {
00357         _isinit = true;
00358         _name = name;
00359         _parent = parent;
00360         on_init ();
00361     }
00362 
00363     void uninit ()
00364     {
00365         if (_isinit) {
00366             _isinit = false;
00367             _name = Key ();
00368             _parent = 0;
00369             on_uninit ();
00370         }
00371     }
00372 
00373     struct tree_lock : public ThreadingPolicy::lock
00374     {
00375         tree_lock (const tree_node* self)
00376             : ThreadingPolicy::lock (dynamic_cast<const Node*> (self))
00377         {}
00378     };
00379 };
00380 
00381 } /* namespace base */
00382 } /* namespace psynth */
00383 
00384 #endif /* PSYNTH_TREE_H  */