change to implement builder
This commit is contained in:
@@ -6,121 +6,181 @@
|
||||
*/
|
||||
|
||||
#include <pv/ntmultiChannel.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace nt {
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
|
||||
bool NTMultiChannel::isNTMultiChannel(PVStructurePtr const & pvStructure)
|
||||
namespace detail {
|
||||
|
||||
static NTFieldPtr ntField = NTField::get();
|
||||
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addValue(UnionConstPtr valuePtr)
|
||||
{
|
||||
PVUnionArrayPtr pvValue = pvStructure->getSubField<PVUnionArray>("value");
|
||||
if(!pvValue) return false;
|
||||
PVStringArrayPtr pvChannelName =
|
||||
pvStructure->getSubField<PVStringArray>("channelName");
|
||||
return true;
|
||||
value = true;
|
||||
valueUnion = valuePtr;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelPtr NTMultiChannel::create(
|
||||
std::vector<std::string> const & optionNames)
|
||||
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addDescriptor()
|
||||
{
|
||||
return NTMultiChannel::create(optionNames,fieldCreate->createVariantUnion());
|
||||
descriptor = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelPtr NTMultiChannel::create(
|
||||
std::vector<std::string> const & optionNames,
|
||||
epics::pvData::UnionConstPtr const & unionPtr)
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addAlarm()
|
||||
{
|
||||
shared_vector<const std::string> channelNames;
|
||||
return NTMultiChannel::create(optionNames,unionPtr,channelNames);
|
||||
alarm = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelPtr NTMultiChannel::create(
|
||||
std::vector<std::string> const & optionNames,
|
||||
UnionConstPtr const & unionPtr,
|
||||
shared_vector<const std::string> channelNames)
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addTimeStamp()
|
||||
{
|
||||
timeStamp = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSeverity()
|
||||
{
|
||||
severity = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addStatus()
|
||||
{
|
||||
status = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addMessage()
|
||||
{
|
||||
message = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSecondsPastEpoch()
|
||||
{
|
||||
secondsPastEpoch = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addNanoseconds()
|
||||
{
|
||||
nanoseconds = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
StructureConstPtr NTMultiChannelBuilder::createStructure()
|
||||
{
|
||||
StandardFieldPtr standardField = getStandardField();
|
||||
size_t nfields = 2;
|
||||
bool hasAlarm = false;
|
||||
bool hasTimeStamp = false;
|
||||
bool hasSeverity = false;
|
||||
bool hasStatus = false;
|
||||
bool hasMessage = false;
|
||||
bool hasSecondsPastEpoch = false;
|
||||
bool hasNanoseconds = false;
|
||||
bool hasDescriptor = false;
|
||||
for(size_t i=0; i<optionNames.size(); ++i) {
|
||||
string name = optionNames[i];
|
||||
if(name.compare("alarm")==0) {hasAlarm = true; ++nfields;}
|
||||
if(name.compare("timeStamp")==0) {hasTimeStamp = true; ++nfields;}
|
||||
if(name.compare("severity")==0) {hasSeverity = true; ++nfields;}
|
||||
if(name.compare("status")==0) {hasStatus = true; ++nfields;}
|
||||
if(name.compare("message")==0) {hasMessage = true; ++nfields;}
|
||||
if(name.compare("secondsPastEpoch")==0) {hasSecondsPastEpoch = true; ++nfields;}
|
||||
if(name.compare("nanoseconds`")==0) {hasNanoseconds = true; ++nfields;}
|
||||
if(name.compare("descriptor")==0) {hasDescriptor = true; ++nfields;}
|
||||
}
|
||||
if(descriptor) ++nfields;
|
||||
if(alarm) ++nfields;
|
||||
if(timeStamp) ++nfields;
|
||||
if(severity) ++nfields;
|
||||
if(status) ++nfields;
|
||||
if(message) ++nfields;
|
||||
if(secondsPastEpoch) ++nfields;
|
||||
if(nanoseconds) ++nfields;
|
||||
FieldConstPtrArray fields(nfields);
|
||||
StringArray names(nfields);
|
||||
size_t ind = 0;
|
||||
names[ind] = "value";
|
||||
fields[ind++] = fieldCreate->createUnionArray(unionPtr);
|
||||
if(value) {
|
||||
fields[ind++] = fieldCreate->createUnionArray(valueUnion);
|
||||
} else {
|
||||
fields[ind++] = fieldCreate->createVariantUnion();
|
||||
}
|
||||
names[ind] = "channelName";
|
||||
fields[ind++] = fieldCreate->createScalarArray(pvString);
|
||||
if(hasTimeStamp) {
|
||||
if(timeStamp) {
|
||||
names[ind] = "timeStamp";
|
||||
fields[ind++] = standardField->timeStamp();
|
||||
}
|
||||
if(hasAlarm) {
|
||||
if(alarm) {
|
||||
names[ind] = "alarm";
|
||||
fields[ind++] = standardField->alarm();
|
||||
}
|
||||
if(hasDescriptor) {
|
||||
if(descriptor) {
|
||||
names[ind] = "descriptor";
|
||||
fields[ind++] = fieldCreate->createScalar(pvString);
|
||||
}
|
||||
if(hasSeverity) {
|
||||
if(severity) {
|
||||
names[ind] = "severity";
|
||||
fields[ind++] = fieldCreate->createScalarArray(pvInt);
|
||||
}
|
||||
if(hasStatus) {
|
||||
if(status) {
|
||||
names[ind] = "status";
|
||||
fields[ind++] = fieldCreate->createScalarArray(pvInt);
|
||||
}
|
||||
if(hasMessage) {
|
||||
if(message) {
|
||||
names[ind] = "message";
|
||||
fields[ind++] = fieldCreate->createScalarArray(pvString);
|
||||
}
|
||||
if(hasSecondsPastEpoch) {
|
||||
if(secondsPastEpoch) {
|
||||
names[ind] = "secondsPastEpoch";
|
||||
fields[ind++] = fieldCreate->createScalarArray(pvLong);
|
||||
}
|
||||
if(hasNanoseconds) {
|
||||
if(nanoseconds) {
|
||||
names[ind] = "nanoseconds";
|
||||
fields[ind++] = fieldCreate->createScalarArray(pvInt);
|
||||
}
|
||||
StructureConstPtr st = fieldCreate->createStructure(names,fields);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(st);
|
||||
if(channelNames.size()>0) {
|
||||
PVStringArrayPtr pvName = pvStructure->getSubField<PVStringArray>("channelName");
|
||||
pvName->replace(channelNames);
|
||||
}
|
||||
return NTMultiChannelPtr(new NTMultiChannel(pvStructure));
|
||||
StructureConstPtr st = fieldCreate->createStructure(NTMultiChannel::URI,names,fields);
|
||||
reset();
|
||||
return st;
|
||||
}
|
||||
|
||||
NTMultiChannelPtr NTMultiChannel::clone(PVStructurePtr const & pv)
|
||||
PVStructurePtr NTMultiChannelBuilder::NTMultiChannelBuilder::createPVStructure()
|
||||
{
|
||||
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(pv);
|
||||
return NTMultiChannelPtr(new NTMultiChannel(pvStructure));
|
||||
return pvDataCreate->createPVStructure(createStructure());
|
||||
}
|
||||
|
||||
NTMultiChannelPtr NTMultiChannelBuilder::create()
|
||||
{
|
||||
return NTMultiChannelPtr(new NTMultiChannel(createPVStructure()));
|
||||
}
|
||||
|
||||
NTMultiChannelBuilder::NTMultiChannelBuilder()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void NTMultiChannelBuilder::reset()
|
||||
{
|
||||
valueUnion.reset();
|
||||
value = false;
|
||||
descriptor = false;
|
||||
alarm = false;
|
||||
timeStamp = false;
|
||||
severity = false;
|
||||
status = false;
|
||||
message = false;
|
||||
secondsPastEpoch = false;
|
||||
nanoseconds = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::string NTMultiChannel::URI("uri:ev4:nt/2012/pwd:NTMultiChannel");
|
||||
|
||||
bool NTMultiChannel::is_a(StructureConstPtr const &structure)
|
||||
{
|
||||
return structure->getID() == URI;
|
||||
}
|
||||
|
||||
NTMultiChannelBuilderPtr NTMultiChannel::createBuilder()
|
||||
{
|
||||
return NTMultiChannelBuilderPtr(new detail::NTMultiChannelBuilder());
|
||||
}
|
||||
|
||||
|
||||
NTMultiChannel::NTMultiChannel(PVStructurePtr const & pvStructure)
|
||||
: pvNTMultiChannel(pvStructure),
|
||||
pvTimeStamp(pvStructure->getSubField<PVStructure>("timeStamp")),
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#define NTMULTICHANNEL_H
|
||||
|
||||
#include <pv/ntfield.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace epics { namespace nt {
|
||||
|
||||
@@ -20,27 +23,125 @@ namespace epics { namespace nt {
|
||||
class NTMultiChannel;
|
||||
typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr;
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Interface for in-line creating of NTMultiChannel.
|
||||
* 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 mse
|
||||
*/
|
||||
class epicsShareClass NTMultiChannelBuilder :
|
||||
public std::tr1::enable_shared_from_this<NTMultiChannelBuilder>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(NTMultiChannelBuilder);
|
||||
/**
|
||||
* specify the union for the value field.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addValue(epics::pvData::UnionConstPtr valuePtr);
|
||||
/**
|
||||
* Add descriptor field to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addDescriptor();
|
||||
/**
|
||||
* Add alarm structure to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addAlarm();
|
||||
/**
|
||||
* Add timeStamp structure to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addTimeStamp();
|
||||
/**
|
||||
* Add severity array to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addSeverity();
|
||||
/**
|
||||
* Add status array to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addStatus();
|
||||
/**
|
||||
* Add message array to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addMessage();
|
||||
/**
|
||||
* Add secondsPastEpoch array to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addSecondsPastEpoch();
|
||||
/**
|
||||
* Add nanoseconds array to the NTMultiChannel.
|
||||
* @return this instance of a {@code NTMultiChannelBuilder}.
|
||||
*/
|
||||
shared_pointer addNanoseconds();
|
||||
/**
|
||||
* Create a {@code Structure} that represents NTMultiChannel.
|
||||
* This resets this instance state and allows new instance to be created.
|
||||
* @return a new instance of a {@code Structure}.
|
||||
*/
|
||||
epics::pvData::StructureConstPtr createStructure();
|
||||
/**
|
||||
* Create a {@code PVStructure} that represents NTMultiChannel.
|
||||
* This resets this instance state and allows new {@code instance to be created.
|
||||
* @return a new instance of a {@code PVStructure}
|
||||
*/
|
||||
epics::pvData::PVStructurePtr createPVStructure();
|
||||
/**
|
||||
* Create a {@code NTMultiChannel} instance.
|
||||
* This resets this instance state and allows new {@code instance to be created.
|
||||
* @return a new instance of a {@code NTMultiChannel}
|
||||
*/
|
||||
NTMultiChannelPtr create();
|
||||
private:
|
||||
NTMultiChannelBuilder();
|
||||
|
||||
void reset();
|
||||
|
||||
epics::pvData::UnionConstPtr valueUnion;
|
||||
bool value;
|
||||
bool descriptor;
|
||||
bool alarm;
|
||||
bool timeStamp;
|
||||
bool severity;
|
||||
bool status;
|
||||
bool message;
|
||||
bool secondsPastEpoch;
|
||||
bool nanoseconds;
|
||||
|
||||
friend class ::epics::nt::NTMultiChannel;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
typedef std::tr1::shared_ptr<detail::NTMultiChannelBuilder> NTMultiChannelBuilderPtr;
|
||||
|
||||
|
||||
class NTMultiChannel
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(NTMultiChannel);
|
||||
|
||||
static const std::string URI;
|
||||
/**
|
||||
* Is the pvStructure an NTMultiChannel.
|
||||
* @param pvStructure The pvStructure to test.
|
||||
* @param structure The structure to test.
|
||||
* @return (false,true) if (is not, is) an NTMultiChannel.
|
||||
*/
|
||||
static bool isNTMultiChannel(
|
||||
epics::pvData::PVStructurePtr const &pvStructure);
|
||||
static NTMultiChannelPtr create(
|
||||
std::vector<std::string> const & optionNames);
|
||||
static NTMultiChannelPtr create(
|
||||
std::vector<std::string> const & optionNames,
|
||||
epics::pvData::UnionConstPtr const & unionPtr);
|
||||
static NTMultiChannelPtr create(
|
||||
std::vector<std::string> const & optionNames,
|
||||
epics::pvData::UnionConstPtr const & unionPtr,
|
||||
epics::pvData::shared_vector<const std::string> channelNames);
|
||||
static NTMultiChannelPtr clone(epics::pvData::PVStructurePtr const &);
|
||||
static bool is_a(
|
||||
epics::pvData::StructureConstPtr const &structure);
|
||||
/**
|
||||
* Create a NTMultiChannelBuilder instance
|
||||
* @return builder instance.
|
||||
*/
|
||||
static NTMultiChannelBuilderPtr createBuilder();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
@@ -72,13 +173,45 @@ public:
|
||||
* @return PVStructurePtr which may be null.
|
||||
*/
|
||||
epics::pvData::PVStructurePtr getAlarm() {return pvAlarm;}
|
||||
/**
|
||||
* Get the value of each channel.
|
||||
* @return PVUnionArrayPtr
|
||||
*/
|
||||
epics::pvData::PVUnionArrayPtr getValue() {return pvValue;}
|
||||
/**
|
||||
* Get the channelName of each channel.
|
||||
* @return PVStringArrayPtr
|
||||
*/
|
||||
epics::pvData::PVStringArrayPtr getChannelName() { return pvChannelName;};
|
||||
/**
|
||||
* Get the severity of each channel.
|
||||
* @return PVIntArrayPtr which may be null.
|
||||
*/
|
||||
epics::pvData::PVIntArrayPtr getSeverity() {return pvSeverity;}
|
||||
/**
|
||||
* Get the status of each channel.
|
||||
* @return PVIntArrayPtr which may be null.
|
||||
*/
|
||||
epics::pvData::PVIntArrayPtr getStatus() {return pvStatus;}
|
||||
/**
|
||||
* Get the message of each chnnel.
|
||||
* @return PVStringArrayPtr which may be null.
|
||||
*/
|
||||
epics::pvData::PVStringArrayPtr getMessage() {return pvMessage;}
|
||||
/**
|
||||
* Get the SecondsPastEpoch of each channel.
|
||||
* @return PVLongArrayPtr which may be null.
|
||||
*/
|
||||
epics::pvData::PVLongArrayPtr getSecondsPastEpoch() {return pvSecondsPastEpoch;}
|
||||
/**
|
||||
* Get the SecondsPastEpoch of each channel.
|
||||
* @return PVIntArrayPtr which may be null.
|
||||
*/
|
||||
epics::pvData::PVIntArrayPtr getNanoseconds() {return pvNanoseconds;}
|
||||
/**
|
||||
* Get the descriptor.
|
||||
* @return PVStringPtr which may be null.
|
||||
*/
|
||||
epics::pvData::PVStringPtr getDescriptor() {return pvDescriptor;}
|
||||
private:
|
||||
NTMultiChannel(epics::pvData::PVStructurePtr const & pvStructure);
|
||||
@@ -93,6 +226,7 @@ private:
|
||||
epics::pvData::PVLongArrayPtr pvSecondsPastEpoch;
|
||||
epics::pvData::PVIntArrayPtr pvNanoseconds;
|
||||
epics::pvData::PVStringPtr pvDescriptor;
|
||||
friend class detail::NTMultiChannelBuilder;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -41,14 +41,20 @@ static PVNTFieldPtr pvntField = PVNTField::get();
|
||||
|
||||
static void test()
|
||||
{
|
||||
vector<string> optionNames(10);
|
||||
optionNames[0] = "alarm";
|
||||
optionNames[1] = "timeStamp";
|
||||
optionNames[2] = "severity";
|
||||
NTMultiChannelPtr multiChannel = NTMultiChannel::create(optionNames);
|
||||
testOk1(multiChannel.get()!=NULL);
|
||||
NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
|
||||
testOk(builder.get() != 0, "Got builder");
|
||||
|
||||
NTMultiChannelPtr multiChannel = builder->
|
||||
addDescriptor()->
|
||||
addAlarm()->
|
||||
addTimeStamp()->
|
||||
addSeverity() ->
|
||||
create();
|
||||
testOk1(multiChannel.get() != 0);
|
||||
|
||||
PVStructurePtr pvStructure = multiChannel->getPVStructure();
|
||||
testOk1(pvStructure.get()!=NULL);
|
||||
testOk1(NTMultiChannel::is_a(pvStructure->getStructure()));
|
||||
size_t nchan = 3;
|
||||
shared_vector<string> names(nchan);
|
||||
names[0] = "channel 0";
|
||||
@@ -63,21 +69,32 @@ static void test()
|
||||
add("doubleValue", pvDouble)->
|
||||
add("intValue", pvInt)->
|
||||
createUnion();
|
||||
multiChannel = NTMultiChannel::create(
|
||||
optionNames,unionPtr,channelNames);
|
||||
testOk1(multiChannel.get()!=NULL);
|
||||
multiChannel = builder->
|
||||
addValue(unionPtr) ->
|
||||
addDescriptor()->
|
||||
addAlarm()->
|
||||
addTimeStamp()->
|
||||
addSeverity() ->
|
||||
create();
|
||||
testOk1(multiChannel.get() != 0);
|
||||
pvStructure = multiChannel->getPVStructure();
|
||||
if(debug) {cout << *pvStructure << endl;}
|
||||
pvChannelName = multiChannel->getChannelName();
|
||||
pvChannelName->replace(channelNames);
|
||||
PVUnionArrayPtr pvValue = multiChannel->getValue();
|
||||
shared_vector<PVUnionPtr> unions(2);
|
||||
shared_vector<PVUnionPtr> unions(nchan);
|
||||
unions[0] = pvDataCreate->createPVUnion(unionPtr);
|
||||
unions[1] = pvDataCreate->createPVUnion(unionPtr);
|
||||
unions[2] = pvDataCreate->createPVUnion(unionPtr);
|
||||
unions[0]->select("doubleValue");
|
||||
unions[1]->select("intValue");
|
||||
unions[2]->select("intValue");
|
||||
PVDoublePtr pvDouble = unions[0]->get<PVDouble>();
|
||||
pvDouble->put(1.235);
|
||||
PVIntPtr pvInt = unions[1]->get<PVInt>();
|
||||
pvInt->put(5);
|
||||
pvInt = unions[2]->get<PVInt>();
|
||||
pvInt->put(7);
|
||||
pvValue->replace(freeze(unions));
|
||||
shared_vector<int32> severities(nchan);
|
||||
severities[0] = 0;
|
||||
@@ -86,12 +103,26 @@ static void test()
|
||||
PVIntArrayPtr pvSeverity = multiChannel->getSeverity();
|
||||
pvSeverity->replace(freeze(severities));
|
||||
if(debug) {cout << *pvStructure << endl;}
|
||||
multiChannel = builder->
|
||||
addValue(unionPtr) ->
|
||||
addDescriptor()->
|
||||
addAlarm()->
|
||||
addTimeStamp()->
|
||||
addSeverity() ->
|
||||
addStatus() ->
|
||||
addMessage() ->
|
||||
addSecondsPastEpoch() ->
|
||||
addNanoseconds() ->
|
||||
create();
|
||||
testOk1(multiChannel.get() != 0);
|
||||
pvStructure = multiChannel->getPVStructure();
|
||||
if(debug) {cout << *pvStructure << endl;}
|
||||
}
|
||||
|
||||
|
||||
MAIN(testCreateRequest)
|
||||
{
|
||||
testPlan(10);
|
||||
testPlan(6);
|
||||
test();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user