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