diff --git a/documentation/pvDataCPP.html b/documentation/pvDataCPP.html index 8618d59..89541be 100644 --- a/documentation/pvDataCPP.html +++ b/documentation/pvDataCPP.html @@ -2309,8 +2309,15 @@ public: template<typename PVT> std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const + PVField& getSubFieldT(std::string const &fieldName) const; + template<typename PVT> - PVT& getSubFieldT(std::string const &fieldName) const; + PVT& getSubFieldT(std::string const &fieldName) const + + PVField& getSubFieldT(std::size_t fieldOffset) const; + + template<typename PVT> + PVT& getSubFieldT(std::size_t fieldOffset) const virtual void serialize( ByteBuffer *pbuffer,SerializableControl *pflusher) const ; @@ -2332,7 +2339,7 @@ public:
getPVFields
Returns the array of subfields. The set of subfields must all have different field names.
-
getSubField(std::string fieldName)
+
getSubField(std::string const &fieldName)
Get a subField of a field.d A non-null result is @@ -2347,12 +2354,13 @@ public:
Get the field located a fieldOffset, where fieldOffset is relative to the top level structure. This returns null if the specified field is not located within this PVStructure. -
- Note The template version replaces getBooleanField, etc.
getSubFieldT(std::string const &fieldName)
Like getSubField except that it throws std::runtime_error if the field does not exists or has the wrong type.
+
getSubFieldT(int fieldOffset)
+
Like getSubField except that it throws std::runtime_error if + the field does not exists or has the wrong type.
dumpValue
Method for streams I/O.
diff --git a/documentation/pvDataCPP_20150623.html b/documentation/pvDataCPP_20150623.html index 8618d59..89541be 100644 --- a/documentation/pvDataCPP_20150623.html +++ b/documentation/pvDataCPP_20150623.html @@ -2309,8 +2309,15 @@ public: template<typename PVT> std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const + PVField& getSubFieldT(std::string const &fieldName) const; + template<typename PVT> - PVT& getSubFieldT(std::string const &fieldName) const; + PVT& getSubFieldT(std::string const &fieldName) const + + PVField& getSubFieldT(std::size_t fieldOffset) const; + + template<typename PVT> + PVT& getSubFieldT(std::size_t fieldOffset) const virtual void serialize( ByteBuffer *pbuffer,SerializableControl *pflusher) const ; @@ -2332,7 +2339,7 @@ public:
getPVFields
Returns the array of subfields. The set of subfields must all have different field names.
-
getSubField(std::string fieldName)
+
getSubField(std::string const &fieldName)
Get a subField of a field.d A non-null result is @@ -2347,12 +2354,13 @@ public:
Get the field located a fieldOffset, where fieldOffset is relative to the top level structure. This returns null if the specified field is not located within this PVStructure. -
- Note The template version replaces getBooleanField, etc.
getSubFieldT(std::string const &fieldName)
Like getSubField except that it throws std::runtime_error if the field does not exists or has the wrong type.
+
getSubFieldT(int fieldOffset)
+
Like getSubField except that it throws std::runtime_error if + the field does not exists or has the wrong type.
dumpValue
Method for streams I/O.
diff --git a/src/factory/PVStructure.cpp b/src/factory/PVStructure.cpp index 5319369..b4ecf6b 100644 --- a/src/factory/PVStructure.cpp +++ b/src/factory/PVStructure.cpp @@ -134,6 +134,20 @@ PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const throw std::logic_error("PVStructure.getSubField: Logic error"); } +PVField& PVStructure::getSubFieldT(std::size_t fieldOffset) const +{ + PVField * raw = getSubField(fieldOffset).get(); + if (raw) + return *raw; + 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 { const PVStructure *parent = this; diff --git a/src/pv/pvData.h b/src/pv/pvData.h index 0e0e6b2..1e305b9 100644 --- a/src/pv/pvData.h +++ b/src/pv/pvData.h @@ -684,23 +684,42 @@ public: */ PVFieldPtr getSubField(std::string const &fieldName) const; + /** + * Get a subfield with the specified name. + * @param fieldName a '.' separated list of child field names (no whitespace allowed) + * @returns A pointer to the sub-field or null if field does not exist or has a different type + * @code + * PVIntPtr ptr = pvStruct->getSubField("substruct.leaffield"); + * @endcode + */ template - std::tr1::shared_ptr getSubField(std::string const &fieldName) const + FORCE_INLINE std::tr1::shared_ptr getSubField(std::string const &fieldName) const { - PVFieldPtr pvField = getSubField(fieldName); - if (pvField.get()) - return std::tr1::dynamic_pointer_cast(pvField); + return this->getSubField(fieldName.c_str()); + } + + 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(); } - + /** * Get the subfield with the specified offset. * @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 std::tr1::shared_ptr getSubField(std::size_t fieldOffset) const { @@ -711,19 +730,32 @@ public: return std::tr1::shared_ptr(); } -private: - PVField *getSubFieldImpl(const char *name, bool throws = true) const; -public: + /** + * 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 PVField& getSubFieldT(std::string const &fieldName) const + { + return *getSubFieldImpl(fieldName.c_str()); + } /** * Get a subfield with the specified name. - * @param name a '.' separated list of child field names (no whitespace allowed) + * @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 * @code * PVInt& ref = pvStruct->getSubFieldT("substruct.leaffield"); * @endcode */ + template + FORCE_INLINE PVT& getSubFieldT(std::string const &fieldName) const + { + return this->getSubFieldT(fieldName.c_str()); + } + template PVT& getSubFieldT(const char *name) const { @@ -737,10 +769,33 @@ public: return *raw; } + /** + * 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 + */ + PVField& getSubFieldT(std::size_t fieldOffset) const; + + /** + * 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, or has a different type + */ template - FORCE_INLINE PVT& getSubFieldT(std::string const &fieldName) const + PVT& getSubFieldT(std::size_t fieldOffset) const { - return this->getSubFieldT(fieldName.c_str()); + PVT* raw = dynamic_cast(&getSubFieldT(fieldOffset)); + if (raw) + return *raw; + else + { + std::stringstream ss; + ss << "Failed to get field with offset " + << fieldOffset << " (Field has wrong type)"; + throw std::runtime_error(ss.str()); + } } /** @@ -915,6 +970,8 @@ public: void copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse = false); private: + PVField *getSubFieldImpl(const char *name, bool throws = true) const; + static PVFieldPtr nullPVField; static PVBooleanPtr nullPVBoolean; static PVBytePtr nullPVByte;