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