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    * 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    * Test whether if the TBaseSet is 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 iterators 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 turn 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("Iterator");
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      /** Indicate 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 
00842 protected:
00843 
00844 
00845   /** Name of this BaseSet */
00846   std::string mMyName;
00847 
00848   /** Pointer on STL set to operate on */
00849   std::set<T,Cmp>* pSet;
00850 
00851   /** Pointer to attribute map to operate on */
00852   std::map<T,AttributeVoid*>* pAttributes;
00853 
00854   /** STL iterator, non-const version */
00855   typedef typename std::set<T,Cmp>::iterator iterator;
00856 
00857   /** STL iterator, const version */
00858   typedef typename std::set<T,Cmp>::const_iterator const_iterator;
00859 
00860   /** Convert STL iterator */
00861   typename TBaseSet<T,Cmp>::Iterator ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const;
00862 
00863   /** STL attribute iterator, non-const version */
00864   typedef typename std::map<T,AttributeVoid*>::iterator aiterator;
00865 
00866   /** STL attribute iterator, const version */
00867   typedef typename std::map<T,AttributeVoid*>::const_iterator const_aiterator;
00868 
00869 
00870 
00871   /** STL set, if this object hosts data (else NULL) */
00872   std::set<T,Cmp>* mpSet;
00873 
00874   /** Attribute map, if this object hosts data (else NULL). */
00875   std::map<T,AttributeVoid*>* mpAttributes;
00876 
00877   /** Pointer on BaseSet that hosts our data (THIS if we host) */
00878   TBaseSet<T,Cmp>* pHostSet;
00879 
00880   /** Iterator to the client list that hosts our data (maintained by host)*/
00881   typename std::list< TBaseSet<T,Cmp>* >::iterator mClientRecord; 
00882 
00883   /** BaseSets, that use data hosted by us (NULL if we dont host data, emptyset if we host to ourself excl.) */
00884   std::list< TBaseSet<T,Cmp>* >* mpClients;
00885 
00886   /** Indicate "hosts data to myself only" */
00887   bool mDetached;
00888 
00889   /** Indicate "dont re-allocate the STL set ever again" */
00890   bool mLocked;
00891 
00892   /** Ensure that we do not host contents to anyone else */
00893   void RelinkClients(void);
00894 
00895   /** Record that we provide contents to some other BaseSet */
00896   void AttachClient(TBaseSet* pRef) const;
00897 
00898   /** Record that we stop providing data for some TBaseSet */
00899   void DetachClient(TBaseSet* pRef) const;
00900 
00901   /** Iterators that refer to this TBaseSet */
00902   std::set< Iterator* > mIterators;
00903 
00904   /** Record that an iterator refers to this TBaseSet */
00905   void AttachIterator(Iterator* pFit) const;
00906 
00907   /** Record that an iterator stops to refer to this TBaseSet */
00908   void DetachIterator(Iterator* pFit) const;
00909 
00910   /** Implementation of union */
00911   void FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00912 
00913   /** Implementation of difference */
00914   void FnctDifference(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00915 
00916   /** Implementation of intersection */
00917   void FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const;
00918 
00919   /** TypeDefinition cache (should use guarded pointer here) */
00920   const TypeDefinition* pTypeDefinition;
00921 
00922   /** Reimplment from type to use chache */
00923   virtual const TypeDefinition* TypeDefinitionp(void) const;
00924 
00925   /** Reimplment from faudes type to use chache */
00926   virtual const std::string& TypeName(void) const;
00927 
00928   /** Name of elements (used for XML IO) */
00929   virtual const std::string& XElementTag(void) const;
00930 
00931 
00932   /** static empty STL set for default constructor */
00933   static std::set<T,Cmp> msEmptySet;
00934 
00935   /** static empty STL map for default constructor */
00936   static std::map<T,AttributeVoid*> msEmptyAttributes;
00937 
00938   /** static empty STL client list */
00939   // std::list< TBaseSet<T,Cmp>* >* msEmptyClients;
00940 };
00941 
00942 
00943 
00944 /* 
00945  * Set union, rti wrapper
00946  *
00947  * @param rSetA
00948  *  Set A
00949  * @param rSetB
00950  *  Set B
00951  * @return
00952  *  Union of set A and set B
00953  */
00954 
00955 template<class T, class Cmp>
00956 void SetUnion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
00957   FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): res at " << &rRes);
00958   // fix name
00959   std::string name=CollapsString(rSetA.Name() + "+" + rSetB.Name());
00960   // all the same
00961   if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
00962   // a and b ths same, res different
00963   if(&rSetA==&rSetB) {rRes.Assign(rSetA); rRes.Name(name); return;}
00964   // a and res the same, b different 
00965   if(&rSetA==&rRes) {rRes.InsertSet(rSetB); rRes.Name(name); return;};
00966   // b and res the same, a different 
00967   if(&rSetB==&rRes) {rRes.InsertSet(rSetA); rRes.Name(name); return;};
00968   // else
00969   rRes.Assign(rSetA);
00970   rRes.InsertSet(rSetB);
00971   rRes.Name(name); 
00972   FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): done, res at " << &rRes << " #" << rRes.Size());
00973 }
00974 
00975 /* 
00976  * Set intersection, rti wrapper
00977  *
00978  * @param rSetA
00979  *  Set A
00980  * @param rSetB
00981  *  Set B
00982  * @return
00983  *  Set A intersected with set B
00984  */
00985 template< class T, class Cmp >
00986 void SetIntersection(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
00987   // fix name
00988   std::string name=CollapsString(rSetA.Name() + "*" + rSetB.Name());
00989   // all the same
00990   if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;}
00991   // a and b ths ame, res different
00992   if(&rSetA==&rSetB) { rRes.Assign(rSetA); rRes.Name(name); return;}
00993   // a and res the same, b different 
00994   if(&rSetA==&rRes) {rRes.RestrictSet(rSetB); rRes.Name(name); return;};
00995   // b and res the same, a different 
00996   if(&rSetB==&rRes) {rRes.RestrictSet(rSetA); rRes.Name(name); return;};
00997   // else
00998   rRes.Assign(rSetA);
00999   rRes.RestrictSet(rSetB);
01000   rRes.Name(name); 
01001 }
01002 
01003 
01004 /* 
01005  * Set difference, rti wrapper
01006  *
01007  * @param rSetA
01008  *  Set A
01009  * @param rSetB
01010  *  Set B
01011  * @return
01012  *  Set A minus set B
01013  */
01014 template< class T, class Cmp >
01015 void SetDifference(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) {
01016   // fix name
01017   std::string name=CollapsString(rSetA.Name() + "-" + rSetB.Name());
01018   // a and b the same
01019   if(&rSetA==&rSetB) { rRes.Clear(); rRes.Name(name); return;}
01020   // a and res the same, b different 
01021   if(&rSetA==&rRes) {rRes.EraseSet(rSetB); rRes.Name(name); return;};
01022   // b and res the same, a different ... need buffer?
01023   if(&rSetB==&rRes) {
01024     TBaseSet<T,Cmp>* buffb=rSetB.Copy();
01025     rRes.Assign(rSetA);
01026     rRes.EraseSet(*buffb); 
01027     rRes.Name(name); 
01028     delete buffb;
01029     return;
01030   }; 
01031   // else: std
01032   rRes.Assign(rSetA);
01033   rRes.EraseSet(rSetB);
01034   rRes.Name(name); 
01035 }
01036 
01037 /* 
01038  * Set equality, rti wrapper
01039  * This method ignores attributes.
01040  *
01041  * @param rSetA
01042  *  Set A
01043  * @param rSetB
01044  *  Set B
01045  * @return
01046  *  True for matching sets.
01047  */
01048 template< class T, class Cmp >
01049 bool SetEquality(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
01050   return rSetA==rSetB;
01051 }
01052 
01053 /* 
01054  * Set inclusion, rti wrapper
01055  * This method ignores attributes.
01056  *
01057  * @param rSetA
01058  *  Set A
01059  * @param rSetB
01060  *  Set B
01061  * @return
01062  *  True for matching sets.
01063  */
01064 template< class T, class Cmp >
01065 bool SetInclusion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) {
01066   return rSetA<=rSetB;
01067 }
01068 
01069 
01070 
01071 
01072 /** @} doxygen group */
01073 
01074 
01075 
01076 /*
01077 ******************************************************************************************
01078 ******************************************************************************************
01079 ******************************************************************************************
01080 
01081 Implementation of TBaseSet
01082 
01083 ******************************************************************************************
01084 ******************************************************************************************
01085 ******************************************************************************************
01086 */
01087 
01088 /* convenience access to relevant scopes */
01089 #define THIS TBaseSet<T,Cmp> 
01090 #define TEMP template<class T, class Cmp>
01091 #define BASE Type
01092 
01093 
01094 // faudes type std: new and cast
01095 FAUDES_TYPE_TIMPLEMENTATION_NEW(Void,THIS,Type,TEMP)
01096 FAUDES_TYPE_TIMPLEMENTATION_COPY(Void,THIS,Type,TEMP)
01097 FAUDES_TYPE_TIMPLEMENTATION_CAST(Void,THIS,Type,TEMP)
01098 
01099 // faudes type std: assignemnt (break cast)
01100 //TEMP THIS& THIS::Assign(const Type& rSrc) { this->Clear(); return *this;};
01101 //TEMP THIS& THIS::Assign(const THIS& rSrc) { DoAssign(rSrc); return *this;};
01102 
01103 // faudes type std: assignemnt (keep cast)
01104 FAUDES_TYPE_TIMPLEMENTATION_ASSIGN(Void,THIS,Type,TEMP)
01105 FAUDES_TYPE_TIMPLEMENTATION_EQUAL(Void,THIS,Type,TEMP)
01106 
01107 
01108 // template statics: empty set
01109 TEMP std::set<T,Cmp>  THIS::msEmptySet=std::set<T,Cmp>();
01110 TEMP std::map<T,AttributeVoid*> THIS::msEmptyAttributes=std::map<T,AttributeVoid*>();
01111 
01112 // TBaseSet()
01113 TEMP THIS::TBaseSet(void) :
01114   Type(),
01115   pSet(&msEmptySet),  
01116   pAttributes(&msEmptyAttributes),
01117   mpSet(NULL),
01118   mpAttributes(NULL),
01119   pHostSet(this),
01120   mpClients(new std::list< TBaseSet<T,Cmp>* >),
01121   mDetached(false), 
01122   mLocked(false),
01123   pTypeDefinition(NULL)
01124 {
01125   FAUDES_OBJCOUNT_INC("BaseSet");
01126   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
01127   // other members
01128   mMyName="BaseSet";
01129 }
01130 
01131 // TBaseSet(filename)
01132 TEMP THIS::TBaseSet(const std::string& rFileName, const std::string& rLabel)  :
01133   Type(),
01134   pSet(&msEmptySet),  
01135   pAttributes(&msEmptyAttributes),
01136   mpSet(NULL),
01137   mpAttributes(NULL),
01138   pHostSet(this),
01139   mpClients(new std::list< TBaseSet<T,Cmp>* >),
01140   mDetached(false), 
01141   mLocked(false), 
01142   pTypeDefinition(NULL)
01143 {
01144   FAUDES_OBJCOUNT_INC("BaseSet");
01145   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
01146   // other members
01147   mMyName="BaseSet";
01148   // do read etc ... this is a dummy anyway
01149   Read(rFileName,rLabel);  
01150 }
01151 
01152 // TBaseSet(rOtherSet)
01153 TEMP THIS::TBaseSet(const TBaseSet& rOtherSet) : 
01154   Type(rOtherSet),
01155   pSet(&msEmptySet),  
01156   pAttributes(&msEmptyAttributes),
01157   mpSet(NULL),  
01158   mpAttributes(NULL),
01159   pHostSet(this),
01160     mpClients(new std::list< TBaseSet<T,Cmp>* >), // small detour ... for readability
01161   mDetached(false), 
01162   mLocked(false),
01163   pTypeDefinition(NULL)
01164 {
01165   FAUDES_OBJCOUNT_INC("BaseSet");
01166   FD_DC("TBaseSet(" << this << ")::TBaseSet(rOtherSet " << &rOtherSet << "): fake copy construct");
01167   // run assignment
01168   DoAssign(rOtherSet);
01169 #ifdef FAUDES_DEBUG_CODE
01170   DValid("CopyConstruct");
01171 #endif
01172 }
01173 
01174 // destructor
01175 TEMP THIS::~TBaseSet(void) {
01176   FAUDES_OBJCOUNT_DEC("BaseSet");
01177   FD_DC("TBaseSet(" << this << ")::~TBaseSet()");
01178   // maintain deferred copy 
01179   RelinkClients();
01180   pHostSet->DetachClient(this);
01181   if(mpClients) delete mpClients;
01182   mpClients=NULL;
01183   // unlink iterators (mandatory, since referenced object will be destructed)
01184   typename std::set< Iterator* >::const_iterator iit;
01185   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01186     (**iit).Invalidate();
01187   }
01188   // delete if we still own data
01189   if(mpSet) delete mpSet;
01190   if(mpAttributes) {
01191     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01192        delete ait->second;
01193     delete mpAttributes;
01194   }
01195 }
01196 
01197 
01198 // fake copy
01199 TEMP void THIS::DoAssign(const THIS& rSourceSet) {
01200   FD_DC("TBaseSet(" << this << ")::DoAssign(rOtherSet " << &rSourceSet << "): fake copy");
01201   // bail out on selfref
01202   if(this==&rSourceSet) return;
01203   // other members 
01204   mMyName=rSourceSet.mMyName;
01205   // bail out on common shared data
01206   if(pHostSet==rSourceSet.pHostSet) return;
01207   // become independant
01208   RelinkClients();
01209   pHostSet->DetachClient(this);
01210   // if we are locked, should do the copy ... not implemented
01211 #ifdef FAUDES_DEBUG_CODE
01212   if(mLocked) {
01213     FD_ERR("TBaseSet::DoAssign(): locked target will be unlocked: not implemented");
01214     abort();
01215   }
01216 #endif
01217   // attatch myself to src host 
01218   pHostSet=rSourceSet.pHostSet;
01219   pHostSet->AttachClient(this);
01220   pSet=rSourceSet.pSet;
01221   pAttributes=&msEmptyAttributes;
01222   // delete own old data
01223   if(mpSet) { 
01224      delete mpSet;
01225      mpSet=NULL;
01226   }
01227   if(mpAttributes) {
01228     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01229        delete ait->second;
01230     delete mpAttributes;
01231     mpAttributes=NULL;
01232   }
01233   if(mpClients) {
01234     delete mpClients;
01235     mpClients=NULL;
01236   }
01237   // record state
01238   mDetached=false; 
01239   mLocked=false;
01240   // fix iterators (invalidate)
01241   typename std::set< Iterator* >::iterator iit;
01242   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01243     (**iit).Invalidate();
01244   }
01245   mIterators.clear();
01246 #ifdef FAUDES_DEBUG_CODE
01247   DValid("PostFakeAssignment");
01248 #endif
01249 }
01250 
01251 // Detach()
01252 TEMP void THIS::Detach(void) const {
01253   FD_DC("TBaseSet(" << this << ")::Detach(void)");
01254 #ifdef FAUDES_DEBUG_CODE
01255   DValid("PreDetach");
01256 #endif
01257 
01258   // nothing todo
01259   if(mDetached) return;
01260 
01261   // provide fake const
01262   THIS* fake_const = const_cast< THIS* >(this);
01263 
01264 #ifdef FAUDES_DEBUG_CODE
01265   // might have missed reference detach
01266   if(pHostSet==this)
01267   if(pSet!=&msEmptySet)
01268   if(mpClients)
01269   if(mpClients->empty()) {
01270     FD_ERR("TBaseSet(" << this << ")::Detach(void): missed detach (?)");
01271     abort();                     // strict
01272     fake_const->mDetached=true;  // fix
01273   }
01274 #endif
01275 
01276   // stragie A: clients get the new copy; thus, the baseset data does
01277   // not get reallocated and we dont need to track iterators; on the
01278   // downside, fixing the references iterators may be more effort.
01279   if(mLocked==true) {
01280    
01281     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie A");
01282     // do allocation and copy of stl set
01283     std::set<T,Cmp>* scopy = new std::set<T,Cmp>();
01284     *scopy = *pSet;     
01285     // first of my clients gets the new data and the old attributes
01286     THIS* newhost = *mpClients->begin();
01287     newhost->pHostSet=newhost;
01288     newhost->mpSet=scopy; 
01289     newhost->pSet=scopy;
01290     newhost->mpAttributes=mpAttributes;
01291     newhost->pAttributes=pAttributes;
01292     newhost->mpClients=mpClients;
01293     newhost->DetachClient(newhost);
01294     // set other users to use the new host
01295     typename std::list< THIS* >::const_iterator rit;
01296     for(rit=newhost->mpClients->begin();rit!=newhost->mpClients->end(); ++rit) {
01297       (*rit)->pHostSet=newhost;
01298       (*rit)->pSet=newhost->pSet;
01299       (*rit)->pAttributes=newhost->pAttributes;
01300     }
01301     // fix newhost clients iterators 
01302     typename std::set< Iterator* >::iterator iit;
01303     for(rit=newhost->mpClients->begin(); rit!=newhost->mpClients->end(); ++rit) {
01304       for(iit=(*rit)->mIterators.begin(); iit!=(*rit)->mIterators.end(); ++iit) {
01305         if((**iit).StlIterator()==pSet->end()) 
01306           **iit=Iterator(this, scopy->end());
01307         else
01308           **iit=Iterator(this, scopy->find(***iit));
01309       }
01310     }
01311     // fix newhost iterators 
01312     for(iit=newhost->mIterators.begin(); iit!=newhost->mIterators.end(); ++iit) {
01313       if((**iit).StlIterator()==pSet->end()) 
01314         **iit=Iterator(this, scopy->end());
01315       else
01316         **iit=Iterator(this, scopy->find(***iit));
01317     }
01318     // make myself own the old data and have empty attributes
01319     fake_const->mpSet=pSet;
01320     fake_const->mpAttributes=NULL;
01321     fake_const->pAttributes=&msEmptyAttributes;
01322     fake_const->mpClients= new std::list< TBaseSet<T,Cmp>* >;
01323     fake_const->mDetached=true;    
01324     // stop tracking my iterators
01325     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01326       (**iit).Detach();
01327     }
01328     fake_const->mIterators.clear();
01329 
01330 
01331   // stragie B: this baseset gets the copy; thus, the clients iterators
01332   // remain valid and dont need to be fixed; on the downside, we need to
01333   // continue to track our iterators.
01334   } else {
01335 
01336 
01337     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie B");
01338     // make someone else handle original data
01339     fake_const->RelinkClients();
01340     pHostSet->DetachClient(fake_const);
01341     // do allocation and copy of stl set
01342     fake_const->mpSet = new std::set<T,Cmp>();
01343     *fake_const->mpSet= *pSet;     
01344     // have empty attributes
01345     fake_const->mpAttributes=NULL;
01346     fake_const->pAttributes=&msEmptyAttributes;
01347     // fix my iterators
01348     typename std::set< Iterator* >::iterator iit;
01349     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01350       if((**iit).StlIterator()==pSet->end()) 
01351         **iit=Iterator(this, mpSet->end());
01352       else
01353         **iit=Iterator(this, mpSet->find(***iit));
01354     }
01355     // record myself as my newhost
01356     fake_const->pHostSet=fake_const;
01357     fake_const->pSet=mpSet;
01358     fake_const->mDetached=true;
01359     fake_const->mpClients= new std::list< TBaseSet<T,Cmp>* >;
01360   }
01361 
01362 #ifdef FAUDES_DEBUG_CODE
01363   DValid("PostDetach");
01364 #endif
01365   FD_DC("TBaseSet(" << this << ")::Detach(void): done");
01366 }
01367 
01368 // Lock()
01369 TEMP  void THIS::Lock(void) const {
01370   FD_DC("TBaseSet(" << this << ")::Lock(void)");
01371 #ifdef FAUDES_DEBUG_CODE
01372   DValid("PreLock");
01373 #endif
01374   // if we are locked: fine
01375   if(mLocked) return;
01376 
01377   // trigger actual copy
01378   Detach();
01379 
01380   // provide fake const
01381   THIS* fake_const = const_cast< THIS* >(this);
01382 
01383   // stop tracking iterators
01384   typename std::set< Iterator* >::const_iterator iit;
01385   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01386     (**iit).Detach();
01387   }
01388   fake_const->mIterators.clear();
01389 
01390   // stop detach from reallocating
01391   fake_const->mLocked=true;
01392 
01393 #ifdef FAUDES_DEBUG_CODE
01394   DValid("PostLock");
01395 #endif
01396 }
01397 
01398 
01399 // if i am a host to others, make someone else the host
01400 TEMP inline void THIS::RelinkClients(void) {
01401   FD_DC("TBaseSet::RelinkClients(" << this << ")")
01402 #ifdef FAUDES_DEBUG_CODE
01403   DValid("PreRelink");
01404 #endif
01405 
01406   // no clients, so i dont host data anyway
01407   if(!mpClients) return;
01408   // empty clients, so i only host to myself
01409   if(mpClients->empty()) return;
01410 
01411   FD_DC("TBaseSet::RelinkClients(" << this << "): doit")
01412 
01413   // make first client the new newhost
01414   THIS* newhost = *mpClients->begin();
01415 #ifdef FAUDES_DEBUG_CODE
01416   if(newhost->pHostSet!=this) {
01417     FD_ERR("BaseSet::RelinkRefernces: old reference must have this as provider");
01418     abort();
01419   }
01420 #endif
01421   newhost->pHostSet=newhost;
01422   newhost->mpSet=mpSet; 
01423   newhost->pSet=pSet;
01424   newhost->mpAttributes=mpAttributes; 
01425   newhost->pAttributes=pAttributes;
01426   newhost->mpClients=mpClients;
01427   newhost->DetachClient(newhost);
01428   // set other users to new newhost
01429   typename std::list< THIS* >::const_iterator rit;
01430   for(rit=newhost->mpClients->begin();rit!=newhost->mpClients->end(); ++rit) {
01431     (*rit)->pHostSet=newhost;
01432   }
01433   // make myself a reference to the new source
01434   pHostSet=newhost;
01435   pSet=newhost->pSet;
01436   mpSet=NULL;
01437   pAttributes=newhost->pAttributes;
01438   mpAttributes=NULL;
01439   newhost->AttachClient(this);
01440   mpClients=NULL;
01441 #ifdef FAUDES_DEBUG_CODE
01442   DValid("PostRelink");
01443 #endif
01444   FD_DC("TBaseSet::RelinkClients(" << this << "): done")
01445 }
01446 
01447 
01448 // record fake copy
01449 TEMP inline void THIS::AttachClient(TBaseSet* pRef) const {
01450   if(!mpClients) const_cast< THIS* >(this)->mpClients=new std::list< TBaseSet<T,Cmp>* >;
01451   const_cast< THIS* >(this)->mpClients->push_back(pRef);
01452   pRef->mClientRecord= -- mpClients->end();
01453   const_cast< THIS* >(this)->mDetached=false;
01454 }
01455 
01456 // discard fake copy
01457 TEMP inline void THIS::DetachClient(TBaseSet* pRef) const {
01458   FD_DC("TBaseSet::DetachClient(" << this << "):" << pRef);
01459   // bail out on trivials
01460   if(!mpClients) return;
01461   if(mpClients->empty()) return;
01462   if(pRef->pHostSet!=this) return;
01463   // provide fake const
01464   THIS* fake_const = const_cast< THIS* >(this);
01465 #ifdef FAUDES_DEBUG_CODE
01466   // find and remove that client
01467   typename std::list< TBaseSet<T,Cmp>* >::iterator cit;
01468   bool cf=false;
01469   for(cit=fake_const->mpClients->begin(); cit!=fake_const->mpClients->end(); ++cit) {
01470     if(*cit==pRef) cf=true;
01471   }
01472   if(!cf) {
01473     FD_ERR("TBaseSet::DetachClient(" << this << "): client not found " << pRef);
01474     abort();
01475   }
01476 #endif  
01477   /*
01478   use recorded client index: performant, and fine when last tested ...
01479   ... however, this really is asking for segfaults.
01480 
01481   // remove from client list
01482   FD_DC("TBaseSet::DetachClient(" << this << "):" << pRef << " must match " << *pRef->mClientRecord);
01483   fake_const->mpClients->erase(pRef->mClientRecord);
01484   */
01485   // remove from client list
01486   typename std::list< TBaseSet<T,Cmp>* >::iterator rit; 
01487   for(rit=fake_const->mpClients->begin(); rit!=fake_const->mpClients->end(); ++rit) {
01488     if(*rit!=pRef) continue;
01489     fake_const->mpClients->erase(rit);
01490     break; 
01491   }
01492   // figure detached status
01493   if(mpClients->empty() && (pSet!=&msEmptySet)) fake_const->mDetached=true;
01494   FD_DC("TBaseSet::DetachClient(" << this << "): done.");
01495 }
01496 
01497 
01498 // record an iterator
01499 TEMP inline void THIS::AttachIterator(Iterator* pFit) const {
01500   if(mLocked) return;
01501   FD_DC("TBaseSet::AttachIterator(" << this << "):" << pFit)
01502   const_cast< THIS* >(this)->mIterators.insert(pFit);
01503 }
01504 
01505 // discard an iterator
01506 TEMP inline void THIS::DetachIterator(Iterator* pFit) const {
01507   if(mLocked) return;
01508   FD_DC("TBaseSet::DetachIterator(" << this << "):" << pFit)
01509   const_cast< THIS* >(this)->mIterators.erase(pFit);
01510 }
01511 
01512 // test some validity
01513 TEMP void THIS::DValid(const std::string& rMessage) const {
01514   typename std::set< Iterator* >::const_iterator iit;
01515   typename std::list< THIS* >::const_iterator rit;
01516 #ifdef FAUDES_DEBUG_CONTAINER
01517   std::cerr << "TBaseSet(" << this << ")::DValid(): " << rMessage << " source " 
01518      << pHostSet << " " << (pHostSet->pSet==&msEmptySet ? "+e+" : "+f+") << 
01519         (mLocked ? " +l+" : " ") << (mDetached ? " +d+" : " ") << " -- refs ";
01520   if(pHostSet->mpClients)Detached
01521   for(rit=pHostSet->mpClients->begin(); rit!=pHostSet->mpClients->end(); ++rit)
01522     std::cerr << *rit << " ";
01523   std::cerr << "-- its ";
01524   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit)
01525     std::cerr << *iit << " ";
01526   std::cerr << "-- attr #" << pAttributes->size();
01527   if(mpAttributes) std::cerr << "(" << mpAttributes->size() << ") ";
01528   else std::cerr << " ";
01529   std::cerr << (pAttributes==&msEmptyAttributes ? "+e+ " : "+f+ ") << std::endl;
01530 #endif
01531   // iterators, that dont refer to me as basset
01532   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01533     if((*iit)->pBaseSet!=this) {
01534       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (baseset): "<< *iit);
01535       abort();
01536     }
01537   }
01538   // iterators, that are not marked as attached
01539   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01540     if(!(*iit)->mAttached) {
01541       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (attached): "<< *iit);
01542       abort();
01543     }
01544   }
01545   // iterators, that are invalid stl iterators
01546   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01547     typename std::set<T,Cmp>::const_iterator vit;
01548     for(vit=pSet->begin(); vit!= pSet->end(); ++vit) {
01549       if(vit==(**iit).StlIterator()) break;
01550     }
01551     if(vit!=(**iit).StlIterator()) { // end-iterator is fine, too
01552       FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (stl) "<< *iit);
01553       (**iit).StlIterator(pSet->end()); // fix invalid iterator to refer to end()
01554       abort(); // strict version: abort
01555     }
01556   }
01557   // must have some base 
01558   if(pHostSet==NULL) {
01559     FD_ERR("BaseSet(" << this << "," << rMessage << "): no host found");
01560     abort();
01561   }
01562   // hosts mut be consistent
01563   if(pHostSet->pHostSet != pHostSet) {
01564     FD_ERR("BaseSet(" << this << "," << rMessage << "): inconsistent host");
01565     abort();
01566   }
01567   // refers to other base and own data
01568   if((mpSet!=NULL) && (pHostSet != this)) {
01569     FD_ERR("BaseSet(" << this << "," << rMessage << "): double data");
01570     abort();
01571   }
01572   // refers to other base and has references
01573   if(pHostSet!=this && mpClients!=NULL) {
01574     FD_ERR("BaseSet(" << this << "," << rMessage << "): cannot be client and have clients oneself");
01575     abort();
01576   }
01577   // refers to invalid base 
01578   if(pHostSet->mpClients==NULL) {
01579     FD_ERR("BaseSet(" << this << "," << rMessage << "): refers to invalid host (a)");
01580     abort();
01581   }
01582   // refers to invalid base 
01583   if(pHostSet!=this && pHostSet->mpClients->empty()) {
01584     FD_ERR("BaseSet(" << this << "," << rMessage << "): refers to invalid host (b)");
01585     abort();
01586   }
01587   // is base but has no own data
01588   if((pHostSet == this) && (mpSet==NULL) && (pSet!=&msEmptySet)) {
01589     FD_ERR("BaseSet(" << this << "," << rMessage << "): no data");
01590     abort();
01591   }
01592   // is base, but has no client list
01593   if((pHostSet==this) && (pSet!=&msEmptySet) && (mpClients==NULL)) {
01594     FD_ERR("BaseSet(" << this << "," << rMessage << "): host with no client list");
01595     abort();
01596   }
01597   // is base but own data pointer mismatch
01598   if((pHostSet == this) && (pSet != mpSet) && (pSet!=&msEmptySet)) {
01599     FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch A");
01600     abort();
01601   }
01602   // refers to base with data pointer mismatch
01603   if(pSet != pHostSet->pSet) {
01604     FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch B");
01605     abort();
01606   }
01607   // test all clients from hosts list
01608   bool hf=false;
01609   for(rit=pHostSet->mpClients->begin(); rit!=pHostSet->mpClients->end(); ++rit) {
01610     if((*rit)== this) hf=true;
01611     if((*rit)->pHostSet== pHostSet) continue;
01612     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid client " << (*rit));
01613     abort();
01614   }
01615   if(!hf && (pHostSet!=this)) {
01616     FD_ERR("BaseSet(" << this << "," << rMessage << "): client not registered with host");
01617     abort();
01618   }
01619   // refers to invalid base 
01620   if(pHostSet!=this && *mClientRecord!=this) {
01621     FD_ERR("BaseSet(" << this << "," << rMessage << "): refers to invalid host (c)");
01622     abort();
01623   } 
01624   // error in detached flag
01625   if(mDetached && mpClients==NULL) {
01626     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid detached flag A");
01627     abort();
01628   }
01629   // error in detached flag
01630   if(mDetached && !mpClients->empty()) {
01631     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid detached flag B");
01632     abort();
01633   }
01634   // error in detached flag
01635   if(mDetached && (pSet==&msEmptySet)) {
01636     FD_ERR("BaseSet(" << this << "," << rMessage << "): detached empty set");
01637     abort();
01638   }
01639   // error in lock flag
01640   if(mLocked && (mpClients==NULL)) {
01641     FD_ERR("BaseSet(" << this << "," << rMessage << "): locked reference (a)");
01642     abort();
01643   }
01644   // invalid emptyset
01645   if(!msEmptySet.empty()) {
01646     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty set");
01647     abort();
01648   }
01649   // invalid emptyset
01650   if(!msEmptyAttributes.empty()) {
01651     FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty attributes");
01652     abort();
01653   }
01654 #ifdef FAUDES_DEBUG_CONTAINER
01655   std::cerr << "TBaseSet(" << this << ")::DValid(): passed" << std::endl;
01656 #endif
01657 }
01658 
01659 
01660 
01661 // Name
01662 TEMP const std::string& THIS::Name(void) const {
01663   return mMyName;
01664 }
01665     
01666 // Name
01667 TEMP void THIS::Name(const std::string& rName) {
01668   mMyName = rName;
01669 }
01670   
01671 
01672 // TypeDefinitionp()
01673 // Note: fake const construct
01674 TEMP const TypeDefinition* THIS::TypeDefinitionp(void) const {
01675   if(!pTypeDefinition) {
01676     // provide fake const
01677     THIS* fake_const = const_cast< THIS* >(this);
01678     fake_const->pTypeDefinition=TypeRegistry::G()->Definitionp(*this);
01679   }
01680   return pTypeDefinition;
01681 }
01682 
01683 // TypeName
01684 TEMP  const std::string& THIS::TypeName(void) const {
01685   const TypeDefinition* fdp=TypeDefinitionp();
01686   if(!fdp) return msStringEmpty;
01687   return fdp->Name();
01688 }
01689 
01690 // ElementTag
01691 TEMP  const std::string& THIS::XElementTag(void) const {
01692   const static std::string etstr("Element");
01693   const TypeDefinition* fdp=TypeDefinitionp();
01694   if(!fdp) return etstr;
01695   return fdp->XElementTag();
01696 }
01697 
01698 
01699 // Str
01700 TEMP std::string THIS::Str(const T& rElem) const { 
01701   (void) rElem;
01702   std::string res=""; 
01703   return res; 
01704 }
01705 
01706 // Size()
01707 TEMP Idx THIS::Size(void) const {
01708   return (Idx) pSet->size();
01709 }
01710 
01711 // Empty()
01712 TEMP bool THIS::Empty(void) const {
01713   return pSet->empty();
01714 }
01715 
01716 
01717 // DoWrite(tw,rLabel,cpntext)
01718 TEMP void THIS::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
01719   (void) pContext;
01720   std::string label=rLabel;
01721   if(label=="") label=Name(); 
01722   if(label=="") label="BaseSet"; 
01723   FD_DC("TBaseSet(" << this << ")::DoWrite(..): section " << label << " #" << Size());
01724   rTw.WriteBegin(label);
01725   rTw.WriteEnd(label);
01726 }
01727 
01728 
01729 // DoDWrite(tw, label, context)
01730 TEMP void THIS::DoDWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
01731   (void) pContext;
01732   (void) rLabel;
01733   BASE::DoSWrite(rTw);
01734   int shares=0;
01735   if(pHostSet->mpClients) shares=pHostSet->mpClients->size();
01736   rTw.WriteComment("");
01737   rTw.WriteComment(" Size/Attributes: " + ToStringInteger(pSet->size()) 
01738         + "/" + ToStringInteger(pHostSet->pAttributes->size()));
01739   rTw.WriteComment(" Shares/Iterators: " + ToStringInteger(shares) 
01740         + "/" + ToStringInteger(mIterators.size()));
01741   rTw.WriteComment("");
01742 #ifdef FAUDES_DEBUG_CODE
01743   DValid();
01744 #endif
01745 }
01746 
01747 // DoSWrite()
01748 TEMP void THIS::DoSWrite(TokenWriter& rTw) const {
01749   BASE::DoSWrite(rTw);
01750   int shares=0;
01751   if(pHostSet->mpClients) shares=pHostSet->mpClients->size();
01752   rTw.WriteComment(" Size: " + ToStringInteger(pSet->size()));
01753   rTw.WriteComment(" Shared Data: #" + ToStringInteger(shares) + " clients");
01754   if(pAttributes->size()!=0)
01755     rTw.WriteComment(" Attributes: " +ToStringInteger(pAttributes->size()));
01756   if(pAttributes->size()!=0) {
01757     AttributeVoid* attr = pAttributes->begin()->second;
01758     rTw.WriteComment(" Attribute Type: " +FaudesTypeName(*attr));
01759   } 
01760 }
01761 
01762 // DoRead(rTr, rLabel, pContext)
01763 TEMP void THIS::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
01764   (void) pContext;
01765   std::string label=rLabel;
01766   if(label=="") label=Name(); 
01767   if(label=="") label="BaseSet"; 
01768   Name(label);
01769   rTr.ReadBegin(label); 
01770   rTr.ReadEnd(label); 
01771 }
01772 
01773 // ThisIterator
01774 TEMP typename THIS::Iterator THIS::ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const {
01775   return Iterator(this,sit);
01776 }
01777 
01778 // Begin() const
01779 TEMP inline typename THIS::Iterator THIS::Begin(void) const {
01780   return ThisIterator(pSet->begin());
01781 }
01782     
01783 // End() const
01784 TEMP inline typename THIS::Iterator THIS::End(void) const {
01785   return ThisIterator(pSet->end());
01786 }
01787 
01788 
01789 //Clear
01790 TEMP void THIS::Clear(void) {
01791   FD_DC("TBaseSet(" << this << ")::Clear()");
01792 #ifdef FAUDES_DEBUG_CODE
01793   DValid("PreClear");
01794 #endif
01795   // special case: empty anyway
01796   if(pSet==&msEmptySet) return;
01797   FD_DC("TBaseSet(" << this << ")::Clear(): doit");
01798 
01799   // special case: locked requires a copy (not efficient!)
01800   if(mLocked) Detach();
01801   // make someone else handle the data
01802   RelinkClients();
01803   pHostSet->DetachClient(this);
01804   // make myself host
01805   pHostSet=this;
01806   if(!mpClients) mpClients= new std::list< TBaseSet<T,Cmp>* >;
01807   mpClients->clear();
01808   // if we hold data, clear it
01809   if(mpSet) {
01810     delete mpSet;
01811     mpSet=NULL;
01812   }
01813   // if we hold data, clear it
01814   if(mpAttributes) {
01815     for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait)
01816        delete ait->second;
01817     delete mpAttributes;
01818     mpAttributes=NULL;
01819   }
01820   // set to empty set
01821   pSet=&msEmptySet;
01822   pAttributes=&msEmptyAttributes;
01823   // fix iterators (invalidate)
01824   typename std::set< Iterator* >::iterator iit;
01825   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01826     (**iit).Invalidate();
01827   }
01828   mIterators.clear();
01829   mDetached=false;
01830   mLocked=false;
01831 #ifdef FAUDES_DEBUG_CODE
01832   DValid("PostClear");
01833 #endif
01834 }
01835 
01836 
01837 //Valid(elem)
01838 TEMP inline bool  THIS::Valid(const T& rElem) const {
01839   (void) rElem;
01840   return true;
01841 }
01842 
01843 //Insert(elem)
01844 TEMP bool THIS::Insert(const T& rElem) {
01845 #ifdef FAUDES_CHECKED
01846   if(!Valid(rElem)) {
01847     std::stringstream errstr;
01848     errstr << "cannot insert invalid element" << std::endl;
01849     throw Exception("BaseSet::Insert", errstr.str(), 61);
01850   }
01851 #endif
01852   if(!mDetached) Detach();
01853   return pSet->insert(rElem).second;
01854 }
01855 
01856 // InsertSet(set)
01857 TEMP void THIS::InsertSet(const TBaseSet& rOtherSet) {
01858   FD_DC("TBaseSet(" << this << ")::InsertSet(" << &rOtherSet << ")");
01859   if(!mDetached) Detach();
01860   /*
01861   rem: cannot use stl since result overlaps with arguments
01862 
01863   std::insert_iterator< std::set<T,Cmp> > insit(*pSet, rpSet->begin());
01864   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01865   */
01866   iterator it1 = pSet->begin();
01867   iterator it2 = rOtherSet.pSet->begin();
01868   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01869     if (*it1 < *it2) {
01870       ++it1;
01871     }
01872     else if (*it1 == *it2) {
01873       ++it1;
01874       ++it2;
01875     }
01876     else { // (*it1 > *it2)
01877       pSet->insert(*it2);
01878       ++it2;
01879     }
01880   }
01881   while (it2 != rOtherSet.pSet->end()) {
01882     pSet->insert(*it2);
01883     ++it2;
01884   }
01885 }
01886 
01887     
01888 //Erase(rElem)
01889 TEMP bool THIS::Erase(const T& rElem) {
01890   if(!mDetached) Detach();
01891   return (pSet->erase(rElem)!=0);
01892 }
01893 
01894 
01895 //Erase(pos)
01896 TEMP typename THIS::Iterator THIS::Erase(const Iterator& pos) { 
01897 #ifdef FAUDES_CHECKED
01898   if (pos == End()) {
01899     std::stringstream errstr;
01900     errstr << "iterator out of range " << std::endl;
01901     throw Exception("BaseSet::Erase", errstr.str(), 62);
01902   }
01903 #endif
01904   Detach();
01905   iterator del= pos.StlIterator(); 
01906   iterator res= del;
01907   res++; 
01908   pSet->erase(del);
01909   return ThisIterator(res); 
01910 }
01911 
01912 
01913 //EraseSet(set)
01914 TEMP void THIS::EraseSet(const TBaseSet& rOtherSet) {
01915   FD_DC("TBaseSet(" << this << ")::EraseSet(" << &rOtherSet << ")");
01916   if(!mDetached) Detach();
01917   // TODO: test and optimize 
01918   iterator tmpit;
01919   iterator it = pSet->begin();
01920   iterator oit = rOtherSet.pSet->begin();
01921   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
01922     if (*it < *oit) {
01923       it=pSet->lower_bound(*oit); // alt: ++it;
01924     }
01925     else if (*it == *oit) { 
01926       tmpit=it;
01927       ++it;
01928       ++oit;
01929       pSet->erase(tmpit);
01930     }
01931     else { // (*it > *oit)
01932       oit=rOtherSet.pSet->lower_bound(*it); // ++it2;
01933     }
01934   }
01935 }
01936 
01937 
01938 //RestrictSet(set)
01939 TEMP void THIS::RestrictSet(const TBaseSet& rOtherSet) {
01940   FD_DC("TBaseSet(" << this << ")::RestrictSet(" << &rOtherSet << ")");
01941   if(!mDetached) Detach();
01942   // TODO: test and optimize 
01943   iterator tmpit;
01944   iterator it = pSet->begin();
01945   iterator oit = rOtherSet.pSet->begin();
01946   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
01947     if (*it < *oit) {
01948       tmpit=it;
01949       ++it;
01950       pSet->erase(tmpit);
01951     }
01952     else if (*it == *oit) { 
01953       ++it;
01954       ++oit;
01955     }
01956     else { // (*it > *oit)
01957       oit=rOtherSet.pSet->lower_bound(*it); 
01958     }
01959   }
01960   while(it != pSet->end()) {
01961     tmpit=it;
01962     ++it;
01963     pSet->erase(tmpit);
01964   }
01965 }
01966 
01967 
01968 //Find(elem)
01969 TEMP typename THIS::Iterator THIS::Find(const T& rElem) const {
01970   return ThisIterator(pSet->find(rElem));
01971 }
01972 
01973 //Exists(elem)
01974 TEMP bool  THIS::Exists(const T& rElem) const {
01975   return pSet->find(rElem) != pSet->end();
01976 }
01977 
01978 
01979 // SetUnion(set)
01980 TEMP void THIS::SetUnion(const TBaseSet& rOtherSet) {
01981   if(!mDetached) Detach();
01982   iterator it1 = pSet->begin();
01983   iterator it2 = rOtherSet.pSet->begin();
01984   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01985     if (*it1 < *it2) {
01986       ++it1;
01987       continue;
01988     }
01989     if (*it1 == *it2) {
01990       ++it1;
01991       ++it2;
01992       continue;
01993     }
01994     // (*it1 > *it2)
01995     pSet->insert(it1,*it2);
01996     ++it2;
01997   }
01998   while (it2 != rOtherSet.pSet->end()) {
01999     pSet->insert(pSet->end(),*it2);
02000     ++it2;
02001   }
02002 }
02003 
02004 // SetIntersection(set)
02005 TEMP void THIS::SetIntersection(const TBaseSet& rOtherSet) {
02006   if(!mDetached) Detach();
02007   iterator tmpit;
02008   iterator it1 = pSet->begin();
02009   iterator it2 = rOtherSet.pSet->begin();
02010   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
02011     if (*it1 < *it2) {
02012       tmpit=it1;
02013       ++it1;
02014       pSet->erase(tmpit);
02015       continue;
02016     }
02017     if (*it1 == *it2) {
02018       ++it1;
02019       ++it2;
02020       continue;
02021     }
02022     // if (*it1 > *it2)
02023     ++it2;
02024   }
02025   while(it1 != pSet->end()) {
02026     tmpit=it1;
02027     ++it1;
02028     pSet->erase(tmpit);
02029   }
02030 }
02031 
02032 
02033 // FnctUnion
02034 TEMP void THIS::FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const {
02035   FD_DC("TBaseSet(" << this << ")::FnctUnion (" << &rOtherSet << ")");
02036   rRes.Detach();
02037   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
02038   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
02039   rRes.Name(CollapsString(Name() + "+" + rOtherSet.Name()));
02040 }
02041 
02042 // FnctDifference
02043 TEMP void THIS::FnctDifference (const TBaseSet& rOtherSet, TBaseSet& rRes) const {
02044   FD_DC("TBaseSet(" << this << ")::FnctDifference (" << &rOtherSet << ")");
02045   rRes.Detach();
02046   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
02047   std::set_difference(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
02048   rRes.Name(CollapsString(Name() + "-" + rOtherSet.Name()));
02049 }
02050 
02051      
02052 // FnctIntersection
02053 TEMP void THIS::FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const {
02054   FD_DC("TBaseSet(" << this << ")::FnctIntersection (" << &rOtherSet << ")");
02055   rRes.Detach();
02056   std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin());
02057   std::set_intersection(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
02058   rRes.Name(CollapsString(Name() + "*" + rOtherSet.Name()));
02059 }
02060 
02061 // operator+
02062 TEMP THIS THIS::operator+ (const TBaseSet& rOtherSet) const {
02063   TBaseSet res;
02064   FnctUnion(rOtherSet,res);
02065   return res;
02066 }
02067 
02068 // operator-
02069 TEMP THIS THIS::operator- (const TBaseSet& rOtherSet) const {
02070   TBaseSet res;
02071   FnctDifference(rOtherSet,res);
02072   return res;
02073 }
02074 
02075      
02076 // operator*
02077 TEMP THIS THIS::operator* (const TBaseSet& rOtherSet) const {
02078   TBaseSet res;
02079   FnctIntersection(rOtherSet,res);
02080   return res;
02081 }
02082 
02083 
02084 // operator==
02085 TEMP bool THIS::DoEqual(const TBaseSet& rOtherSet) const {
02086   FD_DC("TBaseSet::DoEqual()");
02087   // true if we share anyway
02088   if(pSet == rOtherSet.pSet) return true;
02089   // compare sets
02090   return  ( *pSet == *rOtherSet.pSet );
02091 }
02092 
02093 // operator<=
02094 TEMP bool THIS::operator<= (const TBaseSet& rOtherSet) const {
02095   FD_DC("BaseSet::op<=()");
02096   return ( std::includes(rOtherSet.pSet->begin(), rOtherSet.pSet->end(), pSet->begin(), pSet->end()) ) ;
02097 }
02098 
02099 // operator>=
02100 TEMP bool THIS::operator>= (const TBaseSet& rOtherSet) const {
02101   FD_DC("BaseSet::op>=()");
02102   return ( std::includes(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end()) );
02103 }
02104 
02105 // operator<
02106 TEMP bool THIS::operator< (const TBaseSet& rOtherSet) const {
02107   return *pSet < *rOtherSet.pSet;
02108 }
02109 
02110 
02111 // attribute typeinfo
02112 TEMP const AttributeVoid* THIS::Attributep(void) const { 
02113   static AttributeVoid attr; 
02114   return & attr; 
02115 }
02116 
02117 // attribute typeinfo
02118 TEMP const AttributeVoid& THIS::Attribute(void) const { 
02119   static AttributeVoid attr; 
02120   return attr;
02121 }
02122 
02123 // attribute access
02124 TEMP AttributeVoid* THIS::Attributep(const T& rElem) { 
02125   (void) rElem;
02126   std::stringstream errstr;
02127   errstr << "cannot get attribute for TBaseSet \"" << mMyName  << "\" type " << typeid(*this).name();
02128   throw Exception("TBaseSet::Attributep(rElem)", errstr.str(), 63);  
02129   static AttributeVoid attr; 
02130   return &attr; 
02131 }
02132 
02133 // attribute access
02134 TEMP const AttributeVoid& THIS::Attribute(const T& rElem) const { 
02135   (void) rElem;
02136   static AttributeVoid attr; 
02137   return attr;
02138 }
02139 
02140 // attribute access
02141 TEMP void THIS::Attribute(const T& rElem, const Type& rAttr) {
02142   (void) rElem;
02143   /* its pointless to test existence of the element since we wont set any attribute anyway
02144 #ifdef FAUDES_CHECKED
02145   if (!Exists(rElem)) {
02146     std::stringstream errstr;
02147     errstr << "element not member of set" << std::endl;
02148     throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 60);
02149   }
02150 #endif
02151   */
02152   if(!AttributeTry(rAttr)) {
02153     std::stringstream errstr;
02154     errstr << "cannot cast attribute " << std::endl;
02155     throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 63);
02156   }
02157   /* alternative approach: 
02158   // silently ignore any value
02159   // set to void is ok for silient ignore
02160   if(typeid(rAttr)==typeid(const AttributeVoid&)) return;
02161   // set to nontrivial attribute: exception
02162   std::stringstream errstr;
02163   errstr << "cannot set attribute type " << typeid(rAttr).name() << " for TBaseSet \"" << mMyName 
02164     << "\" type " << typeid(*this).name();
02165   throw Exception("TBaseSet::Attribute(rElem,rAttr)", errstr.str(), 63);  
02166   */
02167 }
02168 
02169 
02170 
02171 /* undefine local shortcuts */
02172 #undef THIS
02173 #undef TEMP
02174 #undef BASE
02175 
02176 /** @} doxygen group */
02177 
02178 } // namespace faudes
02179 
02180 #endif 

libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen