diff --git a/src/copy/pv/pvStructureCopy.h b/src/copy/pv/pvStructureCopy.h index 71998ae..9a53213 100644 --- a/src/copy/pv/pvStructureCopy.h +++ b/src/copy/pv/pvStructureCopy.h @@ -204,10 +204,16 @@ private: epics::pvData::PVFieldPtr const &pvCopy, CopyNodePtr const &node, epics::pvData::BitSetPtr const &bitSet); - void updateMaster( - epics::pvData::PVFieldPtr const &pvCopy, - CopyNodePtr const &node, + void updateMasterField( + CopyNodePtr const & node, + epics::pvData::PVFieldPtr const & pvCopy, + epics::pvData::PVFieldPtr const &pvMaster, epics::pvData::BitSetPtr const &bitSet); + void updateMasterCheckBitSet( + epics::pvData::PVStructurePtr const ©PVStructure, + epics::pvData::BitSetPtr const &bitSet, + size_t nextSet); + CopyNodePtr getCopyNode(std::size_t fieldOffset); PVCopy(epics::pvData::PVStructurePtr const &pvMaster); bool init(epics::pvData::PVStructurePtr const &pvRequest); diff --git a/src/copy/pvCopy.cpp b/src/copy/pvCopy.cpp index 31062eb..ae3ff02 100644 --- a/src/copy/pvCopy.cpp +++ b/src/copy/pvCopy.cpp @@ -212,19 +212,91 @@ bool PVCopy::updateCopyFromBitSet( return checkIgnore(copyPVStructure,bitSet); } +void PVCopy::updateMasterField( + CopyNodePtr const & node, + PVFieldPtr const & pvCopy, + PVFieldPtr const &pvMaster, + BitSetPtr const &bitSet) +{ + bool result = false; + for(size_t i=0; i< node->pvFilters.size(); ++i) { + PVFilterPtr pvFilter = node->pvFilters[i]; + if(pvFilter->filter(pvCopy,bitSet,false)) result = true; + } + if(result) return; + pvMaster->copyUnchecked(*pvCopy); +} + +void PVCopy::updateMasterCheckBitSet( + PVStructurePtr const ©PVStructure, + BitSetPtr const &bitSet, + size_t nextSet) +{ + if(!bitSet->get(nextSet)) { + size_t next = bitSet->nextSetBit(nextSet); + if(next==string::npos) return; + updateMasterCheckBitSet(copyPVStructure,bitSet,next); + return; + } + PVFieldPtr pvField = copyPVStructure; + if(nextSet!=0) pvField = copyPVStructure->getSubField(nextSet); + if(pvField->getField()->getType()==epics::pvData::structure) { + bitSet->clear(nextSet); + PVStructurePtr pv = static_pointer_cast(pvField); + PVFieldPtrArray pvFieldArray = pv->getPVFields(); + for(size_t i=0; i>pvFieldArray.size(); ++i) { + PVFieldPtr pvField = pvFieldArray[i]; + bitSet->set(pvField->getFieldOffset()); + } + } + size_t next = bitSet->nextSetBit(nextSet+1); + if(next==string::npos) return; + updateMasterCheckBitSet(copyPVStructure,bitSet,next); +} + +CopyNodePtr PVCopy::getCopyNode(std::size_t fieldOffset) +{ + if(fieldOffset==0) return headNode; + CopyNodePtr node = headNode; + while(true) { + if(!node->isStructure) return node; + CopyStructureNodePtr structNode = static_pointer_cast(node); + CopyNodePtrArrayPtr nodes = structNode->nodes; + bool okToContinue = false; + for(size_t i=0; i< nodes->size(); i++) { + node = (*nodes)[i]; + size_t soff = node->structureOffset; + if(fieldOffset>=soff && fieldOffsetnfields) { + okToContinue = true; + break; + } + } + if(okToContinue) continue; + } + throw std::logic_error("PVCopy::getCopyNode fieldOffset not valid"); +} + + void PVCopy::updateMaster( PVStructurePtr const ©PVStructure, BitSetPtr const &bitSet) { - if(bitSet->get(0)) { - for(size_t i=0; i< copyPVStructure->getNumberFields(); ++i) { - bitSet->set(i,true); + updateMasterCheckBitSet(copyPVStructure,bitSet,0); + size_t nextSet =0; + while(true) { + nextSet = bitSet->nextSetBit(nextSet); + if(nextSet==string::npos) return; + PVFieldPtr pvCopy = copyPVStructure->getSubField(nextSet); + PVFieldPtr pvMaster = headNode->masterPVField; + if(pvMaster->getField()->getType()==epics::pvData::structure) { + PVStructurePtr pv = static_pointer_cast(pvMaster); + pvMaster = pv->getSubField(pvCopy->getFullName()); } + updateMasterField(getCopyNode(nextSet),pvCopy,pvMaster,bitSet); + bitSet->clear(nextSet); } - updateMaster(copyPVStructure,headNode,bitSet); } - - + PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset) { if(fieldOffset==0) return headNode->options; @@ -248,7 +320,7 @@ PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset) } } if(okToContinue) continue; - throw std::logic_error("PVCopy logic error: fieldOffset not valid"); + throw std::logic_error("PVCopy::getOptions logic error: fieldOffset not valid"); } } @@ -349,36 +421,6 @@ void PVCopy::updateCopyFromBitSet( updateCopyFromBitSet(pvCopyFields[i],(*structureNode->nodes)[i],bitSet); } } -void PVCopy::updateMaster( - PVFieldPtr const & pvCopy, - CopyNodePtr const & node, - BitSetPtr const & bitSet) -{ - bool result = false; - bool update = bitSet->get(pvCopy->getFieldOffset()); - if(update) { - for(size_t i=0; i< node->pvFilters.size(); ++i) { - PVFilterPtr pvFilter = node->pvFilters[i]; - if(pvFilter->filter(pvCopy,bitSet,false)) result = true; - } - } - if(!node->isStructure) { - if(result) return; - PVFieldPtr pvMaster = node->masterPVField; - pvMaster->copy(*pvCopy); - return; - } - CopyStructureNodePtr structureNode = static_pointer_cast(node); - size_t offset = structureNode->structureOffset; - size_t nextSet = bitSet->nextSetBit(offset); - if(nextSet==string::npos) return; - if(offset>=pvCopy->getNextFieldOffset()) return; - PVStructurePtr pvCopyStructure = static_pointer_cast(pvCopy); - PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields(); - for(size_t i=0; inodes)[i],bitSet); - } -} PVCopy::PVCopy( PVStructurePtr const &pvMaster) @@ -493,7 +535,7 @@ CopyNodePtr PVCopy::createStructureNodes( requestPVStructure->getSubField("_options"); PVFieldPtr pvMasterField = pvMasterStructure->getSubField(fieldName); if(!pvMasterField) { - throw std::logic_error("PVCopy logic error: did not find field in master"); + throw std::logic_error("PVCopy::createStructureNodes did not find field in master"); } size_t numberRequest = requestPVStructure->getPVFields().size(); bool haveOptions = false;