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