diff --git a/src/pv/pvaClient.h b/src/pv/pvaClient.h index 2107726..aba39cd 100644 --- a/src/pv/pvaClient.h +++ b/src/pv/pvaClient.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -613,6 +614,7 @@ public: void setData( epics::pvData::PVStructurePtr const & pvStructureFrom, epics::pvData::BitSetPtr const & bitSetFrom); + /** @brief Is there a top level field named value. * @return The answer. */ @@ -679,6 +681,29 @@ public: * @return The timeStamp. */ epics::pvData::TimeStamp getTimeStamp(); + /** @brief parse from args + * + * Accepts arguments of the form json or field='value' where value is json syntax. + * field is name.name... + * @param args The arguments + * @throw runtime_error if failure. + */ + void parse(const std::vector &args); + /** @brief generate JSON output from the current PVStructure + * + * @param strm output stream + * @param ignoreUnprintable false or true; default is true. + * @param multiline false or true; default is false + * + * @throw runtime_error if failure. + */ + void streamJSON( + std::ostream& strm, + bool ignoreUnprintable = true, + bool multiLine = false); + /** @brief set length of all array fields to 0 + */ + void zeroArrayLength(); /** @brief Factory method for creating an instance of PvaClientData. * * NOTE: Not normally called by clients @@ -691,12 +716,19 @@ 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); + void zeroArrayLength(const epics::pvData::PVStructurePtr &pvStructure); 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..b503732 100644 --- a/src/pvaClientData.cpp +++ b/src/pvaClientData.cpp @@ -11,9 +11,17 @@ #include #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 +114,7 @@ void PvaClientData::setData( pvValue = pvStructure->getSubField("value"); } + bool PvaClientData::hasValue() { if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n"; @@ -358,4 +367,141 @@ TimeStamp PvaClientData::getTimeStamp() throw std::runtime_error(messagePrefix + noTimeStamp); } +void PvaClientData::zeroArrayLength() +{ + if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure); + zeroArrayLength(pvStructure); +} +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); + size_t num = args.size(); + if(num<1) throw std::runtime_error(messagePrefix + " no arguments"); + 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; + } + parse(rest,pvField,bitSet); + } +} + +void PvaClientData::streamJSON( + std::ostream& strm, + bool ignoreUnprintable, + bool multiLine) +{ +#ifdef USE_JSON + JSONPrintOptions opts; + opts.ignoreUnprintable = ignoreUnprintable; + opts.multiLine = multiLine; + printJSON(strm,*pvStructure,*bitSet,opts); +#else + throw std::runtime_error("JSON support not built"); +#endif +} + + +void PvaClientData::zeroArrayLength(const epics::pvData::PVStructurePtr &pvStructure) +{ +const PVFieldPtrArray pvFields(pvStructure->getPVFields()); + for(size_t i=0; igetField()->getType()); + switch(type) { + case epics::pvData::scalarArray: + { + PVScalarArrayPtr pvScalarArray = static_pointer_cast(pvField); + pvScalarArray->setLength(0); + } + break; + case epics::pvData::structureArray: + { + PVStructureArrayPtr pvStructureArray = static_pointer_cast(pvField); + pvStructureArray->setLength(0); + } + break; + case epics::pvData::structure: + { + PVStructurePtr pvStructure = static_pointer_cast(pvField); + zeroArrayLength(pvStructure); + } + break; + default: + break; + } + } +} + + }}