change to implement builder

This commit is contained in:
Marty Kraimer
2014-08-21 10:27:09 -04:00
parent 7f521bdc3c
commit 072113ab4a
3 changed files with 310 additions and 85 deletions

View File

@@ -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")),

View File

@@ -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;
};
}}

View File

@@ -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();
}