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

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen