From 31412aff2ea371ffa1b7877e2b4a94a664cc99c6 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 29 Jan 2020 13:41:45 -0800 Subject: [PATCH] add request2mask() --- src/Makefile | 1 + src/pvrequest.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++ src/pvrequest.h | 21 +++++++++++++ test/testdata.cpp | 52 +++++++++++++++++++++++++++++++- 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/pvrequest.cpp create mode 100644 src/pvrequest.h diff --git a/src/Makefile b/src/Makefile index 29669a5..c89340e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -57,6 +57,7 @@ LIB_SRCS += util.cpp LIB_SRCS += bitmask.cpp LIB_SRCS += type.cpp LIB_SRCS += data.cpp +LIB_SRCS += pvrequest.cpp LIB_SRCS += dataencode.cpp LIB_SRCS += nt.cpp LIB_SRCS += evhelper.cpp diff --git a/src/pvrequest.cpp b/src/pvrequest.cpp new file mode 100644 index 0000000..6cc4b59 --- /dev/null +++ b/src/pvrequest.cpp @@ -0,0 +1,75 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * pvxs is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ + +#include "pvrequest.h" +#include "dataimpl.h" + +namespace pvxs { +namespace impl { + +BitMask request2mask(const FieldDesc* desc, const Value& pvRequest) +{ + auto fields = pvRequest["field"]; + // pre-select top wildcard bit, which will always be permitted + BitMask ret({0u}, desc->size()); + // have we found at least one requested field? + bool foundrequested = false; + + if(fields.type()==TypeCode::Struct) { + auto rdesc = Value::Helper::desc(fields); + + if(rdesc->mlookup.empty()) + foundrequested = true; // empty is wildcard + + // iterate pvRequest fields + for(auto& pair : rdesc->mlookup) { + auto crdesc = rdesc + pair.second; + + if(crdesc->code==TypeCode::Struct) { + // attempt to match up with actual structure + auto it = desc->mlookup.find(pair.first); + if(it!=desc->mlookup.end()) { + // match found + auto cdesc = desc + it->second; + + ret[it->second] = true; + foundrequested = true; + + if(crdesc->mlookup.empty() && cdesc->code==TypeCode::Struct) { + // implicit select of all fields sub-struct + + for(auto& pair2 : cdesc->mlookup) + ret[it->second + pair2.second] = true; + } + + } else { + // request of non-existant field + } + } + } + + } else if(!fields.valid()) { + foundrequested = true; + + } else { + // .fields isn't a sub-struct + } + + if(!foundrequested) + throw std::runtime_error("pvRequest selects no fields"); + + if(ret.findSet(1)==ret.size()) { + // empty mask is wildcard + for(auto bit : range(desc->size())) + ret[bit] = true; + + } + + return ret; +} + + +}} // namespace pvxs::impl diff --git a/src/pvrequest.h b/src/pvrequest.h new file mode 100644 index 0000000..6e4215a --- /dev/null +++ b/src/pvrequest.h @@ -0,0 +1,21 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * pvxs is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +#ifndef PVREQUEST_H +#define PVREQUEST_H + +#include "utilpvt.h" +#include +#include + +namespace pvxs { +namespace impl { + +PVXS_API +BitMask request2mask(const FieldDesc* desc, const Value& pvRequest); + +}} // namespace pvxs::impl + +#endif // PVREQUEST_H diff --git a/test/testdata.cpp b/test/testdata.cpp index 9cf743d..f842b13 100644 --- a/test/testdata.cpp +++ b/test/testdata.cpp @@ -14,6 +14,7 @@ #include "utilpvt.h" #include "pvaproto.h" #include "dataimpl.h" +#include "pvrequest.h" using namespace pvxs; namespace { @@ -509,11 +510,59 @@ void testIter() testMarked(6u)<<"mark sub-struct"; } +void testPvRequest() +{ + namespace M = members; + + testDiag("%s", __func__); + + auto def = nt::NTScalar{TypeCode::String}.build(); + auto val = def.create(); + testShow()<