aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Rossetto <aaron.rossetto@ni.com>2019-08-28 08:32:00 -0500
committerMartin Braun <martin.braun@ettus.com>2019-09-04 19:06:08 -0700
commit94592641f0647563bc4d2163805d5284a6796273 (patch)
treebaf5ae1d7605c8a6b303426c69eae6c1a9e9b61d
parentUpdate CODING guidelines (diff)
downloaduhd-94592641f0647563bc4d2163805d5284a6796273.tar.xz
uhd-94592641f0647563bc4d2163805d5284a6796273.zip
uhd: Check property type at access; error if mismatch
-rw-r--r--host/include/uhd/property_tree.hpp8
-rw-r--r--host/include/uhd/property_tree.ipp7
-rw-r--r--host/lib/property_tree.cpp25
-rw-r--r--host/tests/property_test.cpp20
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);
+}
+