diff --git a/src/pv/pvaClient.h b/src/pv/pvaClient.h index 2107726..3c972ca 100644 --- a/src/pv/pvaClient.h +++ b/src/pv/pvaClient.h @@ -613,6 +613,14 @@ public: void setData( epics::pvData::PVStructurePtr const & pvStructureFrom, epics::pvData::BitSetPtr const & bitSetFrom); + /** @brief parse from input stream + * + * Accepts arguments of the form field='value' where value is json syntax. + * field is name.name... + * @parm args The arguments + * @throw runtime_error if failure. + */ + void parse(const std::vector &args); /** @brief Is there a top level field named value. * @return The answer. */ @@ -691,12 +699,18 @@ protected: void checkValue(); std::string messagePrefix; private: + void parse( + const std::string &arg, + const epics::pvData::PVFieldPtr &dest, + epics::pvData::BitSetPtr &bitSet); + void parse( + const std::string &arg, + const epics::pvData::PVUnionPtr &dest); epics::pvData::StructureConstPtr structure; epics::pvData::PVStructurePtr pvStructure; epics::pvData::BitSetPtr bitSet; - epics::pvData::PVFieldPtr pvValue; epics::pvData::PVAlarm pvAlarm; epics::pvData::PVTimeStamp pvTimeStamp; diff --git a/src/pvaClientData.cpp b/src/pvaClientData.cpp index 5db266d..ed3eced 100644 --- a/src/pvaClientData.cpp +++ b/src/pvaClientData.cpp @@ -11,9 +11,16 @@ #include #include +#include #include #include +#include + +#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1) +# include +# define USE_JSON +#endif #define epicsExportSharedSymbols @@ -106,6 +113,90 @@ void PvaClientData::setData( pvValue = pvStructure->getSubField("value"); } +void PvaClientData::parse( + const std::string &arg,const PVFieldPtr &dest,BitSetPtr & bitSet) +{ +#ifdef USE_JSON + std::istringstream strm(arg); + parseJSON(strm, dest,&(*bitSet)); +#else + throw std::runtime_error("JSON support not built"); +#endif +} + +void PvaClientData::parse( + const std::string &arg,const PVUnionPtr &pvUnion) +{ + if(pvUnion->getUnion()->isVariant()) { + throw std::runtime_error(messagePrefix + "varient union not implemented"); + } + size_t iequals = arg.find_first_of('='); + string field; + string rest; + if(iequals==std::string::npos) { + string mess(arg); + mess += " was expected to start with field="; + throw std::runtime_error(messagePrefix + mess); + } + field = arg.substr(0,iequals); + rest = arg.substr(iequals+1); + PVFieldPtr pvField(pvUnion->select(field)); + if(pvField->getField()->getType()==epics::pvData::union_) { + PVUnionPtr pvu = static_pointer_cast(pvField); + parse(rest,pvu); + return; + } + BitSetPtr bs; + parse(rest,pvField,bs); + return; +} + +void PvaClientData::parse(const std::vector &args) +{ + if(!pvStructure) throw std::runtime_error(messagePrefix + noStructure); + if(!bitSet) throw std::runtime_error(messagePrefix + noStructure); + bitSet->clear(); + size_t num = args.size(); + for(size_t i=0; igetSubField(field)); + // look for enumerated structure + PVEnumerated pvEnumerated; + bool result = pvEnumerated.attach(pvField); + if(result) { + PVStringArray::const_svector choices(pvEnumerated.getChoices()); + for(size_t i=0; igetSubField(field)); + if(pvUnion) { + parse(rest,pvUnion); + bitSet->set(pvUnion->getFieldOffset()); + return; + } + PVScalarArrayPtr pvScalarArray(pvStructure->getSubField(field)); + if(pvScalarArray) pvScalarArray->setLength(0); + parse(rest,pvField,bitSet); + } +} + bool PvaClientData::hasValue() { if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";