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