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 
68 template <class T=Reference>
69 class ReferenceMap2 : public SmartMap<T> {
70 
71 public:
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 
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  //dstMemberRef.setInputSeparator(srcRef.getInputSeparator());
427  }
428  else {
429  //mout.warn("external: " , key );
430  switch (policy) {
431  case LINK:
432  link(key, (void *)srcVarAddr, srcRef.getType(), srcRef.getElementCount()).copyFormat(srcRef);
433  break;
434  case RESERVE:
435  reserve(key);
436  //mout.warn("reserved: " , key );
437  //mout.warn("keyList: " , getKeys() );
438  break;
439  case SKIP:
440  mout.debug("skipping external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
441  break;
442  case ERROR:
443  mout.error("external variable: '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
444  break;
445  default:
446  mout.warn("unknown enum option in handling external variable '" , key , '=' , srcRef , "' relative addr=" , relativeAddr );
447  }
448  }
449  }
450 
451  // Shared properties.
452  //keyList = m.keyList;
453  separator = m.separator;
454  arraySeparator = m.arraySeparator;
455  unitMap = m.unitMap;
456 
457  }
458 
459 
461  template <class T>
462  inline
464  //Logger log(__FILE__, __FUNCTION__);
465  //log.error() << "in:" << v << log.endl;
466  importMap(v);
467  return *this;
468  }
469 
471  virtual
472  mapped_type & operator[](const std::string &key){
473 
474  Logger mout(__FILE__, __FUNCTION__);
475 
476  iterator it = this->find(key);
477  if (it != this->end()) {
478  return it->second;
479  }
480  else {
481  mout.warn("current contents: " , *this );
482 
483  mout.error("key '" , key ,"' not declared (referenced)" );
484  //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
485  static mapped_type empty;
486  return empty;
487  }
488 
489  }
490 
492  virtual
493  const mapped_type & operator[](const std::string &key) const {
494 
495  Logger mout(__FILE__, __FUNCTION__); //Logger mout(__FILE__, __FUNCTION__);
496 
497  const_iterator it = this->find(key);
498  if (it != this->end()) {
499  return it->second;
500  }
501  else {
502  mout.error("key '" , key ,"' not declared (referenced)" );
503  //throw std::runtime_error(key + ": ReferenceMap & operator[] : key not found");
504  static const mapped_type empty;
505  return empty;
506  }
507  }
508 
509  typedef std::map<std::string,std::string> unitmap_t;
510 
512  inline
513  const unitmap_t & getUnitMap() const { return unitMap; };
514 
516  /*
517  template <class T>
518  static
519  size_t serialize(const SmartMap<T> & rmap, std::vector<char> & memory);
520  */
521 
523 
529 protected:
530 
532  // Questionable: consider SmartReference etc. with caster and unit info?
533  unitmap_t unitMap;
534 
535 
536 };
537 
538 /*
539 template <class T>
540 size_t ReferenceMap::serialize(const SmartMap<T> & smap, std::vector<char> & memory){
541 
542  typedef SmartMap<T> smap_t;
543 
544  size_t i;
545  for (smap_t::const_iterator it = smap.begin(); it != smap.end(); ++it){
546 
547  const std::string & key = it->first;
548  const Castable & value = it->second;
549 
550  if (v.isString()){
551 
553 
554  }
555  else {
556  }
557 
558  }
559 
560 }
561 */
562 
563 } // namespace drain
564 
565 
566 #endif
567 
568 // Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:310
Logger & error(const TT &... args)
Echoes.
Definition: Log.h:414
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:428
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:678
A map of references to base type scalars, arrays or std::string; changing values in either are equiva...
Definition: ReferenceMap.h:69
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:94
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:84
Definition: ReferenceMap.h:207
unitmap_t unitMap
Creating a common segment for.
Definition: ReferenceMap.h:513
virtual const mapped_type & operator[](const std::string &key) const
Calling unreferenced key throws an exception.
Definition: ReferenceMap.h:493
ReferenceMap & operator=(const SmartMap< T > &v)
Import map, adopting the element types.
Definition: ReferenceMap.h:463
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:472
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:513
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