diff --git a/src/Makefile b/src/Makefile index 4f01a81..d5c7b60 100644 --- a/src/Makefile +++ b/src/Makefile @@ -23,6 +23,7 @@ INC += ntattribute.h INC += ntcontinuum.h INC += nthistogram.h INC += nturi.h +INC += ntndarrayAttribute.h LIBSRCS += ntutils.cpp LIBSRCS += ntfield.cpp @@ -41,6 +42,7 @@ LIBSRCS += ntattribute.cpp LIBSRCS += ntcontinuum.cpp LIBSRCS += nthistogram.cpp LIBSRCS += nturi.cpp +LIBSRCS += ntndarrayAttribute.cpp LIBRARY = nt diff --git a/src/nt/nt.h b/src/nt/nt.h index 8bf7ef0..566298f 100644 --- a/src/nt/nt.h +++ b/src/nt/nt.h @@ -26,6 +26,7 @@ #include #include #include +#include #endif /* NT_H */ diff --git a/src/nt/ntattribute.cpp b/src/nt/ntattribute.cpp index 468b9d5..64fb54f 100644 --- a/src/nt/ntattribute.cpp +++ b/src/nt/ntattribute.cpp @@ -133,7 +133,10 @@ bool NTAttribute::isCompatible(PVStructurePtr const & pvStructure) PVUnionPtr pvValue = pvStructure->getSubField("value"); if(!pvValue) return false; + // TODO tags + PVFieldPtr pvField = pvStructure->getSubField("descriptor"); + if(pvField && !pvStructure->getSubField("descriptor")) return false; pvField = pvStructure->getSubField("alarm"); diff --git a/src/nt/ntndarrayAttribute.cpp b/src/nt/ntndarrayAttribute.cpp new file mode 100644 index 0000000..6a98015 --- /dev/null +++ b/src/nt/ntndarrayAttribute.cpp @@ -0,0 +1,235 @@ +/* ntndarrayAttribute.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. + */ + +#define epicsExportSharedSymbols +#include +#include + +using namespace std; +using namespace epics::pvData; + +namespace epics { namespace nt { + +static NTFieldPtr ntField = NTField::get(); + +namespace detail { + +static NTFieldPtr ntField = NTField::get(); + + +StructureConstPtr NTNDArrayAttributeBuilder::createStructure() +{ + FieldBuilderPtr builder = + getFieldCreate()->createFieldBuilder()-> + setId(NTNDArrayAttribute::URI)-> + add("name", pvString)-> + add("value", getFieldCreate()->createVariantUnion()); + + if (tags) + builder->addArray("tags", pvString); + + //if (descriptor) + builder->add("descriptor", pvString); + + builder->add("sourceType", pvInt); + + builder->add("source", pvString); + + if (alarm) + builder->add("alarm", ntField->createAlarm()); + + if (timeStamp) + builder->add("timeStamp", ntField->createTimeStamp()); + + size_t extraCount = extraFieldNames.size(); + for (size_t i = 0; i< extraCount; i++) + builder->add(extraFieldNames[i], extraFields[i]); + + + StructureConstPtr s = builder->createStructure(); + + reset(); + return s; +} + +NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addTags() +{ + tags = true; + return shared_from_this(); +} + +NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addDescriptor() +{ + descriptor = true; + return shared_from_this(); +} + +NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addAlarm() +{ + alarm = true; + return shared_from_this(); +} + +NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::addTimeStamp() +{ + timeStamp = true; + return shared_from_this(); +} + +PVStructurePtr NTNDArrayAttributeBuilder::createPVStructure() +{ + return getPVDataCreate()->createPVStructure(createStructure()); +} + +NTNDArrayAttributePtr NTNDArrayAttributeBuilder::create() +{ + return NTNDArrayAttributePtr(new NTNDArrayAttribute(createPVStructure())); +} + +NTNDArrayAttributeBuilder::NTNDArrayAttributeBuilder() +{ + reset(); +} + +void NTNDArrayAttributeBuilder::reset() +{ + descriptor = false; + alarm = false; + timeStamp = false; + extraFieldNames.clear(); + extraFields.clear(); +} + +NTNDArrayAttributeBuilder::shared_pointer NTNDArrayAttributeBuilder::add(string const & name, FieldConstPtr const & field) +{ + extraFields.push_back(field); extraFieldNames.push_back(name); + return shared_from_this(); +} + +} + +const std::string NTNDArrayAttribute::URI("epics:nt/NTAttribute:1.0"); + +NTNDArrayAttribute::shared_pointer NTNDArrayAttribute::wrap(PVStructurePtr const & structure) +{ + if(!isCompatible(structure)) return shared_pointer(); + return wrapUnsafe(structure); +} + +NTNDArrayAttribute::shared_pointer NTNDArrayAttribute::wrapUnsafe(PVStructurePtr const & structure) +{ + return shared_pointer(new NTNDArrayAttribute(structure)); +} + +bool NTNDArrayAttribute::is_a(StructureConstPtr const & structure) +{ + return NTUtils::is_a(structure->getID(), URI); +} + +bool NTNDArrayAttribute::isCompatible(PVStructurePtr const & pvStructure) +{ + if(!pvStructure) return false; + + PVUnionPtr pvValue = pvStructure->getSubField("value"); + if(!pvValue) return false; + + // TODO tags + + PVStringPtr pvDescriptor = pvStructure->getSubField("descriptor"); + if(!pvDescriptor) return false; + + PVStringPtr pvSource = pvStructure->getSubField("source"); + if(!pvSource) return false; + + PVIntPtr pvSourceType = pvStructure->getSubField("sourceType"); + if(!pvSourceType) return false; + + PVFieldPtr pvField = pvStructure->getSubField("alarm"); + if(pvField && !ntField->isAlarm(pvField->getField())) return false; + + pvField = pvStructure->getSubField("timeStamp"); + if(pvField && !ntField->isTimeStamp(pvField->getField())) return false; + + return true; +} + +NTNDArrayAttributeBuilderPtr NTNDArrayAttribute::createBuilder() +{ + return NTNDArrayAttributeBuilderPtr(new detail::NTNDArrayAttributeBuilder()); +} + +bool NTNDArrayAttribute::attachTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTNDArrayAttribute::attachAlarm(PVAlarm &pvAlarm) const +{ + PVStructurePtr al = getAlarm(); + if (al) + return pvAlarm.attach(al); + else + return false; +} + +PVStructurePtr NTNDArrayAttribute::getPVStructure() const +{ + return pvNTNDArrayAttribute; +} + +PVStringPtr NTNDArrayAttribute::getDescriptor() const +{ + return pvNTNDArrayAttribute->getSubField("descriptor"); +} + +PVStructurePtr NTNDArrayAttribute::getTimeStamp() const +{ + return pvNTNDArrayAttribute->getSubField("timeStamp"); +} + +PVStructurePtr NTNDArrayAttribute::getAlarm() const +{ + return pvNTNDArrayAttribute->getSubField("alarm"); +} + + +PVStringPtr NTNDArrayAttribute::getName() const +{ + return pvNTNDArrayAttribute->getSubField("name"); +} + +PVUnionPtr NTNDArrayAttribute::getValue() const +{ + return pvValue; +} + +PVStringArrayPtr NTNDArrayAttribute::getTags() const +{ + return pvNTNDArrayAttribute->getSubField("tags"); +} + +PVIntPtr NTNDArrayAttribute::getSourceType() const +{ + return pvNTNDArrayAttribute->getSubField("sourceType"); +} + +PVStringPtr NTNDArrayAttribute::getSource() const +{ + return pvNTNDArrayAttribute->getSubField("source"); +} + +NTNDArrayAttribute::NTNDArrayAttribute(PVStructurePtr const & pvStructure) : + pvNTNDArrayAttribute(pvStructure), pvValue(pvNTNDArrayAttribute->getSubField("value")) +{ +} + + +}} diff --git a/src/nt/ntndarrayAttribute.h b/src/nt/ntndarrayAttribute.h new file mode 100644 index 0000000..b5867c0 --- /dev/null +++ b/src/nt/ntndarrayAttribute.h @@ -0,0 +1,279 @@ +/* ntndarrayAttribute.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 NTNDARRAYATTRIBUTE_H +#define NTNDARRAYATTRIBUTE_H + +#ifdef epicsExportSharedSymbols +# define ntndarrayAttributeEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#ifdef ntndarrayAttributeEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef ntndarrayAttributeEpicsExportSharedSymbols +#endif + +#include + +#include + +namespace epics { namespace nt { + +class NTNDArrayAttribute; +typedef std::tr1::shared_ptr NTNDArrayAttributePtr; + +namespace detail { + + /** + * @brief Interface for in-line creating of NTAttribute extended as required by NTNDArray + * + * One instance can be used to create multiple instances. + * An instance of this object must not be used concurrently (an object has a state). + * @author dgh + */ + class epicsShareClass NTNDArrayAttributeBuilder : + public std::tr1::enable_shared_from_this + { + public: + POINTER_DEFINITIONS(NTNDArrayAttributeBuilder); + + /** + * Add tags field to the NTNDArrayAttribute. + * @return this instance of NTNDArrayAttributeBuilder. + */ + virtual shared_pointer addTags(); + + /** + * Add descriptor field to the NTNDArrayAttribute. + * @return this instance of NTNDArrayAttributeBuilder. + */ + shared_pointer addDescriptor(); + + /** + * Add alarm structure to the NTNDArrayAttribute. + * @return this instance of NTNDArrayAttributeBuilder. + */ + shared_pointer addAlarm(); + + /** + * Add timeStamp structure to the NTNDArrayAttribute. + * @return this instance of NTNDArrayAttributeBuilder. + */ + shared_pointer addTimeStamp(); + + /** + * Create a Structure that represents NTNDArrayAttribute. + * This resets this instance state and allows new instance to be created. + * @return a new instance of a Structure. + */ + epics::pvData::StructureConstPtr createStructure(); + + /** + * Create a PVStructure that represents NTNDArrayAttribute. + * This resets this instance state and allows new instance to be created. + * @return a new instance of a PVStructure. + */ + epics::pvData::PVStructurePtr createPVStructure(); + + /** + * Create a NTNDArrayAttribute instance. + * This resets this instance state and allows new instance to be created. + * @return a new instance of a NTNDArrayAttribute. + */ + NTNDArrayAttributePtr create(); + /** + * Add extra Field to the type. + * @param name name of the field. + * @param field a field to add. + * @return this instance of NTNDArrayAttributeBuilder. + */ + shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field); + + protected://private: + NTNDArrayAttributeBuilder(); + + void reset(); + + bool tags; + bool descriptor; + bool alarm; + bool timeStamp; + + // NOTE: this preserves order, however it does not handle duplicates + epics::pvData::StringArray extraFieldNames; + epics::pvData::FieldConstPtrArray extraFields; + + friend class ::epics::nt::NTNDArrayAttribute; + }; + +} + +typedef std::tr1::shared_ptr NTNDArrayAttributeBuilderPtr; + + + +/** + * @briVIntPtref Convenience Class for NTNDArrayAttribute + * + * @author dgh + */ +class epicsShareClass NTNDArrayAttribute +{ +public: + POINTER_DEFINITIONS(NTNDArrayAttribute); + + static const std::string URI; + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTNDArrayAttribute. + * First isCompatible is called. + * This method will nullptr if the structure is is not compatible. + * This method will nullptr if the structure is nullptr. + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNDArrayAttribute. + * @return NTNDArrayAttribute instance on success, nullptr otherwise. + */ + static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure); + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTNDArrayAttribute without checking for isCompatible + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTNDArrayAttribute. + * @return NTNDArrayAttribute instance. + */ + static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure); + + /** + * Is the structure an NTNDArrayAttribute. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTNDArrayAttribute. + */ + static bool is_a(epics::pvData::StructureConstPtr const & structure); + + /** + * Is the structure an NTNDArrayAttribute. + * @param pvStructure The PVStructure to test. + * @return (false,true) if (is not, is) an NTNDArrayAttribute. + */ + static bool is_a(epics::pvData::PVStructurePtr const & pvStructure); + + /** + * Is the Structure compatible with NTNDArrayAttribute. + * This method introspects the fields to see if they are compatible. + * @param structure The Structure to test. + * @return (false,true) if (is not, is) an NTNDArrayAttribute. + */ + static bool isCompatible( + epics::pvData::StructureConstPtr const &structure); + + /** + * Is the PVStructure compatible with NTNDArrayAttribute. + * This method introspects the fields to see if they are compatible. + * @param pvStructure The PVStructure to test. + * @return (false,true) if (is not, is) an NTNDArrayAttribute. + */ + static bool isCompatible( + epics::pvData::PVStructurePtr const &pvStructure); + + /** + * Checks if the specified structure is a valid NTNDArrayAttribute. + * + * Checks whether the wrapped structure is valid with respect to this + * version of NTNDArrayAttribute + * @return (false,true) if (is not, is) a valid NTNDArrayAttribute. + */ + bool isValid(); + + /** + * Create a NTNDArrayAttribute builder instance. + * @return builder instance. + */ + static NTNDArrayAttributeBuilderPtr createBuilder(); + + /** + * Destructor. + */ + ~NTNDArrayAttribute() {} + + /** + * Attach a pvTimeStamp. + * @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 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 descriptor field. + * @return The pvString + */ + epics::pvData::PVStringPtr getDescriptor() const; + + /** + * Get the timeStamp. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getTimeStamp() const; + + /** + * Get the alarm. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getAlarm() const; + + /** + * Get the name field. + * @return The PVString for the name. + */ + epics::pvData::PVStringPtr getName() const; + + /** + * Get the value field. + * @return The PVUnion for the values. + */ + epics::pvData::PVUnionPtr getValue() const; + + /** + * Get the tags field. + * @return The PVStringArray for the tags, which may be null. + */ + epics::pvData::PVStringArrayPtr getTags() const; + + /** + * Get the sourceType field. + * @return The PVInt for the sourceType field. + */ + epics::pvData::PVIntPtr getSourceType() const; + + /** + * Get the source field. + * @return The PVString for the source field, which may be null. + */ + epics::pvData::PVStringPtr getSource() const; + +private: + NTNDArrayAttribute(epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStructurePtr pvNTNDArrayAttribute; + epics::pvData::PVUnionPtr pvValue; + + friend class detail::NTNDArrayAttributeBuilder; +}; + +}} +#endif /* NTNDARRAYATTRIBUTE_H */