This is Unofficial EPICS BASE Doxygen Site
pvCopy.cpp
Go to the documentation of this file.
1 /* pvCopy.cpp */
2 /*
3  * License terms for this software can be found in the file LICENSE that is included with the distribution
4  */
9 #include <string>
10 #include <stdexcept>
11 #include <memory>
12 #include <sstream>
13 
14 #include <epicsThread.h>
15 #include <pv/pvData.h>
16 #include <pv/bitSet.h>
17 #include <pv/thread.h>
18 
19 #define epicsExportSharedSymbols
20 #include "pv/pvPlugin.h"
21 #include "pv/pvStructureCopy.h"
22 
25 using std::string;
26 using std::size_t;
27 using std::cout;
28 using std::endl;
29 using std::vector;
30 using namespace epics::pvData;
31 
32 namespace epics { namespace pvCopy {
33 
40 static void newLine(string *buffer, int indentLevel)
41 {
42  *buffer += "\n";
43  *buffer += string(indentLevel*4, ' ');
44 }
45 
46 static PVCopyPtr NULLPVCopy;
47 static StructureConstPtr NULLStructure;
48 static PVStructurePtr NULLPVStructure;
49 
50 struct CopyNode {
52  : isStructure(false),
53  structureOffset(0),
54  nfields(0)
55  {}
58  size_t structureOffset; // In the copy
59  size_t nfields;
61  vector<PVFilterPtr> pvFilters;
62 };
63 
64 static CopyNodePtr NULLCopyNode;
65 
66 typedef std::vector<CopyNodePtr> CopyNodePtrArray;
67 typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
68 
69 struct CopyStructureNode : public CopyNode {
70  CopyNodePtrArrayPtr nodes;
71 };
72 
73 PVCopyPtr PVCopy::create(
74  PVStructurePtr const &pvMaster,
75  PVStructurePtr const &pvRequest,
76  string const & structureName)
77 {
78  PVStructurePtr pvStructure(pvRequest);
79  if(structureName.size()>0) {
80  if(pvStructure->getStructure()->getNumberFields()>0) {
81  pvStructure = pvRequest->getSubField<PVStructure>(structureName);
82  if(!pvStructure) return NULLPVCopy;
83  }
84  } else if(pvRequest->getSubField<PVStructure>("field")) {
85  pvStructure = pvRequest->getSubField<PVStructure>("field");
86  }
87  PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
88  bool result = pvCopy->init(pvStructure);
89  if(!result) return PVCopyPtr();
90  pvCopy->traverseMasterInitPlugin();
91 //cout << pvCopy->dump() << endl;
92  return pvCopy;
93 }
94 
95 PVStructurePtr PVCopy::getPVMaster()
96 {
97  return pvMaster;
98 }
99 
100 void PVCopy::traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback)
101 {
102  traverseMaster(headNode,callback);
103 }
104 
105 StructureConstPtr PVCopy::getStructure()
106 {
107  return structure;
108 }
109 
110 PVStructurePtr PVCopy::createPVStructure()
111 {
112  if(cacheInitStructure) {
113  PVStructurePtr save = cacheInitStructure;
114  cacheInitStructure.reset();
115  return save;
116  }
117  PVStructurePtr pvStructure =
118  getPVDataCreate()->createPVStructure(structure);
119  return pvStructure;
120 }
121 
122 
123 size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
124 {
125  if(!headNode->isStructure) {
126  CopyNodePtr node = static_pointer_cast<CopyNode>(headNode);
127  if((node->masterPVField.get())==masterPVField.get()) {
128  return headNode->structureOffset;
129  }
130  PVStructure * parent = masterPVField->getParent();
131  size_t offsetParent = parent->getFieldOffset();
132  size_t off = masterPVField->getFieldOffset();
133  size_t offdiff = off -offsetParent;
134  if(offdiff<node->nfields) return headNode->structureOffset + offdiff;
135  return string::npos;
136  }
138  CopyNodePtr node = getCopyOffset(structNode,masterPVField);
139  if(node) return node->structureOffset;
140  return string::npos;
141 }
142 
143 size_t PVCopy::getCopyOffset(
144  PVStructurePtr const &masterPVStructure,
145  PVFieldPtr const &masterPVField)
146 {
147  CopyNodePtr node;
148  if(!headNode->isStructure) {
149  node = static_pointer_cast<CopyNode>(headNode);
150  if(node->masterPVField.get()!=masterPVStructure.get()) return string::npos;
151  } else {
153  node = getCopyOffset(snode,masterPVField);
154  }
155  if(!node) return string::npos;
156  size_t diff = masterPVField->getFieldOffset()
157  - masterPVStructure->getFieldOffset();
158  return node->structureOffset + diff;
159 }
160 
161 PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
162 {
163  CopyNodePtr node;
164  if(!headNode->isStructure) {
165  node = headNode;
166  } else {
168  node = getMasterNode(snode,structureOffset);
169  }
170  if(!node) {
171  throw std::logic_error(
172  "PVCopy::getMasterPVField: structureOffset not valid");
173  }
174  size_t diff = structureOffset - node->structureOffset;
175  PVFieldPtr pvMasterField = node->masterPVField;
176  if(diff==0) return pvMasterField;
177  PVStructurePtr pvStructure
178  = static_pointer_cast<PVStructure>(pvMasterField);
179  return pvStructure->getSubField(
180  pvMasterField->getFieldOffset() + diff);
181 }
182 
183 void PVCopy::initCopy(
184  PVStructurePtr const &copyPVStructure,
185  BitSetPtr const &bitSet)
186 {
187  for(size_t i=0; i< copyPVStructure->getNumberFields(); ++i) {
188  bitSet->set(i,true);
189  }
190  updateCopyFromBitSet(copyPVStructure,headNode,bitSet);
191 }
192 
193 
194 bool PVCopy::updateCopySetBitSet(
195  PVStructurePtr const &copyPVStructure,
196  BitSetPtr const &bitSet)
197 {
198  updateCopySetBitSet(copyPVStructure,headNode,bitSet);
199  return checkIgnore(copyPVStructure,bitSet);
200 }
201 
202 bool PVCopy::updateCopyFromBitSet(
203  PVStructurePtr const &copyPVStructure,
204  BitSetPtr const &bitSet)
205 {
206  if(bitSet->get(0)) {
207  for(size_t i=0; i< copyPVStructure->getNumberFields(); ++i) {
208  bitSet->set(i,true);
209  }
210  }
211  updateCopyFromBitSet(copyPVStructure,headNode,bitSet);
212  return checkIgnore(copyPVStructure,bitSet);
213 }
214 
215 void PVCopy::updateMasterField(
216  CopyNodePtr const & node,
217  PVFieldPtr const & pvCopy,
218  PVFieldPtr const &pvMaster,
219  BitSetPtr const &bitSet)
220 {
221  bool result = false;
222  for(size_t i=0; i< node->pvFilters.size(); ++i) {
223  PVFilterPtr pvFilter = node->pvFilters[i];
224  if(pvFilter->filter(pvCopy,bitSet,false)) result = true;
225  }
226  if(result) return;
227  pvMaster->copyUnchecked(*pvCopy);
228 }
229 
230 void PVCopy::updateMasterCheckBitSet(
231  PVStructurePtr const &copyPVStructure,
232  BitSetPtr const &bitSet,
233  size_t nextSet)
234 {
235  if(!bitSet->get(nextSet)) {
236  size_t next = bitSet->nextSetBit(nextSet);
237  if(next==string::npos) return;
238  updateMasterCheckBitSet(copyPVStructure,bitSet,next);
239  return;
240  }
241  PVFieldPtr pvField = copyPVStructure;
242  if(nextSet!=0) pvField = copyPVStructure->getSubField(nextSet);
243  if(pvField->getField()->getType()==epics::pvData::structure) {
244  bitSet->clear(nextSet);
246  PVFieldPtrArray pvFieldArray = pv->getPVFields();
247  for(size_t i=0; i<pvFieldArray.size(); ++i) {
248  PVFieldPtr pvField = pvFieldArray[i];
249  bitSet->set(pvField->getFieldOffset());
250  }
251  }
252  size_t next = bitSet->nextSetBit(nextSet+1);
253  if(next==string::npos) return;
254  updateMasterCheckBitSet(copyPVStructure,bitSet,next);
255 }
256 
257 CopyNodePtr PVCopy::getCopyNode(std::size_t fieldOffset)
258 {
259  if(fieldOffset==0) return headNode;
260  CopyNodePtr node = headNode;
261  while(true) {
262  if(!node->isStructure) return node;
264  CopyNodePtrArrayPtr nodes = structNode->nodes;
265  bool okToContinue = false;
266  for(size_t i=0; i< nodes->size(); i++) {
267  node = (*nodes)[i];
268  size_t soff = node->structureOffset;
269  if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
270  okToContinue = true;
271  break;
272  }
273  }
274  if(okToContinue) continue;
275  }
276  throw std::logic_error("PVCopy::getCopyNode fieldOffset not valid");
277 }
278 
279 
280 void PVCopy::updateMaster(
281  PVStructurePtr const &copyPVStructure,
282  BitSetPtr const &bitSet)
283 {
284  updateMasterCheckBitSet(copyPVStructure,bitSet,0);
285  size_t nextSet =0;
286  while(true) {
287  nextSet = bitSet->nextSetBit(nextSet);
288  if(nextSet==string::npos) return;
289  PVFieldPtr pvCopy = copyPVStructure->getSubField(nextSet);
290  PVFieldPtr pvMaster = headNode->masterPVField;
291  if(pvMaster->getField()->getType()==epics::pvData::structure) {
293  pvMaster = pv->getSubField(pvCopy->getFullName());
294  }
295  updateMasterField(getCopyNode(nextSet),pvCopy,pvMaster,bitSet);
296  bitSet->clear(nextSet);
297  }
298 }
299 
300 PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
301 {
302  if(fieldOffset==0) return headNode->options;
303  CopyNodePtr node = headNode;
304  while(true) {
305  if(node->structureOffset==fieldOffset) return node->options;
306  if(!node->isStructure) return NULLPVStructure;
308  CopyNodePtrArrayPtr nodes = structNode->nodes;
309  bool okToContinue = false;
310  for(size_t i=0; i< nodes->size(); i++) {
311  node = (*nodes)[i];
312  size_t soff = node->structureOffset;
313  if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
314  if(fieldOffset==soff) return node->options;
315  if(!node->isStructure) {
316  return NULLPVStructure;
317  }
318  okToContinue = true;
319  break;
320  }
321  }
322  if(okToContinue) continue;
323  throw std::logic_error("PVCopy::getOptions logic error: fieldOffset not valid");
324  }
325 }
326 
327 string PVCopy::dump()
328 {
329  string builder;
330  dump(&builder,headNode,0);
331  return builder;
332 }
333 
334 void PVCopy::traverseMaster(
335  CopyNodePtr const &innode,
337 {
338  CopyNodePtr node = innode;
339  if(!node->isStructure) {
340  callback->nextMasterPVField(node->masterPVField);
341  return;
342  }
344  CopyNodePtrArrayPtr nodes = structNode->nodes;
345  for(size_t i=0; i< nodes->size(); i++) {
346  node = (*nodes)[i];
347  traverseMaster(node,callback);
348  }
349 }
350 
351 void PVCopy::updateCopySetBitSet(
352  PVFieldPtr const & pvCopy,
353  PVFieldPtr const & pvMaster,
354  BitSetPtr const & bitSet)
355 {
356  if(pvCopy->getField()->getType()!=epics::pvData::structure) {
357  if(*pvCopy==*pvMaster) return;
358  pvCopy->copy(*pvMaster);
359  bitSet->set(pvCopy->getFieldOffset());
360  return;
361  }
362  PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
363  PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
364  for(size_t i=0; i<pvCopyFields.size(); ++i) {
365  PVFieldPtr master = getMasterPVField(pvCopyFields[i]->getFieldOffset());
366  updateCopySetBitSet(pvCopyFields[i],master,bitSet);
367  }
368 }
369 
370 void PVCopy::updateCopySetBitSet(
371  PVFieldPtr const & pvCopy,
372  CopyNodePtr const & node,
373  BitSetPtr const & bitSet)
374 {
375  bool result = false;
376  for(size_t i=0; i< node->pvFilters.size(); ++i) {
377  PVFilterPtr pvFilter = node->pvFilters[i];
378  if(pvFilter->filter(pvCopy,bitSet,true)) result = true;
379  }
380  if(!node->isStructure) {
381  if(result) return;
382  updateCopySetBitSet(pvCopy,node->masterPVField,bitSet);
383  return;
384  }
386  PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
387  PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
388  for(size_t i=0; i<pvCopyFields.size(); ++i) {
389  updateCopySetBitSet(pvCopyFields[i],(*structureNode->nodes)[i],bitSet);
390  }
391 }
392 
393 
394 void PVCopy::updateCopyFromBitSet(
395  PVFieldPtr const & pvCopy,
396  CopyNodePtr const & node,
397  BitSetPtr const & bitSet)
398 {
399  bool result = false;
400  bool update = bitSet->get(pvCopy->getFieldOffset());
401  if(update) {
402  for(size_t i=0; i< node->pvFilters.size(); ++i) {
403  PVFilterPtr pvFilter = node->pvFilters[i];
404  if(pvFilter->filter(pvCopy,bitSet,true)) result = true;
405  }
406  }
407  if(!node->isStructure) {
408  if(result) return;
409  PVFieldPtr pvMaster = node->masterPVField;
410  pvCopy->copy(*pvMaster);
411  return;
412  }
414  size_t offset = structureNode->structureOffset;
415  size_t nextSet = bitSet->nextSetBit(offset);
416  if(nextSet==string::npos) return;
417  if(offset>=pvCopy->getNextFieldOffset()) return;
418  PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
419  PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
420  for(size_t i=0; i<pvCopyFields.size(); ++i) {
421  updateCopyFromBitSet(pvCopyFields[i],(*structureNode->nodes)[i],bitSet);
422  }
423 }
424 
425 PVCopy::PVCopy(
426  PVStructurePtr const &pvMaster)
427 : pvMaster(pvMaster)
428 {
429 }
430 
431 void PVCopy::destroy()
432 {
433  headNode.reset();
434 }
435 
436 bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
437 {
438  PVStructurePtr pvMasterStructure = pvMaster;
439  size_t len = pvRequest->getPVFields().size();
440  bool entireMaster = false;
441  if(len==0) entireMaster = true;
442  PVStructurePtr pvOptions;
443  if(len==1) {
444  pvOptions = pvRequest->getSubField<PVStructure>("_options");
445  }
446  if(entireMaster) {
447  structure = pvMasterStructure->getStructure();
448  CopyNodePtr node(new CopyNode());
449  headNode = node;
450  node->options = pvOptions;
451  node->isStructure = false;
452  node->structureOffset = 0;
453  node->masterPVField = pvMasterStructure;
454  node->nfields = pvMasterStructure->getNumberFields();
455  return true;
456  }
457  structure = createStructure(pvMasterStructure,pvRequest);
458  if(!structure) return false;
459  cacheInitStructure = createPVStructure();
460  ignorechangeBitSet = BitSetPtr(new BitSet(cacheInitStructure->getNumberFields()));
461  headNode = createStructureNodes(
462  pvMaster,
463  pvRequest,
464  cacheInitStructure);
465  return true;
466 }
467 
468 
469 StructureConstPtr PVCopy::createStructure(
470  PVStructurePtr const &pvMaster,
471  PVStructurePtr const &pvFromRequest)
472 {
473  if(pvFromRequest->getStructure()->getNumberFields()==0) {
474  return pvMaster->getStructure();
475  }
476  PVFieldPtrArray const &pvFromRequestFields = pvFromRequest->getPVFields();
477  StringArray const &fromRequestFieldNames = pvFromRequest->getStructure()->getFieldNames();
478  size_t length = pvFromRequestFields.size();
479  if(length==0) return NULLStructure;
480  FieldConstPtrArray fields; fields.reserve(length);
481  StringArray fieldNames; fieldNames.reserve(length);
482  for(size_t i=0; i<length; ++i) {
483  string const &fieldName = fromRequestFieldNames[i];
484  PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
485  if(!pvMasterField) continue;
486  FieldConstPtr field = pvMasterField->getField();
487  if(field->getType()==epics::pvData::structure) {
488  PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
489  pvFromRequestFields[i]);
490  if(pvRequestStructure->getNumberFields()>0) {
491  StringArray const &names = pvRequestStructure->getStructure()->
492  getFieldNames();
493  size_t num = names.size();
494  if(num>0 && names[0].compare("_options")==0) --num;
495  if(num>0) {
496  if(pvMasterField->getField()->getType()!=epics::pvData::structure) continue;
497  fieldNames.push_back(fieldName);
498  fields.push_back(createStructure(
499  static_pointer_cast<PVStructure>(pvMasterField),
500  pvRequestStructure));
501  continue;
502  }
503  }
504  }
505  fieldNames.push_back(fieldName);
506  fields.push_back(field);
507  }
508  size_t numsubfields = fields.size();
509  if(numsubfields==0) {
510  std::stringstream ss;
511  ss << pvFromRequest << "\n";
512  string val("no fields from the following request were found\n");
513  val += ss.str();
514  throw std::invalid_argument(val);
515  }
516  return getFieldCreate()->createStructure(fieldNames, fields);
517 }
518 
519 CopyNodePtr PVCopy::createStructureNodes(
520  PVStructurePtr const &pvMasterStructure,
521  PVStructurePtr const &pvFromRequest,
522  PVStructurePtr const &pvFromCopy)
523 {
524  PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
525  PVStructurePtr pvOptions = pvFromRequest->getSubField<PVStructure>("_options");
526  size_t number = copyPVFields.size();
527  CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
528  nodes->reserve(number);
529  for(size_t i=0; i<number; i++) {
530  PVFieldPtr copyPVField = copyPVFields[i];
531  string fieldName = copyPVField->getFieldName();
532  PVStructurePtr requestPVStructure =
533  pvFromRequest->getSubField<PVStructure>(fieldName);
534  PVStructurePtr pvSubFieldOptions =
535  requestPVStructure->getSubField<PVStructure>("_options");
536  PVFieldPtr pvMasterField = pvMasterStructure->getSubField(fieldName);
537  if(!pvMasterField) {
538  throw std::logic_error("PVCopy::createStructureNodes did not find field in master");
539  }
540  size_t numberRequest = requestPVStructure->getPVFields().size();
541  bool haveOptions = false;
542  if(pvSubFieldOptions) {
543  numberRequest--;
544  haveOptions = true;
545  }
546  if(numberRequest>0) {
547  Type copyType = copyPVField->getField()->getType();
548  if(copyType==epics::pvData::structure) {
549  nodes->push_back(createStructureNodes(
550  static_pointer_cast<PVStructure>(pvMasterField),
551  requestPVStructure,
552  static_pointer_cast<PVStructure>(copyPVField)));
553  continue;
554  }
555  if(copyType==epics::pvData::union_) {
556  if(numberRequest!=1) {
557  std::stringstream ss;
558  ss << pvFromRequest << "\n";
559  string val("In the following request a union field has more than one subfield in\n");
560  val += ss.str();
561  throw std::invalid_argument(val);
562  }
563  PVUnionPtr pvUnion = static_pointer_cast<PVUnion>(pvMasterField);
564  std::string selectedName = pvUnion->getSelectedFieldName();
565  PVFieldPtrArray const & pvFields = requestPVStructure->getPVFields();
566  size_t len = pvFields.size();
567  if(len>2 || (haveOptions && len!=2)) {
568  std::stringstream ss;
569  ss << pvFromRequest << "\n";
570  string val("PVCopy logic error: pvRequest is\n");
571  val += ss.str();
572  throw std::logic_error(val);
573  }
574  size_t indRequestValue = 0;
575  if((pvFields[0]->getFieldName().compare("_options"))==0) indRequestValue = 1;
576  PVFieldPtr pvRequestValue = pvFields[indRequestValue];
577  if(pvRequestValue) {
578  string requestName = pvRequestValue->getFieldName();
579  if(requestName.compare(selectedName)!=0) {
580  std::stringstream ss;
581  ss << pvFromCopy << "\n";
582  string requestName = pvRequestValue->getFieldName();
583  string val("field ");
584  val += requestName + " does not match union type in\n";
585  val += ss.str();
586  throw std::invalid_argument(val);
587  }
588  }
589  } else {
590  std::stringstream ss;
591  ss << pvFromCopy << "\n";
592  string val("requested a subfield of field ");
593  val += fieldName + " which does not have type structure in\n";
594  val += ss.str();
595  throw std::invalid_argument(val);
596  }
597  }
598  CopyNodePtr node(new CopyNode());
599  node->options = pvSubFieldOptions;
600  node->isStructure = false;
601  node->masterPVField = pvMasterField;
602  node->nfields = copyPVField->getNumberFields();
603  node->structureOffset = copyPVField->getFieldOffset();
604  nodes->push_back(node);
605  }
606  CopyStructureNodePtr structureNode(new CopyStructureNode());
607  structureNode->masterPVField = pvMasterStructure;
608  structureNode->isStructure = true;
609  structureNode->nodes = nodes;
610  structureNode->structureOffset = pvFromCopy->getFieldOffset();
611  structureNode->nfields = pvFromCopy->getNumberFields();
612  structureNode->options = pvOptions;
613  return structureNode;
614 }
615 
616 void PVCopy::initPlugin(
617  CopyNodePtr const & node,
618  PVStructurePtr const & pvOptions,
619  PVFieldPtr const & pvMasterField)
620 {
621  PVFieldPtrArray const & pvFields = pvOptions->getPVFields();
622  size_t num = pvFields.size();
623  vector<PVFilterPtr> pvFilters(num);
624  size_t numfilter = 0;
625  for(size_t i=0; i<num; ++i) {
626  PVStringPtr pvOption = static_pointer_cast<PVString>(pvFields[i]);
627  string name = pvOption->getFieldName();
628  string value = pvOption->get();
629  PVPluginPtr pvPlugin = PVPluginRegistry::find(name);
630  if(!pvPlugin) {
631  if(name.compare("ignore")==0) setIgnore(node);
632  continue;
633  }
634  pvFilters[numfilter] = pvPlugin->create(value,shared_from_this(),pvMasterField);
635  if(pvFilters[numfilter]) ++numfilter;
636  }
637  if(numfilter==0) return;
638  node->pvFilters.resize(numfilter);
639  for(size_t i=0; i<numfilter; ++i) node->pvFilters[i] = pvFilters[i];
640 }
641 
642 void PVCopy::traverseMasterInitPlugin()
643 {
644  traverseMasterInitPlugin(headNode);
645 }
646 
647 void PVCopy::traverseMasterInitPlugin(CopyNodePtr const & node)
648 {
649  PVFieldPtr pvField = node->masterPVField;
650  PVStructurePtr pvOptions = node->options;
651  if(pvOptions) initPlugin(node,pvOptions,pvField);
652  if(!node->isStructure) return;
654  CopyNodePtrArrayPtr nodes = structureNode->nodes;
655  for(size_t i=0; i< nodes->size(); i++) {
656  traverseMasterInitPlugin((*nodes)[i]);
657  }
658 }
659 
660 CopyNodePtr PVCopy::getCopyOffset(
661  CopyStructureNodePtr const &structureNode,
662  PVFieldPtr const &masterPVField)
663 {
664  size_t offset = masterPVField->getFieldOffset();
665  CopyNodePtrArrayPtr nodes = structureNode->nodes;
666  for(size_t i=0; i< nodes->size(); i++) {
667  CopyNodePtr node = (*nodes)[i];
668  if(!node->isStructure) {
669  size_t off = node->masterPVField->getFieldOffset();
670  size_t nextOffset = node->masterPVField->getNextFieldOffset();
671  if(offset>= off && offset<nextOffset) return node;
672  } else {
673  CopyStructureNodePtr subNode =
675  CopyNodePtr node =
676  getCopyOffset(subNode,masterPVField);
677  if(node) return node;
678  }
679  }
680  return NULLCopyNode;
681 }
682 
683 
684 
685 bool PVCopy::checkIgnore(
686  PVStructurePtr const & copyPVStructure,
687  BitSetPtr const & bitSet)
688 {
689  if(!ignorechangeBitSet) {
690  return (bitSet->nextSetBit(0)<0) ? false : true;
691  }
692  int32 numFields = copyPVStructure->getNumberFields();
693  BitSet temp(numFields);
694  temp = *bitSet;
695  int32 ind = 0;
696  while(true) {
697  ind = ignorechangeBitSet->nextSetBit(ind);
698  if(ind<0) break;
699  temp.clear(ind);
700  ind++;
701  if(ind>=numFields) break;
702  }
703  return (temp.nextSetBit(0)<0) ? false : true;
704 }
705 
706 void PVCopy::setIgnore(CopyNodePtr const &node) {
707  ignorechangeBitSet->set(node->structureOffset);
708  if(node->isStructure) {
710  CopyNodePtrArrayPtr nodes = structureNode->nodes;
711  for(size_t i=0; i<nodes->size(); ++i) {
712  CopyNodePtr node = (*nodes)[i];
713  setIgnore(node); }
714  } else {
715  size_t num = node->masterPVField->getNumberFields();
716  if(num>1) {
717  for(size_t i=1; i<num; ++i) {
718  ignorechangeBitSet->set(node->structureOffset+i);
719  }
720  }
721  }
722 }
723 
724 
725 CopyNodePtr PVCopy::getMasterNode(
726  CopyStructureNodePtr const &structureNode,
727  std::size_t structureOffset)
728 {
729  CopyNodePtrArrayPtr nodes = structureNode->nodes;
730  for(size_t i=0; i<nodes->size(); ++i) {
731  CopyNodePtr node = (*nodes)[i];
732  if(structureOffset>=(node->structureOffset + node->nfields)) continue;
733  if(!node->isStructure) return node;
734  CopyStructureNodePtr subNode =
736  return getMasterNode(subNode,structureOffset);
737  }
738  return NULLCopyNode;
739 }
740 
741 void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
742 {
743  newLine(builder,indentLevel);
744  std::stringstream ss;
745  ss << (node->isStructure ? "structureNode" : "node");
746  ss << " structureOffset " << node->structureOffset;
747  ss << " nfields " << node->nfields;
748  *builder += ss.str();
749  PVStructurePtr options = node->options;
750  if(options) {
751  newLine(builder,indentLevel +1);
752  *builder += options->getFieldName();
753  PVFieldPtrArray pvFields = options->getPVFields();
754  for(size_t i=0; i< pvFields.size() ; ++i) {
756  newLine(builder,indentLevel +2);
757  *builder += pvString->getFieldName() + " " + pvString->get();
758  }
759  }
760  string name = node->masterPVField->getFullName();
761  newLine(builder,indentLevel +1);
762  *builder += "masterField " + name;
763  if(node->pvFilters.size()>0) {
764  newLine(builder,indentLevel +2);
765  *builder += "filters:";
766  for(size_t i=0; i< node->pvFilters.size(); ++i) {
767  PVFilterPtr pvFilter = node->pvFilters[i];
768  *builder += " " + pvFilter->getName();
769  }
770  }
771  if(!node->isStructure) return;
772  CopyStructureNodePtr structureNode =
774  CopyNodePtrArrayPtr nodes = structureNode->nodes;
775  for(size_t i=0; i<nodes->size(); ++i) {
776  CopyNodePtr node = (*nodes)[i];
777  if(!node) {
778  newLine(builder,indentLevel +1);
779  ss.str("");
780  ss << "node[" << i << "] is null";
781  *builder += ss.str();
782  continue;
783  }
784  dump(builder,node,indentLevel+1);
785  }
786 }
787 
788 
789 }}
FORCE_INLINE std::tr1::shared_ptr< PVField > getSubField(A a)
Definition: pvData.h:744
const PVFieldPtrArray & getPVFields() const
Definition: pvData.h:736
std::tr1::shared_ptr< CopyStructureNode > CopyStructureNodePtr
Definition: link.h:174
pvac::PutEvent result
Definition: clientSync.cpp:117
BitSet & clear(uint32 bitIndex)
Definition: bitSet.cpp:112
std::tr1::shared_ptr< CopyNode > CopyNodePtr
int i
Definition: scan.c:967
std::tr1::shared_ptr< PVPlugin > PVPluginPtr
Definition: pvPlugin.h:28
std::tr1::shared_ptr< PVFilter > PVFilterPtr
Definition: pvPlugin.h:29
Definition: tool_lib.h:67
std::tr1::shared_ptr< PVCopy > PVCopyPtr
Definition: pvPlugin.h:25
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:788
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
A vector of bits.
Definition: bitSet.h:56
Support for subset of fields in a pvStructure.
std::vector< CopyNodePtr > CopyNodePtrArray
Definition: pvCopy.cpp:66
std::tr1::shared_ptr< PVCopyTraverseMasterCallback > PVCopyTraverseMasterCallbackPtr
CopyNodePtrArrayPtr nodes
Definition: pvCopy.cpp:70
std::string getSelectedFieldName() const
Definition: PVUnion.cpp:45
std::size_t getFieldOffset() const
Definition: PVField.cpp:44
PVString is special case, since it implements SerializableArray.
Definition: pvData.h:521
std::tr1::shared_ptr< PVUnion > PVUnionPtr
Definition: pvData.h:107
std::tr1::shared_ptr< CopyNodePtrArray > CopyNodePtrArrayPtr
Definition: pvCopy.cpp:67
pvData
Definition: monitor.h:428
Definition: caget.c:48
bool compare(const Field &a, const Field &b)
Definition: Compare.cpp:26
int32 nextSetBit(uint32 fromIndex) const
Definition: bitSet.cpp:164
PVUnion has a single subfield.
Definition: pvData.h:940
std::vector< FieldConstPtr > FieldConstPtrArray
Definition: pvIntrospect.h:146
std::vector< PVFieldPtr > PVFieldPtrArray
Definition: pvData.h:70
Data interface for a structure,.
Definition: pvData.h:712
std::tr1::shared_ptr< const Field > FieldConstPtr
Definition: pvIntrospect.h:137
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
PVStructurePtr options
Definition: pvCopy.cpp:60
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
std::tr1::shared_ptr< PVString > PVStringPtr
Definition: pvData.h:540
vector< PVFilterPtr > pvFilters
Definition: pvCopy.cpp:61
PVFieldPtr masterPVField
Definition: pvCopy.cpp:56
std::vector< std::string > StringArray
Definition: pvType.h:110
std::tr1::shared_ptr< PVField > PVFieldPtr
Definition: pvData.h:66
std::tr1::shared_ptr< BitSet > BitSetPtr
Definition: bitSet.h:26
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:808
const StructureConstPtr & getStructure() const
Definition: pvData.h:731
BitSet & set(uint32 bitIndex)
Definition: bitSet.cpp:103
C++ and C descriptions for a thread.
PVStructure * getParent()
Definition: pvData.h:213
#define false
Definition: flexdef.h:85
int32_t int32
Definition: pvType.h:83
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
Definition: pvData.h:1648