cfl_attrmap.h
Go to the documentation of this file.
1/** @file cfl_attrmap.h @brief Class TAttrMap */
2
3
4/* FAU Discrete Event Systems Library (libfaudes)
5
6 Copyright (C) 2008, 2016 Thomas Moor
7 Exclusive copyright is granted to Klaus Schmidt
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
21
22
23
24#ifndef FAUDES_ATTRMAP_H
25#define FAUDES_ATTRMAP_H
26
27#include "cfl_baseset.h"
28
29namespace faudes {
30
31/** @addtogroup ContainerClasses */
32/** @{*/
33
34/**
35 * Attribute interface for TBaseSet.
36 *
37 * TAttrMap provides a typed interface to access the attributes associated with
38 * elements of a TBaseSet. It is meant to faciltate classes derived from TBaseSet
39 * that use non-trivial attributes. Note that the actual attribute map is hosted by
40 * TBaseSet itself.
41 *
42 * Note: technically, the TAttrMap holds a reference to the associated TBaseSet.
43 * When deriving from a child of TBaseSet, the interface is introduced
44 * by additional inheritance of TAttrMap. Effectively, this avoids the diomand-shape
45 * inheritance we used to have in pre 2.30 versions of libFAUDES and which caused various
46 * issues with the MS Visual Studio compilers regarding covaraint return values in the
47 * context of templates.
48 */
49
50
51template<class T, class Attr, class Cmp=std::less<T> >
52class FAUDES_TAPI TAttrMap {
53
54
55public:
56
57 /**
58 * Constructor.
59 *
60 * Record associated set.
61 */
63
64 /**
65 * Virtual destructor
66 */
67 virtual ~TAttrMap(void);
68
69 /**
70 * Copy from a TBaseSet to the associated TBaseSet, with attributes,
71 * provided that they can be casted accordingly.
72 *
73 * @param rSourceSet
74 * Set to copy from
75 */
76 void AssignWithAttributes(const TBaseSet<T,Cmp>& rSourceSet);
77
78 /**
79 * Attribute typeinfo.
80 *
81 * @return
82 * Pointer to some attribute of this sets attribute type.
83 */
84 const Attr* AttributeType(void) const;
85
86
87 /**
88 * Get attribute reference by element. Note that in order to produce a non-const
89 * reference this method will insert an explicit default attribute if necessary.
90 * If a const reference is sufficient, you should use Attribute(rElem) const instead.
91 *
92 * @param rElem
93 * Specify element
94 * @exception Exception
95 * - Element does not exist (60)
96 * @return
97 * Pointer to attribute
98 */
99 Attr* Attributep(const T& rElem);
100
101 /**
102 * Get attribute by element. This function returns a const reference to the attribute
103 * of the specified element.
104 * @param rElem
105 * Specify element
106 * @exception Exception
107 * - Element does not exist (63)
108 * @return
109 * Reference to attribute
110 */
111 const Attr& Attribute(const T& rElem) const;
112
113 /**
114 * Set attribute. Provided that the attribute can be casted to the
115 * appropriate type, this method sets the attribute of the sepcified element to the given value.
116 *
117 * @param rElem
118 * Specify element
119 * @param attr
120 * Attribute value.
121 * @exception Exception
122 * - Element does not exist (60)
123 * - Cannot cast attribute type (63)
124 */
125 void Attribute(const T& rElem, const Type& attr);
126
127 /**
128 * Set attribute. This method sets the attribute of the sepcified element to the given value.
129 *
130 * @param rElem
131 * Specify element
132 * @param attr
133 * Attribute value.
134 * @exception Exception
135 * - Element does not exist (60)
136 * - Cannot cast attribute type (63)
137 */
138 void Attribute(const T& rElem, const Attr& attr);
139
140 /**
141 * Set attribute. Provided that the attribute can be casted to the
142 * appropriate type, this method sets the attribute of the sepcified element to the given value.
143 * If the cast fails, this method does nothing.
144 *
145 * @param rElem
146 * Specify element
147 * @param attr
148 * Attribute value.
149 * @exception Exception
150 * - Element does not exist (60)
151 */
152 void AttributeTry(const T& rElem, const Type& attr);
153
154 /**
155 * Insert element. If the element exists, the attribute is maintained.
156 * If the element does not exist, it is inserted with default attribute.
157 *
158 * @param rElem
159 * Specify element
160 * @return
161 * True if element was new to set
162 */
163 bool Insert(const T& rElem);
164
165 /**
166 * Insert element with attribute.
167 *
168 * @param rElem
169 * Specify element
170 * @param attr
171 * Specify attribute of (new) element
172 * @return
173 * True if element was new to set
174 */
175 bool Insert(const T& rElem, const Attr& attr);
176
177 /**
178 * Inserts elements from rOtherSet.
179 *
180 * Attributes of this set are maintained, newly inserted elements receive attributes
181 * from rOtherSet, provided that can be casted appropriately.
182 *
183 *
184 * @param rOtherSet
185 * Other BaseSet
186 */
187 void InsertSet(const TBaseSet<T,Cmp>& rOtherSet);
188
189
190 /**
191 * Erase Element (incl its attribute)
192 *
193 * @param rElem
194 * Specify element
195 * @return
196 * True if element used to exist
197 */
198 bool Erase(const T& rElem);
199
200 /**
201 * Erase element by iterator (incl attribute)
202 *
203 * @param pos
204 * Iterator to specify element
205 * @return
206 * Iterator to next element or End()
207 */
208 // opt: use declare&define for cl_win issues
210
211
212 /**
213 * Erase elements given by other set. This function
214 * ignores the attributes of the other set and maintains the attributes
215 * of the remaining elements in this set.
216 *
217 * @param rOtherSet
218 * Elements to erase
219 */
220 void EraseSet(const TBaseSet<T,Cmp>& rOtherSet);
221
222 /**
223 * Restrict to specified subset. Erases any elements not in
224 * the specified set. This function
225 * ignores the attributes of the other set and maintains the attributes
226 * of the remaining elements in this set.
227 *
228 * @param rOtherSet
229 * Elements to erase
230 */
231 void RestrictSet(const TBaseSet<T,Cmp>& rOtherSet);
232
233
234
235protected:
236
237 /** use TBaseSet STL iterators */
239
240 /** use TBaseSet STL iterators */
242
243 /** use TBaseSet STL iterators */
245
246 /** use TBaseSet STL iterators */
248
249 /** reference to associated TBaseSet */
251
252};
253
254
255
256/** @} doxygen group */
257
258
259
260/*
261******************************************************************************************
262******************************************************************************************
263******************************************************************************************
264
265Implementation of TAttrMap
266
267******************************************************************************************
268******************************************************************************************
269******************************************************************************************
270*/
271
272/* convenience access to relevant scopes */
273#define THIS TAttrMap<T,Attr,Cmp>
274#define TEMP template<class T, class Attr, class Cmp>
275
276// TAttrMap()
277TEMP THIS::TAttrMap(TBaseSet<T,Cmp>* pBaseSetRef) :
278 pBaseSet(pBaseSetRef)
279{
280 FD_DC("TAttrMap(" << this << ")::TAttrMap(): set at " << pBaseSet);
281}
282
283
284// destructor
285TEMP THIS::~TAttrMap(void) {
286 FD_DC("TAttrMap(" << this << ")::~TAttrMap()");
287}
288
289
290
291// assign, try attributes
292TEMP void THIS::AssignWithAttributes(const TBaseSet<T,Cmp>& rSourceSet) {
293 FD_DC("TAttrMap(" << pBaseSet << ")::Assign(..): dst map type " << typeid(*this).name());
294 FD_DC("TAttrMap(" << pBaseSet << ")::Assign(..): src type " << typeid(rSourceSet).name());
295 // call base (fake copy, this will incl attributes on exact type match or ref to empty attributes else)
296 pBaseSet->DoAssign(rSourceSet);
297 // sense the exact match and bail out
298 if(pBaseSet->AttributesSize()==rSourceSet.AttributesSize()) return;
299 // if we have void attributes, we can not cast
300 FD_DC("TAttrMap(" << this << ")::Assign(..): dst attribute type " << typeid(*AttributeType()).name());
301 if( typeid(*AttributeType()) == typeid(const AttributeVoid) ) return;
302 // if source has void attributes, we can not cast
303 FD_DC("TAttrMap(" << this << ")::Assign(..): src attribute type " << typeid(*rSourceSet.AttributeType()).name());
304 if( typeid(*rSourceSet.AttributeType()) == typeid(const AttributeVoid) ) return;
305 // ifattributes cannot be casted, we dont need to loop either
306 FD_DC("TAttrMap(" << this << ")::Assign(..): try attribute cast");
307 if(!AttributeType()->Cast(rSourceSet.AttributeType())) return;
308 // detach, since we will write to attributes
309 pBaseSet->Detach();
310 FD_DC("TAttrMap(" << this << ")::Assign(..): mind attributes");
311 const_aiterator ait=rSourceSet.pAttributes->begin();
312 for(;ait!=rSourceSet.pAttributes->end(); ++ait) {
313 Attr* attr= new Attr;
314 attr->Assign(*ait->second);
315 (*pBaseSet->pAttributes)[ait->first]=attr;
316 }
317 // done
318 FD_DC("TAttrMap(" << pBaseSet << ")::Assign(..): done");
319}
320
321
322//Insert(elem)
323TEMP bool THIS::Insert(const T& rElem) {
324 FD_DC("TAttrMap(" << pBaseSet << ")::Insert(elem)");
325 pBaseSet->Detach();
326 bool ret=pBaseSet->pSet->insert(rElem).second;
327 return ret;
328}
329
330//Insert(idx,attr)
331TEMP bool THIS::Insert(const T& rElem, const Attr& rAttr) {
332 FD_DC("TAttrMap(" << pBaseSet << ")::Insert(elem,attr)");
333 pBaseSet->Detach();
334 bool ret=pBaseSet->pSet->insert(rElem).second;
335 pBaseSet->DoAttribute(rElem,&rAttr);
336 return ret;
337}
338
339// InsertSet(set)
340TEMP void THIS::InsertSet(const TBaseSet<T,Cmp>& rOtherSet) {
341 bool doattr=pBaseSet->AttributeTest(*rOtherSet.AttributeType());
342 FD_DC("TAttrMap(" << pBaseSet << ")::InsertSet( [v] " << &rOtherSet << "): doattr=" << doattr);
343 pBaseSet->Detach();
344 iterator it1 = pBaseSet->pSet->begin();
345 iterator it2 = rOtherSet.pSet->begin();
346 while ((it1 != pBaseSet->pSet->end()) && (it2 != rOtherSet.pSet->end())) {
347 if (*it1 < *it2) {
348 ++it1;
349 }
350 else if (*it1 == *it2) {
351 ++it1;
352 ++it2;
353 }
354 else { // (*it1 > *it2)
355 pBaseSet->pSet->insert(*it2);
356 if(doattr) pBaseSet->DoAttribute(*it2,&rOtherSet.Attribute(*it2));
357 ++it2;
358 }
359 }
360 while(it2 != rOtherSet.pSet->end()) {
361 pBaseSet->pSet->insert(*it2);
362 if(doattr) pBaseSet->DoAttribute(*it2,&rOtherSet.Attribute(*it2));
363 ++it2;
364 }
365 FD_DC("TAttrMap(" << pBaseSet << ")::InsertSet( [v] " << &rOtherSet << "): done");
366}
367
368//Erase(idx)
369TEMP bool THIS::Erase(const T& rElem) {
370 pBaseSet->Detach();
371 pBaseSet->DoAttribute(rElem,(const AttributeVoid*) 0);
372 return (pBaseSet->pSet->erase(rElem)!=0);
373}
374
375//Erase(it)
376TEMP typename TBaseSet<T,Cmp>::Iterator THIS::Erase(const typename TBaseSet<T,Cmp>::Iterator& pos) {
377 pBaseSet->Detach();
378 iterator del= pos.StlIterator();
379 pBaseSet->DoAttribute(*pos,(const AttributeVoid*) 0);
380 pBaseSet->pSet->erase(del++);
381 return pBaseSet->ThisIterator(del);
382}
383
384
385//EraseSet(set)
386TEMP void THIS::EraseSet(const TBaseSet<T,Cmp>& rOtherSet) {
387 FD_DC("TAttrMap(" << pBaseSet << ")::EraseSet(" << &rOtherSet << ")");
388 pBaseSet->Detach();
389 // todo: test and optimize
390 iterator it = pBaseSet->pSet->begin();
391 iterator oit = rOtherSet.pSet->begin();
392 while ((it != pBaseSet->pSet->end()) && (oit != rOtherSet.pSet->end())) {
393 if (*it < *oit) {
394 it=pBaseSet->pSet->lower_bound(*oit); // alt: ++it;
395 }
396 else if (*it == *oit) {
397 pBaseSet->DoAttribute(*it,(const AttributeVoid*) 0);
398 ++oit;
399 pBaseSet->pSet->erase(it++);
400 }
401 else { // (*it > *oit)
402 oit=rOtherSet.pSet->lower_bound(*it); // ++it2;
403 }
404 }
405}
406
407
408//RestrictSet(set)
409TEMP void THIS::RestrictSet(const TBaseSet<T,Cmp>& rOtherSet) {
410 FD_DC("TAttrMap(" << pBaseSet << ")::RestrictSet(" << &rOtherSet << ")");
411 pBaseSet->Detach();
412 // todo: test and optimize
413 iterator it = pBaseSet->pSet->begin();
414 iterator oit = rOtherSet.pSet->begin();
415 while ((it != pBaseSet->pSet->end()) && (oit != rOtherSet.pSet->end())) {
416 if (*it < *oit) {
417 pBaseSet->DoAttribute(*it,(const AttributeVoid*) 0);
418 pBaseSet->pSet->erase(it++);
419 }
420 else if (*it == *oit) {
421 ++it;
422 ++oit;
423 }
424 else { // (*it > *oit)
425 ++oit;
426 }
427 }
428 while(it != pBaseSet->pSet->end()) {
429 pBaseSet->DoAttribute(*it,(const AttributeVoid*) 0);
430 pBaseSet->pSet->erase(it++);
431 }
432
433}
434
435
436// attribute typeinfo
437TEMP const Attr* THIS::AttributeType(void) const {
438 static Attr attr;
439 FD_DC("TAttrMap::AttributeType(): accessing non trivial type");
440 return &attr;
441}
442
443
444// get attribute wrapper
445TEMP Attr* THIS::Attributep(const T& rElem) {
446#ifdef FAUDES_CHECKED
447 if(!pBaseSet->Exists(rElem)) {
448 std::stringstream errstr;
449 errstr << "element \"" << pBaseSet->Str(rElem) << "\" not member of set " << pBaseSet->Name() << std::endl;
450 throw Exception("TAttrMap::Attributep(elem)", errstr.str(), 60);
451 }
452#endif
453 // must detach
454 pBaseSet->Detach();
455 // find in map (incl insert explicit default)
456 Attr* attr=dynamic_cast<Attr*>(pBaseSet->DoAttributeExplicit(rElem));
457 FD_DC("TAttrMap::Attributep(): found " << attr << " type " << typeid(*attr).name() );
458 // done
459 return attr;
460}
461
462// get attribute wrapper
463TEMP const Attr& THIS::Attribute(const T& rElem) const {
464#ifdef FAUDES_CHECKED
465 if(!pBaseSet->Exists(rElem)) {
466 std::stringstream errstr;
467 errstr << "element \"" << pBaseSet->Str(rElem) << "\" not member of set " << pBaseSet->Name() << std::endl;
468 throw Exception("TAttrMap::Attribute(elem)", errstr.str(), 60);
469 }
470#endif
471 // find in map
472 const Attr* attr=dynamic_cast<const Attr*>(pBaseSet->DoAttribute(rElem));
473 // use default
474 if(!attr) attr=this->AttributeType();
475 // done
476 return *attr;
477}
478
479// set attribute wrapper
480TEMP void THIS::Attribute(const T& rElem, const Type& attr) {
481#ifdef FAUDES_CHECKED
482 if (!pBaseSet->Exists(rElem)) {
483 std::stringstream errstr;
484 errstr << "element \"" << pBaseSet->Str(rElem) << "\" not member of set " << pBaseSet->Name() << std::endl;
485 throw Exception("TAttrMap::Attribute(elem,attr [t])", errstr.str(), 60);
486 }
487#endif
488 if(!pBaseSet->AttributeTest(attr)) {
489 std::stringstream errstr;
490 errstr << "cannot cast attribute " << std::endl;
491 throw Exception("TAttrMap::Attribute(elem,attr [t])", errstr.str(), 63);
492 }
493 pBaseSet->Detach();
494 pBaseSet->DoAttribute(rElem,&attr);
495}
496
497// set attribute wrapper
498TEMP void THIS::AttributeTry(const T& rElem, const Type& attr) {
499 FD_DC("TAttrMap::Attribute(elem,attr) [t]");
500#ifdef FAUDES_CHECKED
501 if(!pBaseSet->Exists(rElem)) {
502 std::stringstream errstr;
503 errstr << "element \"" << pBaseSet->Str(rElem) << "\" not member of set " << pBaseSet->Name() << std::endl;
504 throw Exception("TAttrMap::AttributeTry(elem,attr [t])", errstr.str(), 60);
505 }
506#endif
507 if(!pBaseSet->AttributeTest(attr)) return;
508 pBaseSet->Detach();
509 pBaseSet->DoAttribute(rElem,&attr);
510}
511
512// set attribute wrapper
513TEMP void THIS::Attribute(const T& rElem, const Attr& attr) {
514 FD_DC("TAttrMap::Attribute(elem,attr) [a]");
515#ifdef FAUDES_CHECKED
516 if(!pBaseSet->Exists(rElem)) {
517 pBaseSet->DWrite();
518 std::stringstream errstr;
519 errstr << "element \"" << pBaseSet->Str(rElem) << "\" not member of set " << pBaseSet->Name() << std::endl;
520 throw Exception("TAttrMap::Attribute(elem,attr [a])", errstr.str(), 60);
521 }
522#endif
523 pBaseSet->Detach();
524 pBaseSet->DoAttribute(rElem, &attr);
525}
526
527
528/* undefine local shortcuts */
529#undef THIS
530#undef TEMP
531
532
533} // namespace faudes
534
535#endif
#define TEMP
Class TBaseSet.
#define FD_DC(message)
#define FAUDES_TAPI
bool Insert(const T &rElem, const Attr &attr)
const Attr & Attribute(const T &rElem) const
Attr * Attributep(const T &rElem)
void AttributeTry(const T &rElem, const Type &attr)
bool Erase(const T &rElem)
TBaseSet< T, Cmp >::const_aiterator const_aiterator
void EraseSet(const TBaseSet< T, Cmp > &rOtherSet)
TBaseSet< T, Cmp >::Iterator Erase(const typename TBaseSet< T, Cmp >::Iterator &pos)
TBaseSet< T, Cmp >::aiterator aiterator
void Attribute(const T &rElem, const Type &attr)
void InsertSet(const TBaseSet< T, Cmp > &rOtherSet)
void RestrictSet(const TBaseSet< T, Cmp > &rOtherSet)
TAttrMap(TBaseSet< T, Cmp > *pBaseSetRef)
virtual ~TAttrMap(void)
TBaseSet< T, Cmp >::const_iterator const_iterator
void AssignWithAttributes(const TBaseSet< T, Cmp > &rSourceSet)
TBaseSet< T, Cmp > * pBaseSet
TBaseSet< T, Cmp >::iterator iterator
bool Insert(const T &rElem)
const Attr * AttributeType(void) const
void Attribute(const T &rElem, const Attr &attr)
void StlIterator(const typename std::set< T, Cmp >::const_iterator &sit)
std::set< T, Cmp >::iterator iterator
std::map< T, AttributeVoid * > * pAttributes
std::map< T, AttributeVoid * >::const_iterator const_aiterator
std::set< T, Cmp >::const_iterator const_iterator
std::map< T, AttributeVoid * >::iterator aiterator
std::set< T, Cmp > * pSet
virtual const AttributeVoid * AttributeType(void) const
Idx AttributesSize(void) const
virtual const AttributeVoid & Attribute(const T &rElem) const

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen