From 918b7f96db861cdbe2e3b6664aab2348c73da39f Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 12 Jul 2017 18:33:20 +0200 Subject: [PATCH] valueBuilder: support scalar array fields --- src/pv/valueBuilder.cpp | 34 +++++++++++++++++++++++++++++++++ src/pv/valueBuilder.h | 18 +++++++++++++---- testApp/pv/testValueBuilder.cpp | 26 ++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/pv/valueBuilder.cpp b/src/pv/valueBuilder.cpp index ea1931f..5df9f30 100644 --- a/src/pv/valueBuilder.cpp +++ b/src/pv/valueBuilder.cpp @@ -64,6 +64,26 @@ struct ValueBuilder::child_scalar_base : public ValueBuilder::child } }; +struct ValueBuilder::child_scalar_array : public ValueBuilder::child +{ + virtual ~child_scalar_array() {} + shared_vector array; + child_scalar_array(const shared_vector& v) : child(scalarArray), array(v) {} + + virtual void build(const std::string& name, FieldBuilderPtr& builder) OVERRIDE FINAL + { + builder->addArray(name, array.original_type()); + } + virtual void store(const PVFieldPtr& val) + { + if(val->getField()->getType()!=scalarArray) + THROW_EXCEPTION2(std::logic_error, "Scalar Array type mis-match"); + + PVScalarArrayPtr arr(std::tr1::static_pointer_cast(val)); + arr->putFrom(array); + } +}; + template struct ValueBuilder::child_scalar : public ValueBuilder::child_scalar_base { @@ -188,6 +208,20 @@ void ValueBuilder::_add(const std::string& name, ScalarType stype, const void *V store.release(); } +void ValueBuilder::_add(const std::string& name, const shared_vector& V) +{ + const children_t::iterator it(children.find(name)); + if(it!=children.end()) { + if(it->second->type!=scalar && it->second->type!=scalarArray) + THROW_EXCEPTION2(std::logic_error, "Not allowed to replace field. wrong type"); + } + + std::auto_ptr store(new child_scalar_array(V)); + + children[name] = store.get(); + store.release(); +} + ValueBuilder& ValueBuilder::addNested(const std::string& name, Type type, const std::string &id) { if(type!=structure) diff --git a/src/pv/valueBuilder.h b/src/pv/valueBuilder.h index 5edabc8..39ab572 100644 --- a/src/pv/valueBuilder.h +++ b/src/pv/valueBuilder.h @@ -9,6 +9,7 @@ #include #include +#include namespace epics{namespace pvData{ @@ -44,6 +45,14 @@ public: return *this; } + //! Add a scalar array field + template + FORCE_INLINE ValueBuilder& add(const std::string& name, const shared_vector& V) + { + _add(name, V); + return *this; + } + FORCE_INLINE ValueBuilder& add(const std::string& name, const PVStructure& V) { _add(name, V); return *this; @@ -62,6 +71,7 @@ public: private: void _add(const std::string& name, ScalarType stype, const void *V); + void _add(const std::string& name, const shared_vector &V); void _add(const std::string& name, const PVStructure& V); ValueBuilder(ValueBuilder*, const std::string &id = std::string()); @@ -73,10 +83,10 @@ private: friend struct child_struct; struct child_scalar_base; friend struct child_scalar_base; - template - struct child_scalar; - template - friend struct child_scalar; + template struct child_scalar; + template friend struct child_scalar; + struct child_scalar_array; + friend struct child_scalar_array; typedef std::map children_t; children_t children; diff --git a/testApp/pv/testValueBuilder.cpp b/testApp/pv/testValueBuilder.cpp index 5e8f59f..d1b2d8f 100644 --- a/testApp/pv/testValueBuilder.cpp +++ b/testApp/pv/testValueBuilder.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace pvd = epics::pvData; @@ -136,16 +137,39 @@ void testAppend() testOk1(mod->getSubFieldT("record._options.foo")->get()==1); } +void testArray() +{ + testDiag("testArray()"); + + pvd::ValueBuilder builder; + + pvd::shared_vector V(2); + V[0] = 1; + V[1] = 2; + pvd::shared_vector SV(pvd::freeze(V)); + + pvd::PVStructurePtr S(builder + .add("foo", pvd::static_shared_vector_cast(SV)) + .buildPVStructure()); + + pvd::PVIntArrayPtr I(S->getSubFieldT("foo")); + + pvd::PVIntArray::const_svector out(I->view()); + + testFieldEqual(S, "foo", SV); +} + } // namespace MAIN(testValueBuilder) { - testPlan(27); + testPlan(28); try { testBuild(); testSubStruct(); testReplace(); testAppend(); + testArray(); }catch(std::exception& e){ PRINT_EXCEPTION(e); testAbort("Unexpected exception: %s", e.what());