Loading...
Searching...
No Matches
ReferenceMap.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31//#include <typeinfo>
32#include <drain/Log.h>
33#include <stdexcept>
34//#include <iostream>
35//#include <vector>
36#include <string>
37
38#include <map>
39#include <list>
40
41
42#include <drain/Reference.h>
43#include <drain/String.h>
44
45#include "Range.h"
46// #include "FlexibleVariable.h"
47//#include "ReferenceVariable.h"
48
49#include "SmartMap.h"
50
51
52#ifndef REFERENCE_MAP
53#define REFERENCE_MAP
54
55
56namespace drain {
57
59
68template <class T=Reference>
69class ReferenceMap2 : public SmartMap<T> {
70
71public:
72
73 typedef T ref_t;
74 typedef SmartMap<T> map_t;
75
76
78
82 template <class F>
83 inline
84 ref_t & link(const std::string & key, F &x){
85
86 ref_t & r = (*this)[key];
87 r.link(x); // .setSeparator(this->arraySeparator);
88 return r;
89
90 }
91
93 inline
94 ref_t & link(const std::string & key, void *ptr, const std::type_info &type, size_t count=1){
95
96 ref_t & r = (*this)[key];
97 r.link(ptr, type, count);
98 return r;
99
100 /*
101 if (this->find(key) == this->end()) // not already referenced
102 this->keyList.push_back(key);
103
104 Reference & r = map_t::operator[](key);
105 r.setSeparator(this->arraySeparator); // applicable, if array type element
106 r.link(ptr, type, count);
107 // unitMap[key] = unit;
108 return r;
109 */
110 }
111
112 inline
113 void unlink(const std::string & key){
114 map_t::erase(key);
115 for (std::list<std::string>::iterator it = this->keyList.begin(); it != this->keyList.end(); ++it){
116 if (*it == key){
117 this->keyList.erase(it);
118 break;
119 }
120 }
121 //unitMap.erase(key);
122 }
123
124
134
136
143 template <class T2>
144 //static // Start with T. Todo: consider other
145 void copyStruct(const ReferenceMap2<T> & m, const T2 & src, T2 & dst, extLinkPolicy policy=RESERVE) {
146 //, bool copyValues = true, bool linkExternal = false){
147
148 Logger mout(__FILE__, __FUNCTION__);
149 long s = sizeof(T2); // yes signed
150 //mout.warn("experimental, obj.size=" , s );
151
152 // Clearing is bad, it resets work of base class constructors
153 // if (policy==LINK)
154 // clear();
155
156 typedef unsigned long addr_t;
157 typedef long addr_diff_t;
158
159 const addr_t srcAddr = (addr_t)(&src);
160 const addr_t dstAddr = (addr_t)(&dst);
161 //for (std::list<std::string>::const_iterator it = m.getKeyList().begin(); it != m.getKeyList().end(); ++it){
162 for (const std::string & key: m.getKeyList()){
163 // const std::string & key = *it;
164 const ref_t & srcRef = m[key];
165 addr_t srcVarAddr = (addr_t)srcRef.getPtr();
166 addr_diff_t relativeAddr = srcVarAddr - srcAddr;
167 if ((relativeAddr >= 0) && (relativeAddr < s)){ // INTERNAL
168 //Reference & dstMemberRef = (*this)[key];
169 ref_t & dstMemberRef = link(key, (void *)(dstAddr + relativeAddr), srcRef.getType(), srcRef.getElementCount());
170 //mout.warn("local: " , key , ':' , srcRef.getElementCount() );
171 dstMemberRef.copyFormat(srcRef);
172 dstMemberRef.assignCastable(srcRef); // value
173 }
174 else {
175 //mout.warn("external: " , key );
176 switch (policy) {
177 case LINK:
178 link(key, (void *)srcVarAddr, srcRef.getType(), srcRef.getElementCount()).copyFormat(srcRef);
179 break;
180 case RESERVE:
181 // reserve(key);
182 (*this)[key];
183 //mout.warn("reserved: " , key );
184 //mout.warn("keyList: " , getKeys() );
185 break;
186 case SKIP:
187 mout.debug("skipping external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
188 break;
189 case ERROR:
190 mout.error("external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
191 break;
192 default:
193 mout.warn("unknown enum option in handling external variable '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
194 }
195 }
196 }
197 }
198};
199
200
202
206// TODO: consider clear() (shallow op)
207class ReferenceMap : public SmartMap<Reference> {//public std::map<std::string,Reference> {
208
209public:
210
212
215 // ReferenceMap(bool ordered, char separator) : SmartMap<Reference>(ordered, separator){}; //, STRICTLY_CLOSED, keys(orderedKeyList), units(unitMap)
216 ReferenceMap(char separator=',') : SmartMap<Reference>(separator){}; //, STRICTLY_CLOSED, keys(orderedKeyList), units(unitMap)
217
219 inline
222
223 inline virtual
224 ~ReferenceMap(){};
225
226 // Temporary catch for Range
227 template <class F>
228 Reference & link(const std::string & key, Range<F> &x, const std::string & unit = std::string()){
229 Logger mout(__FILE__, __FUNCTION__);
230 mout.deprecating(" type drain::Range<> use .tuple() instead: ", key, '[', unit, ']');
231 return link(key, &x, typeid(F), 2, unit);
232 }
233
235
239 template <class F>
240 Reference & link(const std::string & key, F &x, const std::string & unit = std::string()){
241
242 if (find(key) == end()){ // not already referenced
243
244 if (keyList.empty()){
245 if (key.empty()){
246 std::cerr << "empty key referencing to " << sprinter(x) << " unit=" << unit << std::endl;
247 }
248 else if (key.at(0) == '_'){
249 throw std::runtime_error(key + ": hidden parameters can be added only after visible");
250 }
251 }
252 else if ((keyList.back().at(0) == '_') && (key.at(0) != '_')){
253 throw std::runtime_error(key + ": cannot add visible parameters after hidden");
254 }
255
256
257 keyList.push_back(key);
258
259 }
260
261 // Create
262 Reference & r = std::map<std::string,Reference>::operator[](key);
263 r.setSeparator(arraySeparator); // applicable, if array type element
264 // Link
265 r.link(x);
266 unitMap[key] = unit;
267 /*
268 if (!unit.empty()){
269 unitMap[key] = unit;
270 }
271 else {
272 unitMap[key] = drain::Type::call<drain::simpleName>(typeid(F));
273 }
274 */
275 return r;
276 }
277
278 inline
279 Reference & link(const std::string & key, Reference &x, const std::string & unit = std::string()){
280 return link(key, x.getPtr(), x.getType(), x.getElementCount(), unit); //.fillArray = item.fillArray;
281 }
282
283
285 inline
286 Reference & link(const std::string & key, void *ptr, const std::type_info &type, size_t count, const std::string & unit = std::string()){
287
288 if (find(key) == end()) // not already referenced
289 keyList.push_back(key);
290
291 Reference & r = std::map<std::string,Reference>::operator[](key);
292 r.setSeparator(arraySeparator); // applicable, if array type element
293 r.link(ptr, type, count);
294 unitMap[key] = unit;
295 return r;
296
297 }
298
300 inline
301 Reference & link(const std::string & key, void *ptr, const std::type_info &type, const std::string & unit = std::string()){
302 return link(key, ptr, type, 1, unit);
303 }
304
306
310 template <class F>
311 Reference & referenceTop(const std::string & key, F &x, const std::string & unit = std::string()){
312
313 if (find(key) != end()) // already referenced
314 keyList.push_front(key);
315
316 //Reference & r = std::map<std::string,Reference>::operator[](key).link(x);
317 Reference & r = std::map<std::string,Reference>::operator[](key);
318 r.setSeparator(arraySeparator); // applicable, if array type element
319 // Link
320 r.link(x);
321
322 unitMap[key] = unit;
323 return r;
324 }
325
326
328 void append(ReferenceMap & rMap, bool replace=true){
329 //std::cerr << __FILE__ << " -> " << __FUNCTION__ << std::endl;
330 const std::list<std::string> & keys = rMap.getKeyList();
331 //for (std::list<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it){
332 for (const std::string & key: keys){
333 //std::cerr << " -> " << *it << std::endl;
334 if (replace || !hasKey(key)){
335 Reference & srcItem = rMap[key];
336 Reference & item = link(key, srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
337 // Reference & item = link(key, (const Castable &)srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
338 // Reference & item = link(key, srcItem.getPtr(), srcItem.getType(), srcItem.getElementCount(), rMap.unitMap[key]); //.fillArray = item.fillArray;
339 item.setFill(srcItem.fillArray);
340 item.setInputSeparator(srcItem.getInputSeparator());
341 item.setOutputSeparator(srcItem.getOutputSeparator());
342 }
343 }
344 }
345
346 // todo: consider NULL? (but leads to problems)
347
349 inline
350 void delink(const std::string & key){
351 std::map<std::string,Reference>::erase(key);
352 for (std::list<std::string>::iterator it = keyList.begin(); it != keyList.end(); ++it)
353 if (*it == key){
354 keyList.erase(it);
355 break;
356 }
357 unitMap.erase(key);
358 }
359
361
365 void reserve(const std::string & key){
366
367 if (find(key) == end()) // not already referenced
368 keyList.push_back(key);
369
370 // Create
371 // Reference & r =
372 std::map<std::string,Reference>::operator[](key);
373 // Now r type is unset. (ptr undefined)
374
375 }
376
378
381 virtual inline
382 void clear(){
384 keyList.clear();
385 unitMap.clear();
386 }
387
397
399
406 template <class T>
407 void copyStruct(const ReferenceMap & m, const T & src, T & dst, extLinkPolicy policy=RESERVE) {
408 //, bool copyValues = true, bool linkExternal = false){
409
410 Logger mout(__FILE__, __FUNCTION__);
411 long s = sizeof(T); // yes signed
412 //mout.warn("experimental, obj.size=" , s );
413
414 // Clearing is bad, it resets work of base class constructors
415 // if (policy==LINK)
416 // clear();
417
418 typedef unsigned long addr_t;
419 typedef long addr_diff_t;
420
421 const addr_t srcAddr = (addr_t)(&src);
422 const addr_t dstAddr = (addr_t)(&dst);
423 //for (std::list<std::string>::const_iterator it = m.getKeyList().begin(); it != m.getKeyList().end(); ++it){
424 for (const std::string & key: m.getKeyList()){
425 // const std::string & key = *it;
426 const Reference & srcRef = m[key];
427 addr_t srcVarAddr = (addr_t)srcRef.getPtr();
428 addr_diff_t relativeAddr = srcVarAddr - srcAddr;
429 if ((relativeAddr >= 0) && (relativeAddr < s)){ // INTERNAL
430 Reference & dstMemberRef = link(key, (void *)(dstAddr + relativeAddr), srcRef.getType(), srcRef.getElementCount());
431 //mout.warn("local: " , key , ':' , srcRef.getElementCount() );
432 dstMemberRef.copyFormat(srcRef);
433 dstMemberRef = srcRef; // value
434 //dstMemberRef.setInputSeparator(srcRef.getInputSeparator());
435 }
436 else {
437 //mout.warn("external: " , key );
438 switch (policy) {
439 case LINK:
440 link(key, (void *)srcVarAddr, srcRef.getType(), srcRef.getElementCount()).copyFormat(srcRef);
441 break;
442 case RESERVE:
443 reserve(key);
444 //mout.warn("reserved: " , key );
445 //mout.warn("keyList: " , getKeys() );
446 break;
447 case SKIP:
448 mout.debug("skipping external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
449 break;
450 case ERROR:
451 mout.error("external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
452 break;
453 default:
454 mout.warn("unknown enum option in handling external variable '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
455 }
456 }
457 }
458
459 // Shared properties.
460 //keyList = m.keyList;
463 unitMap = m.unitMap;
464
465 }
466
467
469 template <class T>
470 inline
472 //Logger log(__FILE__, __FUNCTION__);
473 //log.error() << "in:" << v << log.endl;
474 importMap(v);
475 return *this;
476 }
477
479 virtual
480 mapped_type & operator[](const std::string &key){
481
482 Logger mout(__FILE__, __FUNCTION__);
483
484 iterator it = this->find(key);
485 if (it != this->end()) {
486 return it->second;
487 }
488 else {
489 mout.warn("current contents: " , *this );
490
491 mout.error("key '" , key ,"' not declared (referenced)" );
492 //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
493 static mapped_type empty;
494 return empty;
495 }
496
497 }
498
500 virtual
501 const mapped_type & operator[](const std::string &key) const {
502
503 Logger mout(__FILE__, __FUNCTION__); //Logger mout(__FILE__, __FUNCTION__);
504
505 const_iterator it = this->find(key);
506 if (it != this->end()) {
507 return it->second;
508 }
509 else {
510 mout.error("key '" , key ,"' not declared (referenced)" );
511 //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
512 static const mapped_type empty;
513 return empty;
514 }
515 }
516
517 typedef std::map<std::string,std::string> unitmap_t;
518
520 inline
521 const unitmap_t & getUnitMap() const { return unitMap; };
522
524 /*
525 template <class T>
526 static
527 size_t serialize(const SmartMap<T> & rmap, std::vector<char> & memory);
528 */
529
531
537protected:
538
540 // Questionable: consider SmartReference etc. with caster and unit info?
541 unitmap_t unitMap;
542
543
544};
545
546/*
547template <class T>
548size_t ReferenceMap::serialize(const SmartMap<T> & smap, std::vector<char> & memory){
549
550 typedef SmartMap<T> smap_t;
551
552 size_t i;
553 for (smap_t::const_iterator it = smap.begin(); it != smap.end(); ++it){
554
555 const std::string & key = it->first;
556 const Castable & value = it->second;
557
558 if (v.isString()){
559
561
562 }
563 else {
564 }
565
566 }
567
568}
569*/
570
571} // namespace drain
572
573
574#endif
575
576// Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:430
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:666
Logger & error(const TT &... args)
Echoes.
Definition Log.h:416
A map of references to base type scalars, arrays or std::string; changing values in either are equiva...
Definition ReferenceMap.h:69
ref_t & link(const std::string &key, F &x)
Associates a map entry with a variable.
Definition ReferenceMap.h:84
ref_t & link(const std::string &key, void *ptr, const std::type_info &type, size_t count=1)
Create a reference to a basic type or std::string. (Also for basetype arrays.)
Definition ReferenceMap.h:94
void copyStruct(const ReferenceMap2< T > &m, const T2 &src, T2 &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition ReferenceMap.h:145
extLinkPolicy
Definition ReferenceMap.h:128
@ ERROR
Definition ReferenceMap.h:132
@ SKIP
Definition ReferenceMap.h:130
@ LINK
Definition ReferenceMap.h:129
@ RESERVE
Definition ReferenceMap.h:131
Definition ReferenceMap.h:207
Reference & link(const std::string &key, void *ptr, const std::type_info &type, size_t count, const std::string &unit=std::string())
For arrays.
Definition ReferenceMap.h:286
unitmap_t unitMap
Creating a common segment for.
Definition ReferenceMap.h:541
void append(ReferenceMap &rMap, bool replace=true)
Adopts the references of r. If replace==false, only new entries are appended.
Definition ReferenceMap.h:328
Reference & link(const std::string &key, F &x, const std::string &unit=std::string())
Associates a map entry with a variable.
Definition ReferenceMap.h:240
ReferenceMap(char separator=',')
Default constructor.
Definition ReferenceMap.h:216
Reference & link(const std::string &key, void *ptr, const std::type_info &type, const std::string &unit=std::string())
Convenience: create a reference to a scalar. For arrays, use the.
Definition ReferenceMap.h:301
void copyStruct(const ReferenceMap &m, const T &src, T &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition ReferenceMap.h:407
void reserve(const std::string &key)
Adds a null entry, expecting the link later.
Definition ReferenceMap.h:365
ReferenceMap & operator=(const SmartMap< T > &v)
Import map, adopting the element types.
Definition ReferenceMap.h:471
const unitmap_t & getUnitMap() const
Returns measurement unit information of the actual map entries.
Definition ReferenceMap.h:521
virtual mapped_type & operator[](const std::string &key)
Return element associated with key.
Definition ReferenceMap.h:480
Reference & referenceTop(const std::string &key, F &x, const std::string &unit=std::string())
Associates a map entry with a variable, adding key in the beginning of key list.
Definition ReferenceMap.h:311
virtual void clear()
Removes all the elements of the map.
Definition ReferenceMap.h:382
virtual const mapped_type & operator[](const std::string &key) const
Calling unreferenced key throws an exception.
Definition ReferenceMap.h:501
void delink(const std::string &key)
Removes an entry from the map.
Definition ReferenceMap.h:350
ReferenceMap(const ReferenceMap &rmap)
Copy constructor copies only the separators; does not copy the items.
Definition ReferenceMap.h:220
extLinkPolicy
Definition ReferenceMap.h:391
@ ERROR
Definition ReferenceMap.h:395
@ SKIP
Definition ReferenceMap.h:394
@ LINK
Definition ReferenceMap.h:392
@ RESERVE
Definition ReferenceMap.h:393
A base class for smart maps providing methods for importing and exporting values, among others.
Definition SmartMap.h:66
map_t::iterator iterator
Needed?
Definition SmartMap.h:80
char arraySeparator
Default separator character for array elements (std::vector's)
Definition SmartMap.h:88
std::list< std::string > keyList
Assigns values from std::string of type "value,value2,...valueN".
Definition SmartMap.h:438
char separator
Default character used for splitting input and output. See setValues.
Definition SmartMap.h:85
virtual const keylist_t & getKeyList() const
Derived versions may produce an ordered set of keys.
Definition SmartMap.h:200
void importMap(const std::map< std::string, S > &m)
Assign values from a map, overriding existing entries.
Definition SmartMap.h:252
VariableT is a final class applied through typedefs Variable, Reference and FlexibleVariable.
Definition VariableT.h:87
Definition DataSelector.cpp:1277
VariableT< ReferenceT< Castable > > Reference
Variable-like that is linked to a standard variable: double, int, std::string . Supports multi-elemen...
Definition Reference.h:78