diff --git a/src/factory/FieldCreateFactory.cpp b/src/factory/FieldCreateFactory.cpp index d6d4c33..c4335a6 100644 --- a/src/factory/FieldCreateFactory.cpp +++ b/src/factory/FieldCreateFactory.cpp @@ -532,15 +532,6 @@ string Structure::getID() const return id; } -FieldConstPtr Structure::getField(string const & fieldName) const { - for(size_t i=0, N=fields.size(); i std::tr1::shared_ptr getField(std::string const &fieldName) const @@ -731,13 +731,27 @@ public: return std::tr1::shared_ptr(); } + /** + * Get the field for the specified fieldName. + * @param fieldName The name of the field to get; + * @return The introspection interface. + * This will throw a runtime_error exception if the field is not in the structure. + */ + FieldConstPtr getFieldT(std::string const &fieldName) const {return getFieldImpl(fieldName, true);}; + + template + std::tr1::shared_ptr getFieldT(std::string const &fieldName) const + { + return std::tr1::dynamic_pointer_cast(getFieldT(fieldName)); + } + /** * Get the field for the specified fieldName. * @param index The index of the field to get; * @return The introspection interface. * This will hold a null pointer if the field is not in the structure. */ - const FieldConstPtr& getField(std::size_t index) const {return fields.at(index);} + FieldConstPtr getField(std::size_t index) const {return getFieldImpl(index, false);} template std::tr1::shared_ptr getField(std::size_t index) const @@ -749,6 +763,20 @@ public: return std::tr1::shared_ptr(); } + /** + * Get the field for the specified fieldName. + * @param index The index of the field to get; + * @return The introspection interface. + * This will throw a runtime_error exception if the field is not in the structure. + */ + FieldConstPtr getFieldT(std::size_t index) const {return getFieldImpl(index, true);} + + template + std::tr1::shared_ptr getFieldT(std::size_t index) const + { + return std::tr1::dynamic_pointer_cast(getFieldT(index)); + } + /** * Get the field index for the specified fieldName. * @return The introspection interface. @@ -790,6 +818,8 @@ private: FieldConstPtrArray fields; std::string id; + FieldConstPtr getFieldImpl(const std::string& fieldName, bool throws) const; + FieldConstPtr getFieldImpl(const std::size_t fieldOffset, bool throws) const; void dumpFields(std::ostream& o) const; friend class FieldCreate; @@ -842,7 +872,7 @@ public: * @return The introspection interface. * This will hold a null pointer if the field is not in the union. */ - FieldConstPtr getField(std::string const &fieldName) const; + FieldConstPtr getField(std::string const &fieldName) const {return getFieldImpl(fieldName, false);}; template std::tr1::shared_ptr getField(std::string const &fieldName) const @@ -854,13 +884,27 @@ public: return std::tr1::shared_ptr(); } + /** + * Get the field for the specified fieldName. + * @param fieldName The name of the field to get; + * @return The introspection interface. + * This will throw a runtime_error exception if the field is not in the union. + */ + FieldConstPtr getFieldT(std::string const &fieldName) const {return getFieldImpl(fieldName, true);}; + + template + std::tr1::shared_ptr getFieldT(std::string const &fieldName) const + { + return std::tr1::dynamic_pointer_cast(getFieldT(fieldName)); + } + /** * Get the field for the specified fieldName. * @param index The index of the field to get; * @return The introspection interface. * This will hold a null pointer if the field is not in the union. */ - FieldConstPtr getField(std::size_t index) const {return fields.at(index);} + FieldConstPtr getField(std::size_t index) const {return getFieldImpl(index, false);} template std::tr1::shared_ptr getField(std::size_t index) const @@ -872,6 +916,20 @@ public: return std::tr1::shared_ptr(); } + /** + * Get the field for the specified fieldName. + * @param index The index of the field to get; + * @return The introspection interface. + * This will throw a runtime_error exception if the field is not in the union. + */ + FieldConstPtr getFieldT(std::size_t index) const {return getFieldImpl(index, true);} + + template + std::tr1::shared_ptr getFieldT(std::size_t index) const + { + return std::tr1::dynamic_pointer_cast(getFieldT(index)); + } + /** * Get the field index for the specified fieldName. * @return The introspection interface. @@ -929,7 +987,9 @@ private: StringArray fieldNames; FieldConstPtrArray fields; std::string id; - + + FieldConstPtr getFieldImpl(const std::string& fieldName, bool throws) const; + FieldConstPtr getFieldImpl(const std::size_t fieldOffset, bool throws) const; void dumpFields(std::ostream& o) const; friend class FieldCreate; diff --git a/testApp/pv/testIntrospect.cpp b/testApp/pv/testIntrospect.cpp index 4f02086..9a74203 100644 --- a/testApp/pv/testIntrospect.cpp +++ b/testApp/pv/testIntrospect.cpp @@ -146,6 +146,28 @@ static void testStructure() testOk1(struct1->getFieldName(0)==names1[0]); testOk1(struct1->getFieldName(1)==names1[1]); + testOk1(struct1->getField("nonexistent").get()==NULL); + testOk1(struct1->getField(9999).get()==NULL); + + testOk1(struct1->getFieldT("innerA")==fields1[0]); + testOk1(struct1->getFieldT("innerB")==fields1[1]); + testOk1(struct1->getFieldT(0)==fields1[0]); + testOk1(struct1->getFieldT(1)==fields1[1]); + + try { + FieldConstPtr field(struct1->getFieldT("nonexistent")); + testFail("missing required exception"); + } catch (std::runtime_error& e) { + testPass("caught expected exception: %s", e.what()); + } + + try { + FieldConstPtr field(struct1->getFieldT(9999)); + testFail("missing required exception"); + } catch (std::runtime_error& e) { + testPass("caught expected exception: %s", e.what()); + } + testOk1(struct1->getID() == Structure::DEFAULT_ID); testOk1(fields1 == struct1->getFields()); // vector equality @@ -190,6 +212,28 @@ static void testUnion() testOk1(union1->getFieldName(0)==names1[0]); testOk1(union1->getFieldName(1)==names1[1]); + testOk1(union1->getField("nonexistent").get()==NULL); + testOk1(union1->getField(9999).get()==NULL); + + testOk1(union1->getFieldT("innerA")==fields1[0]); + testOk1(union1->getFieldT("innerB")==fields1[1]); + testOk1(union1->getFieldT(0)==fields1[0]); + testOk1(union1->getFieldT(1)==fields1[1]); + + try { + FieldConstPtr field(union1->getFieldT("nonexistent")); + testFail("missing required exception"); + } catch (std::runtime_error& e) { + testPass("caught expected exception: %s", e.what()); + } + + try { + FieldConstPtr field(union1->getFieldT(9999)); + testFail("missing required exception"); + } catch (std::runtime_error& e) { + testPass("caught expected exception: %s", e.what()); + } + testOk1(union1->getID() == Union::DEFAULT_ID); testOk1(fields1 == union1->getFields()); // vector equality @@ -311,7 +355,7 @@ static void testMapping() MAIN(testIntrospect) { - testPlan(326); + testPlan(342); fieldCreate = getFieldCreate(); pvDataCreate = getPVDataCreate(); standardField = getStandardField();