diff --git a/src/Makefile b/src/Makefile index 2e1fb32..663c92b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ INC += ntscalarArray.h INC += ntnameValue.h INC += nttable.h INC += ntmultiChannel.h +INC += ntscalarMultiChannel.h INC += ntndarray.h LIBSRCS += ntutils.cpp @@ -22,6 +23,7 @@ LIBSRCS += ntscalarArray.cpp LIBSRCS += ntnameValue.cpp LIBSRCS += nttable.cpp LIBSRCS += ntmultiChannel.cpp +LIBSRCS += ntscalarMultiChannel.cpp LIBSRCS += ntndarray.cpp LIBRARY = nt diff --git a/src/nt/ntscalarMultiChannel.cpp b/src/nt/ntscalarMultiChannel.cpp new file mode 100644 index 0000000..2d45142 --- /dev/null +++ b/src/nt/ntscalarMultiChannel.cpp @@ -0,0 +1,278 @@ +/* ntscalarMultiChannel.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvDataCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ + +#include + +#define epicsExportSharedSymbols +#include +#include + +using namespace std; +using namespace epics::pvData; + +namespace epics { namespace nt { + + +static FieldCreatePtr fieldCreate = getFieldCreate(); +static PVDataCreatePtr pvDataCreate = getPVDataCreate(); +static NTFieldPtr ntField = NTField::get(); + +namespace detail { + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::value(ScalarType scalarType) +{ + valueType = scalarType; + return shared_from_this(); +} + + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addDescriptor() +{ + descriptor = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addAlarm() +{ + alarm = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addTimeStamp() +{ + timeStamp = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addSeverity() +{ + severity = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addStatus() +{ + status = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addMessage() +{ + message = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addSecondsPastEpoch() +{ + secondsPastEpoch = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addNanoseconds() +{ + nanoseconds = true; + return shared_from_this(); +} + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::addUserTag() +{ + userTag = true; + return shared_from_this(); +} + +StructureConstPtr NTScalarMultiChannelBuilder::createStructure() +{ + StandardFieldPtr standardField = getStandardField(); + size_t nfields = 3; + size_t extraCount = extraFieldNames.size(); + nfields += extraCount; + if(descriptor) ++nfields; + if(alarm) ++nfields; + if(timeStamp) ++nfields; + if(severity) ++nfields; + if(status) ++nfields; + if(message) ++nfields; + if(secondsPastEpoch) ++nfields; + if(nanoseconds) ++nfields; + if(userTag) ++nfields; + FieldConstPtrArray fields(nfields); + StringArray names(nfields); + size_t ind = 0; + names[ind] = "value"; + fields[ind++] = fieldCreate->createScalarArray(valueType); + names[ind] = "channelName"; + fields[ind++] = fieldCreate->createScalarArray(pvString); + names[ind] = "isConnected"; + fields[ind++] = fieldCreate->createScalarArray(pvBoolean); + if(descriptor) { + names[ind] = "descriptor"; + fields[ind++] = fieldCreate->createScalar(pvString); + } + if(alarm) { + names[ind] = "alarm"; + fields[ind++] = standardField->alarm(); + } + if(timeStamp) { + names[ind] = "timeStamp"; + fields[ind++] = standardField->timeStamp(); + } + if(severity) { + names[ind] = "severity"; + fields[ind++] = fieldCreate->createScalarArray(pvInt); + } + if(status) { + names[ind] = "status"; + fields[ind++] = fieldCreate->createScalarArray(pvInt); + } + if(message) { + names[ind] = "message"; + fields[ind++] = fieldCreate->createScalarArray(pvString); + } + if(secondsPastEpoch) { + names[ind] = "secondsPastEpoch"; + fields[ind++] = fieldCreate->createScalarArray(pvLong); + } + if(nanoseconds) { + names[ind] = "nanoseconds"; + fields[ind++] = fieldCreate->createScalarArray(pvInt); + } + if(userTag) { + names[ind] = "userTag"; + fields[ind++] = fieldCreate->createScalarArray(pvInt); + } + for (size_t i = 0; i< extraCount; i++) { + names[ind] = extraFieldNames[i]; + fields[ind++] = extraFields[i]; + } + + StructureConstPtr st = fieldCreate->createStructure(NTScalarMultiChannel::URI,names,fields); + reset(); + return st; +} + +PVStructurePtr NTScalarMultiChannelBuilder::createPVStructure() +{ + return pvDataCreate->createPVStructure(createStructure()); +} + +NTScalarMultiChannelPtr NTScalarMultiChannelBuilder::create() +{ + return NTScalarMultiChannelPtr(new NTScalarMultiChannel(createPVStructure())); +} + +NTScalarMultiChannelBuilder::NTScalarMultiChannelBuilder() +: valueType(pvDouble) +{ + reset(); +} + +void NTScalarMultiChannelBuilder::reset() +{ + extraFieldNames.clear(); + extraFields.clear(); + valueType = pvDouble; + descriptor = false; + alarm = false; + timeStamp = false; + severity = false; + status = false; + message = false; + secondsPastEpoch = false; + nanoseconds = false; + userTag = false; +} + + +NTScalarMultiChannelBuilder::shared_pointer NTScalarMultiChannelBuilder::add(string const & name, FieldConstPtr const & field) +{ + extraFields.push_back(field); extraFieldNames.push_back(name); + return shared_from_this(); +} + +} + +const std::string NTScalarMultiChannel::URI("epics:nt/NTScalarMultiChannel:1.0"); + +NTScalarMultiChannel::shared_pointer NTScalarMultiChannel::wrap(PVStructurePtr const & structure) +{ + if(!isCompatible(structure)) return shared_pointer(); + return wrapUnsafe(structure); +} + +NTScalarMultiChannel::shared_pointer NTScalarMultiChannel::wrapUnsafe(PVStructurePtr const & structure) +{ + return shared_pointer(new NTScalarMultiChannel(structure)); +} + +bool NTScalarMultiChannel::is_a(StructureConstPtr const &structure) +{ + return NTUtils::is_a(structure->getID(), URI); +} + +bool NTScalarMultiChannel::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("severity"); + if(pvField && !pvStructure->getSubField("severity")) return false; + pvField = pvStructure->getSubField("status"); + if(pvField && !pvStructure->getSubField("status")) return false; + pvField = pvStructure->getSubField("message"); + if(pvField && !pvStructure->getSubField("message")) return false; + pvField = pvStructure->getSubField("secondsPastEpoch"); + if(pvField && !pvStructure->getSubField("secondsPastEpoch")) return false; + pvField = pvStructure->getSubField("nanoseconds"); + if(pvField && !pvStructure->getSubField("nanoseconds")) return false; + pvField = pvStructure->getSubField("userTag"); + if(pvField && !pvStructure->getSubField("userTag")) return false; + return true; +} + +NTScalarMultiChannelBuilderPtr NTScalarMultiChannel::createBuilder() +{ + return NTScalarMultiChannelBuilderPtr(new detail::NTScalarMultiChannelBuilder()); +} + + +NTScalarMultiChannel::NTScalarMultiChannel(PVStructurePtr const & pvStructure) +: pvNTScalarMultiChannel(pvStructure), + pvTimeStamp(pvStructure->getSubField("timeStamp")), + pvAlarm(pvStructure->getSubField("alarm")), + pvValue(pvStructure->getSubField("value")), + pvChannelName(pvStructure->getSubField("channelName")), + pvIsConnected(pvStructure->getSubField("isConnected")), + pvSeverity(pvStructure->getSubField("severity")), + pvStatus(pvStructure->getSubField("status")), + pvMessage(pvStructure->getSubField("message")), + pvSecondsPastEpoch(pvStructure->getSubField("secondsPastEpoch")), + pvNanoseconds(pvStructure->getSubField("nanoseconds")), + pvUserTag(pvStructure->getSubField("userTag")), + pvDescriptor(pvStructure->getSubField("descriptor")) +{ +} + + +void NTScalarMultiChannel::attachTimeStamp(PVTimeStamp &pv) const +{ + if(!pvTimeStamp) return; + pv.attach(pvTimeStamp); +} + +void NTScalarMultiChannel::attachAlarm(PVAlarm &pv) const +{ + if(!pvAlarm) return; + pv.attach(pvAlarm); +} + +}} diff --git a/src/nt/ntscalarMultiChannel.h b/src/nt/ntscalarMultiChannel.h new file mode 100644 index 0000000..9b8c295 --- /dev/null +++ b/src/nt/ntscalarMultiChannel.h @@ -0,0 +1,328 @@ +/* ntscalarMultiChannel.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 NTSCALARMULTICHANNEL_H +#define NTSCALARMULTICHANNEL_H + +#include +#include + +#ifdef epicsExportSharedSymbols +# define ntscalarMultiChannelEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#include +#include + +#ifdef ntscalarMultiChannelEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef ntscalarMultiChannelEpicsExportSharedSymbols +#endif + +#include + +#include + + +namespace epics { namespace nt { + + +class NTScalarMultiChannel; +typedef std::tr1::shared_ptr NTScalarMultiChannelPtr; + +namespace detail { + + /** + * @brief Interface for in-line creating of NTScalarMultiChannel. + * + * 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 + * @author mse + */ + class epicsShareClass NTScalarMultiChannelBuilder : + public std::tr1::enable_shared_from_this + { + public: + POINTER_DEFINITIONS(NTScalarMultiChannelBuilder); + /** + * specify the scalar type for the value field. + * If this is not called then pvDouble is the default. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer value(epics::pvData::ScalarType scalarType); + /** + * Add descriptor field to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addDescriptor(); + /** + * Add alarm structure to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addAlarm(); + /** + * Add timeStamp structure to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addTimeStamp(); + /** + * Add severity array to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addSeverity(); + /** + * Add status array to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addStatus(); + /** + * Add message array to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addMessage(); + /** + * Add secondsPastEpoch array to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addSecondsPastEpoch(); + /** + * Add nanoseconds array to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addNanoseconds(); + /** + * Add userTag array to the NTScalarMultiChannel. + * @return this instance of NTScalarMultiChannelBuilder. + */ + shared_pointer addUserTag(); + /** + * Create a Structure that represents NTScalarMultiChannel. + * 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 NTScalarMultiChannel. + * This resets this instance state and allows new {@code instance to be created.} + * @return a new instance of a PVStructure + */ + epics::pvData::PVStructurePtr createPVStructure(); + /** + * Create a NTScalarMultiChannel instance. + * This resets this instance state and allows new {@code instance to be created.} + * @return a new instance of a NTScalarMultiChannel + */ + NTScalarMultiChannelPtr create(); + /** + * Add extra Field to the type. + * @param name name of the field. + * @param field a field to add. + * @return this instance of a NTScalarMultiChannelBuilder + */ + shared_pointer add(std::string const & name, epics::pvData::FieldConstPtr const & field); + private: + NTScalarMultiChannelBuilder(); + + void reset(); + + epics::pvData::ScalarType valueType; + bool descriptor; + bool alarm; + bool timeStamp; + bool severity; + bool status; + bool message; + bool secondsPastEpoch; + bool nanoseconds; + bool userTag; + + // NOTE: this preserves order, however it does not handle duplicates + epics::pvData::StringArray extraFieldNames; + epics::pvData::FieldConstPtrArray extraFields; + + friend class ::epics::nt::NTScalarMultiChannel; + }; + +} + +typedef std::tr1::shared_ptr NTScalarMultiChannelBuilderPtr; + + +/** + * @brief Convenience Class for NTScalarMultiChannel + * @author dgh + * @author mrk + * + */ +class epicsShareClass NTScalarMultiChannel +{ +public: + POINTER_DEFINITIONS(NTScalarMultiChannel); + + static const std::string URI; + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTScalarMultiChannel. + * First isCompatible is called. + * This method will nullptr if the structure is is not compatible. + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarMultiChannel. + * @return NTScalarMultiChannel instance on success, nullptr otherwise. + */ + static shared_pointer wrap(epics::pvData::PVStructurePtr const & structure); + + /** + * Wrap (aka dynamic cast, or wrap) the structure to NTScalarMultiChannel without checking for isCompatible + * @param structure The structure to wrap-ed (dynamic cast, wrapped) to NTScalarMultiChannel. + * @return NTScalarMultiChannel instance. + */ + static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const & structure); + /** + * Is the Structure an NTScalarMultiChannel. + * This method structure->getID() and checks if it is the same as the URI. + * @param structure The structure to test. + * @return (false,true) if (is not, is) an NTScalarMultiChannel. + */ + static bool is_a( + epics::pvData::StructureConstPtr const &structure); + /** + * Is the pvStructure compatible with NTScalarMultiChannel. + * 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 NTScalarMultiChannel. + */ + static bool isCompatible( + epics::pvData::PVStructurePtr const &pvStructure); + /** + * Create a NTScalarMultiChannelBuilder instance + * @return builder instance. + */ + static NTScalarMultiChannelBuilderPtr createBuilder(); + + /** + * Destructor + */ + ~NTScalarMultiChannel() {} + /** + * Attach a pvTimeStamp. + * @param pvTimeStamp The pvTimeStamp that will be attached. + * Does nothing if no timeStamp + */ + void attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const; + /** + * Attach a pvAlarm. + * @param pvAlarm The pvAlarm that will be attached. + * Does nothing if no alarm + */ + void attachAlarm(epics::pvData::PVAlarm &pvAlarm) const; + /** + * Get the pvStructure. + * @return PVStructurePtr. + */ + epics::pvData::PVStructurePtr getPVStructure() const + {return pvNTScalarMultiChannel;} + /** + * Get the timeStamp. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getTimeStamp() const + {return pvTimeStamp;} + /** + * Get the alarm. + * @return PVStructurePtr which may be null. + */ + epics::pvData::PVStructurePtr getAlarm() const + {return pvAlarm;} + /** + * Get the value of each channel. + * @return PVScalarArrayPtr + */ + epics::pvData::PVScalarArrayPtr getValue() const + {return pvValue;} + /** + * Get the value field of a specified type (e.g. PVDoubleArray). + * @return The field for the values. + */ + template + std::tr1::shared_ptr getValue() const + { + return std::tr1::dynamic_pointer_cast(pvValue); + } + /** + * Get the channelName of each channel. + * @return PVStringArrayPtr + */ + epics::pvData::PVStringArrayPtr getChannelName() const + { return pvChannelName;}; + /** + * Get the connection state of each channel. + * @return PVBooleanArrayPtr + */ + epics::pvData::PVBooleanArrayPtr getIsConnected() const + { return pvIsConnected;}; + /** + * Get the severity of each channel. + * @return PVIntArrayPtr which may be null. + */ + epics::pvData::PVIntArrayPtr getSeverity() const + {return pvSeverity;} + /** + * Get the status of each channel. + * @return PVIntArrayPtr which may be null. + */ + epics::pvData::PVIntArrayPtr getStatus() const + {return pvStatus;} + /** + * Get the message of each chnnel. + * @return PVStringArrayPtr which may be null. + */ + epics::pvData::PVStringArrayPtr getMessage() const + {return pvMessage;} + /** + * Get the secondsPastEpoch of each channel. + * @return PVLongArrayPtr which may be null. + */ + epics::pvData::PVLongArrayPtr getSecondsPastEpoch() const + {return pvSecondsPastEpoch;} + /** + * Get the nanoseconds of each channel. + * @return PVIntArrayPtr which may be null. + */ + epics::pvData::PVIntArrayPtr getNanoseconds() const + {return pvNanoseconds;} + /** + * Get the userTag of each channel. + * @return PVIntArrayPtr which may be null. + */ + epics::pvData::PVIntArrayPtr getUserTag() const + {return pvUserTag;} + /** + * Get the descriptor. + * @return PVStringPtr which may be null. + */ + epics::pvData::PVStringPtr getDescriptor() const + {return pvDescriptor;} +private: + NTScalarMultiChannel(epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStructurePtr pvNTScalarMultiChannel; + epics::pvData::PVStructurePtr pvTimeStamp; + epics::pvData::PVStructurePtr pvAlarm; + epics::pvData::PVScalarArrayPtr pvValue; + epics::pvData::PVStringArrayPtr pvChannelName; + epics::pvData::PVBooleanArrayPtr pvIsConnected; + epics::pvData::PVIntArrayPtr pvSeverity; + epics::pvData::PVIntArrayPtr pvStatus; + epics::pvData::PVStringArrayPtr pvMessage; + epics::pvData::PVLongArrayPtr pvSecondsPastEpoch; + epics::pvData::PVIntArrayPtr pvNanoseconds; + epics::pvData::PVIntArrayPtr pvUserTag; + epics::pvData::PVStringPtr pvDescriptor; + friend class detail::NTScalarMultiChannelBuilder; +}; + +}} +#endif /* NTSCALARMULTICHANNEL_H */ diff --git a/test/nt/Makefile b/test/nt/Makefile index 9aa0587..d948e0d 100644 --- a/test/nt/Makefile +++ b/test/nt/Makefile @@ -24,6 +24,10 @@ TESTPROD_HOST += ntmultiChannelTest ntmultiChannelTest_SRCS += ntmultiChannelTest.cpp TESTS += ntmultiChannelTest +TESTPROD_HOST += ntscalarMultiChannelTest +ntscalarMultiChannelTest_SRCS += ntscalarMultiChannelTest.cpp +TESTS += ntscalarMultiChannelTest + TESTPROD_HOST += nttableTest nttableTest_SRCS = nttableTest.cpp TESTS += nttableTest diff --git a/test/nt/ntscalarMultiChannelTest.cpp b/test/nt/ntscalarMultiChannelTest.cpp new file mode 100644 index 0000000..97bd199 --- /dev/null +++ b/test/nt/ntscalarMultiChannelTest.cpp @@ -0,0 +1,179 @@ +/** + * 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. + */ +/* + * ntscalarMultiChannelTest.cpp + * + * Created on: 2015.08 + * Authors: Marty Kraimer, Dave Hickin + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +#include +#include +#include + +using namespace epics::pvData; +using namespace epics::nt; +using std::string; +using std::cout; +using std::endl; +using std::vector; + +static bool debug = false; + +static FieldCreatePtr fieldCreate = getFieldCreate(); +static PVDataCreatePtr pvDataCreate = getPVDataCreate(); +static NTFieldPtr ntField = NTField::get(); +static PVNTFieldPtr pvntField = PVNTField::get(); + +static void test() +{ + NTScalarMultiChannelBuilderPtr builder = NTScalarMultiChannel::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + NTScalarMultiChannelPtr multiChannel = builder-> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + addSeverity() -> + add("extra1",fieldCreate->createScalar(pvString)) -> + add("extra2",fieldCreate->createScalarArray(pvString)) -> + create(); + testOk1(multiChannel.get() != 0); + + PVStructurePtr pvStructure = multiChannel->getPVStructure(); + testOk1(pvStructure.get()!=NULL); + testOk1(NTScalarMultiChannel::is_a(pvStructure->getStructure())); + size_t nchan = 3; + shared_vector names(nchan); + names[0] = "channel 0"; + names[1] = "channel 1"; + names[2] = "channel 2"; + shared_vector channelNames(freeze(names)); + PVStringArrayPtr pvChannelName = multiChannel->getChannelName(); + pvChannelName->replace(channelNames); + if(debug) {cout << *pvStructure << endl;} + multiChannel = builder-> + value(pvDouble) -> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + addSeverity() -> + create(); + testOk1(multiChannel.get() != 0); + pvStructure = multiChannel->getPVStructure(); + if(debug) {cout << *pvStructure << endl;} + pvChannelName = multiChannel->getChannelName(); + pvChannelName->replace(channelNames); + PVDoubleArrayPtr pvValue = multiChannel->getValue(); + PVDoubleArray::svector doubles(nchan); + doubles.resize(nchan); + doubles[0] = 3.14159; + doubles[1] = 2.71828; + doubles[2] = 137.036; + pvValue->replace(freeze(doubles)); + shared_vector severities(nchan); + severities[0] = 0; + severities[1] = 1; + severities[2] = 2; + PVIntArrayPtr pvSeverity = multiChannel->getSeverity(); + pvSeverity->replace(freeze(severities)); + if(debug) {cout << *pvStructure << endl;} + PVBooleanArrayPtr pvIsConnected = multiChannel->getIsConnected(); + shared_vector isConnected = pvIsConnected->view(); + multiChannel = builder-> + value(pvDouble) -> + addDescriptor()-> + addAlarm()-> + addTimeStamp()-> + addSeverity() -> + addStatus() -> + addMessage() -> + addSecondsPastEpoch() -> + addNanoseconds() -> + addUserTag() -> + create(); + testOk1(multiChannel.get() != 0); + pvStructure = multiChannel->getPVStructure(); + if(debug) {cout << *pvStructure << endl;} + testOk1(NTScalarMultiChannel::isCompatible(pvStructure)==true); + PVStructurePtr pvTimeStamp = multiChannel->getTimeStamp(); + testOk1(pvTimeStamp.get() !=0); + PVStructurePtr pvAlarm = multiChannel->getAlarm(); + testOk1(pvAlarm.get() !=0); + pvValue = multiChannel->getValue(); + testOk1(pvValue.get() !=0); + pvChannelName = multiChannel->getChannelName(); + testOk1(pvChannelName.get() !=0); + pvIsConnected = multiChannel->getIsConnected(); + testOk1(pvIsConnected.get() !=0); + pvSeverity = multiChannel->getSeverity(); + testOk1(pvSeverity.get() !=0); + PVIntArrayPtr pvStatus = multiChannel->getStatus(); + testOk1(pvStatus.get() !=0); + PVStringArrayPtr pvMessage = multiChannel->getMessage(); + testOk1(pvMessage.get() !=0); + PVLongArrayPtr pvSecondsPastEpoch = multiChannel->getSecondsPastEpoch(); + testOk1(pvSecondsPastEpoch.get() !=0); + PVIntArrayPtr pvNanoseconds = multiChannel->getNanoseconds(); + testOk1(pvNanoseconds.get() !=0); + PVIntArrayPtr pvUserTag = multiChannel->getUserTag(); + testOk1(pvUserTag.get() !=0); + PVStringPtr pvDescriptor = multiChannel->getDescriptor(); + testOk1(pvDescriptor.get() !=0); +} + + +void test_wrap() +{ + testDiag("test_wrap"); + + NTScalarMultiChannelPtr nullPtr = NTScalarMultiChannel::wrap(PVStructurePtr()); + testOk(nullPtr.get() == 0, "nullptr wrap"); + + nullPtr = NTScalarMultiChannel::wrap( + getPVDataCreate()->createPVStructure( + NTField::get()->createTimeStamp() + ) + ); + testOk(nullPtr.get() == 0, "wrong type wrap"); + + + NTScalarMultiChannelBuilderPtr builder = NTScalarMultiChannel::createBuilder(); + testOk(builder.get() != 0, "Got builder"); + + PVStructurePtr pvStructure = builder-> + createPVStructure(); + testOk1(pvStructure.get() != 0); + if (!pvStructure) + return; + + NTScalarMultiChannelPtr ptr = NTScalarMultiChannel::wrap(pvStructure); + testOk(ptr.get() != 0, "wrap OK"); + + builder = NTScalarMultiChannel::createBuilder(); + ptr = NTScalarMultiChannel::wrapUnsafe(pvStructure); + testOk(ptr.get() != 0, "wrapUnsafe OK"); +} + +MAIN(testCreateRequest) +{ + testPlan(25); + test(); + test_wrap(); + return testDone(); +} +