@@ -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
|
||||
--------------------
|
||||
|
||||
<b>PVStructure</b> has a new template member <b>getAs(const char *name)</b>
|
||||
<b>PVStructure</b> has a new template member <b>getSubFieldT(std::string const &fieldName)</b>
|
||||
that is like <b>getSubField</b> except that it throws a runtime_error
|
||||
instead of returning null.
|
||||
|
||||
|
||||
@@ -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";
|
||||
</pre>
|
||||
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";
|
||||
</pre>
|
||||
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";
|
||||
</pre>
|
||||
@@ -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:
|
||||
<dt>getPVFields</dt>
|
||||
<dd>Returns the array of subfields. The set of subfields must all have
|
||||
different field names.</dd>
|
||||
<dt>getAs(const char *name)</dt>
|
||||
<dd>Like the getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>getSubField(std::string fieldName)</dt>
|
||||
<dt>getSubField(std::string const &fieldName)</dt>
|
||||
<dd>
|
||||
Get a subField of a field.d
|
||||
A non-null result is
|
||||
@@ -2350,9 +2354,13 @@ public:
|
||||
<dd>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.
|
||||
<br />
|
||||
<b>Note</b> The template version replaces getBooleanField, etc.<br/>
|
||||
</dd>
|
||||
<dt>getSubFieldT(std::string const &fieldName)</dt>
|
||||
<dd>Like getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>getSubFieldT(int fieldOffset)</dt>
|
||||
<dd>Like getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>dumpValue</dt>
|
||||
<dd>Method for streams I/O.</dd>
|
||||
</dl>
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
</pre>
|
||||
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";
|
||||
</pre>
|
||||
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";
|
||||
</pre>
|
||||
@@ -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:
|
||||
<dt>getPVFields</dt>
|
||||
<dd>Returns the array of subfields. The set of subfields must all have
|
||||
different field names.</dd>
|
||||
<dt>getAs(const char *name)</dt>
|
||||
<dd>Like the getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>getSubField(std::string fieldName)</dt>
|
||||
<dt>getSubField(std::string const &fieldName)</dt>
|
||||
<dd>
|
||||
Get a subField of a field.d
|
||||
A non-null result is
|
||||
@@ -2350,9 +2354,13 @@ public:
|
||||
<dd>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.
|
||||
<br />
|
||||
<b>Note</b> The template version replaces getBooleanField, etc.<br/>
|
||||
</dd>
|
||||
<dt>getSubFieldT(std::string const &fieldName)</dt>
|
||||
<dd>Like getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>getSubFieldT(int fieldOffset)</dt>
|
||||
<dd>Like getSubField except that it throws std::runtime_error if
|
||||
the field does not exists or has the wrong type.</dd>
|
||||
<dt>dumpValue</dt>
|
||||
<dd>Method for streams I/O.</dd>
|
||||
</dl>
|
||||
@@ -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;
|
||||
|
||||
@@ -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<PVStructure*>(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<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(
|
||||
|
||||
100
src/pv/pvData.h
100
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<PVInt>("substruct.leaffield");
|
||||
* @endcode
|
||||
*/
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
|
||||
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
|
||||
{
|
||||
PVFieldPtr pvField = getSubField(fieldName);
|
||||
if (pvField.get())
|
||||
return std::tr1::dynamic_pointer_cast<PVT>(pvField);
|
||||
return this->getSubField<PVT>(fieldName.c_str());
|
||||
}
|
||||
|
||||
template<typename PVT>
|
||||
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>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
|
||||
{
|
||||
@@ -711,32 +730,75 @@ public:
|
||||
return std::tr1::shared_ptr<PVT>();
|
||||
}
|
||||
|
||||
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<PVInt>("substruct.leaffield");
|
||||
* PVIntPtr ptr = pvStruct->getSubFieldT<PVInt>("substruct.leaffield");
|
||||
* @endcode
|
||||
*/
|
||||
template<typename PVT>
|
||||
PVT& getAs(const char *name) const
|
||||
FORCE_INLINE std::tr1::shared_ptr<PVT> getSubFieldT(std::string const &fieldName) const
|
||||
{
|
||||
PVT *raw = dynamic_cast<PVT*>(GetAsImpl(name));
|
||||
if(!raw)
|
||||
throw std::runtime_error("Field has wrong type");
|
||||
return *raw;
|
||||
return this->getSubFieldT<PVT>(fieldName.c_str());
|
||||
}
|
||||
|
||||
template<typename PVT>
|
||||
FORCE_INLINE PVT& getAs(std::string const &fieldName) const
|
||||
std::tr1::shared_ptr<PVT> getSubFieldT(const char *name) const
|
||||
{
|
||||
return this->getAs<PVT>(fieldName.c_str());
|
||||
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());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> 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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
|
||||
@@ -541,16 +541,16 @@ static void testFieldAccess()
|
||||
PVIntPtr a = fld->getSubField<PVInt>("test");
|
||||
testOk1(a!=NULL);
|
||||
if(a.get()) {
|
||||
PVInt& b = fld->getAs<PVInt>("test");
|
||||
testOk(&b==a.get(), "%p == %p", &b, a.get());
|
||||
PVIntPtr b = fld->getSubFieldT<PVInt>("test");
|
||||
testOk(b.get()==a.get(), "%p == %p", b.get(), a.get());
|
||||
} else
|
||||
testSkip(1, "test doesn't exist?");
|
||||
|
||||
a = fld->getSubField<PVInt>("hello.world");
|
||||
testOk1(a!=NULL);
|
||||
if(a.get()) {
|
||||
PVInt& b = fld->getAs<PVInt>("hello.world");
|
||||
testOk(&b==a.get(), "%p == %p", &b, a.get());
|
||||
PVIntPtr b = fld->getSubFieldT<PVInt>("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<PVInt>(" test").get()==NULL);
|
||||
|
||||
// intermediate field not structure
|
||||
testOk1(fld->getSubField<PVInt>("hello.world.invalid").get()==NULL);
|
||||
|
||||
// null string
|
||||
try{
|
||||
fld->getAs<PVInt>("invalid");
|
||||
char * name = NULL;
|
||||
fld->getSubFieldT<PVInt>(name);
|
||||
testFail("missing required exception");
|
||||
}catch(std::invalid_argument& e){
|
||||
testPass("caught expected exception: %s", e.what());
|
||||
}
|
||||
|
||||
// non-existent
|
||||
try{
|
||||
fld->getSubFieldT<PVInt>("invalid");
|
||||
testFail("missing required exception");
|
||||
}catch(std::runtime_error& e){
|
||||
testPass("caught expected exception: %s", e.what());
|
||||
}
|
||||
|
||||
// wrong type
|
||||
try{
|
||||
fld->getAs<PVDouble>("test");
|
||||
fld->getSubFieldT<PVDouble>("test");
|
||||
testFail("missing required exception");
|
||||
}catch(std::runtime_error& e){
|
||||
testPass("caught expected exception: %s", e.what());
|
||||
}
|
||||
|
||||
// empty leaf field name
|
||||
try{
|
||||
fld->getAs<PVDouble>("hello.world.invalid");
|
||||
fld->getSubFieldT<PVDouble>("hello.");
|
||||
testFail("missing required exception");
|
||||
}catch(std::runtime_error& e){
|
||||
testPass("caught expected exception: %s", e.what());
|
||||
}
|
||||
|
||||
// empty field name
|
||||
try{
|
||||
fld->getSubFieldT<PVDouble>("hello..world");
|
||||
testFail("missing required exception");
|
||||
}catch(std::runtime_error& e){
|
||||
testPass("caught expected exception: %s", e.what());
|
||||
}
|
||||
try{
|
||||
fld->getSubFieldT<PVDouble>(".");
|
||||
testFail("missing required exception");
|
||||
}catch(std::runtime_error& e){
|
||||
testPass("caught expected exception: %s", e.what());
|
||||
}
|
||||
|
||||
// whitespace
|
||||
try{
|
||||
fld->getSubFieldT<PVDouble>(" test");
|
||||
testFail("missing required exception");
|
||||
}catch(std::runtime_error& e){
|
||||
testPass("caught expected exception: %s", e.what());
|
||||
}
|
||||
|
||||
// intermediate field not structure
|
||||
try{
|
||||
fld->getSubFieldT<PVDouble>("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();
|
||||
|
||||
Reference in New Issue
Block a user