diff --git a/src/factory/FieldCreateFactory.cpp b/src/factory/FieldCreateFactory.cpp index 66c29b0..0a28813 100644 --- a/src/factory/FieldCreateFactory.cpp +++ b/src/factory/FieldCreateFactory.cpp @@ -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; igetType()!=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(fields[i].get()))); + static_cast(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(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(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(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(nestedField)); + else if(nestedClassToBuild==union_) + parentBuilder->fields[i] = fieldCreate->createUnionArray(std::tr1::static_pointer_cast(nestedField)); + else + throw std::logic_error("bad nested class"); + } else { + parentBuilder->fields[i] = nestedField; + } return parentBuilder; } // this only reached if bug in ctor diff --git a/src/pv/pvIntrospect.h b/src/pv/pvIntrospect.h index 0f028fb..b0cd15d 100644 --- a/src/pv/pvIntrospect.h +++ b/src/pv/pvIntrospect.h @@ -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); diff --git a/testApp/pv/testFieldBuilder.cpp b/testApp/pv/testFieldBuilder.cpp index 94dda92..9433d82 100644 --- a/testApp/pv/testFieldBuilder.cpp +++ b/testApp/pv/testFieldBuilder.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -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("nest")->getField("B")==Y->getField("nest")->getField("B")); - testOk1(!X->getField("nest")->getField("B2")); - testOk1(!!Y->getField("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: "<(amended.get()), + static_cast(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");