libFAUDES

Sections

Index

cfl_baseset.h

Go to the documentation of this file.
00001 /** @file cfl_baseset.h @brief Class TBaseSet */
00002 
00003 
00004 /* FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2008  Thomas Moor
00007    Exclusive copyright is granted to Klaus Schmidt
00008 
00009    This library is free software; you can redistribute it and/or
00010    modify it under the terms of the GNU Lesser General Public
00011    License as published by the Free Software Foundation; either
00012    version 2.1 of the License, or (at your option) any later version.
00013 
00014    This library is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017    Lesser General Public License for more details.
00018 
00019    You should have received a copy of the GNU Lesser General Public
00020    License along with this library; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00022 
00023 
00024 
00025 #ifndef FAUDES_BASESET_H
00026 #define FAUDES_BASESET_H
00027 
00028 #include "cfl_definitions.h"
00029 #include "cfl_tokenwriter.h"
00030 #include "cfl_tokenreader.h"
00031 #include "cfl_registry.h"
00032 #include "cfl_types.h"
00033 #include "cfl_attributes.h"
00034 #include <set>
00035 #include <algorithm>
00036 
00037 namespace faudes {
00038 
00039 /** @addtogroup ContainerClasses */
00040 /** @{*/
00041 
00042 // Forward declaration for the attributed version of baseset
00043 template<class T, class Attr, class Cmp> class TaBaseSet;
00044 
00045 /**
00046  * STL style set template.
00047  * This class template is built on top of the STL set template. It provides essentials of 
00048  * the STL interface relevant to libFAUDES plus a deferred copy mechanism, aka copy-on-write. 
00049  * TBaseSet serves as a base class for all libFaudes containers: 
00050  * - IndexSet (indices), 
00051  * - TaIndexSet (indices with attributes), 
00052  * - SymbolSet (symbolic names), 
00053  * - NameSet (indices with symbolic names), 
00054  * - TaNameSet (indices with attributes and symbolic names), 
00055  * - TTransSet (transitions in a sepcific order),
00056  * - TaTransSet (transitions in std order with attribute).
00057  *
00058  * The public functions of a TBaseSet provide the high-level api, with the intention
00059  * to organize the deferred copy machanism in a transparent manner. Since STL iterators
00060  * refer to a particular STL container, they become invalid when the internal container 
00061  * is copied. Therefor, TBaseSet tracks iterators and fixes them when the actual copy takes place.
00062  * Clearly, this introduces some overhead, in particular when your application represents
00063  * subsets as sets of iterators. You may use the public method Lock() to enforce 
00064  * a full copy and to prevent any further re-allocation.
00065  *
00066  * Alternatively to the high-level api, a protected low-level api is provided with direct 
00067  * access to the internal STL set. When using this api, it is up to the derived class to ensure
00068  * that the BaseSet gets detached from its refernces befor write operations can take
00069  * place. 
00070  *
00071  * The virtual function TBaseSet<T>::Valid() is used to indicate whether a candidate
00072  * element is valid as a set member. If the macro FAUDES_CHECKED
00073  * is defined, the attempt to insert an invalid element triggers an exception (id 61). Invalid
00074  * iterators throw an exception (id 62) when used as an argument to a BaseSet function. 
00075  *
00076  * While the TBaseSet itself does not provide any attributes attached to its elements, it
00077  * does provide an interface to attributes implemented in derived classes. The implementation
00078  * of the interface behaves as if the attribute type was AttributeVoid. Thus, there is
00079  * a uniform access to attributes for all faudes container classes. The actual attribute
00080  * type can be detected via the C++ RTTI. 
00081  *
00082  * Note on a boring technical detail: 
00083  * since STL sets are sorted, effectively all set iterators should be const.
00084  * However, there is a minor issue whether or not the erase function should use a 
00085  * const iterator as argument. SGI derived STL implementations (as used on most GNU systems) 
00086  * avoid this issue by defining const and non-const iterators on sets as identical types. 
00087  * MS implementation (used in VS C++ by default) differ in this aspect. The class 
00088  * TBaseSet::Iterator hides the issue from the faudes API but it is still present internaly: 
00089  * in its current implementation, libfaudes will not compile with MS STL. At this stage we are 
00090  * aware of two workarounds, one simple but on cost of performance, one a little bit awkward. 
00091  * Let us know if MS STL is missioncrititical for your libfaudes application.
00092  *
00093  */
00094 
00095 template<class T, class Cmp=std::less<T> >
00096 class TBaseSet : public Type {
00097 
00098   FAUDES_TYPE_TDECLARATION(Void,TBaseSet,Type)
00099 
00100 public:
00101 
00102   /** 
00103    * We implement "protected privacy for template classes" by friendship.
00104    * This is used for the pragmatic implemention conversion constructors.
00105    */
00106   template<class TP, class AP, class CP> friend class TaBaseSet;
00107 
00108 
00109 
00110   /**
00111    * Constructor. 
00112    */
00113   TBaseSet(void);
00114 
00115   /**
00116    * Copy-constructor. 
00117    *
00118    * @param rOtherSet 
00119    *    Source to copy from
00120    */
00121   TBaseSet(const TBaseSet& rOtherSet);
00122 
00123   /**
00124    * Constructor from file.
00125    * This constructor indicates the intended interface for derived classes. The base set 
00126    * itself cannot read from token streams.
00127    *
00128    * @param rFilename
00129    *   Name of File
00130    * @param rLabel
00131    *   Section for the set in the file; 
00132    */
00133   TBaseSet(const std::string& rFilename, const std::string& rLabel = "BaseSet");
00134 
00135   /**
00136    * Virtual destructor
00137    */
00138   virtual ~TBaseSet(void);
00139 
00140   /** 
00141    * Return name of TBaseSet 
00142    * 
00143    * @return
00144    *   Name of TBaseSet
00145    */
00146   const std::string& Name(void) const;
00147         
00148   /**
00149    * Set name of TBaseSet
00150    *
00151    * @param rName
00152    *   Name to set
00153    */
00154   void Name(const std::string& rName);
00155 
00156   /** 
00157    * Clear all set
00158    */
00159   virtual void Clear(void);
00160       
00161   /**
00162    * Get Size of TBaseSet
00163    *
00164    * @return 
00165    *   Number of indices in TBaseSet
00166    */
00167   Idx Size(void) const;
00168 
00169   /** 
00170    * Check if the TBaseSet ist Empty 
00171    *
00172    * @return 
00173    *   True if empty
00174    */
00175   bool Empty(void) const;
00176 
00177   /**
00178    * Return pretty printable element. 
00179    * Reimplement this method for derived classes.
00180    *
00181    * @param rElem
00182    *   Element to print
00183    *
00184    * @return
00185    *   String
00186    */
00187   virtual std::string Str(const T& rElem) const;
00188 
00189   /** 
00190    * Iterator class for high-level api to TBaseSet.
00191    *
00192    */
00193   class Iterator;
00194 
00195   /** 
00196    * Iterator to the begin of set
00197    *
00198    * @return 
00199    *   Iterator
00200    */
00201   Iterator Begin(void) const;
00202         
00203   /** 
00204    * Iterator to the end of set
00205    *
00206    * @return 
00207    *   Iterator
00208    */
00209   Iterator End(void) const;
00210 
00211   /**
00212    * Test validty of candidate element.
00213    *
00214    * Reimplement this function for particular type T of elements,
00215    * eg for an index set with T=Idx indicate 0 an invalid index.
00216    *
00217    * @param rElem
00218    *    Candidate to test
00219    * @return
00220    *    True if element is valid
00221    */
00222   virtual bool Valid(const T& rElem) const;
00223    
00224 
00225   /** 
00226    * Erase element by reference
00227    *
00228    * @param rElem
00229    *    Element to erase
00230    * @return
00231    *    True if element used to exist
00232    */
00233   virtual bool Erase(const T& rElem);
00234 
00235 
00236   /** 
00237    * Erase element by iterator 
00238    *
00239    * @param pos
00240    *    Iterator to specify element
00241    * @return 
00242    *    Iterator to next element (or End if no such)
00243    */
00244   virtual Iterator Erase(const Iterator& pos); 
00245 
00246 
00247   /** 
00248    * Erase elements given by other set 
00249    *
00250    * @param rOtherSet 
00251    *    Set of elements to erase
00252    */
00253   virtual void EraseSet(const TBaseSet& rOtherSet);
00254 
00255   /** 
00256    * Restrict elements given by other set 
00257    *
00258    * @param rOtherSet 
00259    *    Set of elements to keep
00260    */
00261   virtual void RestrictSet(const TBaseSet& rOtherSet);
00262 
00263 
00264   /** 
00265    * Insert specified element
00266    *
00267    * @param rElem
00268    *    Element to insert
00269    * @return
00270    *   True if index was new to set 
00271    */
00272   virtual bool Insert(const T& rElem);
00273 
00274   /**
00275    * Insert elements given by rOtherSet 
00276    *
00277    *
00278    * @param rOtherSet
00279    *   Set of elements to insert
00280    */
00281   virtual void InsertSet(const TBaseSet& rOtherSet);
00282 
00283   /**
00284    * Set Union, result is accumulated in this set.
00285    *
00286    * @param rOtherSet
00287    *   Other TBaseSet
00288    */
00289   virtual void SetUnion(const TBaseSet& rOtherSet);
00290 
00291   /**
00292    * Set Intersection, result is stored in this set.
00293    * 
00294    * @param rOtherSet
00295    *   Other TBaseSet
00296    */
00297   virtual void SetIntersection(const TBaseSet& rOtherSet);
00298 
00299 
00300   /**
00301    * Test existence of element
00302    *
00303    * @param rElem
00304    *   Element to test
00305    *
00306    * @return 
00307    *   True if element exists in set
00308    */
00309   bool Exists(const T& rElem) const;
00310 
00311   /**
00312    * Find element and return iterator.
00313    *
00314    * @param rElem
00315    *   Element to find
00316    *
00317    * @return 
00318    *   Iterator to element or End() if nonexistent
00319    */
00320   Iterator Find(const T& rElem) const;
00321 
00322   /**
00323    * Set union operator
00324    *
00325    * @return 
00326    *   Union Set
00327    */
00328    TBaseSet operator+ (const TBaseSet& rOtherSet) const;
00329 
00330   /**
00331    * Set difference operator
00332    *
00333    * @return 
00334    *   Difference Set
00335    */
00336    TBaseSet operator- (const TBaseSet& rOtherSet) const;
00337 
00338   /**
00339    * Set intersection operator
00340    *
00341    * @return 
00342    *   Intersection Set
00343    */
00344   TBaseSet operator* (const TBaseSet& rOtherSet) const;
00345 
00346 
00347   /** Test for subset  */
00348   bool operator<= (const TBaseSet& rOtherSet) const;
00349 
00350   /** Test for superset */
00351   bool operator>= (const TBaseSet& rOtherSet) const;
00352 
00353   /** Order for sorting containers of TBaseSet */
00354   bool operator< (const TBaseSet& rOtherSet) const;
00355 
00356   /** Some validation of deferred copy mechanism (provoke abort)*/
00357   void DValid(const std::string& rMessage="") const;
00358 
00359   /** Detach from extern storage (incl allocation and true copy) */
00360   virtual void Detach(void) const;
00361 
00362   /** Detach and lock any further reallocation */
00363   virtual void Lock(void) const;
00364 
00365   /** 
00366    * Iterator class for high-level api to TBaseSet.
00367    * This class is derived from STL interators to additionally provide
00368    * a reference of the container to iterate on. This feature
00369    * is used to adjust iterators when the actual set gets reallocated due to a Detach()
00370    * operation. Inheritance is private to ensure that all high-level api functions maintain
00371    * iteretor refernces consistently. Currently, high-level api iterators support
00372    * the operators -&gt; ,*,  =, ++, --, ==, !=.
00373    * 
00374    * Technical detail: the private inheritance prohibits the direct use of stl algorithms on
00375    * faudes Iterators. If you need direct access to stl algorithms from outside the faudes set
00376    * class, you may turmn to public inheritance. Make sure to Lock the relevant sets befor
00377    * applying any stl algorithms.
00378    */
00379    class Iterator : private std::set<T,Cmp>::const_iterator {
00380      public: 
00381      /** Default constructor, container unknown */
00382      Iterator() : 
00383        std::set<T,Cmp>::const_iterator() , 
00384        pBaseSet(NULL),
00385        mAttached(false) 
00386      {};
00387 
00388      /** Construct by members, used by TBaseSet to create temporary iterators */
00389      Iterator(
00390        const TBaseSet<T,Cmp>* pBaseSet,
00391        const typename std::set<T,Cmp>::const_iterator& sit) : 
00392        std::set<T,Cmp>::const_iterator(sit), 
00393        pBaseSet(pBaseSet),
00394        mAttached(false)  
00395      {};
00396 
00397      /** Copy constructor, copies container reference, incl attach */
00398      Iterator(const Iterator& fit) : 
00399        std::set<T,Cmp>::const_iterator(fit),
00400        pBaseSet(fit.pBaseSet), 
00401        mAttached(false) 
00402      {
00403        if(pBaseSet) {
00404           pBaseSet->AttachIterator(this);
00405           mAttached=true;
00406        }
00407      };  
00408 
00409      /** Destructor */
00410      ~Iterator(void) { 
00411        if(mAttached) pBaseSet->DetachIterator(this);
00412      }; 
00413 
00414      /** Assigment, tracks container */
00415      const Iterator& operator= (const Iterator& rSrc) {
00416 #ifdef FAUDES_DEBUG_CODE
00417        if(rSrc.pBaseSet==NULL) {
00418          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator= invalid iterator: no baseset");
00419          abort();
00420        }
00421 #endif
00422        // performance relevant std case 
00423        if(mAttached) if(pBaseSet==rSrc.pBaseSet) {
00424          std::set<T,Cmp>::const_iterator::operator= (rSrc);
00425          return *this;
00426        }
00427        // general case
00428        if(mAttached) pBaseSet->DetachIterator(this);
00429        std::set<T,Cmp>::const_iterator::operator= (rSrc);
00430        pBaseSet = rSrc.pBaseSet;
00431        if(pBaseSet) {
00432          pBaseSet->AttachIterator(this);
00433          mAttached=true;
00434        } else {
00435   mAttached=false;
00436        }
00437        return *this;
00438      };
00439 
00440      /** Assign STL iterator only */
00441      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00442        std::set<T,Cmp>::const_iterator::operator= (sit);
00443      };
00444 
00445      /** Get STL iterator only */
00446      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00447        return *this;
00448      };
00449 
00450      /** Invalidate */
00451      void  Invalidate(void) {
00452        pBaseSet=NULL;
00453        mAttached=false;
00454      }; 
00455 
00456      /** Detach */
00457      void  Detach(void) {
00458        mAttached=false;
00459      }; 
00460 
00461 
00462      /** Check validity (provoke abort error) */
00463      void DValid(void) const {
00464       if(pBaseSet==NULL) {
00465          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):DValid(): invalid iterator: no baseset");
00466          abort();
00467        }
00468        pBaseSet->DValid();
00469      }; 
00470 
00471     /** Reimplement dereference */
00472      const T* operator-> (void) const {
00473 #ifdef FAUDES_DEBUG_CODE
00474        if(pBaseSet==NULL) {
00475          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator->: invalid iterator: no baseset");
00476          abort();
00477        }
00478 #endif
00479        return std::set<T,Cmp>::const_iterator::operator-> ();
00480      };
00481 
00482      /** Reimplement derefernce */
00483      const T& operator* (void) const {
00484 #ifdef FAUDES_DEBUG_CODE
00485        if(pBaseSet==NULL) {
00486          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator*: invalid iterator: no baseset");
00487          abort();
00488        }
00489 #endif
00490        return std::set<T,Cmp>::const_iterator::operator* ();
00491      };
00492 
00493      /** Reimplement == */
00494      bool operator== (const Iterator& rOther) const {
00495 #ifdef FAUDES_DEBUG_CODE
00496        if(pBaseSet==NULL) {
00497          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator==: invalid iterator: no baseset");
00498          abort();
00499        }
00500 #endif
00501        return std::set<T,Cmp>::const_iterator::operator== (rOther);
00502      };
00503 
00504      /** Reimplement != */
00505      bool operator!= (const Iterator& rOther) const {
00506 #ifdef FAUDES_DEBUG_CODE
00507        if(pBaseSet==NULL) {
00508          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator!=: invalid iterator: no baseset");
00509          abort();
00510        }
00511 #endif
00512        return std::set<T,Cmp>::const_iterator::operator!= (rOther);
00513      };
00514 
00515      /** Reimplement postfix ++ */
00516      Iterator operator++ (int step) {
00517 #ifdef FAUDES_DEBUG_CODE
00518        if(pBaseSet==NULL) {
00519          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00520          abort();
00521        }
00522 #endif
00523        Iterator old(pBaseSet,*this);
00524        std::set<T,Cmp>::const_iterator::operator++ (step);
00525        return old;
00526      };
00527 
00528      /** Reimplement prefix ++ */
00529      const Iterator& operator++ (void) {
00530 #ifdef FAUDES_DEBUG_CODE
00531        if(pBaseSet==NULL) {
00532          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00533          abort();
00534        }
00535 #endif
00536        std::set<T,Cmp>::const_iterator::operator++ ();
00537        return *this;
00538      };
00539 
00540      /** Reimplement postfix -- */
00541      Iterator operator-- (int step) {
00542 #ifdef FAUDES_DEBUG_CODE
00543        if(pBaseSet==NULL) {
00544          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00545          abort();
00546        }
00547 #endif
00548        Iterator old(pBaseSet, *this);
00549        std::set<T,Cmp>::const_iterator::operator-- (step);
00550        return old;
00551      };
00552 
00553      /** Reimplement prefix -- */
00554      const Iterator& operator-- (void) {
00555 #ifdef FAUDES_DEBUG_CODE
00556        if(pBaseSet==NULL) {
00557          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00558          abort();
00559        }
00560 #endif
00561        std::set<T,Cmp>::const_iterator::operator-- ();
00562        return *this;
00563      };
00564 
00565 
00566      /** Order by reference for containers of Iterators < */
00567      /*
00568      bool operator< (const Iterator& rOther) const {
00569        return this < &rOther;
00570      };
00571      */
00572 
00573      /** Maintaine container reference */
00574      const TBaseSet<T,Cmp>* pBaseSet;
00575 
00576      /** Indocate that this iterator is attached to some baseset */
00577      bool mAttached;
00578    };
00579 
00580 #ifdef DONT_TRACK_REFERENCES
00581 
00582   /** 
00583    * Iterator class for high-level api to TBaseSet.
00584    * This version is a dummy and does not provide any additional features.
00585    */
00586    class Iterator : public std::set<T,Cmp>::const_iterator {
00587      public:
00588 
00589      /** Default contructor */
00590      Iterator(void) : 
00591        std::set<T,Cmp>::const_iterator()  
00592      {}; 
00593 
00594      /** Copy constructor  */
00595      Iterator(const Iterator& fit) : 
00596        std::set<T,Cmp>::const_iterator(fit)
00597      {};
00598 
00599      /** Copy constructor  */
00600      Iterator(const typename std::set<T,Cmp>::const_iterator& sit) : 
00601        std::set<T,Cmp>::const_iterator(sit)
00602      {};
00603 
00604      /** Copy constructor, compatibility  */
00605      Iterator(
00606        const TBaseSet<T,Cmp>* pBaseSet,
00607        const typename std::set<T,Cmp>::const_iterator& sit) : 
00608        std::set<T,Cmp>::const_iterator(sit) 
00609      {};
00610 
00611      /** Assign STL iterator only, compatibility */
00612      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00613        std::set<T,Cmp>::const_iterator::operator= (sit);
00614      }; 
00615 
00616      /** Get STL iterator only, compatibility */
00617      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00618        return *this;
00619      };
00620 
00621      /** Invalidate, compatibility */
00622      void  Invalidate(void) {};
00623 
00624    };
00625 
00626 #endif
00627 
00628   /** 
00629    * Attribute typeinfo.
00630    * This virtual function provides an interface for derived container classes with attributes 
00631    * eg TaIndexSet. When not re-implemented, it returns an attribute with type AttributeVoid to
00632    * indicate the absence of nontrivial attributes
00633    */
00634   virtual const AttributeVoid* Attributep(void) const;
00635 
00636   /** 
00637    * Attribute typeinfo.
00638    * This virtual function provides an interface for derived container classes with attributes 
00639    * eg TaIndexSet. When not re-implemented, it returns an attribute with type AttributeVoid to
00640    */
00641   virtual const AttributeVoid& Attribute(void) const;
00642 
00643   /** 
00644    * Attribute typeinfo.
00645    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00646    * It is meant to test whether this set accepts the specified attribute type ie whether it can be casted.
00647    * When not re-implemented, the set accepts any attributes derived from attribute void.
00648    * @param rAttr
00649    *     Attribute type to test.
00650    * @return True, if attribute type is accepted.
00651    */
00652   virtual bool AttributeTry(const Type& rAttr) const {return dynamic_cast< const AttributeVoid* >(&rAttr)!=0;};
00653 
00654   /**
00655    * Attribute access.
00656    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00657    * It is meant to ignore any attributes. The TBaseSet itself has no attributes, so it calls its
00658    * Assign method that ignores attributes anyway.
00659    *
00660    * @param rSourceSet 
00661    *    Set to copy from
00662    */
00663    virtual TBaseSet& AssignWithoutAttributes(const TBaseSet& rSourceSet) { return TBaseSet::Assign(rSourceSet); };
00664 
00665   /**
00666    * Attributes access. 
00667    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00668    * It is meant to copy attributes from the specified set.
00669    * The TBaseSet itself has no attributes and thus this function does nothing.
00670    *
00671    * @param rOtherSet
00672    *   Other BaseSet
00673    */
00674   virtual void Attributes(const TBaseSet& rOtherSet) { (void) rOtherSet; };
00675 
00676 
00677   /** 
00678    * Attribute access.
00679    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00680    * It is meant to provide the number of explicit attributes.
00681    * The TBaseSet itself has no attributes and thus this function returns 0.
00682    */
00683   virtual Idx AttributesSize(void) const { return 0; };
00684 
00685   /** 
00686    * Attribute access.
00687    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00688    * The TBaseSet itself has no attributes and thus this function does nothing.
00689    */
00690   virtual void ClearAttributes(void) { };
00691 
00692   /**
00693    * Attribute access.
00694    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00695    * Derived classes that provide attributes are meant to return true if attributes
00696    * match for shared elements. The base set returns true as a default.
00697    * @param rOtherSet 
00698    *    Other object to compare with.
00699    * @return 
00700    *   True on match.
00701    */
00702   virtual bool EqualAttributes(const TBaseSet& rOtherSet) const { 
00703     return typeid(*rOtherSet.Attributep())==typeid(const AttributeVoid);};
00704 
00705   /** 
00706    * Attribute access.
00707    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00708    * The TBaseSet has no attributes and thus throws an exception. 
00709    * Derived classes that provide attributes are meant to return a pointer to the attribute specified by rElem.
00710    *
00711    * @param rElem
00712    *     Element of which the attribute is requested
00713    * @return 
00714    *     Attribute of specified element
00715    * @exception Exception
00716    *   - No attributes provided (id 63)
00717    */
00718   virtual AttributeVoid* Attributep(const T& rElem);
00719 
00720   /** 
00721    * Attribute access.
00722    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00723    * The TBaseSet has no attributes and thus returns a void attribute.
00724    * Derived classes that provide attributes are meant to return the attribute specified by rElem.
00725    * @param rElem
00726    *     Element of which the attribute is requested
00727    * @return 
00728    *     Attribute of specified element
00729    */
00730   virtual const AttributeVoid& Attribute(const T& rElem) const;
00731 
00732   /** 
00733    * Attribute access.
00734    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00735    * The TBaseSet itself has void attributes and thus formally accepts any nontrivial attribute, 
00736    * however, ignoring any value.
00737    * Derived classes that provide attributes are meant to set the attribute as specified. Only if the
00738    * required cast to the actual attribute type fails an exception is thrown.
00739    * @param rElem
00740    *     Element of which the attribute is to be set
00741    * @param rAttr
00742    *     Attribute value to set.
00743    * @exception Exception
00744    *   - Element does not exist (60)
00745    *   - Cannot cast attribute type (63)
00746    */
00747   virtual void Attribute(const T& rElem, const Type& rAttr);
00748 
00749   /** 
00750    * Attribute access.
00751    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00752    * It is meant to try to set the attribute as specified if the type can be casted. Otherwise it does nothing.
00753    * @param rElem
00754    *     Element of which the attribute is to be set
00755    * @param rAttr
00756    *     Attribute value to set.
00757    */
00758    virtual void AttributeTry(const T& rElem, const Type& rAttr) { (void) rElem; (void) rAttr; };
00759 
00760   /** 
00761    * Attribute access.
00762    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00763    * It is meant to set the attribute of the specified element to the default value.
00764    * The TBaseSet itself has no attributes and thus this function does nothing.
00765    * @param rElem
00766    *     Element of which the attribute is to be cleared
00767    */
00768    virtual void ClrAttribute(const T& rElem) { (void) rElem; };
00769 
00770 
00771 
00772 protected:
00773 
00774 
00775   /** 
00776    * Token output, see Type::DWrite for public wrappers.
00777    * Reimplement this function in derived classes for specific
00778    * specific template parameters. By convention, the default label ""
00779    * should be translated to a) the name of the set or b) some meaningful default, 
00780    * eg "IndexSet" for a set of indices. The pContext pointer can de type-checked
00781    * and interpreted, ie as a symboltable to provide symbolic names. It is also
00782    * passed on to attributes.
00783    *
00784    * @param rTw
00785    *   Reference to TokenWriter
00786    * @param rLabel
00787    *   Label of section to write, defaults to name of set
00788    * @param pContext
00789    *   Write context to provide contextual information
00790    */
00791   virtual void DoWrite(TokenWriter& rTw, const std::string& rLabel="", const Type* pContext=0) const;
00792 
00793   /** 
00794    * Token output, debugging see Type::DWrite for public wrappers.
00795    * Reimplement this function in derived classes for specific
00796    * specific template parameters.
00797    * @param rTw
00798    *   Reference to TokenWriter
00799    * @param rLabel
00800    *   Label of section to write, defaults to name of set
00801    * @param pContext
00802    *   Write context to provide contextual information
00803    */
00804   virtual void DoDWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const;
00805 
00806   /** 
00807    * Token output, see Type::SWrite for public wrappers.
00808    * Statistics include size, name and attributey type. The latter
00809    * is retrieved from the RTI, if initialized. Dereived sets may reimplement
00810    * this method.
00811    *
00812    * @param rTw
00813    *   Reference to TokenWriter
00814    */
00815   virtual void DoSWrite(TokenWriter& rTw) const;
00816 
00817   /**
00818    * Token input, see Type::Read for public wrappers.
00819    * Reimplement this function in derived classes for specific
00820    * specific template parameters.
00821    * By convention, the default label "" should be translated to some meaningful default, 
00822    * eg "IndexSet" for a set of indices". The pContext pointer can de type-checked
00823    * and interpreted, ie as a symboltable to provide symbolic names. It is also
00824    * passed on to attributes.
00825    *
00826    * @param rTr
00827    *   Reference to TokenReader
00828    * @param rLabel
00829    *   Label of section to read, defaults to name of set
00830    * @param pContext
00831    *   Read context to provide contextual information
00832    */
00833   virtual void DoRead(TokenReader& rTr, const std::string& rLabel = "", const Type* pContext=0);
00834 
00835   /** assign my members */
00836   virtual void DoAssign(const TBaseSet& rSourceSet);
00837 
00838   /** test equality */
00839   virtual bool DoEqual(const TBaseSet& rOtherSet) const;
00840 
00841   /** STL set, if the object owns content (else NULL) */
00842   std::set<T,Cmp>* mpSet;
00843 
00844   /** Attribute map, if this object owns content (else NULL). */
00845   std::map<T,AttributeVoid*>* mpAttributes;
00846 
00847   /** static empty STL set for default constructor */
00848   static std::set<T,Cmp> mEmptySet;
00849 
00850   /** static empty STL map for default constructor */
00851   static std::map<T,AttributeVoid*> mEmptyAttributes;
00852 
00853   /** Pointer on STL set to operate on */
00854   std::set<T,Cmp>* pSet;
00855 
00856   /** Pointer to attribute map to operate on */
00857   std::map<T,AttributeVoid*>* pAttributes;
00858 
00859   /** STL iterator, non-const version */
00860   typedef typename std::set<T,Cmp>::iterator iterator;
00861 
00862   /** STL iterator, const version */
00863   typedef typename std::set<T,Cmp>::const_iterator const_iterator;
00864 
00865   /** Convert STL iterator */
00866   typename TBaseSet<T,Cmp>::Iterator ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const;
00867 
00868   /** STL attribute iterator, non-const version */
00869   typedef typename std::map<T,AttributeVoid*>::iterator aiterator;
00870 
00871   /** STL attribute iterator, const version */
00872   typedef typename std::map<T,AttributeVoid*>::const_iterator const_aiterator;
00873 
00874 
00875 protected:
00876 
00877 
00878   /** Name of TBaseSet */
00879   std::string mMyName;
00880 
00881   /** Other BaseSets, that refer to the STL set provided by this TBaseSet */
00882   std::set< TBaseSet<T,Cmp>* > mReferences;
00883 
00884   /** Pointer on BaseSet that owns the STL set this BaseSet referrs to */
00885   TBaseSet<T,Cmp>* pBaseSet;
00886 
00887   /** Indicate "has no references, provides STL set" */
00888   bool mDetached;
00889 
00890   /** Indicate "dont re-allocate the STL set again" */
00891   bool mLocked;
00892 
00893   /** Ensure that we do not serve contents to anyone else */
00894   void RelinkReferences(void);
00895 
00896   /** Record that we serve contents to some other TBaseSet */
00897   void AttachReference(TBaseSet* pRef) const;
00898 
00899   /** Record that we stop serving contents to some TBaseSet */
00900   void DetachReference(TBaseSet* pRef) const;
00901 
00902   /** Iterators that refer to this TBaseSet */
00903   std::set< Iterator* > mIterators;
00904 
00905   /** Record that an iterator refers to this TBaseSet */
00906   void AttachIterator(Iterator* pFit) const;
00907 
00908   /** Record that an iterator stops to refer to this TBaseSet */
00909   void DetachIterator(Iterator* pFit) const;
00910 
00911   /** Implementation of union */
00912   void FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00913 
00914   /** Implementation of difference */
00915   void FnctDifference(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00916 
00917   /** Implementation of intersection */
00918   void FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00919 
00920   /** TypeDefinition cache (should use guarded pointer here) */
00921   /** 
00922    * Note: - we should use guarded pointers here
00923    *       - only registered types are caches 
00924    */
00925   const TypeDefinition* pTypeDefinition;
00926 
00927   /** Reimplment from type type to use chache */
00928   virtual const TypeDefinition* TypeDefinitionp(void) const;
00929 
00930   /** Reimplment from faudes type to use chache */
00931   virtual const std::string& TypeName(void) const;
00932 
00933   /** Name of elements (used for XML IO) */
00934   virtual const std::string& XElementTag(void) const;
00935 
00936 };
00937 
00938 
00939 
00940 /* 
00941  * Set union, rti wrapper
00942  *
00943  * @param rSetA
00944  *  Set A
00945  * @param rSetB
00946  *  Set B
00947  * @return
00948  *  Union of set A and set B
00949  */
00950 
00951 template<class T, class Cmp>
00952 void SetUnion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
00953   FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): res at " << &rRes);
00954   // fix name
00955   std::string name=CollapsString(rSetA.Name() + "+" + rSetB.Name());
00956   // all the same
00957   if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
00958   // a and b ths same, res different
00959   if(&rSetA==&rSetB) {rRes.Assign(rSetA); rRes.Name(name); return;}
00960   // a and res the same, b different 
00961   if(&rSetA==&rRes) {rRes.InsertSet(rSetB); rRes.Name(name); return;};
00962   // b and res the same, a different 
00963   if(&rSetB==&rRes) {rRes.InsertSet(rSetA); rRes.Name(name); return;};
00964   // else
00965   rRes.Assign(rSetA);
00966   rRes.InsertSet(rSetB);
00967   rRes.Name(name); 
00968   FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): done, res at " << &rRes << " #" << rRes.Size());
00969 }
00970 
00971 /* 
00972  * Set intersection, rti wrapper
00973  *
00974  * @param rSetA
00975  *  Set A
00976  * @param rSetB
00977  *  Set B
00978  * @return
00979  *  Set A intersected with set B
00980  */
00981 template< class T, class Cmp >
00982 void SetIntersection(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
00983   // fix name
00984   std::string name=CollapsString(rSetA.Name() + "*" + rSetB.Name());
00985   // all the same
00986   if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
00987   // a and b ths ame, res different
00988   if(&rSetA==&rSetB) { rRes.Assign(rSetA); rRes.Name(name); return;}
00989   // a and res the same, b different 
00990   if(&rSetA==&rRes) {rRes.RestrictSet(rSetB); rRes.Name(name); return;};
00991   // b and res the same, a different 
00992   if(&rSetB==&rRes) {rRes.RestrictSet(rSetA); rRes.Name(name); return;};
00993   // else
00994   rRes.Assign(rSetA);
00995   rRes.RestrictSet(rSetB);
00996   rRes.Name(name); 
00997 }
00998 
00999 
01000 /* 
01001  * Set difference, rti wrapper
01002  *
01003  * @param rSetA
01004  *  Set A
01005  * @param rSetB
01006  *  Set B
01007  * @return
01008  *  Set A minus set B
01009  */
01010 template< class T, class Cmp >
01011 void SetDifference(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
01012   // fix name
01013   std::string name=CollapsString(rSetA.Name() + "-" + rSetB.Name());
01014   // a and b the same
01015   if(&rSetA==&rSetB) { rRes.Clear(); rRes.Name(name); return;}
01016   // a and res the same, b different 
01017   if(&rSetA==&rRes) {rRes.EraseSet(rSetB); rRes.Name(name); return;};
01018   // b and res the same, a different ... need buffer?
01019   if(&rSetB==&rRes) {
01020     TBaseSet<T,Cmp>* buffb=rSetB.Copy();
01021     rRes.Assign(rSetA);
01022     rRes.EraseSet(*buffb); 
01023     rRes.Name(name); 
01024     delete buffb;
01025     return;
01026   }; 
01027   // else: std
01028   rRes.Assign(rSetA);
01029   rRes.EraseSet(rSetB);
01030   rRes.Name(name); 
01031 }
01032 
01033 /* 
01034  * Set equality, rti wrapper
01035  * This method ignores attributes.
01036  *
01037  * @param rSetA
01038  *  Set A
01039  * @param rSetB
01040  *  Set B
01041  * @return
01042  *  True for matching sets.
01043  */
01044 template< class T, class Cmp >
01045 bool SetEquality(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
01046   return rSetA==rSetB;
01047 }
01048 
01049 /* 
01050  * Set inclusion, rti wrapper
01051  * This method ignores attributes.
01052  *
01053  * @param rSetA
01054  *  Set A
01055  * @param rSetB
01056  *  Set B
01057  * @return
01058  *  True for matching sets.
01059  */
01060 template< class T, class Cmp >
01061 bool SetInclusion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
01062   return rSetA<=rSetB;
01063 }
01064 
01065 
01066 
01067 
01068 /** @} doxygen group */
01069 
01070 
01071 
01072 /*
01073 ******************************************************************************************
01074 ******************************************************************************************
01075 ******************************************************************************************
01076 
01077 Implementation of TBaseSet
01078 
01079 ******************************************************************************************
01080 ******************************************************************************************
01081 ******************************************************************************************
01082 */
01083 
01084 /* convenience access to relevant scopes */
01085 #define THIS TBaseSet<T,Cmp> 
01086 #define TEMP template<class T, class Cmp>
01087 #define BASE Type
01088 
01089 
01090 // faudes type std: new and cast
01091 FAUDES_TYPE_TIMPLEMENTATION_NEW(Void,THIS,Type,TEMP)
01092 FAUDES_TYPE_TIMPLEMENTATION_COPY(Void,THIS,Type,TEMP)
01093 FAUDES_TYPE_TIMPLEMENTATION_CAST(Void,THIS,Type,TEMP)
01094 
01095 // faudes type std: assignemnt (break cast)
01096 //TEMP THIS& THIS::Assign(const Type& rSrc) { this->Clear(); return *this;};
01097 //TEMP THIS& THIS::Assign(const THIS& rSrc) { DoAssign(rSrc); return *this;};
01098 
01099 // faudes type std: assignemnt (keep cast)
01100 FAUDES_TYPE_TIMPLEMENTATION_ASSIGN(Void,THIS,Type,TEMP)
01101 FAUDES_TYPE_TIMPLEMENTATION_EQUAL(Void,THIS,Type,TEMP)
01102 
01103 
01104 // template statics: empty set
01105 TEMP std::set<T,Cmp>  THIS::mEmptySet=std::set<T,Cmp>();
01106 TEMP std::map<T,AttributeVoid*> THIS::mEmptyAttributes=std::map<T,AttributeVoid*>();
01107 
01108 // TBaseSet()
01109 TEMP THIS::TBaseSet(void) :
01110   Type(),
01111   mpSet(NULL),
01112   mpAttributes(NULL),
01113   pSet(&mEmptySet),  
01114   pAttributes(&mEmptyAttributes),
01115   pBaseSet(this),
01116   mDetached(false), 
01117   mLocked(false),
01118   pTypeDefinition(NULL)
01119 {
01120   FAUDES_OBJCOUNT_INC("BaseSet");
01121   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
01122   // other members
01123   mMyName="BaseSet";
01124 }
01125 
01126 // TBaseSet(filename)
01127 TEMP THIS::TBaseSet(const std::string& rFileName, const std::string& rLabel)  :
01128   Type(),
01129   mpSet(NULL),
01130   mpAttributes(NULL),
01131   pSet(&mEmptySet),  
01132   pAttributes(&mEmptyAttributes),
01133   pBaseSet(this),
01134   mDetached(false), 
01135   mLocked(false), 
01136   pTypeDefinition(NULL)
01137 {
01138   FAUDES_OBJCOUNT_INC("BaseSet");
01139   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
01140   // other members
01141   mMyName="BaseSet";
01142   // do read etc ... this is a dummy anyway
01143   Read(rFileName,rLabel);  
01144 }
01145 
01146 // TBaseSet(rOtherSet)
01147 TEMP THIS::TBaseSet(const TBaseSet& rOtherSet) : 
01148   Type(rOtherSet),
01149   mpSet(NULL),
01150   mpAttributes(NULL),
01151   pSet(NULL),  
01152   pAttributes(NULL),
01153   pBaseSet(this),
01154   mDetached(false), 
01155   mLocked(false),
01156   pTypeDefinition(NULL)
01157 {
01158   FAUDES_OBJCOUNT_INC("BaseSet");
01159   FD_DC("TBaseSet(" << this << ")::TBaseSet(rOtherSet " << &rOtherSet << "): fake copy construct");
01160   // maintain deferred copy 
01161   pBaseSet=rOtherSet.pBaseSet;
01162   pBaseSet->AttachReference(this);
01163   pSet=rOtherSet.pSet;
01164   pAttributes=&mEmptyAttributes;
01165   // other members
01166   mMyName=rOtherSet.mMyName;
01167 #ifdef FAUDES_DEBUG_CONTAINER
01168   DValid();
01169 #endif
01170 }
01171 
01172 // destructor
01173 TEMP THIS::~TBaseSet(void) {
01174   FAUDES_OBJCOUNT_DEC("BaseSet");
01175   FD_DC("TBaseSet(" << this << ")::~TBaseSet()");
01176   // maintain deferred copy 
01177   RelinkReferences();
01178   pBaseSet->DetachReference(this);
01179   // unlink iterators (mandatory, since referenced object will be destructed)
01180   typename std::set< Iterator* >::const_iterator iit;
01181   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01182     (**iit).Invalidate();
01183   }
01184   // delete if we still own data
01185   if(mpSet) delete mpSet;
01186   if(mpAttributes) {
01187     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01188        delete ait->second;
01189     delete mpAttributes;
01190   }
01191 }
01192 
01193 
01194 // fake copy
01195 TEMP void THIS::DoAssign(const THIS& rSourceSet) {
01196   FD_DC("TBaseSet(" << this << ")::DoAssign(rOtherSet " << &rSourceSet << "): fake copy");
01197   // bail out on selfref
01198   if(this==&rSourceSet) return;
01199   // other members 
01200   mMyName=rSourceSet.mMyName;
01201   // bail out on common shared data
01202   if(pBaseSet==rSourceSet.pBaseSet) return;
01203   // become independant
01204   RelinkReferences();
01205   pBaseSet->DetachReference(this);
01206   mReferences.clear();
01207   // if we are locked, should do the copy ... not implemented
01208 #ifdef FAUDES_DEBUG_CONTAINER
01209   if(mLocked) {
01210     FD_DC("TBaseSet::DoAssign(): locked target will be unlocked");
01211   }
01212 #endif
01213   // attatch myself to src
01214   pBaseSet=rSourceSet.pBaseSet;
01215   pBaseSet->AttachReference(this);
01216   pSet=rSourceSet.pSet;
01217   pAttributes=&mEmptyAttributes;
01218   // delete own old data
01219   if(mpSet) { 
01220      delete mpSet;
01221      mpSet=NULL;
01222   }
01223   if(mpAttributes) {
01224     delete mpAttributes;
01225     mpAttributes=NULL;
01226   }
01227   // record state
01228   mDetached=false; 
01229   mLocked=false;
01230   // fix iterators (invalidate)
01231   typename std::set< Iterator* >::iterator iit;
01232   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01233     (**iit).Invalidate();
01234   }
01235   mIterators.clear();
01236 #ifdef FAUDES_DEBUG_CONTAINER
01237   DValid();
01238 #endif
01239 }
01240 
01241 // Detach()
01242 TEMP void THIS::Detach(void) const {
01243   FD_DC("TBaseSet(" << this << ")::Detach(void)");
01244 #ifdef FAUDES_DEBUG_CONTAINER
01245   DValid();
01246 #endif
01247 
01248   // nothing todo
01249   if(mDetached) return;
01250 
01251   // provide fake const
01252   THIS* fake_const = const_cast< THIS* >(this);
01253 
01254   // might have overseen reference detach
01255   if(pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL) {
01256     fake_const->mDetached=true;
01257     return;
01258   }
01259 
01260   // stragie A: references get the copy; thus, the baseset data does
01261   // not get reallocated and we dont need to track iterators. on the
01262   // downside, fixing the references iterators may be more effort.
01263   if(mLocked==true) {
01264    
01265     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie A");
01266     // do allocation and copy of stl set
01267     std::set<T,Cmp>* scopy = new std::set<T,Cmp>();
01268     *scopy = *pSet;     
01269     // first of my reference gets the new data and the old attributes
01270     THIS* storage = *mReferences.begin();
01271     storage->pBaseSet=storage;
01272     storage->mpSet=scopy; 
01273     storage->pSet=scopy;
01274     storage->mpAttributes=mpAttributes;
01275     storage->pAttributes=pAttributes;
01276     storage->mReferences=mReferences;
01277     storage->DetachReference(storage);
01278     // check whether new storage is detached
01279     if(storage->mReferences.empty()) 
01280        storage->mDetached=true;
01281     // set other users to new storage
01282     typename std::set< THIS* >::const_iterator rit;
01283     for(rit=mReferences.begin(), ++rit ;rit!=mReferences.end(); ++rit) {
01284       (*rit)->pBaseSet=storage;
01285       (*rit)->pSet=storage->pSet;
01286       (*rit)->pAttributes=storage->pAttributes;
01287     }
01288     // fix other users iterators (incl new storage)
01289     for(rit=mReferences.begin(); rit!=mReferences.end(); ++rit) {
01290       typename std::set< Iterator* >::iterator iit;
01291       for(iit=(*rit)->mIterators.begin(); iit!=(*rit)->mIterators.end(); ++iit) {
01292         if((**iit).StlIterator()==pSet->end()) 
01293           **iit=Iterator(this, scopy->end());
01294         else
01295           **iit=Iterator(this, scopy->find(***iit));
01296       }
01297     }
01298     // make myself own the old data and have empty attributes
01299     fake_const->mpSet=pSet;
01300     fake_const->mpAttributes=NULL;
01301     fake_const->pAttributes=&mEmptyAttributes;
01302     fake_const->mReferences.clear();
01303     fake_const->mDetached=true;    
01304     // stop tracking iterators
01305     typename std::set< Iterator* >::const_iterator iit;
01306     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01307       (**iit).Detach();
01308     }
01309     fake_const->mIterators.clear();
01310 
01311 
01312   // stragie B: this baseset gets the copy; thus, the references iterators
01313   // remain valid and dont need to be fixed; on the downside, we need to
01314   // continue to track iterators.
01315   } else {
01316 
01317 
01318     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie B");
01319     // make someone else handle original data
01320     fake_const->RelinkReferences();
01321     // do allocation and copy of stl set
01322     fake_const->mpSet = new std::set<T,Cmp>();
01323     *fake_const->mpSet= *pSet;     
01324     // have empty attributes
01325     fake_const->mpAttributes=NULL;
01326     fake_const->pAttributes=&mEmptyAttributes;
01327     // fix iterators
01328     typename std::set< Iterator* >::iterator iit;
01329     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01330       if((**iit).StlIterator()==pSet->end()) 
01331         **iit=Iterator(this, mpSet->end());
01332       else
01333         **iit=Iterator(this, mpSet->find(***iit));
01334     }
01335     // unlink from old source, link to new source
01336     pBaseSet->DetachReference(fake_const);
01337     if(pBaseSet->pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL)
01338       pBaseSet->mDetached=true;
01339     fake_const->pBaseSet=fake_const;
01340     fake_const->pSet=mpSet;
01341     fake_const->mDetached=true;
01342   }
01343 
01344 #ifdef FAUDES_DEBUG_CONTAINER
01345   DValid();
01346 #endif
01347   FD_DC("TBaseSet(" << this << ")::Detach(void): done");
01348 }
01349 
01350 // Lock()
01351 TEMP  void THIS::Lock(void) const {
01352   FD_DC("TBaseSet(" << this << ")::Lock(void)");
01353 #ifdef FAUDES_DEBUG_CONTAINER
01354   DValid();
01355 #endif
01356   // if we are locked: fine
01357   if(mLocked) return;
01358 
01359   // trigger actual copy
01360   Detach();
01361 
01362   // provide fake const
01363   THIS* fake_const = const_cast< THIS* >(this);
01364 
01365   // stop tracking iterators
01366   typename std::set< Iterator* >::const_iterator iit;
01367   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01368     (**iit).Detach();
01369   }
01370   fake_const->mIterators.clear();
01371 
01372   // stop detach from reallocating
01373   fake_const->mLocked=true;
01374 }
01375 
01376 
01377 // if i am a source to others, make someone else source  
01378 TEMP inline void THIS::RelinkReferences(void) {
01379   FD_DC("TBaseSet::RelinkReferences(" << this << ")")
01380 #ifdef FAUDES_DEBUG_CONTAINER
01381   DValid();
01382 #endif
01383   // no references aka this is not a source
01384   if(mReferences.empty()) return;
01385   // make first ref the new storage
01386   THIS* storage = *mReferences.begin();
01387 #ifdef FAUDES_DEBUG_CODE
01388   if(storage->pBaseSet!=this) {
01389     FD_ERR("BaseSet::RelinkRefernces: old reference must have this as storage provider");
01390     abort();
01391   }
01392 #endif
01393   storage->pBaseSet=storage;
01394   storage->mpSet=mpSet; 
01395   storage->pSet=pSet;
01396   storage->mpAttributes=mpAttributes; 
01397   storage->pAttributes=pAttributes;
01398   storage->mReferences=mReferences;
01399   storage->DetachReference(storage);
01400   // set other users to new storage
01401   typename std::set< THIS* >::const_iterator rit;
01402   for(rit=mReferences.begin(), ++rit;rit!=mReferences.end(); ++rit) {
01403     (*rit)->pBaseSet=storage;
01404   }
01405   // make myself a reference to the new source
01406   pBaseSet=storage;
01407   pSet=storage->pSet;
01408   mpSet=NULL;
01409   pAttributes=storage->pAttributes;
01410   mpAttributes=NULL;
01411   storage->AttachReference(this);
01412   mReferences.clear();
01413 #ifdef FAUDES_DEBUG_CONTAINER
01414   DValid();
01415 #endif
01416   FD_DC("TBaseSet::RelinkReferences(" << this << "): done")
01417 }
01418 
01419 
01420 // record fake copy
01421 TEMP inline void THIS::AttachReference(TBaseSet* pRef) const {
01422    const_cast< THIS* >(this)->mReferences.insert(pRef);
01423    const_cast< THIS* >(this)->mDetached=false;
01424 }
01425 
01426 // discard fake copy
01427 TEMP inline void THIS::DetachReference(TBaseSet* pRef) const {
01428    const_cast< THIS* >(this)->mReferences.erase(pRef);
01429 }
01430 
01431 
01432 // record an iterator
01433 TEMP inline void THIS::AttachIterator(Iterator* pFit) const {
01434   if(mLocked) return;
01435   FD_DC("TBaseSet::AttachIterator(" << this << "):" << pFit)
01436   const_cast< THIS* >(this)->mIterators.insert(pFit);
01437 }
01438 
01439 // discard an iterator
01440 TEMP inline void THIS::DetachIterator(Iterator* pFit) const {
01441   if(mLocked) return;
01442   FD_DC("TBaseSet::DetachIterator(" << this << "):" << pFit)
01443   const_cast< THIS* >(this)->mIterators.erase(pFit);
01444 }
01445 
01446 // test some validity
01447 TEMP void THIS::DValid(const std::string& rMessage) const {
01448   typename std::set< Iterator* >::const_iterator iit;
01449 #ifdef FAUDES_DEBUG_CONTAINER
01450   std::cerr << "TBaseSet(" << this << "):DValid() " << rMessage << " source " 
01451      << pBaseSet << " " << (pBaseSet->pSet==&mEmptySet ? "+e+" : "+f+") << 
01452         (mLocked ? " +l+" : " ") << (mDetached ? " +d+" : " ") << " -- refs ";
01453   typename std::set< THIS* >::const_iterator rit;
01454   for(rit=pBaseSet->mReferences.begin(); rit!=pBaseSet->mReferences.end(); ++rit)
01455     std::cerr << *rit << " ";
01456   std::cerr << "-- its ";
01457   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit)
01458     std::cerr << *iit << " ";
01459   std::cerr << "-- attr #" << pAttributes->size();
01460   if(mpAttributes) std::cerr << "(" << mpAttributes->size() << ") ";
01461   std::cerr << (pAttributes==&mEmptyAttributes ? "+e+" : "+f+") << std::endl;
01462 #endif
01463   // iterators, that dont refer to me as basset
01464   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01465     if((*iit)->pBaseSet!=this) {
01466       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (baseset): "<< *iit);
01467       abort();
01468     }
01469   }
01470   // iterators, that are not marked as attached
01471   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01472     if(!(*iit)->mAttached) {
01473       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (attached): "<< *iit);
01474       abort();
01475     }
01476   }
01477   // iterators, that are invalid stl iterators
01478   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01479     typename std::set<T,Cmp>::const_iterator vit;
01480     for(vit=pSet->begin(); vit!= pSet->end(); ++vit) {
01481       if(vit==(**iit).StlIterator()) break;
01482     }
01483     if(vit!=(**iit).StlIterator()) { // end-iterator is fine, too
01484       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (stl "<< *iit);
01485       (**iit).StlIterator(pSet->end()); // fix invalid iterator to refer to end()
01486     }
01487   }
01488   // must have some base 
01489   if(pBaseSet==NULL) {
01490     FD_ERR("BaseSet(" << this << "," << rMessage << "): no base found");
01491     abort();
01492   }
01493   // base must provide data either way
01494   if(pBaseSet->pBaseSet != pBaseSet) {
01495     FD_ERR("BaseSet(" << this << "," << rMessage << "): no source found");
01496     abort();
01497   }
01498   // refers to other base and own data
01499   if((mpSet!=NULL) && (pBaseSet != this)) {
01500     FD_ERR("BaseSet(" << this << "," << rMessage << "): double data");
01501     abort();
01502   }
01503   // refers to other base and has references
01504   if(pBaseSet!=this && !mReferences.empty()) {
01505     FD_ERR("BaseSet(" << this << "," << rMessage << "): cannot have source and refs");
01506     abort();
01507   }
01508   // is base but has no own data
01509   if((pBaseSet == this) && (mpSet==NULL) && (pSet!=&mEmptySet)) {
01510     FD_ERR("BaseSet(" << this << "," << rMessage << "): no data");
01511     abort();
01512   }
01513   // is base but own data pointer mismatch
01514   if((pBaseSet == this) && (pSet != mpSet) && (pSet!=&mEmptySet)) {
01515     FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch A");
01516     abort();
01517   }
01518   // refers to base with data pointer mismatch
01519   if((pBaseSet != this) && (pSet != pBaseSet->pSet)) {
01520     FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch B");
01521     abort();
01522   }
01523   // error in detached flag
01524   if(mDetached && !pBaseSet->mReferences.empty()) {
01525     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid detached flag");
01526     abort();
01527   }
01528   // error in detached flag
01529   if(mDetached && (pSet==&mEmptySet)) {
01530     FD_ERR("BaseSet(" << this << "," << rMessage << "): detached empty set");
01531     abort();
01532   }
01533   // error in lock flag
01534   if(pBaseSet!=this && mLocked) {
01535     FD_ERR("BaseSet(" << this << "," << rMessage << "): locked reference");
01536     abort();
01537   }
01538   // invalid emptyset
01539   if(!mEmptySet.empty()) {
01540     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty set");
01541     abort();
01542   }
01543   // invalid emptyset
01544   if(!mEmptyAttributes.empty()) {
01545     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty attributes");
01546     abort();
01547   }
01548 }
01549 
01550 
01551 
01552 // Name
01553 TEMP const std::string& THIS::Name(void) const {
01554   return mMyName;
01555 }
01556     
01557 // Name
01558 TEMP void THIS::Name(const std::string& rName) {
01559   mMyName = rName;
01560 }
01561   
01562 
01563 // TypeDefinitionp()
01564 // Note: fake const construct
01565 TEMP const TypeDefinition* THIS::TypeDefinitionp(void) const {
01566   if(!pTypeDefinition) {
01567     // provide fake const
01568     THIS* fake_const = const_cast< THIS* >(this);
01569     fake_const->pTypeDefinition=TypeRegistry::G()->Definitionp(*this);
01570   }
01571   return pTypeDefinition;
01572 }
01573 
01574 // TypeName
01575 TEMP  const std::string& THIS::TypeName(void) const {
01576   const TypeDefinition* fdp=TypeDefinitionp();
01577   if(!fdp) return msStringEmpty;
01578   return fdp->Name();
01579 }
01580 
01581 // ElementTag
01582 TEMP  const std::string& THIS::XElementTag(void) const {
01583   const static std::string etstr("Element");
01584   const TypeDefinition* fdp=TypeDefinitionp();
01585   if(!fdp) return etstr;
01586   return fdp->XElementTag();
01587 }
01588 
01589 
01590 // Str
01591 TEMP std::string THIS::Str(const T& rElem) const { 
01592   (void) rElem;
01593   std::string res=""; 
01594   return res; 
01595 }
01596 
01597 // Size()
01598 TEMP Idx THIS::Size(void) const {
01599   return (Idx) pSet->size();
01600 }
01601 
01602 // Empty()
01603 TEMP bool THIS::Empty(void) const {
01604   return pSet->empty();
01605 }
01606 
01607 
01608 // DoWrite(tw,rLabel,cpntext)
01609 TEMP void THIS::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
01610   (void) pContext;
01611   std::string label=rLabel;
01612   if(label=="") label=Name(); 
01613   if(label=="") label="BaseSet"; 
01614   FD_DC("TBaseSet(" << this << ")::DoWrite(..): section " << label << " #" << Size());
01615   rTw.WriteBegin(label);
01616   rTw.WriteEnd(label);
01617 }
01618 
01619 
01620 // DoDWrite(tw, label, context)
01621 TEMP void THIS::DoDWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
01622   (void) pContext;
01623   (void) rLabel;
01624   rTw.WriteComment("");
01625   rTw.WriteComment(" Size/Attributes: " + ToStringInteger(pSet->size()) 
01626         + "/" + ToStringInteger(pBaseSet->pAttributes->size()));
01627   rTw.WriteComment(" Shares/Iterators: " + ToStringInteger(pBaseSet->mReferences.size()) 
01628         + "/" + ToStringInteger(mIterators.size()));
01629   rTw.WriteComment("");
01630 #ifdef FAUDES_DEBUG_CONTAINER
01631   DValid();
01632 #endif
01633 }
01634 
01635 // DoSWrite()
01636 TEMP void THIS::DoSWrite(TokenWriter& rTw) const {
01637   BASE::DoSWrite(rTw);
01638   rTw.WriteComment(" Size: " + ToStringInteger(pSet->size()));
01639   if(!mpSet)
01640     rTw.WriteComment(" Data: shared");
01641   else
01642     rTw.WriteComment(" Data: own");
01643   if(pAttributes->size()!=0)
01644     rTw.WriteComment(" Attributes: " +ToStringInteger(pAttributes->size()));
01645   if(pAttributes->size()!=0) {
01646     AttributeVoid* attr = pAttributes->begin()->second;
01647     rTw.WriteComment(" Attribute Type: " +FaudesTypeName(*attr));
01648   } 
01649 }
01650 
01651 // DoRead(rTr, rLabel, pContext)
01652 TEMP void THIS::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
01653   (void) pContext;
01654   std::string label=rLabel;
01655   if(label=="") label=Name(); 
01656   if(label=="") label="BaseSet"; 
01657   Name(label);
01658   rTr.ReadBegin(label); 
01659   rTr.ReadEnd(label); 
01660 }
01661 
01662 // ThisIterator
01663 TEMP typename THIS::Iterator THIS::ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const {
01664   return Iterator(this,sit);
01665 }
01666 
01667 // Begin() const
01668 TEMP inline typename THIS::Iterator THIS::Begin(void) const {
01669   return ThisIterator(pSet->begin());
01670 }
01671     
01672 // End() const
01673 TEMP inline typename THIS::Iterator THIS::End(void) const {
01674   return ThisIterator(pSet->end());
01675 }
01676 
01677 
01678 //Clear
01679 TEMP void THIS::Clear(void) {
01680   FD_DC("TBaseSet(" << this << ")::Clear()");
01681 #ifdef FAUDES_DEBUG_CONTAINER
01682   DValid();
01683 #endif
01684   // special case: empty anyway
01685   if(pSet==&mEmptySet) return;
01686   // special case: locked requires a copy (not efficient!)
01687   if(mLocked) Detach();
01688   // make someone else handle the data
01689   if(!mReferences.empty()) RelinkReferences();
01690   // unlink myself from source
01691   if(pBaseSet!=this) {
01692     pBaseSet->DetachReference(this);
01693     pBaseSet=this;
01694   }
01695   // if we hold data, clear it
01696   if(mpSet) {
01697     delete mpSet;
01698     mpSet=NULL;
01699   }
01700   // if we hold data, clear it
01701   if(mpAttributes) {
01702     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01703        delete ait->second;
01704     delete mpAttributes;
01705     mpAttributes=NULL;
01706   }
01707   // set to empty set
01708   pSet=&mEmptySet;
01709   pAttributes=&mEmptyAttributes;
01710   // fix iterators (invalidate)
01711   typename std::set< Iterator* >::iterator iit;
01712   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01713     (**iit).Invalidate();
01714   }
01715   mIterators.clear();
01716   mDetached=false;
01717 #ifdef FAUDES_DEBUG_CONTAINER
01718   DValid();
01719 #endif
01720 }
01721 
01722 
01723 //Valid(elem)
01724 TEMP inline bool  THIS::Valid(const T& rElem) const {
01725   (void) rElem;
01726   return true;
01727 }
01728 
01729 //Insert(elem)
01730 TEMP bool THIS::Insert(const T& rElem) {
01731 #ifdef FAUDES_CHECKED
01732   if(!Valid(rElem)) {
01733     std::stringstream errstr;
01734     errstr << "cannot insert invalid element" << std::endl;
01735     throw Exception("BaseSet::Insert", errstr.str(), 61);
01736   }
01737 #endif
01738   if(!mDetached) Detach();
01739   return pSet->insert(rElem).second;
01740 }
01741 
01742 // InsertSet(set)
01743 TEMP void THIS::InsertSet(const TBaseSet& rOtherSet) {
01744   FD_DC("TBaseSet(" << this << ")::InsertSet(" << &rOtherSet << ")");
01745   if(!mDetached) Detach();
01746   /*
01747   rem: cannot use stl since result overlaps with arguments
01748 
01749   std::insert_iterator< std::set<T,Cmp> > insit(*pSet, rpSet->begin());
01750   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01751   */
01752   iterator it1 = pSet->begin();
01753   iterator it2 = rOtherSet.pSet->begin();
01754   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01755     if (*it1 < *it2) {
01756       ++it1;
01757     }
01758     else if (*it1 == *it2) {
01759       ++it1;
01760       ++it2;
01761     }
01762     else { // (*it1 > *it2)
01763       pSet->insert(*it2);
01764       ++it2;
01765     }
01766   }
01767   while (it2 != rOtherSet.pSet->end()) {
01768     pSet->insert(*it2);
01769     ++it2;
01770   }
01771 }
01772 
01773     
01774 //Erase(rElem)
01775 TEMP bool THIS::Erase(const T& rElem) {
01776   if(!mDetached) Detach();
01777   return (pSet->erase(rElem)!=0);
01778 }
01779 
01780 
01781 //Erase(pos)
01782 TEMP typename THIS::Iterator THIS::Erase(const Iterator& pos) { 
01783 #ifdef FAUDES_CHECKED
01784   if (pos == End()) {
01785     std::stringstream errstr;
01786     errstr << "iterator out of range " << std::endl;
01787     throw Exception("BaseSet::Erase", errstr.str(), 62);
01788   }
01789 #endif
01790   Detach();
01791   iterator del= pos.StlIterator(); 
01792   iterator res= del;
01793   res++; 
01794   pSet->erase(del);
01795   return ThisIterator(res); 
01796 }
01797 
01798 
01799 //EraseSet(set)
01800 TEMP void THIS::EraseSet(const TBaseSet& rOtherSet) {
01801   FD_DC("TBaseSet(" << this << ")::EraseSet(" << &rOtherSet << ")");
01802   if(!mDetached) Detach();
01803   // TODO: test and optimize 
01804   iterator tmpit;
01805   iterator it = pSet->begin();
01806   iterator oit = rOtherSet.pSet->begin();
01807   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
01808     if (*it < *oit) {
01809       it=pSet->lower_bound(*oit); // alt: ++it;
01810     }
01811     else if (*it == *oit) { 
01812       tmpit=it;
01813       ++it;
01814       ++oit;
01815       pSet->erase(tmpit);
01816     }
01817     else { // (*it > *oit)
01818       oit=rOtherSet.pSet->lower_bound(*it); // ++it2;
01819     }
01820   }
01821 }
01822 
01823 
01824 //RestrictSet(set)
01825 TEMP void THIS::RestrictSet(const TBaseSet& rOtherSet) {
01826   FD_DC("TBaseSet(" << this << ")::RestrictSet(" << &rOtherSet << ")");
01827   if(!mDetached) Detach();
01828   // TODO: test and optimize 
01829   iterator tmpit;
01830   iterator it = pSet->begin();
01831   iterator oit = rOtherSet.pSet->begin();
01832   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
01833     if (*it < *oit) {
01834       tmpit=it;
01835       ++it;
01836       pSet->erase(tmpit);
01837     }
01838     else if (*it == *oit) { 
01839       ++it;
01840       ++oit;
01841     }
01842     else { // (*it > *oit)
01843       oit=rOtherSet.pSet->lower_bound(*it); 
01844     }
01845   }
01846   while(it != pSet->end()) {
01847     tmpit=it;
01848     ++it;
01849     pSet->erase(tmpit);
01850   }
01851 }
01852 
01853 
01854 //Find(elem)
01855 TEMP typename THIS::Iterator THIS::Find(const T& rElem) const {
01856   return ThisIterator(pSet->find(rElem));
01857 }
01858 
01859 //Exists(elem)
01860 TEMP bool  THIS::Exists(const T& rElem) const {
01861   return pSet->find(rElem) != pSet->end();
01862 }
01863 
01864 
01865 // SetUnion(set)
01866 TEMP void THIS::SetUnion(const TBaseSet& rOtherSet) {
01867   if(!mDetached) Detach();
01868   iterator it1 = pSet->begin();
01869   iterator it2 = rOtherSet.pSet->begin();
01870   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01871     if (*it1 < *it2) {
01872       ++it1;
01873       continue;
01874     }
01875     if (*it1 == *it2) {
01876       ++it1;
01877       ++it2;
01878       continue;
01879     }
01880     // (*it1 > *it2)
01881     pSet->insert(it1,*it2);
01882     ++it2;
01883   }
01884   while (it2 != rOtherSet.pSet->end()) {
01885     pSet->insert(pSet->end(),*it2);
01886     ++it2;
01887   }
01888 }
01889 
01890 // SetIntersection(set)
01891 TEMP void THIS::SetIntersection(const TBaseSet& rOtherSet) {
01892   if(!mDetached) Detach();
01893   iterator tmpit;
01894   iterator it1 = pSet->begin();
01895   iterator it2 = rOtherSet.pSet->begin();
01896   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01897     if (*it1 < *it2) {
01898       tmpit=it1;
01899       ++it1;
01900       pSet->erase(tmpit);
01901       continue;
01902     }
01903     if (*it1 == *it2) {
01904       ++it1;
01905       ++it2;
01906       continue;
01907     }
01908     // if (*it1 > *it2)
01909     ++it2;
01910   }
01911   while(it1 != pSet->end()) {
01912     tmpit=it1;
01913     ++it1;
01914     pSet->erase(tmpit);
01915   }
01916 }
01917 
01918 
01919 // FnctUnion
01920 TEMP void THIS::FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const {
01921   FD_DC("TBaseSet(" << this << ")::FnctUnion (" << &rOtherSet << ")");
01922   rRes.Detach();
01923   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
01924   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01925   rRes.Name(CollapsString(Name() + "+" + rOtherSet.Name()));
01926 }
01927 
01928 // FnctDifference
01929 TEMP void THIS::FnctDifference (const TBaseSet& rOtherSet, TBaseSet& rRes) const {
01930   FD_DC("TBaseSet(" << this << ")::FnctDifference (" << &rOtherSet << ")");
01931   rRes.Detach();
01932   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
01933   std::set_difference(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01934   rRes.Name(CollapsString(Name() + "-" + rOtherSet.Name()));
01935 }
01936 
01937      
01938 // FnctIntersection
01939 TEMP void THIS::FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const {
01940   FD_DC("TBaseSet(" << this << ")::FnctIntersection (" << &rOtherSet << ")");
01941   rRes.Detach();
01942   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
01943   std::set_intersection(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01944   rRes.Name(CollapsString(Name() + "*" + rOtherSet.Name()));
01945 }
01946 
01947 // operator+
01948 TEMP THIS THIS::operator+ (const TBaseSet& rOtherSet) const {
01949   TBaseSet res;
01950   FnctUnion(rOtherSet,res);
01951   return res;
01952 }
01953 
01954 // operator-
01955 TEMP THIS THIS::operator- (const TBaseSet& rOtherSet) const {
01956   TBaseSet res;
01957   FnctDifference(rOtherSet,res);
01958   return res;
01959 }
01960 
01961      
01962 // operator*
01963 TEMP THIS THIS::operator* (const TBaseSet& rOtherSet) const {
01964   TBaseSet res;
01965   FnctIntersection(rOtherSet,res);
01966   return res;
01967 }
01968 
01969 
01970 // operator==
01971 TEMP bool THIS::DoEqual(const TBaseSet& rOtherSet) const {
01972   FD_DC("TBaseSet::DoEqual()");
01973   // true if we share anyway
01974   if(pSet == rOtherSet.pSet) return true;
01975   // compare sets
01976   return  ( *pSet == *rOtherSet.pSet );
01977 }
01978 
01979 // operator<=
01980 TEMP bool THIS::operator<= (const TBaseSet& rOtherSet) const {
01981   FD_DC("BaseSet::op<=()");
01982   return ( std::includes(rOtherSet.pSet->begin(), rOtherSet.pSet->end(), pSet->begin(), pSet->end()) ) ;
01983 }
01984 
01985 // operator>=
01986 TEMP bool THIS::operator>= (const TBaseSet& rOtherSet) const {
01987   FD_DC("BaseSet::op>=()");
01988   return ( std::includes(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end()) );
01989 }
01990 
01991 // operator<
01992 TEMP bool THIS::operator< (const TBaseSet& rOtherSet) const {
01993   return *pSet < *rOtherSet.pSet;
01994 }
01995 
01996 
01997 // attribute typeinfo
01998 TEMP const AttributeVoid* THIS::Attributep(void) const { 
01999   static AttributeVoid attr; 
02000   return & attr; 
02001 }
02002 
02003 // attribute typeinfo
02004 TEMP const AttributeVoid& THIS::Attribute(void) const { 
02005   static AttributeVoid attr; 
02006   return attr;
02007 }
02008 
02009 // attribute access
02010 TEMP AttributeVoid* THIS::Attributep(const T& rElem) { 
02011   (void) rElem;
02012   std::stringstream errstr;
02013   errstr << "cannot get attribute for TBaseSet \"" << mMyName  << "\" type " << typeid(*this).name();
02014   throw Exception("TBaseSet::Attributep(rElem)", errstr.str(), 63);  
02015   static AttributeVoid attr; 
02016   return &attr; 
02017 }
02018 
02019 // attribute access
02020 TEMP const AttributeVoid& THIS::Attribute(const T& rElem) const { 
02021   (void) rElem;
02022   static AttributeVoid attr; 
02023   return attr;
02024 }
02025 
02026 // attribute access
02027 TEMP void THIS::Attribute(const T& rElem, const Type& rAttr) {
02028   (void) rElem;
02029   /* its pointless to test existence of the element since we wont set any attribute anyway
02030 #ifdef FAUDES_CHECKED
02031   if (!Exists(rElem)) {
02032     std::stringstream errstr;
02033     errstr << "element not member of set" << std::endl;
02034     throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 60);
02035   }
02036 #endif
02037   */
02038   if(!AttributeTry(rAttr)) {
02039     std::stringstream errstr;
02040     errstr << "cannot cast attribute " << std::endl;
02041     throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 63);
02042   }
02043   /* alternative approach: 
02044   // silently ignore any value
02045   // set to void is ok for silient ignore
02046   if(typeid(rAttr)==typeid(const AttributeVoid&)) return;
02047   // set to nontrivial attribute: exception
02048   std::stringstream errstr;
02049   errstr << "cannot set attribute type " << typeid(rAttr).name() << " for TBaseSet \"" << mMyName 
02050     << "\" type " << typeid(*this).name();
02051   throw Exception("TBaseSet::Attribute(rElem,rAttr)", errstr.str(), 63);  
02052   */
02053 }
02054 
02055 
02056 
02057 /* undefine local shortcuts */
02058 #undef THIS
02059 #undef TEMP
02060 #undef BASE
02061 
02062 /** @} doxygen group */
02063 
02064 } // namespace faudes
02065 
02066 #endif 

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3