FieldBuilder edit union/structureArray/unionArray

Allow appending fields to existing types
to allow structure-like types
This commit is contained in:
Michael Davidsaver
2017-09-20 13:50:59 -05:00
parent 7a71e758b1
commit 9bce66f307
3 changed files with 161 additions and 20 deletions

View File

@@ -737,6 +737,51 @@ FieldBuilder::FieldBuilder(const FieldBuilderPtr & _parentBuilder,
,createNested(false)
{}
FieldBuilder::FieldBuilder(const FieldBuilderPtr & _parentBuilder,
const std::string& name,
const StructureArray* S)
:fieldCreate(getFieldCreate())
,id(S->getStructure()->getID())
,idSet(!id.empty())
,fieldNames(S->getStructure()->getFieldNames())
,fields(S->getStructure()->getFields())
,parentBuilder(_parentBuilder)
,nestedClassToBuild(structure)
,nestedName(name)
,nestedArray(true)
,createNested(false)
{}
FieldBuilder::FieldBuilder(const FieldBuilderPtr & _parentBuilder,
const std::string& name,
const Union* S)
:fieldCreate(getFieldCreate())
,id(S->getID())
,idSet(!id.empty())
,fieldNames(S->getFieldNames())
,fields(S->getFields())
,parentBuilder(_parentBuilder)
,nestedClassToBuild(union_)
,nestedName(name)
,nestedArray(false)
,createNested(false)
{}
FieldBuilder::FieldBuilder(const FieldBuilderPtr & _parentBuilder,
const std::string& name,
const UnionArray* S)
:fieldCreate(getFieldCreate())
,id(S->getUnion()->getID())
,idSet(!id.empty())
,fieldNames(S->getUnion()->getFieldNames())
,fields(S->getUnion()->getFields())
,parentBuilder(_parentBuilder)
,nestedClassToBuild(union_)
,nestedName(name)
,nestedArray(true)
,createNested(false)
{}
FieldBuilder::FieldBuilder(FieldBuilderPtr const & _parentBuilder,
string const & _nestedName,
Type _nestedClassToBuild, bool _nestedArray)
@@ -893,7 +938,7 @@ UnionConstPtr FieldBuilder::createUnion()
return field;
}
FieldBuilderPtr FieldBuilder::addNestedStructure(string const & name)
const Field* FieldBuilder::findField(const std::string& name, Type ftype)
{
// linear search on the theory that the number of fields is small
for(size_t i=0; i<fieldNames.size(); i++)
@@ -901,11 +946,20 @@ FieldBuilderPtr FieldBuilder::addNestedStructure(string const & name)
if(name!=fieldNames[i])
continue;
if(fields[i]->getType()!=structure)
THROW_EXCEPTION2(std::invalid_argument, "nested field not structure: "+name);
if(fields[i]->getType()!=ftype)
THROW_EXCEPTION2(std::invalid_argument, "nested field not required type: "+name);
return fields[i].get();
}
return 0;
}
FieldBuilderPtr FieldBuilder::addNestedStructure(string const & name)
{
const Field *cur = findField(name, structure);
if(cur) {
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name,
static_cast<const Structure*>(fields[i].get())));
static_cast<const Structure*>(cur)));
}
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, structure, false));
}
@@ -913,23 +967,38 @@ FieldBuilderPtr FieldBuilder::addNestedStructure(string const & name)
FieldBuilderPtr FieldBuilder::addNestedUnion(string const & name)
{
const Field *cur = findField(name, union_);
if(cur) {
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name,
static_cast<const Union*>(cur)));
}
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, union_, false));
}
FieldBuilderPtr FieldBuilder::addNestedStructureArray(string const & name)
{
const Field *cur = findField(name, structureArray);
if(cur) {
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name,
static_cast<const StructureArray*>(cur)));
}
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, structure, true));
}
FieldBuilderPtr FieldBuilder::addNestedUnionArray(string const & name)
{
const Field *cur = findField(name, unionArray);
if(cur) {
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name,
static_cast<const UnionArray*>(cur)));
}
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, union_, true));
}
FieldBuilderPtr FieldBuilder::endNested()
{
if (!parentBuilder.get())
if (!parentBuilder)
THROW_EXCEPTION2(std::runtime_error, "FieldBuilder::endNested() can only be called to create nested fields");
FieldConstPtr nestedField = createFieldInternal(nestedClassToBuild);
@@ -945,9 +1014,17 @@ FieldBuilderPtr FieldBuilder::endNested()
{
if(nestedName!=parentBuilder->fieldNames[i])
continue;
assert(parentBuilder->fields[i]->getType()==structure);
parentBuilder->fields[i] = nestedField;
if(nestedArray) {
if(nestedClassToBuild==structure)
parentBuilder->fields[i] = fieldCreate->createStructureArray(std::tr1::static_pointer_cast<const Structure>(nestedField));
else if(nestedClassToBuild==union_)
parentBuilder->fields[i] = fieldCreate->createUnionArray(std::tr1::static_pointer_cast<const Union>(nestedField));
else
throw std::logic_error("bad nested class");
} else {
parentBuilder->fields[i] = nestedField;
}
return parentBuilder;
}
// this only reached if bug in ctor

View File

@@ -1023,9 +1023,14 @@ private:
FieldBuilder();
FieldBuilder(const Structure*);
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const Structure*);
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const StructureArray*);
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const Union*);
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const UnionArray*);
FieldBuilder(FieldBuilderPtr const & parentBuilder,
std::string const & nestedName,
Type nestedClassToBuild, bool nestedArray);
const Field *findField(const std::string& name, Type ftype);
void reset();
FieldConstPtr createFieldInternal(Type type);

View File

@@ -7,6 +7,7 @@
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/pvUnitTest.h>
#include <pv/pvData.h>
#include <pv/epicsException.h>
@@ -245,31 +246,89 @@ void test_nestedStructureArray()
void test_extendStructure()
{
testDiag("test_extendStructure()");
Structure::const_shared_pointer X(getFieldCreate()->createFieldBuilder()
Structure::const_shared_pointer base(getFieldCreate()->createFieldBuilder()
->add("A", pvInt)
->addNestedStructure("nest")
->add("B", pvInt)
->addNestedStructure("one")
->add("XX", pvInt)
->endNested()
->endNested()
->addNestedUnion("U")
->add("B", pvInt)
->addNestedStructure("one")
->add("XX", pvInt)
->endNested()
->endNested()
->addNestedStructureArray("sarr")
->add("X", pvInt)
->addNestedStructure("one")
->add("XX", pvInt)
->endNested()
->endNested()
->createStructure());
Structure::const_shared_pointer Y(getFieldCreate()->createFieldBuilder(X)
Structure::const_shared_pointer amended(getFieldCreate()->createFieldBuilder(base)
->add("A2", pvInt)
->addNestedStructure("nest")
->add("B2", pvInt)
->addNestedStructure("one")
->add("YY", pvInt)
->endNested()
->endNested()
->addNestedUnion("U")
->add("B2", pvInt)
->addNestedStructure("one")
->add("YY", pvInt)
->endNested()
->endNested()
->addNestedStructureArray("sarr")
->add("Y", pvInt)
->addNestedStructure("one")
->add("YY", pvInt)
->endNested()
->endNested()
->createStructure());
testOk1(X.get()!=Y.get());
testOk1(X->getField("A")==Y->getField("A"));
testOk1(!X->getField("A2"));
testOk1(!!Y->getField("A2"));
testOk1(X->getField("nest")!=Y->getField("nest"));
testOk1(X->getField<Structure>("nest")->getField("B")==Y->getField<Structure>("nest")->getField("B"));
testOk1(!X->getField<Structure>("nest")->getField("B2"));
testOk1(!!Y->getField<Structure>("nest")->getField("B2"));
Structure::const_shared_pointer expected(getFieldCreate()->createFieldBuilder()
->add("A", pvInt)
->addNestedStructure("nest")
->add("B", pvInt)
->addNestedStructure("one")
->add("XX", pvInt)
->add("YY", pvInt)
->endNested()
->add("B2", pvInt)
->endNested()
->addNestedUnion("U")
->add("B", pvInt)
->addNestedStructure("one")
->add("XX", pvInt)
->add("YY", pvInt)
->endNested()
->add("B2", pvInt)
->endNested()
->addNestedStructureArray("sarr")
->add("X", pvInt)
->addNestedStructure("one")
->add("XX", pvInt)
->add("YY", pvInt)
->endNested()
->add("Y", pvInt)
->endNested()
->add("A2", pvInt)
->createStructure());
testShow()<<"base: "<<base
<<"amended: "<<amended
<<"expected: "<<expected;
testNotEqual(static_cast<const void*>(amended.get()),
static_cast<const void*>(expected.get()));
testEqual(*amended, *expected);
try {
Structure::const_shared_pointer Z(getFieldCreate()->createFieldBuilder(Y)
Structure::const_shared_pointer Z(getFieldCreate()->createFieldBuilder(amended)
->add("A2", pvDouble)
->createStructure());
testFail("Unexpected success in adding duplicate field");
@@ -278,7 +337,7 @@ void test_extendStructure()
}
try {
Structure::const_shared_pointer Z(getFieldCreate()->createFieldBuilder(Y)
Structure::const_shared_pointer Z(getFieldCreate()->createFieldBuilder(amended)
->addNestedStructure("nest")
->add("B2", pvDouble)
->endNested()
@@ -293,7 +352,7 @@ void test_extendStructure()
MAIN(testFieldBuilder)
{
testPlan(78);
testPlan(72);
try {
testDiag("Tests for FieldBuilder");