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