NTNDArray mapping

This commit is contained in:
Michael Davidsaver
2017-09-19 14:18:53 -05:00
parent eb92401175
commit 0e4ba7eceb
5 changed files with 123 additions and 73 deletions

View File

@ -59,9 +59,6 @@ struct context {
} else if(key=="+trigger") {
fld.trigger = value.ref<std::string>();
} else if(key=="+predef") {
fld.predef = value.ref<std::string>();
} else if(key=="+putorder") {
fld.putorder = value.as<pvd::int32>();

View File

@ -44,14 +44,6 @@ struct Splitter {
}
};
pvd::StructureConstPtr NTNDArray(pvd::getFieldCreate()->createFieldBuilder()
->setId("epics:nt/NTNDArray:1.0")
//->add("value", pvd::getFieldCreate()->createVariantUnion())
->addNestedStructureArray("dimension")
->add("size", pvd::pvInt)
->endNested()
->createStructure());
struct GroupMemberInfo {
// consumes builder
GroupMemberInfo(const std::string& a, const std::string& b, p2p::auto_ptr<PVIFBuilder>& builder)
@ -80,9 +72,6 @@ struct GroupInfo {
enum tribool {Unset,True,False} atomic;
bool hastriggers;
typedef std::map<std::string, pvd::StructureConstPtr> predefs_t;
predefs_t predefs;
};
// Iterates all PDB records and gathers info() to construct PDB groups
@ -199,18 +188,6 @@ struct PDBProcessor
const std::string& fldname = fit->first;
const GroupConfig::Field& fld = fit->second;
if(!fld.predef.empty()) {
if(fld.predef=="epics:nt/NTNDArray:1.0") {
curgroup->predefs[fldname] = NTNDArray;
} else {
fprintf(stderr, "%s.%s : unknown pre-defined type \"%s\"\n",
grpname.c_str(), fldname.c_str(), fld.predef.c_str());
}
// allow pre-defined fields to skip a channel mapping
if(fld.channel.empty())
continue;
}
if(fld.channel.empty())
throw std::runtime_error("Missing required +channel");
@ -322,31 +299,6 @@ PDBProvider::PDBProvider(const epics::pvAccess::Configuration::shared_pointer &)
pvd::FieldBuilderPtr builder(fcreate->createFieldBuilder());
builder->add("record", _options);
for(GroupInfo::predefs_t::const_iterator it=info.predefs.begin(), end=info.predefs.end();
it!=end; ++it)
{
if(PDBProviderDebug>2)
fprintf(stderr, "%s.%s add pre-defined %s\n",
info.name.c_str(), it->first.c_str(), it->second->getID().c_str());
std::vector<std::string> parts;
{
Splitter S(it->first.c_str(), '.');
std::string part;
while(S.snip(part))
parts.push_back(part);
}
assert(!parts.empty());
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->addNestedStructure(parts[j]);
builder->add(parts.back(), it->second);
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->endNested();
}
for(size_t i=0; i<nchans; i++)
{
GroupMemberInfo &mem = info.members[i];
@ -357,22 +309,25 @@ PDBProvider::PDBProvider(const epics::pvAccess::Configuration::shared_pointer &)
info.builder = PTRMOVE(mem.builder);
assert(info.builder.get());
std::vector<std::string> parts;
{
Splitter S(mem.pvfldname.c_str(), '.');
std::string part;
while(S.snip(part))
parts.push_back(part);
if(info.builder->buildsType) {
std::vector<std::string> parts;
{
Splitter S(mem.pvfldname.c_str(), '.');
std::string part;
while(S.snip(part))
parts.push_back(part);
}
assert(!parts.empty());
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->addNestedStructure(parts[j]);
builder->add(parts.back(), info.builder->dtype(chan));
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->endNested();
}
assert(!parts.empty());
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->addNestedStructure(parts[j]);
builder->add(parts.back(), info.builder->dtype(chan));
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->endNested();
info.attachment = mem.pvfldname;
info.chan.swap(chan);
@ -382,6 +337,7 @@ PDBProvider::PDBProvider(const epics::pvAccess::Configuration::shared_pointer &)
info.triggers.push_back(*idx);
}
assert(info.chan);
records[i] = dbChannelRecord(info.chan);
}
pv->members.swap(members);

View File

@ -22,7 +22,7 @@
struct epicsShareClass GroupConfig
{
struct epicsShareClass Field {
std::string type, channel, trigger, predef;
std::string type, channel, trigger;
int putorder;
Field() :putorder(std::numeric_limits<int>::min()) {}
@ -31,7 +31,6 @@ struct epicsShareClass GroupConfig
std::swap(type, o.type);
std::swap(channel, o.channel);
std::swap(trigger, o.trigger);
std::swap(predef, o.predef);
std::swap(putorder, o.putorder);
}
};

View File

@ -573,7 +573,10 @@ struct PVIFPlain : public PVIF
:PVIF(channel)
,field(std::tr1::static_pointer_cast<PVD>(fld))
,channel(channel)
{}
{
if(!field)
throw std::logic_error("PVIFPlain attached type mis-match");
}
virtual ~PVIFPlain() {}
@ -601,7 +604,7 @@ struct PVIFPlain : public PVIF
struct PlainBuilder : public PVIFBuilder
{
PlainBuilder() {}
PlainBuilder() :PVIFBuilder(true) {}
virtual ~PlainBuilder() {}
// fetch the structure description
@ -632,9 +635,98 @@ struct PlainBuilder : public PVIFBuilder
return new PVIFPlain<pvd::PVScalarArray>(channel, root);
}
};
struct ExistingBuilder : public PVIFBuilder
{
ExistingBuilder() :PVIFBuilder(false) {}
virtual ~ExistingBuilder() {}
// fetch the structure description
virtual epics::pvData::FieldConstPtr dtype(dbChannel *channel) OVERRIDE FINAL {
throw std::logic_error("Don't call me");
}
// Attach to a structure instance.
// must be of the type returned by dtype().
// need not be the root structure
virtual PVIF* attach(dbChannel *channel, const epics::pvData::PVFieldPtr& root) OVERRIDE FINAL
{
const long maxelem = dbChannelFinalElements(channel);
if(maxelem==1)
return new PVIFPlain<pvd::PVScalar>(channel, root);
else
return new PVIFPlain<pvd::PVScalarArray>(channel, root);
}
};
pvd::StructureConstPtr NTNDArray(pvd::getFieldCreate()->createFieldBuilder()
->setId("epics:nt/NTNDArray:1.0")
->add("value", pvd::getFieldCreate()->createVariantUnion())
->addNestedStructureArray("dimension")
->add("size", pvd::pvInt)
->endNested()
->createStructure());
struct NTNDArrayBuilder : public PVIFBuilder
{
NTNDArrayBuilder() :PVIFBuilder(true) {}
virtual ~NTNDArrayBuilder() {}
// fetch the structure description
virtual epics::pvData::FieldConstPtr dtype(dbChannel *channel) OVERRIDE FINAL {
(void)channel; //ignored
return NTNDArray;
}
// Attach to a structure instance.
// must be of the type returned by dtype().
// need not be the root structure
virtual PVIF* attach(dbChannel *channel, const epics::pvData::PVFieldPtr& root) OVERRIDE FINAL
{
pvd::PVDataCreatePtr create(pvd::getPVDataCreate());
const short dbr = dbChannelFinalFieldType(channel);
const pvd::ScalarType pvt = DBR2PVD(dbr);
pvd::PVStructure *base = dynamic_cast<pvd::PVStructure*>(root.get());
if(!base)
throw std::logic_error("Mis-matched attachment point");
// auto-magically ensure that dimension array has at least 2 elements
// TODO: bit of a hack, should be able to do this as needed from builder for size field(s)
{
pvd::PVStructureArrayPtr dims(base->getSubFieldT<pvd::PVStructureArray>("dimension"));
pvd::PVStructureArray::const_svector cur(dims->view());
if(cur.size()<2 || !cur[0] || !cur[1]) {
pvd::PVStructureArray::svector D(dims->reuse());
pvd::StructureConstPtr dtype(dims->getStructureArray()->getStructure());
if(D.size()<2) D.resize(2);
if(!D[0])
D[0] = create->createPVStructure(dtype);
if(!D[1])
D[1] = create->createPVStructure(dtype);
dims->replace(pvd::freeze(D));
}
}
pvd::PVUnionPtr value(base->getSubFieldT<pvd::PVUnion>("value"));
pvd::PVFieldPtr arr(value->get());
if(!arr) {
arr = create->createPVScalarArray(pvt);
value->set(arr);
}
return new PVIFPlain<pvd::PVScalarArray>(channel, arr);
}
};
}//namespace
PVIFBuilder::PVIFBuilder()
PVIFBuilder::PVIFBuilder(bool buildsType)
:buildsType(buildsType)
{}
PVIFBuilder::~PVIFBuilder() {}
@ -646,6 +738,10 @@ PVIFBuilder* PVIFBuilder::create(const std::string& type)
return new ScalarBuilder;
else if(type=="plain")
return new PlainBuilder;
else if(type=="existing")
return new ExistingBuilder;
else if(type=="NTNDArray" || type=="NTNDArray:1.0")
return new NTNDArrayBuilder;
else
throw std::runtime_error(std::string("Unknown +type=")+type);
}

View File

@ -277,6 +277,8 @@ private:
struct epicsShareClass PVIFBuilder {
const bool buildsType;
virtual ~PVIFBuilder();
// fetch the structure description
@ -289,7 +291,7 @@ struct epicsShareClass PVIFBuilder {
static PVIFBuilder* create(const std::string& name);
protected:
PVIFBuilder();
PVIFBuilder(bool buildsType);
private:
PVIFBuilder(const PVIFBuilder&);
PVIFBuilder& operator=(const PVIFBuilder&);
@ -297,7 +299,7 @@ private:
struct epicsShareClass ScalarBuilder : public PVIFBuilder
{
ScalarBuilder() {}
ScalarBuilder() :PVIFBuilder(true) {}
virtual ~ScalarBuilder() {}