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 // ReferenceMap(bool ordered, char separator) : SmartMap<Reference>(ordered, separator){}; //, STRICTLY_CLOSED, keys(orderedKeyList), units(unitMap)
221 ReferenceMap(char separator=',') : SmartMap<Reference>(separator){}; //, STRICTLY_CLOSED, keys(orderedKeyList), units(unitMap)
222
224 inline
227
228 inline virtual
229 ~ReferenceMap(){};
230
231 // Temporary catch for Range
232 template <class F>
233 Reference & link(const std::string & key, Range<F> &x, const std::string & unit = std::string()){
234 Logger mout(__FILE__, __FUNCTION__);
235 mout.deprecating(" type drain::Range<> use .tuple() instead: ", key, '[', unit, ']');
236 return link(key, &x, typeid(F), 2, unit);
237 }
238
240
244 template <class F>
245 Reference & link(const std::string & key, F &x, const std::string & unit = std::string()){
246
247 if (find(key) == end()){ // not already referenced
248
249 if (keyList.empty()){
250 if (key.empty()){
251 std::cerr << "empty key referencing to " << sprinter(x) << " unit=" << unit << std::endl;
252 }
253 else if (key.at(0) == '_'){
254 throw std::runtime_error(key + ": hidden parameters can be added only after visible");
255 }
256 }
257 else if ((keyList.back().at(0) == '_') && (key.at(0) != '_')){
258 throw std::runtime_error(key + ": cannot add visible parameters after hidden");
259 }
260
261
262 keyList.push_back(key);
263
264 }
265
266 // Create
267 Reference & r = std::map<std::string,Reference>::operator[](key);
268 r.setSeparator(arraySeparator); // applicable, if array type element
269 // Link
270 r.link(x);
271 unitMap[key] = unit;
272 /*
273 if (!unit.empty()){
274 unitMap[key] = unit;
275 }
276 else {
277 unitMap[key] = drain::Type::call<drain::simpleName>(typeid(F));
278 }
279 */
280 return r;
281 }
282
283 inline
284 Reference & link(const std::string & key, Reference &x, const std::string & unit = std::string()){
285 return link(key, x.getPtr(), x.getType(), x.getElementCount(), unit); //.fillArray = item.fillArray;
286 }
287
288
290 inline
291 Reference & link(const std::string & key, void *ptr, const std::type_info &type, size_t count, const std::string & unit = std::string()){
292
293 if (find(key) == end()) // not already referenced
294 keyList.push_back(key);
295
296 Reference & r = std::map<std::string,Reference>::operator[](key);
297 r.setSeparator(arraySeparator); // applicable, if array type element
298 r.link(ptr, type, count);
299 unitMap[key] = unit;
300 return r;
301
302 }
303
305 inline
306 Reference & link(const std::string & key, void *ptr, const std::type_info &type, const std::string & unit = std::string()){
307 return link(key, ptr, type, 1, unit);
308 }
309
311
315 template <class F>
316 Reference & referenceTop(const std::string & key, F &x, const std::string & unit = std::string()){
317
318 if (find(key) != end()) // already referenced
319 keyList.push_front(key);
320
321 //Reference & r = std::map<std::string,Reference>::operator[](key).link(x);
322 Reference & r = std::map<std::string,Reference>::operator[](key);
323 r.setSeparator(arraySeparator); // applicable, if array type element
324 // Link
325 r.link(x);
326
327 unitMap[key] = unit;
328 return r;
329 }
330
331
333 void append(ReferenceMap & rMap, bool replace=true){
334 //std::cerr << __FILE__ << " -> " << __FUNCTION__ << std::endl;
335 const std::list<std::string> & keys = rMap.getKeyList();
336 //for (std::list<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it){
337 for (const std::string & key: keys){
338 //std::cerr << " -> " << *it << std::endl;
339 if (replace || !hasKey(key)){
340 Reference & srcItem = rMap[key];
341 Reference & item = link(key, srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
342 // Reference & item = link(key, (const Castable &)srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
343 // Reference & item = link(key, srcItem.getPtr(), srcItem.getType(), srcItem.getElementCount(), rMap.unitMap[key]); //.fillArray = item.fillArray;
344 item.setFill(srcItem.fillArray);
345 item.setInputSeparator(srcItem.getInputSeparator());
346 item.setOutputSeparator(srcItem.getOutputSeparator());
347 }
348 }
349 }
350
351 // todo: consider NULL? (but leads to problems)
352
354 inline
355 void delink(const std::string & key){
356 std::map<std::string,Reference>::erase(key);
357 for (std::list<std::string>::iterator it = keyList.begin(); it != keyList.end(); ++it)
358 if (*it == key){
359 keyList.erase(it);
360 break;
361 }
362 unitMap.erase(key);
363 }
364
366
370 void reserve(const std::string & key){
371
372 if (find(key) == end()) // not already referenced
373 keyList.push_back(key);
374
375 // Create
376 // Reference & r =
377 std::map<std::string,Reference>::operator[](key);
378 // Now r type is unset. (ptr undefined)
379
380 }
381
383
386 virtual inline
387 void clear(){
389 keyList.clear();
390 unitMap.clear();
391 }
392
402
404
411 template <class T>
412 void copyStruct(const ReferenceMap & m, const T & src, T & dst, extLinkPolicy policy=RESERVE) {
413 //, bool copyValues = true, bool linkExternal = false){
414
415 Logger mout(__FILE__, __FUNCTION__);
416 long s = sizeof(T); // yes signed
417 //mout.warn("experimental, obj.size=" , s );
418
419 // Clearing is bad, it resets work of base class constructors
420 // if (policy==LINK)
421 // clear();
422
423 typedef unsigned long addr_t;
424 typedef long addr_diff_t;
425
426 const addr_t srcAddr = (addr_t)(&src);
427 const addr_t dstAddr = (addr_t)(&dst);
428 //for (std::list<std::string>::const_iterator it = m.getKeyList().begin(); it != m.getKeyList().end(); ++it){
429 for (const std::string & key: m.getKeyList()){
430 // const std::string & key = *it;
431 const Reference & srcRef = m[key];
432 addr_t srcVarAddr = (addr_t)srcRef.getPtr();
433 addr_diff_t relativeAddr = srcVarAddr - srcAddr;
434 if ((relativeAddr >= 0) && (relativeAddr < s)){ // INTERNAL
435 Reference & dstMemberRef = link(key, (void *)(dstAddr + relativeAddr), srcRef.getType(), srcRef.getElementCount());
436 //mout.warn("local: " , key , ':' , srcRef.getElementCount() );
437 dstMemberRef.copyFormat(srcRef);
438 dstMemberRef = srcRef; // value
439 //dstMemberRef.setInputSeparator(srcRef.getInputSeparator());
440 }
441 else {
442 //mout.warn("external: " , key );
443 switch (policy) {
444 case LINK:
445 link(key, (void *)srcVarAddr, srcRef.getType(), srcRef.getElementCount()).copyFormat(srcRef);
446 break;
447 case RESERVE:
448 reserve(key);
449 //mout.warn("reserved: " , key );
450 //mout.warn("keyList: " , getKeys() );
451 break;
452 case SKIP:
453 mout.debug("skipping external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
454 break;
455 case ERROR:
456 mout.error("external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
457 break;
458 default:
459 mout.warn("unknown enum option in handling external variable '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
460 }
461 }
462 }
463
464 // Shared properties.
465 //keyList = m.keyList;
468 unitMap = m.unitMap;
469
470 }
471
472
474 template <class T>
475 inline
477 //Logger log(__FILE__, __FUNCTION__);
478 //log.error() << "in:" << v << log.endl;
479 importMap(v);
480 return *this;
481 }
482
484 virtual
485 mapped_type & operator[](const std::string &key){
486
487 Logger mout(__FILE__, __FUNCTION__);
488
489 iterator it = this->find(key);
490 if (it != this->end()) {
491 return it->second;
492 }
493 else {
494 mout.warn("current contents: " , *this );
495
496 mout.error("key '" , key ,"' not declared (referenced)" );
497 //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
498 static mapped_type empty;
499 return empty;
500 }
501
502 }
503
505 virtual
506 const mapped_type & operator[](const std::string &key) const {
507
508 Logger mout(__FILE__, __FUNCTION__); //Logger mout(__FILE__, __FUNCTION__);
509
510 const_iterator it = this->find(key);
511 if (it != this->end()) {
512 return it->second;
513 }
514 else {
515 mout.error("key '" , key ,"' not declared (referenced)" );
516 //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
517 static const mapped_type empty;
518 return empty;
519 }
520 }
521
522 typedef std::map<std::string,std::string> unitmap_t;
523
525 inline
526 const unitmap_t & getUnitMap() const { return unitMap; };
527
529 /*
530 template <class T>
531 static
532 size_t serialize(const SmartMap<T> & rmap, std::vector<char> & memory);
533 */
534
536
542protected:
543
545 // Questionable: consider SmartReference etc. with caster and unit info?
546 unitmap_t unitMap;
547
548
549};
550
551inline
552std::ostream & operator<<(std::ostream & ostr, const ReferenceMap & rmap){
553 // drain::Sprinter::toStream(ostr, rmap, drain::Sprinter::jsLayout);
555 return ostr;
556}
557
558/*
559template <class T>
560size_t ReferenceMap::serialize(const SmartMap<T> & smap, std::vector<char> & memory){
561
562 typedef SmartMap<T> smap_t;
563
564 size_t i;
565 for (smap_t::const_iterator it = smap.begin(); it != smap.end(); ++it){
566
567 const std::string & key = it->first;
568 const Castable & value = it->second;
569
570 if (v.isString()){
571
573
574 }
575 else {
576 }
577
578 }
579
580}
581*/
582
583} // namespace drain
584
585
586#endif
587
588// Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:440
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:676
Logger & error(const TT &... args)
Echoes.
Definition Log.h:426
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:291
unitmap_t unitMap
Creating a common segment for.
Definition ReferenceMap.h:546
void append(ReferenceMap &rMap, bool replace=true)
Adopts the references of r. If replace==false, only new entries are appended.
Definition ReferenceMap.h:333
Reference & link(const std::string &key, F &x, const std::string &unit=std::string())
Associates a map entry with a variable.
Definition ReferenceMap.h:245
ReferenceMap(char separator=',')
Default constructor.
Definition ReferenceMap.h:221
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:306
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:412
void reserve(const std::string &key)
Adds a null entry, expecting the link later.
Definition ReferenceMap.h:370
ReferenceMap & operator=(const SmartMap< T > &v)
Import map, adopting the element types.
Definition ReferenceMap.h:476
const unitmap_t & getUnitMap() const
Returns measurement unit information of the actual map entries.
Definition ReferenceMap.h:526
virtual mapped_type & operator[](const std::string &key)
Return element associated with key.
Definition ReferenceMap.h:485
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:316
virtual void clear()
Removes all the elements of the map.
Definition ReferenceMap.h:387
virtual const mapped_type & operator[](const std::string &key) const
Calling unreferenced key throws an exception.
Definition ReferenceMap.h:506
void delink(const std::string &key)
Removes an entry from the map.
Definition ReferenceMap.h:355
ReferenceMap(const ReferenceMap &rmap)
Copy constructor copies only the separators; does not copy the items.
Definition ReferenceMap.h:225
extLinkPolicy
Definition ReferenceMap.h:396
@ ERROR
Definition ReferenceMap.h:400
@ SKIP
Definition ReferenceMap.h:399
@ LINK
Definition ReferenceMap.h:397
@ RESERVE
Definition ReferenceMap.h:398
A base class for smart maps providing methods for importing and exporting values, among others.
Definition SmartMap.h:62
map_t::iterator iterator
Needed?
Definition SmartMap.h:76
char arraySeparator
Default separator character for array elements (std::vector's)
Definition SmartMap.h:84
std::list< std::string > keyList
Assigns values from std::string of type "value,value2,...valueN".
Definition SmartMap.h:426
char separator
Default character used for splitting input and output. See setValues.
Definition SmartMap.h:81
virtual const keylist_t & getKeyList() const
Derived versions may produce an ordered set of keys.
Definition SmartMap.h:201
void importMap(const std::map< std::string, S > &m)
Assign values from a map, overriding existing entries.
Definition SmartMap.h:253
static const SprinterLayout jsLayout
JavaScript layout. Like JSON layout, but keys without hyphens.
Definition Sprinter.h:227
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:363
VariableT is a final class applied through typedefs Variable, Reference and FlexibleVariable.
Definition VariableT.h:87
Definition Data.h:1473
VariableT< ReferenceT< Castable > > Reference
Variable-like that is linked to a standard variable: double, int, std::string . Supports multi-elemen...
Definition Reference.h:75