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 BASESET_H
00026 
00027 #include "definitions.h"
00028 #include "tokenwriter.h"
00029 #include "tokenreader.h"
00030 #include <set>
00031 #include <algorithm>
00032 
00033 namespace faudes {
00034 
00081 template<class T, class Cmp=std::less<T> >
00082 class TBaseSet {
00083 
00084 public:
00085 
00089   TBaseSet(void);
00090 
00097   TBaseSet(const TBaseSet& rOtherSet);
00098 
00102   virtual ~TBaseSet(void);
00103 
00110   std::string Name(void) const;
00111         
00118   void Name(const std::string& rName);
00119 
00123   virtual void Clear(void);
00124       
00131   Idx Size(void) const;
00132 
00139   bool Empty(void) const;
00140 
00147   void Write(void) const;
00148 
00164   void Write(const std::string& pFileName, const std::string& rLabel="",
00165       std::ios::openmode openmode = std::ios::out|std::ios::trunc) const;
00166 
00180   void Write(TokenWriter& rTw, const std::string& rLabel="") const;
00181 
00192   std::string ToString(void) const;
00193 
00200   void DWrite(void) const;
00201 
00210   void DWrite(TokenWriter& rTw) const;
00211 
00225    void DWrite(const char* pFileName, 
00226       std::ios::openmode openmode = std::ios::out|std::ios::trunc) const;
00227 
00242   void Read(const std::string& rFileName, const std::string& rLabel = "BaseSet");
00243 
00258   void Read(TokenReader& rTr, const std::string& rLabel = "BaseSet");
00259 
00260 
00265   class Iterator;
00266 
00273   Iterator Begin(void) const;
00274         
00281   Iterator End(void) const;
00282 
00294   virtual bool Valid(const T& rElem) const;
00295    
00296 
00305   virtual bool Erase(const T& rElem);
00306 
00307 
00316   virtual Iterator Erase(const Iterator& pos); 
00317 
00318 
00325   virtual void EraseSet(const TBaseSet& rOtherSet);
00326 
00327 
00336   virtual bool Insert(const T& rElem);
00337 
00345   virtual void InsertSet(const TBaseSet& rOtherSet);
00346 
00353   virtual void SetUnion(const TBaseSet& rOtherSet);
00354 
00361   virtual void SetIntersection(const TBaseSet& rOtherSet);
00362 
00363 
00373   bool Exists(const T& rElem) const;
00374 
00384   Iterator Find(const T& rElem) const;
00385 
00392    TBaseSet operator + (const TBaseSet& rOtherSet) const;
00393 
00400    TBaseSet operator - (const TBaseSet& rOtherSet) const;
00401 
00408   TBaseSet operator * (const TBaseSet& rOtherSet) const;
00409 
00410 
00412   bool operator == (const TBaseSet& rOtherSet) const;
00413 
00415   bool operator != (const TBaseSet& rOtherSet) const;
00416 
00418   bool operator <= (const TBaseSet& rOtherSet) const;
00419 
00421   bool operator >= (const TBaseSet& rOtherSet) const;
00422 
00424   bool operator < (const TBaseSet& rOtherSet) const;
00425 
00427   virtual const TBaseSet& operator=(const TBaseSet& rSrc) {return Assign(rSrc);};
00428 
00430   void DValid(const std::string& rMessage="") const;
00431 
00433   void Detach(void) const;
00434 
00436   void Lock(void) const;
00437 
00447    class Iterator : private std::set<T,Cmp>::const_iterator {
00448      public: 
00450      Iterator() : 
00451        std::set<T,Cmp>::const_iterator() , 
00452        pBaseSet(NULL),
00453        mAttached(false) 
00454      {};
00455 
00457      Iterator(
00458        const TBaseSet<T,Cmp>* pBaseSet,
00459        const typename std::set<T,Cmp>::const_iterator& sit) : 
00460        std::set<T,Cmp>::const_iterator(sit), 
00461        pBaseSet(pBaseSet),
00462        mAttached(false)  
00463      {};
00464 
00466      Iterator(const Iterator& fit) : 
00467        std::set<T,Cmp>::const_iterator(fit),
00468        pBaseSet(fit.pBaseSet), 
00469        mAttached(false) 
00470      {
00471        if(pBaseSet) {
00472           pBaseSet->AttachIterator(this);
00473           mAttached=true;
00474        }
00475      };  
00476 
00478      ~Iterator(void) { 
00479        if(mAttached) pBaseSet->DetachIterator(this);
00480      }; 
00481 
00483      const Iterator& operator= (const Iterator& rSrc) {
00484 #ifdef FAUDES_DEBUG_CODE
00485        if(rSrc.pBaseSet==NULL) {
00486          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator= invalid iterator: no baseset");
00487          abort();
00488        }
00489 #endif
00490        // performance relevant std case 
00491        if(mAttached) if(pBaseSet==rSrc.pBaseSet) {
00492          std::set<T,Cmp>::const_iterator::operator= (rSrc);
00493          return *this;
00494        }
00495        // general case
00496        if(mAttached) pBaseSet->DetachIterator(this);
00497        std::set<T,Cmp>::const_iterator::operator= (rSrc);
00498        pBaseSet = rSrc.pBaseSet;
00499        if(pBaseSet) {
00500          pBaseSet->AttachIterator(this);
00501          mAttached=true;
00502        } else {
00503   mAttached=false;
00504        }
00505        return *this;
00506      };
00507 
00509      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00510        std::set<T,Cmp>::const_iterator::operator= (sit);
00511      };
00512 
00514      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00515        return *this;
00516      };
00517 
00519      void  Invalidate(void) {
00520        pBaseSet=NULL;
00521        mAttached=false;
00522      }; 
00523 
00525      void  Detach(void) {
00526        mAttached=false;
00527      }; 
00528 
00529 
00531      void DValid(void) const {
00532       if(pBaseSet==NULL) {
00533          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):DValid(): invalid iterator: no baseset");
00534          abort();
00535        }
00536        pBaseSet->DValid();
00537      }; 
00538 
00540      const T* operator-> (void) const {
00541 #ifdef FAUDES_DEBUG_CODE
00542        if(pBaseSet==NULL) {
00543          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator->: invalid iterator: no baseset");
00544          abort();
00545        }
00546 #endif
00547        return std::set<T,Cmp>::const_iterator::operator-> ();
00548      };
00549 
00551      const T& operator* (void) const {
00552 #ifdef FAUDES_DEBUG_CODE
00553        if(pBaseSet==NULL) {
00554          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator*: invalid iterator: no baseset");
00555          abort();
00556        }
00557 #endif
00558        return std::set<T,Cmp>::const_iterator::operator* ();
00559      };
00560 
00562      bool operator == (const Iterator& rOther) const {
00563 #ifdef FAUDES_DEBUG_CODE
00564        if(pBaseSet==NULL) {
00565          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator==: invalid iterator: no baseset");
00566          abort();
00567        }
00568 #endif
00569        return std::set<T,Cmp>::const_iterator::operator == (rOther);
00570      };
00571 
00573      bool operator != (const Iterator& rOther) const {
00574 #ifdef FAUDES_DEBUG_CODE
00575        if(pBaseSet==NULL) {
00576          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator!=: invalid iterator: no baseset");
00577          abort();
00578        }
00579 #endif
00580        return std::set<T,Cmp>::const_iterator::operator != (rOther);
00581      };
00582 
00584      Iterator operator++ (int step) {
00585 #ifdef FAUDES_DEBUG_CODE
00586        if(pBaseSet==NULL) {
00587          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00588          abort();
00589        }
00590 #endif
00591        Iterator old(pBaseSet,*this);
00592        std::set<T,Cmp>::const_iterator::operator++ (step);
00593        return old;
00594      };
00595 
00597      const Iterator& operator++ (void) {
00598 #ifdef FAUDES_DEBUG_CODE
00599        if(pBaseSet==NULL) {
00600          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator++: invalid iterator: no baseset");
00601          abort();
00602        }
00603 #endif
00604        std::set<T,Cmp>::const_iterator::operator++ ();
00605        return *this;
00606      };
00607 
00609      Iterator operator-- (int step) {
00610 #ifdef FAUDES_DEBUG_CODE
00611        if(pBaseSet==NULL) {
00612          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00613          abort();
00614        }
00615 #endif
00616        Iterator old(pBaseSet, *this);
00617        std::set<T,Cmp>::const_iterator::operator-- (step);
00618        return old;
00619      };
00620 
00622      const Iterator& operator-- (void) {
00623 #ifdef FAUDES_DEBUG_CODE
00624        if(pBaseSet==NULL) {
00625          FD_ERR("TBaseSet<T,Cmp>::Iterator(" << this << "):operator--: invalid iterator: no baseset");
00626          abort();
00627        }
00628 #endif
00629        std::set<T,Cmp>::const_iterator::operator-- ();
00630        return *this;
00631      };
00632 
00633 
00635      /*
00636      bool operator < (const Iterator& rOther) const {
00637        return this < &rOther;
00638      };
00639      */
00640 
00642      const TBaseSet<T,Cmp>* pBaseSet;
00643 
00645      bool mAttached;
00646    };
00647 
00648 #ifdef DONT_TRACK_REFERENCES
00649 
00654    class Iterator : public std::set<T,Cmp>::const_iterator {
00655      public:
00656 
00658      Iterator(void) : 
00659        std::set<T,Cmp>::const_iterator()  
00660      {}; 
00661 
00663      Iterator(const Iterator& fit) : 
00664        std::set<T,Cmp>::const_iterator(fit)
00665      {};
00666 
00668      Iterator(const typename std::set<T,Cmp>::const_iterator& sit) : 
00669        std::set<T,Cmp>::const_iterator(sit)
00670      {};
00671 
00673      Iterator(
00674        const TBaseSet<T,Cmp>* pBaseSet,
00675        const typename std::set<T,Cmp>::const_iterator& sit) : 
00676        std::set<T,Cmp>::const_iterator(sit) 
00677      {};
00678 
00680      void  StlIterator(const typename std::set<T,Cmp>::const_iterator& sit) {
00681        std::set<T,Cmp>::const_iterator::operator= (sit);
00682      }; 
00683 
00685      const typename std::set<T,Cmp>::const_iterator& StlIterator(void) const {
00686        return *this;
00687      };
00688 
00690      void  Invalidate(void) {};
00691 
00692    };
00693 
00694 #endif
00695 
00696 
00697 protected:
00698 
00699 
00705   virtual void DoDWrite(TokenWriter& rTw) const;
00706 
00712   virtual void DoWrite(TokenWriter& rTw, const std::string& rLabel="") const;
00713 
00719   virtual void DoRead(TokenReader& rTr, const std::string& rLabel = "BaseSet");
00720 
00722   const TBaseSet<T,Cmp>& Assign(const TBaseSet<T,Cmp>& rOtherSet);
00723 
00725   std::set<T,Cmp>* mpSet;
00726 
00728   static std::set<T,Cmp> mEmptySet;
00729 
00731   std::set<T,Cmp>* pSet;
00732 
00734   typedef typename std::set<T,Cmp>::iterator iterator;
00735 
00737   typedef typename std::set<T,Cmp>::const_iterator const_iterator;
00738 
00740   typename TBaseSet<T,Cmp>::Iterator ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const;
00741 
00742 
00743 private:
00744 
00745 
00747   std::string mMyName;
00748 
00750   std::set< TBaseSet<T,Cmp>* > mReferences;
00751 
00753   TBaseSet<T,Cmp>* pBaseSet;
00754 
00756   bool mDetached;
00757 
00759   bool mLocked;
00760 
00762   void RelinkReferences(void);
00763 
00765   void AttachReference(TBaseSet* pRef) const;
00766 
00768   void DetachReference(TBaseSet* pRef) const;
00769 
00771   std::set< Iterator* > mIterators;
00772 
00774   void AttachIterator(Iterator* pFit) const;
00775 
00777   void DetachIterator(Iterator* pFit) const;
00778 
00779 };
00780 
00781 
00786 /*
00787 ******************************************************************************************
00788 ******************************************************************************************
00789 ******************************************************************************************
00790 
00791 Implementation of TBaseSet
00792 
00793 ******************************************************************************************
00794 ******************************************************************************************
00795 ******************************************************************************************
00796 */
00797 
00798 
00799 // template staticxs: empty set
00800 template<class T, class Cmp>
00801 std::set<T,Cmp> TBaseSet<T,Cmp>::mEmptySet=std::set<T,Cmp>();
00802 
00803 
00804 // TBaseSet()
00805 template<class T, class Cmp>
00806 TBaseSet<T,Cmp>::TBaseSet(void) :
00807   mpSet(NULL),
00808   pSet(&mEmptySet),  
00809   pBaseSet(this),
00810   mDetached(false), 
00811   mLocked(false) 
00812 {
00813   FD_DC("TBaseSet(" << this << ")::TBaseSet()");
00814   // maintain deferred copy 
00815   /*
00816   mpSet= new std::set<T,Cmp>();
00817   pSet=mpSet;
00818   mDetached=true;
00819   */
00820   // other members
00821   mMyName="BaseSet";
00822 }
00823 
00824 
00825 
00826 // TBaseSet(rOtherSet)
00827 template<class T, class Cmp>
00828 TBaseSet<T,Cmp>::TBaseSet(const TBaseSet& rOtherSet) :
00829   mpSet(NULL),
00830   pSet(NULL),  
00831   pBaseSet(this),
00832   mDetached(false), 
00833   mLocked(false) 
00834 {
00835   FD_DC("TBaseSet(" << this << ")::TBaseSet(rOtherSet " << &rOtherSet << "): fake copy construct");
00836   // maintain deferred copy 
00837   pBaseSet=rOtherSet.pBaseSet;
00838   pBaseSet->AttachReference(this);
00839   pSet=rOtherSet.pSet;
00840   // other members
00841   mMyName=rOtherSet.mMyName;
00842 #ifdef FAUDES_DEBUG_CONTAINER
00843   DValid();
00844 #endif
00845 }
00846 
00847 // destructor
00848 template<class T, class Cmp>
00849 TBaseSet<T,Cmp>::~TBaseSet(void) {
00850   FD_DC("TBaseSet(" << this << ")::~TBaseSet()");
00851   // maintain deferred copy 
00852   RelinkReferences();
00853   pBaseSet->DetachReference(this);
00854   if(mpSet) delete mpSet;
00855   // unlink iterators (mandatory, since referenced object is destructed)
00856   typename std::set< Iterator* >::const_iterator iit;
00857   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00858     (**iit).Invalidate();
00859   }
00860 }
00861 
00862 // assignement
00863 template<class T, class Cmp> 
00864 const TBaseSet<T,Cmp>& TBaseSet<T,Cmp>::Assign(const  TBaseSet<T,Cmp>& rOtherSet) {
00865   FD_DC("TBaseSet(" << this << ")::Assign(rOtherSet " << &rOtherSet << "): fake assignment");
00866   // bail out ojn selfref
00867   if(this==&rOtherSet) return *this;
00868   // maintain deferred copy 
00869   RelinkReferences();
00870   pBaseSet->DetachReference(this);
00871   mReferences.clear();
00872   pBaseSet=rOtherSet.pBaseSet;
00873   pBaseSet->AttachReference(this);
00874   pSet=rOtherSet.pSet;
00875   if(mpSet) {
00876      delete mpSet;
00877      mpSet=NULL;
00878   }
00879   mDetached=false; 
00880   mLocked=false;
00881   // fix iterators (invalidate)
00882   typename std::set< Iterator* >::iterator iit;
00883   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00884     (**iit).Invalidate();
00885   }
00886   mIterators.clear();
00887   // other members 
00888   mMyName=rOtherSet.mMyName;
00889 #ifdef FAUDES_DEBUG_CONTAINER
00890   DValid();
00891 #endif
00892   return *this;
00893 }
00894 
00895 
00896 // Detach()
00897 template<class T, class Cmp> 
00898 void TBaseSet<T,Cmp>::Detach(void) const {
00899   FD_DC("TBaseSet(" << this << ")::Detach(void)");
00900 #ifdef FAUDES_DEBUG_CONTAINER
00901   DValid();
00902 #endif
00903 
00904   // nothing todo
00905   if(mDetached) return;
00906 
00907   // provide fake const
00908   TBaseSet<T,Cmp>* fake_const = const_cast< TBaseSet<T,Cmp>* >(this);
00909 
00910   // might have overseen reference detach
00911   if(pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL) {
00912     fake_const->mDetached=true;
00913     return;
00914   }
00915 
00916   // stragie A: references get the copy; thus, the baseset data does
00917   // not get reallocated and we dont need to track iterators. on the
00918   // downside, fixing the references iterators may be more effort.
00919   if(mLocked==true) {
00920    
00921     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie A");
00922     // do allocation and copy of stl set
00923     std::set<T,Cmp>* copy = new std::set<T,Cmp>();
00924     *copy = *pSet;     
00925     // first of my reference gets the new data
00926     TBaseSet<T,Cmp>* storage = *mReferences.begin();
00927     storage->pBaseSet=storage;
00928     storage->mpSet=copy; 
00929     storage->pSet=copy;
00930     storage->mReferences=mReferences;
00931     storage->DetachReference(storage);
00932     // check whether new storage is detached
00933     if(storage->mReferences.empty()) 
00934        storage->mDetached=true;
00935     // set other users to new storage
00936     typename std::set< TBaseSet<T,Cmp>* >::const_iterator rit;
00937     for(rit=mReferences.begin(), ++rit ;rit!=mReferences.end(); ++rit) {
00938       (*rit)->pBaseSet=storage;
00939       (*rit)->pSet=copy;
00940     }
00941     // fix other users iterators (incl new storage)
00942     for(rit=mReferences.begin(); rit!=mReferences.end(); ++rit) {
00943       typename std::set< Iterator* >::iterator iit;
00944       for(iit=(*rit)->mIterators.begin(); iit!=(*rit)->mIterators.end(); ++iit) {
00945         if((**iit).StlIterator()==pSet->end()) 
00946           **iit=Iterator(this, copy->end());
00947         else
00948           **iit=Iterator(this, copy->find(***iit));
00949       }
00950     }
00951     // make myself own the old data
00952     fake_const->mpSet=pSet;
00953     fake_const->mReferences.clear();
00954     fake_const->mDetached=true;    
00955     // stop tracking iterators
00956     typename std::set< Iterator* >::const_iterator iit;
00957     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00958       (**iit).Detach();
00959     }
00960     fake_const->mIterators.clear();
00961 
00962 
00963   // stragie B: this baseset gets the copy; thus, the references iterators
00964   // remain valid and dont need to be fixed; on the downside, we need to
00965   // continue to track iterators.
00966   } else {
00967 
00968 
00969     FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie B");
00970     // make someone else handle original data
00971     fake_const->RelinkReferences();
00972     // do allocation and copy
00973     fake_const->mpSet = new std::set<T,Cmp>();
00974     *fake_const->mpSet= *pSet;     
00975     // fix iterators
00976     typename std::set< Iterator* >::iterator iit;
00977     for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
00978       if((**iit).StlIterator()==pSet->end()) 
00979         **iit=Iterator(this, mpSet->end());
00980       else
00981         **iit=Iterator(this, mpSet->find(***iit));
00982     }
00983     // unlink from old source, link to new source
00984     pBaseSet->DetachReference(fake_const);
00985     if(pBaseSet->pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL)
00986       pBaseSet->mDetached=true;
00987     fake_const->pBaseSet=fake_const;
00988     fake_const->pSet=mpSet;
00989     fake_const->mDetached=true;
00990 
00991   }
00992 
00993 #ifdef FAUDES_DEBUG_CONTAINER
00994   DValid();
00995 #endif
00996   FD_DC("TBaseSet(" << this << ")::Detach(void): done");
00997 }
00998 
00999 // Lock()
01000 template<class T, class Cmp> 
01001 void TBaseSet<T,Cmp>::Lock(void) const {
01002   FD_DC("TBaseSet(" << this << ")::Lock(void)");
01003 #ifdef FAUDES_DEBUG_CONTAINER
01004   DValid();
01005 #endif
01006 
01007   // trigger actual copy
01008   Detach();
01009 
01010   // provide fake const
01011   TBaseSet<T,Cmp>* fake_const = const_cast< TBaseSet<T,Cmp>* >(this);
01012 
01013   // stop tracking iterators
01014   typename std::set< Iterator* >::const_iterator iit;
01015   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01016     (**iit).Detach();
01017   }
01018   fake_const->mIterators.clear();
01019 
01020   // stop detach from reallocating
01021   fake_const->mLocked=true;
01022 }
01023 
01024 
01025 // if a am a source to others, make someone else source  
01026 template<class T, class Cmp>
01027 inline void TBaseSet<T,Cmp>::RelinkReferences(void) {
01028   FD_DC("TBaseSet::RelinkReferences(" << this << ")")
01029 #ifdef FAUDES_DEBUG_CONTAINER
01030   DValid();
01031 #endif
01032   // no references aka this is not a source
01033   if(mReferences.empty()) return;
01034   // make first ref the new storage
01035   TBaseSet<T,Cmp>* storage = *mReferences.begin();
01036 #ifdef FAUDES_DEBUG_CODE
01037   if(storage->pBaseSet!=this) {
01038     FD_ERR("TBaseSet<T,Cmp>::RelinkRefernces: old reference must have this as storage provider");
01039     abort();
01040   }
01041 #endif
01042   storage->pBaseSet=storage;
01043   storage->mpSet=mpSet; 
01044   storage->pSet=pSet;
01045   storage->mReferences=mReferences;
01046   storage->DetachReference(storage);
01047   // set other users to new storage
01048   typename std::set< TBaseSet<T,Cmp>* >::const_iterator rit;
01049   for(rit=mReferences.begin(), ++rit;rit!=mReferences.end(); ++rit) {
01050     (*rit)->pBaseSet=storage;
01051   }
01052   // make myself a reference to the new source
01053   pBaseSet=storage;
01054   pSet=storage->pSet;
01055   mpSet=NULL;
01056   storage->AttachReference(this);
01057   mReferences.clear();
01058 #ifdef FAUDES_DEBUG_CONTAINER
01059   DValid();
01060 #endif
01061   FD_DC("TBaseSet::RelinkReferences(" << this << "): done")
01062 }
01063 
01064 
01065 // record fake copy
01066 template<class T, class Cmp>
01067 inline void TBaseSet<T,Cmp>::AttachReference(TBaseSet* pRef) const {
01068    const_cast< TBaseSet<T,Cmp>* >(this)->mReferences.insert(pRef);
01069    const_cast< TBaseSet<T,Cmp>* >(this)->mDetached=false;
01070 }
01071 
01072 // discard fake copy
01073 template<class T, class Cmp>
01074 inline void TBaseSet<T,Cmp>::DetachReference(TBaseSet* pRef) const {
01075    const_cast< TBaseSet<T,Cmp>* >(this)->mReferences.erase(pRef);
01076 }
01077 
01078 
01079 // record an iterator
01080 template<class T, class Cmp>
01081 inline void TBaseSet<T,Cmp>::AttachIterator(Iterator* pFit) const {
01082   if(mLocked) return;
01083   FD_DC("TBaseSet::AttachIterator(" << this << "):" << pFit)
01084   const_cast< TBaseSet<T,Cmp>* >(this)->mIterators.insert(pFit);
01085 }
01086 
01087 // discard an iterator
01088 template<class T, class Cmp>
01089 inline void TBaseSet<T,Cmp>::DetachIterator(Iterator* pFit) const {
01090   if(mLocked) return;
01091   FD_DC("TBaseSet::DetachIterator(" << this << "):" << pFit)
01092   const_cast< TBaseSet<T,Cmp>* >(this)->mIterators.erase(pFit);
01093 }
01094 
01095 
01096 
01097 // test some validity
01098 template<class T, class Cmp>
01099 void TBaseSet<T,Cmp>::DValid(const std::string& rMessage) const {
01100   typename std::set< Iterator* >::const_iterator iit;
01101 #ifdef FAUDES_DEBUG_CONTAINER
01102   std::cout << "TBaseSet<T,Cmp>(" << this << "," << rMessage << ")::DValid:  source " 
01103      << pBaseSet << " #" << (pBaseSet->pSet==&mEmptySet ? "e" : "f") << " -- list: ";
01104   typename std::set< TBaseSet<T,Cmp>* >::const_iterator rit;
01105   for(rit=pBaseSet->mReferences.begin(); rit!=pBaseSet->mReferences.end(); ++rit)
01106     std::cout << *rit << " ";
01107   std::cout << "-- iterators: ";
01108   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit)
01109     std::cout << *iit << " ";
01110   std::cout << "." << std::endl;
01111 #endif
01112   // iterators, that dont refer to me as basset
01113   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01114     if((*iit)->pBaseSet!=this) {
01115       FD_ERR("TBaseSet<T,Cmp>("<< this << "," << rMessage <<"): invalid iterator (baseset): "<< *iit);
01116       abort();
01117     }
01118   }
01119   // iterators, that are not marked as attechd
01120   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01121     if(!(*iit)->mAttached) {
01122       FD_ERR("TBaseSet<T,Cmp>("<< this << "," << rMessage <<"): invalid iterator (attached): "<< *iit);
01123       abort();
01124     }
01125   }
01126   // iterators, that are invalid stl iterators
01127   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01128     typename std::set<T,Cmp>::const_iterator vit;
01129     for(vit=pSet->begin(); vit!= pSet->end(); ++vit) {
01130       if(vit==(**iit).StlIterator()) break;
01131     }
01132     if(vit!=(**iit).StlIterator()) { // end-iterator is fine, too
01133       FD_ERR("TBaseSet<T,Cmp>("<< this << "," << rMessage <<"): invalid iterator (stl "<< *iit);
01134       (**iit).StlIterator(pSet->end()); // fix invalid iterator to refer to end()
01135     }
01136   }
01137   // must have some base 
01138   if(pBaseSet==NULL) {
01139     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): no base found");
01140     abort();
01141   }
01142   // base must provide data either way
01143   if(pBaseSet->pBaseSet != pBaseSet) {
01144     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): no source found");
01145     abort();
01146   }
01147   // refers to other base and own data
01148   if((mpSet!=NULL) && (pBaseSet != this)) {
01149     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): double data");
01150     abort();
01151   }
01152   // refers to other base and has references
01153   if(pBaseSet!=this && !mReferences.empty()) {
01154     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): cannot have source and refs");
01155     abort();
01156   }
01157   // is base but has no own data
01158   if((pBaseSet == this) && (mpSet==NULL) && (pSet!=&mEmptySet)) {
01159     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): no data");
01160     abort();
01161   }
01162   // is base but own data pointer mismatch
01163   if((pBaseSet == this) && (pSet != mpSet) && (pSet!=&mEmptySet)) {
01164     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): data pointer mismatch A");
01165     abort();
01166   }
01167   // refers to base with data pointer mismatch
01168   if((pBaseSet != this) && (pSet != pBaseSet->pSet)) {
01169     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): data pointer mismatch B");
01170     abort();
01171   }
01172   // error in detached flag
01173   if(mDetached && !pBaseSet->mReferences.empty()) {
01174     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): invalid detached flag");
01175     abort();
01176   }
01177   // error in detached flag
01178   if(mDetached && (pSet==&mEmptySet)) {
01179     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): detached empty set");
01180     abort();
01181   }
01182   // error in lock flag
01183   if(pBaseSet!=this && mLocked) {
01184     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): locked reference");
01185     abort();
01186   }
01187   // invalid emptyset
01188   if(!mEmptySet.empty()) {
01189     FD_ERR("TBaseSet<T,Cmp>(" << this << "," << rMessage << "): invalid empty set");
01190     abort();
01191   }
01192 }
01193 
01194 
01195 
01196 // Name
01197 template<class T, class Cmp>
01198 std::string TBaseSet<T,Cmp>::Name(void) const {
01199   return mMyName;
01200 }
01201     
01202 // Name
01203 template<class T, class Cmp>
01204 void TBaseSet<T,Cmp>::Name(const std::string& rName) {
01205   mMyName = rName;
01206 }
01207   
01208 // Size()
01209 template<class T, class Cmp>
01210 Idx TBaseSet<T,Cmp>::Size(void) const {
01211   return (Idx) pSet->size();
01212 }
01213 
01214 // Empty()
01215 template<class T, class Cmp>
01216 bool TBaseSet<T,Cmp>::Empty(void) const {
01217   return pSet->empty();
01218 }
01219 
01220 // Write()
01221 template<class T, class Cmp>
01222 void TBaseSet<T,Cmp>::Write(void) const {
01223   TokenWriter tw(TokenWriter::Stdout);
01224   DoWrite(tw);
01225 }
01226 
01227 // Write(rFileName, label, openmode)
01228 template<class T, class Cmp>
01229 void TBaseSet<T,Cmp>::Write(const std::string& rFileName, const std::string& rLabel, std::ios::openmode openmode) const {
01230   try {
01231     TokenWriter tw(rFileName, openmode);
01232     DoWrite(tw, rLabel);
01233   }
01234   catch (std::ios::failure&) {
01235     std::stringstream errstr;
01236     errstr << "Exception opening/writing file \"" << rFileName << "\"";
01237     throw Exception("TBaseSet::Write", errstr.str(), 2);
01238   }
01239 }
01240 
01241 // Write(tw,label)
01242 template<class T, class Cmp>
01243 void TBaseSet<T,Cmp>::Write(TokenWriter& rTw, const std::string& rLabel) const {
01244   DoWrite(rTw,rLabel);
01245 }
01246 
01247 // ToString()
01248 template<class T, class Cmp>
01249 std::string TBaseSet<T,Cmp>::ToString(void) const {
01250   TokenWriter tw(TokenWriter::String);
01251   DoWrite(tw);
01252   return tw.Str();
01253 }
01254 
01255 // DoWrite(tw,rLabel)
01256 template<class T, class Cmp>
01257 void TBaseSet<T,Cmp>::DoWrite(TokenWriter& rTw,const std::string& rLabel) const {
01258   std::string label=rLabel;
01259   if(label=="") label=Name(); 
01260   rTw.WriteBegin(label);
01261   rTw.WriteEnd(label);
01262 }
01263 
01264 // DWrite()
01265 template<class T, class Cmp>
01266 void TBaseSet<T,Cmp>::DWrite(void) const {
01267   TokenWriter tw(TokenWriter::Stdout);
01268   DoDWrite(tw);
01269 }
01270 
01271 // DWrite(rFileName, openmode)
01272 template<class T, class Cmp>
01273 void TBaseSet<T,Cmp>::DWrite(const char* rFileName, std::ios::openmode openmode) const {
01274   try {
01275     TokenWriter tw(rFileName, openmode);
01276     DoDWrite(tw);
01277   }
01278   catch (std::ios::failure&) {
01279     std::stringstream errstr;
01280     errstr << "Exception opening/writing file \"" << rFileName << "\"";
01281     throw Exception("TBaseSet::DWrite", errstr.str(), 2);
01282   }
01283 }
01284 
01285 // DWrite(tw)
01286 template<class T, class Cmp>
01287 void TBaseSet<T,Cmp>::DWrite(TokenWriter& rTw) const {
01288   DoDWrite(rTw);
01289 }
01290 
01291 // DoDWrite(tw)
01292 template<class T, class Cmp>
01293 void TBaseSet<T,Cmp>::DoDWrite(TokenWriter& rTw) const {
01294   rTw.Comment("");
01295   rTw.Comment(" Size/Shares/Iterators: " + ToStringInteger(pSet->size()) 
01296               + "/" + ToStringInteger(pBaseSet->mReferences.size())
01297         + "/" + ToStringInteger(mIterators.size()));
01298   rTw.Comment("");
01299 #ifdef FAUDES_DEBUG_CONTAINER
01300   DValid();
01301 #endif
01302 }
01303 
01304 // Read(rFilename, rLabel)
01305 template<class T, class Cmp>
01306 void TBaseSet<T,Cmp>::Read(const std::string& rFilename, const std::string& rLabel) {
01307   TokenReader tr(rFilename);
01308   Read(tr,rLabel);
01309 }
01310 
01311 // Read(rTr, rLabel)
01312 template<class T, class Cmp>
01313 void TBaseSet<T,Cmp>::Read(TokenReader& rTr, const std::string& rLabel) {
01314   DoRead(rTr,rLabel);
01315 }
01316 
01317 // DoRead(rTr, rLabel)
01318 template<class T, class Cmp>
01319 void TBaseSet<T,Cmp>::DoRead(TokenReader& rTr, const std::string& rLabel) {
01320   Name(rLabel);
01321   Clear();
01322   rTr.SeekBegin(rLabel); 
01323   rTr.SeekEnd(rLabel); 
01324 }
01325 
01326 // ThisIterator
01327 template<class T, class Cmp>
01328 typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const {
01329   return Iterator(this,sit);
01330 }
01331 
01332 // Begin() const
01333 template<class T, class Cmp>
01334 inline typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::Begin(void) const {
01335   return ThisIterator(pSet->begin());
01336 }
01337     
01338 // End() const
01339 template<class T, class Cmp>
01340 inline typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::End(void) const {
01341   return ThisIterator(pSet->end());
01342 }
01343 
01344 
01345 //Clear
01346 template<class T, class Cmp>
01347 void TBaseSet<T,Cmp>::Clear(void) {
01348   FD_DC("TBaseSet(" << this << ")::Clear(void)");
01349 #ifdef FAUDES_DEBUG_CONTAINER
01350   DValid();
01351 #endif
01352   // special case: empty anyway
01353   if(pSet==&mEmptySet) return;
01354   // special case: locked requires a copy
01355   if(mLocked) Detach();
01356   // make someone else handle the data
01357   if(!mReferences.empty()) 
01358     RelinkReferences();
01359   // create empty set
01360   if(pBaseSet!=this) {
01361     FD_DC("TBaseSet(" << this << ")::Clear(void): allocate");
01362     mpSet = new std::set<T,Cmp>();
01363     pSet=mpSet;
01364     pBaseSet->DetachReference(this);
01365     pBaseSet=this;
01366     FD_DC("TBaseSet(" << this << ")::Clear(void): allocate: done");
01367   }
01368   // fix iterators (invalidate)
01369   typename std::set< Iterator* >::iterator iit;
01370   for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) {
01371     (**iit).Invalidate();
01372   }
01373   mIterators.clear();
01374   mDetached=true;
01375   // clear the stl set
01376   pSet->clear();
01377 #ifdef FAUDES_DEBUG_CONTAINER
01378   DValid();
01379 #endif
01380 }
01381 
01382 
01383 //Valid(elem)
01384 template<class T, class Cmp>
01385 inline bool  TBaseSet<T,Cmp>::Valid(const T& rElem) const {
01386   (void) rElem;
01387   return true;
01388 }
01389 
01390 //Insert(elem)
01391 template<class T, class Cmp>
01392 bool TBaseSet<T,Cmp>::Insert(const T& rElem) {
01393 #ifdef FAUDES_CHECKED
01394   if(!Valid(rElem)) {
01395     std::stringstream errstr;
01396     errstr << "cannot insert invalid element" << std::endl;
01397     throw Exception("TBaseSet<T,Cmp>::Insert", errstr.str(), 61);
01398   }
01399 #endif
01400   if(!mDetached) Detach();
01401   return pSet->insert(rElem).second;
01402 }
01403 
01404 // InsertSet(set)
01405 template<class T, class Cmp>
01406 void TBaseSet<T,Cmp>::InsertSet(const TBaseSet& rOtherSet) {
01407   FD_DC("TBaseSet(" << this << ")::InsertSet(" << &rOtherSet << ")");
01408   if(!mDetached) Detach();
01409   // TODO: test and optimize
01410   iterator it1 = pSet->begin();
01411   iterator it2 = rOtherSet.pSet->begin();
01412   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01413     if (*it1 < *it2) {
01414       ++it1;
01415     }
01416     else if (*it1 == *it2) {
01417       ++it1;
01418       ++it2;
01419     }
01420     else { // (*it1 > *it2)
01421       pSet->insert(*it2);
01422       ++it2;
01423     }
01424   }
01425   while (it2 != rOtherSet.pSet->end()) {
01426     pSet->insert(*it2);
01427     ++it2;
01428   }
01429 }
01430     
01431 //Erase(rElem)
01432 template<class T, class Cmp>
01433 bool TBaseSet<T,Cmp>::Erase(const T& rElem) {
01434   if(!mDetached) Detach();
01435   return (pSet->erase(rElem)!=0);
01436 }
01437 
01438 
01439 //Erase(pos)
01440 template<class T, class Cmp>
01441 typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::Erase(const Iterator& pos) { 
01442 #ifdef FAUDES_CHECKED
01443   if (pos == End()) {
01444     std::stringstream errstr;
01445     errstr << "iterator out of range " << std::endl;
01446     throw Exception("TBaseSet<T,Cmp>::Erase", errstr.str(), 62);
01447   }
01448 #endif
01449   Detach();
01450   iterator del= pos.StlIterator(); 
01451   iterator res= del;
01452   res++; 
01453   pSet->erase(del);
01454   return ThisIterator(res); 
01455 }
01456 
01457 
01458 //EraseSet(set)
01459 template<class T, class Cmp>
01460 void TBaseSet<T,Cmp>::EraseSet(const TBaseSet& rOtherSet) {
01461   FD_DC("TBaseSet(" << this << ")::EraseSet(" << &rOtherSet << ")");
01462   if(!mDetached) Detach();
01463   // TODO: test and optimize 
01464   iterator tmpit;
01465   iterator it = pSet->begin();
01466   iterator oit = rOtherSet.pSet->begin();
01467   while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) {
01468     if (*it < *oit) {
01469       it=pSet->lower_bound(*oit); // alt: ++it;
01470     }
01471     else if (*it == *oit) { 
01472       tmpit=it;
01473       ++it;
01474       ++oit;
01475       pSet->erase(tmpit);
01476     }
01477     else { // (*it > *oit)
01478       oit=rOtherSet.pSet->lower_bound(*it); // ++it2;
01479     }
01480   }
01481 }
01482 
01483 
01484 //Find(elem)
01485 template<class T, class Cmp>
01486 typename TBaseSet<T,Cmp>::Iterator TBaseSet<T,Cmp>::Find(const T& rElem) const {
01487   return ThisIterator(pSet->find(rElem));
01488 }
01489 
01490 //Exists(elem)
01491 template<class T, class Cmp>
01492 bool  TBaseSet<T,Cmp>::Exists(const T& rElem) const {
01493   return pSet->find(rElem) != pSet->end();
01494 }
01495 
01496 
01497 // SetUnion(set)
01498 template<class T, class Cmp>
01499 void TBaseSet<T,Cmp>::SetUnion(const TBaseSet& rOtherSet) {
01500   if(!mDetached) Detach();
01501   iterator it1 = pSet->begin();
01502   iterator it2 = rOtherSet.pSet->begin();
01503   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01504     if (*it1 < *it2) {
01505       ++it1;
01506       continue;
01507     }
01508     if (*it1 == *it2) {
01509       ++it1;
01510       ++it2;
01511       continue;
01512     }
01513     // (*it1 > *it2)
01514     pSet->insert(it1,*it2);
01515     ++it2;
01516   }
01517   while (it2 != rOtherSet.pSet->end()) {
01518     pSet->insert(pSet->end(),*it2);
01519     ++it2;
01520   }
01521 }
01522 
01523 // SetIntersection(set)
01524 template<class T, class Cmp>
01525 void TBaseSet<T,Cmp>::SetIntersection(const TBaseSet& rOtherSet) {
01526   if(!mDetached) Detach();
01527   iterator tmpit;
01528   iterator it1 = pSet->begin();
01529   iterator it2 = rOtherSet.pSet->begin();
01530   while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) {
01531     if (*it1 < *it2) {
01532       tmpit=it1;
01533       ++it1;
01534       pSet->erase(tmpit);
01535       continue;
01536     }
01537     if (*it1 == *it2) {
01538       ++it1;
01539       ++it2;
01540       continue;
01541     }
01542     // if (*it1 > *it2)
01543     ++it2;
01544   }
01545   while(it1 != pSet->end()) {
01546     tmpit=it1;
01547     ++it1;
01548     pSet->erase(tmpit);
01549   }
01550 }
01551 
01552 
01553 // operator +
01554 template<class T, class Cmp>
01555 TBaseSet<T,Cmp> TBaseSet<T,Cmp>::operator + (const TBaseSet& rOtherSet) const {
01556   FD_DC("TBaseSet(" << this << ")::operator + (" << &rOtherSet << ")");
01557   TBaseSet res;
01558   res.Detach();
01559   std::insert_iterator< std::set<Idx> > insit(*res.pSet, res.pSet->begin());
01560   std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01561   res.Name(CollapsString(Name() + "+" + rOtherSet.Name()));
01562   return res;
01563 }
01564 
01565 // operator -
01566 template<class T, class Cmp>
01567 TBaseSet<T,Cmp> TBaseSet<T,Cmp>::operator - (const TBaseSet& rOtherSet) const {
01568   FD_DC("TBaseSet(" << this << ")::operator - (" << &rOtherSet << ")");
01569   TBaseSet res;
01570   res.Detach();
01571   std::insert_iterator< std::set<Idx> > insit(*res.pSet, res.pSet->begin());
01572   std::set_difference(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01573   res.Name(CollapsString(Name() + "-" + rOtherSet.Name()));
01574   return res;
01575 }
01576 
01577      
01578 // operator *
01579 template<class T, class Cmp>
01580 TBaseSet<T,Cmp> TBaseSet<T,Cmp>::operator * (const TBaseSet& rOtherSet) const {
01581   FD_DC("TBaseSet(" << this << ")::operator * (" << &rOtherSet << ")");
01582   TBaseSet res;
01583   res.Detach();
01584   std::insert_iterator< std::set<Idx> > insit(*res.pSet, res.pSet->begin());
01585   std::set_intersection(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit);
01586   res.Name(CollapsString(Name() + "*" + rOtherSet.Name()));
01587   return res;
01588 }
01589 
01590 
01591 // operator ==
01592 template<class T, class Cmp>
01593 bool TBaseSet<T,Cmp>::operator == (const TBaseSet& rOtherSet) const {
01594   return  ( *pSet == *rOtherSet.pSet );
01595 }
01596 
01597 // operator != 
01598 template<class T, class Cmp>
01599 bool TBaseSet<T,Cmp>::operator != (const TBaseSet& rOtherSet) const {
01600   return  ( *pSet != *rOtherSet.pSet );
01601 }
01602 
01603 // operator <=
01604 template<class T, class Cmp>
01605 bool TBaseSet<T,Cmp>::operator <= (const TBaseSet& rOtherSet) const {
01606   return ( std::includes(rOtherSet.pSet->begin(), rOtherSet.pSet->end(), pSet->begin(), pSet->end()) ) ;
01607 }
01608 
01609 // operator >=
01610 template<class T, class Cmp>
01611 bool TBaseSet<T,Cmp>::operator >= (const TBaseSet& rOtherSet) const {
01612   return ( std::includes(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end()) );
01613 }
01614 
01615 // operator <
01616 template<class T, class Cmp>
01617 bool TBaseSet<T,Cmp>::operator < (const TBaseSet& rOtherSet) const {
01618   return *pSet < *rOtherSet.pSet;
01619 }
01620 
01621 
01624 } // namespace faudes
01625 
01626 #define BASESET_H
01627 #endif 

Generated on Fri May 9 11:26:47 2008 for libFAUDES 2.09b by  doxygen 1.4.4