/* easyPVStructure.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 2015.02 */ #define epicsExportSharedSymbols #include #include #include #include #include using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; namespace epics { namespace easyPVA { typedef std::tr1::shared_ptr PVArrayPtr; static StructureConstPtr nullStructure; static PVStructurePtr nullPVStructure; static ConvertPtr convert = getConvert(); static Status statusOK(Status::Ok); static Status statusDestroyed(Status::STATUSTYPE_ERROR,"was destroyed"); static Status statusNoPVStructure(Status::STATUSTYPE_ERROR,"setPVStructure not called"); static Status statusNoValue(Status::STATUSTYPE_ERROR,"no value field"); static Status statusNoScalar(Status::STATUSTYPE_ERROR,"value is not a scalar"); static Status statusMismatchedScalar(Status::STATUSTYPE_ERROR,"value is not a compatible scalar"); static Status statusNoArray(Status::STATUSTYPE_ERROR,"value is not a array"); static Status statusNoScalarArray(Status::STATUSTYPE_ERROR,"value is not a scalarArray"); static Status statusMismatchedScalarArray(Status::STATUSTYPE_ERROR,"value is not a compatible scalarArray"); static Status statusNoAlarm(Status::STATUSTYPE_ERROR,"no alarm field"); static Status statusNoTimeStamp(Status::STATUSTYPE_ERROR,"no timeStamp field"); class epicsShareClass EasyPVStructureImpl : public EasyPVStructure, public std::tr1::enable_shared_from_this { public: EasyPVStructureImpl(); ~EasyPVStructureImpl(){} virtual void setMessagePrefix(std::string const & value); virtual void setPVStructure(PVStructurePtr const & pvStructure); virtual PVStructurePtr getPVStructure(); virtual Alarm getAlarm(); virtual TimeStamp getTimeStamp(); virtual bool hasValue(); virtual bool isValueScalar(); virtual bool isValueScalarArray() ; virtual PVFieldPtr getValue(); virtual PVScalarPtr getScalarValue(); virtual std::tr1::shared_ptr getArrayValue(); virtual std::tr1::shared_ptr getScalarArrayValue(); virtual bool getBoolean(); virtual int8 getByte(); virtual int16 getShort(); virtual int32 getInt(); virtual int64 getLong(); virtual uint8 getUByte(); virtual uint16 getUShort(); virtual uint32 getUInt(); virtual uint64 getULong(); virtual float getFloat(); virtual double getDouble(); virtual std::string getString(); virtual shared_vector getBooleanArray(); virtual shared_vector getByteArray(); virtual shared_vector getShortArray(); virtual shared_vector getIntArray(); virtual shared_vector getLongArray(); virtual shared_vector getUByteArray(); virtual shared_vector getUShortArray(); virtual shared_vector getUIntArray(); virtual shared_vector getULongArray(); virtual shared_vector getFloatArray(); virtual shared_vector getDoubleArray(); virtual shared_vector getStringArray(); EasyPVStructurePtr getPtrSelf() { return shared_from_this(); } private: void checkPVStructure(); void checkValue(); bool checkOverflow(ScalarType source,ScalarType dest); PVScalarPtr checkScalar(ScalarType scalarType); PVScalarArrayPtr checkScalarArray(ScalarType elementType); string messagePrefix; PVStructurePtr pvStructure; PVFieldPtr pvValue; PVAlarm pvAlarm; Alarm alarm; PVTimeStamp pvTimeStamp; TimeStamp timeStamp; }; EasyPVStructureImpl::EasyPVStructureImpl() {} EasyPVStructurePtr EasyPVStructureFactory::createEasyPVStructure() { EasyPVStructurePtr epv(new EasyPVStructureImpl()); return epv; } void EasyPVStructureImpl::checkPVStructure() { if(pvStructure) return; throw std::runtime_error(messagePrefix + statusNoPVStructure.getMessage()); } void EasyPVStructureImpl::checkValue() { if(pvValue) return; throw std::runtime_error(messagePrefix + statusNoValue.getMessage()); } bool EasyPVStructureImpl::checkOverflow(ScalarType source,ScalarType dest) { if(dest==pvFloat||dest==pvDouble) return true; if(!ScalarTypeFunc::isInteger(source) && !ScalarTypeFunc::isUInteger(source)) return false; if(ScalarTypeFunc::isUInteger(dest)) { if(ScalarTypeFunc::isUInteger(source)) { if(dest>=source) return true; return false; } if(ScalarTypeFunc::isInteger(source)) { if(dest>=(source+4)) return true; return false; } return false; } if(ScalarTypeFunc::isInteger(dest)) { if(ScalarTypeFunc::isUInteger(source)) { if(dest>(source-4)) return true; return false; } if(ScalarTypeFunc::isInteger(source)) { if(dest>=source) return true; return false; } return false; } return false; } PVScalarPtr EasyPVStructureImpl::checkScalar(ScalarType scalarType) { checkPVStructure(); checkValue(); PVScalarPtr pv = pvStructure->getSubField("value"); if(!pv) { throw std::runtime_error(messagePrefix + statusNoScalar.getMessage()); } ScalarType type = pv->getScalar()->getScalarType(); if((scalarType==pvBoolean && type==pvBoolean) || (scalarType==pvString && type==pvString)) return pv; if((ScalarTypeFunc::isNumeric(type) && ScalarTypeFunc::isNumeric(scalarType)) && checkOverflow(type,scalarType)) return pv; stringstream ss; ss << messagePrefix << statusMismatchedScalar.getMessage(); ss << " source " << type << " dest " << scalarType; throw std::runtime_error(ss.str()); } PVScalarArrayPtr EasyPVStructureImpl::checkScalarArray(ScalarType elementType) { checkPVStructure(); checkValue(); PVScalarArrayPtr pv = pvStructure->getSubField("value"); if(!pv) { throw std::runtime_error(messagePrefix + statusNoScalarArray.getMessage()); } ScalarType type = pv->getScalarArray()->getElementType(); if((elementType==pvBoolean && type==pvBoolean) || (elementType==pvBoolean && type==pvBoolean)) return pv; if((ScalarTypeFunc::isNumeric(type) && ScalarTypeFunc::isNumeric(elementType)) && checkOverflow(type,elementType)) return pv; throw std::runtime_error(messagePrefix + statusMismatchedScalarArray.getMessage()); } void EasyPVStructureImpl::setMessagePrefix(string const & value) { messagePrefix = value; if(value.size()>0) messagePrefix += " "; } void EasyPVStructureImpl::setPVStructure(PVStructurePtr const & pvStructure) { this->pvStructure = pvStructure; pvValue = pvStructure->getSubField("value"); } PVStructurePtr EasyPVStructureImpl::getPVStructure() { checkPVStructure(); return pvStructure; } PVFieldPtr EasyPVStructureImpl::getValue() { checkValue(); return pvValue; } PVScalarPtr EasyPVStructureImpl::getScalarValue() { checkValue(); PVScalarPtr pv = pvStructure->getSubField("value"); if(!pv) { throw std::runtime_error(messagePrefix + statusNoScalar.getMessage()); } return pv; } PVArrayPtr EasyPVStructureImpl::getArrayValue() { checkValue(); PVArrayPtr pv = pvStructure->getSubField("value"); if(!pv) { throw std::runtime_error(messagePrefix + statusNoArray.getMessage()); } return pv; } PVScalarArrayPtr EasyPVStructureImpl::getScalarArrayValue() { checkValue(); PVScalarArrayPtr pv = pvStructure->getSubField("value"); if(!pv) { throw std::runtime_error(messagePrefix + statusNoScalarArray.getMessage()); } return pv; } Alarm EasyPVStructureImpl::getAlarm() { Alarm alarm; alarm.setSeverity(undefinedAlarm); alarm.setStatus(undefinedStatus); alarm.setMessage("no alarm field"); if(!pvStructure) return alarm; PVStructurePtr xxx = pvStructure->getSubField("alarm"); if(xxx) { pvAlarm.attach(xxx); if(pvAlarm.isAttached()) { pvAlarm.get(alarm); pvAlarm.detach(); } } return alarm;; } TimeStamp EasyPVStructureImpl::getTimeStamp() { TimeStamp timeStamp; if(!pvStructure) return timeStamp; PVStructurePtr xxx = pvStructure->getSubField("timeStamp"); if(xxx) { pvTimeStamp.attach(xxx); if(pvTimeStamp.isAttached()) { pvTimeStamp.get(timeStamp); pvTimeStamp.detach(); } } return timeStamp;; } bool EasyPVStructureImpl::hasValue() { if(!pvValue) return false; return true; } bool EasyPVStructureImpl::isValueScalar() { if(!pvValue) return false; if(pvValue->getField()->getType()==scalar) return true; return false; } bool EasyPVStructureImpl::isValueScalarArray() { if(!pvValue) return false; if(pvValue->getField()->getType()==scalarArray) return true; return false; } bool EasyPVStructureImpl::getBoolean() { PVScalarPtr pvScalar = checkScalar(pvBoolean); PVBooleanPtr pv = static_pointer_cast(pvScalar); return pv->get(); } int8 EasyPVStructureImpl::getByte() { PVScalarPtr pvScalar = checkScalar(pvByte); return convert->toByte(pvScalar); } uint8 EasyPVStructureImpl::getUByte() { PVScalarPtr pvScalar = checkScalar(pvUByte); return convert->toUByte(pvScalar); } int16 EasyPVStructureImpl::getShort() { PVScalarPtr pvScalar = checkScalar(pvShort); return convert->toShort(pvScalar); } uint16 EasyPVStructureImpl::getUShort() { PVScalarPtr pvScalar = checkScalar(pvUShort); return convert->toUShort(pvScalar); } int32 EasyPVStructureImpl::getInt() { PVScalarPtr pvScalar = checkScalar(pvInt); return convert->toInt(pvScalar); } uint32 EasyPVStructureImpl::getUInt() { PVScalarPtr pvScalar = checkScalar(pvUInt); return convert->toUInt(pvScalar); } int64 EasyPVStructureImpl::getLong() { PVScalarPtr pvScalar = checkScalar(pvLong); return convert->toLong(pvScalar); } uint64 EasyPVStructureImpl::getULong() { PVScalarPtr pvScalar = checkScalar(pvULong); return convert->toULong(pvScalar); } float EasyPVStructureImpl::getFloat() { PVScalarPtr pvScalar = checkScalar(pvFloat); return convert->toFloat(pvScalar); } double EasyPVStructureImpl::getDouble() { PVScalarPtr pvScalar = checkScalar(pvDouble); return convert->toDouble(pvScalar); } string EasyPVStructureImpl::getString() { PVScalarPtr pvScalar = checkScalar(pvString); PVStringPtr pv = static_pointer_cast(pvScalar); return pv->get(); } shared_vector EasyPVStructureImpl::getBooleanArray() { checkScalarArray(pvBoolean); PVBooleanArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } template shared_vector copy(PVScalarArrayPtr const & pvScalarArray) { ScalarType elementType = pvScalarArray->getScalarArray()->getElementType(); switch(elementType) { case pvBoolean : break; case pvByte : { PVByteArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvShort : { PVShortArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvInt : { PVIntArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvLong : { PVLongArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvUByte : { PVUByteArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvUShort : { PVUShortArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvUInt : { PVUIntArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvULong : { PVULongArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvFloat : { PVFloatArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvDouble : { PVDoubleArrayPtr pv = static_pointer_cast(pvScalarArray); shared_vector data = pv->reuse(); shared_vector to = shared_vector_convert(data); return to; } case pvString : break; } return shared_vector(); } shared_vector EasyPVStructureImpl::getByteArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvByte); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvByte) { PVByteArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getShortArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvShort); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvShort) { PVShortArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getIntArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvInt); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvInt) { PVIntArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getLongArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvLong); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvLong) { PVLongArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getUByteArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvUByte); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvUByte) { PVUByteArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getUShortArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvUShort); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvUShort) { PVUShortArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getUIntArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvUInt); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvUInt) { PVUIntArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getULongArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvULong); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvULong) { PVULongArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getFloatArray() { checkScalarArray(pvFloat); PVFloatArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); PVScalarArrayPtr pvScalarArray = checkScalarArray(pvFloat); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvFloat) { PVFloatArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getDoubleArray() { PVScalarArrayPtr pvScalarArray = checkScalarArray(pvDouble); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(scalarType==pvDouble) { PVDoubleArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } shared_vector xx = copy(pvScalarArray); return xx; } shared_vector EasyPVStructureImpl::getStringArray() { checkScalarArray(pvString); PVStringArrayPtr pv = static_pointer_cast(pvValue); return pv->reuse(); } }}