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

libFAUDES 2.26g --- 2015.08.17 --- c++ api documentaion by doxygen