aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorLane Kolbly <lane.kolbly@ni.com>2021-12-23 09:39:39 -0600
committerAaron Rossetto <aaron.rossetto@ni.com>2022-02-07 14:43:46 -0600
commited18ed376bcc71938ad73872148a3146814d831f (patch)
tree86056811e0643d62032a804dc6a76ff4e10028fa /host
parenta7c5d70fecb7e7e37c81b0154eb3032d4d1cf6b1 (diff)
downloaduhd-ed18ed376bcc71938ad73872148a3146814d831f.tar.gz
uhd-ed18ed376bcc71938ad73872148a3146814d831f.tar.bz2
uhd-ed18ed376bcc71938ad73872148a3146814d831f.zip
host: Throw exception when accessing properties with incorrect type
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/property_tree.hpp17
-rw-r--r--host/include/uhd/property_tree.ipp19
-rw-r--r--host/lib/property_tree.cpp8
-rw-r--r--host/tests/property_test.cpp25
4 files changed, 55 insertions, 14 deletions
diff --git a/host/include/uhd/property_tree.hpp b/host/include/uhd/property_tree.hpp
index 9fc9b3b97..a1d292858 100644
--- a/host/include/uhd/property_tree.hpp
+++ b/host/include/uhd/property_tree.hpp
@@ -18,6 +18,15 @@
namespace uhd {
/*!
+ * A non-templated class which exists solely so we can
+ * dynamic_cast between properties.
+ */
+class UHD_API property_iface {
+public:
+ virtual ~property_iface() = default;
+};
+
+/*!
* A templated property interface for holding the state
* associated with a property in a uhd::property_tree
* and registering callbacks when that value changes.
@@ -65,7 +74,7 @@ namespace uhd {
* - T must have an assignment operator
*/
template <typename T>
-class UHD_API_HEADER property : uhd::noncopyable
+class UHD_API_HEADER property : uhd::noncopyable, public property_iface
{
public:
typedef std::function<void(const T&)> subscriber_type;
@@ -245,14 +254,14 @@ public:
private:
//! Internal pop function
- virtual std::shared_ptr<void> _pop(const fs_path& path) = 0;
+ virtual std::shared_ptr<property_iface> _pop(const fs_path& path) = 0;
//! Internal create property with wild-card type
virtual void _create(const fs_path& path,
- const std::shared_ptr<void>& prop) = 0;
+ const std::shared_ptr<property_iface>& prop) = 0;
//! Internal access property with wild-card type
- virtual std::shared_ptr<void>& _access(const fs_path& path) const = 0;
+ virtual std::shared_ptr<property_iface>& _access(const fs_path& path) const = 0;
};
} // namespace uhd
diff --git a/host/include/uhd/property_tree.ipp b/host/include/uhd/property_tree.ipp
index 273227174..e9dd3072e 100644
--- a/host/include/uhd/property_tree.ipp
+++ b/host/include/uhd/property_tree.ipp
@@ -9,8 +9,8 @@
#pragma once
#include <uhd/exception.hpp>
-#include <vector>
#include <memory>
+#include <vector>
/***********************************************************************
* Implement templated property impl
@@ -179,21 +179,28 @@ namespace uhd {
template <typename T>
property<T>& property_tree::create(const fs_path& path, coerce_mode_t coerce_mode)
{
- this->_create(path, std::make_shared<property_impl<T> >(coerce_mode));
+ this->_create(path, std::make_shared<property_impl<T>>(coerce_mode));
return this->access<T>(path);
}
template <typename T>
property<T>& property_tree::access(const fs_path& path)
{
- return *std::static_pointer_cast<property<T> >(
- this->_access(path));
+ auto ptr = std::dynamic_pointer_cast<property<T>>(this->_access(path));
+ if (!ptr) {
+ throw uhd::type_error("Property " + path + " exists, but was accessed with wrong type");
+ }
+ return *ptr;
}
template <typename T>
-typename std::shared_ptr<property<T> > property_tree::pop(const fs_path& path)
+typename std::shared_ptr<property<T>> property_tree::pop(const fs_path& path)
{
- return std::static_pointer_cast<property<T> >(this->_pop(path));
+ auto ptr = std::dynamic_pointer_cast<property<T>>(this->_pop(path));
+ if (!ptr) {
+ throw uhd::type_error("Property " + path + " exists, but was accessed with wrong type");
+ }
+ return ptr;
}
} // namespace uhd
diff --git a/host/lib/property_tree.cpp b/host/lib/property_tree.cpp
index a21254336..79ec22b67 100644
--- a/host/lib/property_tree.cpp
+++ b/host/lib/property_tree.cpp
@@ -138,7 +138,7 @@ public:
return node->keys();
}
- std::shared_ptr<void> _pop(const fs_path& path_) override
+ std::shared_ptr<property_iface> _pop(const fs_path& path_) override
{
const fs_path path = _root / path_;
std::lock_guard<std::mutex> lock(_guts->mutex);
@@ -164,7 +164,7 @@ public:
return prop;
}
- void _create(const fs_path& path_, const std::shared_ptr<void>& prop) override
+ void _create(const fs_path& path_, const std::shared_ptr<property_iface>& prop) override
{
const fs_path path = _root / path_;
std::lock_guard<std::mutex> lock(_guts->mutex);
@@ -183,7 +183,7 @@ public:
node->prop = prop;
}
- std::shared_ptr<void>& _access(const fs_path& path_) const override
+ std::shared_ptr<property_iface>& _access(const fs_path& path_) const override
{
const fs_path path = _root / path_;
std::lock_guard<std::mutex> lock(_guts->mutex);
@@ -210,7 +210,7 @@ private:
// basic structural node element
struct node_type : uhd::dict<std::string, node_type>
{
- std::shared_ptr<void> prop;
+ std::shared_ptr<property_iface> prop;
};
// tree guts which may be referenced in a subtree
diff --git a/host/tests/property_test.cpp b/host/tests/property_test.cpp
index 9776dd91b..ff9434fd1 100644
--- a/host/tests/property_test.cpp
+++ b/host/tests/property_test.cpp
@@ -7,6 +7,7 @@
//
#include <uhd/property_tree.hpp>
+#include <uhd/types/ranges.hpp>
#include <boost/test/unit_test.hpp>
#include <exception>
#include <functional>
@@ -228,6 +229,30 @@ BOOST_AUTO_TEST_CASE(test_prop_tree)
BOOST_CHECK(not tree->exists("/test/prop1"));
}
+BOOST_AUTO_TEST_CASE(test_prop_tree_wrong_type)
+{
+ uhd::property_tree::sptr tree = uhd::property_tree::make();
+ tree->create<int>("/test/prop0");
+ BOOST_CHECK_THROW(tree->access<std::string>("/test/prop0"), uhd::type_error);
+}
+
+BOOST_AUTO_TEST_CASE(test_prop_tree_wrong_type_range)
+{
+ uhd::property_tree::sptr tree = uhd::property_tree::make();
+
+ // Create the property
+ tree->create<uhd::range_t>("/test/prop1");
+ uhd::range_t singleton_range(5.0);
+ tree->access<uhd::range_t>("/test/prop1").set(singleton_range);
+
+ // Check it throws a type error
+ BOOST_CHECK_THROW(tree->access<std::string>("/test/prop1"), uhd::type_error);
+
+ // Check we can access its value
+ auto& prop = tree->access<uhd::range_t>("/test/prop1");
+ BOOST_CHECK_EQUAL(prop.get().start(), 5.0);
+}
+
BOOST_AUTO_TEST_CASE(test_prop_subtree)
{
uhd::property_tree::sptr tree = uhd::property_tree::make();