From 1fdcfb7ad166e422275cc25240ea731c8b2c2eb3 Mon Sep 17 00:00:00 2001 From: dhickin Date: Fri, 22 Aug 2014 16:56:43 +0100 Subject: [PATCH] Added first implementation of NTNDArray. --- src/Makefile | 2 + src/nt/nt.h | 1 + src/nt/ntndarray.cpp | 244 +++++++++++++++++++++++++++++++++++++++++++ src/nt/ntndarray.h | 165 +++++++++++++++++++++++++++++ 4 files changed, 412 insertions(+) create mode 100644 src/nt/ntndarray.cpp create mode 100644 src/nt/ntndarray.h diff --git a/src/Makefile b/src/Makefile index abd4732..22d207e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,12 +11,14 @@ INC += ntscalar.h INC += ntnameValue.h INC += nttable.h INC += ntmultiChannel.h +INC += ntndarray.h LIBSRCS += ntfield.cpp LIBSRCS += ntscalar.cpp LIBSRCS += ntnameValue.cpp LIBSRCS += nttable.cpp LIBSRCS += ntmultiChannel.cpp +LIBSRCS += ntndarray.cpp LIBRARY=nt diff --git a/src/nt/nt.h b/src/nt/nt.h index 187b90e..296fe6b 100644 --- a/src/nt/nt.h +++ b/src/nt/nt.h @@ -11,6 +11,7 @@ #include #include #include +#include #endif /* NT_H */ diff --git a/src/nt/ntndarray.cpp b/src/nt/ntndarray.cpp new file mode 100644 index 0000000..f225d6c --- /dev/null +++ b/src/nt/ntndarray.cpp @@ -0,0 +1,244 @@ +/* ntndarray.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvDataCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ + +#include + +#include + +using namespace std; +using namespace epics::pvData; + +namespace epics { namespace nt { + +const std::string NTNDArray::URI("uri:ev4:nt/2012/pwd:NTNDArray"); +const std::string ntAttrStr("uri:ev4:nt/2012/pwd:NTAttribute"); + +static FieldCreatePtr fieldCreate = getFieldCreate(); +static PVDataCreatePtr pvDataCreate = getPVDataCreate(); + +bool NTNDArray::is_a(StructureConstPtr const & structure) +{ + return structure->getID() == URI; +} + + +NTNDArrayPtr NTNDArray::create(epics::pvData::PVStructurePtr const &pvStructure) +{ + return NTNDArrayPtr(new NTNDArray(pvStructure)); +} + +NTNDArrayPtr NTNDArray::create(bool hasDescriptor, + bool hasTimeStamp, bool hasAlarm, bool hasDisplay) +{ + PVStructurePtr pvStructure = pvDataCreate->createPVStructure( + createStructure(hasDescriptor, hasTimeStamp, hasAlarm, hasDisplay)); + return NTNDArrayPtr(new NTNDArray(pvStructure)); +} + + +NTNDArrayPtr NTNDArray::create() +{ + return create(true,true,true,true); +} + + + +StructureConstPtr NTNDArray::createStructure(bool hasDescriptor, + bool hasTimeStamp, bool hasAlarm, bool hasDisplay) +{ + enum + { + DISCRIPTOR_INDEX, + TIMESTAMP_INDEX, + ALARM_INDEX, + DISPLAY_INDEX + }; + + const size_t NUMBER_OF_INDICES = DISPLAY_INDEX+1; + const size_t NUMBER_OF_STRUCTURES = 1 << NUMBER_OF_INDICES; + + static epics::pvData::StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES]; + static epics::pvData::StructureConstPtr codecStruc; + static epics::pvData::StructureConstPtr dimensionStruc; + static epics::pvData::StructureConstPtr attributeStruc; + + static Mutex mutex; + Lock xx(mutex); + + size_t index = 0; + if (hasDescriptor) index |= 1 << DISCRIPTOR_INDEX; + if (hasTimeStamp) index |= 1 << TIMESTAMP_INDEX; + if (hasAlarm) index |= 1 << ALARM_INDEX; + if (hasDisplay) index |= 1 << DISPLAY_INDEX; + + if (ntndarrayStruc[index] == NULL) + { + StandardFieldPtr standardField = getStandardField(); + FieldBuilderPtr fb = fieldCreate->createFieldBuilder(); + + UnionConstPtr codecParameters = fb->createUnion(); + + if (codecStruc == NULL) + { + codecStruc = fb->setId("codec_t")-> + add("name", pvString)-> + add("parameters", codecParameters)-> + createStructure(); + } + + if (dimensionStruc == NULL) + { + dimensionStruc = fb->setId("dimension_t")-> + add("size", pvInt)-> + add("offset", pvInt)-> + add("fullSize", pvInt)-> + add("binning", pvInt)-> + add("reverse", pvBoolean)-> + createStructure(); + } + + if (attributeStruc == NULL) + { + attributeStruc = fb->setId(ntAttrStr)-> + add("name", pvString)-> + add("value", fieldCreate->createVariantUnion())-> + add("description", pvString)-> + add("sourceType", pvInt)-> + add("source", pvString)-> + createStructure(); + } + + fb->setId(URI)-> + add("value", makeValueType())-> + add("compressedSize", pvLong)-> + add("uncompressedSize", pvLong)-> + add("codec", codecStruc)-> + addArray("dimension", dimensionStruc)-> + add("dataTimeStamp", standardField->timeStamp())-> + add("uniqueId", pvInt)-> + addArray("attribute", attributeStruc); + + if (hasDescriptor) fb->add("descriptor", pvString); + if (hasAlarm) fb->add("alarm", standardField->alarm()); + if (hasTimeStamp) fb->add("timeStamp", standardField->timeStamp()); + if (hasDisplay) fb->add("display", standardField->display()); + + ntndarrayStruc[index] = fb->createStructure(); + } + + return ntndarrayStruc[index]; +} + +UnionConstPtr NTNDArray::makeValueType() +{ + static epics::pvData::UnionConstPtr valueType; + + if (valueType == NULL) + { + FieldBuilderPtr fb = getFieldCreate()->createFieldBuilder(); + + for (int i = pvBoolean; i < pvString; ++i) + { + ScalarType st = static_cast(i); + fb->addArray(std::string(ScalarTypeFunc::name(st)) + "Value", st); + } + + valueType = fb->createUnion(); + } + return valueType; +} + + +bool NTNDArray::attachTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTNDArray::attachDataTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getDataTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTNDArray::attachAlarm(PVAlarm &pvAlarm) const +{ + PVStructurePtr al = getAlarm(); + if (al) + return pvAlarm.attach(al); + else + return false; +} + +PVStructurePtr NTNDArray::getPVStructure() const +{ + return pvNTNDArray; +} + +PVUnionPtr NTNDArray::getValue() const +{ + return pvNTNDArray->getSubField("value"); +} + +PVLongPtr NTNDArray::getCompressedDataSize() const +{ + return pvNTNDArray->getSubField("compressedSize"); +} + +PVLongPtr NTNDArray::getUncompressedDataSize() const +{ + return pvNTNDArray->getSubField("uncompressedSize"); +} + +PVStructurePtr NTNDArray::getCodec() const +{ + return pvNTNDArray->getSubField("codec"); +} + +PVStructureArrayPtr NTNDArray::getAttribute() const +{ + return pvNTNDArray->getSubField("attribute"); +} + +PVStructureArrayPtr NTNDArray::getDimension() const +{ + return pvNTNDArray->getSubField("dimension"); +} + +PVStructurePtr NTNDArray::getDataTimeStamp() const +{ + return pvNTNDArray->getSubField("dataTimeStamp"); +} + +PVStringPtr NTNDArray::getDescriptor() const +{ + return pvNTNDArray->getSubField("descriptor"); +} + +PVStructurePtr NTNDArray::getTimeStamp() const +{ + return pvNTNDArray->getSubField("timeStamp"); +} + +PVStructurePtr NTNDArray::getAlarm() const +{ + return pvNTNDArray->getSubField("alarm"); +} + + +NTNDArray::NTNDArray(PVStructurePtr const & pvStructure) : + pvNTNDArray(pvStructure) +{} + + +}} diff --git a/src/nt/ntndarray.h b/src/nt/ntndarray.h new file mode 100644 index 0000000..feec21f --- /dev/null +++ b/src/nt/ntndarray.h @@ -0,0 +1,165 @@ +/* ntndarray.h */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvDataCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +#ifndef NTNDARRAY_H +#define NTNDARRAY_H + +#include + +#include +#include + +namespace epics { namespace nt { + +class NTNDArray; +typedef std::tr1::shared_ptr NTNDArrayPtr; + +/** + * Convenience Class for NTNDArray + * @author dgh + */ +class NTNDArray +{ +public: + POINTER_DEFINITIONS(NTNDArray); + + static const std::string URI; + + /** + * Is the structure an NTNDArray. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTNDArray. + */ + static bool is_a(epics::pvData::StructureConstPtr const & structure); + + + static NTNDArrayPtr create( + epics::pvData::PVStructurePtr const &pvStructure); + + static NTNDArrayPtr create(bool hasDescriptor, + bool hasTimeStamp, bool hasAlarm, bool hasDisplay); + + static NTNDArrayPtr create(); + + static NTNDArrayPtr clone(epics::pvData::PVStructurePtr const &); + + /** + * Create a {@code Structure} that represents NTNDArray. + */ + static epics::pvData::StructureConstPtr createStructure(bool hasDescriptor, + bool hasTimeStamp, bool hasAlarm, bool hasDisplay); + + /** + * Destructor. + */ + ~NTNDArray() {} + + /** + * Attach a pvTimeStamp to timeStamp field. + * @param pvTimeStamp The pvTimeStamp that will be attached. + * Does nothing if no timeStamp. + * @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false. + */ + bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const; + + /** + * Attach a pvTimeStamp to dataTimeStamp field. + * @param pvTimeStamp The pvTimeStamp that will be attached. + * Does nothing if no timeStamp. + * @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false. + */ + bool attachDataTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const; + + /** + * Attach an pvAlarm. + * @param pvAlarm The pvAlarm that will be attached. + * Does nothing if no alarm. + * @return true if the operation was successfull (i.e. this instance has a timeStamp field), otherwise false. + */ + bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const; + + /** + * Get the pvStructure. + * @return PVStructurePtr. + */ + epics::pvData::PVStructurePtr getPVStructure() const; + + /** + * Get the value field. + * @return The PVField for the values. + */ + epics::pvData::PVUnionPtr getValue() const; + + /** + * Get the compressedDataSize field. + * @return PVStructurePtr. + */ + epics::pvData::PVLongPtr getCompressedDataSize() const; + + /** + * Get the uncompressedDataSize field. + * @return PVStructurePtr. + */ + epics::pvData::PVLongPtr getUncompressedDataSize() const; + + /** + * Get the codec field. + * @return the PVStructurePtr. + */ + epics::pvData::PVStructurePtr getCodec() const; + + /** + * Get the attribute field. + * @return the PVStructurePtr. + */ + epics::pvData::PVStructureArrayPtr getAttribute() const; + + /** + * Get the dimension field. + * @return the PVStructurePtr. + */ + epics::pvData::PVStructureArrayPtr getDimension() const; + + /** + * Get the uniqueId field. + * @return PVStructurePtr. + */ + epics::pvData::PVIntPtr getUniqueId() const; + + /** + * Get the data timeStamp field. + * @return PVStructurePtr. + */ + epics::pvData::PVStructurePtr getDataTimeStamp() const; + + /** + * Get the descriptor field. + * @return The pvString or null if no function field. + */ + epics::pvData::PVStringPtr getDescriptor() const; + + /** + * Get the timeStamp field. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getTimeStamp() const; + + /** + * Get the alarm field. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getAlarm() const; + + + +private: + NTNDArray(epics::pvData::PVStructurePtr const & pvStructure); + static epics::pvData::UnionConstPtr makeValueType(); + epics::pvData::PVStructurePtr pvNTNDArray; +}; + +}} +#endif /* NTNDARRAY_H */