|
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 * Check if the TBaseSet ist 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 interators 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 turmn 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(); 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 /** Indocate 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 /** STL set, if the object owns content (else NULL) */ 00842 std::set<T,Cmp>* mpSet; 00843 00844 /** Attribute map, if this object owns content (else NULL). */ 00845 std::map<T,AttributeVoid*>* mpAttributes; 00846 00847 /** static empty STL set for default constructor */ 00848 static std::set<T,Cmp> mEmptySet; 00849 00850 /** static empty STL map for default constructor */ 00851 static std::map<T,AttributeVoid*> mEmptyAttributes; 00852 00853 /** Pointer on STL set to operate on */ 00854 std::set<T,Cmp>* pSet; 00855 00856 /** Pointer to attribute map to operate on */ 00857 std::map<T,AttributeVoid*>* pAttributes; 00858 00859 /** STL iterator, non-const version */ 00860 typedef typename std::set<T,Cmp>::iterator iterator; 00861 00862 /** STL iterator, const version */ 00863 typedef typename std::set<T,Cmp>::const_iterator const_iterator; 00864 00865 /** Convert STL iterator */ 00866 typename TBaseSet<T,Cmp>::Iterator ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const; 00867 00868 /** STL attribute iterator, non-const version */ 00869 typedef typename std::map<T,AttributeVoid*>::iterator aiterator; 00870 00871 /** STL attribute iterator, const version */ 00872 typedef typename std::map<T,AttributeVoid*>::const_iterator const_aiterator; 00873 00874 00875 protected: 00876 00877 00878 /** Name of TBaseSet */ 00879 std::string mMyName; 00880 00881 /** Other BaseSets, that refer to the STL set provided by this TBaseSet */ 00882 std::set< TBaseSet<T,Cmp>* > mReferences; 00883 00884 /** Pointer on BaseSet that owns the STL set this BaseSet referrs to */ 00885 TBaseSet<T,Cmp>* pBaseSet; 00886 00887 /** Indicate "has no references, provides STL set" */ 00888 bool mDetached; 00889 00890 /** Indicate "dont re-allocate the STL set again" */ 00891 bool mLocked; 00892 00893 /** Ensure that we do not serve contents to anyone else */ 00894 void RelinkReferences(void); 00895 00896 /** Record that we serve contents to some other TBaseSet */ 00897 void AttachReference(TBaseSet* pRef) const; 00898 00899 /** Record that we stop serving contents to some TBaseSet */ 00900 void DetachReference(TBaseSet* pRef) const; 00901 00902 /** Iterators that refer to this TBaseSet */ 00903 std::set< Iterator* > mIterators; 00904 00905 /** Record that an iterator refers to this TBaseSet */ 00906 void AttachIterator(Iterator* pFit) const; 00907 00908 /** Record that an iterator stops to refer to this TBaseSet */ 00909 void DetachIterator(Iterator* pFit) const; 00910 00911 /** Implementation of union */ 00912 void FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const; 00913 00914 /** Implementation of difference */ 00915 void FnctDifference(const TBaseSet& rOtherSet, TBaseSet& rRes) const; 00916 00917 /** Implementation of intersection */ 00918 void FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const; 00919 00920 /** TypeDefinition cache (should use guarded pointer here) */ 00921 /** 00922 * Note: - we should use guarded pointers here 00923 * - only registered types are caches 00924 */ 00925 const TypeDefinition* pTypeDefinition; 00926 00927 /** Reimplment from type type to use chache */ 00928 virtual const TypeDefinition* TypeDefinitionp(void) const; 00929 00930 /** Reimplment from faudes type to use chache */ 00931 virtual const std::string& TypeName(void) const; 00932 00933 /** Name of elements (used for XML IO) */ 00934 virtual const std::string& XElementTag(void) const; 00935 00936 }; 00937 00938 00939 00940 /* 00941 * Set union, rti wrapper 00942 * 00943 * @param rSetA 00944 * Set A 00945 * @param rSetB 00946 * Set B 00947 * @return 00948 * Union of set A and set B 00949 */ 00950 00951 template<class T, class Cmp> 00952 void SetUnion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) { 00953 FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): res at " << &rRes); 00954 // fix name 00955 std::string name=CollapsString(rSetA.Name() + "+" + rSetB.Name()); 00956 // all the same 00957 if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;} 00958 // a and b ths same, res different 00959 if(&rSetA==&rSetB) {rRes.Assign(rSetA); rRes.Name(name); return;} 00960 // a and res the same, b different 00961 if(&rSetA==&rRes) {rRes.InsertSet(rSetB); rRes.Name(name); return;}; 00962 // b and res the same, a different 00963 if(&rSetB==&rRes) {rRes.InsertSet(rSetA); rRes.Name(name); return;}; 00964 // else 00965 rRes.Assign(rSetA); 00966 rRes.InsertSet(rSetB); 00967 rRes.Name(name); 00968 FD_DC("FAUDES_DEBUG_CONTAINER: SetUnion(TBaseSet<T,Cmp>): done, res at " << &rRes << " #" << rRes.Size()); 00969 } 00970 00971 /* 00972 * Set intersection, rti wrapper 00973 * 00974 * @param rSetA 00975 * Set A 00976 * @param rSetB 00977 * Set B 00978 * @return 00979 * Set A intersected with set B 00980 */ 00981 template< class T, class Cmp > 00982 void SetIntersection(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) { 00983 // fix name 00984 std::string name=CollapsString(rSetA.Name() + "*" + rSetB.Name()); 00985 // all the same 00986 if(&rSetA==&rSetB && &rSetA==&rRes) {rRes.Name(name); return;} 00987 // a and b ths ame, res different 00988 if(&rSetA==&rSetB) { rRes.Assign(rSetA); rRes.Name(name); return;} 00989 // a and res the same, b different 00990 if(&rSetA==&rRes) {rRes.RestrictSet(rSetB); rRes.Name(name); return;}; 00991 // b and res the same, a different 00992 if(&rSetB==&rRes) {rRes.RestrictSet(rSetA); rRes.Name(name); return;}; 00993 // else 00994 rRes.Assign(rSetA); 00995 rRes.RestrictSet(rSetB); 00996 rRes.Name(name); 00997 } 00998 00999 01000 /* 01001 * Set difference, rti wrapper 01002 * 01003 * @param rSetA 01004 * Set A 01005 * @param rSetB 01006 * Set B 01007 * @return 01008 * Set A minus set B 01009 */ 01010 template< class T, class Cmp > 01011 void SetDifference(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB, TBaseSet<T,Cmp>& rRes) { 01012 // fix name 01013 std::string name=CollapsString(rSetA.Name() + "-" + rSetB.Name()); 01014 // a and b the same 01015 if(&rSetA==&rSetB) { rRes.Clear(); rRes.Name(name); return;} 01016 // a and res the same, b different 01017 if(&rSetA==&rRes) {rRes.EraseSet(rSetB); rRes.Name(name); return;}; 01018 // b and res the same, a different ... need buffer? 01019 if(&rSetB==&rRes) { 01020 TBaseSet<T,Cmp>* buffb=rSetB.Copy(); 01021 rRes.Assign(rSetA); 01022 rRes.EraseSet(*buffb); 01023 rRes.Name(name); 01024 delete buffb; 01025 return; 01026 }; 01027 // else: std 01028 rRes.Assign(rSetA); 01029 rRes.EraseSet(rSetB); 01030 rRes.Name(name); 01031 } 01032 01033 /* 01034 * Set equality, rti wrapper 01035 * This method ignores attributes. 01036 * 01037 * @param rSetA 01038 * Set A 01039 * @param rSetB 01040 * Set B 01041 * @return 01042 * True for matching sets. 01043 */ 01044 template< class T, class Cmp > 01045 bool SetEquality(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) { 01046 return rSetA==rSetB; 01047 } 01048 01049 /* 01050 * Set inclusion, rti wrapper 01051 * This method ignores attributes. 01052 * 01053 * @param rSetA 01054 * Set A 01055 * @param rSetB 01056 * Set B 01057 * @return 01058 * True for matching sets. 01059 */ 01060 template< class T, class Cmp > 01061 bool SetInclusion(const TBaseSet<T,Cmp>& rSetA, const TBaseSet<T,Cmp>& rSetB) { 01062 return rSetA<=rSetB; 01063 } 01064 01065 01066 01067 01068 /** @} doxygen group */ 01069 01070 01071 01072 /* 01073 ****************************************************************************************** 01074 ****************************************************************************************** 01075 ****************************************************************************************** 01076 01077 Implementation of TBaseSet 01078 01079 ****************************************************************************************** 01080 ****************************************************************************************** 01081 ****************************************************************************************** 01082 */ 01083 01084 /* convenience access to relevant scopes */ 01085 #define THIS TBaseSet<T,Cmp> 01086 #define TEMP template<class T, class Cmp> 01087 #define BASE Type 01088 01089 01090 // faudes type std: new and cast 01091 FAUDES_TYPE_TIMPLEMENTATION_NEW(Void,THIS,Type,TEMP) 01092 FAUDES_TYPE_TIMPLEMENTATION_COPY(Void,THIS,Type,TEMP) 01093 FAUDES_TYPE_TIMPLEMENTATION_CAST(Void,THIS,Type,TEMP) 01094 01095 // faudes type std: assignemnt (break cast) 01096 //TEMP THIS& THIS::Assign(const Type& rSrc) { this->Clear(); return *this;}; 01097 //TEMP THIS& THIS::Assign(const THIS& rSrc) { DoAssign(rSrc); return *this;}; 01098 01099 // faudes type std: assignemnt (keep cast) 01100 FAUDES_TYPE_TIMPLEMENTATION_ASSIGN(Void,THIS,Type,TEMP) 01101 FAUDES_TYPE_TIMPLEMENTATION_EQUAL(Void,THIS,Type,TEMP) 01102 01103 01104 // template statics: empty set 01105 TEMP std::set<T,Cmp> THIS::mEmptySet=std::set<T,Cmp>(); 01106 TEMP std::map<T,AttributeVoid*> THIS::mEmptyAttributes=std::map<T,AttributeVoid*>(); 01107 01108 // TBaseSet() 01109 TEMP THIS::TBaseSet(void) : 01110 Type(), 01111 mpSet(NULL), 01112 mpAttributes(NULL), 01113 pSet(&mEmptySet), 01114 pAttributes(&mEmptyAttributes), 01115 pBaseSet(this), 01116 mDetached(false), 01117 mLocked(false), 01118 pTypeDefinition(NULL) 01119 { 01120 FAUDES_OBJCOUNT_INC("BaseSet"); 01121 FD_DC("TBaseSet(" << this << ")::TBaseSet()"); 01122 // other members 01123 mMyName="BaseSet"; 01124 } 01125 01126 // TBaseSet(filename) 01127 TEMP THIS::TBaseSet(const std::string& rFileName, const std::string& rLabel) : 01128 Type(), 01129 mpSet(NULL), 01130 mpAttributes(NULL), 01131 pSet(&mEmptySet), 01132 pAttributes(&mEmptyAttributes), 01133 pBaseSet(this), 01134 mDetached(false), 01135 mLocked(false), 01136 pTypeDefinition(NULL) 01137 { 01138 FAUDES_OBJCOUNT_INC("BaseSet"); 01139 FD_DC("TBaseSet(" << this << ")::TBaseSet()"); 01140 // other members 01141 mMyName="BaseSet"; 01142 // do read etc ... this is a dummy anyway 01143 Read(rFileName,rLabel); 01144 } 01145 01146 // TBaseSet(rOtherSet) 01147 TEMP THIS::TBaseSet(const TBaseSet& rOtherSet) : 01148 Type(rOtherSet), 01149 mpSet(NULL), 01150 mpAttributes(NULL), 01151 pSet(NULL), 01152 pAttributes(NULL), 01153 pBaseSet(this), 01154 mDetached(false), 01155 mLocked(false), 01156 pTypeDefinition(NULL) 01157 { 01158 FAUDES_OBJCOUNT_INC("BaseSet"); 01159 FD_DC("TBaseSet(" << this << ")::TBaseSet(rOtherSet " << &rOtherSet << "): fake copy construct"); 01160 // maintain deferred copy 01161 pBaseSet=rOtherSet.pBaseSet; 01162 pBaseSet->AttachReference(this); 01163 pSet=rOtherSet.pSet; 01164 pAttributes=&mEmptyAttributes; 01165 // other members 01166 mMyName=rOtherSet.mMyName; 01167 #ifdef FAUDES_DEBUG_CONTAINER 01168 DValid(); 01169 #endif 01170 } 01171 01172 // destructor 01173 TEMP THIS::~TBaseSet(void) { 01174 FAUDES_OBJCOUNT_DEC("BaseSet"); 01175 FD_DC("TBaseSet(" << this << ")::~TBaseSet()"); 01176 // maintain deferred copy 01177 RelinkReferences(); 01178 pBaseSet->DetachReference(this); 01179 // unlink iterators (mandatory, since referenced object will be destructed) 01180 typename std::set< Iterator* >::const_iterator iit; 01181 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01182 (**iit).Invalidate(); 01183 } 01184 // delete if we still own data 01185 if(mpSet) delete mpSet; 01186 if(mpAttributes) { 01187 for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait) 01188 delete ait->second; 01189 delete mpAttributes; 01190 } 01191 } 01192 01193 01194 // fake copy 01195 TEMP void THIS::DoAssign(const THIS& rSourceSet) { 01196 FD_DC("TBaseSet(" << this << ")::DoAssign(rOtherSet " << &rSourceSet << "): fake copy"); 01197 // bail out on selfref 01198 if(this==&rSourceSet) return; 01199 // other members 01200 mMyName=rSourceSet.mMyName; 01201 // bail out on common shared data 01202 if(pBaseSet==rSourceSet.pBaseSet) return; 01203 // become independant 01204 RelinkReferences(); 01205 pBaseSet->DetachReference(this); 01206 mReferences.clear(); 01207 // if we are locked, should do the copy ... not implemented 01208 #ifdef FAUDES_DEBUG_CONTAINER 01209 if(mLocked) { 01210 FD_DC("TBaseSet::DoAssign(): locked target will be unlocked"); 01211 } 01212 #endif 01213 // attatch myself to src 01214 pBaseSet=rSourceSet.pBaseSet; 01215 pBaseSet->AttachReference(this); 01216 pSet=rSourceSet.pSet; 01217 pAttributes=&mEmptyAttributes; 01218 // delete own old data 01219 if(mpSet) { 01220 delete mpSet; 01221 mpSet=NULL; 01222 } 01223 if(mpAttributes) { 01224 delete mpAttributes; 01225 mpAttributes=NULL; 01226 } 01227 // record state 01228 mDetached=false; 01229 mLocked=false; 01230 // fix iterators (invalidate) 01231 typename std::set< Iterator* >::iterator iit; 01232 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01233 (**iit).Invalidate(); 01234 } 01235 mIterators.clear(); 01236 #ifdef FAUDES_DEBUG_CONTAINER 01237 DValid(); 01238 #endif 01239 } 01240 01241 // Detach() 01242 TEMP void THIS::Detach(void) const { 01243 FD_DC("TBaseSet(" << this << ")::Detach(void)"); 01244 #ifdef FAUDES_DEBUG_CONTAINER 01245 DValid(); 01246 #endif 01247 01248 // nothing todo 01249 if(mDetached) return; 01250 01251 // provide fake const 01252 THIS* fake_const = const_cast< THIS* >(this); 01253 01254 // might have overseen reference detach 01255 if(pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL) { 01256 fake_const->mDetached=true; 01257 return; 01258 } 01259 01260 // stragie A: references get the copy; thus, the baseset data does 01261 // not get reallocated and we dont need to track iterators. on the 01262 // downside, fixing the references iterators may be more effort. 01263 if(mLocked==true) { 01264 01265 FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie A"); 01266 // do allocation and copy of stl set 01267 std::set<T,Cmp>* scopy = new std::set<T,Cmp>(); 01268 *scopy = *pSet; 01269 // first of my reference gets the new data and the old attributes 01270 THIS* storage = *mReferences.begin(); 01271 storage->pBaseSet=storage; 01272 storage->mpSet=scopy; 01273 storage->pSet=scopy; 01274 storage->mpAttributes=mpAttributes; 01275 storage->pAttributes=pAttributes; 01276 storage->mReferences=mReferences; 01277 storage->DetachReference(storage); 01278 // check whether new storage is detached 01279 if(storage->mReferences.empty()) 01280 storage->mDetached=true; 01281 // set other users to new storage 01282 typename std::set< THIS* >::const_iterator rit; 01283 for(rit=mReferences.begin(), ++rit ;rit!=mReferences.end(); ++rit) { 01284 (*rit)->pBaseSet=storage; 01285 (*rit)->pSet=storage->pSet; 01286 (*rit)->pAttributes=storage->pAttributes; 01287 } 01288 // fix other users iterators (incl new storage) 01289 for(rit=mReferences.begin(); rit!=mReferences.end(); ++rit) { 01290 typename std::set< Iterator* >::iterator iit; 01291 for(iit=(*rit)->mIterators.begin(); iit!=(*rit)->mIterators.end(); ++iit) { 01292 if((**iit).StlIterator()==pSet->end()) 01293 **iit=Iterator(this, scopy->end()); 01294 else 01295 **iit=Iterator(this, scopy->find(***iit)); 01296 } 01297 } 01298 // make myself own the old data and have empty attributes 01299 fake_const->mpSet=pSet; 01300 fake_const->mpAttributes=NULL; 01301 fake_const->pAttributes=&mEmptyAttributes; 01302 fake_const->mReferences.clear(); 01303 fake_const->mDetached=true; 01304 // stop tracking iterators 01305 typename std::set< Iterator* >::const_iterator iit; 01306 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01307 (**iit).Detach(); 01308 } 01309 fake_const->mIterators.clear(); 01310 01311 01312 // stragie B: this baseset gets the copy; thus, the references iterators 01313 // remain valid and dont need to be fixed; on the downside, we need to 01314 // continue to track iterators. 01315 } else { 01316 01317 01318 FD_DC("TBaseSet(" << this << ")::Detach(void): allocate and copy, strategie B"); 01319 // make someone else handle original data 01320 fake_const->RelinkReferences(); 01321 // do allocation and copy of stl set 01322 fake_const->mpSet = new std::set<T,Cmp>(); 01323 *fake_const->mpSet= *pSet; 01324 // have empty attributes 01325 fake_const->mpAttributes=NULL; 01326 fake_const->pAttributes=&mEmptyAttributes; 01327 // fix iterators 01328 typename std::set< Iterator* >::iterator iit; 01329 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01330 if((**iit).StlIterator()==pSet->end()) 01331 **iit=Iterator(this, mpSet->end()); 01332 else 01333 **iit=Iterator(this, mpSet->find(***iit)); 01334 } 01335 // unlink from old source, link to new source 01336 pBaseSet->DetachReference(fake_const); 01337 if(pBaseSet->pBaseSet->mReferences.empty() && pBaseSet->mpSet != NULL) 01338 pBaseSet->mDetached=true; 01339 fake_const->pBaseSet=fake_const; 01340 fake_const->pSet=mpSet; 01341 fake_const->mDetached=true; 01342 } 01343 01344 #ifdef FAUDES_DEBUG_CONTAINER 01345 DValid(); 01346 #endif 01347 FD_DC("TBaseSet(" << this << ")::Detach(void): done"); 01348 } 01349 01350 // Lock() 01351 TEMP void THIS::Lock(void) const { 01352 FD_DC("TBaseSet(" << this << ")::Lock(void)"); 01353 #ifdef FAUDES_DEBUG_CONTAINER 01354 DValid(); 01355 #endif 01356 // if we are locked: fine 01357 if(mLocked) return; 01358 01359 // trigger actual copy 01360 Detach(); 01361 01362 // provide fake const 01363 THIS* fake_const = const_cast< THIS* >(this); 01364 01365 // stop tracking iterators 01366 typename std::set< Iterator* >::const_iterator iit; 01367 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01368 (**iit).Detach(); 01369 } 01370 fake_const->mIterators.clear(); 01371 01372 // stop detach from reallocating 01373 fake_const->mLocked=true; 01374 } 01375 01376 01377 // if i am a source to others, make someone else source 01378 TEMP inline void THIS::RelinkReferences(void) { 01379 FD_DC("TBaseSet::RelinkReferences(" << this << ")") 01380 #ifdef FAUDES_DEBUG_CONTAINER 01381 DValid(); 01382 #endif 01383 // no references aka this is not a source 01384 if(mReferences.empty()) return; 01385 // make first ref the new storage 01386 THIS* storage = *mReferences.begin(); 01387 #ifdef FAUDES_DEBUG_CODE 01388 if(storage->pBaseSet!=this) { 01389 FD_ERR("BaseSet::RelinkRefernces: old reference must have this as storage provider"); 01390 abort(); 01391 } 01392 #endif 01393 storage->pBaseSet=storage; 01394 storage->mpSet=mpSet; 01395 storage->pSet=pSet; 01396 storage->mpAttributes=mpAttributes; 01397 storage->pAttributes=pAttributes; 01398 storage->mReferences=mReferences; 01399 storage->DetachReference(storage); 01400 // set other users to new storage 01401 typename std::set< THIS* >::const_iterator rit; 01402 for(rit=mReferences.begin(), ++rit;rit!=mReferences.end(); ++rit) { 01403 (*rit)->pBaseSet=storage; 01404 } 01405 // make myself a reference to the new source 01406 pBaseSet=storage; 01407 pSet=storage->pSet; 01408 mpSet=NULL; 01409 pAttributes=storage->pAttributes; 01410 mpAttributes=NULL; 01411 storage->AttachReference(this); 01412 mReferences.clear(); 01413 #ifdef FAUDES_DEBUG_CONTAINER 01414 DValid(); 01415 #endif 01416 FD_DC("TBaseSet::RelinkReferences(" << this << "): done") 01417 } 01418 01419 01420 // record fake copy 01421 TEMP inline void THIS::AttachReference(TBaseSet* pRef) const { 01422 const_cast< THIS* >(this)->mReferences.insert(pRef); 01423 const_cast< THIS* >(this)->mDetached=false; 01424 } 01425 01426 // discard fake copy 01427 TEMP inline void THIS::DetachReference(TBaseSet* pRef) const { 01428 const_cast< THIS* >(this)->mReferences.erase(pRef); 01429 } 01430 01431 01432 // record an iterator 01433 TEMP inline void THIS::AttachIterator(Iterator* pFit) const { 01434 if(mLocked) return; 01435 FD_DC("TBaseSet::AttachIterator(" << this << "):" << pFit) 01436 const_cast< THIS* >(this)->mIterators.insert(pFit); 01437 } 01438 01439 // discard an iterator 01440 TEMP inline void THIS::DetachIterator(Iterator* pFit) const { 01441 if(mLocked) return; 01442 FD_DC("TBaseSet::DetachIterator(" << this << "):" << pFit) 01443 const_cast< THIS* >(this)->mIterators.erase(pFit); 01444 } 01445 01446 // test some validity 01447 TEMP void THIS::DValid(const std::string& rMessage) const { 01448 typename std::set< Iterator* >::const_iterator iit; 01449 #ifdef FAUDES_DEBUG_CONTAINER 01450 std::cerr << "TBaseSet(" << this << "):DValid() " << rMessage << " source " 01451 << pBaseSet << " " << (pBaseSet->pSet==&mEmptySet ? "+e+" : "+f+") << 01452 (mLocked ? " +l+" : " ") << (mDetached ? " +d+" : " ") << " -- refs "; 01453 typename std::set< THIS* >::const_iterator rit; 01454 for(rit=pBaseSet->mReferences.begin(); rit!=pBaseSet->mReferences.end(); ++rit) 01455 std::cerr << *rit << " "; 01456 std::cerr << "-- its "; 01457 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) 01458 std::cerr << *iit << " "; 01459 std::cerr << "-- attr #" << pAttributes->size(); 01460 if(mpAttributes) std::cerr << "(" << mpAttributes->size() << ") "; 01461 std::cerr << (pAttributes==&mEmptyAttributes ? "+e+" : "+f+") << std::endl; 01462 #endif 01463 // iterators, that dont refer to me as basset 01464 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01465 if((*iit)->pBaseSet!=this) { 01466 FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (baseset): "<< *iit); 01467 abort(); 01468 } 01469 } 01470 // iterators, that are not marked as attached 01471 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01472 if(!(*iit)->mAttached) { 01473 FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (attached): "<< *iit); 01474 abort(); 01475 } 01476 } 01477 // iterators, that are invalid stl iterators 01478 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01479 typename std::set<T,Cmp>::const_iterator vit; 01480 for(vit=pSet->begin(); vit!= pSet->end(); ++vit) { 01481 if(vit==(**iit).StlIterator()) break; 01482 } 01483 if(vit!=(**iit).StlIterator()) { // end-iterator is fine, too 01484 FD_ERR("BaseSet("<< this << "," << rMessage <<"): invalid iterator (stl "<< *iit); 01485 (**iit).StlIterator(pSet->end()); // fix invalid iterator to refer to end() 01486 } 01487 } 01488 // must have some base 01489 if(pBaseSet==NULL) { 01490 FD_ERR("BaseSet(" << this << "," << rMessage << "): no base found"); 01491 abort(); 01492 } 01493 // base must provide data either way 01494 if(pBaseSet->pBaseSet != pBaseSet) { 01495 FD_ERR("BaseSet(" << this << "," << rMessage << "): no source found"); 01496 abort(); 01497 } 01498 // refers to other base and own data 01499 if((mpSet!=NULL) && (pBaseSet != this)) { 01500 FD_ERR("BaseSet(" << this << "," << rMessage << "): double data"); 01501 abort(); 01502 } 01503 // refers to other base and has references 01504 if(pBaseSet!=this && !mReferences.empty()) { 01505 FD_ERR("BaseSet(" << this << "," << rMessage << "): cannot have source and refs"); 01506 abort(); 01507 } 01508 // is base but has no own data 01509 if((pBaseSet == this) && (mpSet==NULL) && (pSet!=&mEmptySet)) { 01510 FD_ERR("BaseSet(" << this << "," << rMessage << "): no data"); 01511 abort(); 01512 } 01513 // is base but own data pointer mismatch 01514 if((pBaseSet == this) && (pSet != mpSet) && (pSet!=&mEmptySet)) { 01515 FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch A"); 01516 abort(); 01517 } 01518 // refers to base with data pointer mismatch 01519 if((pBaseSet != this) && (pSet != pBaseSet->pSet)) { 01520 FD_ERR("BaseSet(" << this << "," << rMessage << "): data pointer mismatch B"); 01521 abort(); 01522 } 01523 // error in detached flag 01524 if(mDetached && !pBaseSet->mReferences.empty()) { 01525 FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid detached flag"); 01526 abort(); 01527 } 01528 // error in detached flag 01529 if(mDetached && (pSet==&mEmptySet)) { 01530 FD_ERR("BaseSet(" << this << "," << rMessage << "): detached empty set"); 01531 abort(); 01532 } 01533 // error in lock flag 01534 if(pBaseSet!=this && mLocked) { 01535 FD_ERR("BaseSet(" << this << "," << rMessage << "): locked reference"); 01536 abort(); 01537 } 01538 // invalid emptyset 01539 if(!mEmptySet.empty()) { 01540 FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty set"); 01541 abort(); 01542 } 01543 // invalid emptyset 01544 if(!mEmptyAttributes.empty()) { 01545 FD_ERR("BaseSet(" << this << "," << rMessage << "): invalid empty attributes"); 01546 abort(); 01547 } 01548 } 01549 01550 01551 01552 // Name 01553 TEMP const std::string& THIS::Name(void) const { 01554 return mMyName; 01555 } 01556 01557 // Name 01558 TEMP void THIS::Name(const std::string& rName) { 01559 mMyName = rName; 01560 } 01561 01562 01563 // TypeDefinitionp() 01564 // Note: fake const construct 01565 TEMP const TypeDefinition* THIS::TypeDefinitionp(void) const { 01566 if(!pTypeDefinition) { 01567 // provide fake const 01568 THIS* fake_const = const_cast< THIS* >(this); 01569 fake_const->pTypeDefinition=TypeRegistry::G()->Definitionp(*this); 01570 } 01571 return pTypeDefinition; 01572 } 01573 01574 // TypeName 01575 TEMP const std::string& THIS::TypeName(void) const { 01576 const TypeDefinition* fdp=TypeDefinitionp(); 01577 if(!fdp) return msStringEmpty; 01578 return fdp->Name(); 01579 } 01580 01581 // ElementTag 01582 TEMP const std::string& THIS::XElementTag(void) const { 01583 const static std::string etstr("Element"); 01584 const TypeDefinition* fdp=TypeDefinitionp(); 01585 if(!fdp) return etstr; 01586 return fdp->XElementTag(); 01587 } 01588 01589 01590 // Str 01591 TEMP std::string THIS::Str(const T& rElem) const { 01592 (void) rElem; 01593 std::string res=""; 01594 return res; 01595 } 01596 01597 // Size() 01598 TEMP Idx THIS::Size(void) const { 01599 return (Idx) pSet->size(); 01600 } 01601 01602 // Empty() 01603 TEMP bool THIS::Empty(void) const { 01604 return pSet->empty(); 01605 } 01606 01607 01608 // DoWrite(tw,rLabel,cpntext) 01609 TEMP void THIS::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const { 01610 (void) pContext; 01611 std::string label=rLabel; 01612 if(label=="") label=Name(); 01613 if(label=="") label="BaseSet"; 01614 FD_DC("TBaseSet(" << this << ")::DoWrite(..): section " << label << " #" << Size()); 01615 rTw.WriteBegin(label); 01616 rTw.WriteEnd(label); 01617 } 01618 01619 01620 // DoDWrite(tw, label, context) 01621 TEMP void THIS::DoDWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const { 01622 (void) pContext; 01623 (void) rLabel; 01624 rTw.WriteComment(""); 01625 rTw.WriteComment(" Size/Attributes: " + ToStringInteger(pSet->size()) 01626 + "/" + ToStringInteger(pBaseSet->pAttributes->size())); 01627 rTw.WriteComment(" Shares/Iterators: " + ToStringInteger(pBaseSet->mReferences.size()) 01628 + "/" + ToStringInteger(mIterators.size())); 01629 rTw.WriteComment(""); 01630 #ifdef FAUDES_DEBUG_CONTAINER 01631 DValid(); 01632 #endif 01633 } 01634 01635 // DoSWrite() 01636 TEMP void THIS::DoSWrite(TokenWriter& rTw) const { 01637 BASE::DoSWrite(rTw); 01638 rTw.WriteComment(" Size: " + ToStringInteger(pSet->size())); 01639 if(!mpSet) 01640 rTw.WriteComment(" Data: shared"); 01641 else 01642 rTw.WriteComment(" Data: own"); 01643 if(pAttributes->size()!=0) 01644 rTw.WriteComment(" Attributes: " +ToStringInteger(pAttributes->size())); 01645 if(pAttributes->size()!=0) { 01646 AttributeVoid* attr = pAttributes->begin()->second; 01647 rTw.WriteComment(" Attribute Type: " +FaudesTypeName(*attr)); 01648 } 01649 } 01650 01651 // DoRead(rTr, rLabel, pContext) 01652 TEMP void THIS::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) { 01653 (void) pContext; 01654 std::string label=rLabel; 01655 if(label=="") label=Name(); 01656 if(label=="") label="BaseSet"; 01657 Name(label); 01658 rTr.ReadBegin(label); 01659 rTr.ReadEnd(label); 01660 } 01661 01662 // ThisIterator 01663 TEMP typename THIS::Iterator THIS::ThisIterator(const typename std::set<T,Cmp>::const_iterator& sit) const { 01664 return Iterator(this,sit); 01665 } 01666 01667 // Begin() const 01668 TEMP inline typename THIS::Iterator THIS::Begin(void) const { 01669 return ThisIterator(pSet->begin()); 01670 } 01671 01672 // End() const 01673 TEMP inline typename THIS::Iterator THIS::End(void) const { 01674 return ThisIterator(pSet->end()); 01675 } 01676 01677 01678 //Clear 01679 TEMP void THIS::Clear(void) { 01680 FD_DC("TBaseSet(" << this << ")::Clear()"); 01681 #ifdef FAUDES_DEBUG_CONTAINER 01682 DValid(); 01683 #endif 01684 // special case: empty anyway 01685 if(pSet==&mEmptySet) return; 01686 // special case: locked requires a copy (not efficient!) 01687 if(mLocked) Detach(); 01688 // make someone else handle the data 01689 if(!mReferences.empty()) RelinkReferences(); 01690 // unlink myself from source 01691 if(pBaseSet!=this) { 01692 pBaseSet->DetachReference(this); 01693 pBaseSet=this; 01694 } 01695 // if we hold data, clear it 01696 if(mpSet) { 01697 delete mpSet; 01698 mpSet=NULL; 01699 } 01700 // if we hold data, clear it 01701 if(mpAttributes) { 01702 for(aiterator ait=mpAttributes->begin(); ait!=mpAttributes->end(); ++ait) 01703 delete ait->second; 01704 delete mpAttributes; 01705 mpAttributes=NULL; 01706 } 01707 // set to empty set 01708 pSet=&mEmptySet; 01709 pAttributes=&mEmptyAttributes; 01710 // fix iterators (invalidate) 01711 typename std::set< Iterator* >::iterator iit; 01712 for(iit=mIterators.begin(); iit!=mIterators.end(); ++iit) { 01713 (**iit).Invalidate(); 01714 } 01715 mIterators.clear(); 01716 mDetached=false; 01717 #ifdef FAUDES_DEBUG_CONTAINER 01718 DValid(); 01719 #endif 01720 } 01721 01722 01723 //Valid(elem) 01724 TEMP inline bool THIS::Valid(const T& rElem) const { 01725 (void) rElem; 01726 return true; 01727 } 01728 01729 //Insert(elem) 01730 TEMP bool THIS::Insert(const T& rElem) { 01731 #ifdef FAUDES_CHECKED 01732 if(!Valid(rElem)) { 01733 std::stringstream errstr; 01734 errstr << "cannot insert invalid element" << std::endl; 01735 throw Exception("BaseSet::Insert", errstr.str(), 61); 01736 } 01737 #endif 01738 if(!mDetached) Detach(); 01739 return pSet->insert(rElem).second; 01740 } 01741 01742 // InsertSet(set) 01743 TEMP void THIS::InsertSet(const TBaseSet& rOtherSet) { 01744 FD_DC("TBaseSet(" << this << ")::InsertSet(" << &rOtherSet << ")"); 01745 if(!mDetached) Detach(); 01746 /* 01747 rem: cannot use stl since result overlaps with arguments 01748 01749 std::insert_iterator< std::set<T,Cmp> > insit(*pSet, rpSet->begin()); 01750 std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit); 01751 */ 01752 iterator it1 = pSet->begin(); 01753 iterator it2 = rOtherSet.pSet->begin(); 01754 while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) { 01755 if (*it1 < *it2) { 01756 ++it1; 01757 } 01758 else if (*it1 == *it2) { 01759 ++it1; 01760 ++it2; 01761 } 01762 else { // (*it1 > *it2) 01763 pSet->insert(*it2); 01764 ++it2; 01765 } 01766 } 01767 while (it2 != rOtherSet.pSet->end()) { 01768 pSet->insert(*it2); 01769 ++it2; 01770 } 01771 } 01772 01773 01774 //Erase(rElem) 01775 TEMP bool THIS::Erase(const T& rElem) { 01776 if(!mDetached) Detach(); 01777 return (pSet->erase(rElem)!=0); 01778 } 01779 01780 01781 //Erase(pos) 01782 TEMP typename THIS::Iterator THIS::Erase(const Iterator& pos) { 01783 #ifdef FAUDES_CHECKED 01784 if (pos == End()) { 01785 std::stringstream errstr; 01786 errstr << "iterator out of range " << std::endl; 01787 throw Exception("BaseSet::Erase", errstr.str(), 62); 01788 } 01789 #endif 01790 Detach(); 01791 iterator del= pos.StlIterator(); 01792 iterator res= del; 01793 res++; 01794 pSet->erase(del); 01795 return ThisIterator(res); 01796 } 01797 01798 01799 //EraseSet(set) 01800 TEMP void THIS::EraseSet(const TBaseSet& rOtherSet) { 01801 FD_DC("TBaseSet(" << this << ")::EraseSet(" << &rOtherSet << ")"); 01802 if(!mDetached) Detach(); 01803 // TODO: test and optimize 01804 iterator tmpit; 01805 iterator it = pSet->begin(); 01806 iterator oit = rOtherSet.pSet->begin(); 01807 while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) { 01808 if (*it < *oit) { 01809 it=pSet->lower_bound(*oit); // alt: ++it; 01810 } 01811 else if (*it == *oit) { 01812 tmpit=it; 01813 ++it; 01814 ++oit; 01815 pSet->erase(tmpit); 01816 } 01817 else { // (*it > *oit) 01818 oit=rOtherSet.pSet->lower_bound(*it); // ++it2; 01819 } 01820 } 01821 } 01822 01823 01824 //RestrictSet(set) 01825 TEMP void THIS::RestrictSet(const TBaseSet& rOtherSet) { 01826 FD_DC("TBaseSet(" << this << ")::RestrictSet(" << &rOtherSet << ")"); 01827 if(!mDetached) Detach(); 01828 // TODO: test and optimize 01829 iterator tmpit; 01830 iterator it = pSet->begin(); 01831 iterator oit = rOtherSet.pSet->begin(); 01832 while ((it != pSet->end()) && (oit != rOtherSet.pSet->end())) { 01833 if (*it < *oit) { 01834 tmpit=it; 01835 ++it; 01836 pSet->erase(tmpit); 01837 } 01838 else if (*it == *oit) { 01839 ++it; 01840 ++oit; 01841 } 01842 else { // (*it > *oit) 01843 oit=rOtherSet.pSet->lower_bound(*it); 01844 } 01845 } 01846 while(it != pSet->end()) { 01847 tmpit=it; 01848 ++it; 01849 pSet->erase(tmpit); 01850 } 01851 } 01852 01853 01854 //Find(elem) 01855 TEMP typename THIS::Iterator THIS::Find(const T& rElem) const { 01856 return ThisIterator(pSet->find(rElem)); 01857 } 01858 01859 //Exists(elem) 01860 TEMP bool THIS::Exists(const T& rElem) const { 01861 return pSet->find(rElem) != pSet->end(); 01862 } 01863 01864 01865 // SetUnion(set) 01866 TEMP void THIS::SetUnion(const TBaseSet& rOtherSet) { 01867 if(!mDetached) Detach(); 01868 iterator it1 = pSet->begin(); 01869 iterator it2 = rOtherSet.pSet->begin(); 01870 while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) { 01871 if (*it1 < *it2) { 01872 ++it1; 01873 continue; 01874 } 01875 if (*it1 == *it2) { 01876 ++it1; 01877 ++it2; 01878 continue; 01879 } 01880 // (*it1 > *it2) 01881 pSet->insert(it1,*it2); 01882 ++it2; 01883 } 01884 while (it2 != rOtherSet.pSet->end()) { 01885 pSet->insert(pSet->end(),*it2); 01886 ++it2; 01887 } 01888 } 01889 01890 // SetIntersection(set) 01891 TEMP void THIS::SetIntersection(const TBaseSet& rOtherSet) { 01892 if(!mDetached) Detach(); 01893 iterator tmpit; 01894 iterator it1 = pSet->begin(); 01895 iterator it2 = rOtherSet.pSet->begin(); 01896 while ((it1 != pSet->end()) && (it2 != rOtherSet.pSet->end())) { 01897 if (*it1 < *it2) { 01898 tmpit=it1; 01899 ++it1; 01900 pSet->erase(tmpit); 01901 continue; 01902 } 01903 if (*it1 == *it2) { 01904 ++it1; 01905 ++it2; 01906 continue; 01907 } 01908 // if (*it1 > *it2) 01909 ++it2; 01910 } 01911 while(it1 != pSet->end()) { 01912 tmpit=it1; 01913 ++it1; 01914 pSet->erase(tmpit); 01915 } 01916 } 01917 01918 01919 // FnctUnion 01920 TEMP void THIS::FnctUnion(const TBaseSet& rOtherSet, TBaseSet& rRes) const { 01921 FD_DC("TBaseSet(" << this << ")::FnctUnion (" << &rOtherSet << ")"); 01922 rRes.Detach(); 01923 std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin()); 01924 std::set_union(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit); 01925 rRes.Name(CollapsString(Name() + "+" + rOtherSet.Name())); 01926 } 01927 01928 // FnctDifference 01929 TEMP void THIS::FnctDifference (const TBaseSet& rOtherSet, TBaseSet& rRes) const { 01930 FD_DC("TBaseSet(" << this << ")::FnctDifference (" << &rOtherSet << ")"); 01931 rRes.Detach(); 01932 std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin()); 01933 std::set_difference(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit); 01934 rRes.Name(CollapsString(Name() + "-" + rOtherSet.Name())); 01935 } 01936 01937 01938 // FnctIntersection 01939 TEMP void THIS::FnctIntersection(const TBaseSet& rOtherSet, TBaseSet& rRes) const { 01940 FD_DC("TBaseSet(" << this << ")::FnctIntersection (" << &rOtherSet << ")"); 01941 rRes.Detach(); 01942 std::insert_iterator< std::set<T,Cmp> > insit(*rRes.pSet, rRes.pSet->begin()); 01943 std::set_intersection(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end(), insit); 01944 rRes.Name(CollapsString(Name() + "*" + rOtherSet.Name())); 01945 } 01946 01947 // operator+ 01948 TEMP THIS THIS::operator+ (const TBaseSet& rOtherSet) const { 01949 TBaseSet res; 01950 FnctUnion(rOtherSet,res); 01951 return res; 01952 } 01953 01954 // operator- 01955 TEMP THIS THIS::operator- (const TBaseSet& rOtherSet) const { 01956 TBaseSet res; 01957 FnctDifference(rOtherSet,res); 01958 return res; 01959 } 01960 01961 01962 // operator* 01963 TEMP THIS THIS::operator* (const TBaseSet& rOtherSet) const { 01964 TBaseSet res; 01965 FnctIntersection(rOtherSet,res); 01966 return res; 01967 } 01968 01969 01970 // operator== 01971 TEMP bool THIS::DoEqual(const TBaseSet& rOtherSet) const { 01972 FD_DC("TBaseSet::DoEqual()"); 01973 // true if we share anyway 01974 if(pSet == rOtherSet.pSet) return true; 01975 // compare sets 01976 return ( *pSet == *rOtherSet.pSet ); 01977 } 01978 01979 // operator<= 01980 TEMP bool THIS::operator<= (const TBaseSet& rOtherSet) const { 01981 FD_DC("BaseSet::op<=()"); 01982 return ( std::includes(rOtherSet.pSet->begin(), rOtherSet.pSet->end(), pSet->begin(), pSet->end()) ) ; 01983 } 01984 01985 // operator>= 01986 TEMP bool THIS::operator>= (const TBaseSet& rOtherSet) const { 01987 FD_DC("BaseSet::op>=()"); 01988 return ( std::includes(pSet->begin(), pSet->end(), rOtherSet.pSet->begin(), rOtherSet.pSet->end()) ); 01989 } 01990 01991 // operator< 01992 TEMP bool THIS::operator< (const TBaseSet& rOtherSet) const { 01993 return *pSet < *rOtherSet.pSet; 01994 } 01995 01996 01997 // attribute typeinfo 01998 TEMP const AttributeVoid* THIS::Attributep(void) const { 01999 static AttributeVoid attr; 02000 return & attr; 02001 } 02002 02003 // attribute typeinfo 02004 TEMP const AttributeVoid& THIS::Attribute(void) const { 02005 static AttributeVoid attr; 02006 return attr; 02007 } 02008 02009 // attribute access 02010 TEMP AttributeVoid* THIS::Attributep(const T& rElem) { 02011 (void) rElem; 02012 std::stringstream errstr; 02013 errstr << "cannot get attribute for TBaseSet \"" << mMyName << "\" type " << typeid(*this).name(); 02014 throw Exception("TBaseSet::Attributep(rElem)", errstr.str(), 63); 02015 static AttributeVoid attr; 02016 return &attr; 02017 } 02018 02019 // attribute access 02020 TEMP const AttributeVoid& THIS::Attribute(const T& rElem) const { 02021 (void) rElem; 02022 static AttributeVoid attr; 02023 return attr; 02024 } 02025 02026 // attribute access 02027 TEMP void THIS::Attribute(const T& rElem, const Type& rAttr) { 02028 (void) rElem; 02029 /* its pointless to test existence of the element since we wont set any attribute anyway 02030 #ifdef FAUDES_CHECKED 02031 if (!Exists(rElem)) { 02032 std::stringstream errstr; 02033 errstr << "element not member of set" << std::endl; 02034 throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 60); 02035 } 02036 #endif 02037 */ 02038 if(!AttributeTry(rAttr)) { 02039 std::stringstream errstr; 02040 errstr << "cannot cast attribute " << std::endl; 02041 throw Exception("TBaseSet::Attribute(elem,attr)", errstr.str(), 63); 02042 } 02043 /* alternative approach: 02044 // silently ignore any value 02045 // set to void is ok for silient ignore 02046 if(typeid(rAttr)==typeid(const AttributeVoid&)) return; 02047 // set to nontrivial attribute: exception 02048 std::stringstream errstr; 02049 errstr << "cannot set attribute type " << typeid(rAttr).name() << " for TBaseSet \"" << mMyName 02050 << "\" type " << typeid(*this).name(); 02051 throw Exception("TBaseSet::Attribute(rElem,rAttr)", errstr.str(), 63); 02052 */ 02053 } 02054 02055 02056 02057 /* undefine local shortcuts */ 02058 #undef THIS 02059 #undef TEMP 02060 #undef BASE 02061 02062 /** @} doxygen group */ 02063 02064 } // namespace faudes 02065 02066 #endif |
libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3