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