About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
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   /** 
00158    * Clear all set
00159    */
00160   virtual void Clear(void);
00161       
00162   /**
00163    * Get Size of TBaseSet
00164    *
00165    * @return 
00166    *   Number of indices in TBaseSet
00167    */
00168   Idx Size(void) const;
00169 
00170   /** 
00171    * Test whether if the TBaseSet is Empty 
00172    *
00173    * @return 
00174    *   True if empty
00175    */
00176   bool Empty(void) const;
00177 
00178   /**
00179    * Return pretty printable element. 
00180    * Reimplement this method for derived classes.
00181    *
00182    * @param rElem
00183    *   Element to print
00184    *
00185    * @return
00186    *   String
00187    */
00188   virtual std::string Str(const T& rElem) const;
00189 
00190   /** 
00191    * Iterator class for high-level api to TBaseSet.
00192    *
00193    */
00194   class Iterator;
00195 
00196   /** 
00197    * Iterator to the begin of set
00198    *
00199    * @return 
00200    *   Iterator
00201    */
00202   Iterator Begin(void) const;
00203         
00204   /** 
00205    * Iterator to the end of set
00206    *
00207    * @return 
00208    *   Iterator
00209    */
00210   Iterator End(void) const;
00211 
00212   /**
00213    * Test validty of candidate element.
00214    *
00215    * Reimplement this function for particular type T of elements,
00216    * eg for an index set with T=Idx indicate 0 an invalid index.
00217    *
00218    * @param rElem
00219    *    Candidate to test
00220    * @return
00221    *    True if element is valid
00222    */
00223   virtual bool Valid(const T& rElem) const;
00224    
00225 
00226   /** 
00227    * Erase element by reference
00228    *
00229    * @param rElem
00230    *    Element to erase
00231    * @return
00232    *    True if element used to exist
00233    */
00234   virtual bool Erase(const T& rElem);
00235 
00236 
00237   /** 
00238    * Erase element by iterator 
00239    *
00240    * @param pos
00241    *    Iterator to specify element
00242    * @return 
00243    *    Iterator to next element (or End if no such)
00244    */
00245   virtual Iterator Erase(const Iterator& pos); 
00246 
00247 
00248   /** 
00249    * Erase elements given by other set 
00250    *
00251    * @param rOtherSet 
00252    *    Set of elements to erase
00253    */
00254   virtual void EraseSet(const TBaseSet& rOtherSet);
00255 
00256   /** 
00257    * Restrict elements given by other set 
00258    *
00259    * @param rOtherSet 
00260    *    Set of elements to keep
00261    */
00262   virtual void RestrictSet(const TBaseSet& rOtherSet);
00263 
00264 
00265   /** 
00266    * Insert specified element
00267    *
00268    * @param rElem
00269    *    Element to insert
00270    * @return
00271    *   True if index was new to set 
00272    */
00273   virtual bool Insert(const T& rElem);
00274 
00275   /**
00276    * Insert elements given by rOtherSet 
00277    *
00278    *
00279    * @param rOtherSet
00280    *   Set of elements to insert
00281    */
00282   virtual void InsertSet(const TBaseSet& rOtherSet);
00283 
00284   /**
00285    * Set Union, result is accumulated in this set.
00286    *
00287    * @param rOtherSet
00288    *   Other TBaseSet
00289    */
00290   virtual void SetUnion(const TBaseSet& rOtherSet);
00291 
00292   /**
00293    * Set Intersection, result is stored in this set.
00294    * 
00295    * @param rOtherSet
00296    *   Other TBaseSet
00297    */
00298   virtual void SetIntersection(const TBaseSet& rOtherSet);
00299 
00300 
00301   /**
00302    * Test existence of element
00303    *
00304    * @param rElem
00305    *   Element to test
00306    *
00307    * @return 
00308    *   True if element exists in set
00309    */
00310   bool Exists(const T& rElem) const;
00311 
00312   /**
00313    * Find element and return iterator.
00314    *
00315    * @param rElem
00316    *   Element to find
00317    *
00318    * @return 
00319    *   Iterator to element or End() if nonexistent
00320    */
00321   Iterator Find(const T& rElem) const;
00322 
00323   /**
00324    * Set union operator
00325    *
00326    * @return 
00327    *   Union Set
00328    */
00329    TBaseSet operator+ (const TBaseSet& rOtherSet) const;
00330 
00331   /**
00332    * Set difference operator
00333    *
00334    * @return 
00335    *   Difference Set
00336    */
00337    TBaseSet operator- (const TBaseSet& rOtherSet) const;
00338 
00339   /**
00340    * Set intersection operator
00341    *
00342    * @return 
00343    *   Intersection Set
00344    */
00345   TBaseSet operator* (const TBaseSet& rOtherSet) const;
00346 
00347 
00348   /** Test for subset  */
00349   bool operator<= (const TBaseSet& rOtherSet) const;
00350 
00351   /** Test for superset */
00352   bool operator>= (const TBaseSet& rOtherSet) const;
00353 
00354   /** Order for sorting containers of TBaseSet */
00355   bool operator< (const TBaseSet& rOtherSet) const;
00356 
00357   /** Some validation of deferred copy mechanism (provoke abort)*/
00358   void DValid(const std::string& rMessage="") const;
00359 
00360   /** Detach from extern storage (incl allocation and true copy) */
00361   virtual void Detach(void) const;
00362 
00363   /** Detach and lock any further reallocation */
00364   virtual void Lock(void) const;
00365 
00366   /** 
00367    * Iterator class for high-level api to TBaseSet.
00368    * This class is derived from STL iterators to additionally provide
00369    * a reference of the container to iterate on. This feature
00370    * is used to adjust iterators when the actual set gets reallocated due to a Detach()
00371    * operation. Inheritance is private to ensure that all high-level api functions maintain
00372    * iteretor refernces consistently. Currently, high-level api iterators support
00373    * the operators -&gt; ,*,  =, ++, --, ==, !=.
00374    * 
00375    * Technical detail: the private inheritance prohibits the direct use of stl algorithms on
00376    * faudes Iterators. If you need direct access to stl algorithms from outside the faudes set
00377    * class, you may turn to public inheritance. Make sure to Lock the relevant sets befor
00378    * applying any stl algorithms.
00379    */
00380    class Iterator : private std::set<T,Cmp>::const_iterator {
00381      public: 
00382      /** Default constructor, container unknown */
00383      Iterator() : 
00384        std::set<T,Cmp>::const_iterator() , 
00385        pBaseSet(NULL),
00386        mAttached(false) 
00387      {};
00388 
00389      /** Construct by members, used by TBaseSet to create temporary iterators */
00390      Iterator(
00391        const TBaseSet<T,Cmp>* pBaseSet,
00392        const typename std::set<T,Cmp>::const_iterator& sit) : 
00393        std::set<T,Cmp>::const_iterator(sit), 
00394        pBaseSet(pBaseSet),
00395        mAttached(false)  
00396      {};
00397 
00398      /** Copy constructor, copies container reference, incl attach */
00399      Iterator(const Iterator& fit) : 
00400        std::set<T,Cmp>::const_iterator(fit),
00401        pBaseSet(fit.pBaseSet), 
00402        mAttached(false) 
00403      {
00404        if(pBaseSet) {
00405           pBaseSet->AttachIterator(this);
00406           mAttached=true;
00407        }
00408      };  
00409 
00410      /** Destructor */
00411      ~Iterator(void) { 
00412        if(mAttached) pBaseSet->DetachIterator(this);
00413      }; 
00414 
00415      /** Assigment, tracks container */
00416      const Iterator& operator= (const Iterator& rSrc) {
00417 #ifdef FAUDES_DEBUG_CODE
00418        if(rSrc.pBaseSet==NULL) {
00419          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator= invalid iterator: no baseset");
00420          abort();
00421        }
00422 #endif
00423        // performance relevant std case 
00424        if(mAttached) if(pBaseSet==rSrc.pBaseSet) {
00425          std::set<T,Cmp>::const_iterator::operator= (rSrc);
00426          return *this;
00427        }
00428        // general case
00429        if(mAttached) pBaseSet->DetachIterator(this);
00430        std::set<T,Cmp>::const_iterator::operator= (rSrc);
00431        pBaseSet = rSrc.pBaseSet;
00432        if(pBaseSet) {
00433          pBaseSet->AttachIterator(this);
00434          mAttached=true;
00435        } else {
00436      mAttached=false;
00437        }
00438        return *this;
00439      };
00440 
00441      /** Assign STL iterator only */
00442      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00443        std::set<T,Cmp>::const_iterator::operator= (sit);
00444      };
00445 
00446      /** Get STL iterator only */
00447      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00448        return *this;
00449      };
00450 
00451      /** Invalidate */
00452      void  Invalidate(void) {
00453        pBaseSet=NULL;
00454        mAttached=false;
00455      }; 
00456 
00457      /** Detach */
00458      void  Detach(void) {
00459        mAttached=false;
00460      }; 
00461 
00462 
00463      /** Check validity (provoke abort error) */
00464      void DValid(void) const {
00465       if(pBaseSet==NULL) {
00466          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):DValid(): invalid iterator: no baseset");
00467          abort();
00468        }
00469        pBaseSet->DValid("Iterator");
00470      }; 
00471 
00472     /** Reimplement dereference */
00473      const T* operator-> (void) const {
00474 #ifdef FAUDES_DEBUG_CODE
00475        if(pBaseSet==NULL) {
00476          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator->: invalid iterator: no baseset");
00477          abort();
00478        }
00479 #endif
00480        return std::set<T,Cmp>::const_iterator::operator-> ();
00481      };
00482 
00483      /** Reimplement derefernce */
00484      const T& operator* (void) const {
00485 #ifdef FAUDES_DEBUG_CODE
00486        if(pBaseSet==NULL) {
00487          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator*: invalid iterator: no baseset");
00488          abort();
00489        }
00490 #endif
00491        return std::set<T,Cmp>::const_iterator::operator* ();
00492      };
00493 
00494      /** Reimplement == */
00495      bool operator== (const Iterator& rOther) const {
00496 #ifdef FAUDES_DEBUG_CODE
00497        if(pBaseSet==NULL) {
00498          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator==: invalid iterator: no baseset");
00499          abort();
00500        }
00501 #endif
00502        return std::set<T,Cmp>::const_iterator::operator== (rOther);
00503      };
00504 
00505      /** Reimplement != */
00506      bool operator!= (const Iterator& rOther) const {
00507 #ifdef FAUDES_DEBUG_CODE
00508        if(pBaseSet==NULL) {
00509          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator!=: invalid iterator: no baseset");
00510          abort();
00511        }
00512 #endif
00513        return std::set<T,Cmp>::const_iterator::operator!= (rOther);
00514      };
00515 
00516      /** Reimplement postfix ++ */
00517      Iterator operator++ (int step) {
00518 #ifdef FAUDES_DEBUG_CODE
00519        if(pBaseSet==NULL) {
00520          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00521          abort();
00522        }
00523 #endif
00524        Iterator old(pBaseSet,*this);
00525        std::set<T,Cmp>::const_iterator::operator++ (step);
00526        return old;
00527      };
00528 
00529      /** Reimplement prefix ++ */
00530      const Iterator& operator++ (void) {
00531 #ifdef FAUDES_DEBUG_CODE
00532        if(pBaseSet==NULL) {
00533          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00534          abort();
00535        }
00536 #endif
00537        std::set<T,Cmp>::const_iterator::operator++ ();
00538        return *this;
00539      };
00540 
00541      /** Reimplement postfix -- */
00542      Iterator operator-- (int step) {
00543 #ifdef FAUDES_DEBUG_CODE
00544        if(pBaseSet==NULL) {
00545          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00546          abort();
00547        }
00548 #endif
00549        Iterator old(pBaseSet, *this);
00550        std::set<T,Cmp>::const_iterator::operator-- (step);
00551        return old;
00552      };
00553 
00554      /** Reimplement prefix -- */
00555      const Iterator& operator-- (void) {
00556 #ifdef FAUDES_DEBUG_CODE
00557        if(pBaseSet==NULL) {
00558          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00559          abort();
00560        }
00561 #endif
00562        std::set<T,Cmp>::const_iterator::operator-- ();
00563        return *this;
00564      };
00565 
00566 
00567      /** Order by reference for containers of Iterators < */
00568      /*
00569      bool operator< (const Iterator& rOther) const {
00570        return this < &rOther;
00571      };
00572      */
00573 
00574      /** Maintaine container reference */
00575      const TBaseSet<T,Cmp>* pBaseSet;
00576 
00577      /** Indicate that this iterator is attached to some baseset */
00578      bool mAttached;
00579    };
00580 
00581 #ifdef DONT_TRACK_REFERENCES
00582 
00583   /** 
00584    * Iterator class for high-level api to TBaseSet.
00585    * This version is a dummy and does not provide any additional features.
00586    */
00587    class Iterator : public std::set<T,Cmp>::const_iterator {
00588      public:
00589 
00590      /** Default contructor */
00591      Iterator(void) : 
00592        std::set<T,Cmp>::const_iterator()  
00593      {}; 
00594 
00595      /** Copy constructor  */
00596      Iterator(const Iterator& fit) : 
00597        std::set<T,Cmp>::const_iterator(fit)
00598      {};
00599 
00600      /** Copy constructor  */
00601      Iterator(const typename std::set<T,Cmp>::const_iterator& sit) : 
00602        std::set<T,Cmp>::const_iterator(sit)
00603      {};
00604 
00605      /** Copy constructor, compatibility  */
00606      Iterator(
00607        const TBaseSet<T,Cmp>* pBaseSet,
00608        const typename std::set<T,Cmp>::const_iterator& sit) : 
00609        std::set<T,Cmp>::const_iterator(sit) 
00610      {};
00611 
00612      /** Assign STL iterator only, compatibility */
00613      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00614        std::set<T,Cmp>::const_iterator::operator= (sit);
00615      }; 
00616 
00617      /** Get STL iterator only, compatibility */
00618      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00619        return *this;
00620      };
00621 
00622      /** Invalidate, compatibility */
00623      void  Invalidate(void) {};
00624 
00625    };
00626 
00627 #endif
00628 
00629   /** 
00630    * Attribute typeinfo.
00631    * This virtual function provides an interface for derived container classes with attributes 
00632    * eg TaIndexSet. When not re-implemented, it returns an attribute with type AttributeVoid to
00633    * indicate the absence of nontrivial attributes
00634    */
00635   virtual const AttributeVoid* Attributep(void) const;
00636 
00637   /** 
00638    * Attribute typeinfo.
00639    * This virtual function provides an interface for derived container classes with attributes 
00640    * eg TaIndexSet. When not re-implemented, it returns an attribute with type AttributeVoid to
00641    */
00642   virtual const AttributeVoid& Attribute(void) const;
00643 
00644   /** 
00645    * Attribute typeinfo.
00646    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00647    * It is meant to test whether this set accepts the specified attribute type ie whether it can be casted.
00648    * When not re-implemented, the set accepts any attributes derived from attribute void.
00649    * @param rAttr
00650    *     Attribute type to test.
00651    * @return True, if attribute type is accepted.
00652    */
00653   virtual bool AttributeTry(const Type& rAttr) const {return dynamic_cast< const AttributeVoid* >(&rAttr)!=0;};
00654 
00655   /**
00656    * Attribute access.
00657    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00658    * It is meant to ignore any attributes. The TBaseSet itself has no attributes, so it calls its
00659    * Assign method that ignores attributes anyway.
00660    *
00661    * @param rSourceSet 
00662    *    Set to copy from
00663    */
00664    virtual TBaseSet& AssignWithoutAttributes(const TBaseSet& rSourceSet) { return TBaseSet::Assign(rSourceSet); };
00665 
00666   /**
00667    * Attributes access. 
00668    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00669    * It is meant to copy attributes from the specified set.
00670    * The TBaseSet itself has no attributes and thus this function does nothing.
00671    *
00672    * @param rOtherSet
00673    *   Other BaseSet
00674    */
00675   virtual void Attributes(const TBaseSet& rOtherSet) { (void) rOtherSet; };
00676 
00677 
00678   /** 
00679    * Attribute access.
00680    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00681    * It is meant to provide the number of explicit attributes.
00682    * The TBaseSet itself has no attributes and thus this function returns 0.
00683    */
00684   virtual Idx AttributesSize(void) const { return 0; };
00685 
00686   /** 
00687    * Attribute access.
00688    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00689    * The TBaseSet itself has no attributes and thus this function does nothing.
00690    */
00691   virtual void ClearAttributes(void) { };
00692 
00693   /**
00694    * Attribute access.
00695    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00696    * Derived classes that provide attributes are meant to return true if attributes
00697    * match for shared elements. The base set returns true as a default.
00698    * @param rOtherSet 
00699    *    Other object to compare with.
00700    * @return 
00701    *   True on match.
00702    */
00703   virtual bool EqualAttributes(const TBaseSet& rOtherSet) const { 
00704     return typeid(*rOtherSet.Attributep())==typeid(const AttributeVoid);};
00705 
00706   /** 
00707    * Attribute access.
00708    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00709    * The TBaseSet has no attributes and thus throws an exception. 
00710    * Derived classes that provide attributes are meant to return a pointer to the attribute specified by rElem.
00711    *
00712    * @param rElem
00713    *     Element of which the attribute is requested
00714    * @return 
00715    *     Attribute of specified element
00716    * @exception Exception
00717    *   - No attributes provided (id 63)
00718    */
00719   virtual AttributeVoid* Attributep(const T& rElem);
00720 
00721   /** 
00722    * Attribute access.
00723    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00724    * The TBaseSet has no attributes and thus returns a void attribute.
00725    * Derived classes that provide attributes are meant to return the attribute specified by rElem.
00726    * @param rElem
00727    *     Element of which the attribute is requested
00728    * @return 
00729    *     Attribute of specified element
00730    */
00731   virtual const AttributeVoid& Attribute(const T& rElem) const;
00732 
00733   /** 
00734    * Attribute access.
00735    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00736    * The TBaseSet itself has void attributes and thus formally accepts any nontrivial attribute, 
00737    * however, ignoring any value.
00738    * Derived classes that provide attributes are meant to set the attribute as specified. Only if the
00739    * required cast to the actual attribute type fails an exception is thrown.
00740    * @param rElem
00741    *     Element of which the attribute is to be set
00742    * @param rAttr
00743    *     Attribute value to set.
00744    * @exception Exception
00745    *   - Element does not exist (60)
00746    *   - Cannot cast attribute type (63)
00747    */
00748   virtual void Attribute(const T& rElem, const Type& rAttr);
00749 
00750   /** 
00751    * Attribute access.
00752    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00753    * It is meant to try to set the attribute as specified if the type can be casted. Otherwise it does nothing.
00754    * @param rElem
00755    *     Element of which the attribute is to be set
00756    * @param rAttr
00757    *     Attribute value to set.
00758    */
00759    virtual void AttributeTry(const T& rElem, const Type& rAttr) { (void) rElem; (void) rAttr; };
00760 
00761   /** 
00762    * Attribute access.
00763    * This virtual function provides an interface for derived classes with attributes eg TaIndexSet. 
00764    * It is meant to set the attribute of the specified element to the default value.
00765    * The TBaseSet itself has no attributes and thus this function does nothing.
00766    * @param rElem
00767    *     Element of which the attribute is to be cleared
00768    */
00769    virtual void ClrAttribute(const T& rElem) { (void) rElem; };
00770 
00771   /**
00772    * Configure the element name tag.
00773    * This method allows to overwrite the tag used for elements
00774    * in XML IO. For usual, you will register derived class with
00775    * the run-time-interface and set the elemen tag for XML IO.
00776    *
00777    * @param rTag
00778    *   Name to set
00779    */
00780   virtual void XElementTag(const std::string& rTag);
00781 
00782   /** 
00783    * Get objects's type name. 
00784    *
00785    * Retrieve the faudes-type name from the type registry.
00786    * Sets allow to overwrite the faudes-type identifier. This is allows
00787    * for light-weight derived classes that do not need to be registered.
00788    *
00789    * @return 
00790    *   Faudes-type name or empty string.
00791    */
00792   virtual const std::string& TypeName(void) const;
00793 
00794   /**
00795    * Overwrite faudes-type name.
00796    * This method is used to overwrite the faudes-type identifyer.
00797    *
00798    * @param rType
00799    *   Faudes-type name to set
00800    */
00801   virtual void TypeName(const std::string& rType);
00802 
00803 
00804 
00805 
00806 protected:
00807 
00808 
00809   /** 
00810    * Token output, see Type::DWrite for public wrappers.
00811    * Reimplement this function in derived classes for specific
00812    * specific template parameters. By convention, the default label ""
00813    * should be translated to a) the name of the set or b) some meaningful default, 
00814    * eg "IndexSet" for a set of indices. The pContext pointer can de type-checked
00815    * and interpreted, ie as a symboltable to provide symbolic names. It is also
00816    * passed on to attributes.
00817    *
00818    * @param rTw
00819    *   Reference to TokenWriter
00820    * @param rLabel
00821    *   Label of section to write, defaults to name of set
00822    * @param pContext
00823    *   Write context to provide contextual information
00824    */
00825   virtual void DoWrite(TokenWriter& rTw, const std::string& rLabel="", const Type* pContext=0) const;
00826 
00827   /** 
00828    * Token output, debugging see Type::DWrite for public wrappers.
00829    * Reimplement this function in derived classes for specific
00830    * specific template parameters.
00831    * @param rTw
00832    *   Reference to TokenWriter
00833    * @param rLabel
00834    *   Label of section to write, defaults to name of set
00835    * @param pContext
00836    *   Write context to provide contextual information
00837    */
00838   virtual void DoDWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const;
00839 
00840   /** 
00841    * Token output, see Type::SWrite for public wrappers.
00842    * Statistics include size, name and attributey type. The latter
00843    * is retrieved from the RTI, if initialized. Dereived sets may reimplement
00844    * this method.
00845    *
00846    * @param rTw
00847    *   Reference to TokenWriter
00848    */
00849   virtual void DoSWrite(TokenWriter& rTw) const;
00850 
00851   /**
00852    * Token input, see Type::Read for public wrappers.
00853    * Reimplement this function in derived classes for specific
00854    * specific template parameters.
00855    * By convention, the default label "" should be translated to some meaningful default, 
00856    * eg "IndexSet" for a set of indices". The pContext pointer can de type-checked
00857    * and interpreted, ie as a symboltable to provide symbolic names. It is also
00858    * passed on to attributes.
00859    *
00860    * @param rTr
00861    *   Reference to TokenReader
00862    * @param rLabel
00863    *   Label of section to read, defaults to name of set
00864    * @param pContext
00865    *   Read context to provide contextual information
00866    */
00867   virtual void DoRead(TokenReader& rTr, const std::string& rLabel = "", const Type* pContext=0);
00868 
00869   /** assign my members */
00870   virtual void DoAssign(const TBaseSet& rSourceSet);
00871 
00872   /** test equality */
00873   virtual bool DoEqual(const TBaseSet& rOtherSet) const;
00874 
00875 
00876 protected:
00877 
00878 
00879   /** Name of this BaseSet */
00880   std::string mMyName;
00881 
00882   /** Pointer on STL set to operate on */
00883   std::set<T,Cmp>* pSet;
00884 
00885   /** Pointer to attribute map to operate on */
00886   std::map<T,AttributeVoid*>* pAttributes;
00887 
00888   /** STL iterator, non-const version */
00889   typedef typename std::set<T,Cmp>::iterator iterator;
00890 
00891   /** STL iterator, const version */
00892   typedef typename std::set<T,Cmp>::const_iterator const_iterator;
00893 
00894   /** Convert STL iterator */
00895   typename TBaseSet<T,Cmp>::Iterator ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const;
00896 
00897   /** STL attribute iterator, non-const version */
00898   typedef typename std::map<T,AttributeVoid*>::iterator aiterator;
00899 
00900   /** STL attribute iterator, const version */
00901   typedef typename std::map<T,AttributeVoid*>::const_iterator const_aiterator;
00902 
00903 
00904 
00905   /** STL set, if this object hosts data (else NULL) */
00906   std::set<T,Cmp>* mpSet;
00907 
00908   /** Attribute map, if this object hosts data (else NULL). */
00909   std::map<T,AttributeVoid*>* mpAttributes;
00910 
00911   /** Pointer on BaseSet that hosts our data (THIS if we host) */
00912   TBaseSet<T,Cmp>* pHostSet;
00913 
00914   /** Iterator to the client list that hosts our data (maintained by host)*/
00915   typename std::list< TBaseSet<T,Cmp>* >::iterator mClientRecord; 
00916 
00917   /** BaseSets, that use data hosted by us (NULL if we dont host data, emptyset if we host to ourself excl.) */
00918   std::list< TBaseSet<T,Cmp>* >* mpClients;
00919 
00920   /** Indicate "hosts data to myself only" */
00921   bool mDetached;
00922 
00923   /** Indicate "dont re-allocate the STL set ever again" */
00924   bool mLocked;
00925 
00926   /** Ensure that we do not host contents to anyone else */
00927   void RelinkClients(void);
00928 
00929   /** Record that we provide contents to some other BaseSet */
00930   void AttachClient(TBaseSet* pRef) const;
00931 
00932   /** Record that we stop providing data for some TBaseSet */
00933   void DetachClient(TBaseSet* pRef) const;
00934 
00935   /** Iterators that refer to this TBaseSet */
00936   std::set< Iterator* > mIterators;
00937 
00938   /** Record that an iterator refers to this TBaseSet */
00939   void AttachIterator(Iterator* pFit) const;
00940 
00941   /** Record that an iterator stops to refer to this TBaseSet */
00942   void DetachIterator(Iterator* pFit) const;
00943 
00944   /** Implementation of union */
00945   void FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00946 
00947   /** Implementation of difference */
00948   void FnctDifference(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00949 
00950   /** Implementation of intersection */
00951   void FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00952 
00953   /** TypeDefinition cache (should use guarded pointer here) */
00954   const TypeDefinition* pTypeDefinition;
00955 
00956   /** Reimplment from type to use chache */
00957   virtual const TypeDefinition* TypeDefinitionp(void) const;
00958 
00959   /** Get name of elements (used for XML IO) */
00960   virtual const std::string& XElementTag(void) const;
00961 
00962   /** static empty STL set for default constructor */
00963   static std::set<T,Cmp> msEmptySet;
00964 
00965   /** static empty STL map for default constructor */
00966   static std::map<T,AttributeVoid*> msEmptyAttributes;
00967 
00968   /** static empty STL client list */
00969   // std::list< TBaseSet<T,Cmp>* >* msEmptyClients;
00970 
00971 private:
00972 
00973   /** Current/cached name of elements (used protected accessor method) */
00974   std::string  mXElementTag;
00975 
00976   /** Current/cached faudes type-name */
00977   std::string  mFaudesTypeName;
00978 
00979 
00980 };
00981 
00982 
00983 
00984 /* 
00985  * Set union, rti wrapper
00986  *
00987  * @param rSetA
00988  *  Set A
00989  * @param rSetB
00990  *  Set B
00991  * @return
00992  *  Union of set A and set B
00993  */
00994 
00995 template<class T, class Cmp>
00996 void SetUnion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
00997   FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): res at " << &rRes);
00998   // fix name
00999   std::string name=CollapsString(rSetA.Name() + "+" + rSetB.Name());
01000   // all the same
01001   if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
01002   // a and b ths same, res different
01003   if(&rSetA==&rSetB) {rRes.Assign(rSetA); rRes.Name(name); return;}
01004   // a and res the same, b different 
01005   if(&rSetA==&rRes) {rRes.InsertSet(rSetB); rRes.Name(name); return;};
01006   // b and res the same, a different 
01007   if(&rSetB==&rRes) {rRes.InsertSet(rSetA); rRes.Name(name); return;};
01008   // else
01009   rRes.Assign(rSetA);
01010   rRes.InsertSet(rSetB);
01011   rRes.Name(name); 
01012   FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): done, res at " << &rRes << " #" << rRes.Size());
01013 }
01014 
01015 /* 
01016  * Set intersection, rti wrapper
01017  *
01018  * @param rSetA
01019  *  Set A
01020  * @param rSetB
01021  *  Set B
01022  * @return
01023  *  Set A intersected with set B
01024  */
01025 template< class T, class Cmp >
01026 void SetIntersection(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
01027   // fix name
01028   std::string name=CollapsString(rSetA.Name() + "*" + rSetB.Name());
01029   // all the same
01030   if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
01031   // a and b ths ame, res different
01032   if(&rSetA==&rSetB) { rRes.Assign(rSetA); rRes.Name(name); return;}
01033   // a and res the same, b different 
01034   if(&rSetA==&rRes) {rRes.RestrictSet(rSetB); rRes.Name(name); return;};
01035   // b and res the same, a different 
01036   if(&rSetB==&rRes) {rRes.RestrictSet(rSetA); rRes.Name(name); return;};
01037   // else
01038   rRes.Assign(rSetA);
01039   rRes.RestrictSet(rSetB);
01040   rRes.Name(name); 
01041 }
01042 
01043 
01044 /* 
01045  * Set difference, rti wrapper
01046  *
01047  * @param rSetA
01048  *  Set A
01049  * @param rSetB
01050  *  Set B
01051  * @return
01052  *  Set A minus set B
01053  */
01054 template< class T, class Cmp >
01055 void SetDifference(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
01056   // fix name
01057   std::string name=CollapsString(rSetA.Name() + "-" + rSetB.Name());
01058   // a and b the same
01059   if(&rSetA==&rSetB) { rRes.Clear(); rRes.Name(name); return;}
01060   // a and res the same, b different 
01061   if(&rSetA==&rRes) {rRes.EraseSet(rSetB); rRes.Name(name); return;};
01062   // b and res the same, a different ... need buffer?
01063   if(&rSetB==&rRes) {
01064     TBaseSet<T,Cmp>* buffb=rSetB.Copy();
01065     rRes.Assign(rSetA);
01066     rRes.EraseSet(*buffb); 
01067     rRes.Name(name); 
01068     delete buffb;
01069     return;
01070   }; 
01071   // else: std
01072   rRes.Assign(rSetA);
01073   rRes.EraseSet(rSetB);
01074   rRes.Name(name); 
01075 }
01076 
01077 /* 
01078  * Set equality, rti wrapper
01079  * This method ignores attributes.
01080  *
01081  * @param rSetA
01082  *  Set A
01083  * @param rSetB
01084  *  Set B
01085  * @return
01086  *  True for matching sets.
01087  */
01088 template< class T, class Cmp >
01089 bool SetEquality(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
01090   return rSetA==rSetB;
01091 }
01092 
01093 /* 
01094  * Set inclusion, rti wrapper
01095  * This method ignores attributes.
01096  *
01097  * @param rSetA
01098  *  Set A
01099  * @param rSetB
01100  *  Set B
01101  * @return
01102  *  True for matching sets.
01103  */
01104 template< class T, class Cmp >
01105 bool SetInclusion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
01106   return rSetA<=rSetB;
01107 }
01108 
01109 
01110 
01111 
01112 /** @} doxygen group */
01113 
01114 
01115 
01116 /*
01117 ******************************************************************************************
01118 ******************************************************************************************
01119 ******************************************************************************************
01120 
01121 Implementation of TBaseSet
01122 
01123 ******************************************************************************************
01124 ******************************************************************************************
01125 ******************************************************************************************
01126 */
01127 
01128 /* convenience access to relevant scopes */
01129 #define THIS TBaseSet<T,Cmp> 
01130 #define TEMP template<class T, class Cmp>
01131 #define BASE Type
01132 
01133 
01134 // faudes type std: new and cast
01135 FAUDES_TYPE_TIMPLEMENTATION_NEW(Void,THIS,Type,TEMP)
01136 FAUDES_TYPE_TIMPLEMENTATION_COPY(Void,THIS,Type,TEMP)
01137 FAUDES_TYPE_TIMPLEMENTATION_CAST(Void,THIS,Type,TEMP)
01138 
01139 // faudes type std: assignemnt (break cast)
01140 //TEMP THIS& THIS::Assign(const Type& rSrc) { this->Clear(); return *this;};
01141 //TEMP THIS& THIS::Assign(const THIS& rSrc) { DoAssign(rSrc); return *this;};
01142 
01143 // faudes type std: assignemnt (keep cast)
01144 FAUDES_TYPE_TIMPLEMENTATION_ASSIGN(Void,THIS,Type,TEMP)
01145 FAUDES_TYPE_TIMPLEMENTATION_EQUAL(Void,THIS,Type,TEMP)
01146 
01147 
01148 // template statics: empty set
01149 TEMP std::set<T,Cmp>  THIS::msEmptySet=std::set<T,Cmp>();
01150 TEMP std::map<T,AttributeVoid*> THIS::msEmptyAttributes=std::map<T,AttributeVoid*>();
01151 
01152 // TBaseSet()
01153 TEMP THIS::TBaseSet(void) :
01154   Type(),
01155   pSet(&msEmptySet),  
01156   pAttributes(&msEmptyAttributes),
01157   mpSet(NULL),
01158   mpAttributes(NULL),
01159   pHostSet(this),
01160   mpClients(new std::list< TBaseSet<T,Cmp>* >),
01161   mDetached(false), 
01162   mLocked(false),
01163   pTypeDefinition(NULL)
01164 {
01165   FAUDES_OBJCOUNT_INC("BaseSet");
01166   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
01167   // other members
01168   mMyName="BaseSet";
01169 }
01170 
01171 // TBaseSet(filename)
01172 TEMP THIS::TBaseSet(const std::string& rFileName, const std::string& rLabel)  :
01173   Type(),
01174   pSet(&msEmptySet),  
01175   pAttributes(&msEmptyAttributes),
01176   mpSet(NULL),
01177   mpAttributes(NULL),
01178   pHostSet(this),
01179   mpClients(new std::list< TBaseSet<T,Cmp>* >),
01180   mDetached(false), 
01181   mLocked(false), 
01182   pTypeDefinition(NULL)
01183 {
01184   FAUDES_OBJCOUNT_INC("BaseSet");
01185   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
01186   // other members
01187   mMyName="BaseSet";
01188   // do read etc ... this is a dummy anyway
01189   Read(rFileName,rLabel);  
01190 }
01191 
01192 // TBaseSet(rOtherSet)
01193 TEMP THIS::TBaseSet(const TBaseSet& rOtherSet) : 
01194   Type(rOtherSet),
01195   pSet(&msEmptySet),  
01196   pAttributes(&msEmptyAttributes),
01197   mpSet(NULL),  
01198   mpAttributes(NULL),
01199   pHostSet(this),
01200     mpClients(new std::list< TBaseSet<T,Cmp>* >), // small detour ... for readability
01201   mDetached(false), 
01202   mLocked(false),
01203   pTypeDefinition(NULL)
01204 {
01205   FAUDES_OBJCOUNT_INC("BaseSet");
01206   FD_DC("TBaseSet(" << this << ")::TBaseSet(rOtherSet " << &rOtherSet << "): fake copy construct");
01207   // run assignment
01208   DoAssign(rOtherSet);
01209 #ifdef FAUDES_DEBUG_CODE
01210   DValid("CopyConstruct");
01211 #endif
01212 }
01213 
01214 // destructor
01215 TEMP THIS::~TBaseSet(void) {
01216   FAUDES_OBJCOUNT_DEC("BaseSet");
01217   FD_DC("TBaseSet(" << this << ")::~TBaseSet()");
01218   // maintain deferred copy 
01219   RelinkClients();
01220   pHostSet->DetachClient(this);
01221   if(mpClients) delete mpClients;
01222   mpClients=NULL;
01223   // unlink iterators (mandatory, since referenced object will be destructed)
01224   typename std::set< Iterator* >::const_iterator iit;
01225   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01226     (**iit).Invalidate();
01227   }
01228   // delete if we still own data
01229   if(mpSet) delete mpSet;
01230   if(mpAttributes) {
01231     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01232        delete ait->second;
01233     delete mpAttributes;
01234   }
01235 }
01236 
01237 
01238 // fake copy
01239 TEMP void THIS::DoAssign(const THIS& rSourceSet) {
01240   FD_DC("TBaseSet(" << this << ")::DoAssign(rOtherSet " << &rSourceSet << "): fake copy");
01241   // bail out on selfref
01242   if(this==&rSourceSet) return;
01243   // other members 
01244   mMyName=rSourceSet.mMyName;
01245   // bail out on common shared data
01246   if(pHostSet==rSourceSet.pHostSet) return;
01247   // become independant
01248   RelinkClients();
01249   pHostSet->DetachClient(this);
01250   // if we are locked, should do the copy ... not implemented
01251 #ifdef FAUDES_DEBUG_CODE
01252   if(mLocked) {
01253     FD_ERR("TBaseSet::DoAssign(): locked target will be unlocked: not implemented");
01254     abort();
01255   }
01256 #endif
01257   // attatch myself to src host 
01258   pHostSet=rSourceSet.pHostSet;
01259   pHostSet->AttachClient(this);
01260   pSet=rSourceSet.pSet;
01261   pAttributes=&msEmptyAttributes;
01262   // delete own old data
01263   if(mpSet) { 
01264      delete mpSet;
01265      mpSet=NULL;
01266   }
01267   if(mpAttributes) {
01268     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01269        delete ait->second;
01270     delete mpAttributes;
01271     mpAttributes=NULL;
01272   }
01273   if(mpClients) {
01274     delete mpClients;
01275     mpClients=NULL;
01276   }
01277   // record state
01278   mDetached=false; 
01279   mLocked=false;
01280   // fix iterators (invalidate)
01281   typename std::set< Iterator* >::iterator iit;
01282   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01283     (**iit).Invalidate();
01284   }
01285   mIterators.clear();
01286 #ifdef FAUDES_DEBUG_CODE
01287   DValid("PostFakeAssignment");
01288 #endif
01289 }
01290 
01291 // Detach()
01292 TEMP void THIS::Detach(void) const {
01293   FD_DC("TBaseSet(" << this << ")::Detach(void)");
01294 #ifdef FAUDES_DEBUG_CODE
01295   DValid("PreDetach");
01296 #endif
01297 
01298   // nothing todo
01299   if(mDetached) return;
01300 
01301   // provide fake const
01302   THIS* fake_const = const_cast< THIS* >(this);
01303 
01304 #ifdef FAUDES_DEBUG_CODE
01305   // might have missed reference detach
01306   if(pHostSet==this)
01307   if(pSet!=&msEmptySet)
01308   if(mpClients)
01309   if(mpClients->empty()) {
01310     FD_ERR("TBaseSet(" << this << ")::Detach(void): missed detach (?)");
01311     abort();                     // strict
01312     fake_const->mDetached=true;  // fix
01313   }
01314 #endif
01315 
01316   // stragie A: clients get the new copy; thus, the baseset data does
01317   // not get reallocated and we dont need to track iterators; on the
01318   // downside, fixing the references iterators may be more effort.
01319   if(mLocked==true) {
01320    
01321     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie A");
01322     // do allocation and copy of stl set
01323     std::set<T,Cmp>* scopy = new std::set<T,Cmp>();
01324     *scopy = *pSet;     
01325     // first of my clients gets the new data and the old attributes
01326     THIS* newhost = *mpClients->begin();
01327     newhost->pHostSet=newhost;
01328     newhost->mpSet=scopy; 
01329     newhost->pSet=scopy;
01330     newhost->mpAttributes=mpAttributes;
01331     newhost->pAttributes=pAttributes;
01332     newhost->mpClients=mpClients;
01333     newhost->DetachClient(newhost);
01334     // set other users to use the new host
01335     typename std::list< THIS* >::const_iterator rit;
01336     for(rit=newhost->mpClients->begin();rit!=newhost->mpClients->end(); ++rit) {
01337       (*rit)->pHostSet=newhost;
01338       (*rit)->pSet=newhost->pSet;
01339       (*rit)->pAttributes=newhost->pAttributes;
01340     }
01341     // fix newhost clients iterators 
01342     typename std::set< Iterator* >::iterator iit;
01343     for(rit=newhost->mpClients->begin(); rit!=newhost->mpClients->end(); ++rit) {
01344       for(iit=(*rit)->mIterators.begin(); iit!=(*rit)->mIterators.end(); ++iit) {
01345         if((**iit).StlIterator()==pSet->end()) 
01346           **iit=Iterator(this, scopy->end());
01347         else
01348           **iit=Iterator(this, scopy->find(***iit));
01349       }
01350     }
01351     // fix newhost iterators 
01352     for(iit=newhost->mIterators.begin(); iit!=newhost->mIterators.end(); ++iit) {
01353       if((**iit).StlIterator()==pSet->end()) 
01354         **iit=Iterator(this, scopy->end());
01355       else
01356         **iit=Iterator(this, scopy->find(***iit));
01357     }
01358     // make myself own the old data and have empty attributes
01359     fake_const->mpSet=pSet;
01360     fake_const->mpAttributes=NULL;
01361     fake_const->pAttributes=&msEmptyAttributes;
01362     fake_const->mpClients= new std::list< TBaseSet<T,Cmp>* >;
01363     fake_const->mDetached=true;    
01364     // stop tracking my iterators
01365     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01366       (**iit).Detach();
01367     }
01368     fake_const->mIterators.clear();
01369 
01370 
01371   // stragie B: this baseset gets the copy; thus, the clients iterators
01372   // remain valid and dont need to be fixed; on the downside, we need to
01373   // continue to track our iterators.
01374   } else {
01375 
01376 
01377     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie B");
01378     // make someone else handle original data
01379     fake_const->RelinkClients();
01380     pHostSet->DetachClient(fake_const);
01381     // do allocation and copy of stl set
01382     fake_const->mpSet = new std::set<T,Cmp>();
01383     *fake_const->mpSet= *pSet;     
01384     // have empty attributes
01385     fake_const->mpAttributes=NULL;
01386     fake_const->pAttributes=&msEmptyAttributes;
01387     // fix my iterators
01388     typename std::set< Iterator* >::iterator iit;
01389     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01390       if((**iit).StlIterator()==pSet->end()) 
01391         **iit=Iterator(this, mpSet->end());
01392       else
01393         **iit=Iterator(this, mpSet->find(***iit));
01394     }
01395     // record myself as my newhost
01396     fake_const->pHostSet=fake_const;
01397     fake_const->pSet=mpSet;
01398     fake_const->mDetached=true;
01399     fake_const->mpClients= new std::list< TBaseSet<T,Cmp>* >;
01400   }
01401 
01402 #ifdef FAUDES_DEBUG_CODE
01403   DValid("PostDetach");
01404 #endif
01405   FD_DC("TBaseSet(" << this << ")::Detach(void): done");
01406 }
01407 
01408 // Lock()
01409 TEMP  void THIS::Lock(void) const {
01410   FD_DC("TBaseSet(" << this << ")::Lock(void)");
01411 #ifdef FAUDES_DEBUG_CODE
01412   DValid("PreLock");
01413 #endif
01414   // if we are locked: fine
01415   if(mLocked) return;
01416 
01417   // trigger actual copy
01418   Detach();
01419 
01420   // provide fake const
01421   THIS* fake_const = const_cast< THIS* >(this);
01422 
01423   // stop tracking iterators
01424   typename std::set< Iterator* >::const_iterator iit;
01425   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01426     (**iit).Detach();
01427   }
01428   fake_const->mIterators.clear();
01429 
01430   // stop detach from reallocating
01431   fake_const->mLocked=true;
01432 
01433 #ifdef FAUDES_DEBUG_CODE
01434   DValid("PostLock");
01435 #endif
01436 }
01437 
01438 
01439 // if i am a host to others, make someone else the host
01440 TEMP inline void THIS::RelinkClients(void) {
01441   FD_DC("TBaseSet::RelinkClients(" << this << ")")
01442 #ifdef FAUDES_DEBUG_CODE
01443   DValid("PreRelink");
01444 #endif
01445 
01446   // no clients, so i dont host data anyway
01447   if(!mpClients) return;
01448   // empty clients, so i only host to myself
01449   if(mpClients->empty()) return;
01450 
01451   FD_DC("TBaseSet::RelinkClients(" << this << "): doit")
01452 
01453   // make first client the new newhost
01454   THIS* newhost = *mpClients->begin();
01455 #ifdef FAUDES_DEBUG_CODE
01456   if(newhost->pHostSet!=this) {
01457     FD_ERR("BaseSet::RelinkRefernces: old reference must have this as provider");
01458     abort();
01459   }
01460 #endif
01461   newhost->pHostSet=newhost;
01462   newhost->mpSet=mpSet; 
01463   newhost->pSet=pSet;
01464   newhost->mpAttributes=mpAttributes; 
01465   newhost->pAttributes=pAttributes;
01466   newhost->mpClients=mpClients;
01467   newhost->DetachClient(newhost);
01468   // set other users to new newhost
01469   typename std::list< THIS* >::const_iterator rit;
01470   for(rit=newhost->mpClients->begin();rit!=newhost->mpClients->end(); ++rit) {
01471     (*rit)->pHostSet=newhost;
01472   }
01473   // make myself a reference to the new source
01474   pHostSet=newhost;
01475   pSet=newhost->pSet;
01476   mpSet=NULL;
01477   pAttributes=newhost->pAttributes;
01478   mpAttributes=NULL;
01479   newhost->AttachClient(this);
01480   mpClients=NULL;
01481 #ifdef FAUDES_DEBUG_CODE
01482   DValid("PostRelink");
01483 #endif
01484   FD_DC("TBaseSet::RelinkClients(" << this << "): done")
01485 }
01486 
01487 
01488 // record fake copy
01489 TEMP inline void THIS::AttachClient(TBaseSet* pRef) const {
01490   if(!mpClients) const_cast< THIS* >(this)->mpClients=new std::list< TBaseSet<T,Cmp>* >;
01491   const_cast< THIS* >(this)->mpClients->push_back(pRef);
01492   pRef->mClientRecord= -- mpClients->end();
01493   const_cast< THIS* >(this)->mDetached=false;
01494 }
01495 
01496 // discard fake copy
01497 TEMP inline void THIS::DetachClient(TBaseSet* pRef) const {
01498   FD_DC("TBaseSet::DetachClient(" << this << "):" << pRef);
01499   // bail out on trivials
01500   if(!mpClients) return;
01501   if(mpClients->empty()) return;
01502   if(pRef->pHostSet!=this) return;
01503   // provide fake const
01504   THIS* fake_const = const_cast< THIS* >(this);
01505 #ifdef FAUDES_DEBUG_CODE
01506   // find and remove that client
01507   typename std::list< TBaseSet<T,Cmp>* >::iterator cit;
01508   bool cf=false;
01509   for(cit=fake_const->mpClients->begin(); cit!=fake_const->mpClients->end(); ++cit) {
01510     if(*cit==pRef) cf=true;
01511   }
01512   if(!cf) {
01513     FD_ERR("TBaseSet::DetachClient(" << this << "): client not found " << pRef);
01514     abort();
01515   }
01516 #endif  
01517   /*
01518   use recorded client index: performant, and fine when last tested ...
01519   ... however, this really is asking for segfaults.
01520 
01521   // remove from client list
01522   FD_DC("TBaseSet::DetachClient(" << this << "):" << pRef << " must match " << *pRef->mClientRecord);
01523   fake_const->mpClients->erase(pRef->mClientRecord);
01524   */
01525   // remove from client list
01526   typename std::list< TBaseSet<T,Cmp>* >::iterator rit; 
01527   for(rit=fake_const->mpClients->begin(); rit!=fake_const->mpClients->end(); ++rit) {
01528     if(*rit!=pRef) continue;
01529     fake_const->mpClients->erase(rit);
01530     break; 
01531   }
01532   // figure detached status
01533   if(mpClients->empty() && (pSet!=&msEmptySet)) fake_const->mDetached=true;
01534   FD_DC("TBaseSet::DetachClient(" << this << "): done.");
01535 }
01536 
01537 
01538 // record an iterator
01539 TEMP inline void THIS::AttachIterator(Iterator* pFit) const {
01540   if(mLocked) return;
01541   FD_DC("TBaseSet::AttachIterator(" << this << "):" << pFit)
01542   const_cast< THIS* >(this)->mIterators.insert(pFit);
01543 }
01544 
01545 // discard an iterator
01546 TEMP inline void THIS::DetachIterator(Iterator* pFit) const {
01547   if(mLocked) return;
01548   FD_DC("TBaseSet::DetachIterator(" << this << "):" << pFit)
01549   const_cast< THIS* >(this)->mIterators.erase(pFit);
01550 }
01551 
01552 // test some validity
01553 TEMP void THIS::DValid(const std::string& rMessage) const {
01554   typename std::set< Iterator* >::const_iterator iit;
01555   typename std::list< THIS* >::const_iterator rit;
01556 #ifdef FAUDES_DEBUG_CONTAINER
01557   std::cerr << "TBaseSet(" << this << ")::DValid(): " << rMessage << " source " 
01558      << pHostSet << " " << (pHostSet->pSet==&msEmptySet ? "+e+" : "+f+") << 
01559         (mLocked ? " +l+" : " ") << (mDetached ? " +d+" : " ") << " -- refs ";
01560   if(pHostSet->mpClients)
01561   for(rit=pHostSet->mpClients->begin(); rit!=pHostSet->mpClients->end(); ++rit)
01562     std::cerr << *rit << " ";
01563   std::cerr << "-- its ";
01564   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit)
01565     std::cerr << *iit << " ";
01566   std::cerr << "-- attr #" << pAttributes->size();
01567   if(mpAttributes) std::cerr << "(" << mpAttributes->size() << ") ";
01568   else std::cerr << " ";
01569   std::cerr << (pAttributes==&msEmptyAttributes ? "+e+ " : "+f+ ") << std::endl;
01570 #endif
01571   // iterators, that dont refer to me as basset
01572   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01573     if((*iit)->pBaseSet!=this) {
01574       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (baseset): "<< *iit);
01575       abort();
01576     }
01577   }
01578   // iterators, that are not marked as attached
01579   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01580     if(!(*iit)->mAttached) {
01581       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (attached): "<< *iit);
01582       abort();
01583     }
01584   }
01585   // iterators, that are invalid stl iterators
01586   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01587     typename std::set<T,Cmp>::const_iterator vit;
01588     for(vit=pSet->begin(); vit!= pSet->end(); ++vit) {
01589       if(vit==(**iit).StlIterator()) break;
01590     }
01591     if(vit!=(**iit).StlIterator()) { // end-iterator is fine, too
01592       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (stl) "<< *iit);
01593       (**iit).StlIterator(pSet->end()); // fix invalid iterator to refer to end()
01594       abort(); // strict version: abort
01595     }
01596   }
01597   // must have some base 
01598   if(pHostSet==NULL) {
01599     FD_ERR("BaseSet(" << this << "," << rMessage << "): no host found");
01600     abort();
01601   }
01602   // hosts mut be consistent
01603   if(pHostSet->pHostSet != pHostSet) {
01604     FD_ERR("BaseSet(" << this << "," << rMessage << "): inconsistent host");
01605     abort();
01606   }
01607   // refers to other base and own data
01608   if((mpSet!=NULL) && (pHostSet != this)) {
01609     FD_ERR("BaseSet(" << this << "," << rMessage << "): double data");
01610     abort();
01611   }
01612   // refers to other base and has references
01613   if(pHostSet!=this && mpClients!=NULL) {
01614     FD_ERR("BaseSet(" << this << "," << rMessage << "): cannot be client and have clients oneself");
01615     abort();
01616   }
01617   // refers to invalid base 
01618   if(pHostSet->mpClients==NULL) {
01619     FD_ERR("BaseSet(" << this << "," << rMessage << "): refers to invalid host (a)");
01620     abort();
01621   }
01622   // refers to invalid base 
01623   if(pHostSet!=this && pHostSet->mpClients->empty()) {
01624     FD_ERR("BaseSet(" << this << "," << rMessage << "): refers to invalid host (b)");
01625     abort();
01626   }
01627   // is base but has no own data
01628   if((pHostSet == this) && (mpSet==NULL) && (pSet!=&msEmptySet)) {
01629     FD_ERR("BaseSet(" << this << "," << rMessage << "): no data");
01630     abort();
01631   }
01632   // is base, but has no client list
01633   if((pHostSet==this) && (pSet!=&msEmptySet) && (mpClients==NULL)) {
01634     FD_ERR("BaseSet(" << this << "," << rMessage << "): host with no client list");
01635     abort();
01636   }
01637   // is base but own data pointer mismatch
01638   if((pHostSet == this) && (pSet != mpSet) && (pSet!=&msEmptySet)) {
01639     FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch A");
01640     abort();
01641   }
01642   // refers to base with data pointer mismatch
01643   if(pSet != pHostSet->pSet) {
01644     FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch B");
01645     abort();
01646   }
01647   // test all clients from hosts list
01648   bool hf=false;
01649   for(rit=pHostSet->mpClients->begin(); rit!=pHostSet->mpClients->end(); ++rit) {
01650     if((*rit)== this) hf=true;
01651     if((*rit)->pHostSet== pHostSet) continue;
01652     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid client " << (*rit));
01653     abort();
01654   }
01655   if(!hf && (pHostSet!=this)) {
01656     FD_ERR("BaseSet(" << this << "," << rMessage << "): client not registered with host");
01657     abort();
01658   }
01659   // refers to invalid base 
01660   if(pHostSet!=this && *mClientRecord!=this) {
01661     FD_ERR("BaseSet(" << this << "," << rMessage << "): refers to invalid host (c)");
01662     abort();
01663   } 
01664   // error in detached flag
01665   if(mDetached && mpClients==NULL) {
01666     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid detached flag A");
01667     abort();
01668   }
01669   // error in detached flag
01670   if(mDetached && !mpClients->empty()) {
01671     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid detached flag B");
01672     abort();
01673   }
01674   // error in detached flag
01675   if(mDetached && (pSet==&msEmptySet)) {
01676     FD_ERR("BaseSet(" << this << "," << rMessage << "): detached empty set");
01677     abort();
01678   }
01679   // error in lock flag
01680   if(mLocked && (mpClients==NULL)) {
01681     FD_ERR("BaseSet(" << this << "," << rMessage << "): locked reference (a)");
01682     abort();
01683   }
01684   // invalid emptyset
01685   if(!msEmptySet.empty()) {
01686     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty set");
01687     abort();
01688   }
01689   // invalid emptyset
01690   if(!msEmptyAttributes.empty()) {
01691     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty attributes");
01692     abort();
01693   }
01694 #ifdef FAUDES_DEBUG_CONTAINER
01695   std::cerr << "TBaseSet(" << this << ")::DValid(): passed" << std::endl;
01696 #endif
01697 }
01698 
01699 
01700 
01701 // Name
01702 TEMP const std::string& THIS::Name(void) const {
01703   return mMyName;
01704 }
01705     
01706 // Name
01707 TEMP void THIS::Name(const std::string& rName) {
01708   mMyName = rName;
01709 }
01710   
01711 
01712 // TypeDefinitionp()
01713 // Note: fake const construct
01714 TEMP const TypeDefinition* THIS::TypeDefinitionp(void) const {
01715   if(!pTypeDefinition) {
01716     // provide fake const
01717     THIS* fake_const = const_cast< THIS* >(this);
01718     fake_const->pTypeDefinition=TypeRegistry::G()->Definitionp(*this);
01719   }
01720   return pTypeDefinition;
01721 }
01722 
01723 // ElementTag
01724 TEMP const std::string& THIS::XElementTag(void) const {
01725   if(mXElementTag.empty()) {
01726     // provide fake const
01727     THIS* fake_const = const_cast< THIS* >(this);
01728     fake_const->mXElementTag="Element";
01729     const TypeDefinition* fdp=TypeDefinitionp();
01730     if(fdp) fake_const->mXElementTag=fdp->XElementTag();
01731   }
01732   return mXElementTag;
01733 }
01734 
01735 // ElementTag
01736 TEMP void THIS::XElementTag(const std::string& rTag) {
01737   mXElementTag=rTag;
01738 }
01739 
01740 
01741 // Faudes Type
01742 TEMP const std::string& THIS::TypeName(void) const {
01743   if(mFaudesTypeName.empty()) {
01744     // provide fake const
01745     THIS* fake_const = const_cast< THIS* >(this);
01746     const TypeDefinition* fdp=TypeDefinitionp();
01747     if(fdp) fake_const->mFaudesTypeName=fdp->Name();
01748   }
01749   return mFaudesTypeName;
01750 }
01751 
01752 // ElementTag
01753 TEMP void THIS::TypeName(const std::string& rType) {
01754   mFaudesTypeName=rType;
01755 }
01756 
01757 
01758 // Str
01759 TEMP std::string THIS::Str(const T& rElem) const { 
01760   (void) rElem;
01761   std::string res=""; 
01762   return res; 
01763 }
01764 
01765 // Size()
01766 TEMP Idx THIS::Size(void) const {
01767   return (Idx) pSet->size();
01768 }
01769 
01770 // Empty()
01771 TEMP bool THIS::Empty(void) const {
01772   return pSet->empty();
01773 }
01774 
01775 
01776 // DoWrite(tw,rLabel,cpntext)
01777 TEMP void THIS::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
01778   (void) pContext;
01779   std::string label=rLabel;
01780   if(label=="") label=Name(); 
01781   if(label=="") label="BaseSet"; 
01782   FD_DC("TBaseSet(" << this << ")::DoWrite(..): section " << label << " #" << Size());
01783   rTw.WriteBegin(label);
01784   rTw.WriteEnd(label);
01785 }
01786 
01787 
01788 // DoDWrite(tw, label, context)
01789 TEMP void THIS::DoDWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
01790   (void) pContext;
01791   (void) rLabel;
01792   BASE::DoSWrite(rTw);
01793   int shares=0;
01794   if(pHostSet->mpClients) shares=pHostSet->mpClients->size();
01795   rTw.WriteComment("");
01796   rTw.WriteComment(" Size/Attributes: " + ToStringInteger(pSet->size()) 
01797         + "/" + ToStringInteger(pHostSet->pAttributes->size()));
01798   rTw.WriteComment(" Shares/Iterators: " + ToStringInteger(shares) 
01799         + "/" + ToStringInteger(mIterators.size()));
01800   rTw.WriteComment("");
01801 #ifdef FAUDES_DEBUG_CODE
01802   DValid();
01803 #endif
01804 }
01805 
01806 // DoSWrite()
01807 TEMP void THIS::DoSWrite(TokenWriter& rTw) const {
01808   BASE::DoSWrite(rTw);
01809   int shares=0;
01810   if(pHostSet->mpClients) shares=pHostSet->mpClients->size();
01811   rTw.WriteComment(" Size: " + ToStringInteger(pSet->size()));
01812   rTw.WriteComment(" Shared Data: #" + ToStringInteger(shares) + " clients");
01813   if(pAttributes->size()!=0)
01814     rTw.WriteComment(" Attributes: " +ToStringInteger(pAttributes->size()));
01815   if(pAttributes->size()!=0) {
01816     AttributeVoid* attr = pAttributes->begin()->second;
01817     rTw.WriteComment(" Attribute Type: " +FaudesTypeName(*attr));
01818   } 
01819 }
01820 
01821 // DoRead(rTr, rLabel, pContext)
01822 TEMP void THIS::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
01823   (void) pContext;
01824   std::string label=rLabel;
01825   if(label=="") label=Name(); 
01826   if(label=="") label="BaseSet"; 
01827   Name(label);
01828   rTr.ReadBegin(label); 
01829   rTr.ReadEnd(label); 
01830 }
01831 
01832 // ThisIterator
01833 TEMP typename THIS::Iterator THIS::ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const {
01834   return Iterator(this,sit);
01835 }
01836 
01837 // Begin() const
01838 TEMP inline typename THIS::Iterator THIS::Begin(void) const {
01839   return ThisIterator(pSet->begin());
01840 }
01841     
01842 // End() const
01843 TEMP inline typename THIS::Iterator THIS::End(void) const {
01844   return ThisIterator(pSet->end());
01845 }
01846 
01847 
01848 //Clear
01849 TEMP void THIS::Clear(void) {
01850   FD_DC("TBaseSet(" << this << ")::Clear()");
01851 #ifdef FAUDES_DEBUG_CODE
01852   DValid("PreClear");
01853 #endif
01854   // special case: empty anyway
01855   if(pSet==&msEmptySet) return;
01856   FD_DC("TBaseSet(" << this << ")::Clear(): doit");
01857 
01858   // special case: locked requires a copy (not efficient!)
01859   if(mLocked) Detach();
01860   // make someone else handle the data
01861   RelinkClients();
01862   pHostSet->DetachClient(this);
01863   // make myself host
01864   pHostSet=this;
01865   if(!mpClients) mpClients= new std::list< TBaseSet<T,Cmp>* >;
01866   mpClients->clear();
01867   // if we hold data, clear it
01868   if(mpSet) {
01869     delete mpSet;
01870     mpSet=NULL;
01871   }
01872   // if we hold data, clear it
01873   if(mpAttributes) {
01874     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01875        delete ait->second;
01876     delete mpAttributes;
01877     mpAttributes=NULL;
01878   }
01879   // set to empty set
01880   pSet=&msEmptySet;
01881   pAttributes=&msEmptyAttributes;
01882   // fix iterators (invalidate)
01883   typename std::set< Iterator* >::iterator iit;
01884   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01885     (**iit).Invalidate();
01886   }
01887   mIterators.clear();
01888   mDetached=false;
01889   mLocked=false;
01890 #ifdef FAUDES_DEBUG_CODE
01891   DValid("PostClear");
01892 #endif
01893 }
01894 
01895 
01896 //Valid(elem)
01897 TEMP inline bool  THIS::Valid(const T& rElem) const {
01898   (void) rElem;
01899   return true;
01900 }
01901 
01902 //Insert(elem)
01903 TEMP bool THIS::Insert(const T& rElem) {
01904 #ifdef FAUDES_CHECKED
01905   if(!Valid(rElem)) {
01906     std::stringstream errstr;
01907     errstr << "cannot insert invalid element" << std::endl;
01908     throw Exception("BaseSet::Insert", errstr.str(), 61);
01909   }
01910 #endif
01911   if(!mDetached) Detach();
01912   return pSet->insert(rElem).second;
01913 }
01914 
01915 // InsertSet(set)
01916 TEMP void THIS::InsertSet(const TBaseSet& rOtherSet) {
01917   FD_DC("TBaseSet(" << this << ")::InsertSet(" << &rOtherSet << ")");
01918   if(!mDetached) Detach();
01919   /*
01920   rem: cannot use stl since result overlaps with arguments
01921 
01922   std::insert_iterator< std::set<T,Cmp> > insit(*pSet, rpSet->begin());
01923   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01924   */
01925   iterator it1 = pSet->begin();
01926   iterator it2 = rOtherSet.pSet->begin();
01927   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01928     if (*it1 < *it2) {
01929       ++it1;
01930     }
01931     else if (*it1 == *it2) {
01932       ++it1;
01933       ++it2;
01934     }
01935     else { // (*it1 > *it2)
01936       pSet->insert(*it2);
01937       ++it2;
01938     }
01939   }
01940   while (it2 != rOtherSet.pSet->end()) {
01941     pSet->insert(*it2);
01942     ++it2;
01943   }
01944 }
01945 
01946     
01947 //Erase(rElem)
01948 TEMP bool THIS::Erase(const T& rElem) {
01949   if(!mDetached) Detach();
01950   return (pSet->erase(rElem)!=0);
01951 }
01952 
01953 
01954 //Erase(pos)
01955 TEMP typename THIS::Iterator THIS::Erase(const Iterator& pos) { 
01956 #ifdef FAUDES_CHECKED
01957   if (pos == End()) {
01958     std::stringstream errstr;
01959     errstr << "iterator out of range " << std::endl;
01960     throw Exception("BaseSet::Erase", errstr.str(), 62);
01961   }
01962 #endif
01963   Detach();
01964   iterator del= pos.StlIterator(); 
01965   iterator res= del;
01966   res++; 
01967   pSet->erase(del);
01968   return ThisIterator(res); 
01969 }
01970 
01971 
01972 //EraseSet(set)
01973 TEMP void THIS::EraseSet(const TBaseSet& rOtherSet) {
01974   FD_DC("TBaseSet(" << this << ")::EraseSet(" << &rOtherSet << ")");
01975   if(!mDetached) Detach();
01976   // TODO: test and optimize 
01977   iterator tmpit;
01978   iterator it = pSet->begin();
01979   iterator oit = rOtherSet.pSet->begin();
01980   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
01981     if (*it < *oit) {
01982       it=pSet->lower_bound(*oit); // alt: ++it;
01983     }
01984     else if (*it == *oit) { 
01985       tmpit=it;
01986       ++it;
01987       ++oit;
01988       pSet->erase(tmpit);
01989     }
01990     else { // (*it > *oit)
01991       oit=rOtherSet.pSet->lower_bound(*it); // ++it2;
01992     }
01993   }
01994 }
01995 
01996 
01997 //RestrictSet(set)
01998 TEMP void THIS::RestrictSet(const TBaseSet& rOtherSet) {
01999   FD_DC("TBaseSet(" << this << ")::RestrictSet(" << &rOtherSet << ")");
02000   if(!mDetached) Detach();
02001   // TODO: test and optimize 
02002   iterator tmpit;
02003   iterator it = pSet->begin();
02004   iterator oit = rOtherSet.pSet->begin();
02005   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
02006     if (*it < *oit) {
02007       tmpit=it;
02008       ++it;
02009       pSet->erase(tmpit);
02010     }
02011     else if (*it == *oit) { 
02012       ++it;
02013       ++oit;
02014     }
02015     else { // (*it > *oit)
02016       oit=rOtherSet.pSet->lower_bound(*it); 
02017     }
02018   }
02019   while(it != pSet->end()) {
02020     tmpit=it;
02021     ++it;
02022     pSet->erase(tmpit);
02023   }
02024 }
02025 
02026 
02027 //Find(elem)
02028 TEMP typename THIS::Iterator THIS::Find(const T& rElem) const {
02029   return ThisIterator(pSet->find(rElem));
02030 }
02031 
02032 //Exists(elem)
02033 TEMP bool  THIS::Exists(const T& rElem) const {
02034   return pSet->find(rElem) != pSet->end();
02035 }
02036 
02037 
02038 // SetUnion(set)
02039 TEMP void THIS::SetUnion(const TBaseSet& rOtherSet) {
02040   if(!mDetached) Detach();
02041   iterator it1 = pSet->begin();
02042   iterator it2 = rOtherSet.pSet->begin();
02043   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
02044     if (*it1 < *it2) {
02045       ++it1;
02046       continue;
02047     }
02048     if (*it1 == *it2) {
02049       ++it1;
02050       ++it2;
02051       continue;
02052     }
02053     // (*it1 > *it2)
02054     pSet->insert(it1,*it2);
02055     ++it2;
02056   }
02057   while (it2 != rOtherSet.pSet->end()) {
02058     pSet->insert(pSet->end(),*it2);
02059     ++it2;
02060   }
02061 }
02062 
02063 // SetIntersection(set)
02064 TEMP void THIS::SetIntersection(const TBaseSet& rOtherSet) {
02065   if(!mDetached) Detach();
02066   iterator tmpit;
02067   iterator it1 = pSet->begin();
02068   iterator it2 = rOtherSet.pSet->begin();
02069   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
02070     if (*it1 < *it2) {
02071       tmpit=it1;
02072       ++it1;
02073       pSet->erase(tmpit);
02074       continue;
02075     }
02076     if (*it1 == *it2) {
02077       ++it1;
02078       ++it2;
02079       continue;
02080     }
02081     // if (*it1 > *it2)
02082     ++it2;
02083   }
02084   while(it1 != pSet->end()) {
02085     tmpit=it1;
02086     ++it1;
02087     pSet->erase(tmpit);
02088   }
02089 }
02090 
02091 
02092 // FnctUnion
02093 TEMP void THIS::FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const {
02094   FD_DC("TBaseSet(" << this << ")::FnctUnion (" << &rOtherSet << ")");
02095   rRes.Detach();
02096   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
02097   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
02098   rRes.Name(CollapsString(Name() + "+" + rOtherSet.Name()));
02099 }
02100 
02101 // FnctDifference
02102 TEMP void THIS::FnctDifference (const TBaseSet& rOtherSet, TBaseSet& rRes) const {
02103   FD_DC("TBaseSet(" << this << ")::FnctDifference (" << &rOtherSet << ")");
02104   rRes.Detach();
02105   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
02106   std::set_difference(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
02107   rRes.Name(CollapsString(Name() + "-" + rOtherSet.Name()));
02108 }
02109 
02110      
02111 // FnctIntersection
02112 TEMP void THIS::FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const {
02113   FD_DC("TBaseSet(" << this << ")::FnctIntersection (" << &rOtherSet << ")");
02114   rRes.Detach();
02115   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
02116   std::set_intersection(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
02117   rRes.Name(CollapsString(Name() + "*" + rOtherSet.Name()));
02118 }
02119 
02120 // operator+
02121 TEMP THIS THIS::operator+ (const TBaseSet& rOtherSet) const {
02122   TBaseSet res;
02123   FnctUnion(rOtherSet,res);
02124   return res;
02125 }
02126 
02127 // operator-
02128 TEMP THIS THIS::operator- (const TBaseSet& rOtherSet) const {
02129   TBaseSet res;
02130   FnctDifference(rOtherSet,res);
02131   return res;
02132 }
02133 
02134      
02135 // operator*
02136 TEMP THIS THIS::operator* (const TBaseSet& rOtherSet) const {
02137   TBaseSet res;
02138   FnctIntersection(rOtherSet,res);
02139   return res;
02140 }
02141 
02142 
02143 // operator==
02144 TEMP bool THIS::DoEqual(const TBaseSet& rOtherSet) const {
02145   FD_DC("TBaseSet::DoEqual()");
02146   // true if we share anyway
02147   if(pSet == rOtherSet.pSet) return true;
02148   // compare sets
02149   return  ( *pSet == *rOtherSet.pSet );
02150 }
02151 
02152 // operator<=
02153 TEMP bool THIS::operator<= (const TBaseSet& rOtherSet) const {
02154   FD_DC("BaseSet::op<=()");
02155   return ( std::includes(rOtherSet.pSet->begin(), rOtherSet.pSet->end(), pSet->begin(), pSet->end()) ) ;
02156 }
02157 
02158 // operator>=
02159 TEMP bool THIS::operator>= (const TBaseSet& rOtherSet) const {
02160   FD_DC("BaseSet::op>=()");
02161   return ( std::includes(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end()) );
02162 }
02163 
02164 // operator<
02165 TEMP bool THIS::operator< (const TBaseSet& rOtherSet) const {
02166   return *pSet < *rOtherSet.pSet;
02167 }
02168 
02169 
02170 // attribute typeinfo
02171 TEMP const AttributeVoid* THIS::Attributep(void) const { 
02172   static AttributeVoid attr; 
02173   return & attr; 
02174 }
02175 
02176 // attribute typeinfo
02177 TEMP const AttributeVoid& THIS::Attribute(void) const { 
02178   static AttributeVoid attr; 
02179   return attr;
02180 }
02181 
02182 // attribute access
02183 TEMP AttributeVoid* THIS::Attributep(const T& rElem) { 
02184   (void) rElem;
02185   std::stringstream errstr;
02186   errstr << "cannot get attribute for TBaseSet \"" << mMyName  << "\" type " << typeid(*this).name();
02187   throw Exception("TBaseSet::Attributep(rElem)", errstr.str(), 63);  
02188   static AttributeVoid attr; 
02189   return &attr; 
02190 }
02191 
02192 // attribute access
02193 TEMP const AttributeVoid& THIS::Attribute(const T& rElem) const { 
02194   (void) rElem;
02195   static AttributeVoid attr; 
02196   return attr;
02197 }
02198 
02199 // attribute access
02200 TEMP void THIS::Attribute(const T& rElem, const Type& rAttr) {
02201   (void) rElem;
02202   /* its pointless to test existence of the element since we wont set any attribute anyway
02203 #ifdef FAUDES_CHECKED
02204   if (!Exists(rElem)) {
02205     std::stringstream errstr;
02206     errstr << "element not member of set" << std::endl;
02207     throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 60);
02208   }
02209 #endif
02210   */
02211   if(!AttributeTry(rAttr)) {
02212     std::stringstream errstr;
02213     errstr << "cannot cast attribute " << std::endl;
02214     throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 63);
02215   }
02216   /* alternative approach: 
02217   // silently ignore any value
02218   // set to void is ok for silient ignore
02219   if(typeid(rAttr)==typeid(const AttributeVoid&)) return;
02220   // set to nontrivial attribute: exception
02221   std::stringstream errstr;
02222   errstr << "cannot set attribute type " << typeid(rAttr).name() << " for TBaseSet \"" << mMyName 
02223     << "\" type " << typeid(*this).name();
02224   throw Exception("TBaseSet::Attribute(rElem,rAttr)", errstr.str(), 63);  
02225   */
02226 }
02227 
02228 
02229 
02230 /* undefine local shortcuts */
02231 #undef THIS
02232 #undef TEMP
02233 #undef BASE
02234 
02235 /** @} doxygen group */
02236 
02237 } // namespace faudes
02238 
02239 #endif 

libFAUDES 2.20s --- 2011.10.12 --- c++ source docu by doxygen