From 2381f28c734d349b53556e35eeb4351cb74058b2 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 16 Jul 2020 14:05:35 -0700 Subject: [PATCH] allow unselection/clear of Union/Any --- src/data.cpp | 6 ++++++ src/pvxs/data.h | 8 +++++++- test/testdata.cpp | 7 ++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/data.cpp b/src/data.cpp index 1fd8074..0ea3713 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -584,12 +584,18 @@ void Value::copyIn(const void *ptr, StoreType type) break; } case StoreType::Compound: + if(type==StoreType::Null) { + store->as() = Value(); // unselect Union or Any + break; + } + if(desc->code==TypeCode::Any) { // assigning variant union. auto& val = store->as(); if(type==StoreType::Compound) { val = *reinterpret_cast(ptr); break; + } else { val = Value::Helper::build(ptr, type); break; diff --git a/src/pvxs/data.h b/src/pvxs/data.h index b2c33c8..41fe11e 100644 --- a/src/pvxs/data.h +++ b/src/pvxs/data.h @@ -37,6 +37,8 @@ enum struct StoreType : uint8_t { Array, //!< shared_array }; +constexpr struct unselect_t {} unselect; + namespace impl { struct FieldStorage; struct FieldDesc; @@ -87,6 +89,10 @@ template<> struct StorageMap { typedef Value store_t; static constexpr StoreType code{StoreType::Compound}; }; +template<> +struct StorageMap +{ typedef unselect_t store_t; static constexpr StoreType code{StoreType::Null}; }; + template using StoreAs = StorageMap::type>; @@ -229,7 +235,7 @@ CASE(std::string, std::string, String); #undef CASE -} // namespace +} // namespace impl //! Definition of a member of a Struct/Union for use with TypeDef struct Member { diff --git a/test/testdata.cpp b/test/testdata.cpp index 335f6e9..eb3cf96 100644 --- a/test/testdata.cpp +++ b/test/testdata.cpp @@ -83,11 +83,16 @@ void testAssignUnion() testEq(val.nameOf(val["->"]), "s"); + val = unselect; + + testFalse(val["->"].valid()); + testThrows([&val](){ val["->u16"] = "hello"; }); - //val = nullptr; + // previous selection succeeds, but assignment fails + testTrue(val["->"].valid()); } void testName()