From b84ed964f9bc1e6e4f06127382fabef02c8e89d2 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 8 Aug 2017 16:37:12 +0200 Subject: [PATCH] reduce # of PVStructure::getSubField overloads --- src/factory/PVStructure.cpp | 89 +++++++++++++------------- src/pv/pvData.h | 122 ++++++++++-------------------------- 2 files changed, 81 insertions(+), 130 deletions(-) diff --git a/src/factory/PVStructure.cpp b/src/factory/PVStructure.cpp index 861f5ac..8dc2195 100644 --- a/src/factory/PVStructure.cpp +++ b/src/factory/PVStructure.cpp @@ -84,50 +84,41 @@ const PVFieldPtrArray & PVStructure::getPVFields() const return pvFields; } -PVFieldPtr PVStructure::getSubField(const char * fieldName) const +PVFieldPtr PVStructure::getSubFieldImpl(size_t fieldOffset, bool throws) const { - PVField * field = getSubFieldImpl(fieldName, false); - if (field) - return field->shared_from_this(); - else - return PVFieldPtr(); -} + const PVStructure *current = this; - -PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const -{ - if(fieldOffset<=getFieldOffset()) { - return PVFieldPtr(); - } - if(fieldOffset>getNextFieldOffset()) return PVFieldPtr(); - size_t numFields = pvFields.size(); - for(size_t i=0; igetFieldOffset()==fieldOffset) return pvFields[i]; - if(pvField->getNextFieldOffset()<=fieldOffset) continue; - if(pvField->getField()->getType()==structure) { - PVStructure *pvStructure = static_cast(pvField.get()); - return pvStructure->getSubField(fieldOffset); +recurse: + if(fieldOffset<=current->getFieldOffset() || fieldOffset>current->getNextFieldOffset()) { + if(throws) { + std::stringstream ss; + ss << "Failed to get field with offset " + << fieldOffset << " (Invalid offset)" ; + throw std::runtime_error(ss.str()); + } else { + return PVFieldPtr(); } } + + for(size_t i=0, numFields = current->pvFields.size(); ipvFields[i]; + + if(pvField->getFieldOffset()==fieldOffset) { + return pvFields[i]; + + } else if(pvField->getNextFieldOffset()<=fieldOffset) { + continue; + + } else if(pvField->getField()->getType()==structure) { + current = static_cast(pvField.get()); + goto recurse; + } + } + // the first test against current->getNextFieldOffset() would avoid this throw std::logic_error("PVStructure.getSubField: Logic error"); } -PVFieldPtr PVStructure::getSubFieldT(std::size_t fieldOffset) const -{ - PVFieldPtr pvField = getSubField(fieldOffset); - if (pvField.get()) - return pvField; - else - { - std::stringstream ss; - ss << "Failed to get field with offset " - << fieldOffset << "(Invalid offset)" ; - throw std::runtime_error(ss.str()); - } -} - -PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const +PVFieldPtr PVStructure::getSubFieldImpl(const char *name, bool throws) const { const PVStructure *parent = this; if(!name) @@ -135,7 +126,7 @@ PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const if (throws) throw std::invalid_argument("Failed to get field: (Field name is NULL string)"); else - return NULL; + return PVFieldPtr(); } const char *fullName = name; while(true) { @@ -151,7 +142,7 @@ PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const throw std::runtime_error(ss.str()); } else - return NULL; + return PVFieldPtr(); } size_t N = sep-name; if(N==0) @@ -164,7 +155,7 @@ PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const throw std::runtime_error(ss.str()); } else - return NULL; + return PVFieldPtr(); } const PVFieldPtrArray& pvFields = parent->getPVFields(); @@ -191,7 +182,7 @@ PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const throw std::runtime_error(ss.str()); } else - return NULL; + return PVFieldPtr(); } if(*sep) { @@ -215,11 +206,25 @@ PVField* PVStructure::getSubFieldImpl(const char *name, bool throws) const // loop around to new parent } else { - return child; + return child->shared_from_this(); } } } +void PVStructure::throwBadFieldType(const char *name) +{ + std::ostringstream ss; + ss << "Failed to get field: " << name << " (Field has wrong type)"; + throw std::runtime_error(ss.str()); +} + +void PVStructure::throwBadFieldType(std::size_t fieldOffset) +{ + std::stringstream ss; + ss << "Failed to get field with offset " + << fieldOffset << " (Field has wrong type)"; + throw std::runtime_error(ss.str()); +} void PVStructure::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { diff --git a/src/pv/pvData.h b/src/pv/pvData.h index b55aaf9..0825e51 100644 --- a/src/pv/pvData.h +++ b/src/pv/pvData.h @@ -778,17 +778,6 @@ public: * @return The array. */ const PVFieldPtrArray & getPVFields() const; - /** - * Get the subfield with the specified name. - * @param fieldName The name of the field. - * @return Pointer to the field or null if field does not exist. - */ - FORCE_INLINE PVFieldPtr getSubField(std::string const &fieldName) const - { - return getSubField(fieldName.c_str()); - } - - PVFieldPtr getSubField(const char *fieldName) const; /** * Get a subfield with the specified name. @@ -798,20 +787,16 @@ public: * PVIntPtr ptr = pvStruct->getSubField("substruct.leaffield"); * @endcode */ - template + template FORCE_INLINE std::tr1::shared_ptr getSubField(std::string const &fieldName) const { return this->getSubField(fieldName.c_str()); } - template + template std::tr1::shared_ptr getSubField(const char *name) const { - PVField *raw = getSubFieldImpl(name, false); - if (raw) - return std::tr1::dynamic_pointer_cast(raw->shared_from_this()); - else - return std::tr1::shared_ptr(); + return std::tr1::dynamic_pointer_cast(getSubFieldImpl(name, false)); } /** @@ -819,32 +804,10 @@ public: * @param fieldOffset The offset. * @return Pointer to the field or null if field does not exist. */ - PVFieldPtr getSubField(std::size_t fieldOffset) const; - - /** - * Get the subfield with the specified offset. - * @param fieldOffset The offset. - * @return Pointer to the field or null if field does not exist. - */ - template + template std::tr1::shared_ptr getSubField(std::size_t fieldOffset) const { - PVFieldPtr pvField = getSubField(fieldOffset); - if (pvField.get()) - return std::tr1::dynamic_pointer_cast(pvField); - else - return std::tr1::shared_ptr(); - } - - /** - * Get a subfield with the specified name. - * @param fieldName a '.' separated list of child field names (no whitespace allowed) - * @returns A reference to the sub-field (never NULL) - * @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type - */ - FORCE_INLINE PVFieldPtr getSubFieldT(std::string const &fieldName) const - { - return getSubFieldImpl(fieldName.c_str())->shared_from_this(); + return std::tr1::dynamic_pointer_cast(getSubFieldImpl(fieldOffset, false)); } /** @@ -856,22 +819,29 @@ public: * PVIntPtr ptr = pvStruct->getSubFieldT("substruct.leaffield"); * @endcode */ - template + template FORCE_INLINE std::tr1::shared_ptr getSubFieldT(std::string const &fieldName) const { return this->getSubFieldT(fieldName.c_str()); } - template - std::tr1::shared_ptr getSubFieldT(const char *name) const; +private: + static void throwBadFieldType(const char *name); +public: - /** - * Get the subfield with the specified offset. - * @param fieldOffset The offset. - * @returns A reference to the sub-field (never NULL) - * @throws std::runtime_error if the requested sub-field doesn't exist - */ - PVFieldPtr getSubFieldT(std::size_t fieldOffset) const; + template + std::tr1::shared_ptr getSubFieldT(const char *name) const + { + std::tr1::shared_ptr pvField(std::tr1::dynamic_pointer_cast( + getSubFieldImpl(name, true))); + if(!pvField) + throwBadFieldType(name); + return pvField; + } + +private: + static void throwBadFieldType(std::size_t fieldOffset); +public: /** * Get the subfield with the specified offset. @@ -879,8 +849,16 @@ public: * @returns A reference to the sub-field (never NULL) * @throws std::runtime_error if the requested sub-field doesn't exist, or has a different type */ - template - std::tr1::shared_ptr getSubFieldT(std::size_t fieldOffset) const; + template + std::tr1::shared_ptr getSubFieldT(std::size_t fieldOffset) const + { + std::tr1::shared_ptr pvField = std::tr1::dynamic_pointer_cast( + getSubFieldImpl(fieldOffset, true)); + if(!pvField) + throwBadFieldType(fieldOffset); + return pvField; + } + /** * Serialize. @@ -932,7 +910,8 @@ public: void copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse = false); private: - PVField *getSubFieldImpl(const char *name, bool throws = true) const; + PVFieldPtr getSubFieldImpl(const char *name, bool throws) const; + PVFieldPtr getSubFieldImpl(std::size_t fieldOffset, bool throws) const; PVFieldPtrArray pvFields; StructureConstPtr structurePtr; @@ -940,39 +919,6 @@ private: friend class PVDataCreate; }; - -template -std::tr1::shared_ptr PVStructure::getSubFieldT(const char *name) const -{ - std::tr1::shared_ptr pvField = std::tr1::dynamic_pointer_cast( - getSubFieldImpl(name)->shared_from_this()); - - if (pvField.get()) - return pvField; - else - { - std::stringstream ss; - ss << "Failed to get field: " << name << " (Field has wrong type)"; - throw std::runtime_error(ss.str()); - } -} - -template -std::tr1::shared_ptr PVStructure::getSubFieldT(std::size_t fieldOffset) const -{ - std::tr1::shared_ptr pvField = std::tr1::dynamic_pointer_cast( - getSubFieldT(fieldOffset)); - if (pvField.get()) - return pvField; - else - { - std::stringstream ss; - ss << "Failed to get field with offset " - << fieldOffset << " (Field has wrong type)"; - throw std::runtime_error(ss.str()); - } -} - /** * @brief PVUnion has a single subfield. *