baseset.h

Go to the documentation of this file.
00001 
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 "definitions.h"
00029 #include "interface.h"
00030 #include "tokenwriter.h"
00031 #include "tokenreader.h"
00032 #include <set>
00033 #include <algorithm>
00034 
00035 namespace faudes {
00036 
00084 template<class T, class Cmp=std::less<T> >
00085   class TBaseSet : FAUDES_TYPE {
00086 
00087 public:
00088 
00092   TBaseSet(void);
00093 
00100   TBaseSet(const TBaseSet& rOtherSet);
00101 
00105   virtual ~TBaseSet(void);
00106 
00113   std::string Name(void) const;
00114         
00121   void Name(const std::string& rName);
00122 
00126   virtual void Clear(void);
00127       
00134   Idx Size(void) const;
00135 
00142   bool Empty(void) const;
00143 
00148   class Iterator;
00149 
00156   Iterator Begin(void) const;
00157         
00164   Iterator End(void) const;
00165 
00177   virtual bool Valid(const T& rElem) const;
00178    
00179 
00188   virtual bool Erase(const T& rElem);
00189 
00190 
00199   virtual Iterator Erase(const Iterator& pos); 
00200 
00201 
00208   virtual void EraseSet(const TBaseSet& rOtherSet);
00209 
00210 
00219   virtual bool Insert(const T& rElem);
00220 
00228   virtual void InsertSet(const TBaseSet& rOtherSet);
00229 
00236   virtual void SetUnion(const TBaseSet& rOtherSet);
00237 
00244   virtual void SetIntersection(const TBaseSet& rOtherSet);
00245 
00246 
00256   bool Exists(const T& rElem) const;
00257 
00267   Iterator Find(const T& rElem) const;
00268 
00275    TBaseSet operator + (const TBaseSet& rOtherSet) const;
00276 
00283    TBaseSet operator - (const TBaseSet& rOtherSet) const;
00284 
00291   TBaseSet operator * (const TBaseSet& rOtherSet) const;
00292 
00293 
00295   bool operator == (const TBaseSet& rOtherSet) const;
00296 
00298   bool operator != (const TBaseSet& rOtherSet) const;
00299 
00301   bool operator <= (const TBaseSet& rOtherSet) const;
00302 
00304   bool operator >= (const TBaseSet& rOtherSet) const;
00305 
00307   bool operator < (const TBaseSet& rOtherSet) const;
00308 
00310   virtual const TBaseSet& operator=(const TBaseSet& rSrc) {return Assign(rSrc);};
00311 
00313   void DValid(const std::string& rMessage="") const;
00314 
00316   void Detach(void) const;
00317 
00319   void Lock(void) const;
00320 
00334    class Iterator : public std::set<T,Cmp>::const_iterator {
00335      public: 
00337      Iterator() : 
00338        std::set<T,Cmp>::const_iterator() , 
00339        pBaseSet(NULL),
00340        mAttached(false) 
00341      {};
00342 
00344      Iterator(
00345        const TBaseSet<T,Cmp>* pBaseSet,
00346        const typename std::set<T,Cmp>::const_iterator& sit) : 
00347        std::set<T,Cmp>::const_iterator(sit), 
00348        pBaseSet(pBaseSet),
00349        mAttached(false)  
00350      {};
00351 
00353      Iterator(const Iterator& fit) : 
00354        std::set<T,Cmp>::const_iterator(fit),
00355        pBaseSet(fit.pBaseSet), 
00356        mAttached(false) 
00357      {
00358        if(pBaseSet) {
00359           pBaseSet->AttachIterator(this);
00360           mAttached=true;
00361        }
00362      };  
00363 
00365      ~Iterator(void) { 
00366        if(mAttached) pBaseSet->DetachIterator(this);
00367      }; 
00368 
00370      const Iterator& operator= (const Iterator& rSrc) {
00371 #ifdef FAUDES_DEBUG_CODE
00372        if(rSrc.pBaseSet==NULL) {
00373          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator= invalid iterator: no baseset");
00374          abort();
00375        }
00376 #endif
00377        // performance relevant std case 
00378        if(mAttached) if(pBaseSet==rSrc.pBaseSet) {
00379          std::set<T,Cmp>::const_iterator::operator= (rSrc);
00380          return *this;
00381        }
00382        // general case
00383        if(mAttached) pBaseSet->DetachIterator(this);
00384        std::set<T,Cmp>::const_iterator::operator= (rSrc);
00385        pBaseSet = rSrc.pBaseSet;
00386        if(pBaseSet) {
00387          pBaseSet->AttachIterator(this);
00388          mAttached=true;
00389        } else {
00390   mAttached=false;
00391        }
00392        return *this;
00393      };
00394 
00396      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00397        std::set<T,Cmp>::const_iterator::operator= (sit);
00398      };
00399 
00401      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00402        return *this;
00403      };
00404 
00406      void  Invalidate(void) {
00407        pBaseSet=NULL;
00408        mAttached=false;
00409      }; 
00410 
00412      void  Detach(void) {
00413        mAttached=false;
00414      }; 
00415 
00416 
00418      void DValid(void) const {
00419       if(pBaseSet==NULL) {
00420          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):DValid(): invalid iterator: no baseset");
00421          abort();
00422        }
00423        pBaseSet->DValid();
00424      }; 
00425 
00427      const T* operator-> (void) const {
00428 #ifdef FAUDES_DEBUG_CODE
00429        if(pBaseSet==NULL) {
00430          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator->: invalid iterator: no baseset");
00431          abort();
00432        }
00433 #endif
00434        return std::set<T,Cmp>::const_iterator::operator-> ();
00435      };
00436 
00438      const T& operator* (void) const {
00439 #ifdef FAUDES_DEBUG_CODE
00440        if(pBaseSet==NULL) {
00441          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator*: invalid iterator: no baseset");
00442          abort();
00443        }
00444 #endif
00445        return std::set<T,Cmp>::const_iterator::operator* ();
00446      };
00447 
00449      bool operator == (const Iterator& rOther) const {
00450 #ifdef FAUDES_DEBUG_CODE
00451        if(pBaseSet==NULL) {
00452          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator==: invalid iterator: no baseset");
00453          abort();
00454        }
00455 #endif
00456        return std::set<T,Cmp>::const_iterator::operator == (rOther);
00457      };
00458 
00460      bool operator != (const Iterator& rOther) const {
00461 #ifdef FAUDES_DEBUG_CODE
00462        if(pBaseSet==NULL) {
00463          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator!=: invalid iterator: no baseset");
00464          abort();
00465        }
00466 #endif
00467        return std::set<T,Cmp>::const_iterator::operator != (rOther);
00468      };
00469 
00471      Iterator operator++ (int step) {
00472 #ifdef FAUDES_DEBUG_CODE
00473        if(pBaseSet==NULL) {
00474          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00475          abort();
00476        }
00477 #endif
00478        Iterator old(pBaseSet,*this);
00479        std::set<T,Cmp>::const_iterator::operator++ (step);
00480        return old;
00481      };
00482 
00484      const Iterator& operator++ (void) {
00485 #ifdef FAUDES_DEBUG_CODE
00486        if(pBaseSet==NULL) {
00487          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00488          abort();
00489        }
00490 #endif
00491        std::set<T,Cmp>::const_iterator::operator++ ();
00492        return *this;
00493      };
00494 
00496      Iterator operator-- (int step) {
00497 #ifdef FAUDES_DEBUG_CODE
00498        if(pBaseSet==NULL) {
00499          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00500          abort();
00501        }
00502 #endif
00503        Iterator old(pBaseSet, *this);
00504        std::set<T,Cmp>::const_iterator::operator-- (step);
00505        return old;
00506      };
00507 
00509      const Iterator& operator-- (void) {
00510 #ifdef FAUDES_DEBUG_CODE
00511        if(pBaseSet==NULL) {
00512          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00513          abort();
00514        }
00515 #endif
00516        std::set<T,Cmp>::const_iterator::operator-- ();
00517        return *this;
00518      };
00519 
00520 
00522      /*
00523      bool operator < (const Iterator& rOther) const {
00524        return this < &rOther;
00525      };
00526      */
00527 
00529      const TBaseSet<T,Cmp>* pBaseSet;
00530 
00532      bool mAttached;
00533    };
00534 
00535 #ifdef DONT_TRACK_REFERENCES
00536 
00541    class Iterator : public std::set<T,Cmp>::const_iterator {
00542      public:
00543 
00545      Iterator(void) : 
00546        std::set<T,Cmp>::const_iterator()  
00547      {}; 
00548 
00550      Iterator(const Iterator& fit) : 
00551        std::set<T,Cmp>::const_iterator(fit)
00552      {};
00553 
00555      Iterator(const typename std::set<T,Cmp>::const_iterator& sit) : 
00556        std::set<T,Cmp>::const_iterator(sit)
00557      {};
00558 
00560      Iterator(
00561        const TBaseSet<T,Cmp>* pBaseSet,
00562        const typename std::set<T,Cmp>::const_iterator& sit) : 
00563        std::set<T,Cmp>::const_iterator(sit) 
00564      {};
00565 
00567      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00568        std::set<T,Cmp>::const_iterator::operator= (sit);
00569      }; 
00570 
00572      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00573        return *this;
00574      };
00575 
00577      void  Invalidate(void) {};
00578 
00579    };
00580 
00581 #endif
00582 
00583 
00584 protected:
00585 
00586 
00598   virtual void DoDWrite(TokenWriter& rTw,const std::string& rLabel="", const Type* pContext=0) const;
00599 
00616   virtual void DoWrite(TokenWriter& rTw, const std::string& rLabel="", const Type* pContext=0) const;
00617 
00634   virtual void DoRead(TokenReader& rTr, const std::string& rLabel = "", const Type* pContext=0);
00635 
00637   const TBaseSet<T,Cmp>& Assign(const TBaseSet<T,Cmp>& rOtherSet);
00638 
00640   std::set<T,Cmp>* mpSet;
00641 
00643   static std::set<T,Cmp> mEmptySet;
00644 
00646   std::set<T,Cmp>* pSet;
00647 
00649   typedef typename std::set<T,Cmp>::iterator iterator;
00650 
00652   typedef typename std::set<T,Cmp>::const_iterator const_iterator;
00653 
00655   typename TBaseSet<T,Cmp>::Iterator ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const;
00656 
00657 
00658 private:
00659 
00660 
00662   std::string mMyName;
00663 
00665   std::set< TBaseSet<T,Cmp>* > mReferences;
00666 
00668   TBaseSet<T,Cmp>* pBaseSet;
00669 
00671   bool mDetached;
00672 
00674   bool mLocked;
00675 
00677   void RelinkReferences(void);
00678 
00680   void AttachReference(TBaseSet* pRef) const;
00681 
00683   void DetachReference(TBaseSet* pRef) const;
00684 
00686   std::set< Iterator* > mIterators;
00687 
00689   void AttachIterator(Iterator* pFit) const;
00690 
00692   void DetachIterator(Iterator* pFit) const;
00693 
00694 };
00695 
00696 
00701 /*
00702 ******************************************************************************************
00703 ******************************************************************************************
00704 ******************************************************************************************
00705 
00706 Implementation of TBaseSet
00707 
00708 ******************************************************************************************
00709 ******************************************************************************************
00710 ******************************************************************************************
00711 */
00712 
00713 
00714 // template staticxs: empty set
00715 template<class T, class Cmp>
00716 std::set<T,Cmp> TBaseSet<T,Cmp>::mEmptySet=std::set<T,Cmp>();
00717 
00718 
00719 // TBaseSet()
00720 template<class T, class Cmp>
00721 TBaseSet<T,Cmp>::TBaseSet(void) :
00722   mpSet(NULL),
00723   pSet(&mEmptySet),  
00724   pBaseSet(this),
00725   mDetached(false), 
00726   mLocked(false) 
00727 {
00728   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
00729   // maintain deferred copy 
00730   /*
00731   mpSet= new std::set<T,Cmp>();
00732   pSet=mpSet;
00733   mDetached=true;
00734   */
00735   // other members
00736   mMyName="BaseSet";
00737 }
00738 
00739 
00740 
00741 // TBaseSet(rOtherSet)
00742 template<class T, class Cmp>
00743 TBaseSet<T,Cmp>::TBaseSet(const TBaseSet& rOtherSet) : 
00744   Type(rOtherSet),
00745   mpSet(NULL),
00746   pSet(NULL),  
00747   pBaseSet(this),
00748   mDetached(false), 
00749   mLocked(false) 
00750 {
00751   FD_DC("TBaseSet(" << this << ")::TBaseSet(rOtherSet " << &rOtherSet << "): fake copy construct");
00752   // maintain deferred copy 
00753   pBaseSet=rOtherSet.pBaseSet;
00754   pBaseSet->AttachReference(this);
00755   pSet=rOtherSet.pSet;
00756   // other members
00757   mMyName=rOtherSet.mMyName;
00758 #ifdef FAUDES_DEBUG_CONTAINER
00759   DValid();
00760 #endif
00761 }
00762 
00763 // destructor
00764 template<class T, class Cmp>
00765 TBaseSet<T,Cmp>::~TBaseSet(void) {
00766   FD_DC("TBaseSet(" << this << ")::~TBaseSet()");
00767   // maintain deferred copy 
00768   RelinkReferences();
00769   pBaseSet->DetachReference(this);
00770   if(mpSet) delete mpSet;
00771   // unlink iterators (mandatory, since referenced object is destructed)
00772   typename std::set< Iterator* >::const_iterator iit;
00773   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00774     (**iit).Invalidate();
00775   }
00776 }
00777 
00778 // assignement
00779 template<class T, class Cmp> 
00780 const TBaseSet<T,Cmp>& TBaseSet<T,Cmp>::Assign(const  TBaseSet<T,Cmp>& rOtherSet) {
00781   FD_DC("TBaseSet(" << this << ")::Assign(rOtherSet " << &rOtherSet << "): fake assignment");
00782   // bail out ojn selfref
00783   if(this==&rOtherSet) return *this;
00784   // maintain deferred copy 
00785   RelinkReferences();
00786   pBaseSet->DetachReference(this);
00787   mReferences.clear();
00788   pBaseSet=rOtherSet.pBaseSet;
00789   pBaseSet->AttachReference(this);
00790   pSet=rOtherSet.pSet;
00791   if(mpSet) {
00792      delete mpSet;
00793      mpSet=NULL;
00794   }
00795   mDetached=false; 
00796   mLocked=false;
00797   // fix iterators (invalidate)
00798   typename std::set< Iterator* >::iterator iit;
00799   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00800     (**iit).Invalidate();
00801   }
00802   mIterators.clear();
00803   // other members 
00804   mMyName=rOtherSet.mMyName;
00805 #ifdef FAUDES_DEBUG_CONTAINER
00806   DValid();
00807 #endif
00808   return *this;
00809 }
00810 
00811 
00812 // Detach()
00813 template<class T, class Cmp> 
00814 void TBaseSet<T,Cmp>::Detach(void) const {
00815   FD_DC("TBaseSet(" << this << ")::Detach(void)");
00816 #ifdef FAUDES_DEBUG_CONTAINER
00817   DValid();
00818 #endif
00819 
00820   // nothing todo
00821   if(mDetached) return;
00822 
00823   // provide fake const
00824   TBaseSet<T,Cmp>* fake_const = const_cast< TBaseSet<T,Cmp>* >(this);
00825 
00826   // might have overseen reference detach
00827   if(pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL) {
00828     fake_const->mDetached=true;
00829     return;
00830   }
00831 
00832   // stragie A: references get the copy; thus, the baseset data does
00833   // not get reallocated and we dont need to track iterators. on the
00834   // downside, fixing the references iterators may be more effort.
00835   if(mLocked==true) {
00836    
00837     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie A");
00838     // do allocation and copy of stl set
00839     std::set<T,Cmp>* copy = new std::set<T,Cmp>();
00840     *copy = *pSet;     
00841     // first of my reference gets the new data
00842     TBaseSet<T,Cmp>* storage = *mReferences.begin();
00843     storage->pBaseSet=storage;
00844     storage->mpSet=copy; 
00845     storage->pSet=copy;
00846     storage->mReferences=mReferences;
00847     storage->DetachReference(storage);
00848     // check whether new storage is detached
00849     if(storage->mReferences.empty()) 
00850        storage->mDetached=true;
00851     // set other users to new storage
00852     typename std::set< TBaseSet<T,Cmp>* >::const_iterator rit;
00853     for(rit=mReferences.begin(), ++rit ;rit!=mReferences.end(); ++rit) {
00854       (*rit)->pBaseSet=storage;
00855       (*rit)->pSet=copy;
00856     }
00857     // fix other users iterators (incl new storage)
00858     for(rit=mReferences.begin(); rit!=mReferences.end(); ++rit) {
00859       typename std::set< Iterator* >::iterator iit;
00860       for(iit=(*rit)->mIterators.begin(); iit!=(*rit)->mIterators.end(); ++iit) {
00861         if((**iit).StlIterator()==pSet->end()) 
00862           **iit=Iterator(this, copy->end());
00863         else
00864           **iit=Iterator(this, copy->find(***iit));
00865       }
00866     }
00867     // make myself own the old data
00868     fake_const->mpSet=pSet;
00869     fake_const->mReferences.clear();
00870     fake_const->mDetached=true;    
00871     // stop tracking iterators
00872     typename std::set< Iterator* >::const_iterator iit;
00873     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00874       (**iit).Detach();
00875     }
00876     fake_const->mIterators.clear();
00877 
00878 
00879   // stragie B: this baseset gets the copy; thus, the references iterators
00880   // remain valid and dont need to be fixed; on the downside, we need to
00881   // continue to track iterators.
00882   } else {
00883 
00884 
00885     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie B");
00886     // make someone else handle original data
00887     fake_const->RelinkReferences();
00888     // do allocation and copy
00889     fake_const->mpSet = new std::set<T,Cmp>();
00890     *fake_const->mpSet= *pSet;     
00891     // fix iterators
00892     typename std::set< Iterator* >::iterator iit;
00893     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00894       if((**iit).StlIterator()==pSet->end()) 
00895         **iit=Iterator(this, mpSet->end());
00896       else
00897         **iit=Iterator(this, mpSet->find(***iit));
00898     }
00899     // unlink from old source, link to new source
00900     pBaseSet->DetachReference(fake_const);
00901     if(pBaseSet->pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL)
00902       pBaseSet->mDetached=true;
00903     fake_const->pBaseSet=fake_const;
00904     fake_const->pSet=mpSet;
00905     fake_const->mDetached=true;
00906 
00907   }
00908 
00909 #ifdef FAUDES_DEBUG_CONTAINER
00910   DValid();
00911 #endif
00912   FD_DC("TBaseSet(" << this << ")::Detach(void): done");
00913 }
00914 
00915 // Lock()
00916 template<class T, class Cmp> 
00917 void TBaseSet<T,Cmp>::Lock(void) const {
00918   FD_DC("TBaseSet(" << this << ")::Lock(void)");
00919 #ifdef FAUDES_DEBUG_CONTAINER
00920   DValid();
00921 #endif
00922 
00923   // trigger actual copy
00924   Detach();
00925 
00926   // provide fake const
00927   TBaseSet<T,Cmp>* fake_const = const_cast< TBaseSet<T,Cmp>* >(this);
00928 
00929   // stop tracking iterators
00930   typename std::set< Iterator* >::const_iterator iit;
00931   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00932     (**iit).Detach();
00933   }
00934   fake_const->mIterators.clear();
00935 
00936   // stop detach from reallocating
00937   fake_const->mLocked=true;
00938 }
00939 
00940 
00941 // if a am a source to others, make someone else source  
00942 template<class T, class Cmp>
00943 inline void TBaseSet<T,Cmp>::RelinkReferences(void) {
00944   FD_DC("TBaseSet::RelinkReferences(" << this << ")")
00945 #ifdef FAUDES_DEBUG_CONTAINER
00946   DValid();
00947 #endif
00948   // no references aka this is not a source
00949   if(mReferences.empty()) return;
00950   // make first ref the new storage
00951   TBaseSet<T,Cmp>* storage = *mReferences.begin();
00952 #ifdef FAUDES_DEBUG_CODE
00953   if(storage->pBaseSet!=this) {
00954     FD_ERR("TBaseSet<T,Cmp>::RelinkRefernces: old reference must have this as storage provider");
00955     abort();
00956   }
00957 #endif
00958   storage->pBaseSet=storage;
00959   storage->mpSet=mpSet; 
00960   storage->pSet=pSet;
00961   storage->mReferences=mReferences;
00962   storage->DetachReference(storage);
00963   // set other users to new storage
00964   typename std::set< TBaseSet<T,Cmp>* >::const_iterator rit;
00965   for(rit=mReferences.begin(), ++rit;rit!=mReferences.end(); ++rit) {
00966     (*rit)->pBaseSet=storage;
00967   }
00968   // make myself a reference to the new source
00969   pBaseSet=storage;
00970   pSet=storage->pSet;
00971   mpSet=NULL;
00972   storage->AttachReference(this);
00973   mReferences.clear();
00974 #ifdef FAUDES_DEBUG_CONTAINER
00975   DValid();
00976 #endif
00977   FD_DC("TBaseSet::RelinkReferences(" << this << "): done")
00978 }
00979 
00980 
00981 // record fake copy
00982 template<class T, class Cmp>
00983 inline void TBaseSet<T,Cmp>::AttachReference(TBaseSet* pRef) const {
00984    const_cast< TBaseSet<T,Cmp>* >(this)->mReferences.insert(pRef);
00985    const_cast< TBaseSet<T,Cmp>* >(this)->mDetached=false;
00986 }
00987 
00988 // discard fake copy
00989 template<class T, class Cmp>
00990 inline void TBaseSet<T,Cmp>::DetachReference(TBaseSet* pRef) const {
00991    const_cast< TBaseSet<T,Cmp>* >(this)->mReferences.erase(pRef);
00992 }
00993 
00994 
00995 // record an iterator
00996 template<class T, class Cmp>
00997 inline void TBaseSet<T,Cmp>::AttachIterator(Iterator* pFit) const {
00998   if(mLocked) return;
00999   FD_DC("TBaseSet::AttachIterator(" << this << "):" << pFit)
01000   const_cast< TBaseSet<T,Cmp>* >(this)->mIterators.insert(pFit);
01001 }
01002 
01003 // discard an iterator
01004 template<class T, class Cmp>
01005 inline void TBaseSet<T,Cmp>::DetachIterator(Iterator* pFit) const {
01006   if(mLocked) return;
01007   FD_DC("TBaseSet::DetachIterator(" << this << "):" << pFit)
01008   const_cast< TBaseSet<T,Cmp>* >(this)->mIterators.erase(pFit);
01009 }
01010 
01011 
01012 
01013 // test some validity
01014 template<class T, class Cmp>
01015 void TBaseSet<T,Cmp>::DValid(const std::string& rMessage) const {
01016   typename std::set< Iterator* >::const_iterator iit;
01017 #ifdef FAUDES_DEBUG_CONTAINER
01018   std::cout << "TBaseSet<T,Cmp>(" << this << "," << rMessage << ")::DValid:  source " 
01019      << pBaseSet << " #" << (pBaseSet->pSet==&mEmptySet ? "e" : "f") << " -- list: ";
01020   typename std::set< TBaseSet<T,Cmp>* >::const_iterator rit;
01021   for(rit=pBaseSet->mReferences.begin(); rit!=pBaseSet->mReferences.end(); ++rit)
01022     std::cout << *rit << " ";
01023   std::cout << "-- iterators: ";
01024   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit)
01025     std::cout << *iit << " ";
01026   std::cout << "." << std::endl;
01027 #endif
01028   // iterators, that dont refer to me as basset
01029   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01030     if((*iit)->pBaseSet!=this) {
01031       FD_ERR("TBaseSet<T,Cmp>("<< this << "," << rMessage <<"): invalid iterator (baseset): "<< *iit);
01032       abort();
01033     }
01034   }
01035   // iterators, that are not marked as attechd
01036   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01037     if(!(*iit)->mAttached) {
01038       FD_ERR("TBaseSet<T,Cmp>("<< this << "," << rMessage <<"): invalid iterator (attached): "<< *iit);
01039       abort();
01040     }
01041   }
01042   // iterators, that are invalid stl iterators
01043   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01044     typename std::set<T,Cmp>::const_iterator vit;
01045     for(vit=pSet->begin(); vit!= pSet->end(); ++vit) {
01046       if(vit==(**iit).StlIterator()) break;
01047     }
01048     if(vit!=(**iit).StlIterator()) { // end-iterator is fine, too
01049       FD_ERR("TBaseSet<T,Cmp>("<< this << "," << rMessage <<"): invalid iterator (stl "<< *iit);
01050       (**iit).StlIterator(pSet->end()); // fix invalid iterator to refer to end()
01051     }
01052   }
01053   // must have some base 
01054   if(pBaseSet==NULL) {
01055     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): no base found");
01056     abort();
01057   }
01058   // base must provide data either way
01059   if(pBaseSet->pBaseSet != pBaseSet) {
01060     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): no source found");
01061     abort();
01062   }
01063   // refers to other base and own data
01064   if((mpSet!=NULL) && (pBaseSet != this)) {
01065     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): double data");
01066     abort();
01067   }
01068   // refers to other base and has references
01069   if(pBaseSet!=this && !mReferences.empty()) {
01070     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): cannot have source and refs");
01071     abort();
01072   }
01073   // is base but has no own data
01074   if((pBaseSet == this) && (mpSet==NULL) && (pSet!=&mEmptySet)) {
01075     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): no data");
01076     abort();
01077   }
01078   // is base but own data pointer mismatch
01079   if((pBaseSet == this) && (pSet != mpSet) && (pSet!=&mEmptySet)) {
01080     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): data pointer mismatch A");
01081     abort();
01082   }
01083   // refers to base with data pointer mismatch
01084   if((pBaseSet != this) && (pSet != pBaseSet->pSet)) {
01085     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): data pointer mismatch B");
01086     abort();
01087   }
01088   // error in detached flag
01089   if(mDetached && !pBaseSet->mReferences.empty()) {
01090     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): invalid detached flag");
01091     abort();
01092   }
01093   // error in detached flag
01094   if(mDetached && (pSet==&mEmptySet)) {
01095     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): detached empty set");
01096     abort();
01097   }
01098   // error in lock flag
01099   if(pBaseSet!=this && mLocked) {
01100     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): locked reference");
01101     abort();
01102   }
01103   // invalid emptyset
01104   if(!mEmptySet.empty()) {
01105     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): invalid empty set");
01106     abort();
01107   }
01108 }
01109 
01110 
01111 
01112 // Name
01113 template<class T, class Cmp>
01114 std::string TBaseSet<T,Cmp>::Name(void) const {
01115   return mMyName;
01116 }
01117     
01118 // Name
01119 template<class T, class Cmp>
01120 void TBaseSet<T,Cmp>::Name(const std::string& rName) {
01121   mMyName = rName;
01122 }
01123   
01124 // Size()
01125 template<class T, class Cmp>
01126 Idx TBaseSet<T,Cmp>::Size(void) const {
01127   return (Idx) pSet->size();
01128 }
01129 
01130 // Empty()
01131 template<class T, class Cmp>
01132 bool TBaseSet<T,Cmp>::Empty(void) const {
01133   return pSet->empty();
01134 }
01135 
01136 
01137 // DoWrite(tw,rLabel,cpntext)
01138 template<class T, class Cmp>
01139 void TBaseSet<T,Cmp>::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
01140   (void) pContext;
01141   std::string label=rLabel;
01142   if(label=="") label=Name(); 
01143   if(label=="") label="BaseSet"; 
01144   rTw.WriteBegin(label);
01145   rTw.WriteEnd(label);
01146 }
01147 
01148 
01149 // DoDWrite(tw, label, context)
01150 template<class T, class Cmp>
01151 void TBaseSet<T,Cmp>::DoDWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
01152   (void) pContext;
01153   (void) rLabel;
01154   rTw.WriteComment("");
01155   rTw.WriteComment(" Size/Shares/Iterators: " + ToStringInteger(pSet->size()) 
01156               + "/" + ToStringInteger(pBaseSet->mReferences.size())
01157         + "/" + ToStringInteger(mIterators.size()));
01158   rTw.WriteComment("");
01159 #ifdef FAUDES_DEBUG_CONTAINER
01160   DValid();
01161 #endif
01162 }
01163 
01164 // DoRead(rTr, rLabel, pContext)
01165 template<class T, class Cmp>
01166 void TBaseSet<T,Cmp>::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
01167   (void) pContext;
01168   Name(rLabel);
01169   rTr.SeekBegin(rLabel); 
01170   rTr.SeekEnd(rLabel); 
01171 }
01172 
01173 // ThisIterator
01174 template<class T, class Cmp>
01175 typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const {
01176   return Iterator(this,sit);
01177 }
01178 
01179 // Begin() const
01180 template<class T, class Cmp>
01181 inline typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::Begin(void) const {
01182   return ThisIterator(pSet->begin());
01183 }
01184     
01185 // End() const
01186 template<class T, class Cmp>
01187 inline typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::End(void) const {
01188   return ThisIterator(pSet->end());
01189 }
01190 
01191 
01192 //Clear
01193 template<class T, class Cmp>
01194 void TBaseSet<T,Cmp>::Clear(void) {
01195   FD_DC("TBaseSet(" << this << ")::Clear()");
01196 #ifdef FAUDES_DEBUG_CONTAINER
01197   DValid();
01198 #endif
01199   // special case: empty anyway
01200   if(pSet==&mEmptySet) return;
01201   // special case: locked requires a copy
01202   if(mLocked) Detach();
01203   // make someone else handle the data
01204   if(!mReferences.empty()) 
01205     RelinkReferences();
01206   // create empty set
01207   if(pBaseSet!=this) {
01208     FD_DC("TBaseSet(" << this << ")::Clear(): allocate");
01209     mpSet = new std::set<T,Cmp>();
01210     pSet=mpSet;
01211     pBaseSet->DetachReference(this);
01212     pBaseSet=this;
01213     FD_DC("TBaseSet(" << this << ")::Clear(): allocate: done");
01214   }
01215   // fix iterators (invalidate)
01216   typename std::set< Iterator* >::iterator iit;
01217   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01218     (**iit).Invalidate();
01219   }
01220   mIterators.clear();
01221   mDetached=true;
01222   // clear the stl set
01223   pSet->clear();
01224 #ifdef FAUDES_DEBUG_CONTAINER
01225   DValid();
01226 #endif
01227 }
01228 
01229 
01230 //Valid(elem)
01231 template<class T, class Cmp>
01232 inline bool  TBaseSet<T,Cmp>::Valid(const T& rElem) const {
01233   (void) rElem;
01234   return true;
01235 }
01236 
01237 //Insert(elem)
01238 template<class T, class Cmp>
01239 bool TBaseSet<T,Cmp>::Insert(const T& rElem) {
01240 #ifdef FAUDES_CHECKED
01241   if(!Valid(rElem)) {
01242     std::stringstream errstr;
01243     errstr << "cannot insert invalid element" << std::endl;
01244     throw Exception("TBaseSet<T,Cmp>::Insert", errstr.str(), 61);
01245   }
01246 #endif
01247   if(!mDetached) Detach();
01248   return pSet->insert(rElem).second;
01249 }
01250 
01251 // InsertSet(set)
01252 template<class T, class Cmp>
01253 void TBaseSet<T,Cmp>::InsertSet(const TBaseSet& rOtherSet) {
01254   FD_DC("TBaseSet(" << this << ")::InsertSet(" << &rOtherSet << ")");
01255   if(!mDetached) Detach();
01256   // TODO: test and optimize
01257   iterator it1 = pSet->begin();
01258   iterator it2 = rOtherSet.pSet->begin();
01259   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01260     if (*it1 < *it2) {
01261       ++it1;
01262     }
01263     else if (*it1 == *it2) {
01264       ++it1;
01265       ++it2;
01266     }
01267     else { // (*it1 > *it2)
01268       pSet->insert(*it2);
01269       ++it2;
01270     }
01271   }
01272   while (it2 != rOtherSet.pSet->end()) {
01273     pSet->insert(*it2);
01274     ++it2;
01275   }
01276 }
01277     
01278 //Erase(rElem)
01279 template<class T, class Cmp>
01280 bool TBaseSet<T,Cmp>::Erase(const T& rElem) {
01281   if(!mDetached) Detach();
01282   return (pSet->erase(rElem)!=0);
01283 }
01284 
01285 
01286 //Erase(pos)
01287 template<class T, class Cmp>
01288 typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::Erase(const Iterator& pos) { 
01289 #ifdef FAUDES_CHECKED
01290   if (pos == End()) {
01291     std::stringstream errstr;
01292     errstr << "iterator out of range " << std::endl;
01293     throw Exception("TBaseSet<T,Cmp>::Erase", errstr.str(), 62);
01294   }
01295 #endif
01296   Detach();
01297   iterator del= pos.StlIterator(); 
01298   iterator res= del;
01299   res++; 
01300   pSet->erase(del);
01301   return ThisIterator(res); 
01302 }
01303 
01304 
01305 //EraseSet(set)
01306 template<class T, class Cmp>
01307 void TBaseSet<T,Cmp>::EraseSet(const TBaseSet& rOtherSet) {
01308   FD_DC("TBaseSet(" << this << ")::EraseSet(" << &rOtherSet << ")");
01309   if(!mDetached) Detach();
01310   // TODO: test and optimize 
01311   iterator tmpit;
01312   iterator it = pSet->begin();
01313   iterator oit = rOtherSet.pSet->begin();
01314   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
01315     if (*it < *oit) {
01316       it=pSet->lower_bound(*oit); // alt: ++it;
01317     }
01318     else if (*it == *oit) { 
01319       tmpit=it;
01320       ++it;
01321       ++oit;
01322       pSet->erase(tmpit);
01323     }
01324     else { // (*it > *oit)
01325       oit=rOtherSet.pSet->lower_bound(*it); // ++it2;
01326     }
01327   }
01328 }
01329 
01330 
01331 //Find(elem)
01332 template<class T, class Cmp>
01333 typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::Find(const T& rElem) const {
01334   return ThisIterator(pSet->find(rElem));
01335 }
01336 
01337 //Exists(elem)
01338 template<class T, class Cmp>
01339 bool  TBaseSet<T,Cmp>::Exists(const T& rElem) const {
01340   return pSet->find(rElem) != pSet->end();
01341 }
01342 
01343 
01344 // SetUnion(set)
01345 template<class T, class Cmp>
01346 void TBaseSet<T,Cmp>::SetUnion(const TBaseSet& rOtherSet) {
01347   if(!mDetached) Detach();
01348   iterator it1 = pSet->begin();
01349   iterator it2 = rOtherSet.pSet->begin();
01350   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01351     if (*it1 < *it2) {
01352       ++it1;
01353       continue;
01354     }
01355     if (*it1 == *it2) {
01356       ++it1;
01357       ++it2;
01358       continue;
01359     }
01360     // (*it1 > *it2)
01361     pSet->insert(it1,*it2);
01362     ++it2;
01363   }
01364   while (it2 != rOtherSet.pSet->end()) {
01365     pSet->insert(pSet->end(),*it2);
01366     ++it2;
01367   }
01368 }
01369 
01370 // SetIntersection(set)
01371 template<class T, class Cmp>
01372 void TBaseSet<T,Cmp>::SetIntersection(const TBaseSet& rOtherSet) {
01373   if(!mDetached) Detach();
01374   iterator tmpit;
01375   iterator it1 = pSet->begin();
01376   iterator it2 = rOtherSet.pSet->begin();
01377   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01378     if (*it1 < *it2) {
01379       tmpit=it1;
01380       ++it1;
01381       pSet->erase(tmpit);
01382       continue;
01383     }
01384     if (*it1 == *it2) {
01385       ++it1;
01386       ++it2;
01387       continue;
01388     }
01389     // if (*it1 > *it2)
01390     ++it2;
01391   }
01392   while(it1 != pSet->end()) {
01393     tmpit=it1;
01394     ++it1;
01395     pSet->erase(tmpit);
01396   }
01397 }
01398 
01399 
01400 // operator +
01401 template<class T, class Cmp>
01402 TBaseSet<T,Cmp> TBaseSet<T,Cmp>::operator + (const TBaseSet& rOtherSet) const {
01403   FD_DC("TBaseSet(" << this << ")::operator + (" << &rOtherSet << ")");
01404   TBaseSet res;
01405   res.Detach();
01406   std::insert_iterator< std::set<Idx> > insit(*res.pSet, res.pSet->begin());
01407   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01408   res.Name(CollapsString(Name() + "+" + rOtherSet.Name()));
01409   return res;
01410 }
01411 
01412 // operator -
01413 template<class T, class Cmp>
01414 TBaseSet<T,Cmp> TBaseSet<T,Cmp>::operator - (const TBaseSet& rOtherSet) const {
01415   FD_DC("TBaseSet(" << this << ")::operator - (" << &rOtherSet << ")");
01416   TBaseSet res;
01417   res.Detach();
01418   std::insert_iterator< std::set<Idx> > insit(*res.pSet, res.pSet->begin());
01419   std::set_difference(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01420   res.Name(CollapsString(Name() + "-" + rOtherSet.Name()));
01421   return res;
01422 }
01423 
01424      
01425 // operator *
01426 template<class T, class Cmp>
01427 TBaseSet<T,Cmp> TBaseSet<T,Cmp>::operator * (const TBaseSet& rOtherSet) const {
01428   FD_DC("TBaseSet(" << this << ")::operator * (" << &rOtherSet << ")");
01429   TBaseSet res;
01430   res.Detach();
01431   std::insert_iterator< std::set<Idx> > insit(*res.pSet, res.pSet->begin());
01432   std::set_intersection(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01433   res.Name(CollapsString(Name() + "*" + rOtherSet.Name()));
01434   return res;
01435 }
01436 
01437 
01438 // operator ==
01439 template<class T, class Cmp>
01440 bool TBaseSet<T,Cmp>::operator == (const TBaseSet& rOtherSet) const {
01441   return  ( *pSet == *rOtherSet.pSet );
01442 }
01443 
01444 // operator != 
01445 template<class T, class Cmp>
01446 bool TBaseSet<T,Cmp>::operator != (const TBaseSet& rOtherSet) const {
01447   return  ( *pSet != *rOtherSet.pSet );
01448 }
01449 
01450 // operator <=
01451 template<class T, class Cmp>
01452 bool TBaseSet<T,Cmp>::operator <= (const TBaseSet& rOtherSet) const {
01453   return ( std::includes(rOtherSet.pSet->begin(), rOtherSet.pSet->end(), pSet->begin(), pSet->end()) ) ;
01454 }
01455 
01456 // operator >=
01457 template<class T, class Cmp>
01458 bool TBaseSet<T,Cmp>::operator >= (const TBaseSet& rOtherSet) const {
01459   return ( std::includes(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end()) );
01460 }
01461 
01462 // operator <
01463 template<class T, class Cmp>
01464 bool TBaseSet<T,Cmp>::operator < (const TBaseSet& rOtherSet) const {
01465   return *pSet < *rOtherSet.pSet;
01466 }
01467 
01468 
01471 } // namespace faudes
01472 
01473 #endif 

Generated on Mon Nov 10 08:13:14 2008 for libFAUDES 2.11v by  doxygen 1.4.4