Implement getSubField functions without using exceptions

Implementation of getSubField (and getScalarArrayField) introduced in
the getAs pull request throws an exception then catches it to return a
null pointer. Implement without throwing.

Signed-off-by: Dave Hickin <david.hickin@diamond.ac.uk>
This commit is contained in:
Dave Hickin
2015-07-13 02:16:08 +01:00
parent d9963b0631
commit 97cbea6f4d
2 changed files with 43 additions and 29 deletions

View File

@@ -107,11 +107,11 @@ const PVFieldPtrArray & PVStructure::getPVFields() const
PVFieldPtr PVStructure::getSubField(string const &fieldName) const
{
try{
return GetAsImpl(fieldName.c_str())->shared_from_this();
}catch(...){
return PVFieldPtr();
}
PVField * field = GetAsImpl(fieldName.c_str(), false);
if (field)
return field->shared_from_this();
else
return PVFieldPtr();
}
@@ -134,21 +134,34 @@ PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
throw std::logic_error("PVStructure.getSubField: Logic error");
}
PVField* PVStructure::GetAsImpl(const char *name) const
PVField* PVStructure::GetAsImpl(const char *name, bool throws) const
{
const PVStructure *parent = this;
if(!name)
throw std::invalid_argument("field name is NULL string");
{
if (throws)
throw std::invalid_argument("field name is NULL string");
else
return NULL;
}
while(true) {
const char *sep=name;
while(*sep!='\0' && *sep!='.' && *sep!=' ') sep++;
if(*sep==' ')
throw std::runtime_error("No spaces allowed in field name");
{
if (throws)
throw std::runtime_error("No spaces allowed in field name ");
else
return NULL;
}
size_t N = sep-name;
if(N==0)
throw std::runtime_error("zero-length field name encountered");
{
if (throws)
throw std::runtime_error("zero-length field name encountered");
else
return NULL;
}
const PVFieldPtrArray& pvFields = parent->getPVFields();
@@ -165,13 +178,23 @@ PVField* PVStructure::GetAsImpl(const char *name) const
}
if(!child)
throw std::runtime_error("field not found"); //TODO: which sub field?
{
if (throws)
throw std::runtime_error("field not found"); //TODO: which sub field?
else
return NULL;
}
if(*sep) {
// this is not the requested leaf
parent = dynamic_cast<PVStructure*>(child);
if(!parent)
throw std::runtime_error("mid-field is not a PVStructure"); //TODO: which sub field?
{
if (throws)
throw std::runtime_error("mid-field is not a PVStructure"); //TODO: which sub field?
else
return NULL;
}
child = NULL;
name = sep+1; // skip past '.'
// loop around to new parent
@@ -256,22 +279,13 @@ PVUnionPtr PVStructure::getUnionField(string const &fieldName)
PVScalarArrayPtr PVStructure::getScalarArrayField(
string const &fieldName,ScalarType elementType)
{
try{
PVFieldPtr pvField = GetAsImpl(fieldName.c_str())->shared_from_this();
FieldConstPtr field = pvField->getField();
Type type = field->getType();
if(type!=scalarArray) {
return nullPVScalarArray;
}
ScalarArrayConstPtr pscalarArray
= static_pointer_cast<const ScalarArray>(pvField->getField());
if(pscalarArray->getElementType()!=elementType) {
return nullPVScalarArray;
}
return std::tr1::static_pointer_cast<PVScalarArray>(pvField);
}catch(...){
PVScalarArrayPtr arrayField = getSubField<PVScalarArray>(fieldName);
if (arrayField.get() &&
arrayField->getScalarArray()->getElementType()!=elementType)
{
return nullPVScalarArray;
}
}
return arrayField;
}
PVStructureArrayPtr PVStructure::getStructureArrayField(

View File

@@ -712,7 +712,7 @@ public:
}
private:
PVField *GetAsImpl(const char *name) const;
PVField *GetAsImpl(const char *name, bool throws = true) const;
public:
/**