Free Electron
RecordView_spRA.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __datatool_RecordView_h__
8 #define __datatool_RecordView_h__
9 
10 #define FE_RV_VERBOSE (FE_CODEGEN<=FE_DEBUG)
11 #define FE_RV_CHECK (FE_CODEGEN<=FE_DEBUG)
12 
13 // check that RecordArray has current index
14 #define FE_RV_R_CHECK (FE_CODEGEN<=FE_DEBUG)
15 
16 // check that WeakRecord's have serial numbers
17 #define FE_RV_WR_CHECK (FE_CODEGEN<=FE_DEBUG)
18 
19 namespace fe
20 {
21 namespace ext
22 {
23 
24 //* TODO remove RecordArray support overhead (use RecordArrayView)
25 
26 /**************************************************************************//**
27  @brief Bindable collection of accessor Functors
28 
29  @ingroup datatool
30 
31  RecordView is an enhanced AccessorSet that supports inheritance
32  and default values. Like an AccessorSet, a RecordView instance
33  can be reused for any number of Record instances.
34 
35  For example:
36 
37 @code
38 class FE_DL_EXPORT Point: public RecordView
39 {
40  public:
41  Functor<SpatialVector> location;
42 
43  Point(void) { setName("Point"); }
44 virtual void addFunctors(void)
45  {
46  add(length, "spatial_vector",
47  FE_SPEC("spc:at",
48  "translation from origin"));
49  }
50 virtual void initializeRecord(void)
51  {
52  set(location());
53  }
54 virtual void finalizeRecord(void)
55  {
56  }
57 };
58 @endcode
59 
60  A class that derives from RecordView is expected to provide several things.
61  Added attributes are provided through Functors,
62  an enhancement of the Accessor.
63 
64  Provide a name for the generated Layout by setting the name
65  of the RecordView, using setName().
66 
67  Functors are wired up using add() during addFunctors().
68  The implementation of addFunctors() should call the like-named functions
69  for any direct base classes, much like a manual constructor mechanism.
70  Convention insists that attributes names are provided using
71  FE_USE or FE_SPEC. FE_USE presumes that an FE_SPEC or FE_ATTRIBUTE
72  elsewhere has provided a description for the atrribute.
73 
74  As a RecordFactoryI, a RecordView can be used to instantiate Records
75  by name from file. The method initializeRecord is called before
76  loading data to provide basic defaults. A method finalizeRecord
77  can be used after loading a Record for producing derived values,
78  such as creating a component as named by an attribute.
79  Both initializeRecord and finalizeRecord may be omitted if
80  nothing needs to be done for that stage.
81  As with addFunctors, both initializeRecord and finalizeRecord should
82  call the like-named functions for any direct base classes.
83 
84  To be available as a RecordFactoryI, each RecordView-derived type
85  should be added to a library during CreateLibrary()
86  like any other Component.
87 
88 @code
89 pLibrary->add<Point>("RecordFactoryI.Point.fe");
90 @endcode
91 
92  File-based defaults can be provided as a template in a record group file.
93 
94 @code
95 TEMPLATE Point ""
96  spc:at "0 0 0"
97 @endcode
98 
99  Attributes not represented by a template retain settings from
100  initializeRecord or their type's constructor.
101  Derived templates can provide new defaults that override prior values.
102  In the basic case, templates will parallel provided Factories,
103  including multiple inheritance (the second argument to TEMPLATE).
104  However, new templates can be provided purely on multiple inheritance
105  where no new attributes are added.
106 
107 *//***************************************************************************/
108 class RecordView:
109  public AccessorSet,
110  virtual public RecordFactoryI
111 {
112  protected:
113 
114  /// @brief Untyped Functor base
115  class RecordHolder
116  {
117  public:
118 #if FE_RV_CHECK
119  RecordHolder(void):
120  m_pspRecordArray(NULL),
121  m_pWeakRecord(NULL),
122  m_pIndex(0) {}
123 #endif
124  /// NOP: RecordView will handle copying
125  RecordHolder& operator=(const RecordHolder& rRecordHolder)
126  { return *this; }
127 
128  void bind(sp<RecordArray>& rspRecordArray,
129  WeakRecord& rWeakRecord,U32& rIndex)
130  {
131  m_pspRecordArray=&rspRecordArray;
132  m_pWeakRecord=&rWeakRecord;
133  m_pIndex=&rIndex;
134  }
135  protected:
136  sp<RecordArray>& array(void) const
137  {
138 #if FE_RV_R_CHECK
139  if(!m_pspRecordArray)
140  {
141  feX("RecordView::RecordHolder::array",
142  "m_pspRecordArray NULL");
143  }
144 #endif
145  return *m_pspRecordArray;
146  }
147 
148  WeakRecord& weakRecord(void) const
149  {
150 #if FE_RV_R_CHECK
151  if(!m_pWeakRecord)
152  {
153  feX("RecordView::RecordHolder"
154  "::weakRecord",
155  "m_pWeakRecord NULL");
156  }
157 #endif
158  return *m_pWeakRecord;
159  }
160 
161  U32 arrayIndex(void) const { return *m_pIndex; }
162 
163  sp<RecordArray>* m_pspRecordArray;
164  WeakRecord* m_pWeakRecord;
165  U32* m_pIndex;
166  };
167 
168  /// @brief Bound accessor in a RecordView
169  /// @ingroup datatool
170  template<typename T>
171  class Functor: public RecordHolder, public Accessor<T>
172  {
173  public:
174  Functor(void) {}
175  T& operator()(void);
176  const T operator()(void) const;
177  T& operator()(const Record& r)
178  { return Accessor<T>::operator()(r); }
179 const T operator()(const Record& r) const
180  { return Accessor<T>::operator()(r); }
181  T& operator()(const WeakRecord& r)
182  { checkWeakRecord(r);
183  return Accessor<T>::operator()(r); }
184 const T operator()(const WeakRecord& r) const
185  { checkWeakRecord(r);
186  return Accessor<T>::operator()(r); }
187  T& operator()(sp<RecordArray>& rspRA, FE_UWORD index)
188  { return Accessor<T>::operator()(rspRA,index); }
189 const T& operator()(sp<RecordArray>& rspRA, FE_UWORD index) const
190  { return Accessor<T>::operator()(rspRA,index); }
191 
192  BWORD check(void) const
193  {
194  FEASSERT(m_pspRecordArray);
195  FEASSERT(m_pWeakRecord);
196  FEASSERT((array()).isValid());
197  FEASSERT(m_pIndex);
198  return Accessor<T>::check(array());
199  }
200  BWORD check(sp<RecordArray>& rspRA) const
201  { return Accessor<T>::check(rspRA); }
202  BWORD check(const Record& r) const
203  { return Accessor<T>::check(r); }
204 
205  /** @brief Get the value, checking first
206 
207  If the bound Record does not support the
208  attribute, zero is returned, cast to the
209  attribute type. */
210  T safeGet(void)
211  {
212  T* pValue=NULL;
213  if(array().isValid() &&
215  array(),arrayIndex())))
216  {
217  return *pValue;
218  }
219  if(weakRecord().isValid() &&
221  weakRecord())))
222  {
223  return *pValue;
224  }
225  return T(0);
226  }
227 
228  /** @brief Set the value, checking first
229 
230  If the bound Record does not support the
231  attribute, nothing occurs. */
232  void safeSet(T value)
233  {
234  T* pValue=NULL;
235  if(array().isValid() &&
237  array(),arrayIndex())))
238  {
239  *pValue=value;
240  }
241  if(weakRecord().isValid() &&
243  weakRecord())))
244  {
245  *pValue=value;
246  }
247  }
248 
249  /** @brief Call the attribute as a method
250 
251  If the attribute cannot be cast to HandlerI,
252  nothing occurs.
253  If the cast is successful, the currently indexed
254  Record is passed to the HandlerI using handle().
255 
256  Trying to call an attribute whose content is not
257  derived from Counted or similar may cause a
258  compiler error. */
259  void call(void)
260  {
261  sp<HandlerI> spHandlerI=safeGet();
262  if(spHandlerI.isValid())
263  {
264  Record record;
265  if(array().isValid())
266  {
267  record=array()->getRecord(
268  arrayIndex());
269  }
270  else
271  {
272  record=weakRecord();
273  }
274 
275  spHandlerI->handle(record);
276  }
277  }
278 
279  /** @brief Create a named component for the attribute
280 
281  The created component is placed in the attribute.
282  If the attribute is not a component,
283  a compile error should occur. */
284  void createAndSetComponent(String componentName)
285  {
286  sp<Scope> spScope=Accessor<T>::scope();
287  FEASSERT(spScope.isValid());
288  sp<Component> spComponent=
289  spScope->registry()->create(componentName);
290  if(!spComponent.isValid())
291  {
292  feX("Functor<>::createAndSetComponent",
293  "\"%s\" failed to create \"%s\"\n",
294  name().c_str(),
295  componentName.c_str());
296  }
297  spComponent->setName(componentName+" "+name());
298  operator()()=spComponent;
299  }
300 
301  /** @brief Create a RecordGroup for the attribute
302 
303  The RecordGroup is placed in the attribute.
304  If the attribute is not a RecordGroup,
305  a compile error should occur. */
307  {
308  FEASSERT(m_pspRecordArray);
309  FEASSERT(m_pWeakRecord);
310  FEASSERT(m_pIndex);
311  sp<RecordGroup> spRecordGroup(new RecordGroup());
312  FEASSERT(spRecordGroup.isValid());
313 #if FE_COUNTED_TRACK
314  spRecordGroup->setName(name());
315 #endif
316  operator()()=spRecordGroup;
317  }
318 
319 const String& name(void) const
320  { return BaseAccessor::attribute()->name(); }
321  private:
322  void checkRecordExists(void) const
323  {
324 #if FE_RV_R_CHECK
325  if(weakRecord().isValid())
326  {
327  return;
328  }
329  if(!array().isValid())
330  {
331  feX("RecordView::checkRecordExists",
332  "RecordArray invalid");
333  }
334  if(!array()->length())
335  {
336  feX("RecordView::checkRecordExists",
337  "no Record bound");
338  }
339  else if((int)arrayIndex()>=array()->length())
340  {
341  feX("RecordView::checkRecordExists",
342  "looking for index %d in RA length %d",
343  arrayIndex(),array()->length());
344  }
345 #endif
346  }
347 
348  void checkWeakRecord(const WeakRecord& r) const
349  {
350 #if FE_RV_WR_CHECK
351  r.demandSerialNumber();
352 #endif
353  }
354  };
355 
356  public:
357  RecordView(void):
358  m_tempArray(FALSE)
359  {
360  }
361 
362 virtual ~RecordView(void)
363  {
364 #if FE_COUNTED_TRACK
365  deregisterRegion(fe_cast<Counted>(this));
366 #endif
367  }
368 
369  void setName(const String& name)
370  {
371  Component::setName(name);
372 #if FE_COUNTED_TRACK
373  registerRegion(fe_cast<Counted>(this),
374  sizeof(RecordView));
375 #endif
376  }
377 
378 const String verboseName(void) const
379  { return "RecordView " + name(); }
380 
382 
383  /** @brief Associate with a Scope
384 
385  This can happen automatically by binding
386  to a Record or RecordArray, but may be neccessary
387  if you need to use the Functors before an
388  appropriate Layout exists. */
389  void bind(sp<Scope>& rspScope)
390  {
391  FEASSERT(rspScope.isValid());
392 
393  if(!m_hpScope.isValid())
394  {
395  AccessorSet::bind(rspScope);
396  addFunctors();
397  }
398 #if FE_RV_CHECK
399  else if(m_hpScope!=rspScope)
400  {
401  feX("RecordView::bind(sp<Scope>&) \"%s\"",
402  "changed scope",name().c_str());
403  }
404 #endif
405  }
406 
407  /// @brief Associate with a Scope by Handle
408  void bind(hp<Scope>& rhpScope)
409  {
410  FEASSERT(rhpScope.isValid());
411 
412  if(!m_hpScope.isValid())
413  {
414  AccessorSet::bind(rhpScope);
415  addFunctors();
416  }
417 #if FE_RV_CHECK
418  else if(m_hpScope!=rhpScope)
419  {
420  feX("RecordView::bind(hp<Scope>&) \"%s\"",
421  "changed scope",name().c_str());
422  }
423 #endif
424  }
425 
426  /// @brief Return associated Scope
427  hp<Scope>& scope(void) { return m_hpScope; }
428 
429  /** @brief Associate with a specific RecordArray
430 
431  Use setIndex() or step() to associate with
432  each Record. */
433  void bind(const sp<RecordArray>& rspRecordArray)
434  {
435  m_weakRecord=WeakRecord();
436  m_tempArray=FALSE;
437  m_index=0;
438  m_nextIndex=0;
439  if(m_spRecordArray==rspRecordArray)
440  return;
441 
442  m_spRecordArray=rspRecordArray;
443 #if !FE_RV_CHECK
444  if(!m_hpScope.isValid())
445 #endif
446  {
447  bind(rspRecordArray->layout()->scope());
448  }
449  }
450 
451  /** @brief Disassociate with any Record or RecordArray
452 
453  This should free all references. */
454  void unbind(void)
455  {
456  m_spRecordArray=NULL;
457  m_weakRecord=WeakRecord();
458  }
459 
460  /** @brief Associate with a specific Record
461 
462  This is only intended to be used when there is no
463  containing RecordArray available.
464  It can be more efficient to bind to
465  a RecordArray and use setIndex() or step().
466 
467  Passing Record objects is not thread-safe. */
468  void bind(const Record record,BWORD weak=FALSE)
469  {
470  m_weakRecord=WeakRecord();
471  m_index=0;
472  m_nextIndex=0;
473 
474  if(!record.isValid())
475  {
476  if(m_tempArray && m_spRecordArray.isValid())
477  {
478  m_spRecordArray->clear();
479  }
480  else
481  {
482  m_spRecordArray=NULL;
483  }
484  return;
485  }
486 
487  if(m_tempArray && m_spRecordArray.isValid() &&
488  m_spRecordArray->layout()!=record.layout())
489  {
490 #if 1
491  feLog("RecordView::bind(Record) \"%s\" tempArray"
492  " switching type from \"%s\""
493  " to \"%s\"\n",
494  name().c_str(),
495  m_spRecordArray->layout()->name().c_str(),
496  record.layout()->name().c_str());
497 #endif
498 
499 #if 0
500  m_tempArray=FALSE;
501  m_spRecordArray=NULL;
502 #else
503  // is this safe?
504  m_spRecordArray->clear();
505  m_spRecordArray->setLayout(record.layout());
506  m_spRecordArray->setWeak(weak);
507 #endif
508  }
509  else if(!m_tempArray || !m_spRecordArray.isValid())
510  {
511 #if 0
512  feLog("RecordView::bind(Record)"
513  " \"%s\" new \"%s\"\n",
514  name().c_str(),
515  record.layout()->name().c_str());
516 #endif
517  m_spRecordArray=new RecordArray;
518  m_spRecordArray->setWeak(weak);
519  }
520  else
521  {
522  m_spRecordArray->clear();
523  }
524 
525  m_tempArray=TRUE;
526 
527  if(!m_spRecordArray.isValid() ||
528  !m_spRecordArray->add(record))
529  {
530  feX("RecordView::bind(Record)",
531  "failed to create and populate RA \"%s\"",
532  name().c_str());
533  }
534 #if !FE_RV_CHECK
535  if(!m_hpScope.isValid())
536 #endif
537  {
538  bind(record.layout()->scope());
539  }
540  }
541 
542  void bind(const WeakRecord weakRecord,BWORD weak=FALSE)
543  {
544  m_weakRecord=weakRecord;
545 
546  m_index=0;
547  m_nextIndex=0;
548  m_spRecordArray=NULL;
549  m_tempArray=FALSE;
550 
551 #if !FE_RV_CHECK
552  if(!m_hpScope.isValid())
553 #endif
554  {
555  bind(weakRecord.layout()->scope());
556  }
557  }
558 
559  /** @brief Set the index into the bound RecordArray
560 
561  The first step() after setIndex() does not increment
562  the index. */
563  void setIndex(U32 index)
564  {
565  assignIndex(index);
566  m_nextIndex=index;
567  }
568 
569  /** @brief Step through the records in the array
570 
571  The first step will stay on the first record.
572  Later steps increment the index.
573  Stepping past the last record will return FALSE.
574 
575  In the future, filters may allow step() to
576  skip records. */
577  BWORD step(void)
578  {
579  if(m_spRecordArray.isValid() &&
580  I32(m_nextIndex)<m_spRecordArray->length())
581  {
582  assignIndex(m_nextIndex);
583  m_nextIndex++;
584  return !m_spRecordArray->isWeak() ||
585  record().isValid();
586  }
587 
588  return FALSE;
589  }
590 
591  /// @brief Return the current index into the RecordArray
592  U32 index(void)
593  {
594  return m_index;
595  }
596 
597  /** @brief Produce a Record using all the attributes
598 
599  The Record is unbound after initialization. */
600 virtual void produce(Record& rRecord)
601  {
602  if(rRecord.isValid())
603  {
604  bind(rRecord);
606  }
607  else
608  {
609  rRecord=createRecord();
610  }
611  unbind();
612  }
613 
614  /** @brief Finalize a Record using all the attributes
615 
616  This step follows after the record is fully
617  initialized and potentially serialized in.
618 
619  The Record is unbound after initialization. */
620 virtual void finalize(Record& rRecord)
621  {
622  if(rRecord.isValid())
623  {
624  bind(rRecord);
625  finalizeRecord();
626  }
627  unbind();
628  }
629 
630  /** @brief Create a Record using all the attributes
631 
632  The Record is automatically bound. */
634  {
635  if(!m_hpScope.isValid())
636  {
637  feX("RecordView::createRecord",
638  "\"%s\" has invalid scope\n",
639  name().c_str());
640  }
641 
642  Record record=m_hpScope->createRecord(layout());
643  if(!m_hpLayout.isValid())
644  {
645  feX("RecordView::createRecord",
646  "\"%s\" failed to create layout\n",
647  name().c_str());
648  }
649  if(!record.isValid())
650  {
651  feX("RecordView::createRecord",
652  "\"%s\" failed to create record\n",
653  name().c_str());
654  }
655 
656  bind(record);
658  return record;
659  }
660 
661  /// @brief Access the record by weak (fast) reference
662  WeakRecord record(void) const
663  {
664  if(m_spRecordArray.isValid())
665  return m_spRecordArray->getWeakRecord(m_index);
666 
667  return m_weakRecord;
668  }
669 
670  /// @brief Access a Layout of all the attributes
672  {
673  if(!m_hpScope.isValid())
674  {
675  feLog("RecordView::layout \"%s\" invalid scope\n",
676  name().c_str());
677  return sp<Layout>(NULL);
678  }
679  if(!m_hpLayout.isValid())
680  {
681 // feLog("RecordView::layout \"%s\" createLayout\n",
682 // name().c_str());
683  m_hpLayout=createLayout();
684  }
685  return m_hpLayout;
686  }
687 
688  /// @brief Spew attributes and state for the bound Record
689  void dump(void)
690  {
691  U32 number=size();
692  for(U32 m=0;m<number;m++)
693  {
694  FEASSERT((*this)[m]);
695  if(!record().isValid())
696  {
697  feLog("%2d %-16s %-16s <invalid record>\n",m,
698  nameOf(*(*this)[m]).c_str(),
699  typeOf(*(*this)[m]).c_str());
700  }
701 // valid record should always be locked anyway
702 #if 0
703  else if(!record().layout()->locked())
704  {
705  feLog("%2d %-16s %-16s <not locked>\n",m,
706  nameOf(*(*this)[m]).c_str(),
707  typeOf(*(*this)[m]).c_str());
708  }
709 #endif
710  else
711  {
712  feLog("%2d %-16s %-16s %s\n",m,
713  nameOf(*(*this)[m]).c_str(),
714  typeOf(*(*this)[m]).c_str(),
715  printOf(*(*this)[m]).c_str());
716  }
717  }
718  }
719 
720  /** @brief Called at instantiation to add functors
721 
722  In addition to using add() to explicitly adding all
723  the functors for a particular class,
724  the implementation of this function should first call
725  addFunctors() for all directly inherited classes
726  that are indirectly or directly derived from
727  RecordView(). */
728 virtual void addFunctors(void) =0;
729 
730  /** @brief Called at instantiation to initialize
731  attributes
732 
733  In addition to setting any attributes, the
734  implementation of this function should first call
735  initializeRecord() for all directly inherited classes
736  that are indirectly or directly derived from
737  RecordView().
738 
739  Functors can be used as accessors at this point. */
740 virtual void initializeRecord(void) {}
741 
742  /** @brief Called right after instantiation to finalize
743  complex attributes
744 
745  In addition to adjusting any attributes, the
746  implementation of this function should first call
747  finalizeRecord() for all directly inherited classes
748  that are indirectly or directly derived from
749  RecordView().
750 
751  Functors can be used as accessors at this point. */
752 virtual void finalizeRecord(void) {}
753 
754  /** @brief Indicate a RecordFactoryI for a Scope
755 
756  The template type is presumably a RecordView.
757  This function extracts the relevant arguments
758  to pass to the Scope.
759 
760  It is usually preferable to add the RecordView
761  as a Scope-generic RecordFactoryI using the
762  general registry mechanism.
763 
764  This is a convenience that doesn't really relate
765  to RecordView. */
766  template <typename T>
767 static void registerFactory(sp<Scope> spScope)
768  {
769  T* pRV=new T();
770  sp<RecordFactoryI> spRecordFactoryI(pRV);
771  spScope->registerFactory(pRV->name(),spRecordFactoryI);
772  }
773 
774  /** @brief Load the root RecordGroup from a file
775 
776  This is a convenience that doesn't really relate
777  to RecordView. */
779  String filename,BWORD a_binary=FALSE)
780  {
781  std::ifstream inFile(filename.c_str());
782  if(!inFile)
783  {
784 #if FE_RV_VERBOSE
785  feLog("RecordView::loadRecordGroup"
786  " could not open\n \"%s\"\n",
787  filename.c_str());
788 #endif
789  return sp<RecordGroup>();
790  }
791 
792  sp<data::StreamI> spStream(a_binary?
794  new data::BinaryStream(spScope)):
796  new data::AsciiStream(spScope)));
797  sp<RecordGroup> spRecordGroup=spStream->input(inFile);
798  inFile.close();
799 
800  return spRecordGroup;
801  }
802 
804  String buffer,BWORD a_binary=FALSE)
805  {
806  std::istringstream inString(buffer.c_str());
807  if(!inString)
808  {
809 #if FE_RV_VERBOSE
810  feLog("RecordView::loadRecordGroupFromBuffer"
811  " could not open string buffer\n");
812 #endif
813  return sp<RecordGroup>();
814  }
815 
816  sp<data::StreamI> spStream=a_binary?
818  new data::BinaryStream(spScope)):
820  new data::AsciiStream(spScope));
821  sp<RecordGroup> spRecordGroup=spStream->input(inString);
822 
823  return spRecordGroup;
824  }
825 
826  /** @brief Save the root RecordGroup to a file
827 
828  This is a convenience that doesn't really relate
829  to RecordView. */
830 static void saveRecordGroup(sp<Scope> spScope,
831  sp<RecordGroup>& rspRecordGroup,
832  String filename,BWORD a_binary=FALSE)
833  {
834  std::ofstream outfile(filename.c_str());
835  if(!outfile)
836  {
837  feLog("RecordView::saveRecordGroup"
838  " could not open test output file\n");
839  }
840  else
841  {
842  sp<data::StreamI> spStream=a_binary?
844  new data::BinaryStream(spScope)):
846  new data::AsciiStream(spScope));
847  spStream->output(outfile, rspRecordGroup);
848  outfile.close();
849  }
850  }
851 
852  protected:
853  /** @brief Add an attribute Functor
854 
855  The functor should be a member variable.
856  The name can be arbitrary, but conventions
857  may be wise. */
858  void add(BaseAccessor& rFunctor,const char* name)
859  {
860  rFunctor.setup(m_hpScope,name);
861 // m_hpScope->support(name,type);
862  AccessorSet::add(rFunctor,name);
863  RecordHolder* pHolder=
864  static_cast<RecordHolder*>(
865  static_cast<Functor<int>*>(&rFunctor));
866  pHolder->bind(m_spRecordArray,m_weakRecord,m_index);
867  }
868  private:
869 // RecordView(const RecordView& rRecordView) :
870 // Initialized(), Component(), PopulateI(),
871 // AccessorSet(), RecordFactoryI()
872  RecordView(const RecordView& rRecordView):
873  AccessorSet() {}
874 
875  void assignIndex(U32 index)
876  {
877 #if FE_RV_CHECK
878  if(!m_spRecordArray.isValid())
879  {
880  feLog("RecordView::assignIndex \"%s\""
881  " no m_spRecordArray bound\n",
882  name().c_str());
883  return;
884  }
885 #endif
886 #if FE_RV_CHECK || 0//FE_PREFETCHING
887  const U32 length=m_spRecordArray->length();
888 #endif
889 #if FE_RV_CHECK
890  if(U32(index) >= length)
891  {
892  feLog("RecordView::assignIndex \"%s\""
893  " index out of bounds (%d/%d)\n",
894  name().c_str(),index,
895  m_spRecordArray->length());
896  }
897 #endif
898 #if 0//FE_PREFETCHING
899  if(index+2<length)
900  {
901  FEPREFETCH_READ(m_spRecordArray->data(index+2));
902  }
903 #endif
904  m_index=index;
905  }
906 
907  sp<Layout> createLayout(void)
908  {
909  if(!m_hpScope.isValid())
910  {
911  feX("AccessorArray::createLayout",
912  "\"%s\" has invalid scope\n",
913  name().c_str());
914  }
915 
916  sp<Layout> spLayout=m_hpScope->declare(name());
917  if(!spLayout.isValid())
918  {
919  feX("AccessorArray::createLayout",
920  "\"%s\" failed to create layout\n",
921  name().c_str());
922  }
923 
924  populate(spLayout);
925  return spLayout;
926  }
927 
928  String nameOf(BaseAccessor& accessor) const
929  {
930  return accessor.attribute()->name();
931  }
932 
933  String typeOf(BaseAccessor& accessor) const
934  {
935  std::list<String> nameList;
936  m_hpScope->registry()->master()->typeMaster()
937  ->reverseLookup(baseTypeOf(accessor),nameList);
938  return nameList.front();
939  }
940 
941  String printOf(BaseAccessor& accessor)
942  {
943  void* pVoid=record().rawAttribute(accessor.index());
944 
945  sp<BaseType::Info> spInfo=helpOf(accessor);
946  return spInfo->print(pVoid);
947  }
948 
949  sp<BaseType::Info> helpOf(BaseAccessor& accessor) const
950  {
951  sp<BaseType::Info> spInfo=
952  baseTypeOf(accessor)->getInfo();
953  FEASSERT(spInfo.isValid());
954  return spInfo;
955  }
956 
957  sp<BaseType> baseTypeOf(BaseAccessor& accessor) const
958  {
959  sp<Attribute> spAttribute=accessor.attribute();
960  return spAttribute->type();
961  }
962 
963  hp<Layout> m_hpLayout;
964 
965  sp<RecordArray> m_spRecordArray;
966  WeakRecord m_weakRecord;
967  U32 m_index;
968  U32 m_nextIndex;
969  BWORD m_tempArray;
970 };
971 
972 template<typename T>
974 {
975 #if FE_RV_CHECK
976  // Accessor already checks
977 // FEASSERT(check());
978 #endif
979 #if FE_RV_R_CHECK
980  checkRecordExists();
981 #endif
982  if(array().isValid())
983  {
984  return Accessor<T>::operator()(array(),arrayIndex());
985  }
986  return Accessor<T>::operator()(weakRecord());
987 }
988 
989 template<typename T>
990 inline const T RecordView::Functor<T>::operator()(void) const
991 {
992 #if FE_RV_CHECK
993  // Accessor already checks
994 // FEASSERT(check());
995 #endif
996 #if FE_RV_R_CHECK
997  checkRecordExists();
998 #endif
999  if(array().isValid())
1000  {
1001  return Accessor<T>::operator()(array(),arrayIndex());
1002  }
1003  return Accessor<T>::operator()(weakRecord());
1004 }
1005 
1006 template<>
1008 {
1009 #if FE_RV_CHECK
1010  // Accessor already checks
1011 // FEASSERT(check());
1012 #endif
1013 #if FE_RV_R_CHECK
1014  checkRecordExists();
1015 #endif
1016 
1017  if(array().isValid())
1018  {
1019 #if FE_RV_WR_CHECK
1020  checkWeakRecord(Accessor<WeakRecord>::operator()(array(),arrayIndex()));
1021 #endif
1022  return Accessor<WeakRecord>::operator()(array(),arrayIndex());
1023  }
1024 
1025 #if FE_RV_WR_CHECK
1026  checkWeakRecord(Accessor<WeakRecord>::operator()(weakRecord()));
1027 #endif
1028  return Accessor<WeakRecord>::operator()(weakRecord());
1029 }
1030 
1031 template<>
1033 {
1034 #if FE_RV_CHECK
1035  // Accessor already checks
1036 // FEASSERT(check());
1037 #endif
1038 #if FE_RV_R_CHECK
1039  checkRecordExists();
1040 #endif
1041 
1042  if(array().isValid())
1043  {
1044 #if FE_RV_WR_CHECK
1045  checkWeakRecord(Accessor<WeakRecord>::operator()(array(),arrayIndex()));
1046 #endif
1047  return Accessor<WeakRecord>::operator()(array(),arrayIndex());
1048  }
1049 
1050 #if FE_RV_WR_CHECK
1051  checkWeakRecord(Accessor<WeakRecord>::operator()(weakRecord()));
1052 #endif
1053  return Accessor<WeakRecord>::operator()(weakRecord());
1054 }
1055 
1056 inline BWORD operator==(const RecordView& rRecordView1,
1057  const RecordView& rRecordView2)
1058 {
1059  return rRecordView1.record()==rRecordView2.record();
1060 }
1061 
1062 inline BWORD operator!=(const RecordView& rRecordView1,
1063  const RecordView& rRecordView2)
1064 {
1065  return rRecordView1.record()!=rRecordView2.record();
1066 }
1067 
1068 } /* namespace ext */
1069 } /* namespace fe */
1070 
1071 #endif /* __datatool_RecordView_h__ */
1072 
A heterogenous collection of records.
Definition: RecordGroup.h:35
Set of accessors.
Definition: AccessorSet.h:18
void createAndSetRecordGroup(void)
Create a RecordGroup for the attribute.
Definition: RecordView_spRA.h:306
const FESTRING_I8 * c_str(void) const
Return the contents of the 8-bit buffer cast as signed bytes.
Definition: String.h:352
bool isValid(void) const
Return true if the Record points to a valid state block.
Definition: RecordSB.h:184
void add(BaseAccessor &rFunctor, const char *name)
Add an attribute Functor.
Definition: RecordView_spRA.h:858
void bind(sp< Scope > &rspScope)
Associate with a Scope.
Definition: RecordView_spRA.h:389
kernel
Definition: namespace.dox:3
Bound accessor in a RecordView.
Definition: RecordView.h:147
void bind(const sp< RecordArray > &rspRecordArray)
Associate with a specific RecordArray.
Definition: RecordView_spRA.h:433
void demandSerialNumber(void) const
throw if the record doesn&#39;t have a serial number
Definition: WeakRecordSB.cc:14
const sp< LayoutSB > & layout(void) const
Return the Layout.
Definition: WeakRecordSB.h:251
RecordHolder & operator=(const RecordHolder &rRecordHolder)
NOP: RecordView will handle copying.
Definition: RecordView_spRA.h:125
hp< Registry > registry(void) const
Get the Registry that created this component.
Definition: Component.cc:219
The main data access class for the data system.
Definition: Accessor.h:128
static void registerFactory(sp< Scope > spScope)
Indicate a RecordFactoryI for a Scope.
Definition: RecordView_spRA.h:767
sp< Layout > layout(void) const
Return the Layout.
Definition: RecordSB.h:189
hp< Scope > & scope(void)
Return associated Scope.
Definition: RecordView_spRA.h:427
BWORD operator!=(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s (reverse logic)
Definition: DualString.h:229
static sp< RecordGroup > loadRecordGroup(sp< Scope > spScope, String filename, BWORD a_binary=FALSE)
Load the root RecordGroup from a file.
Definition: RecordView_spRA.h:778
void call(void)
Call the attribute as a method.
Definition: RecordView_spRA.h:259
Type inspecific Accessor.
Definition: Accessor.h:26
virtual void finalize(Record &rRecord)
Finalize a Record using all the attributes.
Definition: RecordView_spRA.h:620
sp< Component > create(const String &a_pattern, BWORD quiet=FALSE) const
Instantiate a Component of the given named implementation.
Definition: Registry.cc:628
Untyped Functor base.
Definition: RecordView.h:113
Safe handle for shared pointer.
Definition: Handled.h:61
void safeSet(T value)
Set the value, checking first.
Definition: RecordView_spRA.h:232
sp< Attribute > attribute(void) const
Return the attribute this accessor is for.
Definition: Accessor.cc:151
WeakRecord record(void) const
Access the record by weak (fast) reference.
Definition: RecordView.h:498
void dump(void)
Spew attributes and state for the bound Record.
Definition: RecordView_spRA.h:689
void unbind(void)
Disassociate with any Record or RecordArray.
Definition: RecordView_spRA.h:454
Automatically reference-counted string container.
Definition: String.h:128
void bind(hp< Scope > &rhpScope)
Associate with a Scope by Handle.
Definition: RecordView_spRA.h:408
bool check(const RecordSB &r) const
Return true if record has attribute.
Definition: Accessor.h:314
void createAndSetComponent(String componentName)
Create a named component for the attribute.
Definition: RecordView_spRA.h:284
virtual void addFunctors(void)=0
Called at instantiation to add functors.
Record createRecord(void)
Create a Record using all the attributes.
Definition: RecordView.h:469
BWORD step(void)
Step through the records in the array.
Definition: RecordView_spRA.h:577
Bindable collection of accessor Functors.
Definition: RecordView.h:106
Reference to an instance of a Layout.
Definition: RecordSB.h:35
U32 index(void)
Return the current index into the RecordArray.
Definition: RecordView_spRA.h:592
static void saveRecordGroup(sp< Scope > spScope, sp< RecordGroup > &rspRecordGroup, String filename, BWORD a_binary=FALSE)
Save the root RecordGroup to a file.
Definition: RecordView_spRA.h:830
int count(void) const
Return the count of references.
Definition: Counted.h:156
void setIndex(U32 index)
Set the index into the bound RecordArray.
Definition: RecordView_spRA.h:563
virtual void initializeRecord(void)
Called at instantiation to initialize attributes.
Definition: RecordView.h:571
bool isValid(void) const
Return true if the record points to the original valid state block.
Definition: WeakRecordSB.h:181
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
const String & name(void) const
Return the components chosen name.
Definition: Component.h:77
static sp< RecordGroup > loadRecordGroupFromBuffer(sp< Scope > spScope, String buffer, BWORD a_binary=FALSE)
Serialize a RecordGroup from a string.
Definition: RecordView.h:638
virtual void finalizeRecord(void)
Called right after instantiation to finalize complex attributes.
Definition: RecordView.h:583
T safeGet(void)
Get the value, checking first.
Definition: RecordView_spRA.h:210
virtual void produce(Record &rRecord)
Produce a Record using all the attributes.
Definition: RecordView_spRA.h:600
void setName(const String &name)
Rename the component to anything you want.
Definition: Component.h:84
BWORD isValid(void) const
Returns true if the pointer is set.
Definition: Handled.h:179
void bind(const Record record, BWORD weak=FALSE)
Associate with a specific Record.
Definition: RecordView_spRA.h:468
T & operator()(const RecordSB &r)
Return the attribute.
Definition: Accessor.h:489
void setWeak(BWORD weak)
Choose weak referencing.
Definition: RecordArraySB.h:183
void registerFactory(String name, sp< RecordFactoryI > spRecordFactoryI)
Specify who can produce a named layout.
Definition: Scope.cc:524
void setup(sp< Scope > spScope, const String &attribute)
setup functions setup the accessor and also setup the Scope.
Definition: Accessor.cc:113
U32 length(void) const
Return the number of represented characters, but not necessarily the size of any buffer.
Definition: String.h:662
Homogeneous collection of Records.
Definition: RecordArraySB.h:40
sp< Layout > layout(void)
Access a Layout of all the attributes.
Definition: RecordView.h:504
Non-persistent reference to an instance of a Layout.
Definition: WeakRecordSB.h:17