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