Validator: add simple Result caching
This commit is contained in:

committed by
mdavidsaver

parent
e0d422ffd9
commit
31050952b6
@ -193,15 +193,20 @@ bool NTAggregate::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTAggregate::isCompatible(StructureConstPtr const &structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<Scalar>("value")
|
||||
.has<Scalar>("N")
|
||||
|
@ -130,14 +130,20 @@ bool NTAttribute::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTAttribute::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<Scalar>("name")
|
||||
.has<Union>("value")
|
||||
|
@ -122,14 +122,20 @@ bool NTContinuum::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTContinuum::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<ScalarArray>("base")
|
||||
.has<ScalarArray>("value")
|
||||
|
@ -121,14 +121,20 @@ bool NTEnum::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTEnum::isCompatible(StructureConstPtr const &structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<&NTField::isEnumerated, Structure>("value")
|
||||
.maybeHas<Scalar>("descriptor")
|
||||
|
@ -39,12 +39,6 @@ Result& NTField::isEnumerated(Result& result)
|
||||
.has<ScalarArray>("choices");
|
||||
}
|
||||
|
||||
bool NTField::isEnumerated(FieldConstPtr const & field)
|
||||
{
|
||||
Result result(field);
|
||||
return isEnumerated(result.is<Structure>()).valid();
|
||||
}
|
||||
|
||||
Result& NTField::isTimeStamp(Result& result)
|
||||
{
|
||||
return result
|
||||
@ -53,12 +47,6 @@ Result& NTField::isTimeStamp(Result& result)
|
||||
.has<Scalar>("userTag");
|
||||
}
|
||||
|
||||
bool NTField::isTimeStamp(FieldConstPtr const & field)
|
||||
{
|
||||
Result result(field);
|
||||
return isTimeStamp(result.is<Structure>()).valid();
|
||||
}
|
||||
|
||||
Result& NTField::isAlarm(Result& result)
|
||||
{
|
||||
return result
|
||||
@ -67,12 +55,6 @@ Result& NTField::isAlarm(Result& result)
|
||||
.has<Scalar>("message");
|
||||
}
|
||||
|
||||
bool NTField::isAlarm(FieldConstPtr const & field)
|
||||
{
|
||||
Result result(field);
|
||||
return isAlarm(result.is<Structure>()).valid();
|
||||
}
|
||||
|
||||
Result& NTField::isDisplay(Result& result)
|
||||
{
|
||||
return result
|
||||
@ -81,13 +63,6 @@ Result& NTField::isDisplay(Result& result)
|
||||
.has<Scalar>("description")
|
||||
.has<Scalar>("format")
|
||||
.has<Scalar>("units");
|
||||
|
||||
}
|
||||
|
||||
bool NTField::isDisplay(FieldConstPtr const & field)
|
||||
{
|
||||
Result result(field);
|
||||
return isDisplay(result.is<Structure>()).valid();
|
||||
}
|
||||
|
||||
Result& NTField::isAlarmLimit(Result& result)
|
||||
@ -105,12 +80,6 @@ Result& NTField::isAlarmLimit(Result& result)
|
||||
.has<Scalar>("hysteresis");
|
||||
}
|
||||
|
||||
bool NTField::isAlarmLimit(FieldConstPtr const & field)
|
||||
{
|
||||
Result result(field);
|
||||
return isAlarmLimit(result.is<Structure>()).valid();
|
||||
}
|
||||
|
||||
Result& NTField::isControl(Result& result)
|
||||
{
|
||||
return result
|
||||
@ -119,11 +88,24 @@ Result& NTField::isControl(Result& result)
|
||||
.has<Scalar>("minStep");
|
||||
}
|
||||
|
||||
bool NTField::isControl(FieldConstPtr const & field)
|
||||
{
|
||||
Result result(field);
|
||||
return isControl(result.is<Structure>()).valid();
|
||||
}
|
||||
#define IS_NTFIELD_FUNC(name) \
|
||||
static epicsThreadOnceId cached##name##OnceId = EPICS_THREAD_ONCE_INIT; \
|
||||
static epicsThreadPrivateId cached##name##Id; \
|
||||
bool NTField::is##name(FieldConstPtr const & field) { \
|
||||
Result& result = Result::fromCache(&cached##name##OnceId, \
|
||||
&cached##name##Id); \
|
||||
if (result.wraps(field)) return result.valid(); \
|
||||
return is##name(result.reset(field).is<Structure>()).valid(); \
|
||||
}
|
||||
|
||||
IS_NTFIELD_FUNC(Enumerated)
|
||||
IS_NTFIELD_FUNC(TimeStamp)
|
||||
IS_NTFIELD_FUNC(Alarm)
|
||||
IS_NTFIELD_FUNC(Display)
|
||||
IS_NTFIELD_FUNC(AlarmLimit)
|
||||
IS_NTFIELD_FUNC(Control)
|
||||
|
||||
#undef IS_NTFIELD_FUNC
|
||||
|
||||
StructureConstPtr NTField::createEnumerated()
|
||||
{
|
||||
|
@ -135,14 +135,20 @@ bool NTHistogram::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTHistogram::isCompatible(StructureConstPtr const &structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<ScalarArray>("ranges")
|
||||
.has<ScalarArray>("value")
|
||||
|
@ -139,14 +139,20 @@ bool NTMatrix::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTMatrix::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<ScalarArray>("value")
|
||||
.maybeHas<ScalarArray>("dim")
|
||||
|
@ -232,14 +232,20 @@ bool NTMultiChannel::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTMultiChannel::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<UnionArray>("value")
|
||||
.has<ScalarArray>("channelName")
|
||||
|
@ -134,14 +134,20 @@ bool NTNameValue::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTNameValue::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<ScalarArray>("name")
|
||||
.has<ScalarArray>("value")
|
||||
|
@ -252,14 +252,20 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTNDArray::isCompatible(StructureConstPtr const &structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<&isValue>("value")
|
||||
.has<&isCodec>("codec")
|
||||
@ -276,7 +282,6 @@ bool NTNDArray::isCompatible(StructureConstPtr const &structure)
|
||||
.valid();
|
||||
}
|
||||
|
||||
|
||||
bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure)
|
||||
{
|
||||
if(!pvStructure.get()) return false;
|
||||
|
@ -146,13 +146,20 @@ Result& NTNDArrayAttribute::isAttribute(Result& result) {
|
||||
.has<Scalar>("source");
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTNDArrayAttribute::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
return isAttribute(result.is<Structure>()).valid();
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return isAttribute(result.reset(structure).is<Structure>()).valid();
|
||||
}
|
||||
|
||||
bool NTNDArrayAttribute::isCompatible(PVStructurePtr const & pvStructure)
|
||||
|
@ -152,14 +152,20 @@ bool NTScalar::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTScalar::isCompatible(StructureConstPtr const &structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<Scalar>("value")
|
||||
.maybeHas<Scalar>("descriptor")
|
||||
|
@ -161,14 +161,20 @@ bool NTScalarArray::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTScalarArray::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<ScalarArray>("value")
|
||||
.maybeHas<Scalar>("descriptor")
|
||||
|
@ -227,14 +227,20 @@ bool NTScalarMultiChannel::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTScalarMultiChannel::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<ScalarArray>("value")
|
||||
.has<ScalarArray>("channelName")
|
||||
|
@ -148,14 +148,20 @@ bool NTTable::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTTable::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<Structure>("value")
|
||||
.has<ScalarArray>("labels")
|
||||
|
@ -128,14 +128,20 @@ bool NTUnion::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTUnion::isCompatible(StructureConstPtr const &structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
return result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
return result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<Union>("value")
|
||||
.maybeHas<Scalar>("descriptor")
|
||||
|
@ -148,14 +148,20 @@ bool NTURI::is_a(PVStructurePtr const & pvStructure)
|
||||
return is_a(pvStructure->getStructure());
|
||||
}
|
||||
|
||||
static epicsThreadOnceId cachedResultOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadPrivateId cachedResultId;
|
||||
|
||||
bool NTURI::isCompatible(StructureConstPtr const & structure)
|
||||
{
|
||||
if (!structure)
|
||||
return false;
|
||||
|
||||
Result result(structure);
|
||||
Result& result = Result::fromCache(&cachedResultOnceId, &cachedResultId);
|
||||
|
||||
result
|
||||
if (result.wraps(structure))
|
||||
return result.valid();
|
||||
|
||||
result.reset(structure)
|
||||
.is<Structure>()
|
||||
.has<Scalar>("scheme")
|
||||
.has<Scalar>("path")
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
|
||||
namespace epics { namespace nt {
|
||||
@ -48,8 +50,8 @@ struct Result {
|
||||
}
|
||||
};
|
||||
|
||||
const epics::pvData::FieldConstPtr f;
|
||||
const std::string path;
|
||||
epics::pvData::FieldConstPtr field;
|
||||
std::string path;
|
||||
std::vector<Error> errors;
|
||||
|
||||
enum result_t {
|
||||
@ -57,8 +59,10 @@ struct Result {
|
||||
Fail,
|
||||
} result;
|
||||
|
||||
explicit Result(const epics::pvData::FieldConstPtr& f, const std::string& path = std::string())
|
||||
: f(f), path(path), errors(), result(Pass) {}
|
||||
Result(const epics::pvData::FieldConstPtr& field, const std::string& path = std::string())
|
||||
: field(field), path(path), errors(), result(Pass) {}
|
||||
|
||||
Result() {}
|
||||
|
||||
Result& operator|=(const Result& other) {
|
||||
result = std::max(result, other.result);
|
||||
@ -66,12 +70,56 @@ struct Result {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the contents of this Result.
|
||||
*
|
||||
* @return a reference to itself.
|
||||
*/
|
||||
Result& reset(const epics::pvData::FieldConstPtr& newField) {
|
||||
field = newField;
|
||||
path.clear();
|
||||
errors.clear();
|
||||
result = Pass;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a Result from a thread-local cache. Allocates a new Result
|
||||
* if it wasn't allocated yet.
|
||||
*
|
||||
* @return a reference to the stored Result.
|
||||
*
|
||||
*/
|
||||
static Result& fromCache(epicsThreadOnceId *onceId, epicsThreadPrivateId *cachedId) {
|
||||
epicsThreadOnce(onceId, &once, static_cast<void*>(cachedId));
|
||||
|
||||
Result *result = static_cast<Result*>(epicsThreadPrivateGet(*cachedId));
|
||||
|
||||
if (!result) {
|
||||
result = new Result;
|
||||
epicsThreadPrivateSet(*cachedId, result);
|
||||
}
|
||||
|
||||
return *result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this Result already wraps a particular Field.
|
||||
* Note: this is done via pointer equality, which pvData guarantees
|
||||
* will work if the pointed-to Fields are the same.
|
||||
*
|
||||
* @return true if it does wrap the passed-in field, false otherwise.
|
||||
*/
|
||||
inline bool wraps(epics::pvData::FieldConstPtr const & other) const {
|
||||
return field && field == other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this Result is valid.
|
||||
*
|
||||
* @return true if all tests passed, false otherwise.
|
||||
*/
|
||||
bool valid(void) const {
|
||||
inline bool valid(void) const {
|
||||
return result == Pass;
|
||||
}
|
||||
|
||||
@ -84,7 +132,7 @@ struct Result {
|
||||
*/
|
||||
template<typename T>
|
||||
Result& is(void) {
|
||||
if (!dynamic_cast<T const *>(f.get())) {
|
||||
if (!dynamic_cast<T const *>(field.get())) {
|
||||
result = Fail;
|
||||
errors.push_back(Error(path, Error::IncorrectType));
|
||||
}
|
||||
@ -103,7 +151,7 @@ struct Result {
|
||||
*/
|
||||
template<typename T>
|
||||
Result& is(const std::string& id) {
|
||||
T const *s = dynamic_cast<T const *>(f.get());
|
||||
T const *s = dynamic_cast<T const *>(field.get());
|
||||
if (!s) {
|
||||
result = Fail;
|
||||
errors.push_back(Error(path, Error::IncorrectType));
|
||||
@ -199,20 +247,20 @@ struct Result {
|
||||
private:
|
||||
template<typename T>
|
||||
Result& has(const std::string& name, bool optional, Result& (*check)(Result&) = NULL) {
|
||||
epics::pvData::FieldConstPtr field;
|
||||
epics::pvData::FieldConstPtr subField;
|
||||
|
||||
switch(f->getType()) {
|
||||
switch(field->getType()) {
|
||||
case epics::pvData::Type::structure:
|
||||
field = static_cast<epics::pvData::Structure const *>(f.get())->getField(name);
|
||||
subField = static_cast<epics::pvData::Structure const *>(field.get())->getField(name);
|
||||
break;
|
||||
case epics::pvData::Type::structureArray:
|
||||
field = static_cast<epics::pvData::StructureArray const *>(f.get())->getStructure()->getField(name);
|
||||
subField = static_cast<epics::pvData::StructureArray const *>(field.get())->getStructure()->getField(name);
|
||||
break;
|
||||
case epics::pvData::Type::union_:
|
||||
field = static_cast<epics::pvData::Union const *>(f.get())->getField(name);
|
||||
subField = static_cast<epics::pvData::Union const *>(field.get())->getField(name);
|
||||
break;
|
||||
case epics::pvData::Type::unionArray:
|
||||
field = static_cast<epics::pvData::UnionArray const *>(f.get())->getUnion()->getField(name);
|
||||
subField = static_cast<epics::pvData::UnionArray const *>(field.get())->getUnion()->getField(name);
|
||||
break;
|
||||
default:
|
||||
// Expected a structure-like Field
|
||||
@ -221,23 +269,28 @@ private:
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string fieldPath(path.empty() ? name : path + "." + name);
|
||||
std::string subFieldPath(path.empty() ? name : path + "." + name);
|
||||
|
||||
if (!field) {
|
||||
if (!subField) {
|
||||
if (!optional) {
|
||||
result = Fail;
|
||||
errors.push_back(Error(fieldPath, Error::Type::MissingField));
|
||||
errors.push_back(Error(subFieldPath, Error::Type::MissingField));
|
||||
}
|
||||
} else if (!dynamic_cast<T const *>(field.get())) {
|
||||
} else if (!dynamic_cast<T const *>(subField.get())) {
|
||||
result = Fail;
|
||||
errors.push_back(Error(fieldPath, Error::Type::IncorrectType));
|
||||
errors.push_back(Error(subFieldPath, Error::Type::IncorrectType));
|
||||
} else if (check) {
|
||||
Result r(field, fieldPath);
|
||||
Result r(subField, subFieldPath);
|
||||
*this |= check(r);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
static void once(void *arg) {
|
||||
epicsThreadPrivateId *id = static_cast<epicsThreadPrivateId *>(arg);
|
||||
*id = epicsThreadPrivateCreate();
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
|
Reference in New Issue
Block a user