ReferenceMap.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood 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 
56 namespace drain {
57 
59 
66 template <class T=Reference>
67 class ReferenceMap2 : public SmartMap<T> {
68 
69 public:
70 
71  typedef T ref_t;
72  typedef SmartMap<T> map_t;
73 
74 
76 
80  template <class F>
81  inline
82  ref_t & link(const std::string & key, F &x){
83 
84  ref_t & r = (*this)[key];
85 
86  r.link(x); // .setSeparator(this->arraySeparator);
87 
88  return r;
89 
90  /*
91  if (this->find(key) == this->end()) // not already referenced
92  this->keyList.push_back(key);
93  // Create
94  ref_t & r = map_t::operator[](key);
95  r.setSeparator(this->arraySeparator); // applicable, if array type element
96  // Link
97  r.link(x);
98  // unitMap[key] = unit;
99  return r;
100  */
101  }
102 
104  inline
105  ref_t & link(const std::string & key, void *ptr, const std::type_info &type, size_t count=1){
106 
107  ref_t & r = (*this)[key];
108 
109  r.link(ptr, type, count);
110 
111  return r;
112 
113  /*
114  if (this->find(key) == this->end()) // not already referenced
115  this->keyList.push_back(key);
116 
117  Reference & r = map_t::operator[](key);
118  r.setSeparator(this->arraySeparator); // applicable, if array type element
119  r.link(ptr, type, count);
120  // unitMap[key] = unit;
121  return r;
122  */
123  }
124 
128  typedef enum {
132  ERROR
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)
207 class ReferenceMap : public SmartMap<Reference> {//public std::map<std::string,Reference> {
208 
209 public:
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
221  };
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 " << 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  return r;
268  }
269 
270  inline
271  Reference & link(const std::string & key, Reference &x, const std::string & unit = std::string()){
272  return link(key, x.getPtr(), x.getType(), x.getElementCount(), unit); //.fillArray = item.fillArray;
273  }
274 
275 
277  inline
278  Reference & link(const std::string & key, void *ptr, const std::type_info &type, size_t count, const std::string & unit = std::string()){
279 
280  if (find(key) == end()) // not already referenced
281  keyList.push_back(key);
282 
283  Reference & r = std::map<std::string,Reference>::operator[](key);
284  r.setSeparator(arraySeparator); // applicable, if array type element
285  r.link(ptr, type, count);
286  unitMap[key] = unit;
287  return r;
288 
289  }
290 
292  inline
293  Reference & link(const std::string & key, void *ptr, const std::type_info &type, const std::string & unit = std::string()){
294  return link(key, ptr, type, 1, unit);
295  }
296 
298 
302  template <class F>
303  Reference & referenceTop(const std::string & key, F &x, const std::string & unit = std::string()){
304 
305  if (find(key) != end()) // already referenced
306  keyList.push_front(key);
307 
308  //Reference & r = std::map<std::string,Reference>::operator[](key).link(x);
309  Reference & r = std::map<std::string,Reference>::operator[](key);
310  r.setSeparator(arraySeparator); // applicable, if array type element
311  // Link
312  r.link(x);
313 
314  unitMap[key] = unit;
315  return r;
316  }
317 
318 
320  void append(ReferenceMap & rMap, bool replace=true){
321  //std::cerr << __FILE__ << " -> " << __FUNCTION__ << std::endl;
322  const std::list<std::string> & keys = rMap.getKeyList();
323  //for (std::list<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it){
324  for (const std::string & key: keys){
325  //std::cerr << " -> " << *it << std::endl;
326  if (replace || !hasKey(key)){
327  Reference & srcItem = rMap[key];
328  Reference & item = link(key, srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
329  // Reference & item = link(key, (const Castable &)srcItem, rMap.unitMap[key]); //.fillArray = item.fillArray;
330  // Reference & item = link(key, srcItem.getPtr(), srcItem.getType(), srcItem.getElementCount(), rMap.unitMap[key]); //.fillArray = item.fillArray;
331  item.setFill(srcItem.fillArray);
332  item.setInputSeparator(srcItem.getInputSeparator());
333  item.setOutputSeparator(srcItem.getOutputSeparator());
334  }
335  }
336  }
337 
338  // todo: consider NULL? (but leads to problems)
339 
341  inline
342  void delink(const std::string & key){
343  std::map<std::string,Reference>::erase(key);
344  for (std::list<std::string>::iterator it = keyList.begin(); it != keyList.end(); ++it)
345  if (*it == key){
346  keyList.erase(it);
347  break;
348  }
349  unitMap.erase(key);
350  }
351 
353 
357  void reserve(const std::string & key){
358 
359  if (find(key) == end()) // not already referenced
360  keyList.push_back(key);
361 
362  // Create
363  // Reference & r =
364  std::map<std::string,Reference>::operator[](key);
365  // Now r type is unset. (ptr undefined)
366 
367  }
368 
370 
373  virtual inline
374  void clear(){
376  keyList.clear();
377  unitMap.clear();
378  }
379 
383  typedef enum {
387  ERROR
389 
391 
398  template <class T>
399  void copyStruct(const ReferenceMap & m, const T & src, T & dst, extLinkPolicy policy=RESERVE) {
400  //, bool copyValues = true, bool linkExternal = false){
401 
402  Logger mout(__FILE__, __FUNCTION__);
403  long s = sizeof(T); // yes signed
404  //mout.warn("experimental, obj.size=" , s );
405 
406  // Clearing is bad, it resets work of base class constructors
407  // if (policy==LINK)
408  // clear();
409 
410  typedef unsigned long addr_t;
411  typedef long addr_diff_t;
412 
413  const addr_t srcAddr = (addr_t)(&src);
414  const addr_t dstAddr = (addr_t)(&dst);
415  //for (std::list<std::string>::const_iterator it = m.getKeyList().begin(); it != m.getKeyList().end(); ++it){
416  for (const std::string & key: m.getKeyList()){
417  // const std::string & key = *it;
418  const Reference & srcRef = m[key];
419  addr_t srcVarAddr = (addr_t)srcRef.getPtr();
420  addr_diff_t relativeAddr = srcVarAddr - srcAddr;
421  if ((relativeAddr >= 0) && (relativeAddr < s)){ // INTERNAL
422  Reference & dstMemberRef = link(key, (void *)(dstAddr + relativeAddr), srcRef.getType(), srcRef.getElementCount());
423  //mout.warn("local: " , key , ':' , srcRef.getElementCount() );
424  dstMemberRef.copyFormat(srcRef);
425  dstMemberRef = srcRef; // value
426  }
427  else {
428  //mout.warn("external: " , key );
429  switch (policy) {
430  case LINK:
431  link(key, (void *)srcVarAddr, srcRef.getType(), srcRef.getElementCount()).copyFormat(srcRef);
432  break;
433  case RESERVE:
434  reserve(key);
435  //mout.warn("reserved: " , key );
436  //mout.warn("keyList: " , getKeys() );
437  break;
438  case SKIP:
439  mout.debug("skipping external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
440  break;
441  case ERROR:
442  mout.error("external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
443  break;
444  default:
445  mout.warn("unknown enum option in handling external variable '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
446  }
447  }
448  }
449 
450  // Shared properties.
451  //keyList = m.keyList;
452  separator = m.separator;
454  unitMap = m.unitMap;
455 
456  }
457 
458 
460  template <class T>
461  inline
463  //Logger log(__FILE__, __FUNCTION__);
464  //log.error() << "in:" << v << log.endl;
465  importMap(v);
466  return *this;
467  }
468 
470  virtual
471  mapped_type & operator[](const std::string &key){
472 
473  Logger mout(__FILE__, __FUNCTION__);
474 
475  iterator it = this->find(key);
476  if (it != this->end()) {
477  return it->second;
478  }
479  else {
480  mout.warn("current contents: " , *this );
481 
482  mout.error("key '" , key ,"' not declared (referenced)" );
483  //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
484  static mapped_type empty;
485  return empty;
486  }
487 
488  }
489 
491  virtual
492  const mapped_type & operator[](const std::string &key) const {
493 
494  Logger mout(__FILE__, __FUNCTION__); //Logger mout(__FILE__, __FUNCTION__);
495 
496  const_iterator it = this->find(key);
497  if (it != this->end()) {
498  return it->second;
499  }
500  else {
501  mout.error("key '" , key ,"' not declared (referenced)" );
502  //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
503  static const mapped_type empty;
504  return empty;
505  }
506  }
507 
508  typedef std::map<std::string,std::string> unitmap_t;
509 
511  inline
512  const unitmap_t & getUnitMap() const { return unitMap; };
513 
515  /*
516  template <class T>
517  static
518  size_t serialize(const SmartMap<T> & rmap, std::vector<char> & memory);
519  */
520 
522 
528 protected:
529 
531  // Questionable: consider SmartReference etc. with caster and unit info?
532  unitmap_t unitMap;
533 
534 
535 };
536 
537 /*
538 template <class T>
539 size_t ReferenceMap::serialize(const SmartMap<T> & smap, std::vector<char> & memory){
540 
541  typedef SmartMap<T> smap_t;
542 
543  size_t i;
544  for (smap_t::const_iterator it = smap.begin(); it != smap.end(); ++it){
545 
546  const std::string & key = it->first;
547  const Castable & value = it->second;
548 
549  if (v.isString()){
550 
552 
553  }
554  else {
555  }
556 
557  }
558 
559 }
560 */
561 
562 } // namespace drain
563 
564 
565 #endif
566 
567 // Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & error(const TT &... args)
Echoes.
Definition: Log.h:412
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:676
A map of references to base type scalars, arrays or std::string; changing values in either are equiva...
Definition: ReferenceMap.h:67
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
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:105
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
ref_t & link(const std::string &key, F &x)
Associates a map entry with a variable.
Definition: ReferenceMap.h:82
Definition: ReferenceMap.h:207
unitmap_t unitMap
Creating a common segment for.
Definition: ReferenceMap.h:512
virtual const mapped_type & operator[](const std::string &key) const
Calling unreferenced key throws an exception.
Definition: ReferenceMap.h:492
ReferenceMap & operator=(const SmartMap< T > &v)
Import map, adopting the element types.
Definition: ReferenceMap.h:462
void append(ReferenceMap &rMap, bool replace=true)
Adopts the references of r. If replace==false, only new entries are appended.
Definition: ReferenceMap.h:320
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:303
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:278
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:293
virtual mapped_type & operator[](const std::string &key)
Return element associated with key.
Definition: ReferenceMap.h:471
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:399
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
void reserve(const std::string &key)
Adds a null entry, expecting the link later.
Definition: ReferenceMap.h:357
virtual void clear()
Removes all the elements of the map.
Definition: ReferenceMap.h:374
void delink(const std::string &key)
Removes an entry from the map.
Definition: ReferenceMap.h:342
ReferenceMap(const ReferenceMap &rmap)
Copy constructor copies only the separators; does not copy the items.
Definition: ReferenceMap.h:220
extLinkPolicy
Definition: ReferenceMap.h:383
@ ERROR
Definition: ReferenceMap.h:387
@ SKIP
Definition: ReferenceMap.h:386
@ LINK
Definition: ReferenceMap.h:384
@ RESERVE
Definition: ReferenceMap.h:385
const unitmap_t & getUnitMap() const
Returns measurement unit information of the actual map entries.
Definition: ReferenceMap.h:512
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