From: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx> Implement the copy operator for line_settings. We have a copy() method for line settings in C API while in C++ it's useful to copy line_settings returned in an std::map from line_config.get_line_settings(). Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx> --- bindings/cxx/gpiodcxx/line-settings.hpp | 13 ++++++- bindings/cxx/internal.hpp | 2 +- bindings/cxx/line-settings.cpp | 28 ++++++++++++++ bindings/cxx/tests/tests-line-settings.cpp | 43 ++++++++++++++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/bindings/cxx/gpiodcxx/line-settings.hpp b/bindings/cxx/gpiodcxx/line-settings.hpp index c1477b1..c18dc52 100644 --- a/bindings/cxx/gpiodcxx/line-settings.hpp +++ b/bindings/cxx/gpiodcxx/line-settings.hpp @@ -38,7 +38,11 @@ public: */ line_settings(); - line_settings(const line_settings& other) = delete; + /** + * @brief Copy constructor. + * @param other Object to copy. + */ + line_settings(const line_settings& other); /** * @brief Move constructor. @@ -48,7 +52,12 @@ public: ~line_settings(); - line_settings& operator=(const line_settings& other) = delete; + /** + * @brief Copy assignment operator. + * @param other Object to copy. + * @return Reference to self. + */ + line_settings& operator=(const line_settings& other); /** * @brief Move assignment operator. diff --git a/bindings/cxx/internal.hpp b/bindings/cxx/internal.hpp index d27aa22..6aceac1 100644 --- a/bindings/cxx/internal.hpp +++ b/bindings/cxx/internal.hpp @@ -120,7 +120,7 @@ struct info_event::impl struct line_settings::impl { impl(); - impl(const impl& other) = delete; + impl(const impl& other); impl(impl&& other) = delete; impl& operator=(const impl& other) = delete; impl& operator=(impl&& other) = delete; diff --git a/bindings/cxx/line-settings.cpp b/bindings/cxx/line-settings.cpp index 5ded953..32f21a3 100644 --- a/bindings/cxx/line-settings.cpp +++ b/bindings/cxx/line-settings.cpp @@ -86,6 +86,15 @@ line_settings_ptr make_line_settings() return settings; } +line_settings_ptr copy_line_settings(const line_settings_ptr& ptr) +{ + line_settings_ptr settings(::gpiod_line_settings_copy(ptr.get())); + if (!settings) + throw_from_errno("Unable to copy the line settings object"); + + return settings; +} + template<class key_type, class value_type, class exception_type> value_type map_setting(const key_type& key, const ::std::map<key_type, value_type>& mapping) { @@ -136,12 +145,24 @@ line_settings::impl::impl() } +line_settings::impl::impl(const impl& other) + : settings(copy_line_settings(other.settings)) +{ + +} + GPIOD_CXX_API line_settings::line_settings() : _m_priv(new impl) { } +GPIOD_CXX_API line_settings::line_settings(const line_settings& other) + : _m_priv(new impl(*other._m_priv)) +{ + +} + GPIOD_CXX_API line_settings::line_settings(line_settings&& other) noexcept : _m_priv(::std::move(other._m_priv)) { @@ -153,6 +174,13 @@ GPIOD_CXX_API line_settings::~line_settings() } +GPIOD_CXX_API line_settings& line_settings::operator=(const line_settings& other) +{ + this->_m_priv.reset(new impl(*other._m_priv)); + + return *this; +} + GPIOD_CXX_API line_settings& line_settings::operator=(line_settings&& other) { this->_m_priv = ::std::move(other._m_priv); diff --git a/bindings/cxx/tests/tests-line-settings.cpp b/bindings/cxx/tests/tests-line-settings.cpp index a3f4bc5..dc821bb 100644 --- a/bindings/cxx/tests/tests-line-settings.cpp +++ b/bindings/cxx/tests/tests-line-settings.cpp @@ -124,6 +124,49 @@ TEST_CASE("line_settings mutators work", "[line-settings]") } } +TEST_CASE("line_settings can be moved and copied", "[line-settings]") +{ + ::gpiod::line_settings settings; + + settings + .set_direction(direction::INPUT) + .set_edge_detection(edge::BOTH); + + SECTION("copy constructor works") + { + auto copy(settings); + settings.set_direction(direction::OUTPUT); + settings.set_edge_detection(edge::NONE); + REQUIRE(copy.direction() == direction::INPUT); + REQUIRE(copy.edge_detection() == edge::BOTH); + } + + SECTION("assignment operator works") + { + ::gpiod::line_settings copy; + copy = settings; + settings.set_direction(direction::OUTPUT); + settings.set_edge_detection(edge::NONE); + REQUIRE(copy.direction() == direction::INPUT); + REQUIRE(copy.edge_detection() == edge::BOTH); + } + + SECTION("move constructor works") + { + auto copy(::std::move(settings)); + REQUIRE(copy.direction() == direction::INPUT); + REQUIRE(copy.edge_detection() == edge::BOTH); + } + + SECTION("move assignment operator works") + { + ::gpiod::line_settings copy; + copy = ::std::move(settings); + REQUIRE(copy.direction() == direction::INPUT); + REQUIRE(copy.edge_detection() == edge::BOTH); + } +} + TEST_CASE("line_settings stream insertion operator works", "[line-settings]") { ::gpiod::line_settings settings; -- 2.37.2