diff options
author | Aaron Rossetto <aaron.rossetto@ni.com> | 2019-08-28 08:32:00 -0500 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 12:21:31 -0800 |
commit | cb9329a681552e6ac6277d16e1627afcbb23e637 (patch) | |
tree | bb87fc4362cb0d683ed41259498888fa71f15d36 | |
parent | 4f130e3c129111cb8fb044a5cbc007df3628978c (diff) | |
download | uhd-cb9329a681552e6ac6277d16e1627afcbb23e637.tar.gz uhd-cb9329a681552e6ac6277d16e1627afcbb23e637.tar.bz2 uhd-cb9329a681552e6ac6277d16e1627afcbb23e637.zip |
uhd: Check property type at access; error if mismatch
-rw-r--r-- | host/include/uhd/property_tree.hpp | 8 | ||||
-rw-r--r-- | host/include/uhd/property_tree.ipp | 7 | ||||
-rw-r--r-- | host/lib/property_tree.cpp | 25 | ||||
-rw-r--r-- | host/tests/property_test.cpp | 20 |
4 files changed, 55 insertions, 5 deletions
diff --git a/host/include/uhd/property_tree.hpp b/host/include/uhd/property_tree.hpp index 11b92393a..d97a5505e 100644 --- a/host/include/uhd/property_tree.hpp +++ b/host/include/uhd/property_tree.hpp @@ -14,6 +14,7 @@ #include <boost/function.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> +#include <typeindex> #include <vector> namespace uhd { @@ -252,10 +253,15 @@ private: virtual boost::shared_ptr<void> _pop(const fs_path& path) = 0; //! Internal create property with wild-card type - virtual void _create(const fs_path& path, const boost::shared_ptr<void>& prop) = 0; + virtual void _create(const fs_path& path, const boost::shared_ptr<void>& prop, + std::type_index prop_type) = 0; //! Internal access property with wild-card type virtual boost::shared_ptr<void>& _access(const fs_path& path) const = 0; + + //! Internal access property with wild-card type but with type verification + virtual boost::shared_ptr<void>& _access_with_type_check( + const fs_path& path, std::type_index expected_prop_type) const = 0; }; } // namespace uhd diff --git a/host/include/uhd/property_tree.ipp b/host/include/uhd/property_tree.ipp index ca5d6904f..20ad43fb1 100644 --- a/host/include/uhd/property_tree.ipp +++ b/host/include/uhd/property_tree.ipp @@ -12,6 +12,7 @@ #include <uhd/exception.hpp> #include <boost/foreach.hpp> #include <boost/scoped_ptr.hpp> +#include <typeindex> #include <vector> /*********************************************************************** @@ -182,14 +183,16 @@ template <typename T> property<T>& property_tree::create(const fs_path& path, coerce_mode_t coerce_mode) { this->_create(path, - typename boost::shared_ptr<property<T> >(new property_impl<T>(coerce_mode))); + typename boost::shared_ptr<property<T> >(new property_impl<T>(coerce_mode)), + std::type_index(typeid(T))); return this->access<T>(path); } template <typename T> property<T>& property_tree::access(const fs_path& path) { - return *boost::static_pointer_cast<property<T> >(this->_access(path)); + return *boost::static_pointer_cast<property<T> >( + this->_access_with_type_check(path, std::type_index(typeid(T)))); } template <typename T> diff --git a/host/lib/property_tree.cpp b/host/lib/property_tree.cpp index 85868b27c..6f797bc2e 100644 --- a/host/lib/property_tree.cpp +++ b/host/lib/property_tree.cpp @@ -11,6 +11,7 @@ #include <boost/make_shared.hpp> #include <boost/thread/mutex.hpp> #include <iostream> +#include <typeindex> using namespace uhd; @@ -156,7 +157,8 @@ public: return prop; } - void _create(const fs_path& path_, const boost::shared_ptr<void>& prop) + void _create(const fs_path& path_, const boost::shared_ptr<void>& prop, + std::type_index prop_type) { const fs_path path = _root / path_; boost::mutex::scoped_lock lock(_guts->mutex); @@ -171,6 +173,7 @@ public: throw uhd::runtime_error( "Cannot create! Property already exists at: " + path); node->prop = prop; + node->prop_type_hash = prop_type.hash_code(); } boost::shared_ptr<void>& _access(const fs_path& path_) const @@ -189,6 +192,25 @@ public: return node->prop; } + boost::shared_ptr<void>& _access_with_type_check( + const fs_path& path_, std::type_index expected_prop_type) const + { + const fs_path path = _root / path_; + boost::mutex::scoped_lock lock(_guts->mutex); + + node_type* node = &_guts->root; + for (const std::string& name : path_tokenizer(path)) { + if (not node->has_key(name)) + throw_path_not_found(path); + node = &(*node)[name]; + } + if (node->prop.get() == NULL) + throw uhd::runtime_error("Cannot access! Property uninitialized at: " + path); + if (node->prop_type_hash != expected_prop_type.hash_code()) + throw uhd::runtime_error("Cannot access! Property types do not match at: " + path); + return node->prop; + } + private: void throw_path_not_found(const fs_path& path) const { @@ -199,6 +221,7 @@ private: struct node_type : uhd::dict<std::string, node_type> { boost::shared_ptr<void> prop; + std::size_t prop_type_hash; }; // tree guts which may be referenced in a subtree diff --git a/host/tests/property_test.cpp b/host/tests/property_test.cpp index 907ca9f73..732e3ca84 100644 --- a/host/tests/property_test.cpp +++ b/host/tests/property_test.cpp @@ -239,7 +239,6 @@ BOOST_AUTO_TEST_CASE(test_prop_subtree) tree_dirs2.begin(), tree_dirs2.end(), subtree2_dirs.begin(), subtree2_dirs.end()); } - BOOST_AUTO_TEST_CASE(test_prop_operators) { uhd::fs_path path1 = "/root/"; @@ -259,3 +258,22 @@ BOOST_AUTO_TEST_CASE(test_prop_operators) path4 = path4 / x; BOOST_CHECK_EQUAL(path4, "/root/2"); } + +BOOST_AUTO_TEST_CASE(test_mismatched_type_access) +{ + uhd::property_tree::sptr tree = uhd::property_tree::make(); + + // accesses of the correct type should succeed + tree->create<int>("/intprop"); + tree->create<double>("/doubleprop"); + tree->create<std::string>("/stringprop"); + BOOST_CHECK_NO_THROW(tree->access<int>("/intprop")); + BOOST_CHECK_NO_THROW(tree->access<double>("/doubleprop")); + BOOST_CHECK_NO_THROW(tree->access<std::string>("/stringprop")); + + // accesses of the incorrect type should throw an exception + BOOST_CHECK_THROW(tree->access<int>("/doubleprop"), uhd::runtime_error); + BOOST_CHECK_THROW(tree->access<double>("/stringprop"), uhd::runtime_error); + BOOST_CHECK_THROW(tree->access<std::string>("/intprop"), uhd::runtime_error); +} + |