FieldBuilder allow append to Structure
Helpful to allow a new definition to be created as an extension of an existing definition.
This commit is contained in:
@@ -701,18 +701,52 @@ void Union::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*control
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
FieldBuilder::FieldBuilder()
|
||||
:fieldCreate(getFieldCreate())
|
||||
,idSet(false)
|
||||
,nestedClassToBuild(structure)
|
||||
,nestedArray(false)
|
||||
,createNested(true)
|
||||
{}
|
||||
|
||||
FieldBuilder::FieldBuilder() : fieldCreate(getFieldCreate()), idSet(false) {}
|
||||
FieldBuilder::FieldBuilder(const Structure* S)
|
||||
:fieldCreate(getFieldCreate())
|
||||
,id(S->getID())
|
||||
,idSet(!id.empty())
|
||||
,fieldNames(S->getFieldNames())
|
||||
,fields(S->getFields())
|
||||
,parentBuilder()
|
||||
,nestedClassToBuild(structure)
|
||||
,nestedName()
|
||||
,nestedArray(false)
|
||||
,createNested(false)
|
||||
{}
|
||||
|
||||
FieldBuilder::FieldBuilder(const FieldBuilderPtr & _parentBuilder,
|
||||
const std::string& name,
|
||||
const Structure* S)
|
||||
:fieldCreate(_parentBuilder->fieldCreate)
|
||||
,id(S->getID())
|
||||
,idSet(!id.empty())
|
||||
,fieldNames(S->getFieldNames())
|
||||
,fields(S->getFields())
|
||||
,parentBuilder(_parentBuilder)
|
||||
,nestedClassToBuild(structure)
|
||||
,nestedName(name)
|
||||
,nestedArray(false)
|
||||
,createNested(false)
|
||||
{}
|
||||
|
||||
FieldBuilder::FieldBuilder(FieldBuilderPtr const & _parentBuilder,
|
||||
string const & _nestedName,
|
||||
Type _nestedClassToBuild, bool _nestedArray) :
|
||||
fieldCreate(getFieldCreate()),
|
||||
idSet(false),
|
||||
parentBuilder(_parentBuilder),
|
||||
nestedClassToBuild(_nestedClassToBuild),
|
||||
nestedName(_nestedName),
|
||||
nestedArray(_nestedArray)
|
||||
Type _nestedClassToBuild, bool _nestedArray)
|
||||
:fieldCreate(_parentBuilder->fieldCreate)
|
||||
,idSet(false)
|
||||
,parentBuilder(_parentBuilder)
|
||||
,nestedClassToBuild(_nestedClassToBuild)
|
||||
,nestedName(_nestedName)
|
||||
,nestedArray(_nestedArray)
|
||||
,createNested(true)
|
||||
{}
|
||||
|
||||
void FieldBuilder::reset()
|
||||
@@ -737,7 +771,7 @@ void FieldBuilder::checkFieldName(const std::string& name)
|
||||
it != end; ++it)
|
||||
{
|
||||
if(name==*it)
|
||||
throw std::invalid_argument("duplicate fieldName "+name);
|
||||
THROW_EXCEPTION2(std::invalid_argument, std::string("duplicate fieldName ")+name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -861,6 +895,18 @@ UnionConstPtr FieldBuilder::createUnion()
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addNestedStructure(string const & name)
|
||||
{
|
||||
// linear search on the theory that the number of fields is small
|
||||
for(size_t i=0; i<fieldNames.size(); i++)
|
||||
{
|
||||
if(name!=fieldNames[i])
|
||||
continue;
|
||||
|
||||
if(fields[i]->getType()!=structure)
|
||||
THROW_EXCEPTION2(std::invalid_argument, "nested field not structure: "+name);
|
||||
|
||||
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name,
|
||||
static_cast<const Structure*>(fields[i].get())));
|
||||
}
|
||||
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, structure, false));
|
||||
}
|
||||
|
||||
@@ -887,20 +933,39 @@ FieldBuilderPtr FieldBuilder::endNested()
|
||||
THROW_EXCEPTION2(std::runtime_error, "this method can only be called to create nested fields");
|
||||
|
||||
FieldConstPtr nestedField = createFieldInternal(nestedClassToBuild);
|
||||
if (nestedArray)
|
||||
parentBuilder->addArray(nestedName, nestedField);
|
||||
else
|
||||
parentBuilder->add(nestedName, nestedField);
|
||||
|
||||
return parentBuilder;
|
||||
}
|
||||
|
||||
if(createNested) {
|
||||
if (nestedArray)
|
||||
parentBuilder->addArray(nestedName, nestedField);
|
||||
else
|
||||
parentBuilder->add(nestedName, nestedField);
|
||||
return parentBuilder;
|
||||
} else {
|
||||
for(size_t i=0, N = parentBuilder->fieldNames.size(); i<N; i++)
|
||||
{
|
||||
if(nestedName!=parentBuilder->fieldNames[i])
|
||||
continue;
|
||||
assert(parentBuilder->fields[i]->getType()==structure);
|
||||
|
||||
parentBuilder->fields[i] = nestedField;
|
||||
return parentBuilder;
|
||||
}
|
||||
// this only reached if bug in ctor
|
||||
THROW_EXCEPTION2(std::logic_error, "no nested field field?");
|
||||
}
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldCreate::createFieldBuilder() const
|
||||
{
|
||||
return FieldBuilderPtr(new FieldBuilder());
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldCreate::createFieldBuilder(StructureConstPtr S) const
|
||||
{
|
||||
FieldBuilderPtr ret(new FieldBuilder(S.get()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
|
||||
{
|
||||
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE) {
|
||||
|
||||
+13
-6
@@ -1021,6 +1021,8 @@ public:
|
||||
|
||||
private:
|
||||
FieldBuilder();
|
||||
FieldBuilder(const Structure*);
|
||||
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const Structure*);
|
||||
FieldBuilder(FieldBuilderPtr const & parentBuilder,
|
||||
std::string const & nestedName,
|
||||
Type nestedClassToBuild, bool nestedArray);
|
||||
@@ -1032,7 +1034,7 @@ private:
|
||||
|
||||
friend class FieldCreate;
|
||||
|
||||
FieldCreatePtr fieldCreate;
|
||||
const FieldCreatePtr fieldCreate;
|
||||
|
||||
std::string id;
|
||||
bool idSet;
|
||||
@@ -1040,11 +1042,11 @@ private:
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
|
||||
FieldBuilderPtr parentBuilder;
|
||||
Type nestedClassToBuild;
|
||||
std::string nestedName;
|
||||
bool nestedArray;
|
||||
|
||||
const FieldBuilderPtr parentBuilder;
|
||||
const Type nestedClassToBuild;
|
||||
const std::string nestedName;
|
||||
const bool nestedArray;
|
||||
const bool createNested; // true - endNested() creates in parent, false - endNested() appends to parent
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1059,6 +1061,11 @@ public:
|
||||
* @return a new instance of a @c FieldBuilder.
|
||||
*/
|
||||
FieldBuilderPtr createFieldBuilder() const;
|
||||
/**
|
||||
* Create a new instance of in-line @c Field builder pre-initialized with and existing Structure
|
||||
* @return a new instance of a @c FieldBuilder.
|
||||
*/
|
||||
FieldBuilderPtr createFieldBuilder(StructureConstPtr S) const;
|
||||
/**
|
||||
* Create a @c ScalarField.
|
||||
* @param scalarType The scalar type.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
@@ -241,21 +242,73 @@ void test_nestedStructureArray()
|
||||
|
||||
}
|
||||
|
||||
void test_extendStructure()
|
||||
{
|
||||
testDiag("test_extendStructure()");
|
||||
Structure::const_shared_pointer X(getFieldCreate()->createFieldBuilder()
|
||||
->add("A", pvInt)
|
||||
->addNestedStructure("nest")
|
||||
->add("B", pvInt)
|
||||
->endNested()
|
||||
->createStructure());
|
||||
|
||||
Structure::const_shared_pointer Y(getFieldCreate()->createFieldBuilder(X)
|
||||
->add("A2", pvInt)
|
||||
->addNestedStructure("nest")
|
||||
->add("B2", pvInt)
|
||||
->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"));
|
||||
|
||||
try {
|
||||
Structure::const_shared_pointer Z(getFieldCreate()->createFieldBuilder(Y)
|
||||
->add("A2", pvDouble)
|
||||
->createStructure());
|
||||
testFail("Unexpected success in adding duplicate field");
|
||||
}catch(std::exception& e){
|
||||
testPass("catch expected exception: %s", e.what());
|
||||
}
|
||||
|
||||
try {
|
||||
Structure::const_shared_pointer Z(getFieldCreate()->createFieldBuilder(Y)
|
||||
->addNestedStructure("nest")
|
||||
->add("B2", pvDouble)
|
||||
->endNested()
|
||||
->createStructure());
|
||||
testFail("Unexpected success in adding duplicate nested field");
|
||||
}catch(std::exception& e){
|
||||
testPass("catch expected exception: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MAIN(testFieldBuilder)
|
||||
{
|
||||
testPlan(68);
|
||||
testDiag("Tests for FieldBuilder");
|
||||
testPlan(78);
|
||||
try {
|
||||
testDiag("Tests for FieldBuilder");
|
||||
|
||||
test_factory();
|
||||
test_structure();
|
||||
test_arraySizeTypes();
|
||||
test_nestedStructure();
|
||||
test_nestedStructureArray();
|
||||
|
||||
|
||||
test_invalid();
|
||||
test_factory();
|
||||
test_structure();
|
||||
test_arraySizeTypes();
|
||||
test_nestedStructure();
|
||||
test_nestedStructureArray();
|
||||
test_extendStructure();
|
||||
|
||||
test_invalid();
|
||||
}catch(std::exception& e) {
|
||||
PRINT_EXCEPTION(e);
|
||||
testAbort("Unhandled exception: %s", e.what());
|
||||
}
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user