10 #include <epicsVersion.h> 16 #define epicsExportSharedSymbols 22 static const unsigned maxDepth = 5;
24 namespace epics{
namespace pvData {
39 return typeRequested->build();
46 return typeBase->build();
54 THROW_EXCEPTION2(std::logic_error,
"Mapper must be used with top level PVStructure");
63 PVScalar::const_shared_pointer pbp(pvRequest.
getSubField<
PVScalar>(
"record._options.keepIDs"));
65 if(pbp) keepids = pbp->getAs<
boolean>();
66 }
catch(std::runtime_error& e){
67 std::ostringstream msg;
68 msg<<
"Can't parse keepIDs : '"<<e.what()<<
"' ";
69 temp.messages+=msg.str();
73 if(!fields || fields->getPVFields().empty()) {
75 temp.typeBase = temp.typeRequested = base.
getStructure();
78 temp.maskRequested.
set(
i);
86 ok &= temp._compute(base, *fields, builder, keepids, 0);
89 temp.typeRequested = builder->createStructure();
95 temp.typeRequested = temp.typeBase;
104 temp.req2base.resize(proto->getNextFieldOffset());
107 temp.base2req[0] = Mapping(0,
false);
108 temp.req2base[0] = Mapping(0,
false);
113 for(
size_t r=1, N=proto->getNextFieldOffset(); r<N; r++) {
114 PVField::const_shared_pointer fld_req(proto->getSubFieldT(r)),
116 const size_t b = fld_base->getFieldOffset();
121 bool leaf = fld_base->getField()->getType()!=
structure;
124 temp.base2req[b] = Mapping(r, leaf);
125 temp.req2base[r] = Mapping(b, leaf);
129 temp.req2base[parent->getFieldOffset()].tomask .set(b);
130 temp.req2base[parent->getFieldOffset()].frommask.set(r);
134 temp.base2req[parent->getFieldOffset()].tomask .set(r);
135 temp.base2req[parent->getFieldOffset()].frommask.set(b);
140 temp.maskRequested.
set(0);
144 temp.messages+=
"Empty field selection";
148 throw std::runtime_error(temp.messages);
159 for(
size_t i=0, N=reqNames.size();
i<N;
i++) {
162 PVField::const_shared_pointer subtype(base.
getSubField(reqNames[
i]));
167 std::ostringstream msg;
171 msg<<
"request invalid '"<<pvReq.
getStructure()->getFieldNames()[
i]<<
"' ";
175 }
else if(!subtype) {
177 std::ostringstream msg;
178 msg<<
"No field '"<<pvReq.
getStructure()->getFieldNames()[
i]<<
"' ";
181 }
else if(depth>=maxDepth
182 || subtype->getField()->getType()!=
structure 187 builder = builder->add(reqNames[i], subtype->getField());
188 for(
size_t j=subtype->getFieldOffset(), N=subtype->getNextFieldOffset(); j<N; j++)
189 maskRequested.
set(j);
191 if(subtype->getField()->getType()!=
structure 195 std::ostringstream msg;
198 }
else if(depth>=maxDepth) {
199 std::ostringstream msg;
200 msg<<
"selection truncated at '"<<pvReq.
getFullName()<<
"' ";
208 builder = builder->addNestedStructure(reqNames[i]);
212 builder = builder->setId(substruct.
getStructure()->getID());
215 static_cast<const PVStructure&>(*pvReq.
getPVFields()[
i]),
216 builder, keepids, depth+1u);
218 builder = builder->endNested();
232 _map(base, baseMask, request, requestMask,
false);
243 _map(request, requestMask, base, baseMask,
true);
252 const mapping_t& map = dir_r2b ? req2base : base2req;
257 const Mapping& M = map[
i];
269 scratch |= M.frommask;
279 void PVRequestMapper::_mapMask(
const BitSet& maskSrc,
287 const mapping_t& map = dir_r2b ? req2base : base2req;
290 const Mapping& M = map[
i];
298 maskDest |= M.tomask;
308 typeBase.swap(other.typeBase);
309 typeRequested.swap(other.typeRequested);
310 maskRequested.
swap(other.maskRequested);
311 base2req.swap(other.base2req);
312 req2base.swap(other.req2base);
313 messages.swap(other.messages);
314 scratch.
swap(other.scratch);
320 typeRequested.reset();
321 maskRequested.
clear();
FORCE_INLINE std::tr1::shared_ptr< PVField > getSubField(A a)
const PVFieldPtrArray & getPVFields() const
void copyBaseToRequested(const PVStructure &base, const BitSet &baseMask, PVStructure &request, BitSet &requestMask) const
PVScalar is the base class for each scalar field.
#define assert(exp)
Declare that a condition should be true.
BitSet & clear(uint32 bitIndex)
const BitSet & requestedMask() const
bool get(uint32 bitIndex) const
#define THROW_EXCEPTION2(TYPE, MSG)
An EPICS-specific replacement for ANSI C's assert.
void compute(const PVStructure &base, const PVStructure &pvRequest, mode_t mode=Mask)
PVStructurePtr buildRequested() const
TODO only here because of the Lockable.
void swap(PVRequestMapper &other)
Exchange contents of two mappers. O(0) and never throws.
std::tr1::shared_ptr< FieldBuilder > FieldBuilderPtr
std::size_t getFieldOffset() const
std::string getFullName() const
This class implements introspection object for a structure.
const StructureConstPtr & base() const
APIs for the epicsMutex mutual exclusion semaphore.
int32 nextSetBit(uint32 fromIndex) const
Data interface for a structure,.
std::tr1::shared_ptr< const Field > FieldConstPtr
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
std::tr1::shared_ptr< PVStructure > PVStructurePtr
FORCE_INLINE std::tr1::shared_ptr< PVField > getSubFieldT(A a)
std::vector< std::string > StringArray
void swap(BitSet &set)
Swap contents.
PVStructurePtr buildBase() const
const StructureConstPtr & getStructure() const
BitSet & set(uint32 bitIndex)
PVStructure * getParent()
void copyBaseFromRequested(PVStructure &base, BitSet &baseMask, const PVStructure &request, const BitSet &requestMask) const
std::size_t getNextFieldOffset() const
StringArray const & getFieldNames() const
void reset()
return to state of default ctor
std::size_t getNumberFields() const