cfl_baseset.h
Go to the documentation of this file.
1 /** @file cfl_baseset.h @brief Class TBaseSet */
2 
3 
4 /* FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2008 Thomas Moor
7  Exclusive copyright is granted to Klaus Schmidt
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 
24 
25 #ifndef FAUDES_BASESET_H
26 #define FAUDES_BASESET_H
27 
28 #include "cfl_definitions.h"
29 #include "cfl_tokenwriter.h"
30 #include "cfl_tokenreader.h"
31 #include "cfl_registry.h"
32 #include "cfl_types.h"
33 #include "cfl_attributes.h"
34 #include <set>
35 #include <algorithm>
36 
37 namespace faudes {
38 
39 /** @addtogroup ContainerClasses */
40 /** @{*/
41 
42 // Forward declaration for the attribute interface class
43 template<class T, class Attr, class Cmp> class TAttrMap;
44 
45 /**
46  * STL style set template.
47  * This class template is built on top of the STL set template. It provides essentials of
48  * the STL interface relevant to libFAUDES plus a deferred copy mechanism, aka copy-on-write.
49  * TBaseSet serves as a base class for all libFaudes containers:
50  * - IndexSet (indices),
51  * - TaIndexSet (indices with attributes),
52  * - SymbolSet (symbolic names),
53  * - NameSet (indices with symbolic names),
54  * - TaNameSet (indices with attributes and symbolic names),
55  * - TTransSet (transitions in a sepcific order),
56  * - TaTransSet (transitions in std order with attribute).
57  *
58  * The public functions of a TBaseSet provide the high-level api, with the intention
59  * to organize the deferred copy machanism in a transparent manner. Since STL iterators
60  * refer to a particular STL container, they become invalid when the internal container
61  * is copied. Therefor, TBaseSet tracks iterators and fixes them when the actual copy takes place.
62  * This introduces some runtime overhead, in particular when your application represents
63  * subsets as sets of iterators. You may use the public method Lock() to enforce
64  * a full copy and to prevent any further re-allocation.
65  *
66  * Alternatively to the high-level api, a protected low-level api is provided with direct
67  * access to the internal STL set. When using this api, it is up to the derived class to ensure
68  * that the BaseSet gets detached from its refernces befor write operations can take
69  * place.
70  *
71  * The virtual function TBaseSet<T>::Valid() is used to indicate whether a candidate
72  * element is valid as a set member. If the macro FAUDES_CHECKED
73  * is defined, the attempt to insert an invalid element triggers an exception (id 61). Invalid
74  * iterators throw an exception (id 62) when used as an argument to a BaseSet function.
75  *
76  * The TBaseSet also hosts a container to associate an attribute with each set element. However,
77  * in the plain TBAseSey the attribute type is set to void and member methods only deal
78  * with attributes when this does not invilve too much overhead. To make effective use of attributes,
79  * one is meant to derive a class from TBaseSet that encodes the actual attribute type and
80  * that provides appropriate access methods. This is facilitated by the class TAttrMap.
81  *
82  * Note on a boring technical detail:
83  * since STL sets are sorted, effectively all set iterators should be const.
84  * However, there is a minor issue whether or not the erase function should use a
85  * const iterator as argument. SGI derived STL implementations (as used on most GNU systems)
86  * avoid this issue by defining const and non-const iterators on sets as identical types.
87  * MS implementation (used in VS C++ by default, as of 2006) differ in this aspect. The class
88  * TBaseSet::Iterator hides the issue from the faudes API but it is still present internaly.
89  *
90  */
91 
92 template<class T, class Cmp=std::less<T> >
93 class TBaseSet : public Type {
94 
96 
97 public:
98 
99  /** allow access to attribute interface class */
100  template<class TP, class AP, class CP> friend class TAttrMap;
101 
102 
103  /**
104  * Constructor.
105  */
106  TBaseSet(void);
107 
108  /**
109  * Copy-constructor.
110  *
111  * @param rOtherSet
112  * Source to copy from
113  */
114  TBaseSet(const TBaseSet& rOtherSet);
115 
116  /**
117  * Constructor from file.
118  * This constructor indicates the intended interface for derived classes. The base set
119  * itself cannot read from token streams.
120  *
121  * @param rFilename
122  * Name of File
123  * @param rLabel
124  * Section for the set in the file;
125  */
126  TBaseSet(const std::string& rFilename, const std::string& rLabel = "BaseSet");
127 
128  /**
129  * Virtual destructor
130  */
131  virtual ~TBaseSet(void);
132 
133  /**
134  * Return name of TBaseSet
135  *
136  * @return
137  * Name of TBaseSet
138  */
139  const std::string& Name(void) const;
140 
141  /**
142  * Set name of TBaseSet
143  *
144  * @param rName
145  * Name to set
146  */
147  void Name(const std::string& rName);
148 
149 
150  /**
151  * Clear all set
152  */
153  virtual void Clear(void);
154 
155  /**
156  * Get Size of TBaseSet
157  *
158  * @return
159  * Number of indices in TBaseSet
160  */
161  Idx Size(void) const;
162 
163  /**
164  * Test whether if the TBaseSet is Empty
165  *
166  * @return
167  * True if empty
168  */
169  bool Empty(void) const;
170 
171  /**
172  * Return pretty printable element.
173  * Reimplement this method for derived classes.
174  *
175  * @param rElem
176  * Element to print
177  *
178  * @return
179  * String
180  */
181  virtual std::string Str(const T& rElem) const;
182 
183  /**
184  * Iterator class for high-level api to TBaseSet.
185  *
186  */
187  class Iterator;
188 
189  /**
190  * Iterator to the begin of set
191  *
192  * @return
193  * Iterator
194  */
195  Iterator Begin(void) const;
196 
197  /**
198  * Iterator to the end of set
199  *
200  * @return
201  * Iterator
202  */
203  Iterator End(void) const;
204 
205  /**
206  * Test validty of candidate element.
207  *
208  * Reimplement this function for particular type T of elements,
209  * eg for an index set with T=Idx indicate 0 an invalid index.
210  *
211  * @param rElem
212  * Candidate to test
213  * @return
214  * True if element is valid
215  */
216  virtual bool Valid(const T& rElem) const;
217 
218 
219  /**
220  * Erase element by reference
221  *
222  * @param rElem
223  * Element to erase
224  * @return
225  * True if element used to exist
226  */
227  virtual bool Erase(const T& rElem);
228 
229 
230  /**
231  * Erase element by iterator
232  *
233  * @param pos
234  * Iterator to specify element
235  * @return
236  * Iterator to next element (or End if no such)
237  */
238  virtual Iterator Erase(const Iterator& pos);
239 
240 
241  /**
242  * Erase elements given by other set
243  *
244  * @param rOtherSet
245  * Set of elements to erase
246  */
247  virtual void EraseSet(const TBaseSet& rOtherSet);
248 
249  /**
250  * Restrict elements given by other set
251  *
252  * @param rOtherSet
253  * Set of elements to keep
254  */
255  virtual void RestrictSet(const TBaseSet& rOtherSet);
256 
257 
258  /**
259  * Insert specified element
260  *
261  * @param rElem
262  * Element to insert
263  * @return
264  * True if index was new to set
265  */
266  virtual bool Insert(const T& rElem);
267 
268  /**
269  * Insert specified element
270  *
271  * @param pos
272  * Insertion hint passed to STL
273  * @param rElem
274  * Element to insert
275  * @return
276  * Insertion position
277  *
278  */
279  virtual Iterator Inject(const Iterator& pos, const T& rElem);
280 
281  /**
282  * Insert specified element
283  *
284  * @param rElem
285  * Element to insert
286  *
287  */
288  virtual void Inject(const T& rElem);
289 
290  /**
291  * Insert elements given by rOtherSet
292  *
293  *
294  * @param rOtherSet
295  * Set of elements to insert
296  */
297  virtual void InsertSet(const TBaseSet& rOtherSet);
298 
299 
300  /**
301  * Test existence of element
302  *
303  * @param rElem
304  * Element to test
305  *
306  * @return
307  * True if element exists in set
308  */
309  bool Exists(const T& rElem) const;
310 
311  /**
312  * Find element and return iterator.
313  *
314  * @param rElem
315  * Element to find
316  *
317  * @return
318  * Iterator to element or End() if nonexistent
319  */
320  Iterator Find(const T& rElem) const;
321 
322  /**
323  * Set union operator
324  *
325  * @return
326  * Union Set
327  */
328  TBaseSet operator+ (const TBaseSet& rOtherSet) const;
329 
330  /**
331  * Set difference operator
332  *
333  * @return
334  * Difference Set
335  */
336  TBaseSet operator- (const TBaseSet& rOtherSet) const;
337 
338  /**
339  * Set intersection operator
340  *
341  * @return
342  * Intersection Set
343  */
344  TBaseSet operator* (const TBaseSet& rOtherSet) const;
345 
346 
347  /** Test for subset */
348  bool operator<= (const TBaseSet& rOtherSet) const;
349 
350  /** Test for superset */
351  bool operator>= (const TBaseSet& rOtherSet) const;
352 
353  /** Order for sorting containers of TBaseSet */
354  bool operator< (const TBaseSet& rOtherSet) const;
355 
356  /** Some validation of deferred copy mechanism (provoke abort)*/
357  void DValid(const std::string& rMessage="") const;
358 
359  /** Detach from extern storage (incl allocation and true copy) */
361  void Detach(DetachMode flag=AttrIncl) const;
362 
363  /** Detach and lock any further reallocation */
364  void Lock(void) const;
365 
366  /**
367  * Iterator class for high-level api to TBaseSet.
368  * This class is derived from STL iterators to additionally provide
369  * a reference of the container to iterate on. This feature
370  * is used to adjust iterators when the actual set gets reallocated due to a Detach()
371  * operation. Inheritance is private to ensure that all high-level api functions maintain
372  * iteretor refernces consistently. Currently, high-level api iterators support
373  * the operators -&gt; ,*, =, ++, --, ==, !=.
374  *
375  * Technical detail: the private inheritance prohibits the direct use of stl algorithms on
376  * faudes Iterators. If you need direct access to stl algorithms from outside the faudes set
377  * class, you may turn to public inheritance. Make sure to Lock the relevant sets befor
378  * applying any stl algorithms.
379  */
380  class Iterator : private std::set<T,Cmp>::const_iterator {
381  public:
382  /** Default constructor, container unknown */
383  Iterator() :
384  std::set<T,Cmp>::const_iterator() ,
385  pBaseSet(NULL),
386  mAttached(false)
387  {};
388 
389  /** Construct by members (used by TBaseSet to create temporary iterators) */
391  const TBaseSet<T,Cmp>* pBaseSet,
392  const typename std::set<T,Cmp>::const_iterator& sit,
393  bool att=false) :
394  std::set<T,Cmp>::const_iterator(sit),
395  pBaseSet(pBaseSet),
396  mAttached(false)
397  {
398  if(pBaseSet && att) {
399  pBaseSet->AttachIterator(this);
400  mAttached=true;
401  }
402  };
403 
404  /** Copy constructor, copies container reference, incl attach */
405  Iterator(const Iterator& fit) :
406  std::set<T,Cmp>::const_iterator(fit),
407  pBaseSet(fit.pBaseSet),
408  mAttached(false)
409  {
410  if(pBaseSet) {
411  pBaseSet->AttachIterator(this);
412  mAttached=true;
413  }
414  };
415 
416  /** Destructor */
417  ~Iterator(void) {
418  if(mAttached) pBaseSet->DetachIterator(this);
419  };
420 
421  /** report (debugging) */
422  std::string DStr(void) const {
423  std::stringstream rstr;
424  rstr << "[dit base " << pBaseSet << " a" << mAttached << " data " << pBaseSet->pSet;
425  if(pBaseSet) rstr << " elem " << pBaseSet->Str(**this);
426  rstr << "]";
427  return rstr.str();
428  }
429 
430  /** Assigment, tracks container */
431  const Iterator& operator= (const Iterator& rSrc) {
432 #ifdef FAUDES_DEBUG_CODE
433  if(rSrc.pBaseSet==NULL) {
434  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator= invalid iterator: no baseset");
435  abort();
436  }
437 #endif
438  // performance relevant std case
439  if(mAttached) if(pBaseSet==rSrc.pBaseSet) {
441  return *this;
442  }
443  // general case
444  if(mAttached) pBaseSet->DetachIterator(this);
446  pBaseSet = rSrc.pBaseSet;
447  if(pBaseSet) {
448  pBaseSet->AttachIterator(this);
449  mAttached=true;
450  } else {
451  mAttached=false;
452  }
453  return *this;
454  };
455 
456  /** Assign STL iterator only */
457  void StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
459  };
460 
461  /** Get STL iterator only */
462  const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
463  return *this;
464  };
465 
466  /** Invalidate */
467  void Invalidate(void) {
468  pBaseSet=NULL;
469  mAttached=false;
470  };
471 
472  /** Detach */
473  void Detach(void) {
474  mAttached=false;
475  };
476 
477 
478  /** Check validity (provoke abort error) */
479  void DValid(void) const {
480  if(pBaseSet==NULL) {
481  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):DValid(): invalid iterator: no baseset");
482  abort();
483  }
484  pBaseSet->DValid("Iterator");
485  };
486 
487  /** Reimplement dereference */
488  const T* operator-> (void) const {
489 #ifdef FAUDES_DEBUG_CODE
490  if(pBaseSet==NULL) {
491  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator->: invalid iterator: no baseset");
492  abort();
493  }
494 #endif
496  };
497 
498  /** Reimplement derefernce */
499  const T& operator* (void) const {
500 #ifdef FAUDES_DEBUG_CODE
501  if(pBaseSet==NULL) {
502  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator*: invalid iterator: no baseset");
503  abort();
504  }
505 #endif
507  };
508 
509  /** Reimplement == */
510  bool operator== (const Iterator& rOther) const {
511 #ifdef FAUDES_DEBUG_CODE
512  if(pBaseSet==NULL) {
513  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator==: invalid iterator: no baseset");
514  abort();
515  }
516 #endif
517  return *static_cast< const typename std::set<T,Cmp>::const_iterator *>(this) == rOther;
518  };
519 
520  /** Reimplement != */
521  bool operator!= (const Iterator& rOther) const {
522 #ifdef FAUDES_DEBUG_CODE
523  if(pBaseSet==NULL) {
524  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator!=: invalid iterator: no baseset");
525  abort();
526  }
527 #endif
528  return *static_cast< const typename std::set<T,Cmp>::const_iterator *>(this) != rOther;
529  };
530 
531  /** Reimplement postfix ++ */
532  Iterator operator++ (int step) {
533 #ifdef FAUDES_DEBUG_CODE
534  if(pBaseSet==NULL) {
535  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
536  abort();
537  }
538 #endif
539  Iterator old(pBaseSet,*this, true); // (tmoor 201308: very tricky issue in "erase(it++)" construct)
541  return old;
542  };
543 
544  /** Reimplement prefix ++ */
545  const Iterator& operator++ (void) {
546 #ifdef FAUDES_DEBUG_CODE
547  if(pBaseSet==NULL) {
548  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
549  abort();
550  }
551 #endif
553  return *this;
554  };
555 
556  /** Reimplement postfix -- */
557  Iterator operator-- (int step) {
558 #ifdef FAUDES_DEBUG_CODE
559  if(pBaseSet==NULL) {
560  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
561  abort();
562  }
563 #endif
564  Iterator old(pBaseSet, *this, true);
566  return old;
567  };
568 
569  /** Reimplement prefix -- */
570  const Iterator& operator-- (void) {
571 #ifdef FAUDES_DEBUG_CODE
572  if(pBaseSet==NULL) {
573  FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
574  abort();
575  }
576 #endif
578  return *this;
579  };
580 
581 
582  /** Order by reference for containers of Iterators < */
583  /*
584  bool operator< (const Iterator& rOther) const {
585  return this < &rOther;
586  };
587  */
588 
589  /** Maintaine container reference */
590  const TBaseSet<T,Cmp>* pBaseSet;
591 
592  /** Indicate that this iterator is attached to some baseset */
593  bool mAttached;
594  };
595 
596 #ifdef DONT_TRACK_REFERENCES
597 
598  /**
599  * Iterator class for high-level api to TBaseSet.
600  * This version is a dummy and does not provide any additional features.
601  */
602  class Iterator : public std::set<T,Cmp>::const_iterator {
603  public:
604 
605  /** Default contructor */
606  Iterator(void) :
608  {};
609 
610  /** Copy constructor */
611  Iterator(const Iterator& fit) :
612  std::set<T,Cmp>::const_iterator(fit)
613  {};
614 
615  /** Copy constructor */
616  Iterator(const typename std::set<T,Cmp>::const_iterator& sit) :
617  std::set<T,Cmp>::const_iterator(sit)
618  {};
619 
620  /** Copy constructor, compatibility */
621  Iterator(
622  const TBaseSet<T,Cmp>* pBaseSet,
623  const typename std::set<T,Cmp>::const_iterator& sit) :
624  std::set<T,Cmp>::const_iterator(sit)
625  {};
626 
627  /** Assign STL iterator only, compatibility */
628  void StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
630  };
631 
632  /** Get STL iterator only, compatibility */
633  const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
634  return *this;
635  };
636 
637  /** Invalidate, compatibility */
638  void Invalidate(void) {};
639 
640  };
641 
642 #endif
643 
644 
645  /**
646  * Attribute typeinfo.
647  * This virtual function provides an interface for derived container classes with attributes
648  * eg TaIndexSet. When not re-implemented, it returns an attribute with type AttributeVoid to
649  * indicate the absence of nontrivial attributes
650  */
651  virtual const AttributeVoid* AttributeType(void) const;
652 
653  /**
654  * Attribute typeinfo.
655  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
656  * It tests whether this set accepts the specified attribute type ie whether it can be casted.
657  * The test is performned by the Cast function of the attribute type returned by AttributeType().
658  * @param rAttr
659  * Attribute type to test.
660  * @return True, if attribute type is accepted.
661  */
662  virtual bool AttributeTest(const Type& rAttr) const;
663 
664  /**
665  * Attribute access.
666  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
667  * The current implementation uses the DoAssign method and clears any attributes afterwards.
668  * Future implementations may be more efficient.
669  *
670  * @param rSourceSet
671  * Set to copy from
672  */
673  virtual TBaseSet& AssignWithoutAttributes(const TBaseSet& rSourceSet);
674 
675  /**
676  * Attributes access.
677  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
678  * It copies attributes from the specified set, provided that they can be casted appropriately.
679  * Elements of this set which are not in rOtherSet maintain their attribute.
680  *
681  * @param rOtherSet
682  * Other BaseSet
683  * @exception Exception
684  * - Cannot cast attribute type (63)
685  */
686  virtual void Attributes(const TBaseSet& rOtherSet);
687 
688 
689 
690  /**
691  * Attribute access.
692  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
693  * Provide the number of explicit attributes.
694  * The TBaseSet itself has no attributes and thus this function returns 0.
695  */
696  Idx AttributesSize(void) const;
697 
698  /**
699  * Attribute access.
700  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
701  * The TBaseSet itself has no attributes and thus this function does nothing.
702  */
703  void ClearAttributes(void);
704 
705  /**
706  * Attribute access.
707  * Test whether attributes match with other set,
708  * and return true if attributes match for shared elements. It uses
709  * the equality test of individual attributes and, hence, requires the attribute type
710  * match too.
711  * @param rOtherSet
712  * Other set to compare with.
713  * @return
714  * True on match.
715  */
716  bool EqualAttributes(const TBaseSet& rOtherSet) const;
717 
718  /**
719  * Attribute access.
720  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
721  * The TBaseSet has no attributes and thus throws an exception.
722  * Derived classes that provide attributes are meant to return a pointer to the attribute specified by rElem.
723  *
724  * @param rElem
725  * Element of which the attribute is requested
726  * @return
727  * Attribute of specified element
728  * @exception Exception
729  * - No attributes provided (id 63)
730  */
731  virtual AttributeVoid* Attributep(const T& rElem);
732 
733  /**
734  * Attribute access.
735  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
736  * The TBaseSet has no attributes and thus returns a void attribute.
737  * Derived classes that provide attributes are meant to return the attribute specified by rElem.
738  * @param rElem
739  * Element of which the attribute is requested
740  * @return
741  * Attribute of specified element
742  */
743  virtual const AttributeVoid& Attribute(const T& rElem) const;
744 
745  /**
746  * Attribute access.
747  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
748  * The TBaseSet itself has void attributes and thus formally accepts any nontrivial attribute,
749  * however, ignoring any value.
750  * Derived classes that provide attributes are meant to set the attribute as specified. Only if the
751  * required cast to the actual attribute type fails an exception is thrown.
752  * @param rElem
753  * Element of which the attribute is to be set
754  * @param rAttr
755  * Attribute value to set.
756  * @exception Exception
757  * - Element does not exist (60)
758  * - Cannot cast attribute type (63)
759  */
760  virtual void Attribute(const T& rElem, const Type& rAttr);
761 
762  /**
763  * Attribute access.
764  * This virtual function provides an interface for derived classes with attributes eg TaIndexSet.
765  * It is meant to try to set the attribute as specified if the type can be casted. Otherwise it does nothing.
766  * @param rElem
767  * Element of which the attribute is to be set
768  * @param rAttr
769  * Attribute value to set.
770  */
771  virtual void AttributeTry(const T& rElem, const Type& rAttr) { (void) rElem; (void) rAttr; };
772 
773  /**
774  * Attribute access.
775  * Cleras an explicit attribute associated with the specified element if sucht attribute exists.
776  * The TBaseSet itself has no attributes and thus this function will do nothing.
777  * @param rElem
778  * Element of which the attribute is to be cleared
779  */
780  virtual void ClrAttribute(const T& rElem);
781 
782  /**
783  * Configure the element name tag.
784  * This method allows to overwrite the tag used for elements
785  * in XML IO. For usual, you will register derived class with
786  * the run-time-interface and set the elemen tag for XML IO.
787  *
788  * @param rTag
789  * Name to set
790  */
791  virtual void XElementTag(const std::string& rTag);
792 
793  /**
794  * Get objects's type name.
795  *
796  * Retrieve the faudes-type name from the type registry.
797  * Sets allow to overwrite the faudes-type identifier. This is allows
798  * for light-weight derived classes that do not need to be registered.
799  *
800  * @return
801  * Faudes-type name or empty string.
802  */
803  virtual const std::string& TypeName(void) const;
804 
805  /**
806  * Overwrite faudes-type name.
807  * This method is used to overwrite the faudes-type identifyer.
808  *
809  * @param rType
810  * Faudes-type name to set
811  */
812  virtual void TypeName(const std::string& rType);
813 
814 
815 
816 
817 protected:
818 
819 
820  /**
821  * Token output, see Type::DWrite for public wrappers.
822  * Reimplement this function in derived classes for specific
823  * specific template parameters. By convention, the default label ""
824  * should be translated to a) the name of the set or b) some meaningful default,
825  * eg "IndexSet" for a set of indices. The pContext pointer can de type-checked
826  * and interpreted, ie as a symboltable to provide symbolic names. It is also
827  * passed on to attributes.
828  *
829  * @param rTw
830  * Reference to TokenWriter
831  * @param rLabel
832  * Label of section to write, defaults to name of set
833  * @param pContext
834  * Write context to provide contextual information
835  */
836  virtual void DoWrite(TokenWriter& rTw, const std::string& rLabel="", const Type* pContext=0) const;
837 
838  /**
839  * Token output, debugging see Type::DWrite for public wrappers.
840  * Reimplement this function in derived classes for specific
841  * specific template parameters.
842  * @param rTw
843  * Reference to TokenWriter
844  * @param rLabel
845  * Label of section to write, defaults to name of set
846  * @param pContext
847  * Write context to provide contextual information
848  */
849  virtual void DoDWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const;
850 
851  /**
852  * Token output, see Type::SWrite for public wrappers.
853  * Statistics include size, name and attributey type. The latter
854  * is retrieved from the RTI, if initialized. Dereived sets may reimplement
855  * this method.
856  *
857  * @param rTw
858  * Reference to TokenWriter
859  */
860  virtual void DoSWrite(TokenWriter& rTw) const;
861 
862  /**
863  * Token input, see Type::Read for public wrappers.
864  * Reimplement this function in derived classes for specific
865  * specific template parameters.
866  * By convention, the default label "" should be translated to some meaningful default,
867  * eg "IndexSet" for a set of indices". The pContext pointer can de type-checked
868  * and interpreted, ie as a symboltable to provide symbolic names. It is also
869  * passed on to attributes.
870  *
871  * @param rTr
872  * Reference to TokenReader
873  * @param rLabel
874  * Label of section to read, defaults to name of set
875  * @param pContext
876  * Read context to provide contextual information
877  */
878  virtual void DoRead(TokenReader& rTr, const std::string& rLabel = "", const Type* pContext=0);
879 
880  /** assign my members */
881  void DoAssign(const TBaseSet& rSourceSet);
882 
883  /** test equality */
884  bool DoEqual(const TBaseSet& rOtherSet) const;
885 
886 
887  /** set attribute in map (assume elem exists in set, NULL <=> set to default) */
888  void DoAttribute(const T& rElem, const Type* pAttr);
889 
890  /** get attribute from map (return null if elem does not exist in map) */
891  const AttributeVoid* DoAttribute(const T& rElem) const;
892 
893  /** get attribute from map (insert explicit default if elem does not exist in map) */
894  AttributeVoid* DoAttributeExplicit(const T& rElem);
895 
896 protected:
897 
898 
899  /** Name of this BaseSet */
900  std::string mMyName;
901 
902  /** Pointer on STL set to operate on */
903  std::set<T,Cmp>* pSet;
904 
905  /** STL set, if this object hosts data (else NULL) */
906  std::set<T,Cmp>* mpSet;
907 
908  /** STL iterator, non-const version */
909  typedef typename std::set<T,Cmp>::iterator iterator;
910 
911  /** STL iterator, const version */
912  typedef typename std::set<T,Cmp>::const_iterator const_iterator;
913 
914  /** Convert STL iterator to API iterator*/
915  typename TBaseSet<T,Cmp>::Iterator ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const;
916 
917 
918 
919  /** Pointer to attribute map to operate on */
920  std::map<T,AttributeVoid*>* pAttributes;
921 
922  /** Attribute map, if this object hosts data (else NULL). */
923  std::map<T,AttributeVoid*>* mpAttributes;
924 
925  /** STL attribute iterator, non-const version */
926  typedef typename std::map<T,AttributeVoid*>::iterator aiterator;
927 
928  /** STL attribute iterator, const version */
929  typedef typename std::map<T,AttributeVoid*>::const_iterator const_aiterator;
930 
931 
932 
933 
934  /** Pointer on BaseSet that hosts our data (THIS if we host) */
936 
937  /** Iterator to the client list that hosts our data (maintained by host)*/
938  typename std::list< TBaseSet<T,Cmp>* >::iterator mClientRecord;
939 
940  /** BaseSets, that use data hosted by us (NULL if we dont host data, emptyset if we host to ourself excl.) */
941  std::list< TBaseSet<T,Cmp>* >* mpClients;
942 
943  /** Indicate "hosts data to myself only" */
944  bool mDetached;
945 
946  /** Indicate "dont re-allocate the STL set ever again" */
947  bool mLocked;
948 
949  /** Ensure that we do not host contents to anyone else */
950  void RelinkClients(void);
951 
952  /** Record that we provide contents to some other BaseSet */
953  void AttachClient(TBaseSet* pRef) const;
954 
955  /** Record that we stop providing data for some TBaseSet */
956  void DetachClient(TBaseSet* pRef) const;
957 
958  /** Iterators that refer to this TBaseSet */
959  std::set< Iterator* > mIterators;
960 
961  /** Record that an iterator refers to this TBaseSet */
962  void AttachIterator(Iterator* pFit) const;
963 
964  /** Record that an iterator stops to refer to this TBaseSet */
965  void DetachIterator(Iterator* pFit) const;
966 
967 
968 
969  /** Reimplment from type to use chache */
970  virtual const TypeDefinition* TypeDefinitionp(void) const;
971 
972  /** Get name of elements (used for XML IO) */
973  virtual const std::string& XElementTag(void) const;
974 
975  /** static empty STL set for default constructor */
976  static std::set<T,Cmp> msEmptySet;
977 
978  /** static empty STL map for default constructor */
979  static std::map<T,AttributeVoid*> msEmptyAttributes;
980 
981  /** static empty STL client list */
982  // std::list< TBaseSet<T,Cmp>* >* msEmptyClients;
983 
984 private:
985 
986  /** TypeDefinition cache (should use guarded pointer here) */
988 
989  /** Current/cached name of elements (used protected accessor method) */
990  std::string mXElementTag;
991 
992  /** Current/cached faudes type-name */
993  std::string mFaudesTypeName;
994 
995 
996 };
997 
998 
999 
1000 /*
1001  * Set union, rti wrapper
1002  *
1003  * @param rSetA
1004  * Set A
1005  * @param rSetB
1006  * Set B
1007  * @return
1008  * Union of set A and set B
1009  */
1010 
1011 template<class T, class Cmp>
1012 void SetUnion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
1013  FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): res at " << &rRes);
1014  // fix name
1015  std::string name=CollapsString(rSetA.Name() + "+" + rSetB.Name());
1016  // all the same
1017  if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
1018  // a and b ths same, res different
1019  if(&rSetA==&rSetB) {rRes.Assign(rSetA); rRes.Name(name); return;}
1020  // a and res the same, b different
1021  if(&rSetA==&rRes) {rRes.InsertSet(rSetB); rRes.Name(name); return;};
1022  // b and res the same, a different
1023  if(&rSetB==&rRes) {rRes.InsertSet(rSetA); rRes.Name(name); return;};
1024  // else
1025  rRes.Assign(rSetA);
1026  rRes.InsertSet(rSetB);
1027  rRes.Name(name);
1028  FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): done, res at " << &rRes << " #" << rRes.Size());
1029 }
1030 
1031 /*
1032  * Set intersection, rti wrapper
1033  *
1034  * @param rSetA
1035  * Set A
1036  * @param rSetB
1037  * Set B
1038  * @return
1039  * Set A intersected with set B
1040  */
1041 template< class T, class Cmp >
1042 void SetIntersection(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
1043  // fix name
1044  std::string name=CollapsString(rSetA.Name() + "*" + rSetB.Name());
1045  // all the same
1046  if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
1047  // a and b ths ame, res different
1048  if(&rSetA==&rSetB) { rRes.Assign(rSetA); rRes.Name(name); return;}
1049  // a and res the same, b different
1050  if(&rSetA==&rRes) {rRes.RestrictSet(rSetB); rRes.Name(name); return;};
1051  // b and res the same, a different
1052  if(&rSetB==&rRes) {rRes.RestrictSet(rSetA); rRes.Name(name); return;};
1053  // else
1054  rRes.Assign(rSetA);
1055  rRes.RestrictSet(rSetB);
1056  rRes.Name(name);
1057 }
1058 
1059 
1060 /*
1061  * Set difference, rti wrapper
1062  *
1063  * @param rSetA
1064  * Set A
1065  * @param rSetB
1066  * Set B
1067  * @return
1068  * Set A minus set B
1069  */
1070 template< class T, class Cmp >
1071 void SetDifference(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
1072  // fix name
1073  std::string name=CollapsString(rSetA.Name() + "-" + rSetB.Name());
1074  // a and b the same
1075  if(&rSetA==&rSetB) { rRes.Clear(); rRes.Name(name); return;}
1076  // a and res the same, b different
1077  if(&rSetA==&rRes) {rRes.EraseSet(rSetB); rRes.Name(name); return;};
1078  // b and res the same, a different ... need buffer?
1079  if(&rSetB==&rRes) {
1080  TBaseSet<T,Cmp>* buffb=rSetB.Copy();
1081  rRes.Assign(rSetA);
1082  rRes.EraseSet(*buffb);
1083  rRes.Name(name);
1084  delete buffb;
1085  return;
1086  };
1087  // else: std
1088  rRes.Assign(rSetA);
1089  rRes.EraseSet(rSetB);
1090  rRes.Name(name);
1091 }
1092 
1093 /*
1094  * Set equality, rti wrapper
1095  * This method ignores attributes.
1096  *
1097  * @param rSetA
1098  * Set A
1099  * @param rSetB
1100  * Set B
1101  * @return
1102  * True for matching sets.
1103  */
1104 template< class T, class Cmp >
1105 bool SetEquality(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
1106  return rSetA==rSetB;
1107 }
1108 
1109 /*
1110  * Set inclusion, rti wrapper
1111  * This method ignores attributes.
1112  *
1113  * @param rSetA
1114  * Set A
1115  * @param rSetB
1116  * Set B
1117  * @return
1118  * True for matching sets.
1119  */
1120 template< class T, class Cmp >
1121 bool SetInclusion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
1122  return rSetA<=rSetB;
1123 }
1124 
1125 
1126 
1127 
1128 /** @} doxygen group */
1129 
1130 
1131 
1132 /*
1133 ******************************************************************************************
1134 ******************************************************************************************
1135 ******************************************************************************************
1136 
1137 Implementation of TBaseSet
1138 
1139 ******************************************************************************************
1140 ******************************************************************************************
1141 ******************************************************************************************
1142 */
1143 
1144 /* convenience access to relevant scopes */
1145 #define THIS TBaseSet<T,Cmp>
1146 #define TEMP template<class T, class Cmp>
1147 #define BASE Type
1148 
1149 
1150 // faudes type std: new and cast
1153 FAUDES_TYPE_TIMPLEMENTATION_CAST(Void,THIS,Type,TEMP)
1154 
1155 // faudes type std: assignemnt (break cast)
1156 //TEMP THIS& THIS::Assign(const Type& rSrc) { this->Clear(); return *this;};
1157 //TEMP THIS& THIS::Assign(const THIS& rSrc) { DoAssign(rSrc); return *this;};
1158 
1159 // faudes type std: assignemnt (keep cast)
1162 
1163 
1164 // template statics: empty set
1165 TEMP std::set<T,Cmp> THIS::msEmptySet=std::set<T,Cmp>();
1166 TEMP std::map<T,AttributeVoid*> THIS::msEmptyAttributes=std::map<T,AttributeVoid*>();
1167 
1168 // TBaseSet()
1169 TEMP THIS::TBaseSet(void) :
1170  Type(),
1171  pSet(&msEmptySet),
1172  mpSet(NULL),
1173  pAttributes(&msEmptyAttributes),
1174  mpAttributes(NULL),
1175  pHostSet(this),
1176  mpClients(new std::list< TBaseSet<T,Cmp>* >),
1177  mDetached(false),
1178  mLocked(false),
1179  pTypeDefinition(NULL)
1180 {
1181  FAUDES_OBJCOUNT_INC("BaseSet");
1182  FD_DC("TBaseSet(" << this << ")::TBaseSet()");
1183  // other members
1184  mMyName="BaseSet";
1185 }
1186 
1187 // TBaseSet(filename)
1188 TEMP THIS::TBaseSet(const std::string& rFileName, const std::string& rLabel) :
1189  Type(),
1190  pSet(&msEmptySet),
1191  mpSet(NULL),
1192  pAttributes(&msEmptyAttributes),
1193  mpAttributes(NULL),
1194  pHostSet(this),
1195  mpClients(new std::list< TBaseSet<T,Cmp>* >),
1196  mDetached(false),
1197  mLocked(false),
1198  pTypeDefinition(NULL)
1199 {
1200  FAUDES_OBJCOUNT_INC("BaseSet");
1201  FD_DC("TBaseSet(" << this << ")::TBaseSet()");
1202  // other members
1203  mMyName="BaseSet";
1204  // do read etc ... this is a dummy anyway
1205  Read(rFileName,rLabel);
1206 }
1207 
1208 // TBaseSet(rOtherSet)
1209 TEMP THIS::TBaseSet(const TBaseSet& rOtherSet) :
1210  Type(rOtherSet),
1211  pSet(&msEmptySet),
1212  mpSet(NULL),
1213  pAttributes(&msEmptyAttributes),
1214  mpAttributes(NULL),
1215  pHostSet(this),
1216  mpClients(new std::list< TBaseSet<T,Cmp>* >), // small detour ... for readability
1217  mDetached(false),
1218  mLocked(false),
1219  pTypeDefinition(NULL)
1220 {
1221  FAUDES_OBJCOUNT_INC("BaseSet");
1222  FD_DC("TBaseSet(" << this << ")::TBaseSet(rOtherSet " << &rOtherSet << "): fake copy construct");
1223  // run assignment
1224  DoAssign(rOtherSet);
1225 #ifdef FAUDES_DEBUG_CODE
1226  DValid("CopyConstruct");
1227 #endif
1228 }
1229 
1230 // destructor
1231 TEMP THIS::~TBaseSet(void) {
1232  FAUDES_OBJCOUNT_DEC("BaseSet");
1233  FD_DC("TBaseSet(" << this << ")::~TBaseSet()");
1234  // maintain deferred copy
1235  RelinkClients();
1236  pHostSet->DetachClient(this);
1237  if(mpClients) delete mpClients;
1238  mpClients=NULL;
1239  // unlink iterators (mandatory, since referenced object will be destructed)
1240  typename std::set< Iterator* >::const_iterator iit;
1241  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1242  (**iit).Invalidate();
1243  }
1244  // delete if we still own data
1245  if(mpSet) delete mpSet;
1246  if(mpAttributes) {
1247  for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
1248  delete ait->second;
1249  delete mpAttributes;
1250  }
1251 }
1252 
1253 
1254 // fake copy
1255 TEMP void THIS::DoAssign(const THIS& rSourceSet) {
1256  FD_DC("TBaseSet(" << this << "/" << this->Name() << ")::DoAssign(rOtherSet " << &rSourceSet << "): shallow copy -- src attr# " << rSourceSet.pAttributes->size());
1257  FD_DC("TBaseSet():DoAssign(): " << typeid(*this->AttributeType()).name() << " <== " << typeid(*rSourceSet.AttributeType()).name());
1258  // bail out on selfref
1259  if(this==&rSourceSet) return;
1260  // other members
1261  mMyName=rSourceSet.mMyName;
1262  // bail out on common shared data
1263  if(pHostSet==rSourceSet.pHostSet) return;
1264  // become independant
1265  RelinkClients();
1266  pHostSet->DetachClient(this);
1267  // delete own old data
1268  if(mpSet) {
1269  delete mpSet;
1270  mpSet=NULL;
1271  }
1272  if(mpAttributes) {
1273  for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
1274  delete ait->second;
1275  delete mpAttributes;
1276  mpAttributes=NULL;
1277  }
1278  if(mpClients) {
1279  delete mpClients;
1280  mpClients=NULL;
1281  }
1282 
1283  // if attribute type matches, use source as host
1284  if(typeid(*rSourceSet.AttributeType())==typeid(*this->AttributeType())) {
1285  pHostSet=rSourceSet.pHostSet;
1286  pHostSet->AttachClient(this);
1287  pSet=rSourceSet.pSet;
1288  pAttributes=rSourceSet.pAttributes;
1289  }
1290  // else do a deep copy (avoid mixed typed attributeb maps)
1291  else {
1292  mpSet = new std::set<T,Cmp>();
1293  *mpSet = *rSourceSet.pSet;
1294  pSet = mpSet;
1295  mpAttributes = new std::map<T,AttributeVoid*>();
1296  if(typeid(*this->AttributeType()) != typeid(const AttributeVoid)) {
1297  for(aiterator ait=rSourceSet.pAttributes->begin(); ait!=rSourceSet.pAttributes->end(); ++ait) {
1298  AttributeVoid* attr= ait->second->Copy();
1299  (*mpAttributes)[ait->first]=attr;
1300  }
1301  }
1302  pAttributes = mpAttributes;
1303  pHostSet = this;
1304  }
1305  // fix iterators (invalidate)
1306  typename std::set< Iterator* >::iterator iit;
1307  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1308  (**iit).Invalidate();
1309  }
1310  mIterators.clear();
1311  // record state
1312  mDetached=false;
1313  // if we were locked, relock (i.e. do the copy)
1314  if(mLocked) {
1315  mLocked=false;
1316  Lock();
1317  };
1318 #ifdef FAUDES_DEBUG_CODE
1319  DValid("PostFakeAssignment");
1320 #endif
1321  FD_DC("TBaseSet(" << this << ")::DoAssign(rOtherSet " << &rSourceSet << "): fake copy -- done with attr# " << pAttributes->size());
1322 }
1323 
1324 // Detach()
1325 TEMP void THIS::Detach(DetachMode flag) const {
1326  FD_DC("TBaseSet(" << this << ")::Detach(void)");
1327 #ifdef FAUDES_DEBUG_CODE
1328  DValid("PreDetach");
1329 #endif
1330 
1331  // clear attributes for consistent behaviour
1332  if(mDetached) {
1333  if(flag==SetOnly) pAttributes->clear();
1334  return;
1335  }
1336 
1337  // provide fake const
1338  THIS* fake_const = const_cast< THIS* >(this);
1339 
1340 #ifdef FAUDES_DEBUG_CODE
1341  // might have missed reference detach
1342  if(pHostSet==this)
1343  if(pSet!=&msEmptySet)
1344  if(mpClients)
1345  if(mpClients->empty()) {
1346  FD_ERR("TBaseSet(" << this << ")::Detach(): missed detach (?)");
1347  abort(); // strict
1348  fake_const->mDetached=true; // fix
1349  }
1350 #endif
1351 
1352  // prepare: construct a copy of my data -- the set
1353  std::set<T,Cmp>* scopy = new std::set<T,Cmp>();
1354  *scopy = *pSet;
1355 
1356  // prepare: construct a copy of my data -- the attribute map (optional)
1357  std::map<T,AttributeVoid*>* acopy = new std::map<T,AttributeVoid*>();
1358  if(flag==AttrIncl) {
1359  for(aiterator ait=pAttributes->begin(); ait!=pAttributes->end(); ++ait) {
1360  AttributeVoid* attr= ait->second->Copy();
1361  (*acopy)[ait->first]=attr;
1362  }
1363  }
1364 
1365  // stragie A: clients get the new copy; thus, the baseset data does
1366  // not get reallocated and we dont need to track iterators; on the
1367  // downside, fixing the references iterators may be more effort.
1368  if(mLocked==true) {
1369 
1370  FD_DC("TBaseSet(" << this << ")::Detach(): allocate and copy, strategie A");
1371  // first of my clients gets the new data
1372  THIS* newhost = *mpClients->begin();
1373 #ifdef FAUDES_DEBUG_CODE
1374  if(newhost->mpClients)
1375  FD_ERR("TBaseSet(" << this << ")::Detach(): new host used to heve clients (?)");
1376 #endif
1377  newhost->pHostSet=newhost;
1378  newhost->mpSet=scopy;
1379  newhost->pSet=scopy;
1380  newhost->mpAttributes=acopy;
1381  newhost->pAttributes=acopy;
1382  newhost->mpClients=mpClients;
1383  newhost->DetachClient(newhost);
1384  // set other users to use the new host
1385  typename std::list< THIS* >::const_iterator rit;
1386  for(rit=newhost->mpClients->begin();rit!=newhost->mpClients->end(); ++rit) {
1387  (*rit)->pHostSet=newhost;
1388  (*rit)->pSet=newhost->pSet;
1389  (*rit)->pAttributes=newhost->pAttributes;
1390  }
1391  // fix newhost clients iterators
1392  typename std::set< Iterator* >::iterator iit;
1393  for(rit=newhost->mpClients->begin(); rit!=newhost->mpClients->end(); ++rit) {
1394  for(iit=(*rit)->mIterators.begin(); iit!=(*rit)->mIterators.end(); ++iit) {
1395  if((**iit).StlIterator()==pSet->end())
1396  **iit=Iterator(this, scopy->end());
1397  else
1398  **iit=Iterator(this, scopy->find(***iit));
1399  }
1400  }
1401  // fix newhost iterators
1402  for(iit=newhost->mIterators.begin(); iit!=newhost->mIterators.end(); ++iit) {
1403  if((**iit).StlIterator()==pSet->end())
1404  **iit=Iterator(this, scopy->end());
1405  else
1406  **iit=Iterator(this, scopy->find(***iit));
1407  }
1408  // make myself own the old data
1409  fake_const->mpSet=pSet;
1410  fake_const->mpAttributes=pAttributes;
1411  fake_const->mpClients= new std::list< TBaseSet<T,Cmp>* >;
1412  fake_const->mDetached=true;
1413  // stop tracking my iterators
1414  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit)
1415  (**iit).Detach();
1416  fake_const->mIterators.clear();
1417 
1418 
1419  // stragie B: this baseset gets the copy; thus, the clients iterators
1420  // remain valid and dont need to be fixed; on the downside, we need to
1421  // continue to track our iterators.
1422  } else {
1423 
1424  FD_DC("TBaseSet(" << this << ")::Detach(): allocate and copy, strategie B");
1425  // make someone else handle original data
1426  fake_const->RelinkClients();
1427  pHostSet->DetachClient(fake_const);
1428  // own the copied data
1429  fake_const->mpSet = scopy;
1430  fake_const->mpAttributes=acopy;
1431  // fix my iterators
1432  typename std::set< Iterator* >::iterator iit;
1433  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1434  if((**iit).StlIterator()==pSet->end())
1435  **iit=Iterator(this, mpSet->end());
1436  else
1437  **iit=Iterator(this, mpSet->find(***iit));
1438  }
1439  // record myself as my newhost
1440  fake_const->pHostSet=fake_const;
1441  fake_const->pSet=mpSet;
1442  fake_const->pAttributes=mpAttributes;
1443  fake_const->mDetached=true;
1444  if(fake_const->mpClients) delete fake_const->mpClients; // memeory leak fixed 20121004
1445  fake_const->mpClients= new std::list< TBaseSet<T,Cmp>* >;
1446  }
1447 
1448 
1449 #ifdef FAUDES_DEBUG_CODE
1450  DValid("PostDetach");
1451 #endif
1452  FD_DC("TBaseSet(" << this << ")::Detach(): done");
1453 }
1454 
1455 // Lock()
1456 TEMP void THIS::Lock(void) const {
1457  FD_DC("TBaseSet(" << this << ")::Lock(void)");
1458 #ifdef FAUDES_DEBUG_CODE
1459  DValid("PreLock");
1460 #endif
1461  // if we are locked: fine
1462  if(mLocked) return;
1463 
1464  // trigger actual copy (this set getting the copy)
1465  Detach(AttrIncl);
1466 
1467  // provide fake const
1468  THIS* fake_const = const_cast< THIS* >(this);
1469 
1470  // stop tracking iterators
1471  typename std::set< Iterator* >::const_iterator iit;
1472  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1473  (**iit).Detach();
1474  }
1475  fake_const->mIterators.clear();
1476 
1477  // stop detach from reallocating
1478  fake_const->mLocked=true;
1479 
1480 #ifdef FAUDES_DEBUG_CODE
1481  DValid("PostLock");
1482 #endif
1483 }
1484 
1485 
1486 // if i am a host to others, make someone else the host
1487 TEMP inline void THIS::RelinkClients(void) {
1488  FD_DC("TBaseSet::RelinkClients(" << this << ")")
1489 #ifdef FAUDES_DEBUG_CODE
1490  DValid("PreRelink");
1491 #endif
1492 
1493  // no clients record, so i dont host any data
1494  if(!mpClients) return;
1495  // empty clients, so i only host to myself
1496  if(mpClients->empty()) return;
1497 
1498  FD_DC("TBaseSet::RelinkClients(" << this << "): doit")
1499 
1500  // make first client the new host
1501  THIS* newhost = *mpClients->begin();
1502 #ifdef FAUDES_DEBUG_CODE
1503  if(newhost->pHostSet!=this)
1504  FD_ERR("BaseSet::RelinkRefernces: old reference must have this as provider");
1505  if(newhost->mpClients)
1506  FD_ERR("TBaseSet(" << this << ")::RelinkClients(void): client is a host (?)");
1507 #endif
1508  newhost->pHostSet=newhost;
1509  newhost->mpSet=mpSet;
1510  newhost->pSet=pSet;
1511  newhost->mpAttributes=mpAttributes;
1512  newhost->pAttributes=pAttributes;
1513  newhost->mpClients=mpClients;
1514  newhost->DetachClient(newhost);
1515  // set other users to new newhost
1516  typename std::list< THIS* >::const_iterator rit;
1517  for(rit=newhost->mpClients->begin();rit!=newhost->mpClients->end(); ++rit) {
1518  (*rit)->pHostSet=newhost;
1519  }
1520  // make myself a reference to the new source
1521  pHostSet=newhost;
1522  pSet=newhost->pSet;
1523  mpSet=NULL;
1524  pAttributes=newhost->pAttributes;
1525  mpAttributes=NULL;
1526  newhost->AttachClient(this);
1527  mpClients=NULL;
1528 #ifdef FAUDES_DEBUG_CODE
1529  DValid("PostRelink");
1530 #endif
1531  FD_DC("TBaseSet::RelinkClients(" << this << "): done")
1532 }
1533 
1534 
1535 // record fake copy
1536 TEMP inline void THIS::AttachClient(TBaseSet* pRef) const {
1537  if(!mpClients) const_cast< THIS* >(this)->mpClients=new std::list< TBaseSet<T,Cmp>* >;
1538  const_cast< THIS* >(this)->mpClients->push_back(pRef);
1539  pRef->mClientRecord= -- mpClients->end();
1540  const_cast< THIS* >(this)->mDetached=false;
1541 }
1542 
1543 // discard fake copy
1544 TEMP inline void THIS::DetachClient(TBaseSet* pRef) const {
1545  FD_DC("TBaseSet::DetachClient(" << this << "):" << pRef);
1546  // bail out on trivials
1547  if(!mpClients) return;
1548  if(mpClients->empty()) return;
1549  if(pRef->pHostSet!=this) return;
1550  // provide fake const
1551  THIS* fake_const = const_cast< THIS* >(this);
1552 #ifdef FAUDES_DEBUG_CODE
1553  // find and remove that client
1554  typename std::list< TBaseSet<T,Cmp>* >::iterator cit;
1555  bool cf=false;
1556  for(cit=fake_const->mpClients->begin(); cit!=fake_const->mpClients->end(); ++cit) {
1557  if(*cit==pRef) cf=true;
1558  }
1559  if(!cf) {
1560  FD_ERR("TBaseSet::DetachClient(" << this << "): client not found " << pRef);
1561  abort();
1562  }
1563 #endif
1564  /*
1565  use recorded client index: performant, and fine when last tested ...
1566  ... however, this really is asking for segfaults.
1567 
1568  // remove from client list
1569  FD_DC("TBaseSet::DetachClient(" << this << "):" << pRef << " must match " << *pRef->mClientRecord);
1570  fake_const->mpClients->erase(pRef->mClientRecord);
1571  */
1572  // remove from client list
1573  typename std::list< TBaseSet<T,Cmp>* >::iterator rit;
1574  for(rit=fake_const->mpClients->begin(); rit!=fake_const->mpClients->end(); ++rit) {
1575  if(*rit!=pRef) continue;
1576  fake_const->mpClients->erase(rit);
1577  break;
1578  }
1579  // figure detached status
1580  if(mpClients->empty() && (pSet!=&msEmptySet)) fake_const->mDetached=true;
1581  FD_DC("TBaseSet::DetachClient(" << this << "): done.");
1582 }
1583 
1584 
1585 // record an iterator
1586 TEMP inline void THIS::AttachIterator(Iterator* pFit) const {
1587  if(mLocked) return;
1588  FD_DC("TBaseSet::AttachIterator(" << this << "):" << pFit)
1589  const_cast< THIS* >(this)->mIterators.insert(pFit);
1590 }
1591 
1592 // discard an iterator
1593 TEMP inline void THIS::DetachIterator(Iterator* pFit) const {
1594  if(mLocked) return;
1595  FD_DC("TBaseSet::DetachIterator(" << this << "):" << pFit)
1596  const_cast< THIS* >(this)->mIterators.erase(pFit);
1597 }
1598 
1599 // test some validity
1600 TEMP void THIS::DValid(const std::string& rMessage) const {
1601  typename std::set< Iterator* >::const_iterator iit;
1602  typename std::list< THIS* >::const_iterator rit;
1603 #ifdef FAUDES_DEBUG_CONTAINER
1604  std::cerr << "TBaseSet(" << this << ")::DValid(): " << rMessage << " source "
1605  << pHostSet << " " << (pHostSet->pSet==&msEmptySet ? "+e+" : "+f+") <<
1606  (mLocked ? " +l+" : " ") << (mDetached ? " +d+" : " ") << " -- refs ";
1607  if(pHostSet->mpClients)
1608  for(rit=pHostSet->mpClients->begin(); rit!=pHostSet->mpClients->end(); ++rit)
1609  std::cerr << *rit << " ";
1610  std::cerr << "-- its ";
1611  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit)
1612  std::cerr << *iit << " ";
1613  std::cerr << "-- attr #" << pAttributes->size();
1614  if(mpAttributes) std::cerr << "(" << mpAttributes->size() << ") ";
1615  else std::cerr << " ";
1616  std::cerr << (pAttributes==&msEmptyAttributes ? "+e+ " : "+f+ ") << std::endl;
1617 #endif
1618  // iterators, that dont refer to me as basset
1619  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1620  if((*iit)->pBaseSet!=this) {
1621  FD_WARN("BaseSet("<< this << "," << rMessage <<"): invalid iterator (baseset): "<< *iit);
1622  abort();
1623  }
1624  }
1625  // iterators, that are not marked as attached
1626  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1627  if(!(*iit)->mAttached) {
1628  FD_WARN("BaseSet("<< this << "," << rMessage <<"): invalid iterator (attached): "<< *iit);
1629  abort();
1630  }
1631  }
1632  // iterators, that are invalid stl iterators
1633  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1634  typename std::set<T,Cmp>::const_iterator vit;
1635  for(vit=pSet->begin(); vit!= pSet->end(); ++vit) {
1636  if(vit==(**iit).StlIterator()) break;
1637  }
1638  if(vit!=(**iit).StlIterator()) { // end-iterator is fine, too
1639  FD_WARN("BaseSet("<< this << "," << rMessage <<"): invalid iterator (stl) "<< *iit);
1640  (**iit).StlIterator(pSet->end()); // fix invalid iterator to refer to end()
1641  abort(); // strict version: abort
1642  }
1643  }
1644  // must have some base
1645  if(pHostSet==NULL) {
1646  FD_WARN("BaseSet(" << this << "," << rMessage << "): no host found");
1647  abort();
1648  }
1649  // hosts mut be consistent
1650  if(pHostSet->pHostSet != pHostSet) {
1651  FD_WARN("BaseSet(" << this << "," << rMessage << "): inconsistent host");
1652  abort();
1653  }
1654  // refers to other base and own data
1655  if((mpSet!=NULL) && (pHostSet != this)) {
1656  FD_WARN("BaseSet(" << this << "," << rMessage << "): double data");
1657  abort();
1658  }
1659  // refers to other base and has references
1660  if(pHostSet!=this && mpClients!=NULL) {
1661  FD_WARN("BaseSet(" << this << "," << rMessage << "): cannot be client and have clients oneself");
1662  abort();
1663  }
1664  // refers to invalid base
1665  if(pHostSet->mpClients==NULL) {
1666  FD_WARN("BaseSet(" << this << "," << rMessage << "): refers to invalid host (a)");
1667  abort();
1668  }
1669  // refers to invalid base
1670  if(pHostSet!=this && pHostSet->mpClients->empty()) {
1671  FD_WARN("BaseSet(" << this << "," << rMessage << "): refers to invalid host (b)");
1672  abort();
1673  }
1674  // is base but has no own data
1675  if((pHostSet == this) && (mpSet==NULL) && (pSet!=&msEmptySet)) {
1676  FD_WARN("BaseSet(" << this << "," << rMessage << "): no data");
1677  abort();
1678  }
1679  // is base, but has no client list
1680  if((pHostSet==this) && (pSet!=&msEmptySet) && (mpClients==NULL)) {
1681  FD_WARN("BaseSet(" << this << "," << rMessage << "): host with no client list");
1682  abort();
1683  }
1684  // is base but own data pointer mismatch
1685  if((pHostSet == this) && (pSet != mpSet) && (pSet!=&msEmptySet)) {
1686  FD_WARN("BaseSet(" << this << "," << rMessage << "): data pointer mismatch A");
1687  abort();
1688  }
1689  // refers to base with data pointer mismatch
1690  if(pSet != pHostSet->pSet) {
1691  FD_WARN("BaseSet(" << this << "," << rMessage << "): data pointer mismatch B");
1692  abort();
1693  }
1694  // test all clients from hosts list
1695  bool hf=false;
1696  for(rit=pHostSet->mpClients->begin(); rit!=pHostSet->mpClients->end(); ++rit) {
1697  if((*rit)== this) hf=true;
1698  if((*rit)->pHostSet== pHostSet) continue;
1699  FD_WARN("BaseSet(" << this << "," << rMessage << "): invalid client " << (*rit));
1700  abort();
1701  }
1702  if(!hf && (pHostSet!=this)) {
1703  FD_WARN("BaseSet(" << this << "," << rMessage << "): client not registered with host");
1704  abort();
1705  }
1706  // refers to invalid base
1707  if(pHostSet!=this && *mClientRecord!=this) {
1708  FD_WARN("BaseSet(" << this << "," << rMessage << "): refers to invalid host (c)");
1709  abort();
1710  }
1711  // error in detached flag
1712  if(mDetached && mpClients==NULL) {
1713  FD_WARN("BaseSet(" << this << "," << rMessage << "): invalid detached flag A");
1714  abort();
1715  }
1716  // error in detached flag
1717  if(mDetached && !mpClients->empty()) {
1718  FD_WARN("BaseSet(" << this << "," << rMessage << "): invalid detached flag B");
1719  abort();
1720  }
1721  // error in detached flag
1722  if(mDetached && (pSet==&msEmptySet)) {
1723  FD_WARN("BaseSet(" << this << "," << rMessage << "): detached empty set");
1724  abort();
1725  }
1726  // error in lock flag
1727  if(mLocked && (mpClients==NULL)) {
1728  FD_WARN("BaseSet(" << this << "," << rMessage << "): locked reference (a)");
1729  abort();
1730  }
1731  // invalid emptyset
1732  if(!msEmptySet.empty()) {
1733  FD_WARN("BaseSet(" << this << "," << rMessage << "): invalid empty set");
1734  abort();
1735  }
1736  // invalid emptyset
1737  if(!msEmptyAttributes.empty()) {
1738  FD_WARN("BaseSet(" << this << "," << rMessage << "): invalid empty attributes");
1739  abort();
1740  }
1741 #ifdef FAUDES_DEBUG_CONTAINER
1742  std::cerr << "TBaseSet(" << this << ")::DValid(): passed" << std::endl;
1743 #endif
1744 }
1745 
1746 
1747 
1748 // Name
1749 TEMP const std::string& THIS::Name(void) const {
1750  return mMyName;
1751 }
1752 
1753 // Name
1754 TEMP void THIS::Name(const std::string& rName) {
1755  mMyName = rName;
1756 }
1757 
1758 
1759 // TypeDefinitionp()
1760 // Note: fake const construct
1761 TEMP const TypeDefinition* THIS::TypeDefinitionp(void) const {
1762  if(!pTypeDefinition) {
1763  // provide fake const
1764  THIS* fake_const = const_cast< THIS* >(this);
1765  fake_const->pTypeDefinition=TypeRegistry::G()->Definitionp(*this);
1766  }
1767  return pTypeDefinition;
1768 }
1769 
1770 // ElementTag
1771 TEMP const std::string& THIS::XElementTag(void) const {
1772  if(mXElementTag.empty()) {
1773  // provide fake const
1774  THIS* fake_const = const_cast< THIS* >(this);
1775  fake_const->mXElementTag="Element";
1776  const TypeDefinition* fdp=TypeDefinitionp();
1777  if(fdp) fake_const->mXElementTag=fdp->XElementTag();
1778  }
1779  return mXElementTag;
1780 }
1781 
1782 // ElementTag
1783 TEMP void THIS::XElementTag(const std::string& rTag) {
1784  mXElementTag=rTag;
1785 }
1786 
1787 
1788 // Faudes Type
1789 TEMP const std::string& THIS::TypeName(void) const {
1790  if(mFaudesTypeName.empty()) {
1791  // provide fake const
1792  THIS* fake_const = const_cast< THIS* >(this);
1793  const TypeDefinition* fdp=TypeDefinitionp();
1794  if(fdp) fake_const->mFaudesTypeName=fdp->Name();
1795  }
1796  return mFaudesTypeName;
1797 }
1798 
1799 // ElementTag
1800 TEMP void THIS::TypeName(const std::string& rType) {
1801  mFaudesTypeName=rType;
1802 }
1803 
1804 
1805 // Str
1806 TEMP std::string THIS::Str(const T& rElem) const {
1807  (void) rElem;
1808  std::string res="";
1809  return res;
1810 }
1811 
1812 // Size()
1813 TEMP Idx THIS::Size(void) const {
1814  return (Idx) pSet->size();
1815 }
1816 
1817 // Empty()
1818 TEMP bool THIS::Empty(void) const {
1819  return pSet->empty();
1820 }
1821 
1822 
1823 // DoWrite(tw,rLabel,cpntext)
1824 TEMP void THIS::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
1825  (void) pContext;
1826  std::string label=rLabel;
1827  if(label=="") label=Name();
1828  if(label=="") label="BaseSet";
1829  FD_DC("TBaseSet(" << this << ")::DoWrite(..): section " << label << " #" << Size());
1830  rTw.WriteBegin(label);
1831  rTw.WriteEnd(label);
1832 }
1833 
1834 
1835 // DoDWrite(tw, label, context)
1836 TEMP void THIS::DoDWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
1837  (void) pContext;
1838  (void) rLabel;
1839  BASE::DoSWrite(rTw);
1840  size_t shares=0;
1841  if(pHostSet->mpClients) shares=pHostSet->mpClients->size();
1842  rTw.WriteComment("");
1843  rTw.WriteComment(" Size/Attributes: " + ToStringInteger(this->Size())
1844  + "/" + ToStringInteger((Idx) pHostSet->pAttributes->size()));
1845  rTw.WriteComment(" Shares/Iterators: " + ToStringInteger((Idx) shares)
1846  + "/" + ToStringInteger((Idx) mIterators.size()));
1847  rTw.WriteComment("");
1848 #ifdef FAUDES_DEBUG_CODE
1849  DValid();
1850 #endif
1851 }
1852 
1853 // DoSWrite()
1854 TEMP void THIS::DoSWrite(TokenWriter& rTw) const {
1855  BASE::DoSWrite(rTw);
1856  size_t shares=0;
1857  if(pHostSet->mpClients) shares=pHostSet->mpClients->size();
1858  rTw.WriteComment(" Size: " + ToStringInteger(this->Size()));
1859  rTw.WriteComment(" Shared Data: #" + ToStringInteger((Idx) shares) + " clients");
1860  if(pAttributes->size()!=0)
1861  rTw.WriteComment(" Attributes: " +ToStringInteger((Idx) pAttributes->size()));
1862  if(pAttributes->size()!=0) {
1863  AttributeVoid* attr = pAttributes->begin()->second;
1864  rTw.WriteComment(" Attribute Type: " +FaudesTypeName(*attr));
1865  }
1866 }
1867 
1868 // DoRead(rTr, rLabel, pContext)
1869 TEMP void THIS::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
1870  (void) pContext;
1871  std::string label=rLabel;
1872  if(label=="") label=Name();
1873  if(label=="") label="BaseSet";
1874  Name(label);
1875  rTr.ReadBegin(label);
1876  rTr.ReadEnd(label);
1877 }
1878 
1879 // ThisIterator (tmoor 201308: this is by default an attached iterator)
1880 TEMP typename THIS::Iterator THIS::ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const {
1881  return Iterator(this,sit,true);
1882 }
1883 
1884 // Begin() const
1885 TEMP inline typename THIS::Iterator THIS::Begin(void) const {
1886  return ThisIterator(pSet->begin());
1887 }
1888 
1889 // End() const
1890 TEMP inline typename THIS::Iterator THIS::End(void) const {
1891  return ThisIterator(pSet->end());
1892 }
1893 
1894 
1895 //Clear
1896 TEMP void THIS::Clear(void) {
1897  FD_DC("TBaseSet(" << this << ")::Clear()");
1898 #ifdef FAUDES_DEBUG_CODE
1899  DValid("PreClear");
1900 #endif
1901  // special case: empty anyway
1902  if(pSet==&msEmptySet) return;
1903 
1904  FD_DC("TBaseSet(" << this << ")::Clear(): doit");
1905  FD_DC("TBaseSet(" << this << ")::Clear(): type " << typeid(*this).name());
1906  // special case: locked requires a copy (not efficient!)
1907  if(mLocked) Detach(SetOnly);
1908  // make someone else handle the data
1909  RelinkClients();
1910  pHostSet->DetachClient(this);
1911  // make myself host
1912  pHostSet=this;
1913  if(!mpClients) mpClients= new std::list< TBaseSet<T,Cmp>* >;
1914  mpClients->clear();
1915  // if we hold data, clear it
1916  if(mpSet) {
1917  delete mpSet;
1918  mpSet=NULL;
1919  }
1920  // if we hold data, clear it
1921  if(mpAttributes) {
1922  for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait) {
1923  FD_DC("TBaseSet(" << this << ")::Clear(): del attr " << ait->second);
1924  delete ait->second;
1925  }
1926  delete mpAttributes;
1927  mpAttributes=NULL;
1928  }
1929  // set to empty set
1930  pSet=&msEmptySet;
1931  pAttributes=&msEmptyAttributes;
1932  // fix iterators (invalidate)
1933  typename std::set< Iterator* >::iterator iit;
1934  for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
1935  (**iit).Invalidate();
1936  }
1937  mIterators.clear();
1938  mDetached=false;
1939  mLocked=false;
1940 #ifdef FAUDES_DEBUG_CODE
1941  DValid("PostClear");
1942 #endif
1943  FD_DC("TBaseSet(" << this << ")::Clear(): done");
1944 }
1945 
1946 
1947 //Valid(elem)
1948 TEMP inline bool THIS::Valid(const T& rElem) const {
1949  (void) rElem;
1950  return true;
1951 }
1952 
1953 //Insert(elem)
1954 TEMP bool THIS::Insert(const T& rElem) {
1955 #ifdef FAUDES_CHECKED
1956  if(!Valid(rElem)) {
1957  std::stringstream errstr;
1958  errstr << "refuse to insert invalid element" << std::endl;
1959  throw Exception("BaseSet::Insert", errstr.str(), 61);
1960  }
1961 #endif
1962  if(!mDetached) Detach();
1963  return pSet->insert(rElem).second;
1964 }
1965 
1966 //Inject(elem)
1967 TEMP typename THIS::Iterator THIS::Inject(const Iterator& pos, const T& rElem) {
1968  if(!mDetached) Detach();
1969  iterator dst= pos.StlIterator();
1970  return ThisIterator(pSet->insert(dst,rElem));
1971 }
1972 
1973 
1974 //Inject(elem)
1975 TEMP void THIS::Inject(const T& rElem) {
1976  if(!mDetached) Detach();
1977  pSet->insert(pSet->end(),rElem);
1978 }
1979 
1980 // InsertSet(set)
1981 TEMP void THIS::InsertSet(const TBaseSet& rOtherSet) {
1982  FD_DC("TBaseSet(" << this << ")::InsertSet(" << &rOtherSet << ")");
1983  if(!mDetached) Detach();
1984  /*
1985  rm: cannot use stl since result overlaps with arguments
1986 
1987  std::insert_iterator< std::set<T,Cmp> > insit(*pSet, rpSet->begin());
1988  std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
1989  */
1990  iterator it1 = pSet->begin();
1991  iterator it2 = rOtherSet.pSet->begin();
1992  while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
1993  if (*it1 < *it2) {
1994  ++it1;
1995  }
1996  else if (*it1 == *it2) {
1997  ++it1;
1998  ++it2;
1999  }
2000  else { // (*it1 > *it2)
2001  pSet->insert(*it2);
2002  ++it2;
2003  }
2004  }
2005  while (it2 != rOtherSet.pSet->end()) {
2006  pSet->insert(*it2);
2007  ++it2;
2008  }
2009 }
2010 
2011 
2012 //Erase(rElem)
2013 TEMP bool THIS::Erase(const T& rElem) {
2014  if(!mDetached) Detach();
2015  return (pSet->erase(rElem)!=0);
2016 }
2017 
2018 
2019 //Erase(pos)
2020 TEMP typename THIS::Iterator THIS::Erase(const Iterator& pos) {
2021 #ifdef FAUDES_CHECKED
2022  if (pos == End()) {
2023  std::stringstream errstr;
2024  errstr << "iterator out of range " << std::endl;
2025  throw Exception("BaseSet::Erase", errstr.str(), 62);
2026  }
2027 #endif
2028  Detach();
2029  iterator del= pos.StlIterator();
2030  pSet->erase(del++);
2031  return ThisIterator(del);
2032 }
2033 
2034 
2035 //EraseSet(set)
2036 TEMP void THIS::EraseSet(const TBaseSet& rOtherSet) {
2037  FD_DC("TBaseSet(" << this << ")::EraseSet(" << &rOtherSet << ")");
2038  if(!mDetached) Detach();
2039  // TODO: test and optimize
2040  iterator it = pSet->begin();
2041  iterator oit = rOtherSet.pSet->begin();
2042  while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
2043  if (*it < *oit) {
2044  it=pSet->lower_bound(*oit); // alt: ++it;
2045  }
2046  else if (*it == *oit) {
2047  ++oit;
2048  pSet->erase(it++);
2049  }
2050  else { // (*it > *oit)
2051  oit=rOtherSet.pSet->lower_bound(*it); // ++it2;
2052  }
2053  }
2054 }
2055 
2056 
2057 //RestrictSet(set)
2058 TEMP void THIS::RestrictSet(const TBaseSet& rOtherSet) {
2059  FD_DC("TBaseSet(" << this << ")::RestrictSet(" << &rOtherSet << ")");
2060  if(!mDetached) Detach();
2061  // TODO: test and optimize
2062  iterator it = pSet->begin();
2063  iterator oit = rOtherSet.pSet->begin();
2064  while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
2065  if (*it < *oit) {
2066  pSet->erase(it++);
2067  }
2068  else if (*it == *oit) {
2069  ++it;
2070  ++oit;
2071  }
2072  else { // (*it > *oit)
2073  oit=rOtherSet.pSet->lower_bound(*it);
2074  }
2075  }
2076  while(it != pSet->end()) {
2077  pSet->erase(it++);
2078  }
2079 }
2080 
2081 
2082 //Find(elem)
2083 TEMP typename THIS::Iterator THIS::Find(const T& rElem) const {
2084  return ThisIterator(pSet->find(rElem));
2085 }
2086 
2087 //Exists(elem)
2088 TEMP bool THIS::Exists(const T& rElem) const {
2089  return pSet->find(rElem) != pSet->end();
2090 }
2091 
2092 
2093 // operator+
2094 TEMP THIS THIS::operator+ (const TBaseSet& rOtherSet) const {
2095  TBaseSet res(*this);
2096  res.InsertSet(rOtherSet);
2097  return res;
2098 }
2099 
2100 // operator-
2101 TEMP THIS THIS::operator- (const TBaseSet& rOtherSet) const {
2102  TBaseSet res(*this);
2103  res.EraseSet(rOtherSet);
2104  return res;
2105 }
2106 
2107 
2108 // operator*
2109 TEMP THIS THIS::operator* (const TBaseSet& rOtherSet) const {
2110  TBaseSet res(*this);
2111  res.RestrictSet(rOtherSet);
2112  return res;
2113 }
2114 
2115 
2116 // operator==
2117 TEMP bool THIS::DoEqual(const TBaseSet& rOtherSet) const {
2118  FD_DC("TBaseSet::DoEqual()");
2119  // true if we share anyway
2120  if(pSet == rOtherSet.pSet) return true;
2121  // compare sets
2122  return ( *pSet == *rOtherSet.pSet );
2123 }
2124 
2125 // operator<=
2126 TEMP bool THIS::operator<= (const TBaseSet& rOtherSet) const {
2127  FD_DC("BaseSet::op<=()");
2128  return ( std::includes(rOtherSet.pSet->begin(), rOtherSet.pSet->end(), pSet->begin(), pSet->end()) ) ;
2129 }
2130 
2131 // operator>=
2132 TEMP bool THIS::operator>= (const TBaseSet& rOtherSet) const {
2133  FD_DC("BaseSet::op>=()");
2134  return ( std::includes(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end()) );
2135 }
2136 
2137 // operator<
2138 TEMP bool THIS::operator< (const TBaseSet& rOtherSet) const {
2139  return *pSet < *rOtherSet.pSet;
2140 }
2141 
2142 
2143 // attribute typeinfo
2144 TEMP const AttributeVoid* THIS::AttributeType(void) const {
2145  static AttributeVoid attr;
2146  return & attr;
2147 }
2148 
2149 // test attribute type
2150 TEMP bool THIS::AttributeTest(const Type& rAttr) const {
2151  return AttributeType()->Cast(&rAttr)!=NULL;
2152 }
2153 
2154 // number of attributes
2155 TEMP Idx THIS::AttributesSize(void) const {
2156  return (Idx) pAttributes->size();
2157 }
2158 
2159 // clear attributes
2160 TEMP void THIS::ClearAttributes(void) {
2161  // bail out if there are no attributes anyway
2162  if(this->pAttributes->size()==0) return;
2163  // detach (this will copy the set if required and return with empty attributes)
2164  this->Detach(SetOnly);
2165 }
2166 
2167 
2168 // Implement attributes: equality
2169 TEMP bool THIS::EqualAttributes(const TBaseSet<T,Cmp>& rOtherSet) const {
2170  FD_DC("TBaseSet::EqualAttributes(TBaseSet)");
2171  // false, if type does not match
2172  FD_DC("TBaseSet::EqualAttributes(TBaseSet): 1");
2173  if(typeid(*rOtherSet.AttributeType())!=typeid(*this->AttributeType()))
2174  return false;
2175  // true, if we share attribute data
2176  FD_DC("TBaseSet::EqualAttributes(TBaseSet): 2");
2177  if(pAttributes==rOtherSet.pAttributes)
2178  return true;
2179  // true if there are no attributes
2180  FD_DC("TBaseSet::EqualAttributes(TBaseSet): 3");
2181  if(rOtherSet.AttributesSize()==0)
2182  if(this->AttributesSize()==0)
2183  return true;
2184  // figure shared elements and test for equal attributes
2185  aiterator ait1 = pAttributes->begin();
2186  aiterator ait2 = rOtherSet.pAttributes->begin();
2187  while ((ait1 != pAttributes->end()) && (ait2 != rOtherSet.pAttributes->end())) {
2188  if (ait1->first < ait2->first) {
2189  ++ait1;
2190  }
2191  else if (ait1->first == ait2->first) {
2192  FD_DC("TBaseSet::EqualAttributes(TBaseSet): cmp " << ait1->second->ToString()
2193  << " vs " << ait2->second->ToString());
2194  if( ! ait1->second->Equal(*ait2->second)) return false;
2195  ++ait1;
2196  ++ait2;
2197  }
2198  else { // (*it1 > *it2)
2199  ++ait2;
2200  }
2201  }
2202  // passed
2203  FD_DC("TBaseSet::EqualAttributes(TBaseSet): pass");
2204  return true;
2205 }
2206 
2207 
2208 
2209 // public wrapper
2210 TEMP THIS& THIS::AssignWithoutAttributes(const TBaseSet<T,Cmp>& rSourceSet) {
2211  // call virtual (fake copy, will only copy attributes on type match)
2212  this->DoAssign(rSourceSet);
2213  // detach, effectively clears attributes
2214  this->Detach(SetOnly);
2215  return *this;
2216 }
2217 
2218 // set attribute wrapper
2219 TEMP void THIS::Attributes(const TBaseSet<T,Cmp>& rOtherSet) {
2220  FD_DC("TBaseSet::Attributes("<<this<<")");
2221  // type mismatch
2222  if(!this->AttributeTest(*rOtherSet.AttributeType())) {
2223  std::stringstream errstr;
2224  errstr << "cannot cast attribute " << std::endl;
2225  throw Exception("TBaseSet::Attributes(otherset)", errstr.str(), 63);
2226  }
2227  // can not hold attributes anyway
2228  if(typeid(*this->AttributeType())== typeid(const AttributeVoid)) return;
2229  // do assign
2230  this->Detach(AttrIncl);
2231  iterator it1 = pSet->begin();
2232  iterator it2 = rOtherSet.pSet->begin();
2233  while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
2234  if (*it1 < *it2) {
2235  ++it1;
2236  }
2237  else if (*it1 == *it2) {
2238  DoAttribute(*it1,&rOtherSet.Attribute(*it2));
2239  ++it1;
2240  ++it2;
2241  }
2242  else { // (*it1 > *it2)
2243  ++it2;
2244  }
2245  }
2246  FD_DC("TBaseSet::Attributes(): copy ok");
2247 }
2248 
2249 
2250 
2251 // attribute access
2252 TEMP AttributeVoid* THIS::Attributep(const T& rElem) {
2253  (void) rElem;
2254  std::stringstream errstr;
2255  errstr << "cannot get attribute for TBaseSet \"" << mMyName << "\" type " << typeid(*this).name();
2256  throw Exception("TBaseSet::Attributep(rElem)", errstr.str(), 63);
2257  // dummy: will through exception before
2258  static AttributeVoid attr;
2259  return &attr;
2260 }
2261 
2262 // attribute access
2263 TEMP const AttributeVoid& THIS::Attribute(const T& rElem) const {
2264  (void) rElem;
2265  static AttributeVoid attr;
2266  return attr;
2267 }
2268 
2269 // attribute access
2270 TEMP void THIS::Attribute(const T& rElem, const Type& rAttr) {
2271  (void) rElem;
2272  /* its pointless to test existence of the element since we wont set any attribute anyway */
2273 #ifdef FAUDES_CHECKED
2274  if (!Exists(rElem)) {
2275  std::stringstream errstr;
2276  errstr << "element not member of set" << std::endl;
2277  throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 60);
2278  }
2279 #endif
2280  if(!AttributeTest(rAttr)) {
2281  std::stringstream errstr;
2282  errstr << "cannot cast attribute " << std::endl;
2283  throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 63);
2284  }
2285  // passes test for all childs of AttributeVoid
2286 }
2287 
2288 
2289 // clr attributes wrapper
2290 TEMP void THIS::ClrAttribute(const T& rElem) {
2291  this->Detach();
2292  DoAttribute(rElem,(const AttributeVoid*) NULL);
2293 }
2294 
2295 
2296 // implement attributes: get pointer, NULL for implicit default
2297 TEMP const AttributeVoid* THIS::DoAttribute(const T& rElem) const {
2298  const_aiterator ait;
2299  ait=this->pAttributes->find(rElem);
2300  if(ait==this->pAttributes->end()) return NULL;
2301  return ait->second;
2302 }
2303 
2304 // implement attributes: get pointer (assume detached)
2305 TEMP AttributeVoid* THIS::DoAttributeExplicit(const T& rElem) {
2306  FD_DC("TBaseSet::DoAttributeExplicit(elem)");
2307 #ifdef FAUDES_DEBUG_CODE
2308  if(this->pAttributes!=this->::mpAttributes) {
2309  FD_ERR("TBaseSet::DoAttributeExplicit(elem): attributes not detached");
2310  abort();
2311  }
2312 #endif
2313  aiterator ait;
2314  ait=this->pAttributes->find(rElem);
2315  if(ait!=this->pAttributes->end())
2316  return ait->second;
2317  // instantiate explicit default
2318  AttributeVoid* attr = this->AttributeType()->Copy();
2319  FD_DC("TBaseSet::DoAttributeExplicit(Elem): inserting explicit default " << attr << " type " << typeid(*attr).name());
2320  (*this->pAttributes)[rElem]=attr;
2321  return attr;
2322 }
2323 
2324 // implement attributes: set (assume detached)
2325 TEMP void THIS::DoAttribute(const T& rElem, const Type* pAttr) {
2326  FD_DC("TBaseSet::DoAttribute([v] " << this->Str(rElem) << ", ...)");
2327 #ifdef FAUDES_DEBUG_CODE
2328  if(this->pAttributes!=this->mpAttributes) {
2329  FD_ERR("TBaseSet::DoAttribute([v] set): attributes not detached");
2330  abort();
2331  }
2332 #endif
2333  // type check new attribute
2334  const AttributeVoid* newattr=dynamic_cast<const AttributeVoid*>(pAttr);
2335  if(!this->AttributeType()->Cast(pAttr)) newattr=NULL;
2336  // find element in map
2337  aiterator ait;
2338  AttributeVoid* oldattr=NULL;
2339  ait=this->pAttributes->find(rElem);
2340  if(ait!=this->pAttributes->end() )
2341  oldattr=ait->second;
2342  // set to default, case 1
2343  if(newattr==NULL) {
2344  FD_DC("TBaseSet::DoAttribute([v] " << this->Str(rElem) << ", ...): default 1");
2345  if(oldattr==NULL) return;
2346  delete oldattr;
2347  this->pAttributes->erase(ait);
2348  return;
2349  }
2350  // set to default, case 2
2351  if(newattr->IsDefault()) {
2352  FD_DC("TBaseSet::DoAttribute([v] " << this->Str(rElem) << ", ...): default 2");
2353  if(oldattr==NULL) return;
2354  delete oldattr;
2355  this->pAttributes->erase(ait);
2356  return;
2357  }
2358  FD_DC("TBaseSet::DoAttribute([v] " << this->Str(rElem) << ", ...): " << newattr->ToString());
2359  // prepare attribute and set
2360  if(oldattr==NULL) {
2361  AttributeVoid* attr = this->AttributeType()->New();
2362  attr->Assign(*newattr);
2363  (*this->pAttributes)[rElem]=attr;
2364  return;
2365  }
2366  // plain set
2367  FD_DC("TBaseSet::DoAttribute([v] " << this->Str(rElem) << ", ...): " << newattr->ToString());
2368  oldattr->Assign(*newattr);
2369 }
2370 
2371 
2372 /* undefine local shortcuts */
2373 #undef THIS
2374 #undef TEMP
2375 #undef BASE
2376 
2377 /** @} doxygen group */
2378 
2379 } // namespace faudes
2380 
2381 #endif

libFAUDES 2.28a --- 2016.09.13 --- c++ api documentaion by doxygen