diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 4792c7d..26bb62b 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -2,6 +2,31 @@ This document summarizes the changes to the module between releases. +## release (EPICS 7.0.2.2 April 2019) + +Changes have been made for getDouble, putDouble, getDoubleArray, putDoubleArray, getString, putString, getStringArray, and putStringArray. + +1) Previously each only had support for a top level field named value. +Each now allows access to a single sub field that has the correct type. +Thus pvRequest must select a single field. For example + + pva->channel("PVRdumbPowerSupply")->putDouble(1.0,"power.value" ); + +2) PvaChannel now has a method for each of the above. +For example instead of + + PvaClientChannelPtr channel = pva->channel("PVRdouble"); + PvaClientPutPtr clientPut = channel->put(); + PvaClientPutDataPtr putData = clientPut->getData(); + putData->putDouble(1.0); clientPut->put(); + +now it can be + + pva->channel("PVRdouble")->putDouble(1.0 ); + +3) getDoubleArray and putDoubleArray work with any numeric scalar array + +4) getStringArray and putStringArray work with any scalar array. ## Release 4.4 (EPICS 7.0.2, Dec 2018) diff --git a/documentation/pvaClientCPP.html b/documentation/pvaClientCPP.html index 0279af3..68fe4c2 100644 --- a/documentation/pvaClientCPP.html +++ b/documentation/pvaClientCPP.html @@ -26,7 +26,7 @@

EPICS pvaClientCPP

-

Release 4.4 - December 2018

+

Release 4.4 - April 2019

Abstract

@@ -79,7 +79,7 @@ It is intended for developers that want to use pvaClientCPP.

Developer Guide

A guide for developers is available at +href="https://mrkraimer.github.io/website/developerGuide/developerGuide.html"> developerGuide

diff --git a/src/Makefile b/src/Makefile index ed7bd4c..7dfc878 100644 --- a/src/Makefile +++ b/src/Makefile @@ -12,6 +12,7 @@ INC += pv/pvaClient.h INC += pv/pvaClientMultiChannel.h LIBSRCS += pvaClient.cpp +LIBSRCS += pvaClientData.cpp LIBSRCS += pvaClientPutData.cpp LIBSRCS += pvaClientGetData.cpp LIBSRCS += pvaClientMonitorData.cpp diff --git a/src/pv/pvaClient.h b/src/pv/pvaClient.h index 1ada4c7..123aa23 100644 --- a/src/pv/pvaClient.h +++ b/src/pv/pvaClient.h @@ -44,6 +44,8 @@ namespace epics { namespace pvaClient { class PvaClient; typedef std::tr1::shared_ptr PvaClientPtr; +class PvaClientData; +typedef std::tr1::shared_ptr PvaClientDataPtr; class PvaClientGetData; typedef std::tr1::shared_ptr PvaClientGetDataPtr; class PvaClientPutData; @@ -311,11 +313,42 @@ public: PvaClientGetPtr createGet(std::string const & request = "field(value,alarm,timeStamp)"); /** @brief Creates an PvaClientGet. * - * @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData. + * @param pvRequest The syntax of request is defined by the copy facility of pvData. + * @return The interface. * @return The interface. * @throw runtime_error if failure. */ PvaClientGetPtr createGet(epics::pvData::PVStructurePtr const & pvRequest); + /** @brief Get the value as a double. + * + * @param request The syntax of request is defined by the copy facility of pvData. + * @return The value. + * @throw runtime_error if failure. + */ + double getDouble(std::string const & request = "field(value)"); + /** Get the value as a string. + * + * @param request The syntax of request is defined by the copy facility of pvData. + * @return The value. + * @throw runtime_error if failure. + */ + std::string getString(std::string const & request = "field(value)"); + /** @brief Get the value as a double array. + * + * @param request The syntax of request is defined by the copy facility of pvData. + * @return The value. + * @throw runtime_error if failure. + */ + epics::pvData::shared_vector getDoubleArray( + std::string const & request = "field(value)"); + /** @brief Get the value as a string array. + * + * @param request The syntax of request is defined by the copy facility of pvData. + * @return The value. + * @throw runtime_error if failure. + */ + epics::pvData::shared_vector getStringArray( + std::string const & request = "field(value)"); /** @brief create a PvaClientPut. * * Get a cached PvaClientPut or create and connect to a new PvaClientPut. @@ -339,6 +372,44 @@ public: * @return The interface. */ PvaClientPutPtr createPut(epics::pvData::PVStructurePtr const & pvRequest); + /** @brief Put the value as a double. + * + * @param value The new value. + * @param request The syntax of request is defined by the copy facility of pvData. + * @throw runtime_error if failure. + */ + void putDouble(double value,std::string const & request = "field(value)"); + /** @brief Put the value as a string. + * + * @param value The new value. + * @param request The syntax of request is defined by the copy facility of pvData. + * @throw runtime_error if failure. + */ + void putString(std::string const & value,std::string const & request = "field(value)"); + /** @brief Copy the array to the value field. + * + * @param value The new value. + * @param request The syntax of request is defined by the copy facility of pvData. + * @throw runtime_error if failure. + */ + void putDoubleArray( + epics::pvData::shared_vector const & value, + std::string const & request = "field(value)"); + /** @brief Copy array to the value field. + * + * @param value The new value. + * @param request The syntax of request is defined by the copy facility of pvData. + * @throw runtime_error if failure. + */ + void putStringArray( + epics::pvData::shared_vector const & value, + std::string const & request = "field(value)"); + /** @brief Copy array to the value field. + * @param value The data used to update the channel value. + * @param request The request as a string to pass to createRequest. + * @throw runtime_error if failure. + */ + void putStringArray(std::vector const & value,std::string const & request = "field(value)"); /** @brief create a PvaClientPutGet. * * First call createRequest as implemented by pvDataJava and then calls the next method. @@ -490,18 +561,18 @@ public: }; /** - * @brief A class that holds data returned by PvaClientGet or PvaClientPutGet + * @brief A base class for PvaClientGetData, PvaClientPutData, and PvaClientMonitorData. * - * Overview of PvaClientGetData + * Overview of PvaClientData */ -class epicsShareClass PvaClientGetData +class epicsShareClass PvaClientData { public: - POINTER_DEFINITIONS(PvaClientGetData); + POINTER_DEFINITIONS(PvaClientData); /** * @brief Destructor */ - ~PvaClientGetData() {} + ~PvaClientData() {} /** @brief Set a prefix for throw messages. * * This is called by other pvaClient classes. @@ -608,6 +679,44 @@ public: * @return The timeStamp. */ epics::pvData::TimeStamp getTimeStamp(); + /** @brief Factory method for creating an instance of PvaClientData. + * + * NOTE: Not normally called by clients + * @param structure Introspection interface + * @throw runtime_error if failure. + */ + static PvaClientDataPtr create(epics::pvData::StructureConstPtr const & structure); +protected: + PvaClientData(epics::pvData::StructureConstPtr const & structure); + void checkValue(); + std::string messagePrefix; +private: + + epics::pvData::StructureConstPtr structure; + epics::pvData::PVStructurePtr pvStructure; + epics::pvData::BitSetPtr bitSet; + + + epics::pvData::PVFieldPtr pvValue; + epics::pvData::PVAlarm pvAlarm; + epics::pvData::PVTimeStamp pvTimeStamp; + friend class PvaClientGet; + friend class PvaClientPutGet; +}; + +/** + * @brief A class that holds data returned by PvaClientGet or PvaClientPutGet + * + * Overview of PvaClientGetData + */ +class epicsShareClass PvaClientGetData : public PvaClientData +{ +public: + POINTER_DEFINITIONS(PvaClientGetData); + /** + * @brief Destructor + */ + ~PvaClientGetData() {} /** @brief Factory method for creating an instance of PvaClientGetData. * * NOTE: Not normally called by clients @@ -617,15 +726,6 @@ public: static PvaClientGetDataPtr create(epics::pvData::StructureConstPtr const & structure); private: PvaClientGetData(epics::pvData::StructureConstPtr const & structure); - void checkValue(); - epics::pvData::StructureConstPtr structure; - epics::pvData::PVStructurePtr pvStructure; - epics::pvData::BitSetPtr bitSet; - - std::string messagePrefix; - epics::pvData::PVFieldPtr pvValue; - epics::pvData::PVAlarm pvAlarm; - epics::pvData::PVTimeStamp pvTimeStamp; friend class PvaClientGet; friend class PvaClientPutGet; }; @@ -636,7 +736,7 @@ class PvaClientPostHandlerPvt; // private to PvaClientPutData * * Overview of PvaClientPutData */ -class epicsShareClass PvaClientPutData +class epicsShareClass PvaClientPutData : public PvaClientData { public: POINTER_DEFINITIONS(PvaClientPutData); @@ -644,93 +744,6 @@ public: * @brief Destructor */ ~PvaClientPutData() {} - /** @brief Set a prefix for throw messages. - * - * @param value The prefix. - */ - void setMessagePrefix(std::string const & value); - /** @brief Get the structure. - * - * @return The Structure - * @throw runtime_error if failure. - */ - epics::pvData::StructureConstPtr getStructure(); - /** @brief Get the pvStructure. - * - * @return the pvStructure. - * @throw runtime_error if failure. - */ - epics::pvData::PVStructurePtr getPVStructure(); - /** @brief Get the changed BitSet for the pvStructure - * - * This shows which fields have changed values. - * @return The bitSet - * @throw runtime_error if failure. - */ - epics::pvData::BitSetPtr getChangedBitSet(); - /** @brief Show the fields that have changed values. - * - * @param out The stream that shows the changed fields. - * @return The stream that was passed as out. - */ - std::ostream & showChanged(std::ostream & out); - /** - * @brief Is there a top level field named value. - * - * @return The answer. - */ - bool hasValue(); - /** @brief Is the value field a scalar? - * - * @return The answer. - */ - bool isValueScalar(); - /** @brief Is the value field a scalar array? - * @return The answer. - */ - bool isValueScalarArray(); - /** Get the interface to the value field. - * - * @return The interface. an excetion is thrown if a value field does not exist. - */ - epics::pvData::PVFieldPtr getValue(); - /** @brief Get the interface to a scalar value field. - * - * @return The interface for a scalar value field. - * @throw runtime_error if failure. - */ - epics::pvData::PVScalarPtr getScalarValue(); - /** @brief Get the interface to an array value field. - * @return The interface. - * An exception is thown if no array value field. - */ - std::tr1::shared_ptr getArrayValue(); - /** @brief Get the interface to a scalar array value field. - * @return Return the interface. - * @throw runtime_error if failure. - */ - std::tr1::shared_ptr getScalarArrayValue(); - /** @brief Get the value as a double. - * - * If value is not a numeric scalar an exception is thrown. - * @return The value. - */ - double getDouble(); - /** @brief Get the value as a string. - * @return The value. - * @throw runtime_error if failure. - */ - std::string getString(); - /** @brief Get the value as a double array. - * If the value is not a numeric array an exception is thrown. - * @return The value. - */ - epics::pvData::shared_vector getDoubleArray(); - /** @brief Get the value as a string array. - * @return The value. - * @throw runtime_error if failure. - */ - epics::pvData::shared_vector getStringArray(); /** @brief Put the value as a double. * @param value The new value. * An exception is also thrown if the actualy type can cause an overflow. @@ -764,17 +777,9 @@ public: static PvaClientPutDataPtr create(epics::pvData::StructureConstPtr const & structure); private: PvaClientPutData(epics::pvData::StructureConstPtr const &structure); - void checkValue(); void postPut(size_t fieldNumber); - std::vector postHandler; - epics::pvData::StructureConstPtr structure; - epics::pvData::PVStructurePtr pvStructure; - epics::pvData::BitSetPtr bitSet; friend class PvaClientPostHandlerPvt; - - std::string messagePrefix; - epics::pvData::PVFieldPtr pvValue; friend class PvaClientPut; friend class PvaClientPutGet; }; @@ -784,7 +789,7 @@ private: * * Overview of PvaClientMonitorData */ -class epicsShareClass PvaClientMonitorData +class epicsShareClass PvaClientMonitorData : public PvaClientData { public: POINTER_DEFINITIONS(PvaClientMonitorData); @@ -792,27 +797,6 @@ public: * @brief Destructor */ ~PvaClientMonitorData() {} - /** @brief Set a prefix for throw messages. - * @param value The prefix. - */ - void setMessagePrefix(std::string const & value); - /** @brief Get the structure. - * @return The Structure - * @throw runtime_error if failure. - */ - epics::pvData::StructureConstPtr getStructure(); - /** @brief Get the pvStructure. - * @return the pvStructure. - * @throw runtime_error if failure. - */ - epics::pvData::PVStructurePtr getPVStructure(); - /** @brief Get the changed BitSet for the pvStructure, - * - * This shows which fields have changed value. - * @return The bitSet - * @throw runtime_error if failure. - */ - epics::pvData::BitSetPtr getChangedBitSet(); /** @brief Get the overrun BitSet for the pvStructure * This shows which fields have had more than one change. * @return The bitSet @@ -823,111 +807,21 @@ public: * @param out The stream that shows the changed fields. * @return The stream that was passed as out. */ - std::ostream & showChanged(std::ostream & out); - /** @brief Show the fields that have overrun. - * @param out The stream that shows the overrun fields. - * @return The stream that was passed as out - */ std::ostream & showOverrun(std::ostream & out); - /** @brief Is there a top level field named value. - * @return The answer. - */ - bool hasValue(); - /** @brief Is the value field a scalar? - * @return The answer. - */ - bool isValueScalar(); - /** @brief Is the value field a scalar array? - * @return The answer. - */ - bool isValueScalarArray(); - /** @brief Get the interface to the value field. - * @return The interface. an excetion is thrown if a value field does not exist. - */ - epics::pvData::PVFieldPtr getValue(); - /** @brief Get the interface to a scalar value field. - * @return The interface for a scalar value field. - * @throw runtime_error if failure. - * An exception is thown if no scalar value field. - */ - epics::pvData::PVScalarPtr getScalarValue(); - /** @brief Get the interface to an array value field. - * @return The interface. - * @throw runtime_error if failure. - * An exception is thown if no array value field. - */ - std::tr1::shared_ptr getArrayValue(); - /** @brief Get the interface to a scalar array value field. - * @return Return the interface. - * @throw runtime_error if failure. - * An exception is thown if no scalar array value field. - */ - std::tr1::shared_ptr getScalarArrayValue(); - /** @brief Get the value as a double. - * - * If value is not a numeric scalar an exception is thrown. - * @return The value. - */ - double getDouble(); - /** @brief Get the value as a string. - * - * If value is not a scalar an exception is thrown - * @return The value. - * @throw runtime_error if failure. - */ - std::string getString(); - /** @brief Get the value as a double array. - * - * If the value is not a numeric array an exception is thrown. - * @return The value. - * @throw runtime_error if failure. - */ - epics::pvData::shared_vector getDoubleArray(); - /** @brief Get the value as a string array. - * - * If the value is not a string array an exception is thrown. - * @return The value. - * @throw runtime_error if failure. - */ - epics::pvData::shared_vector getStringArray(); - /** @brief Get the alarm. - * - * If the pvStructure as an alarm field it's values are returned. - * If no then alarm shows that not alarm defined. - * @return The alarm. - * @throw runtime_error if failure. - */ - epics::pvData::Alarm getAlarm(); - /** @brief Get the timeStamp. - * - * If the pvStructure has a timeStamp field, it's values are returned. - * If no then all fields are 0. - * @return The timeStamp. - */ - epics::pvData::TimeStamp getTimeStamp(); - /** Factory method for creating an instance of PvaClientGetData. - * NOTE: Not normally called by clients - * @param structure Introspection interface - */ - static PvaClientMonitorDataPtr create(epics::pvData::StructureConstPtr const & structure); /** Put data into PVStructure from monitorElement * NOTE: Not normally called by clients * @param monitorElement the monitorElement that has new data. */ void setData(epics::pvData::MonitorElementPtr const & monitorElement); + /** Factory method for creating an instance of PvaClientGetData. + * NOTE: Not normally called by clients + * @param structure Introspection interface + */ + static PvaClientMonitorDataPtr create(epics::pvData::StructureConstPtr const & structure); private: PvaClientMonitorData(epics::pvData::StructureConstPtr const & structure); - void checkValue(); - - epics::pvData::StructureConstPtr structure; - epics::pvData::PVStructurePtr pvStructure; - epics::pvData::BitSetPtr changedBitSet; epics::pvData::BitSetPtr overrunBitSet; - std::string messagePrefix; - epics::pvData::PVFieldPtr pvValue; - epics::pvData::PVAlarm pvAlarm; - epics::pvData::PVTimeStamp pvTimeStamp; friend class PvaClientMonitor; }; diff --git a/src/pvaClient.cpp b/src/pvaClient.cpp index b95e7ab..5545342 100644 --- a/src/pvaClient.cpp +++ b/src/pvaClient.cpp @@ -18,7 +18,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::pvAccess::ca; diff --git a/src/pvaClientChannel.cpp b/src/pvaClientChannel.cpp index 16338a2..2ee538e 100644 --- a/src/pvaClientChannel.cpp +++ b/src/pvaClientChannel.cpp @@ -18,7 +18,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; @@ -381,6 +380,26 @@ PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & pvRequest) return PvaClientGet::create(yyy,shared_from_this(),pvRequest); } +double PvaClientChannel::getDouble(string const & request) +{ + return get(request)->getData()->getDouble(); +} + +string PvaClientChannel::getString(string const & request) +{ + return get(request)->getData()->getString(); +} + +shared_vector PvaClientChannel::getDoubleArray(string const & request) +{ + return get(request)->getData()->getDoubleArray(); +} + +shared_vector PvaClientChannel::getStringArray(string const & request) +{ + return get(request)->getData()->getStringArray(); +} + PvaClientPutPtr PvaClientChannel::put(string const & request) { @@ -416,6 +435,44 @@ PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest) return PvaClientPut::create(yyy,shared_from_this(),pvRequest); } +void PvaClientChannel::putDouble(double value,string const & request) +{ + PvaClientPutPtr clientPut = put(request); + PvaClientPutDataPtr putData = clientPut->getData(); + putData->putDouble(value); clientPut->put(); +} + +void PvaClientChannel::putString(std::string const & value,string const & request) +{ + PvaClientPutPtr clientPut = put(request); + PvaClientPutDataPtr putData = clientPut->getData(); + putData->putString(value); clientPut->put(); +} + +void PvaClientChannel::putDoubleArray( + shared_vector const & value, + string const & request) +{ + PvaClientPutPtr clientPut = put(request); + PvaClientPutDataPtr putData = clientPut->getData(); + size_t n = value.size(); + shared_vector valueArray(n); + for(size_t i=0; iputDoubleArray(freeze(valueArray)); clientPut->put(); +} + +void PvaClientChannel::putStringArray( + shared_vector const & value, + string const & request) +{ + PvaClientPutPtr clientPut = put(request); + PvaClientPutDataPtr putData = clientPut->getData(); + size_t n = value.size(); + shared_vector valueArray(n); + for(size_t i=0; iputStringArray(freeze(valueArray)); clientPut->put(); +} + PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request) { PVStructurePtr pvRequest = createRequest->createRequest(request); diff --git a/src/pvaClientData.cpp b/src/pvaClientData.cpp new file mode 100644 index 0000000..5db266d --- /dev/null +++ b/src/pvaClientData.cpp @@ -0,0 +1,361 @@ +/* pvaClientData.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvData is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/** + * @author mrk + * @date 2019.04 + */ + +#include +#include + +#include +#include + +#define epicsExportSharedSymbols + +#include + +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace std; + +namespace epics { namespace pvaClient { + + +typedef std::tr1::shared_ptr PVArrayPtr; +static ConvertPtr convert = getConvert(); +static string noStructure("no pvStructure "); +static string noValue("no value field"); +static string noScalar("value is not a scalar"); +static string noArray("value is not an array"); +static string noScalarArray("value is not a scalarArray"); +static string noAlarm("no alarm"); +static string noTimeStamp("no timeStamp"); + +PvaClientDataPtr PvaClientData::create(StructureConstPtr const & structure) +{ + if(PvaClient::getDebug()) cout << "PvaClientData::create\n"; + PvaClientDataPtr epv(new PvaClientData(structure)); + return epv; +} + +PvaClientData::PvaClientData(StructureConstPtr const & structure) +: structure(structure) +{ +} + +void PvaClientData::checkValue() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n"; + if(pvValue) return; + throw std::runtime_error(messagePrefix + noValue); +} + +void PvaClientData::setMessagePrefix(std::string const & value) +{ + messagePrefix = value + " "; +} + +StructureConstPtr PvaClientData::getStructure() +{ + return structure; +} + +PVStructurePtr PvaClientData::getPVStructure() +{ + if(pvStructure) return pvStructure; + throw std::runtime_error(messagePrefix + noStructure); +} + +BitSetPtr PvaClientData::getChangedBitSet() +{ + if(bitSet)return bitSet; + throw std::runtime_error(messagePrefix + noStructure); +} + +std::ostream & PvaClientData::showChanged(std::ostream & out) +{ + if(!bitSet) throw std::runtime_error(messagePrefix + noStructure); + size_t nextSet = bitSet->nextSetBit(0); + PVFieldPtr pvField; + while(nextSet!=string::npos) { + if(nextSet==0) { + pvField = pvStructure; + } else { + pvField = pvStructure->getSubField(nextSet); + } + string name = pvField->getFullName(); + out << name << " = " << pvField << endl; + nextSet = bitSet->nextSetBit(nextSet+1); + } + return out; +} + +void PvaClientData::setData( + PVStructurePtr const & pvStructureFrom, + BitSetPtr const & bitSetFrom) +{ + if(PvaClient::getDebug()) cout << "PvaClientData::setData\n"; + pvStructure = pvStructureFrom; + bitSet = bitSetFrom; + pvValue = pvStructure->getSubField("value"); +} + +bool PvaClientData::hasValue() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n"; + if(!pvValue) return false; + return true; +} + +bool PvaClientData::isValueScalar() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalar\n"; + if(!pvValue) return false; + if(pvValue->getField()->getType()==scalar) return true; + return false; +} + +bool PvaClientData::isValueScalarArray() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalarArray\n"; + if(!pvValue) return false; + if(pvValue->getField()->getType()==scalarArray) return true; + return false; +} + +PVFieldPtr PvaClientData::getValue() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getValue\n"; + checkValue(); + return pvValue; +} + +PVScalarPtr PvaClientData::getScalarValue() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getScalarValue\n"; + checkValue(); + if(pvValue->getField()->getType()!=scalar) { + throw std::runtime_error(messagePrefix + noScalar); + } + return pvStructure->getSubField("value"); +} + +PVArrayPtr PvaClientData::getArrayValue() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getArrayValue\n"; + checkValue(); + Type type = pvValue->getField()->getType(); + if(type!=scalarArray && type!=structureArray && type!=unionArray) { + throw std::runtime_error(messagePrefix + noArray); + } + return pvStructure->getSubField("value"); +} + +PVScalarArrayPtr PvaClientData::getScalarArrayValue() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getScalarArrayValue\n"; + checkValue(); + Type type = pvValue->getField()->getType(); + if(type!=scalarArray) { + throw std::runtime_error(messagePrefix + noScalarArray); + } + return pvStructure->getSubField("value"); +} + +double PvaClientData::getDouble() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n"; + PVScalarPtr pvScalar; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalar) pvScalar = static_pointer_cast(pvValue); + } + if(!pvScalar) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::getDouble() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalar) { + pvScalar = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalar) { + throw std::logic_error( + "PvaClientData::getDouble() did not find a scalar field"); + } + ScalarType scalarType = pvScalar->getScalar()->getScalarType(); + if(scalarType==pvDouble) { + PVDoublePtr pvDouble = static_pointer_cast(pvScalar); + return pvDouble->get(); + } + if(!ScalarTypeFunc::isNumeric(scalarType)) { + throw std::logic_error( + "PvaClientData::getDouble() did not find a numeric scalar field"); + } + return convert->toDouble(pvScalar); +} + +string PvaClientData::getString() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getString\n"; + PVScalarPtr pvScalar; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalar) pvScalar = static_pointer_cast(pvValue); + } + if(!pvScalar) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::getString() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalar) { + pvScalar = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalar) { + throw std::logic_error( + "PvaClientData::getString() did not find a scalar field"); + } + return convert->toString(pvScalar); +} + +shared_vector PvaClientData::getDoubleArray() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n"; + PVScalarArrayPtr pvScalarArray; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalarArray) { + pvScalarArray = static_pointer_cast(pvValue); + } + } + if(!pvScalarArray) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::getDoubleArray() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalarArray) { + pvScalarArray = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalarArray) { + throw std::logic_error( + "PvaClientData::getDoubleArray() did not find a scalarArray field"); + } + ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); + if(!ScalarTypeFunc::isNumeric(scalarType)) { + throw std::logic_error( + "PvaClientData::getDoubleArray() did not find a numeric scalarArray field"); + } + shared_vector retValue; + pvScalarArray->getAs(retValue); + return retValue; +} + +shared_vector PvaClientData::getStringArray() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n"; + PVScalarArrayPtr pvScalarArray; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalarArray) { + pvScalarArray = static_pointer_cast(pvValue); + } + } + if(!pvScalarArray) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::getStringArray() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalarArray) { + pvScalarArray = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalarArray) { + throw std::logic_error( + "PvaClientData::getStringArray() did not find a scalarArray field"); + } + shared_vector retValue; + pvScalarArray->getAs(retValue); + return retValue; +} + +Alarm PvaClientData::getAlarm() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getAlarm\n"; + if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure); + PVStructurePtr pvs = pvStructure->getSubField("alarm"); + if(!pvs) throw std::runtime_error(messagePrefix + noAlarm); + pvAlarm.attach(pvs); + if(pvAlarm.isAttached()) { + Alarm alarm; + pvAlarm.get(alarm); + pvAlarm.detach(); + return alarm; + } + throw std::runtime_error(messagePrefix + noAlarm); +} + +TimeStamp PvaClientData::getTimeStamp() +{ + if(PvaClient::getDebug()) cout << "PvaClientData::getTimeStamp\n"; + if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure); + PVStructurePtr pvs = pvStructure->getSubField("timeStamp"); + if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp); + pvTimeStamp.attach(pvs); + if(pvTimeStamp.isAttached()) { + TimeStamp timeStamp; + pvTimeStamp.get(timeStamp); + pvTimeStamp.detach(); + return timeStamp; + } + throw std::runtime_error(messagePrefix + noTimeStamp); +} + +}} diff --git a/src/pvaClientGet.cpp b/src/pvaClientGet.cpp index c93fc0f..0b7398d 100644 --- a/src/pvaClientGet.cpp +++ b/src/pvaClientGet.cpp @@ -15,7 +15,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; @@ -99,18 +98,16 @@ PvaClientGet::PvaClientGet( getState(getIdle) { if(PvaClient::getDebug()) { - cout << "PvaClientGet::PvaClientGet::PvaClientGet" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::PvaClientGet channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } } PvaClientGet::~PvaClientGet() { if(PvaClient::getDebug()) { - cout<< "PvaClientGet::~PvaClientGet" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout<< "PvaClientGet::~PvaClientGet channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } } @@ -118,9 +115,8 @@ PvaClientGet::~PvaClientGet() void PvaClientGet::checkConnectState() { if(PvaClient::getDebug()) { - cout << "PvaClientGet::checkConnectState" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::checkConnectState channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } if(!pvaClientChannel->getChannel()->isConnected()) { string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() @@ -159,10 +155,10 @@ void PvaClientGet::channelGetConnect( StructureConstPtr const & structure) { if(PvaClient::getDebug()) { - cout << "PvaClientGet::channelGetConnect" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() + cout << "PvaClientGet::channelGetConnect channelName " + << pvaClientChannel->getChannel()->getChannelName() << " status.isOK " << (status.isOK() ? "true" : "false") - << endl; + << "\n"; } { Lock xx(mutex); @@ -196,10 +192,10 @@ void PvaClientGet::getDone( BitSetPtr const & bitSet) { if(PvaClient::getDebug()) { - cout << "PvaClientGet::getDone" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() + cout << "PvaClientGet::getDone channelName " + << pvaClientChannel->getChannel()->getChannelName() << " status.isOK " << (status.isOK() ? "true" : "false") - << endl; + << "\n"; } { Lock xx(mutex); @@ -219,9 +215,8 @@ void PvaClientGet::getDone( void PvaClientGet::connect() { if(PvaClient::getDebug()) { - cout << "PvaClientGet::connect" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::connect channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } issueConnect(); Status status = waitConnect(); @@ -234,9 +229,8 @@ void PvaClientGet::connect() void PvaClientGet::issueConnect() { if(PvaClient::getDebug()) { - cout << "PvaClientGet::issueConnect" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::issueConnect channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } if(connectState!=connectIdle) { string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() @@ -251,9 +245,8 @@ void PvaClientGet::issueConnect() Status PvaClientGet::waitConnect() { if(PvaClient::getDebug()) { - cout << "PvaClientGet::waitConnect" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::waitConnect channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } { Lock xx(mutex); @@ -275,9 +268,8 @@ Status PvaClientGet::waitConnect() void PvaClientGet::get() { if(PvaClient::getDebug()) { - cout << "PvaClientGet::get" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::get channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } issueGet(); Status status = waitGet(); @@ -290,9 +282,8 @@ void PvaClientGet::get() void PvaClientGet::issueGet() { if(PvaClient::getDebug()) { - cout << "PvaClientGet::issueGet" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::issueGet channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } if(connectState==connectIdle) connect(); if(getState==getActive) { @@ -307,9 +298,8 @@ void PvaClientGet::issueGet() Status PvaClientGet::waitGet() { if(PvaClient::getDebug()) { - cout << "PvaClientGet::waitGet" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::waitGet channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } { Lock xx(mutex); @@ -330,9 +320,8 @@ Status PvaClientGet::waitGet() PvaClientGetDataPtr PvaClientGet::getData() { if(PvaClient::getDebug()) { - cout<< "PvaClientGet::getData" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout<< "PvaClientGet::getData channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } checkConnectState(); if(getState==getIdle) get(); @@ -342,9 +331,8 @@ PvaClientGetDataPtr PvaClientGet::getData() void PvaClientGet::setRequester(PvaClientGetRequesterPtr const & pvaClientGetRequester) { if(PvaClient::getDebug()) { - cout << "PvaClientGet::setRequester" - << " channelName " << pvaClientChannel->getChannel()->getChannelName() - << endl; + cout << "PvaClientGet::setRequester channelName " + << pvaClientChannel->getChannel()->getChannelName() << "\n"; } this->pvaClientGetRequester = pvaClientGetRequester; } diff --git a/src/pvaClientGetData.cpp b/src/pvaClientGetData.cpp index 6da72db..e253cb9 100644 --- a/src/pvaClientGetData.cpp +++ b/src/pvaClientGetData.cpp @@ -19,7 +19,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; @@ -27,214 +26,15 @@ using namespace std; namespace epics { namespace pvaClient { -typedef std::tr1::shared_ptr PVArrayPtr; -static ConvertPtr convert = getConvert(); -static string noStructure("no pvStructure "); -static string noValue("no value field"); -static string noScalar("value is not a scalar"); -static string notCompatibleScalar("value is not a compatible scalar"); -static string noArray("value is not an array"); -static string noScalarArray("value is not a scalarArray"); -static string notDoubleArray("value is not a doubleArray"); -static string notStringArray("value is not a stringArray"); -static string noAlarm("no alarm"); -static string noTimeStamp("no timeStamp"); - PvaClientGetDataPtr PvaClientGetData::create(StructureConstPtr const & structure) { - if(PvaClient::getDebug()) { - cout << "PvaClientGetData::create" - << endl; - } + if(PvaClient::getDebug()) cout << "PvaClientGetData::create\n"; PvaClientGetDataPtr epv(new PvaClientGetData(structure)); return epv; } PvaClientGetData::PvaClientGetData(StructureConstPtr const & structure) -: structure(structure), - pvStructure(getPVDataCreate()->createPVStructure(structure)), - bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields()))) -{ - messagePrefix = ""; - pvValue = pvStructure->getSubField("value"); -} - -void PvaClientGetData::checkValue() -{ - if(PvaClient::getDebug()) { - cout << "PvaClientGetData::checkValue" - << endl; - } - if(pvValue) return; - throw std::runtime_error(messagePrefix + noValue); -} - -void PvaClientGetData::setMessagePrefix(std::string const & value) -{ - messagePrefix = value + " "; -} - -StructureConstPtr PvaClientGetData::getStructure() -{return structure;} - -PVStructurePtr PvaClientGetData::getPVStructure() -{ - if(pvStructure) return pvStructure; - throw std::runtime_error(messagePrefix + noStructure); -} - -BitSetPtr PvaClientGetData::getChangedBitSet() -{ - if(bitSet)return bitSet; - throw std::runtime_error(messagePrefix + noStructure); -} - -std::ostream & PvaClientGetData::showChanged(std::ostream & out) -{ - if(!bitSet) throw std::runtime_error(messagePrefix + noStructure); - size_t nextSet = bitSet->nextSetBit(0); - PVFieldPtr pvField; - while(nextSet!=string::npos) { - if(nextSet==0) { - pvField = pvStructure; - } else { - pvField = pvStructure->getSubField(nextSet); - } - string name = pvField->getFullName(); - out << name << " = " << pvField << endl; - nextSet = bitSet->nextSetBit(nextSet+1); - } - return out; -} - -void PvaClientGetData::setData( - PVStructurePtr const & pvStructureFrom, - BitSetPtr const & bitSetFrom) -{ - if(PvaClient::getDebug()) { - cout << "PvaClientGetData::setData" - << endl; - } - pvStructure = pvStructureFrom; - bitSet = bitSetFrom; - pvValue = pvStructure->getSubField("value"); -} - -bool PvaClientGetData::hasValue() -{ - if(!pvValue) return false; - return true; -} - -bool PvaClientGetData::isValueScalar() -{ - if(!pvValue) return false; - if(pvValue->getField()->getType()==scalar) return true; - return false; -} - -bool PvaClientGetData::isValueScalarArray() -{ - if(!pvValue) return false; - if(pvValue->getField()->getType()==scalarArray) return true; - return false; -} - -PVFieldPtr PvaClientGetData::getValue() -{ - checkValue(); - return pvValue; -} - -PVScalarPtr PvaClientGetData::getScalarValue() -{ - checkValue(); - PVScalarPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + noScalar); - return pv; -} - -PVArrayPtr PvaClientGetData::getArrayValue() -{ - checkValue(); - PVArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + noArray); - return pv; -} - -PVScalarArrayPtr PvaClientGetData::getScalarArrayValue() -{ - checkValue(); - PVScalarArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + noScalarArray); - return pv; -} - -double PvaClientGetData::getDouble() -{ - PVScalarPtr pvScalar = getScalarValue(); - ScalarType scalarType = pvScalar->getScalar()->getScalarType(); - if(scalarType==pvDouble) { - PVDoublePtr pvDouble = static_pointer_cast(pvScalar); - return pvDouble->get(); - } - if(!ScalarTypeFunc::isNumeric(scalarType)) { - throw std::runtime_error(messagePrefix + notCompatibleScalar); - } - return convert->toDouble(pvScalar); -} - -string PvaClientGetData::getString() -{ - PVScalarPtr pvScalar = getScalarValue(); - return convert->toString(pvScalar); -} - -shared_vector PvaClientGetData::getDoubleArray() -{ - checkValue(); - PVDoubleArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + notDoubleArray); - return pv->view(); -} - -shared_vector PvaClientGetData::getStringArray() -{ - checkValue(); - PVStringArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + notStringArray); - return pv->view(); -} - - -Alarm PvaClientGetData::getAlarm() -{ - if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure); - PVStructurePtr pvs = pvStructure->getSubField("alarm"); - if(!pvs) throw std::runtime_error(messagePrefix + noAlarm); - pvAlarm.attach(pvs); - if(pvAlarm.isAttached()) { - Alarm alarm; - pvAlarm.get(alarm); - pvAlarm.detach(); - return alarm; - } - throw std::runtime_error(messagePrefix + noAlarm); -} - -TimeStamp PvaClientGetData::getTimeStamp() -{ - if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure); - PVStructurePtr pvs = pvStructure->getSubField("timeStamp"); - if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp); - pvTimeStamp.attach(pvs); - if(pvTimeStamp.isAttached()) { - TimeStamp timeStamp; - pvTimeStamp.get(timeStamp); - pvTimeStamp.detach(); - return timeStamp; - } - throw std::runtime_error(messagePrefix + noTimeStamp); -} +: PvaClientData(structure) +{} }} diff --git a/src/pvaClientMonitor.cpp b/src/pvaClientMonitor.cpp index 246f630..e253366 100644 --- a/src/pvaClientMonitor.cpp +++ b/src/pvaClientMonitor.cpp @@ -17,8 +17,6 @@ #include -using std::tr1::static_pointer_cast; -using std::tr1::dynamic_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; diff --git a/src/pvaClientMonitorData.cpp b/src/pvaClientMonitorData.cpp index 03b8bce..7c5d1da 100644 --- a/src/pvaClientMonitorData.cpp +++ b/src/pvaClientMonitorData.cpp @@ -19,7 +19,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; @@ -53,43 +52,16 @@ PvaClientMonitorDataPtr PvaClientMonitorData::create(StructureConstPtr const & s } PvaClientMonitorData::PvaClientMonitorData(StructureConstPtr const & structure) -: structure(structure) +: PvaClientData(structure) { - messagePrefix = ""; } void PvaClientMonitorData::setData(MonitorElementPtr const & monitorElement) { - pvStructure = monitorElement->pvStructurePtr; - changedBitSet = monitorElement->changedBitSet; + PVStructurePtr pvStructure = monitorElement->pvStructurePtr; + BitSetPtr changedBitSet = monitorElement->changedBitSet; + PvaClientData::setData(pvStructure,changedBitSet); overrunBitSet = monitorElement->overrunBitSet; - pvValue = pvStructure->getSubField("value"); -} - -void PvaClientMonitorData::checkValue() -{ - if(pvValue) return; - throw std::runtime_error(messagePrefix + noValue); -} - -void PvaClientMonitorData::setMessagePrefix(std::string const & value) -{ - messagePrefix = value + " "; -} - -StructureConstPtr PvaClientMonitorData::getStructure() -{return structure;} - -PVStructurePtr PvaClientMonitorData::getPVStructure() -{ - if(pvStructure) return pvStructure; - throw std::runtime_error(messagePrefix + noStructure); -} - -BitSetPtr PvaClientMonitorData::getChangedBitSet() -{ - if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure); - return changedBitSet; } BitSetPtr PvaClientMonitorData::getOverrunBitSet() @@ -98,24 +70,6 @@ BitSetPtr PvaClientMonitorData::getOverrunBitSet() return overrunBitSet; } -std::ostream & PvaClientMonitorData::showChanged(std::ostream & out) -{ - if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure); - size_t nextSet = changedBitSet->nextSetBit(0); - PVFieldPtr pvField; - while(nextSet!=string::npos) { - if(nextSet==0) { - pvField = pvStructure; - } else { - pvField = pvStructure->getSubField(nextSet); - } - string name = pvField->getFullName(); - out << name << " = " << pvField << endl; - nextSet = changedBitSet->nextSetBit(nextSet+1); - } - return out; -} - std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out) { if(!overrunBitSet) throw std::runtime_error(messagePrefix + noStructure); @@ -123,9 +77,9 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out) PVFieldPtr pvField; while(nextSet!=string::npos) { if(nextSet==0) { - pvField = pvStructure; + pvField = getPVStructure(); } else { - pvField = pvStructure->getSubField(nextSet); + pvField = getPVStructure()->getSubField(nextSet); } string name = pvField->getFullName(); out << name << " = " << pvField << endl; @@ -134,135 +88,4 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out) return out; } -bool PvaClientMonitorData::hasValue() -{ - if(!pvValue) return false; - return true; -} - -bool PvaClientMonitorData::isValueScalar() -{ - if(!pvValue) return false; - if(pvValue->getField()->getType()==scalar) return true; - return false; -} - -bool PvaClientMonitorData::isValueScalarArray() -{ - if(!pvValue) return false; - if(pvValue->getField()->getType()==scalarArray) return true; - return false; -} - -PVFieldPtr PvaClientMonitorData::getValue() -{ - checkValue(); - return pvValue; -} - -PVScalarPtr PvaClientMonitorData::getScalarValue() -{ - checkValue(); - PVScalarPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + noScalar); - } - return pv; -} - -PVArrayPtr PvaClientMonitorData::getArrayValue() -{ - checkValue(); - PVArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + noArray); - } - return pv; -} - -PVScalarArrayPtr PvaClientMonitorData::getScalarArrayValue() -{ - checkValue(); - PVScalarArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + noScalarArray); - } - return pv; -} - -double PvaClientMonitorData::getDouble() -{ - PVScalarPtr pvScalar = getScalarValue(); - ScalarType scalarType = pvScalar->getScalar()->getScalarType(); - if(scalarType==pvDouble) { - PVDoublePtr pvDouble = static_pointer_cast(pvScalar); - return pvDouble->get(); - } - if(!ScalarTypeFunc::isNumeric(scalarType)) { - throw std::runtime_error(messagePrefix + notCompatibleScalar); - } - return convert->toDouble(pvScalar); -} - -string PvaClientMonitorData::getString() -{ - PVScalarPtr pvScalar = getScalarValue(); - return convert->toString(pvScalar); -} - -shared_vector PvaClientMonitorData::getDoubleArray() -{ - checkValue(); - PVDoubleArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + notDoubleArray); - } - return pv->view(); -} - -shared_vector PvaClientMonitorData::getStringArray() -{ - checkValue(); - PVStringArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + notStringArray); - } - return pv->view(); - -} - -Alarm PvaClientMonitorData::getAlarm() -{ - if(!pvStructure) { - throw std::runtime_error(messagePrefix + noAlarm); - } - PVStructurePtr pvs = pvStructure->getSubField("alarm"); - if(!pvs) throw std::runtime_error(messagePrefix + noAlarm); - pvAlarm.attach(pvs); - if(pvAlarm.isAttached()) { - Alarm alarm; - pvAlarm.get(alarm); - pvAlarm.detach(); - return alarm; - } - throw std::runtime_error(messagePrefix + noAlarm); -} - -TimeStamp PvaClientMonitorData::getTimeStamp() -{ - if(!pvStructure) { - throw std::runtime_error(messagePrefix + noTimeStamp); - } - PVStructurePtr pvs = pvStructure->getSubField("timeStamp"); - if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp); - pvTimeStamp.attach(pvs); - if(pvTimeStamp.isAttached()) { - TimeStamp timeStamp; - pvTimeStamp.get(timeStamp); - pvTimeStamp.detach(); - return timeStamp; - } - throw std::runtime_error(messagePrefix + noTimeStamp); -} - }} diff --git a/src/pvaClientMultiChannel.cpp b/src/pvaClientMultiChannel.cpp index 33e6481..932dc8a 100644 --- a/src/pvaClientMultiChannel.cpp +++ b/src/pvaClientMultiChannel.cpp @@ -17,9 +17,6 @@ #include - - -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; diff --git a/src/pvaClientMultiGetDouble.cpp b/src/pvaClientMultiGetDouble.cpp index 9b803d7..3683363 100644 --- a/src/pvaClientMultiGetDouble.cpp +++ b/src/pvaClientMultiGetDouble.cpp @@ -16,7 +16,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::nt; diff --git a/src/pvaClientMultiMonitorDouble.cpp b/src/pvaClientMultiMonitorDouble.cpp index 95dda92..dafdef7 100644 --- a/src/pvaClientMultiMonitorDouble.cpp +++ b/src/pvaClientMultiMonitorDouble.cpp @@ -16,7 +16,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::nt; diff --git a/src/pvaClientMultiPutDouble.cpp b/src/pvaClientMultiPutDouble.cpp index 0169641..d61b640 100644 --- a/src/pvaClientMultiPutDouble.cpp +++ b/src/pvaClientMultiPutDouble.cpp @@ -16,7 +16,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::nt; diff --git a/src/pvaClientNTMultiData.cpp b/src/pvaClientNTMultiData.cpp index c4ca69e..7e5de88 100644 --- a/src/pvaClientNTMultiData.cpp +++ b/src/pvaClientNTMultiData.cpp @@ -15,7 +15,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::nt; diff --git a/src/pvaClientNTMultiGet.cpp b/src/pvaClientNTMultiGet.cpp index 0f77ce1..6641e95 100644 --- a/src/pvaClientNTMultiGet.cpp +++ b/src/pvaClientNTMultiGet.cpp @@ -15,7 +15,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::nt; diff --git a/src/pvaClientNTMultiMonitor.cpp b/src/pvaClientNTMultiMonitor.cpp index 126476a..a095936 100644 --- a/src/pvaClientNTMultiMonitor.cpp +++ b/src/pvaClientNTMultiMonitor.cpp @@ -18,7 +18,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::nt; diff --git a/src/pvaClientNTMultiPut.cpp b/src/pvaClientNTMultiPut.cpp index cd18a6e..a965026 100644 --- a/src/pvaClientNTMultiPut.cpp +++ b/src/pvaClientNTMultiPut.cpp @@ -17,7 +17,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::nt; diff --git a/src/pvaClientProcess.cpp b/src/pvaClientProcess.cpp index e8b7d06..87412cf 100644 --- a/src/pvaClientProcess.cpp +++ b/src/pvaClientProcess.cpp @@ -15,7 +15,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; diff --git a/src/pvaClientPut.cpp b/src/pvaClientPut.cpp index c42ba19..f046263 100644 --- a/src/pvaClientPut.cpp +++ b/src/pvaClientPut.cpp @@ -15,7 +15,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; diff --git a/src/pvaClientPutData.cpp b/src/pvaClientPutData.cpp index 94ad0a8..e1cf019 100644 --- a/src/pvaClientPutData.cpp +++ b/src/pvaClientPutData.cpp @@ -25,6 +25,10 @@ using namespace epics::pvAccess; using namespace std; namespace epics { namespace pvaClient { +static ConvertPtr convert = getConvert(); +static string notCompatibleScalar("value is not a compatible scalar"); +static string notDoubleArray("value is not a doubleArray"); +static string notStringArray("value is not a stringArray"); class PvaClientPostHandlerPvt: public PostHandler { @@ -36,28 +40,21 @@ public: void postPut() { putData->postPut(fieldNumber);} }; -typedef std::tr1::shared_ptr PVArrayPtr; -static ConvertPtr convert = getConvert(); -static string noValue("no value field"); -static string notScalar("value is not a scalar"); -static string notCompatibleScalar("value is not a compatible scalar"); -static string notArray("value is not an array"); -static string notScalarArray("value is not a scalarArray"); -static string notDoubleArray("value is not a doubleArray"); -static string notStringArray("value is not a stringArray"); PvaClientPutDataPtr PvaClientPutData::create(StructureConstPtr const & structure) { + if(PvaClient::getDebug()) cout << "PvaClientPutData::create\n"; PvaClientPutDataPtr epv(new PvaClientPutData(structure)); return epv; } PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure) -: structure(structure), - pvStructure(getPVDataCreate()->createPVStructure(structure)), - bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields()))) +: PvaClientData(structure) { - messagePrefix = ""; + if(PvaClient::getDebug()) cout << "PvaClientPutData::PvaClientPutData\n"; + PVStructurePtr pvStructure(getPVDataCreate()->createPVStructure(structure)); + BitSetPtr bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields()))); + setData(pvStructure,bitSet); size_t nfields = pvStructure->getNumberFields(); postHandler.resize(nfields); PVFieldPtr pvField; @@ -71,145 +68,40 @@ PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure) } pvField->setPostHandler(postHandler[i]); } - pvValue = pvStructure->getSubField("value"); } -void PvaClientPutData::checkValue() -{ - if(pvValue) return; - throw std::runtime_error(messagePrefix + noValue); -} - -void PvaClientPutData::postPut(size_t fieldNumber) -{ - bitSet->set(fieldNumber); -} - -void PvaClientPutData::setMessagePrefix(std::string const & value) -{ - messagePrefix = value + " "; -} - -StructureConstPtr PvaClientPutData::getStructure() -{return structure;} - -PVStructurePtr PvaClientPutData::getPVStructure() -{return pvStructure;} - -BitSetPtr PvaClientPutData::getChangedBitSet() -{return bitSet;} - -std::ostream & PvaClientPutData::showChanged(std::ostream & out) -{ - size_t nextSet = bitSet->nextSetBit(0); - PVFieldPtr pvField; - while(nextSet!=string::npos) { - if(nextSet==0) { - pvField = pvStructure; - } else { - pvField = pvStructure->getSubField(nextSet); - } - string name = pvField->getFullName(); - out << name << " = " << pvField << endl; - nextSet = bitSet->nextSetBit(nextSet+1); - } - return out; -} - -bool PvaClientPutData::hasValue() -{ - if(!pvValue) return false; - return true; -} - -bool PvaClientPutData::isValueScalar() -{ - if(!pvValue) return false; - if(pvValue->getField()->getType()==scalar) return true; - return false; -} - -bool PvaClientPutData::isValueScalarArray() -{ - if(!pvValue) return false; - if(pvValue->getField()->getType()==scalarArray) return true; - return false; -} - -PVFieldPtr PvaClientPutData::getValue() -{ - checkValue(); - return pvValue; -} - -PVScalarPtr PvaClientPutData::getScalarValue() -{ - checkValue(); - PVScalarPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + notScalar); - return pv; -} - -PVArrayPtr PvaClientPutData::getArrayValue() -{ - checkValue(); - PVArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + notArray); - return pv; -} - -PVScalarArrayPtr PvaClientPutData::getScalarArrayValue() -{ - checkValue(); - PVScalarArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) throw std::runtime_error(messagePrefix + notScalarArray); - return pv; -} - -double PvaClientPutData::getDouble() -{ - PVScalarPtr pvScalar = getScalarValue(); - ScalarType scalarType = pvScalar->getScalar()->getScalarType(); - if(scalarType==pvDouble) { - PVDoublePtr pvDouble = static_pointer_cast(pvScalar); - return pvDouble->get(); - } - if(!ScalarTypeFunc::isNumeric(scalarType)) { - throw std::runtime_error(messagePrefix + notCompatibleScalar); - } - return convert->toDouble(pvScalar); -} - -string PvaClientPutData::getString() -{ - PVScalarPtr pvScalar = getScalarValue(); - return convert->toString(pvScalar); -} - -shared_vector PvaClientPutData::getDoubleArray() -{ - checkValue(); - PVDoubleArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + notDoubleArray); - } - return pv->view(); -} - -shared_vector PvaClientPutData::getStringArray() -{ - checkValue(); - PVStringArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + notStringArray); - } - return pv->view(); - -} void PvaClientPutData::putDouble(double value) { - PVScalarPtr pvScalar = getScalarValue(); + if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n"; + PVScalarPtr pvScalar; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalar) pvScalar = static_pointer_cast(pvValue); + } + if(!pvScalar) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::putDouble() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalar) { + pvScalar = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalar) { + throw std::logic_error( + "PvaClientData::putDouble() did not find a scalar field"); + } ScalarType scalarType = pvScalar->getScalar()->getScalarType(); if(scalarType==pvDouble) { PVDoublePtr pvDouble = static_pointer_cast(pvScalar); @@ -217,47 +109,138 @@ void PvaClientPutData::putDouble(double value) return; } if(!ScalarTypeFunc::isNumeric(scalarType)) { - throw std::runtime_error(messagePrefix + notCompatibleScalar); + throw std::logic_error( + "PvaClientData::putDouble() did not find a numeric scalar field"); } convert->fromDouble(pvScalar,value); } void PvaClientPutData::putString(std::string const & value) { - PVScalarPtr pvScalar = getScalarValue(); + if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n"; + PVScalarPtr pvScalar; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalar) pvScalar = static_pointer_cast(pvValue); + } + if(!pvScalar) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::putString() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalar) { + pvScalar = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalar) { + throw std::logic_error( + "PvaClientData::putString() did not find a scalar field"); + } convert->fromString(pvScalar,value); } - - void PvaClientPutData::putDoubleArray(shared_vector const & value) { - checkValue(); - PVDoubleArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + notDoubleArray); + if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n"; + PVScalarArrayPtr pvScalarArray; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalarArray) { + pvScalarArray = static_pointer_cast(pvValue); + } } - pv->replace(value); + if(!pvScalarArray) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::putDoubleArray() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalarArray) { + PVScalarArrayPtr pvScalarArray = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalarArray) { + throw std::logic_error( + "PvaClientData::putDoubleArray() did not find a scalarArray field"); + } + ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); + if(!ScalarTypeFunc::isNumeric(scalarType)) { + throw std::logic_error( + "PvaClientData::putDoubleArray() did not find a numeric scalarArray field"); + } + pvScalarArray->putFrom(value); } void PvaClientPutData::putStringArray(shared_vector const & value) { - checkValue(); - PVStringArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + notStringArray); + if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n"; + PVScalarArrayPtr pvScalarArray; + PVStructurePtr pvStructure = getPVStructure(); + PVFieldPtr pvValue = pvStructure->getSubField("value"); + if(pvValue) { + Type type = pvValue->getField()->getType(); + if(type==scalarArray) { + pvScalarArray = static_pointer_cast(pvValue); + } } - pv->replace(value); + if(!pvScalarArray) { + while(true) { + const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); + if(fieldPtrArray.size()!=1) { + throw std::logic_error( + "PvaClientData::putStringArray() pvRequest for multiple fields"); + } + PVFieldPtr pvField(fieldPtrArray[0]); + Type type = pvField->getField()->getType(); + if(type==scalarArray) { + pvScalarArray = static_pointer_cast(pvField); + break; + } + if(pvField->getField()->getType()!=epics::pvData::structure) break; + pvStructure = static_pointer_cast(pvField); + } + } + if(!pvScalarArray) { + throw std::logic_error( + "PvaClientData::putStringArray() did not find a scalarArray field"); + } + pvScalarArray->putFrom(value); + return; } -void PvaClientPutData::putStringArray(std::vector const & value) +void PvaClientPutData::putStringArray(std::vector const & value) { - checkValue(); - PVScalarArrayPtr pv = pvStructure->getSubField("value"); - if(!pv) { - throw std::runtime_error(messagePrefix + notScalarArray); - } - convert->fromStringArray(pv,0,value.size(),value,0); + size_t length = value.size(); + shared_vector val(length); + for(size_t i=0; i < length; ++i) val[i] = value[i]; + putStringArray(freeze(val)); + return; } +void PvaClientPutData::postPut(size_t fieldNumber) +{ + if(PvaClient::getDebug()) cout << "PvaClientPutData::postPut\n"; + getChangedBitSet()->set(fieldNumber); +} + + }} diff --git a/src/pvaClientPutGet.cpp b/src/pvaClientPutGet.cpp index bde22a3..a370c07 100644 --- a/src/pvaClientPutGet.cpp +++ b/src/pvaClientPutGet.cpp @@ -14,7 +14,6 @@ #include -using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; @@ -174,7 +173,7 @@ void PvaClientPutGet::channelPutGetConnect( << " channelName " << pvaClientChannel->getChannel()->getChannelName() << " status.isOK " << (status.isOK() ? "true" : "false") << endl; - } + } { Lock xx(mutex); this->channelPutGet = channelPutGet; @@ -215,14 +214,13 @@ void PvaClientPutGet::putGetDone( << " status.isOK " << (status.isOK() ? "true" : "false") << endl; } - channelPutGetStatus = status; - putGetState = putGetComplete; - if(status.isOK()) { - PVStructurePtr pvs = pvaClientGetData->getPVStructure(); - pvs->copyUnchecked(*getPVStructure,*getChangedBitSet); - BitSetPtr bs = pvaClientGetData->getChangedBitSet(); - bs->clear(); - *bs |= *getChangedBitSet; + { + Lock xx(mutex); + channelPutGetStatus = status; + putGetState = putGetComplete; + if(status.isOK()) { + pvaClientGetData->setData(getPVStructure,getChangedBitSet); + } } PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); if(req) { @@ -243,14 +241,17 @@ void PvaClientPutGet::getPutDone( << " status.isOK " << (status.isOK() ? "true" : "false") << endl; } - channelPutGetStatus = status; - putGetState = putGetComplete; - if(status.isOK()) { - PVStructurePtr pvs = pvaClientPutData->getPVStructure(); - pvs->copyUnchecked(*putPVStructure,*putBitSet); - BitSetPtr bs = pvaClientPutData->getChangedBitSet(); - bs->clear(); - *bs |= *putBitSet; + { + Lock xx(mutex); + channelPutGetStatus = status; + putGetState = putGetComplete; + if(status.isOK()) { + PVStructurePtr pvs = pvaClientPutData->getPVStructure(); + pvs->copyUnchecked(*putPVStructure,*putBitSet); + BitSetPtr bs = pvaClientPutData->getChangedBitSet(); + bs->clear(); + *bs |= *putBitSet; + } } PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); if(req) { @@ -271,14 +272,13 @@ void PvaClientPutGet::getGetDone( << " status.isOK " << (status.isOK() ? "true" : "false") << endl; } - channelPutGetStatus = status; - putGetState = putGetComplete; - if(status.isOK()) { - PVStructurePtr pvs = pvaClientGetData->getPVStructure(); - pvs->copyUnchecked(*getPVStructure,*getChangedBitSet); - BitSetPtr bs = pvaClientGetData->getChangedBitSet(); - bs->clear(); - *bs |= *getChangedBitSet; + { + Lock xx(mutex); + channelPutGetStatus = status; + putGetState = putGetComplete; + if(status.isOK()) { + pvaClientGetData->setData(getPVStructure,getChangedBitSet); + } } PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); if(req) { @@ -555,6 +555,4 @@ PvaClientChannelPtr PvaClientPutGet::getPvaClientChannel() return pvaClientChannel; } - - }} diff --git a/src/pvaClientRPC.cpp b/src/pvaClientRPC.cpp index bcc21bc..94a5411 100644 --- a/src/pvaClientRPC.cpp +++ b/src/pvaClientRPC.cpp @@ -17,8 +17,6 @@ #include -using std::tr1::static_pointer_cast; -using std::tr1::dynamic_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std;