diff --git a/src/Makefile b/src/Makefile index 663c92b..f9cca3e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,6 +15,11 @@ INC += nttable.h INC += ntmultiChannel.h INC += ntscalarMultiChannel.h INC += ntndarray.h +INC += ntmatrix.h +INC += ntenum.h +INC += ntunion.h +INC += ntaggregate.h +INC += ntattribute.h LIBSRCS += ntutils.cpp LIBSRCS += ntfield.cpp @@ -25,6 +30,11 @@ LIBSRCS += nttable.cpp LIBSRCS += ntmultiChannel.cpp LIBSRCS += ntscalarMultiChannel.cpp LIBSRCS += ntndarray.cpp +LIBSRCS += ntmatrix.cpp +LIBSRCS += ntenum.cpp +LIBSRCS += ntunion.cpp +LIBSRCS += ntaggregate.cpp +LIBSRCS += ntattribute.cpp LIBRARY = nt diff --git a/src/nt/nt.h b/src/nt/nt.h index 46ec733..909c612 100644 --- a/src/nt/nt.h +++ b/src/nt/nt.h @@ -18,6 +18,11 @@ #include #include #include +#include +#include +#include +#include +#include #endif /* NT_H */ diff --git a/src/nt/ntaggregate.cpp b/src/nt/ntaggregate.cpp new file mode 100644 index 0000000..243c9ac --- /dev/null +++ b/src/nt/ntaggregate.cpp @@ -0,0 +1,311 @@ +/* ntaggregate.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 NTAggregateBuilder::createStructure() +{ + FieldBuilderPtr builder = + getFieldCreate()->createFieldBuilder()-> + setId(NTAggregate::URI)-> + add("value", pvDouble)-> + add("N", pvLong); + + if (dispersion) + builder->add("dispersion", pvDouble); + + if (first) + builder->add("first", pvDouble); + + if (firstTimeStamp) + builder->add("firstTimeStamp", ntField->createTimeStamp()); + + if (last) + builder->add("last" , pvDouble); + + if (lastTimeStamp) + builder->add("lastTimeStamp", ntField->createTimeStamp()); + + if (max) + builder->add("max", pvDouble); + + if (min) + builder->add("min", pvDouble); + + if (descriptor) + builder->add("descriptor", 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; +} + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addDispersion() +{ + dispersion = true; + return shared_from_this(); +} + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addFirst() +{ + first = true; + return shared_from_this(); +} + + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addFirstTimeStamp() +{ + firstTimeStamp = true; + return shared_from_this(); +} + + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addLast() +{ + last = true; + return shared_from_this(); +} + + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addLastTimeStamp() +{ + lastTimeStamp = true; + return shared_from_this(); +} + + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addMax() +{ + max = true; + return shared_from_this(); +} + + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addMin() +{ + min = true; + return shared_from_this(); +} + + + + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addDescriptor() +{ + descriptor = true; + return shared_from_this(); +} + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addAlarm() +{ + alarm = true; + return shared_from_this(); +} + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::addTimeStamp() +{ + timeStamp = true; + return shared_from_this(); +} + +PVStructurePtr NTAggregateBuilder::createPVStructure() +{ + return getPVDataCreate()->createPVStructure(createStructure()); +} + +NTAggregatePtr NTAggregateBuilder::create() +{ + return NTAggregatePtr(new NTAggregate(createPVStructure())); +} + +NTAggregateBuilder::NTAggregateBuilder() +{ + reset(); +} + +void NTAggregateBuilder::reset() +{ + dispersion = false; + first = false; + firstTimeStamp = false; + last = false; + lastTimeStamp = false; + max = false; + min = false; + + descriptor = false; + alarm = false; + timeStamp = false; + + extraFieldNames.clear(); + extraFields.clear(); +} + +NTAggregateBuilder::shared_pointer NTAggregateBuilder::add(string const & name, FieldConstPtr const & field) +{ + extraFields.push_back(field); extraFieldNames.push_back(name); + return shared_from_this(); +} + + +} + +const std::string NTAggregate::URI("epics:nt/NTAggregate:1.0"); + +NTAggregate::shared_pointer NTAggregate::wrap(PVStructurePtr const & structure) +{ + if(!isCompatible(structure)) return shared_pointer(); + return wrapUnsafe(structure); +} + +NTAggregate::shared_pointer NTAggregate::wrapUnsafe(PVStructurePtr const & structure) +{ + return shared_pointer(new NTAggregate(structure)); +} + +bool NTAggregate::is_a(StructureConstPtr const & structure) +{ + return NTUtils::is_a(structure->getID(), URI); +} + +bool NTAggregate::isCompatible(PVStructurePtr const & pvStructure) +{ + if(!pvStructure) return false; + + PVDoublePtr pvValue = pvStructure->getSubField("value"); + if(!pvValue) return false; + + PVFieldPtr pvField = pvStructure->getSubField("descriptor"); + if(pvField && !pvStructure->getSubField("descriptor")) return false; + 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; +} + +NTAggregateBuilderPtr NTAggregate::createBuilder() +{ + return NTAggregateBuilderPtr(new detail::NTAggregateBuilder()); +} + +bool NTAggregate::attachTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTAggregate::attachAlarm(PVAlarm &pvAlarm) const +{ + PVStructurePtr al = getAlarm(); + if (al) + return pvAlarm.attach(al); + else + return false; +} + +PVStructurePtr NTAggregate::getPVStructure() const +{ + return pvNTAggregate; +} + +PVStringPtr NTAggregate::getDescriptor() const +{ + return pvNTAggregate->getSubField("descriptor"); +} + +PVStructurePtr NTAggregate::getTimeStamp() const +{ + return pvNTAggregate->getSubField("timeStamp"); +} + +PVStructurePtr NTAggregate::getAlarm() const +{ + return pvNTAggregate->getSubField("alarm"); +} + +PVDoublePtr NTAggregate::getValue() const +{ + return pvValue; +} + +PVLongPtr NTAggregate::getN() const +{ + return pvNTAggregate->getSubField("N"); +} + +PVDoublePtr NTAggregate::getDispersion() const +{ + return pvNTAggregate->getSubField("dispersion"); +} + +PVDoublePtr NTAggregate::getFirst() const +{ + return pvNTAggregate->getSubField("first"); +} + +PVStructurePtr NTAggregate::getFirstTimeStamp() const +{ + return pvNTAggregate->getSubField("firstTimeStamp"); +} + +PVDoublePtr NTAggregate::getLast() const +{ + return pvNTAggregate->getSubField("last"); +} + +PVStructurePtr NTAggregate::getLastTimeStamp() const +{ + return pvNTAggregate->getSubField("lastTimeStamp"); +} + +PVDoublePtr NTAggregate::getMax() const +{ + return pvNTAggregate->getSubField("max"); +} + +PVDoublePtr NTAggregate::getMin() const +{ + return pvNTAggregate->getSubField("min"); +} + +NTAggregate::NTAggregate(PVStructurePtr const & pvStructure) : + pvNTAggregate(pvStructure), pvValue(pvNTAggregate->getSubField("value")) +{} + + +}} diff --git a/src/nt/ntaggregate.h b/src/nt/ntaggregate.h new file mode 100644 index 0000000..0b231df --- /dev/null +++ b/src/nt/ntaggregate.h @@ -0,0 +1,318 @@ +/* ntaggregate.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 NTAGGREGATE_H +#define NTAGGREGATE_H + +#ifdef epicsExportSharedSymbols +# define ntaggregateEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#ifdef ntaggregateEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef ntaggregateEpicsExportSharedSymbols +#endif + +#include + +#include + +namespace epics { namespace nt { + +class NTAggregate; +typedef std::tr1::shared_ptr NTAggregatePtr; + +namespace detail { + + /** + * @brief Interface for in-line creating of NTAggregate. + * + * 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 NTAggregateBuilder : + public std::tr1::enable_shared_from_this + { + public: + POINTER_DEFINITIONS(NTAggregateBuilder); + + /** + * Add dispersion field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addDispersion(); + + /** + * Add first field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addFirst(); + + /** + * Add firstTimeStamp field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addFirstTimeStamp(); + + /** + * Add last field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addLast(); + + /** + * Add lastTimeStamp field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addLastTimeStamp(); + + /** + * Add max field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addMax(); + + /** + * Add min field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addMin(); + + /** + * Add descriptor field to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addDescriptor(); + + /** + * Add alarm structure to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addAlarm(); + + /** + * Add timeStamp structure to the NTAggregate. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer addTimeStamp(); + + /** + * Create a Structure that represents NTAggregate. + * 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 NTAggregate. + * 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 NTAggregate instance. + * This resets this instance state and allows new instance to be created. + * @return a new instance of a NTAggregate. + */ + NTAggregatePtr create(); + /** + * Add extra Field to the type. + * @param name name of the field. + * @param field a field to add. + * @return this instance of NTAggregateBuilder. + */ + shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field); + + private: + NTAggregateBuilder(); + + void reset(); + + bool dispersion; + bool first; + bool firstTimeStamp; + bool last; + bool lastTimeStamp; + bool max; + bool min; + + 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::NTAggregate; + }; + +} + +typedef std::tr1::shared_ptr NTAggregateBuilderPtr; + + +/** + * @brief Convenience Class for NTAggregate + * + * @author dgh + */ +class epicsShareClass NTAggregate +{ +public: + POINTER_DEFINITIONS(NTAggregate); + + static const std::string URI; + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTAggregate. + * 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 NTAggregate. + * @return NTAggregate instance on success, nullptr otherwise. + */ + static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure); + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTAggregate. + * @return NTAggregate instance. + */ + static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure); + + /** + * Is the structure an NTAggregate. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTAggregate. + */ + static bool is_a(epics::pvData::StructureConstPtr const & structure); + /** + * Is the pvStructure compatible with NTAggregate. + * 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 NTMultiChannel. + */ + static bool isCompatible( + epics::pvData::PVStructurePtr const &pvStructure); + /** + * Create a NTAggregate builder instance. + * @return builder instance. + */ + static NTAggregateBuilderPtr createBuilder(); + + /** + * Destructor. + */ + ~NTAggregate() {} + + /** + * 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 or null if no function field. + */ + 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 value field. + * @return The PVDouble for the value. + */ + epics::pvData::PVDoublePtr getValue() const; + + /** + * Get the N field. + * @return The PVLong for the N field. + */ + epics::pvData::PVLongPtr getN() const; + + /** + * Get the dispersion field. + * @return The PVDouble for the dispersion which may be null + */ + epics::pvData::PVDoublePtr getDispersion() const; + + /** + * Get the first field. + * @return The PVDouble for the first field which may be null + */ + epics::pvData::PVDoublePtr getFirst() const; + + /** + * Get the firstTimeStamp field. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getFirstTimeStamp() const; + + /** + * Get the last field. + * @return The PVDouble for the last field which may be null + */ + epics::pvData::PVDoublePtr getLast() const; + + /** + * Get the lastTimeStamp field. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getLastTimeStamp() const; + + /** + * Get the max field. + * @return The PVDouble for the max field which may be null + */ + epics::pvData::PVDoublePtr getMax() const; + + /** + * Get the min field. + * @return The PVDouble for the max field which may be null + */ + epics::pvData::PVDoublePtr getMin() const; + +private: + NTAggregate(epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStructurePtr pvNTAggregate; + epics::pvData::PVDoublePtr pvValue; + + friend class detail::NTAggregateBuilder; +}; + +}} +#endif /* NTAGGREGATE_H */ diff --git a/src/nt/ntattribute.cpp b/src/nt/ntattribute.cpp new file mode 100644 index 0000000..468b9d5 --- /dev/null +++ b/src/nt/ntattribute.cpp @@ -0,0 +1,213 @@ +/* ntattribute.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 NTAttributeBuilder::createStructure() +{ + FieldBuilderPtr builder = + getFieldCreate()->createFieldBuilder()-> + setId(NTAttribute::URI)-> + add("name", pvString)-> + add("value", getFieldCreate()->createVariantUnion()); + + if (tags) + builder->addArray("tags", pvString); + + if (descriptor) + builder->add("descriptor", 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; +} + +NTAttributeBuilder::shared_pointer NTAttributeBuilder::addTags() +{ + tags = true; + return shared_from_this(); +} + +NTAttributeBuilder::shared_pointer NTAttributeBuilder::addDescriptor() +{ + descriptor = true; + return shared_from_this(); +} + +NTAttributeBuilder::shared_pointer NTAttributeBuilder::addAlarm() +{ + alarm = true; + return shared_from_this(); +} + +NTAttributeBuilder::shared_pointer NTAttributeBuilder::addTimeStamp() +{ + timeStamp = true; + return shared_from_this(); +} + +PVStructurePtr NTAttributeBuilder::createPVStructure() +{ + return getPVDataCreate()->createPVStructure(createStructure()); +} + +NTAttributePtr NTAttributeBuilder::create() +{ + return NTAttributePtr(new NTAttribute(createPVStructure())); +} + +NTAttributeBuilder::NTAttributeBuilder() +{ + reset(); +} + +void NTAttributeBuilder::reset() +{ + descriptor = false; + alarm = false; + timeStamp = false; + extraFieldNames.clear(); + extraFields.clear(); +} + +NTAttributeBuilder::shared_pointer NTAttributeBuilder::add(string const & name, FieldConstPtr const & field) +{ + extraFields.push_back(field); extraFieldNames.push_back(name); + return shared_from_this(); +} + +} + +const std::string NTAttribute::URI("epics:nt/NTAttribute:1.0"); + +NTAttribute::shared_pointer NTAttribute::wrap(PVStructurePtr const & structure) +{ + if(!isCompatible(structure)) return shared_pointer(); + return wrapUnsafe(structure); +} + +NTAttribute::shared_pointer NTAttribute::wrapUnsafe(PVStructurePtr const & structure) +{ + return shared_pointer(new NTAttribute(structure)); +} + +bool NTAttribute::is_a(StructureConstPtr const & structure) +{ + return NTUtils::is_a(structure->getID(), URI); +} + +bool NTAttribute::isCompatible(PVStructurePtr const & pvStructure) +{ + if(!pvStructure) return false; + + PVUnionPtr pvValue = pvStructure->getSubField("value"); + if(!pvValue) return false; + + PVFieldPtr pvField = pvStructure->getSubField("descriptor"); + if(pvField && !pvStructure->getSubField("descriptor")) return false; + + 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; +} + +NTAttributeBuilderPtr NTAttribute::createBuilder() +{ + return NTAttributeBuilderPtr(new detail::NTAttributeBuilder()); +} + +bool NTAttribute::attachTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTAttribute::attachAlarm(PVAlarm &pvAlarm) const +{ + PVStructurePtr al = getAlarm(); + if (al) + return pvAlarm.attach(al); + else + return false; +} + +PVStructurePtr NTAttribute::getPVStructure() const +{ + return pvNTAttribute; +} + +PVStringPtr NTAttribute::getDescriptor() const +{ + return pvNTAttribute->getSubField("descriptor"); +} + +PVStructurePtr NTAttribute::getTimeStamp() const +{ + return pvNTAttribute->getSubField("timeStamp"); +} + +PVStructurePtr NTAttribute::getAlarm() const +{ + return pvNTAttribute->getSubField("alarm"); +} + + +PVStringPtr NTAttribute::getName() const +{ + return pvNTAttribute->getSubField("name"); +} + +PVUnionPtr NTAttribute::getValue() const +{ + return pvValue; +} + +PVStringArrayPtr NTAttribute::getTags() const +{ + return pvNTAttribute->getSubField("tags"); +} + +NTAttribute::NTAttribute(PVStructurePtr const & pvStructure) : + pvNTAttribute(pvStructure), pvValue(pvNTAttribute->getSubField("value")) +{ +} + + +}} diff --git a/src/nt/ntattribute.h b/src/nt/ntattribute.h new file mode 100644 index 0000000..b090660 --- /dev/null +++ b/src/nt/ntattribute.h @@ -0,0 +1,240 @@ +/* ntattribute.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 NTATTRIBUTE_H +#define NTATTRIBUTE_H + +#ifdef epicsExportSharedSymbols +# define ntattributeEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#ifdef ntattributeEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef ntattributeEpicsExportSharedSymbols +#endif + +#include + +#include + +namespace epics { namespace nt { + +class NTAttribute; +typedef std::tr1::shared_ptr NTAttributePtr; + +namespace detail { + + /** + * @brief Interface for in-line creating of NTAttribute. + * + * 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 NTAttributeBuilder : + public std::tr1::enable_shared_from_this + { + public: + POINTER_DEFINITIONS(NTAttributeBuilder); + + /** + * Add tags field to the NTAttribute. + * @return this instance of NTAttributeBuilder. + */ + virtual shared_pointer addTags(); + + /** + * Add descriptor field to the NTAttribute. + * @return this instance of NTAttributeBuilder. + */ + shared_pointer addDescriptor(); + + /** + * Add alarm structure to the NTAttribute. + * @return this instance of NTAttributeBuilder. + */ + shared_pointer addAlarm(); + + /** + * Add timeStamp structure to the NTAttribute. + * @return this instance of NTAttributeBuilder. + */ + shared_pointer addTimeStamp(); + + /** + * Create a Structure that represents NTAttribute. + * 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 NTAttribute. + * 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 NTAttribute instance. + * This resets this instance state and allows new instance to be created. + * @return a new instance of a NTAttribute. + */ + NTAttributePtr create(); + /** + * Add extra Field to the type. + * @param name name of the field. + * @param field a field to add. + * @return this instance of NTAttributeBuilder. + */ + shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field); + + protected://private: + NTAttributeBuilder(); + + 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::NTAttribute; + }; + +} + +typedef std::tr1::shared_ptr NTAttributeBuilderPtr; + + + +/** + * @brief Convenience Class for NTAttribute + * + * @author dgh + */ +class epicsShareClass NTAttribute +{ +public: + POINTER_DEFINITIONS(NTAttribute); + + static const std::string URI; + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTAttribute. + * 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 NTAttribute. + * @return NTAttribute instance on success, nullptr otherwise. + */ + static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure); + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTAttribute. + * @return NTAttribute instance. + */ + static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure); + + /** + * Is the structure an NTAttribute. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTAttribute. + */ + static bool is_a(epics::pvData::StructureConstPtr const & structure); + /** + * Is the pvStructure compatible with NTAttribute. + * 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 NTMultiChannel. + */ + static bool isCompatible( + epics::pvData::PVStructurePtr const &pvStructure); + /** + * Create a NTAttribute builder instance. + * @return builder instance. + */ + static NTAttributeBuilderPtr createBuilder(); + + /** + * Destructor. + */ + ~NTAttribute() {} + + /** + * 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 or null if no function field. + */ + 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; + +private: + NTAttribute(epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStructurePtr pvNTAttribute; + epics::pvData::PVUnionPtr pvValue; + + friend class detail::NTAttributeBuilder; +}; + +}} +#endif /* NTATTRIBUTE_H */ diff --git a/src/nt/ntenum.cpp b/src/nt/ntenum.cpp new file mode 100644 index 0000000..213f444 --- /dev/null +++ b/src/nt/ntenum.cpp @@ -0,0 +1,190 @@ +/* ntenum.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 NTEnumBuilder::createStructure() +{ + FieldBuilderPtr builder = + getFieldCreate()->createFieldBuilder()-> + setId(NTEnum::URI)-> + add("value", ntField->createEnumerated()); + + if (descriptor) + builder->add("descriptor", 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; +} + +NTEnumBuilder::shared_pointer NTEnumBuilder::addDescriptor() +{ + descriptor = true; + return shared_from_this(); +} + +NTEnumBuilder::shared_pointer NTEnumBuilder::addAlarm() +{ + alarm = true; + return shared_from_this(); +} + +NTEnumBuilder::shared_pointer NTEnumBuilder::addTimeStamp() +{ + timeStamp = true; + return shared_from_this(); +} + +PVStructurePtr NTEnumBuilder::createPVStructure() +{ + return getPVDataCreate()->createPVStructure(createStructure()); +} + +NTEnumPtr NTEnumBuilder::create() +{ + return NTEnumPtr(new NTEnum(createPVStructure())); +} + +NTEnumBuilder::NTEnumBuilder() +{ + reset(); +} + +void NTEnumBuilder::reset() +{ + descriptor = false; + alarm = false; + timeStamp = false; + extraFieldNames.clear(); + extraFields.clear(); +} + +NTEnumBuilder::shared_pointer NTEnumBuilder::add(string const & name, FieldConstPtr const & field) +{ + extraFields.push_back(field); extraFieldNames.push_back(name); + return shared_from_this(); +} + + +} + +const std::string NTEnum::URI("epics:nt/NTEnum:1.0"); + +NTEnum::shared_pointer NTEnum::wrap(PVStructurePtr const & structure) +{ + if(!isCompatible(structure)) return shared_pointer(); + return wrapUnsafe(structure); +} + +NTEnum::shared_pointer NTEnum::wrapUnsafe(PVStructurePtr const & structure) +{ + return shared_pointer(new NTEnum(structure)); +} + +bool NTEnum::is_a(StructureConstPtr const & structure) +{ + return NTUtils::is_a(structure->getID(), URI); +} + +bool NTEnum::isCompatible(PVStructurePtr const & pvStructure) +{ + if(!pvStructure) return false; + PVStructurePtr pvValue = pvStructure->getSubField("value"); + if(!pvValue) return false; + if (!ntField->isEnumerated(pvValue->getField())) return false; + + PVFieldPtr pvField = pvStructure->getSubField("descriptor"); + if(pvField && !pvStructure->getSubField("descriptor")) return false; + 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; +} + +NTEnumBuilderPtr NTEnum::createBuilder() +{ + return NTEnumBuilderPtr(new detail::NTEnumBuilder()); +} + +bool NTEnum::attachTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTEnum::attachAlarm(PVAlarm &pvAlarm) const +{ + PVStructurePtr al = getAlarm(); + if (al) + return pvAlarm.attach(al); + else + return false; +} + +PVStructurePtr NTEnum::getPVStructure() const +{ + return pvNTEnum; +} + +PVStringPtr NTEnum::getDescriptor() const +{ + return pvNTEnum->getSubField("descriptor"); +} + +PVStructurePtr NTEnum::getTimeStamp() const +{ + return pvNTEnum->getSubField("timeStamp"); +} + +PVStructurePtr NTEnum::getAlarm() const +{ + return pvNTEnum->getSubField("alarm"); +} + +PVStructurePtr NTEnum::getValue() const +{ + return pvValue; +} + +NTEnum::NTEnum(PVStructurePtr const & pvStructure) : + pvNTEnum(pvStructure), pvValue(pvNTEnum->getSubField("value")) +{} + + +}} diff --git a/src/nt/ntenum.h b/src/nt/ntenum.h new file mode 100644 index 0000000..4e7fad8 --- /dev/null +++ b/src/nt/ntenum.h @@ -0,0 +1,221 @@ +/* ntenum.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 NTENUM_H +#define NTENUM_H + +#ifdef epicsExportSharedSymbols +# define ntenumEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#ifdef ntenumEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef ntenumEpicsExportSharedSymbols +#endif + +#include + +#include + +namespace epics { namespace nt { + +class NTEnum; +typedef std::tr1::shared_ptr NTEnumPtr; + +namespace detail { + + /** + * @brief Interface for in-line creating of NTEnum. + * + * 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 NTEnumBuilder : + public std::tr1::enable_shared_from_this + { + public: + POINTER_DEFINITIONS(NTEnumBuilder); + + /** + * Add descriptor field to the NTEnum. + * @return this instance of NTEnumBuilder. + */ + shared_pointer addDescriptor(); + + /** + * Add alarm structure to the NTEnum. + * @return this instance of NTEnumBuilder. + */ + shared_pointer addAlarm(); + + /** + * Add timeStamp structure to the NTEnum. + * @return this instance of NTEnumBuilder. + */ + shared_pointer addTimeStamp(); + + /** + * Create a Structure that represents NTEnum. + * 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 NTEnum. + * 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 NTEnum instance. + * This resets this instance state and allows new instance to be created. + * @return a new instance of a NTEnum. + */ + NTEnumPtr create(); + /** + * Add extra Field to the type. + * @param name name of the field. + * @param field a field to add. + * @return this instance of NTEnumBuilder. + */ + shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field); + + private: + NTEnumBuilder(); + + void reset(); + + 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::NTEnum; + }; + +} + +typedef std::tr1::shared_ptr NTEnumBuilderPtr; + + + +/** + * @brief Convenience Class for NTEnum + * + * @author dgh + */ +class epicsShareClass NTEnum +{ +public: + POINTER_DEFINITIONS(NTEnum); + + static const std::string URI; + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTEnum. + * 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 NTEnum. + * @return NTEnum instance on success, nullptr otherwise. + */ + static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure); + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTEnum. + * @return NTEnum instance. + */ + static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure); + + /** + * Is the structure an NTEnum. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTEnum. + */ + static bool is_a(epics::pvData::StructureConstPtr const & structure); + /** + * Is the pvStructure compatible with NTEnum. + * 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 NTMultiChannel. + */ + static bool isCompatible( + epics::pvData::PVStructurePtr const &pvStructure); + /** + * Create a NTEnum builder instance. + * @return builder instance. + */ + static NTEnumBuilderPtr createBuilder(); + + /** + * Destructor. + */ + ~NTEnum() {} + + /** + * 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 or null if no function field. + */ + 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 value field. + * @return The PVStructure for the values. + */ + epics::pvData::PVStructurePtr getValue() const; + +private: + NTEnum(epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStructurePtr pvNTEnum; + epics::pvData::PVStructurePtr pvValue; + + friend class detail::NTEnumBuilder; +}; + +}} +#endif /* NTENUM_H */ diff --git a/src/nt/ntmatrix.cpp b/src/nt/ntmatrix.cpp new file mode 100644 index 0000000..e7fdab0 --- /dev/null +++ b/src/nt/ntmatrix.cpp @@ -0,0 +1,228 @@ +/* ntmatrix.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 { + +StructureConstPtr NTMatrixBuilder::createStructure() +{ + FieldBuilderPtr builder = + getFieldCreate()->createFieldBuilder()-> + setId(NTMatrix::URI)-> + addArray("value", pvDouble); + + if (dim) + builder->addArray("dim", pvInt); + + if (descriptor) + builder->add("descriptor", pvString); + + if (alarm) + builder->add("alarm", ntField->createAlarm()); + + if (timeStamp) + builder->add("timeStamp", ntField->createTimeStamp()); + + if (display) + builder->add("display", ntField->createDisplay()); + + 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; +} + +NTMatrixBuilder::shared_pointer NTMatrixBuilder::addDim() +{ + dim = true; + return shared_from_this(); +} + +NTMatrixBuilder::shared_pointer NTMatrixBuilder::addDescriptor() +{ + descriptor = true; + return shared_from_this(); +} + +NTMatrixBuilder::shared_pointer NTMatrixBuilder::addAlarm() +{ + alarm = true; + return shared_from_this(); +} + +NTMatrixBuilder::shared_pointer NTMatrixBuilder::addTimeStamp() +{ + timeStamp = true; + return shared_from_this(); +} + +NTMatrixBuilder::shared_pointer NTMatrixBuilder::addDisplay() +{ + display = true; + return shared_from_this(); +} + +PVStructurePtr NTMatrixBuilder::createPVStructure() +{ + return getPVDataCreate()->createPVStructure(createStructure()); +} + +NTMatrixPtr NTMatrixBuilder::create() +{ + return NTMatrixPtr(new NTMatrix(createPVStructure())); +} + +NTMatrixBuilder::NTMatrixBuilder() +{ + reset(); +} + +void NTMatrixBuilder::reset() +{ + dim = false; + descriptor = false; + alarm = false; + timeStamp = false; + display = false; + extraFieldNames.clear(); + extraFields.clear(); +} + +NTMatrixBuilder::shared_pointer NTMatrixBuilder::add(string const & name, FieldConstPtr const & field) +{ + extraFields.push_back(field); extraFieldNames.push_back(name); + return shared_from_this(); +} + +} + +const std::string NTMatrix::URI("epics:nt/NTMatrix:1.0"); + +NTMatrix::shared_pointer NTMatrix::wrap(PVStructurePtr const & structure) +{ + if(!isCompatible(structure)) return shared_pointer(); + return wrapUnsafe(structure); +} + +NTMatrix::shared_pointer NTMatrix::wrapUnsafe(PVStructurePtr const & structure) +{ + return shared_pointer(new NTMatrix(structure)); +} + +bool NTMatrix::is_a(StructureConstPtr const & structure) +{ + return NTUtils::is_a(structure->getID(), URI); +} + +bool NTMatrix::isCompatible(PVStructurePtr const & pvStructure) +{ + if(!pvStructure) return false; + PVScalarArrayPtr pvValue = pvStructure->getSubField("value"); + if(!pvValue) return false; + PVFieldPtr pvField = pvStructure->getSubField("descriptor"); + if(pvField && !pvStructure->getSubField("descriptor")) return false; + pvField = pvStructure->getSubField("alarm"); + if(pvField && !ntField->isAlarm(pvField->getField())) return false; + pvField = pvStructure->getSubField("timeStamp"); + if(pvField && !ntField->isTimeStamp(pvField->getField())) return false; + pvField = pvStructure->getSubField("display"); + if(pvField && !ntField->isDisplay(pvField->getField())) return false; + pvField = pvStructure->getSubField("control"); + if(pvField && !ntField->isControl(pvField->getField())) return false; + return true; +} + + +NTMatrixBuilderPtr NTMatrix::createBuilder() +{ + return NTMatrixBuilderPtr(new detail::NTMatrixBuilder()); +} + +bool NTMatrix::attachTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTMatrix::attachAlarm(PVAlarm &pvAlarm) const +{ + PVStructurePtr al = getAlarm(); + if (al) + return pvAlarm.attach(al); + else + return false; +} + +bool NTMatrix::attachDisplay(PVDisplay &pvDisplay) const +{ + PVStructurePtr dp = getDisplay(); + if (dp) + return pvDisplay.attach(dp); + else + return false; +} + +PVStructurePtr NTMatrix::getPVStructure() const +{ + return pvNTMatrix; +} + +PVStringPtr NTMatrix::getDescriptor() const +{ + return pvNTMatrix->getSubField("descriptor"); +} + +PVStructurePtr NTMatrix::getTimeStamp() const +{ + return pvNTMatrix->getSubField("timeStamp"); +} + +PVStructurePtr NTMatrix::getAlarm() const +{ + return pvNTMatrix->getSubField("alarm"); +} + +PVStructurePtr NTMatrix::getDisplay() const +{ + return pvNTMatrix->getSubField("display"); +} + +PVDoubleArrayPtr NTMatrix::getValue() const +{ + return pvValue; +} + +PVIntArrayPtr NTMatrix::getDim() const +{ + return pvNTMatrix->getSubField("dim"); +} + +NTMatrix::NTMatrix(PVStructurePtr const & pvStructure) : + pvNTMatrix(pvStructure), + pvValue(pvNTMatrix->getSubField("value")) +{} + + +}} diff --git a/src/nt/ntmatrix.h b/src/nt/ntmatrix.h new file mode 100644 index 0000000..3eb0757 --- /dev/null +++ b/src/nt/ntmatrix.h @@ -0,0 +1,260 @@ +/* ntmatrix.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 NTMATRIX_H +#define NTMATRIX_H + +#ifdef epicsExportSharedSymbols +# define ntmatrixEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#include + +#ifdef ntmatrixEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef ntmatrixEpicsExportSharedSymbols +#endif + +#include + +#include + + +namespace epics { namespace nt { + +class NTMatrix; +typedef std::tr1::shared_ptr NTMatrixPtr; + +namespace detail { + + /** + * @brief Interface for in-line creating of NTMatrix. + * + * 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 NTMatrixBuilder : + public std::tr1::enable_shared_from_this + { + public: + POINTER_DEFINITIONS(NTMatrixBuilder); + + /** + * Add dimensionfield to the NTMatrix. + * @return this instance of NTMatrixBuilder. + */ + shared_pointer addDim(); + + /** + * Add descriptor field to the NTMatrix. + * @return this instance of NTMatrixBuilder. + */ + shared_pointer addDescriptor(); + + /** + * Add alarm structure to the NTMatrix. + * @return this instance of NTMatrixBuilder. + */ + shared_pointer addAlarm(); + + /** + * Add timeStamp structure to the NTMatrix. + * @return this instance of NTMatrixBuilder. + */ + shared_pointer addTimeStamp(); + + /** + * Add display structure to the NTMatrix. + * @return this instance of NTMatrixBuilder. + */ + shared_pointer addDisplay(); + + /** + * Create a Structure that represents NTMatrix. + * This resets this instance state and allows new instance to be created. + * @return a new instance of Structure. + */ + epics::pvData::StructureConstPtr createStructure(); + + /** + * Create a PVStructure that represents NTMatrix. + * This resets this instance state and allows new instance to be created. + * @return a new instance of PVStructure. + */ + epics::pvData::PVStructurePtr createPVStructure(); + + /** + * Create a NTMatrix instance. + * This resets this instance state and allows new instance to be created. + * @return a new instance of NTMatrix. + */ + NTMatrixPtr create(); + /** + * Add extra Field to the type. + * @param name name of the field. + * @param field a field to add. + * @return this instance of NTMatrixBuilder. + */ + shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field); + + private: + NTMatrixBuilder(); + + void reset(); + + bool dim; + bool descriptor; + bool alarm; + bool timeStamp; + bool display; + + // NOTE: this preserves order, however it does not handle duplicates + epics::pvData::StringArray extraFieldNames; + epics::pvData::FieldConstPtrArray extraFields; + + friend class ::epics::nt::NTMatrix; + }; + +} + +typedef std::tr1::shared_ptr NTMatrixBuilderPtr; + + + +/** + * @brief Convenience Class for NTMatrix + * + * @author dgh + */ +class epicsShareClass NTMatrix +{ +public: + POINTER_DEFINITIONS(NTMatrix); + + static const std::string URI; + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTMatrix. + * 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 NTMatrix. + * @return NTMatrix instance on success, nullptr otherwise. + */ + static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure); + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTMatrix. + * @return NTMatrix instance. + */ + static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure); + + + /** + * Is the structure an NTMatrix. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTMatrix. + */ + static bool is_a(epics::pvData::StructureConstPtr const & structure); + /** + * Is the pvStructure compatible with NTMatrix.. + * 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 NTMultiChannel. + */ + static bool isCompatible( + epics::pvData::PVStructurePtr const &pvStructure); + + /** + * Create a NTMatrix builder instance. + * @return builder instance. + */ + static NTMatrixBuilderPtr createBuilder(); + + /** + * Destructor. + */ + ~NTMatrix() {} + + /** + * 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; + + /** + * Attach an pvDisplay. + * @param pvDisplay The pvDisplay that will be attached. + * Does nothing if no display. + * @return true if the operation was successfull (i.e. this instance has a display field), otherwise false. + */ + bool attachDisplay(epics::pvData::PVDisplay &pvDisplay) const; + + /** + * Get the pvStructure. + * @return PVStructurePtr. + */ + epics::pvData::PVStructurePtr getPVStructure() const; + + /** + * Get the descriptor field. + * @return The pvString or null if no function field. + */ + 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 display. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getDisplay() const; + + /** + * Get the value field. + * @return The PVDoubleArray for the values. + */ + epics::pvData::PVDoubleArrayPtr getValue() const; + + /** + * Get the dim field. + * @return The PVIntArray for the dim which may be null. + */ + epics::pvData::PVIntArrayPtr getDim() const; + +private: + NTMatrix(epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStructurePtr pvNTMatrix; + epics::pvData::PVDoubleArrayPtr pvValue; + + friend class detail::NTMatrixBuilder; +}; + +}} +#endif /* NTMATRIX_H */ diff --git a/src/nt/ntunion.cpp b/src/nt/ntunion.cpp new file mode 100644 index 0000000..f911f71 --- /dev/null +++ b/src/nt/ntunion.cpp @@ -0,0 +1,193 @@ +/* ntunion.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 NTUnionBuilder::createStructure() +{ + FieldBuilderPtr builder = + getFieldCreate()->createFieldBuilder()-> + setId(NTUnion::URI)-> + add("value", valueType); + + if (descriptor) + builder->add("descriptor", 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; +} + +NTUnionBuilder::shared_pointer NTUnionBuilder::addDescriptor() +{ + descriptor = true; + return shared_from_this(); +} + +NTUnionBuilder::shared_pointer NTUnionBuilder::addAlarm() +{ + alarm = true; + return shared_from_this(); +} + +NTUnionBuilder::shared_pointer NTUnionBuilder::addTimeStamp() +{ + timeStamp = true; + return shared_from_this(); +} + +PVStructurePtr NTUnionBuilder::createPVStructure() +{ + return getPVDataCreate()->createPVStructure(createStructure()); +} + +NTUnionPtr NTUnionBuilder::create() +{ + return NTUnionPtr(new NTUnion(createPVStructure())); +} + +NTUnionBuilder::NTUnionBuilder() +{ + reset(); +} + +void NTUnionBuilder::reset() +{ + valueType = getFieldCreate()->createVariantUnion(); + descriptor = false; + alarm = false; + timeStamp = false; + extraFieldNames.clear(); + extraFields.clear(); +} + +NTUnionBuilder::shared_pointer NTUnionBuilder::add(string const & name, FieldConstPtr const & field) +{ + extraFields.push_back(field); extraFieldNames.push_back(name); + return shared_from_this(); +} + + +} + +const std::string NTUnion::URI("epics:nt/NTUnion:1.0"); + +NTUnion::shared_pointer NTUnion::wrap(PVStructurePtr const & structure) +{ + if(!isCompatible(structure)) return shared_pointer(); + return wrapUnsafe(structure); +} + +NTUnion::shared_pointer NTUnion::wrapUnsafe(PVStructurePtr const & structure) +{ + return shared_pointer(new NTUnion(structure)); +} + +bool NTUnion::is_a(StructureConstPtr const & structure) +{ + return NTUtils::is_a(structure->getID(), URI); +} + +bool NTUnion::isCompatible(PVStructurePtr const & pvStructure) +{ + if(!pvStructure) return false; + + PVUnionPtr pvValue = pvStructure->getSubField("value"); + if(!pvValue) return false; + + PVFieldPtr pvField = pvStructure->getSubField("descriptor"); + if(pvField && !pvStructure->getSubField("descriptor")) return false; + + 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; +} + +NTUnionBuilderPtr NTUnion::createBuilder() +{ + return NTUnionBuilderPtr(new detail::NTUnionBuilder()); +} + +bool NTUnion::attachTimeStamp(PVTimeStamp &pvTimeStamp) const +{ + PVStructurePtr ts = getTimeStamp(); + if (ts) + return pvTimeStamp.attach(ts); + else + return false; +} + +bool NTUnion::attachAlarm(PVAlarm &pvAlarm) const +{ + PVStructurePtr al = getAlarm(); + if (al) + return pvAlarm.attach(al); + else + return false; +} + +PVStructurePtr NTUnion::getPVStructure() const +{ + return pvNTUnion; +} + +PVStringPtr NTUnion::getDescriptor() const +{ + return pvNTUnion->getSubField("descriptor"); +} + +PVStructurePtr NTUnion::getTimeStamp() const +{ + return pvNTUnion->getSubField("timeStamp"); +} + +PVStructurePtr NTUnion::getAlarm() const +{ + return pvNTUnion->getSubField("alarm"); +} + +PVUnionPtr NTUnion::getValue() const +{ + return pvValue; +} + +NTUnion::NTUnion(PVStructurePtr const & pvStructure) : + pvNTUnion(pvStructure), pvValue(pvNTUnion->getSubField("value")) +{} + + +}} diff --git a/src/nt/ntunion.h b/src/nt/ntunion.h new file mode 100644 index 0000000..f080f84 --- /dev/null +++ b/src/nt/ntunion.h @@ -0,0 +1,223 @@ +/* ntunion.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 NTUNION_H +#define NTUNION_H + +#ifdef epicsExportSharedSymbols +# define ntunionEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#ifdef ntunionEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef ntunionEpicsExportSharedSymbols +#endif + +#include + +#include + +namespace epics { namespace nt { + +class NTUnion; +typedef std::tr1::shared_ptr NTUnionPtr; + +namespace detail { + + /** + * @brief Interface for in-line creating of NTUnion. + * + * 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 NTUnionBuilder : + public std::tr1::enable_shared_from_this + { + public: + POINTER_DEFINITIONS(NTUnionBuilder); + + /** + * Add descriptor field to the NTUnion. + * @return this instance of NTUnionBuilder. + */ + shared_pointer addDescriptor(); + + /** + * Add alarm structure to the NTUnion. + * @return this instance of NTUnionBuilder. + */ + shared_pointer addAlarm(); + + /** + * Add timeStamp structure to the NTUnion. + * @return this instance of NTUnionBuilder. + */ + shared_pointer addTimeStamp(); + + /** + * Create a Structure that represents NTUnion. + * 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 NTUnion. + * 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 NTUnion instance. + * This resets this instance state and allows new instance to be created. + * @return a new instance of a NTUnion. + */ + NTUnionPtr create(); + /** + * Add extra Field to the type. + * @param name name of the field. + * @param field a field to add. + * @return this instance of NTUnionBuilder. + */ + shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field); + + private: + NTUnionBuilder(); + + epics::pvData::UnionConstPtr valueType; + + void reset(); + + 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::NTUnion; + }; + +} + +typedef std::tr1::shared_ptr NTUnionBuilderPtr; + + + +/** + * @brief Convenience Class for NTUnion + * + * @author dgh + */ +class epicsShareClass NTUnion +{ +public: + POINTER_DEFINITIONS(NTUnion); + + static const std::string URI; + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTUnion. + * 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 NTUnion. + * @return NTUnion instance on success, nullptr otherwise. + */ + static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure); + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTMultiChannel without checking for isCompatible + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTUnion. + * @return NTUnion instance. + */ + static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure); + + /** + * Is the structure an NTUnion. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTUnion. + */ + static bool is_a(epics::pvData::StructureConstPtr const & structure); + /** + * Is the pvStructure compatible with NTUnion. + * 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 NTMultiChannel. + */ + static bool isCompatible( + epics::pvData::PVStructurePtr const &pvStructure); + /** + * Create a NTUnion builder instance. + * @return builder instance. + */ + static NTUnionBuilderPtr createBuilder(); + + /** + * Destructor. + */ + ~NTUnion() {} + + /** + * 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 or null if no function field. + */ + 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 value field. + * @return The PVUnion for the values. + */ + epics::pvData::PVUnionPtr getValue() const; + +private: + NTUnion(epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStructurePtr pvNTUnion; + epics::pvData::PVUnionPtr pvValue; + + friend class detail::NTUnionBuilder; +}; + +}} +#endif /* NTUNION_H */ diff --git a/test/nt/Makefile b/test/nt/Makefile index d948e0d..2369833 100644 --- a/test/nt/Makefile +++ b/test/nt/Makefile @@ -36,6 +36,26 @@ TESTPROD_HOST += ntndarrayTest ntndarrayTest_SRCS = ntndarrayTest.cpp TESTS += ntndarrayTest +TESTPROD_HOST += ntmatrixTest +ntmatrixTest_SRCS = ntmatrixTest.cpp +TESTS += ntmatrixTest + +TESTPROD_HOST += ntenumTest +ntenumTest_SRCS = ntenumTest.cpp +TESTS += ntenumTest + +TESTPROD_HOST += ntunionTest +ntunionTest_SRCS = ntunionTest.cpp +TESTS += ntunionTest + +TESTPROD_HOST += ntaggregateTest +ntaggregateTest_SRCS = ntaggregateTest.cpp +TESTS += ntaggregateTest + +TESTPROD_HOST += ntattributeTest +ntattributeTest_SRCS = ntattributeTest.cpp +TESTS += ntattributeTest + TESTPROD_HOST += ntutilsTest ntutilsTest_SRCS = ntutilsTest.cpp TESTS += ntutilsTest diff --git a/test/nt/ntaggregateTest.cpp b/test/nt/ntaggregateTest.cpp new file mode 100644 index 0000000..3d961a6 --- /dev/null +++ b/test/nt/ntaggregateTest.cpp @@ -0,0 +1,175 @@ +/** + * 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 + +#include + + +using namespace epics::nt; +using namespace epics::pvData; +using std::tr1::dynamic_pointer_cast; + +static FieldCreatePtr fieldCreate = getFieldCreate(); +static StandardFieldPtr standardField = getStandardField(); +static NTFieldPtr ntField = NTField::get(); + +void test_builder() +{ + testDiag("test_builder"); + + NTAggregateBuilderPtr builder = NTAggregate::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + StructureConstPtr structure = builder-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + add("valueAlarm",standardField->doubleAlarm()) -> + add("extra",fieldCreate->createScalarArray(pvString)) -> + createStructure(); + testOk1(structure.get() != 0); + if (!structure) + return; + + testOk1(NTAggregate::is_a(structure)); + testOk1(structure->getID() == NTAggregate::URI); + testOk1(structure->getNumberFields() == 7); + testOk1(structure->getField("value").get() != 0); + testOk1(structure->getField("descriptor").get() != 0); + testOk1(structure->getField("alarm").get() != 0); + testOk1(structure->getField("timeStamp").get() != 0); + + ScalarConstPtr valueField = structure->getField("value"); + testOk(valueField.get() != 0, "value is scalar"); + + std::cout << *structure << std::endl; + +} + +void test_ntaggregate() +{ + testDiag("test_ntaggregate"); + + NTAggregateBuilderPtr builder = NTAggregate::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + NTAggregatePtr ntAggregate = builder-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + add("valueAlarm",standardField->intAlarm()) -> + create(); + testOk1(ntAggregate.get() != 0); + + testOk1(ntAggregate->getPVStructure().get() != 0); + testOk1(ntAggregate->getValue().get() != 0); + testOk1(ntAggregate->getDescriptor().get() != 0); + testOk1(ntAggregate->getAlarm().get() != 0); + testOk1(ntAggregate->getTimeStamp().get() != 0); + + // + // example how to set a value + // + ntAggregate->getValue()->put(1.0); + + // + // example how to get a value + // + double value = ntAggregate->getValue()->get(); + testOk1(value == 1.0); + + // + // timeStamp ops + // + PVTimeStamp pvTimeStamp; + if (ntAggregate->attachTimeStamp(pvTimeStamp)) + { + testPass("timeStamp attach"); + + // example how to set current time + TimeStamp ts; + ts.getCurrent(); + pvTimeStamp.set(ts); + + // example how to get EPICS time + TimeStamp ts2; + pvTimeStamp.get(ts2); + testOk1(ts2.getEpicsSecondsPastEpoch() != 0); + } + else + testFail("timeStamp attach fail"); + + // + // alarm ops + // + PVAlarm pvAlarm; + if (ntAggregate->attachAlarm(pvAlarm)) + { + testPass("alarm attach"); + + // example how to set an alarm + Alarm alarm; + alarm.setStatus(deviceStatus); + alarm.setSeverity(minorAlarm); + alarm.setMessage("simulation alarm"); + pvAlarm.set(alarm); + } + else + testFail("alarm attach fail"); + + // + // set descriptor + // + ntAggregate->getDescriptor()->put("This is a test NTAggregate"); + + // dump ntAggregate + std::cout << *ntAggregate->getPVStructure() << std::endl; + +} + +void test_wrap() +{ + testDiag("test_wrap"); + + NTAggregatePtr nullPtr = NTAggregate::wrap(PVStructurePtr()); + testOk(nullPtr.get() == 0, "nullptr wrap"); + + nullPtr = NTAggregate::wrap( + getPVDataCreate()->createPVStructure( + NTField::get()->createTimeStamp() + ) + ); + testOk(nullPtr.get() == 0, "wrong type wrap"); + + + NTAggregateBuilderPtr builder = NTAggregate::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + PVStructurePtr pvStructure = builder-> + createPVStructure(); + testOk1(pvStructure.get() != 0); + if (!pvStructure) + return; + + testOk1(NTAggregate::isCompatible(pvStructure)==true); + NTAggregatePtr ptr = NTAggregate::wrap(pvStructure); + testOk(ptr.get() != 0, "wrap OK"); + + ptr = NTAggregate::wrapUnsafe(pvStructure); + testOk(ptr.get() != 0, "wrapUnsafe OK"); +} + +MAIN(testNTAggregate) { + testPlan(28); + test_builder(); + test_ntaggregate(); + test_wrap(); + return testDone(); +} + + diff --git a/test/nt/ntattributeTest.cpp b/test/nt/ntattributeTest.cpp new file mode 100644 index 0000000..5e46bdb --- /dev/null +++ b/test/nt/ntattributeTest.cpp @@ -0,0 +1,176 @@ +/** + * 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 + +#include + + +using namespace epics::nt; +using namespace epics::pvData; +using std::tr1::dynamic_pointer_cast; + +static FieldCreatePtr fieldCreate = getFieldCreate(); +static StandardFieldPtr standardField = getStandardField(); +static NTFieldPtr ntField = NTField::get(); + +void test_builder() +{ + testDiag("test_builder"); + + NTAttributeBuilderPtr builder = NTAttribute::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + StructureConstPtr structure = builder-> + addTags()-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + add("extra",fieldCreate->createScalar(pvString)) -> + createStructure(); + testOk1(structure.get() != 0); + if (!structure) + return; + + testOk1(NTAttribute::is_a(structure)); + testOk1(structure->getID() == NTAttribute::URI); + testOk1(structure->getNumberFields() == 7); + testOk1(structure->getField("name").get() != 0); + testOk1(structure->getField("value").get() != 0); + testOk1(structure->getField("tags").get() != 0); + testOk1(structure->getField("descriptor").get() != 0); + testOk1(structure->getField("alarm").get() != 0); + testOk1(structure->getField("timeStamp").get() != 0); + + ScalarConstPtr nameField = structure->getField("name"); + testOk(nameField.get() != 0 && nameField->getScalarType() == pvString, + "name is string"); + + UnionConstPtr valueField = structure->getField("value"); + testOk(valueField.get() != 0, "value is enum"); + + ScalarArrayConstPtr tagsField = structure->getField("tags"); + testOk(tagsField.get() != 0 && tagsField->getElementType() == pvString, + "tags is string[]"); + + std::cout << *structure << std::endl; + +} + +void test_ntattribute() +{ + testDiag("test_ntattribute"); + + NTAttributeBuilderPtr builder = NTAttribute::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + NTAttributePtr ntAttribute = builder-> + addTags()-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + create(); + testOk1(ntAttribute.get() != 0); + + testOk1(ntAttribute->getPVStructure().get() != 0); + testOk1(ntAttribute->getName().get() != 0); + testOk1(ntAttribute->getValue().get() != 0); + testOk1(ntAttribute->getTags().get() != 0); + testOk1(ntAttribute->getDescriptor().get() != 0); + testOk1(ntAttribute->getAlarm().get() != 0); + testOk1(ntAttribute->getTimeStamp().get() != 0); + + // + // timeStamp ops + // + PVTimeStamp pvTimeStamp; + if (ntAttribute->attachTimeStamp(pvTimeStamp)) + { + testPass("timeStamp attach"); + + // example how to set current time + TimeStamp ts; + ts.getCurrent(); + pvTimeStamp.set(ts); + + // example how to get EPICS time + TimeStamp ts2; + pvTimeStamp.get(ts2); + testOk1(ts2.getEpicsSecondsPastEpoch() != 0); + } + else + testFail("timeStamp attach fail"); + + // + // alarm ops + // + PVAlarm pvAlarm; + if (ntAttribute->attachAlarm(pvAlarm)) + { + testPass("alarm attach"); + + // example how to set an alarm + Alarm alarm; + alarm.setStatus(deviceStatus); + alarm.setSeverity(minorAlarm); + alarm.setMessage("simulation alarm"); + pvAlarm.set(alarm); + } + else + testFail("alarm attach fail"); + + // + // set descriptor + // + ntAttribute->getDescriptor()->put("This is a test NTAttribute"); + + // dump ntAttribute + std::cout << *ntAttribute->getPVStructure() << std::endl; + +} + +void test_wrap() +{ + testDiag("test_wrap"); + + NTAttributePtr nullPtr = NTAttribute::wrap(PVStructurePtr()); + testOk(nullPtr.get() == 0, "nullptr wrap"); + + nullPtr = NTAttribute::wrap( + getPVDataCreate()->createPVStructure( + NTField::get()->createTimeStamp() + ) + ); + testOk(nullPtr.get() == 0, "wrong type wrap"); + + + NTAttributeBuilderPtr builder = NTAttribute::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + PVStructurePtr pvStructure = builder-> + createPVStructure(); + testOk1(pvStructure.get() != 0); + if (!pvStructure) + return; + + testOk1(NTAttribute::isCompatible(pvStructure)==true); + NTAttributePtr ptr = NTAttribute::wrap(pvStructure); + testOk(ptr.get() != 0, "wrap OK"); + + ptr = NTAttribute::wrapUnsafe(pvStructure); + testOk(ptr.get() != 0, "wrapUnsafe OK"); +} + +MAIN(testNTAttribute) { + testPlan(33); + test_builder(); + test_ntattribute(); + test_wrap(); + return testDone(); +} + + diff --git a/test/nt/ntenumTest.cpp b/test/nt/ntenumTest.cpp new file mode 100644 index 0000000..2b36205 --- /dev/null +++ b/test/nt/ntenumTest.cpp @@ -0,0 +1,188 @@ +/** + * 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 + +#include + + +using namespace epics::nt; +using namespace epics::pvData; +using std::tr1::dynamic_pointer_cast; + +static FieldCreatePtr fieldCreate = getFieldCreate(); +static StandardFieldPtr standardField = getStandardField(); +static NTFieldPtr ntField = NTField::get(); + +void test_builder() +{ + testDiag("test_builder"); + + NTEnumBuilderPtr builder = NTEnum::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + StructureConstPtr structure = builder-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + add("valueAlarm",standardField->doubleAlarm()) -> + add("extra",fieldCreate->createScalarArray(pvString)) -> + createStructure(); + testOk1(structure.get() != 0); + if (!structure) + return; + + testOk1(NTEnum::is_a(structure)); + testOk1(structure->getID() == NTEnum::URI); + testOk1(structure->getNumberFields() == 6); + testOk1(structure->getField("value").get() != 0); + testOk1(structure->getField("descriptor").get() != 0); + testOk1(structure->getField("alarm").get() != 0); + testOk1(structure->getField("timeStamp").get() != 0); + + FieldConstPtr valueField = structure->getField("value"); + testOk(valueField.get() != 0 && + ntField->isEnumerated(valueField), "value is enum"); + + std::cout << *structure << std::endl; + +} + +void test_ntenum() +{ + testDiag("test_ntenum"); + + NTEnumBuilderPtr builder = NTEnum::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + NTEnumPtr ntEnum = builder-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + add("valueAlarm",standardField->intAlarm()) -> + create(); + testOk1(ntEnum.get() != 0); + + testOk1(ntEnum->getPVStructure().get() != 0); + testOk1(ntEnum->getValue().get() != 0); + testOk1(ntEnum->getDescriptor().get() != 0); + testOk1(ntEnum->getAlarm().get() != 0); + testOk1(ntEnum->getTimeStamp().get() != 0); + + // + // example how to set a value + // + PVStructurePtr pvValue = ntEnum->getValue(); + //PVStringArray pvChoices = pvValue->getSubField("choices"); + PVStringArray::svector choices(2); + choices[0] = "Off"; + choices[1] = "On"; + pvValue->getSubField("choices")->replace(freeze(choices)); + pvValue->getSubField("index")->put(1); + + // + // example how to get a value + // + int32 value = ntEnum->getValue()->getSubField("index")->get(); + testOk1(value == 1); + + PVStringArrayPtr pvChoices = ntEnum->getValue()->getSubField("choices"); + std::string choice0 = pvChoices->view()[0]; + std::string choice1 = pvChoices->view()[1]; + testOk1(choice0 == "Off"); + testOk1(choice1 == "On"); + + // + // timeStamp ops + // + PVTimeStamp pvTimeStamp; + if (ntEnum->attachTimeStamp(pvTimeStamp)) + { + testPass("timeStamp attach"); + + // example how to set current time + TimeStamp ts; + ts.getCurrent(); + pvTimeStamp.set(ts); + + // example how to get EPICS time + TimeStamp ts2; + pvTimeStamp.get(ts2); + testOk1(ts2.getEpicsSecondsPastEpoch() != 0); + } + else + testFail("timeStamp attach fail"); + + // + // alarm ops + // + PVAlarm pvAlarm; + if (ntEnum->attachAlarm(pvAlarm)) + { + testPass("alarm attach"); + + // example how to set an alarm + Alarm alarm; + alarm.setStatus(deviceStatus); + alarm.setSeverity(minorAlarm); + alarm.setMessage("simulation alarm"); + pvAlarm.set(alarm); + } + else + testFail("alarm attach fail"); + + // + // set descriptor + // + ntEnum->getDescriptor()->put("This is a test NTEnum"); + + // dump ntEnum + std::cout << *ntEnum->getPVStructure() << std::endl; + +} + +void test_wrap() +{ + testDiag("test_wrap"); + + NTEnumPtr nullPtr = NTEnum::wrap(PVStructurePtr()); + testOk(nullPtr.get() == 0, "nullptr wrap"); + + nullPtr = NTEnum::wrap( + getPVDataCreate()->createPVStructure( + NTField::get()->createTimeStamp() + ) + ); + testOk(nullPtr.get() == 0, "wrong type wrap"); + + + NTEnumBuilderPtr builder = NTEnum::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + PVStructurePtr pvStructure = builder-> + createPVStructure(); + testOk1(pvStructure.get() != 0); + if (!pvStructure) + return; + + testOk1(NTEnum::isCompatible(pvStructure)==true); + NTEnumPtr ptr = NTEnum::wrap(pvStructure); + testOk(ptr.get() != 0, "wrap OK"); + + ptr = NTEnum::wrapUnsafe(pvStructure); + testOk(ptr.get() != 0, "wrapUnsafe OK"); +} + +MAIN(testNTEnum) { + testPlan(30); + test_builder(); + test_ntenum(); + test_wrap(); + return testDone(); +} + + diff --git a/test/nt/ntmatrixTest.cpp b/test/nt/ntmatrixTest.cpp new file mode 100644 index 0000000..175cdda --- /dev/null +++ b/test/nt/ntmatrixTest.cpp @@ -0,0 +1,211 @@ +/** + * 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 + +#include + +using namespace epics::nt; +using namespace epics::pvData; +using std::tr1::dynamic_pointer_cast; + +static FieldCreatePtr fieldCreate = getFieldCreate(); + +void test_builder() +{ + testDiag("test_builder"); + + NTMatrixBuilderPtr builder = NTMatrix::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + StructureConstPtr structure = builder-> + //arrayValue(pvDouble)-> + addDim()-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + addDisplay()-> + add("extra1",fieldCreate->createScalar(pvString)) -> + add("extra2",fieldCreate->createScalarArray(pvString)) -> + createStructure(); + testOk1(structure.get() != 0); + if (!structure) + return; + + testOk1(NTMatrix::is_a(structure)); + testOk1(structure->getID() == NTMatrix::URI); + testOk1(structure->getNumberFields() == 8); + testOk1(structure->getField("value").get() != 0); + testOk1(structure->getField("dim").get() != 0); + testOk1(structure->getField("descriptor").get() != 0); + testOk1(structure->getField("alarm").get() != 0); + testOk1(structure->getField("timeStamp").get() != 0); + testOk1(structure->getField("display").get() != 0); + + testOk(dynamic_pointer_cast(structure->getField("value")).get() != 0 && + dynamic_pointer_cast(structure->getField("value"))->getElementType() == pvDouble, "value type"); + + std::cout << *structure << std::endl; +} + +void test_ntmatrix() +{ + testDiag("test_ntmatrix"); + + NTMatrixBuilderPtr builder = NTMatrix::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + NTMatrixPtr ntScalarArray = builder-> + //arrayValue(pvInt)-> + addDim()-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + addDisplay()-> + create(); + testOk1(ntScalarArray.get() != 0); + + testOk1(ntScalarArray->getPVStructure().get() != 0); + testOk1(ntScalarArray->getValue().get() != 0); + testOk1(ntScalarArray->getDim().get() != 0); + testOk1(ntScalarArray->getDescriptor().get() != 0); + testOk1(ntScalarArray->getAlarm().get() != 0); + testOk1(ntScalarArray->getTimeStamp().get() != 0); + testOk1(ntScalarArray->getDisplay().get() != 0); + + // + // example how to set values + // + PVDoubleArray::svector newValues; + newValues.push_back(1.0); + newValues.push_back(2.0); + newValues.push_back(8.0); + + PVDoubleArrayPtr pvValueField = ntScalarArray->getValue(); + pvValueField->replace(freeze(newValues)); + + // + // example how to get values + // + PVDoubleArray::const_svector values(pvValueField->view()); + + testOk1(values.size() == 3); + testOk1(values[0] == 1.0); + testOk1(values[1] == 2.0); + testOk1(values[2] == 8.0); + + // + // timeStamp ops + // + PVTimeStamp pvTimeStamp; + if (ntScalarArray->attachTimeStamp(pvTimeStamp)) + { + testPass("timeStamp attach"); + + // example how to set current time + TimeStamp ts; + ts.getCurrent(); + pvTimeStamp.set(ts); + + // example how to get EPICS time + TimeStamp ts2; + pvTimeStamp.get(ts2); + testOk1(ts2.getEpicsSecondsPastEpoch() != 0); + } + else + testFail("timeStamp attach fail"); + + // + // alarm ops + // + PVAlarm pvAlarm; + if (ntScalarArray->attachAlarm(pvAlarm)) + { + testPass("alarm attach"); + + // example how to set an alarm + Alarm alarm; + alarm.setStatus(deviceStatus); + alarm.setSeverity(minorAlarm); + alarm.setMessage("simulation alarm"); + pvAlarm.set(alarm); + } + else + testFail("alarm attach fail"); + + // + // display ops + // + PVDisplay pvDisplay; + if (ntScalarArray->attachDisplay(pvDisplay)) + { + testPass("display attach"); + + // example how to set an display + Display display; + display.setLow(-15); + display.setHigh(15); + display.setDescription("This is a test scalar array"); + display.setFormat("%d"); + display.setUnits("A"); + pvDisplay.set(display); + } + else + testFail("display attach fail"); + + // + // set descriptor + // + ntScalarArray->getDescriptor()->put("This is a test NTMatrix"); + + // dump ntScalarArray + std::cout << *ntScalarArray->getPVStructure() << std::endl; + +} + + +void test_wrap() +{ + testDiag("test_wrap"); + + NTMatrixPtr nullPtr = NTMatrix::wrap(PVStructurePtr()); + testOk(nullPtr.get() == 0, "nullptr wrap"); + + nullPtr = NTMatrix::wrap( + getPVDataCreate()->createPVStructure( + NTField::get()->createTimeStamp() + ) + ); + testOk(nullPtr.get() == 0, "wrong type wrap"); + + + NTMatrixBuilderPtr builder = NTMatrix::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + PVStructurePtr pvStructure = builder-> + createPVStructure(); + testOk1(pvStructure.get() != 0); + if (!pvStructure) + return; + + testOk1(NTMatrix::isCompatible(pvStructure)==true); + NTMatrixPtr ptr = NTMatrix::wrap(pvStructure); + testOk(ptr.get() != 0, "wrap OK"); + + ptr = NTMatrix::wrapUnsafe(pvStructure); + testOk(ptr.get() != 0, "wrapUnsafe OK"); +} + +MAIN(testNTMatrix) { + testPlan(36); + test_builder(); + test_ntmatrix(); + test_wrap(); + return testDone(); +} + + diff --git a/test/nt/ntunionTest.cpp b/test/nt/ntunionTest.cpp new file mode 100644 index 0000000..8224fe4 --- /dev/null +++ b/test/nt/ntunionTest.cpp @@ -0,0 +1,167 @@ +/** + * 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 + +#include + + +using namespace epics::nt; +using namespace epics::pvData; +using std::tr1::dynamic_pointer_cast; + +static FieldCreatePtr fieldCreate = getFieldCreate(); +static StandardFieldPtr standardField = getStandardField(); +static NTFieldPtr ntField = NTField::get(); + +void test_builder() +{ + testDiag("test_builder"); + + NTUnionBuilderPtr builder = NTUnion::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + StructureConstPtr structure = builder-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + add("valueAlarm",standardField->doubleAlarm()) -> + add("extra",fieldCreate->createScalarArray(pvString)) -> + createStructure(); + testOk1(structure.get() != 0); + if (!structure) + return; + + testOk1(NTUnion::is_a(structure)); + testOk1(structure->getID() == NTUnion::URI); + testOk1(structure->getNumberFields() == 6); + testOk1(structure->getField("value").get() != 0); + testOk1(structure->getField("descriptor").get() != 0); + testOk1(structure->getField("alarm").get() != 0); + testOk1(structure->getField("timeStamp").get() != 0); + + UnionConstPtr valueField = structure->getField("value"); + testOk(valueField.get() != 0, "value is enum"); + + std::cout << *structure << std::endl; + +} + +void test_ntunion() +{ + testDiag("test_ntunion"); + + NTUnionBuilderPtr builder = NTUnion::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + NTUnionPtr ntUnion = builder-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + create(); + testOk1(ntUnion.get() != 0); + + testOk1(ntUnion->getPVStructure().get() != 0); + testOk1(ntUnion->getValue().get() != 0); + testOk1(ntUnion->getDescriptor().get() != 0); + testOk1(ntUnion->getAlarm().get() != 0); + testOk1(ntUnion->getTimeStamp().get() != 0); + + // TODO + // 1. Variant union example. + // 2. set the union value. + + // + // timeStamp ops + // + PVTimeStamp pvTimeStamp; + if (ntUnion->attachTimeStamp(pvTimeStamp)) + { + testPass("timeStamp attach"); + + // example how to set current time + TimeStamp ts; + ts.getCurrent(); + pvTimeStamp.set(ts); + + // example how to get EPICS time + TimeStamp ts2; + pvTimeStamp.get(ts2); + testOk1(ts2.getEpicsSecondsPastEpoch() != 0); + } + else + testFail("timeStamp attach fail"); + + // + // alarm ops + // + PVAlarm pvAlarm; + if (ntUnion->attachAlarm(pvAlarm)) + { + testPass("alarm attach"); + + // example how to set an alarm + Alarm alarm; + alarm.setStatus(deviceStatus); + alarm.setSeverity(minorAlarm); + alarm.setMessage("simulation alarm"); + pvAlarm.set(alarm); + } + else + testFail("alarm attach fail"); + + // + // set descriptor + // + ntUnion->getDescriptor()->put("This is a test NTUnion"); + + // dump ntUnion + std::cout << *ntUnion->getPVStructure() << std::endl; + +} + +void test_wrap() +{ + testDiag("test_wrap"); + + NTUnionPtr nullPtr = NTUnion::wrap(PVStructurePtr()); + testOk(nullPtr.get() == 0, "nullptr wrap"); + + nullPtr = NTUnion::wrap( + getPVDataCreate()->createPVStructure( + NTField::get()->createTimeStamp() + ) + ); + testOk(nullPtr.get() == 0, "wrong type wrap"); + + + NTUnionBuilderPtr builder = NTUnion::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + PVStructurePtr pvStructure = builder-> + createPVStructure(); + testOk1(pvStructure.get() != 0); + if (!pvStructure) + return; + + testOk1(NTUnion::isCompatible(pvStructure)==true); + NTUnionPtr ptr = NTUnion::wrap(pvStructure); + testOk(ptr.get() != 0, "wrap OK"); + + ptr = NTUnion::wrapUnsafe(pvStructure); + testOk(ptr.get() != 0, "wrapUnsafe OK"); +} + +MAIN(testNTUnion) { + testPlan(27); + test_builder(); + test_ntunion(); + test_wrap(); + return testDone(); +} + +