reduce # of PVStructure::getSubField overloads

This commit is contained in:
Michael Davidsaver
2017-08-08 16:37:12 +02:00
parent 8bfe7b6b9d
commit b84ed964f9
2 changed files with 81 additions and 130 deletions

View File

@@ -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; i<numFields; i++) {
PVFieldPtr pvField = pvFields[i];
if(pvField->getFieldOffset()==fieldOffset) return pvFields[i];
if(pvField->getNextFieldOffset()<=fieldOffset) continue;
if(pvField->getField()->getType()==structure) {
PVStructure *pvStructure = static_cast<PVStructure *>(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(); i<numFields; i++) {
const PVFieldPtr& pvField = current->pvFields[i];
if(pvField->getFieldOffset()==fieldOffset) {
return pvFields[i];
} else if(pvField->getNextFieldOffset()<=fieldOffset) {
continue;
} else if(pvField->getField()->getType()==structure) {
current = static_cast<PVStructure *>(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 {

View File

@@ -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<PVInt>("substruct.leaffield");
* @endcode
*/
template<typename PVT>
template<typename PVT = PVField>
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
{
return this->getSubField<PVT>(fieldName.c_str());
}
template<typename PVT>
template<typename PVT = PVField>
std::tr1::shared_ptr<PVT> getSubField(const char *name) const
{
PVField *raw = getSubFieldImpl(name, false);
if (raw)
return std::tr1::dynamic_pointer_cast<PVT>(raw->shared_from_this());
else
return std::tr1::shared_ptr<PVT>();
return std::tr1::dynamic_pointer_cast<PVT>(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<typename PVT>
template<typename PVT = PVField>
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
{
PVFieldPtr pvField = getSubField(fieldOffset);
if (pvField.get())
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
else
return std::tr1::shared_ptr<PVT>();
}
/**
* 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<PVT>(getSubFieldImpl(fieldOffset, false));
}
/**
@@ -856,22 +819,29 @@ public:
* PVIntPtr ptr = pvStruct->getSubFieldT<PVInt>("substruct.leaffield");
* @endcode
*/
template<typename PVT>
template<typename PVT = PVField>
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubFieldT(std::string const &fieldName) const
{
return this->getSubFieldT<PVT>(fieldName.c_str());
}
template<typename PVT>
std::tr1::shared_ptr<PVT> 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<typename PVT = PVField>
std::tr1::shared_ptr<PVT> getSubFieldT(const char *name) const
{
std::tr1::shared_ptr<PVT> pvField(std::tr1::dynamic_pointer_cast<PVT>(
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<typename PVT>
std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const;
template<typename PVT = PVField>
std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const
{
std::tr1::shared_ptr<PVT> pvField = std::tr1::dynamic_pointer_cast<PVT>(
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<typename PVT>
std::tr1::shared_ptr<PVT> PVStructure::getSubFieldT(const char *name) const
{
std::tr1::shared_ptr<PVT> pvField = std::tr1::dynamic_pointer_cast<PVT>(
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<typename PVT>
std::tr1::shared_ptr<PVT> PVStructure::getSubFieldT(std::size_t fieldOffset) const
{
std::tr1::shared_ptr<PVT> pvField = std::tr1::dynamic_pointer_cast<PVT>(
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.
*