diff --git a/src/data.cpp b/src/data.cpp index 961aeb7..1a0c954 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -175,6 +175,41 @@ Value Value::allocMember() return Value::Helper::build(fld, *this); } +void Value::clear() +{ + if(!desc) + return; + + for(auto i : range(size_t(0u), desc->size())) { + auto& s = store.get()[i]; + s.valid = false; + + switch(s.code) { + case StoreType::Array: + s.as>().clear(); + break; + case StoreType::Compound: + { + auto& v = s.as(); + v.desc = nullptr; + v.store.reset(); + } + break; + case StoreType::String: + s.as().clear(); + break; + case StoreType::Null: + break; // nothing to do + case StoreType::Bool: + case StoreType::UInteger: + case StoreType::Integer: + case StoreType::Real: + memset(&s.store, 0, sizeof(s.store)); // just zero + break; + } + } +} + bool Value::isMarked(bool parents, bool children) const { if(!desc) diff --git a/src/pvxs/data.h b/src/pvxs/data.h index da4eba9..de9cfdb 100644 --- a/src/pvxs/data.h +++ b/src/pvxs/data.h @@ -550,6 +550,15 @@ public: //! Use to allocate members for an array of Struct and array of Union Value allocMember(); + /** Restore to newly allocated state. + * + * Free any allocation for array or string values, zero numeric values. + * unmark() all fields. + * + * @since UNRELEASED + */ + void clear(); + //! Does this Value actually reference some underlying storage inline bool valid() const { return desc; } inline explicit operator bool() const { return desc; } diff --git a/test/testdata.cpp b/test/testdata.cpp index d45e159..5c6e2a4 100644 --- a/test/testdata.cpp +++ b/test/testdata.cpp @@ -342,11 +342,44 @@ void testExtract() } } +void testClear() +{ + testShow()<<__func__; + + auto val = TypeDef(TypeCode::Struct, { + members::UInt32("int"), + members::String("string"), + members::UInt32A("arr"), + members::Any("any"), + }).create(); + + val["int"] = 0x12345678; + val["string"] = "testing"; + val["arr"] = shared_array({1,2,3}); + val["any"].assign(nt::NTScalar{TypeCode::UInt32}.create()); + val["any->value"] = 0x01020304; + + testEq(val["int"].as(), 0x12345678u); + testEq(val["string"].as(), std::string("testing")); + testEq(val["arr"].as>().size(), 3u); + testTrue(!!val["any->"]); + testEq(val["any->value"].as(), 0x01020304u); + testTrue(val.isMarked(true, true)); + + val.clear(); + + testEq(val["int"].as(), 0u); + testEq(val["string"].as(), std::string("")); + testEq(val["arr"].as>().size(), 0u); + testFalse(val["any->"]); + testFalse(val.isMarked(true, true)); +} + } // namespace MAIN(testdata) { - testPlan(116); + testPlan(127); testSetup(); testTraverse(); testAssign(); @@ -390,6 +423,7 @@ MAIN(testdata) testAssignSimilar(); testExtract(); + testClear(); cleanup_for_valgrind(); return testDone(); }