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

libFAUDES 2.22k --- 2013.04.02 --- c++ source docu by doxygen