diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md
index 61ca2d7..2076f68 100644
--- a/documentation/RELEASE_NOTES.md
+++ b/documentation/RELEASE_NOTES.md
@@ -7,7 +7,7 @@ The main changes since release 4.0 are:
* Convert::copyUnion now always copies between subfields.
* CreateRequest prevents a possible SEGFAULT.
* New stream operators for Field and PVField are provided.
-* New method getAs that is like getSubField except that it throws exception
+* New method getSubFieldT that is like getSubField except that it throws exception
Convert copy methods and equals operators
-----------------------------------------
@@ -73,10 +73,10 @@ Now it can be done as follows:
cout << pv << endl;
}
-New method getAs that is like getSubField except that it throws exception
+New method getSubFieldT that is like getSubField except that it throws exception
--------------------
-PVStructure has a new template member getAs(const char *name)
+PVStructure has a new template member getSubFieldT(std::string const &fieldName)
that is like getSubField except that it throws a runtime_error
instead of returning null.
diff --git a/documentation/pvDataCPP.html b/documentation/pvDataCPP.html
index 6ea31bd..53902c0 100644
--- a/documentation/pvDataCPP.html
+++ b/documentation/pvDataCPP.html
@@ -465,10 +465,10 @@ structure
PVStructurePtr doubleValue = getPVDataCreate()->createPVStructure(
getStandardField()->scalar(pvDouble,"alarm,timeStamp"));
PVDoublePtr pvdouble =
- doubleValue->getAs<PVDouble>("value");
+ doubleValue->getSubField<PVDouble>("value");
pvdouble->put(1e5);
cout << *doubleValue << endl;
- double value = doubleValue->getAs<PVDouble>("value")->get();
+ double value = doubleValue->getSubField<PVDouble>("value")->get();
cout << "from get " << value << "\n\n";
This produces:
@@ -491,7 +491,7 @@ from get 100000
PVStructurePtr doubleArrayValue = pvDataCreate->createPVStructure(
standardField->scalarArray(pvDouble,"alarm,timeStamp"));
PVDoubleArrayPtr pvDoubleArray =
- doubleArrayValue->getAs<PVDoubleArray>("value");
+ doubleArrayValue->getSubField<PVDoubleArray>("value");
size_t len = 10;
shared_vector<double> xxx(len);
for(size_t i=0; i< len; ++i) xxx[i] = i;
@@ -605,10 +605,10 @@ structure
createUnion(),
"alarm,timeStamp"));
PVStructurePtr pvTimeStamp =
- pvStructure->getAs<PVUnion>("value")->select<PVStructure>(2);
- pvTimeStamp->getAs<PVLong>("secondsPastEpoch")->put(1000);
+ pvStructure->getSubField<PVUnion>("value")->select<PVStructure>(2);
+ pvTimeStamp->getSubField<PVLong>("secondsPastEpoch")->put(1000);
cout << *pvStructure) << "\n";
- pvStructure->getAs<PVUnion>("value")->select<PVDouble>(0)->put(1e5);
+ pvStructure->getSubField<PVUnion>("value")->select<PVDouble>(0)->put(1e5);
cout << *pvStructure << "\n\n";
This produces:
@@ -648,13 +648,13 @@ epics:nt/NTUnion:1.0
standardField->variantUnion("alarm,timeStamp"));
PVStructurePtr pvTimeStamp =
pvDataCreate->createPVStructure(standardField->timeStamp());
- pvStructure->getAs<PVUnion>("value")->set(pvTimeStamp);
- pvTimeStamp->getAs<PVLong>("secondsPastEpoch")->put(1000);
+ pvStructure->getSubField<PVUnion>("value")->set(pvTimeStamp);
+ pvTimeStamp->getSubField<PVLong>("secondsPastEpoch")->put(1000);
cout << *pvStructure << "\n";
- pvStructure->getAs<PVUnion>("value")->set(
+ pvStructure->getSubField<PVUnion>("value")->set(
pvDataCreate->createPVScalar(pvDouble));
PVDoublePtr pvValue = static_pointer_cast<PVDouble>(
- pvStructure->getAs<PVUnion>("value")->get());
+ pvStructure->getSubField<PVUnion>("value")->get());
pvValue->put(1e5);
cout << *pvStructure << "\n\n";
@@ -718,7 +718,7 @@ epics:nt/NTUnion:1.0
cout << *pvStructure->getStructure() << endl;
cout << "data\n";
cout << *pvStructure << "\n";
- PVUnionPtr pvUnion = pvStructure->getAs<PVUnion>("value");;
+ PVUnionPtr pvUnion = pvStructure->getSubField<PVUnion>("value");;
pvUnion->select("doubleValue");
PVDoublePtr pvDouble = pvUnion->get<PVDouble>();
pvDouble->put(1.55);
@@ -726,7 +726,7 @@ epics:nt/NTUnion:1.0
cout << *pvStructure << "\n";
cout << "value = " << pvDouble->get() << "\n";
pvUnion->select("structValue");
- pvDouble = pvUnion->get<PVStructure>()->getAs<PVDouble>("doubleValue");
+ pvDouble = pvUnion->get<PVStructure>()->getSubField<PVDouble>("doubleValue");
pvDouble->put(1.65);
cout << "select structValue\n";
cout << *pvStructure << "\n";
@@ -2304,14 +2304,21 @@ public:
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
- template<typename PVT>
- PVT& getAs(const char *name) const;
-
PVFieldPtr getSubField(std::size_t fieldOffset) const;
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
+ PVFieldPtr getSubFieldT(std::string const &fieldName) const;
+
+ template<typename PVT>
+ std::tr1::shared_ptr<PVT> getSubFieldT(std::string const &fieldName) const
+
+ PVFieldPtr getSubFieldT(std::size_t fieldOffset) const;
+
+ template<typename PVT>
+ std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const
+
virtual void serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
virtual void deserialize(
@@ -2332,10 +2339,7 @@ public:
getPVFields
Returns the array of subfields. The set of subfields must all have
different field names.
- getAs(const char *name)
- Like the getSubField except that it throws std::runtime_error if
- the field does not exists or has the wrong type.
- getSubField(std::string fieldName)
+ getSubField(std::string const &fieldName)
Get a subField of a field.d
A non-null result is
@@ -2350,9 +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.
@@ -5414,7 +5422,7 @@ public:
raiseMonitor = true;
if(pvFieldOptions!=NULL) {
PVStringPtr pvString =
- pvFieldOptions->getAs<PVString>("raiseMonitor");
+ pvFieldOptions->getSubField<PVString>("raiseMonitor");
if(pvString!=NULL) {
std::string value = pvString->get();
if(value.compare("false")==0) raiseMonitor = false;
diff --git a/documentation/pvDataCPP_20150623.html b/documentation/pvDataCPP_20150623.html
index 6ea31bd..53902c0 100644
--- a/documentation/pvDataCPP_20150623.html
+++ b/documentation/pvDataCPP_20150623.html
@@ -465,10 +465,10 @@ structure
PVStructurePtr doubleValue = getPVDataCreate()->createPVStructure(
getStandardField()->scalar(pvDouble,"alarm,timeStamp"));
PVDoublePtr pvdouble =
- doubleValue->getAs<PVDouble>("value");
+ doubleValue->getSubField<PVDouble>("value");
pvdouble->put(1e5);
cout << *doubleValue << endl;
- double value = doubleValue->getAs<PVDouble>("value")->get();
+ double value = doubleValue->getSubField<PVDouble>("value")->get();
cout << "from get " << value << "\n\n";
This produces:
@@ -491,7 +491,7 @@ from get 100000
PVStructurePtr doubleArrayValue = pvDataCreate->createPVStructure(
standardField->scalarArray(pvDouble,"alarm,timeStamp"));
PVDoubleArrayPtr pvDoubleArray =
- doubleArrayValue->getAs<PVDoubleArray>("value");
+ doubleArrayValue->getSubField<PVDoubleArray>("value");
size_t len = 10;
shared_vector<double> xxx(len);
for(size_t i=0; i< len; ++i) xxx[i] = i;
@@ -605,10 +605,10 @@ structure
createUnion(),
"alarm,timeStamp"));
PVStructurePtr pvTimeStamp =
- pvStructure->getAs<PVUnion>("value")->select<PVStructure>(2);
- pvTimeStamp->getAs<PVLong>("secondsPastEpoch")->put(1000);
+ pvStructure->getSubField<PVUnion>("value")->select<PVStructure>(2);
+ pvTimeStamp->getSubField<PVLong>("secondsPastEpoch")->put(1000);
cout << *pvStructure) << "\n";
- pvStructure->getAs<PVUnion>("value")->select<PVDouble>(0)->put(1e5);
+ pvStructure->getSubField<PVUnion>("value")->select<PVDouble>(0)->put(1e5);
cout << *pvStructure << "\n\n";
This produces:
@@ -648,13 +648,13 @@ epics:nt/NTUnion:1.0
standardField->variantUnion("alarm,timeStamp"));
PVStructurePtr pvTimeStamp =
pvDataCreate->createPVStructure(standardField->timeStamp());
- pvStructure->getAs<PVUnion>("value")->set(pvTimeStamp);
- pvTimeStamp->getAs<PVLong>("secondsPastEpoch")->put(1000);
+ pvStructure->getSubField<PVUnion>("value")->set(pvTimeStamp);
+ pvTimeStamp->getSubField<PVLong>("secondsPastEpoch")->put(1000);
cout << *pvStructure << "\n";
- pvStructure->getAs<PVUnion>("value")->set(
+ pvStructure->getSubField<PVUnion>("value")->set(
pvDataCreate->createPVScalar(pvDouble));
PVDoublePtr pvValue = static_pointer_cast<PVDouble>(
- pvStructure->getAs<PVUnion>("value")->get());
+ pvStructure->getSubField<PVUnion>("value")->get());
pvValue->put(1e5);
cout << *pvStructure << "\n\n";
@@ -718,7 +718,7 @@ epics:nt/NTUnion:1.0
cout << *pvStructure->getStructure() << endl;
cout << "data\n";
cout << *pvStructure << "\n";
- PVUnionPtr pvUnion = pvStructure->getAs<PVUnion>("value");;
+ PVUnionPtr pvUnion = pvStructure->getSubField<PVUnion>("value");;
pvUnion->select("doubleValue");
PVDoublePtr pvDouble = pvUnion->get<PVDouble>();
pvDouble->put(1.55);
@@ -726,7 +726,7 @@ epics:nt/NTUnion:1.0
cout << *pvStructure << "\n";
cout << "value = " << pvDouble->get() << "\n";
pvUnion->select("structValue");
- pvDouble = pvUnion->get<PVStructure>()->getAs<PVDouble>("doubleValue");
+ pvDouble = pvUnion->get<PVStructure>()->getSubField<PVDouble>("doubleValue");
pvDouble->put(1.65);
cout << "select structValue\n";
cout << *pvStructure << "\n";
@@ -2304,14 +2304,21 @@ public:
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
- template<typename PVT>
- PVT& getAs(const char *name) const;
-
PVFieldPtr getSubField(std::size_t fieldOffset) const;
template<typename PVT>
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
+ PVFieldPtr getSubFieldT(std::string const &fieldName) const;
+
+ template<typename PVT>
+ std::tr1::shared_ptr<PVT> getSubFieldT(std::string const &fieldName) const
+
+ PVFieldPtr getSubFieldT(std::size_t fieldOffset) const;
+
+ template<typename PVT>
+ std::tr1::shared_ptr<PVT> getSubFieldT(std::size_t fieldOffset) const
+
virtual void serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
virtual void deserialize(
@@ -2332,10 +2339,7 @@ public:
getPVFields
Returns the array of subfields. The set of subfields must all have
different field names.
- getAs(const char *name)
- Like the getSubField except that it throws std::runtime_error if
- the field does not exists or has the wrong type.
- getSubField(std::string fieldName)
+ getSubField(std::string const &fieldName)
Get a subField of a field.d
A non-null result is
@@ -2350,9 +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.
@@ -5414,7 +5422,7 @@ public:
raiseMonitor = true;
if(pvFieldOptions!=NULL) {
PVStringPtr pvString =
- pvFieldOptions->getAs<PVString>("raiseMonitor");
+ pvFieldOptions->getSubField<PVString>("raiseMonitor");
if(pvString!=NULL) {
std::string value = pvString->get();
if(value.compare("false")==0) raiseMonitor = false;
diff --git a/src/factory/PVStructure.cpp b/src/factory/PVStructure.cpp
index 5d61056..a7996b7 100644
--- a/src/factory/PVStructure.cpp
+++ b/src/factory/PVStructure.cpp
@@ -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 = getSubFieldImpl(fieldName.c_str(), false);
+ if (field)
+ return field->shared_from_this();
+ else
+ return PVFieldPtr();
}
@@ -134,21 +134,59 @@ PVFieldPtr PVStructure::getSubField(size_t fieldOffset) const
throw std::logic_error("PVStructure.getSubField: Logic error");
}
-PVField* PVStructure::GetAsImpl(const char *name) const
+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
{
const PVStructure *parent = this;
if(!name)
- throw std::invalid_argument("field name is NULL string");
-
+ {
+ if (throws)
+ throw std::invalid_argument("Failed to get field: (Field name is NULL string)");
+ else
+ return NULL;
+ }
+ const char *fullName = name;
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)
+ {
+ std::stringstream ss;
+ ss << "Failed to get field: " << fullName
+ << " (No spaces allowed in field name)";
+ throw std::runtime_error(ss.str());
+ }
+ else
+ return NULL;
+ }
size_t N = sep-name;
if(N==0)
- throw std::runtime_error("zero-length field name encountered");
+ {
+ if (throws)
+ {
+ std::stringstream ss;
+ ss << "Failed to get field: " << fullName
+ << " (Zero-length field name encountered)";
+ throw std::runtime_error(ss.str());
+ }
+ else
+ return NULL;
+ }
const PVFieldPtrArray& pvFields = parent->getPVFields();
@@ -165,13 +203,34 @@ PVField* PVStructure::GetAsImpl(const char *name) const
}
if(!child)
- throw std::runtime_error("field not found"); //TODO: which sub field?
+ {
+ if (throws)
+ {
+ std::stringstream ss;
+ ss << "Failed to get field: " << fullName << " ("
+ << std::string(fullName, sep) << " not found)";
+ throw std::runtime_error(ss.str());
+ }
+ else
+ return NULL;
+ }
if(*sep) {
// this is not the requested leaf
parent = dynamic_cast(child);
if(!parent)
- throw std::runtime_error("mid-field is not a PVStructure"); //TODO: which sub field?
+ {
+ if (throws)
+ {
+ std::stringstream ss;
+ ss << "Failed to get field: " << fullName
+ << " (" << std::string(fullName, sep)
+ << " is not a structure)";
+ throw std::runtime_error(ss.str());
+ }
+ else
+ return NULL;
+ }
child = NULL;
name = sep+1; // skip past '.'
// loop around to new parent
@@ -256,22 +315,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(pvField->getField());
- if(pscalarArray->getElementType()!=elementType) {
- return nullPVScalarArray;
- }
- return std::tr1::static_pointer_cast(pvField);
- }catch(...){
+ PVScalarArrayPtr arrayField = getSubField(fieldName);
+ if (arrayField.get() &&
+ arrayField->getScalarArray()->getElementType()!=elementType)
+ {
return nullPVScalarArray;
- }
+ }
+ return arrayField;
}
PVStructureArrayPtr PVStructure::getStructureArrayField(
diff --git a/src/pv/pvData.h b/src/pv/pvData.h
index 7384cac..e54d636 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,32 +730,75 @@ public:
return std::tr1::shared_ptr();
}
-private:
- PVField *GetAsImpl(const char *name) 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 PVFieldPtr getSubFieldT(std::string const &fieldName) const
+ {
+ return getSubFieldImpl(fieldName.c_str())->shared_from_this();
+ }
/**
* 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->getAs("substruct.leaffield");
+ * PVIntPtr ptr = pvStruct->getSubFieldT("substruct.leaffield");
* @endcode
*/
template
- PVT& getAs(const char *name) const
+ FORCE_INLINE std::tr1::shared_ptr getSubFieldT(std::string const &fieldName) const
{
- PVT *raw = dynamic_cast(GetAsImpl(name));
- if(!raw)
- throw std::runtime_error("Field has wrong type");
- return *raw;
+ return this->getSubFieldT(fieldName.c_str());
}
template
- FORCE_INLINE PVT& getAs(std::string const &fieldName) const
+ std::tr1::shared_ptr getSubFieldT(const char *name) const
{
- return this->getAs(fieldName.c_str());
+ 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());
+ }
+ }
+ /**
+ * 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;
+
+ /**
+ * 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
+ std::tr1::shared_ptr 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());
+ }
}
/**
@@ -911,6 +973,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;
diff --git a/testApp/pv/testPVData.cpp b/testApp/pv/testPVData.cpp
index 327a9c2..ec387f7 100644
--- a/testApp/pv/testPVData.cpp
+++ b/testApp/pv/testPVData.cpp
@@ -541,16 +541,16 @@ static void testFieldAccess()
PVIntPtr a = fld->getSubField("test");
testOk1(a!=NULL);
if(a.get()) {
- PVInt& b = fld->getAs("test");
- testOk(&b==a.get(), "%p == %p", &b, a.get());
+ PVIntPtr b = fld->getSubFieldT("test");
+ testOk(b.get()==a.get(), "%p == %p", b.get(), a.get());
} else
testSkip(1, "test doesn't exist?");
a = fld->getSubField("hello.world");
testOk1(a!=NULL);
if(a.get()) {
- PVInt& b = fld->getAs("hello.world");
- testOk(&b==a.get(), "%p == %p", &b, a.get());
+ PVIntPtr b = fld->getSubFieldT("hello.world");
+ testOk(b.get()==a.get(), "%p == %p", b.get(), a.get());
} else
testSkip(1, "hello.world doesn't exist?");
@@ -573,22 +573,67 @@ static void testFieldAccess()
// whitespace
testOk1(fld->getSubField(" test").get()==NULL);
+ // intermediate field not structure
+ testOk1(fld->getSubField("hello.world.invalid").get()==NULL);
+
+ // null string
try{
- fld->getAs("invalid");
+ char * name = NULL;
+ fld->getSubFieldT(name);
+ testFail("missing required exception");
+ }catch(std::invalid_argument& e){
+ testPass("caught expected exception: %s", e.what());
+ }
+
+ // non-existent
+ try{
+ fld->getSubFieldT("invalid");
testFail("missing required exception");
}catch(std::runtime_error& e){
testPass("caught expected exception: %s", e.what());
}
+ // wrong type
try{
- fld->getAs("test");
+ fld->getSubFieldT("test");
testFail("missing required exception");
}catch(std::runtime_error& e){
testPass("caught expected exception: %s", e.what());
}
+ // empty leaf field name
try{
- fld->getAs("hello.world.invalid");
+ fld->getSubFieldT("hello.");
+ testFail("missing required exception");
+ }catch(std::runtime_error& e){
+ testPass("caught expected exception: %s", e.what());
+ }
+
+ // empty field name
+ try{
+ fld->getSubFieldT("hello..world");
+ testFail("missing required exception");
+ }catch(std::runtime_error& e){
+ testPass("caught expected exception: %s", e.what());
+ }
+ try{
+ fld->getSubFieldT(".");
+ testFail("missing required exception");
+ }catch(std::runtime_error& e){
+ testPass("caught expected exception: %s", e.what());
+ }
+
+ // whitespace
+ try{
+ fld->getSubFieldT(" test");
+ testFail("missing required exception");
+ }catch(std::runtime_error& e){
+ testPass("caught expected exception: %s", e.what());
+ }
+
+ // intermediate field not structure
+ try{
+ fld->getSubFieldT("hello.world.invalid");
testFail("missing required exception");
}catch(std::runtime_error& e){
testPass("caught expected exception: %s", e.what());
@@ -597,7 +642,7 @@ static void testFieldAccess()
MAIN(testPVData)
{
- testPlan(236);
+ testPlan(242);
fieldCreate = getFieldCreate();
pvDataCreate = getPVDataCreate();
standardField = getStandardField();