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/StringTools.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
200template <class T>
201inline
202std::ostream & operator<<(std::ostream & ostr, const ReferenceMap2<T> & rmap){
203 //drain::Sprinter::toStream(ostr, rmap, drain::Sprinter::jsLayout);
204 drain::Sprinter::mapToStream(ostr, rmap, drain::Sprinter::jsLayout, rmap.getKeyList());
205 return ostr;
206}
207
208
210
214// TODO: consider clear() (shallow op)
215class ReferenceMap : public SmartMap<Reference> {//public std::map<std::string,Reference> {
216
217public:
218
220
223 // ReferenceMap(bool ordered, char separator) : SmartMap<Reference>(ordered, separator){}; //, STRICTLY_CLOSED, keys(orderedKeyList), units(unitMap)
224 ReferenceMap(char separator=',') : SmartMap<Reference>(separator){}; //, STRICTLY_CLOSED, keys(orderedKeyList), units(unitMap)
225
227 inline
230
231 inline virtual
232 ~ReferenceMap(){};
233
234 // Temporary catch for Range
235 template <class F>
236 Reference & link(const std::string & key, Range<F> &x, const std::string & unit = std::string()){
237 Logger mout(__FILE__, __FUNCTION__);
238 mout.deprecating(" type drain::Range<> use .tuple() instead: ", key, '[', unit, ']');
239 return link(key, &x, typeid(F), 2, unit);
240 }
241
243
247 template <class F>
248 Reference & link(const std::string & key, F &x, const std::string & unit = std::string()){
249
250 if (find(key) == end()){ // not already referenced
251
252 if (keyList.empty()){
253 if (key.empty()){
254 std::cerr << "empty key referencing to " << sprinter(x) << " unit=" << unit << std::endl;
255 }
256 else if (key.at(0) == '_'){
257 throw std::runtime_error(key + ": hidden parameters can be added only after visible");
258 }
259 }
260 else if ((keyList.back().at(0) == '_') && (key.at(0) != '_')){
261 throw std::runtime_error(key + ": cannot add visible parameters after hidden");
262 }
263
264
265 keyList.push_back(key);
266
267 }
268
269 // Create
270 Reference & r = std::map<std::string,Reference>::operator[](key);
271 r.setSeparator(arraySeparator); // applicable, if array type element
272 // Link
273 r.link(x);
274 unitMap[key] = unit;
275 /*
276 if (!unit.empty()){
277 unitMap[key] = unit;
278 }
279 else {
280 unitMap[key] = drain::Type::call<drain::simpleName>(typeid(F));
281 }
282 */
283 return r;
284 }
285
286 inline
287 Reference & link(const std::string & key, Reference &x, const std::string & unit = std::string()){
288 return link(key, x.getPtr(), x.getType(), x.getElementCount(), unit); //.fillArray = item.fillArray;
289 }
290
291
293 inline
294 Reference & link(const std::string & key, void *ptr, const std::type_info &type, size_t count, const std::string & unit = std::string()){
295
296 if (find(key) == end()) // not already referenced
297 keyList.push_back(key);
298
299 Reference & r = std::map<std::string,Reference>::operator[](key);
300 r.setSeparator(arraySeparator); // applicable, if array type element
301 r.link(ptr, type, count);
302 unitMap[key] = unit;
303 return r;
304
305 }
306
308 inline
309 Reference & link(const std::string & key, void *ptr, const std::type_info &type, const std::string & unit = std::string()){
310 return link(key, ptr, type, 1, unit);
311 }
312
314
318 template <class F>
319 Reference & referenceTop(const std::string & key, F &x, const std::string & unit = std::string()){
320
321 if (find(key) != end()) // already referenced
322 keyList.push_front(key);
323
324 //Reference & r = std::map<std::string,Reference>::operator[](key).link(x);
325 Reference & r = std::map<std::string,Reference>::operator[](key);
326 r.setSeparator(arraySeparator); // applicable, if array type element
327 // Link
328 r.link(x);
329
330 unitMap[key] = unit;
331 return r;
332 }
333
334
336 void append(ReferenceMap & rMap, bool replace=true){
337 //std::cerr << __FILE__ << " -> " << __FUNCTION__ << std::endl;
338 const std::list<std::string> & keys = rMap.getKeyList();
339 //for (std::list<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it){
340 for (const std::string & key: keys){
341 //std::cerr << " -> " << *it << std::endl;
342 if (replace || !hasKey(key)){
343 Reference & srcItem = rMap[key];
344 Reference & item = link(key, srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
345 // Reference & item = link(key, (const Castable &)srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
346 // Reference & item = link(key, srcItem.getPtr(), srcItem.getType(), srcItem.getElementCount(), rMap.unitMap[key]); //.fillArray = item.fillArray;
347 item.setFill(srcItem.fillArray);
348 item.setInputSeparator(srcItem.getInputSeparator());
349 item.setOutputSeparator(srcItem.getOutputSeparator());
350 }
351 }
352 }
353
354 // todo: consider NULL? (but leads to problems)
355
357 inline
358 void delink(const std::string & key){
359 std::map<std::string,Reference>::erase(key);
360 for (std::list<std::string>::iterator it = keyList.begin(); it != keyList.end(); ++it)
361 if (*it == key){
362 keyList.erase(it);
363 break;
364 }
365 unitMap.erase(key);
366 }
367
369
373 void reserve(const std::string & key){
374
375 if (find(key) == end()) // not already referenced
376 keyList.push_back(key);
377
378 // Create
379 // Reference & r =
380 std::map<std::string,Reference>::operator[](key);
381 // Now r type is unset. (ptr undefined)
382
383 }
384
386
389 virtual inline
390 void clear(){
392 keyList.clear();
393 unitMap.clear();
394 }
395
405
407
414 template <class T>
415 void copyStruct(const ReferenceMap & m, const T & src, T & dst, extLinkPolicy policy=RESERVE) {
416 //, bool copyValues = true, bool linkExternal = false){
417
418 Logger mout(__FILE__, __FUNCTION__);
419 long s = sizeof(T); // yes signed
420 //mout.warn("experimental, obj.size=" , s );
421
422 // Clearing is bad, it resets work of base class constructors
423 // if (policy==LINK)
424 // clear();
425
426 typedef unsigned long addr_t;
427 typedef long addr_diff_t;
428
429 const addr_t srcAddr = (addr_t)(&src);
430 const addr_t dstAddr = (addr_t)(&dst);
431 //for (std::list<std::string>::const_iterator it = m.getKeyList().begin(); it != m.getKeyList().end(); ++it){
432 for (const std::string & key: m.getKeyList()){
433 // const std::string & key = *it;
434 const Reference & srcRef = m[key];
435 addr_t srcVarAddr = (addr_t)srcRef.getPtr();
436 addr_diff_t relativeAddr = srcVarAddr - srcAddr;
437 if ((relativeAddr >= 0) && (relativeAddr < s)){ // INTERNAL
438 Reference & dstMemberRef = link(key, (void *)(dstAddr + relativeAddr), srcRef.getType(), srcRef.getElementCount());
439 //mout.warn("local: " , key , ':' , srcRef.getElementCount() );
440 dstMemberRef.copyFormat(srcRef);
441 dstMemberRef = srcRef; // value
442 //dstMemberRef.setInputSeparator(srcRef.getInputSeparator());
443 }
444 else {
445 //mout.warn("external: " , key );
446 switch (policy) {
447 case LINK:
448 link(key, (void *)srcVarAddr, srcRef.getType(), srcRef.getElementCount()).copyFormat(srcRef);
449 break;
450 case RESERVE:
451 reserve(key);
452 //mout.warn("reserved: " , key );
453 //mout.warn("keyList: " , getKeys() );
454 break;
455 case SKIP:
456 mout.debug("skipping external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
457 break;
458 case ERROR:
459 mout.error("external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
460 break;
461 default:
462 mout.warn("unknown enum option in handling external variable '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
463 }
464 }
465 }
466
467 // Shared properties.
468 //keyList = m.keyList;
471 unitMap = m.unitMap;
472
473 }
474
475
477 template <class T>
478 inline
480 //Logger log(__FILE__, __FUNCTION__);
481 //log.error() << "in:" << v << log.endl;
482 importMap(v);
483 return *this;
484 }
485
487 virtual
488 mapped_type & operator[](const std::string &key){
489
490 Logger mout(__FILE__, __FUNCTION__);
491
492 iterator it = this->find(key);
493 if (it != this->end()) {
494 return it->second;
495 }
496 else {
497 mout.warn("current contents: " , *this );
498
499 mout.error("key '" , key ,"' not declared (referenced)" );
500 //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
501 static mapped_type empty;
502 return empty;
503 }
504
505 }
506
508 virtual
509 const mapped_type & operator[](const std::string &key) const {
510
511 Logger mout(__FILE__, __FUNCTION__); //Logger mout(__FILE__, __FUNCTION__);
512
513 const_iterator it = this->find(key);
514 if (it != this->end()) {
515 return it->second;
516 }
517 else {
518 mout.error("key '" , key ,"' not declared (referenced)" );
519 //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
520 static const mapped_type empty;
521 return empty;
522 }
523 }
524
525 typedef std::map<std::string,std::string> unitmap_t;
526
528 inline
529 const unitmap_t & getUnitMap() const { return unitMap; };
530
532 /*
533 template <class T>
534 static
535 size_t serialize(const SmartMap<T> & rmap, std::vector<char> & memory);
536 */
537
539
545protected:
546
548 // Questionable: consider SmartReference etc. with caster and unit info?
549 unitmap_t unitMap;
550
551
552};
553
554inline
555std::ostream & operator<<(std::ostream & ostr, const ReferenceMap & rmap){
556 // drain::Sprinter::toStream(ostr, rmap, drain::Sprinter::jsLayout);
558 return ostr;
559}
560
561/*
562template <class T>
563size_t ReferenceMap::serialize(const SmartMap<T> & smap, std::vector<char> & memory){
564
565 typedef SmartMap<T> smap_t;
566
567 size_t i;
568 for (smap_t::const_iterator it = smap.begin(); it != smap.end(); ++it){
569
570 const std::string & key = it->first;
571 const Castable & value = it->second;
572
573 if (v.isString()){
574
576
577 }
578 else {
579 }
580
581 }
582
583}
584*/
585
586} // namespace drain
587
588
589#endif
590
591// Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:431
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:667
Logger & error(const TT &... args)
Echoes.
Definition Log.h:417
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:215
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:294
unitmap_t unitMap
Creating a common segment for.
Definition ReferenceMap.h:549
void append(ReferenceMap &rMap, bool replace=true)
Adopts the references of r. If replace==false, only new entries are appended.
Definition ReferenceMap.h:336
Reference & link(const std::string &key, F &x, const std::string &unit=std::string())
Associates a map entry with a variable.
Definition ReferenceMap.h:248
ReferenceMap(char separator=',')
Default constructor.
Definition ReferenceMap.h:224
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:309
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:415
void reserve(const std::string &key)
Adds a null entry, expecting the link later.
Definition ReferenceMap.h:373
ReferenceMap & operator=(const SmartMap< T > &v)
Import map, adopting the element types.
Definition ReferenceMap.h:479
const unitmap_t & getUnitMap() const
Returns measurement unit information of the actual map entries.
Definition ReferenceMap.h:529
virtual mapped_type & operator[](const std::string &key)
Return element associated with key.
Definition ReferenceMap.h:488
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:319
virtual void clear()
Removes all the elements of the map.
Definition ReferenceMap.h:390
virtual const mapped_type & operator[](const std::string &key) const
Calling unreferenced key throws an exception.
Definition ReferenceMap.h:509
void delink(const std::string &key)
Removes an entry from the map.
Definition ReferenceMap.h:358
ReferenceMap(const ReferenceMap &rmap)
Copy constructor copies only the separators; does not copy the items.
Definition ReferenceMap.h:228
extLinkPolicy
Definition ReferenceMap.h:399
@ ERROR
Definition ReferenceMap.h:403
@ SKIP
Definition ReferenceMap.h:402
@ LINK
Definition ReferenceMap.h:400
@ RESERVE
Definition ReferenceMap.h:401
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:430
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:255
static const SprinterLayout jsLayout
JavaScript layout. Like JSON layout, but keys without hyphens.
Definition Sprinter.h:228
static std::ostream & mapToStream(std::ostream &ostr, const M &m, const SprinterLayout &layout, const K &keys)
Given a sequence or subsequence of keys, output values of a map in that order.
Definition Sprinter.h:364
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