diff options
author | Lane Kolbly <lane.kolbly@ni.com> | 2021-12-23 09:39:39 -0600 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2022-02-07 14:43:46 -0600 |
commit | ed18ed376bcc71938ad73872148a3146814d831f (patch) | |
tree | 86056811e0643d62032a804dc6a76ff4e10028fa /host | |
parent | a7c5d70fecb7e7e37c81b0154eb3032d4d1cf6b1 (diff) | |
download | uhd-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.hpp | 17 | ||||
-rw-r--r-- | host/include/uhd/property_tree.ipp | 19 | ||||
-rw-r--r-- | host/lib/property_tree.cpp | 8 | ||||
-rw-r--r-- | host/tests/property_test.cpp | 25 |
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(); |