diff options
-rw-r--r-- | include/gras/element.hpp | 31 | ||||
-rw-r--r-- | include/gras/hier_block.hpp | 9 | ||||
-rw-r--r-- | lib/block_props.cpp | 47 | ||||
-rw-r--r-- | lib/element.cpp | 57 | ||||
-rw-r--r-- | lib/element_impl.hpp | 6 | ||||
-rw-r--r-- | lib/hier_block.cpp | 15 | ||||
-rw-r--r-- | tests/block_props_test.py | 33 |
7 files changed, 119 insertions, 79 deletions
diff --git a/include/gras/element.hpp b/include/gras/element.hpp index 3211ac3..13ebb7c 100644 --- a/include/gras/element.hpp +++ b/include/gras/element.hpp @@ -19,6 +19,8 @@ struct ElementImpl; typedef boost::shared_ptr<ElementImpl> ElementBase; +struct Block; + struct GRAS_API Element : ElementBase, boost::enable_shared_from_this<Element> { @@ -42,6 +44,35 @@ struct GRAS_API Element : ElementBase, boost::enable_shared_from_this<Element> std::string to_string(void) const; /******************************************************************* + * element tree interface + ******************************************************************/ + + /*! + * Adopt an element as a child under the given name. + * + * This API allows the user to structure a hierarchy of elements. + * This element will become the parent of the child element. + * + * \param name the name of the child node + * \param child an element to be adopted + */ + void adopt_element(const std::string &name, const Element &child); + + /*! + * Lookup a block in the element tree hierarchy. + * + * Paths are unix style, absolte and relatives paths are possible. + * This call throws an invalid argument when bad paths are given. + * + * Example path: /my_hier_block/my_block0 + * Example path: ../my_block1 + * + * \param path a path to a block (leaf) in the tree + * \return a pointer to the block + */ + Block *lookup_block(const std::string &path); + + /******************************************************************* * Compatibility for dealing with shared ptrs of Elements ******************************************************************/ /*! diff --git a/include/gras/hier_block.hpp b/include/gras/hier_block.hpp index 25c1424..398024e 100644 --- a/include/gras/hier_block.hpp +++ b/include/gras/hier_block.hpp @@ -44,15 +44,6 @@ struct GRAS_API HierBlock : Element */ virtual void commit(void); - /******************************************************************* - * property tree interface - ******************************************************************/ - - /*! - * Register a subelement's properties into this element. - */ - void register_subelement(const std::string &node, const Element &subelem); - }; } //namespace gras diff --git a/lib/block_props.cpp b/lib/block_props.cpp index ab8b642..672200b 100644 --- a/lib/block_props.cpp +++ b/lib/block_props.cpp @@ -2,8 +2,6 @@ #include "element_impl.hpp" #include <gras/block.hpp> -#include <boost/foreach.hpp> -#include <boost/algorithm/string.hpp> using namespace gras; @@ -76,51 +74,8 @@ struct PropAccessReceiver : Theron::Receiver * Handle the get and set calls from the user's call-stack **********************************************************************/ template <typename ActorType> -static PMCC prop_access_dispatcher(ActorType &actor, const std::string &path, const PMCC &value, const bool set) +static PMCC prop_access_dispatcher(ActorType &actor, const std::string &key, const PMCC &value, const bool set) { - //split the paths into nodes - std::vector<std::string> nodes; - boost::split(nodes, path, boost::is_any_of("/")); - - //iterate through the path to find the element - std::string key; - Element elem = *(actor->block_ptr); - size_t i = 0; - BOOST_FOREACH(const std::string &node, nodes) - { - i++; - if (node == "" and i == 1) //find root - { - while (elem->_parent) elem = elem->_parent; - continue; - } - if (node == ".") //this dir - { - continue; - } - if (node == "..") //up a dir - { - if (not elem->_parent) throw std::runtime_error( - "Property tree lookup fail - null parent: " + path - ); - elem = elem->_parent; - continue; - } - if (i == nodes.size() or elem->block) //leaf - { - key = node; - if (i != nodes.size() or not elem->block) throw std::runtime_error( - "Property tree lookup fail - beyond leaf: " + path - ); - continue; - } - if (elem->_subelems.count(node) == 0) throw std::runtime_error( - "Property tree lookup fail - no such path: " + path - ); - elem = elem->_subelems[node]; - } - - //now send a message to the actor to perform the action PropAccessReceiver receiver; PropAccessMessage message; message.set = set; diff --git a/lib/element.cpp b/lib/element.cpp index 368dbea..e6c8499 100644 --- a/lib/element.cpp +++ b/lib/element.cpp @@ -4,6 +4,8 @@ #include <gras/element.hpp> #include <boost/format.hpp> #include <boost/detail/atomic_count.hpp> +#include <boost/foreach.hpp> +#include <boost/algorithm/string.hpp> static boost::detail::atomic_count unique_id_pool(0); @@ -45,3 +47,58 @@ std::string Element::to_string(void) const { return (*this)->id; } + +void Element::adopt_element(const std::string &name, const Element &child) +{ + if (child->parent) throw std::invalid_argument(str(boost::format( + "Could not register child %s into %s.\n" + "The child %s already has parent %s.\n" + ) + % child.to_string() + % this->to_string() + % child.to_string() + % child->parent.to_string() + )); + //TODO check name not already taken + child->parent = *this; + (*this)->children[name] = child; +} + +Block *Element::lookup_block(const std::string &path) +{ + //split the paths into nodes + std::vector<std::string> nodes; + boost::split(nodes, path, boost::is_any_of("/")); + + //iterate through the path to find the element + boost::shared_ptr<ElementImpl> elem = *this; + size_t i = 0; + BOOST_FOREACH(const std::string &node, nodes) + { + i++; + if (node == "" and i == 1) //find root + { + while (elem->parent) elem = elem->parent; + continue; + } + if (node == ".") //this dir + { + continue; + } + if (node == "..") //up a dir + { + if (not elem->parent) throw std::invalid_argument( + "Element tree lookup fail - null parent: " + path + ); + elem = elem->parent; + continue; + } + if (elem->children.count(node) == 0) throw std::invalid_argument( + "Element tree lookup fail - no such path: " + path + ); + elem = elem->children[node]; + } + + //return block ptr as result + return elem->block->block_ptr; +} diff --git a/lib/element_impl.hpp b/lib/element_impl.hpp index ccdbb54..869006e 100644 --- a/lib/element_impl.hpp +++ b/lib/element_impl.hpp @@ -35,9 +35,9 @@ struct ElementImpl Token token; GlobalBlockConfig top_config; - //hier block stuff - Element _parent; - std::map<std::string, Element> _subelems; + //element tree stuff + Element parent; + std::map<std::string, Element> children; //things may be in this element boost::shared_ptr<Apology::Topology> topology; diff --git a/lib/hier_block.cpp b/lib/hier_block.cpp index cfaca86..b7ffe4c 100644 --- a/lib/hier_block.cpp +++ b/lib/hier_block.cpp @@ -76,18 +76,3 @@ void HierBlock::commit(void) { (*this)->topology->commit(); } - -void HierBlock::register_subelement(const std::string &node, const Element &subelem) -{ - if (subelem->_parent) throw std::runtime_error(str(boost::format( - "Could not register subelement %s into %s.\n" - "The subelement %s already has parent %s.\n" - ) - % subelem.to_string() - % this->to_string() - % subelem.to_string() - % subelem->_parent.to_string() - )); - subelem->_parent = *this; - (*this)->_subelems[node] = subelem; -} diff --git a/tests/block_props_test.py b/tests/block_props_test.py index ccc6dd2..b392693 100644 --- a/tests/block_props_test.py +++ b/tests/block_props_test.py @@ -47,19 +47,40 @@ class BlockPropsTest(unittest.TestCase): except: threw = True self.assertTrue(threw) - def test_property_tree_paths(self): + def test_element_tree_paths(self): my_block = MyBlock() tb = gras.TopBlock() hb = gras.HierBlock() - tb.register_subelement("my_hier", hb) - hb.register_subelement("my_block", my_block) + tb.adopt_element("my_hier", hb) + hb.adopt_element("my_block", my_block) my_block.set("foo", 42) - self.assertEqual(my_block.get("foo"), 42) - self.assertEqual(my_block.get("./../my_block/foo"), 42) - self.assertEqual(my_block.get("/my_hier/my_block/foo"), 42) + + my_block0 = tb.lookup_block('/my_hier/my_block') + self.assertEqual(my_block0.get("foo"), 42) + + my_block1 = hb.lookup_block('my_block') + self.assertEqual(my_block1.get("foo"), 42) + + my_block2 = hb.lookup_block('./../my_hier/my_block') + self.assertEqual(my_block2.get("foo"), 42) + + threw = False + try: hb.lookup_block('../../my_hier/my_block') + except: threw = True + self.assertTrue(threw) + + threw = False + try: hb.lookup_block('../../my_hier/my_block0') + except: threw = True + self.assertTrue(threw) + + threw = False + try: hb.lookup_block('../../my_hier/my_block/test') + except: threw = True + self.assertTrue(threw) if __name__ == '__main__': unittest.main() |