SmartMapTools.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 #ifndef DRAIN_SMARTMAP_TOOLS_H
32 #define DRAIN_SMARTMAP_TOOLS_H
33 
34 #include <drain/Log.h>
35 #include <drain/Reference.h>
36 #include <iostream>
37 #include <string>
38 #include <set>
39 #include <list>
40 #include <vector>
41 #include <map>
42 //#include <stdlib.h>
43 #include <sys/syslog.h>
44 #include <syslog.h>
45 
46 #include "Castable.h"
47 #include "Reference.h"
48 #include "Sprinter.h"
49 #include "String.h"
50 #include "Variable.h"
51 
52 
53 namespace drain {
54 
56 class MapTools {
57 
58 public:
59 
61 
67  template <class M>
68  static
69  const typename M::mapped_type & get(const M & m, const typename M::key_type & key){
70  typename M::const_iterator it = m.find(key);
71  if (it != m.end()){
72  return it->second;
73  }
74  else {
75  static const typename M::mapped_type empty;
76  return empty;
77  }
78  }
79 
80 
82 
88  template <class M,class F>
89  static
90  void get(const M & m, const typename M::key_type & key, F & value){
91  typename M::const_iterator it = m.find(key);
92  if (it != m.end()){
93  drain::Reference r(value);
94  r = it->second;
95  return; // false; // it->second;
96  }
97  else { //
98  return; // true; // defaultValue;
99  }
100  }
101 
102 };
103 
105 // Note: some update()'s may still be buggy
106 class SmartMapTools : public MapTools {
107 
108 public:
109 
110  typedef std::list<std::string> keylist_t;
111 
113  /*
114  template <class T>
115  static
116  void getKeyList(const std::map<std::string,T> & src, keylist_t & keys) {
117  keys.clear();
118  for (const std::pair<std::string,T> & entry : src){
119  keys.push_back(entry.first);
120  }
121  }
122  */
123 
124 
125 
127 
131  template <class M,class V,bool STRICT=true>
132  static
133  void setValue(M & dst, const std::string & key, const V & value) {
134  if (STRICT){
135  dst[key] = value; // throws exception in derived classes!
136  }
137  else {
138  //typename std::map<std::string,T>::iterator it = dst.find(key);
139  typename M::iterator it = dst.find(key);
140  if (it != dst.end()){
141  it->second = value;
142  }
143  else {
144  //std::cerr << __FILE__ << ':' << __FUNCTION__ << ": key '" << key << "' not found\n";
145  }
146  }
147  }
148 
149  template <class M,class V>
150  static inline
151  void setValue(M & dst, const std::string & key, const V & value, bool STRICT) {
152  if (STRICT)
153  setValue<M,V,true>(dst, key, value);
154  else
155  setValue<M,V,false>(dst, key, value);
156  }
157 
158 
160 
164  template <class M,class V>
165  static inline
166  void updateValue(M & dst, const std::string & key, const V & value) {
167  setValue<M,V,false>(dst, key, value);
168  }
169 
170 
174  template <class M,class S,bool STRICT=true>
175  static
176  void setValues(M & dst, const std::map<std::string,S> & srcMap) {
177  // std::cerr << __FUNCTION__ << ':' << typeid(M).name() << " <= map<str," << typeid(S).name() << ">\n";
178  for (const typename std::map<std::string,S>::value_type & entry: srcMap){
179  setValue<M,S,STRICT>(dst, entry.first, entry.second);
180  }
181  }
182 
183  template <class M,class S,bool STRICT=true>
184  static
185  void setCastableValues(M & dst, const std::map<std::string,S> & srcMap) {
186  //std::cerr << __FUNCTION__ << ':' << typeid(M).name() << " <= map<str," << typeid(S).name() << ">\n";
187  for (const typename std::map<std::string,S>::value_type & entry: srcMap){
188  setValue<M,drain::Castable,STRICT>(dst, entry.first, (const drain::Castable &) entry.second);
189  }
190  /*
191  for (typename std::map<std::string,S>::const_iterator it = srcMap.begin(); it != srcMap.end(); ++it){
192  setValue<M,S,STRICT>(dst, it->first, (const drain::Castable &) it->second);
193  }
194  */
195  }
196 
197 
198 
203  template <class M,class S>
204  static inline
205  void updateValues(M & dst, const std::map<std::string,S> & src) {
206  setValues<M,S,false>(dst, src);
207  }
208 
213  template <class M,class S>
214  static inline
215  void updateCastableValues(M & dst, const std::map<std::string,S> & src) {
216  setCastableValues<M,S,false>(dst, src);
217  }
218 
220 
225  template <class M, bool STRICT=true>
226  static
227  void setValues(M & dst, const std::list<std::string> & values, char equalSign='=') {
228  for (const std::string & entry: values){
229  if (entry.empty()){
230  Logger mout(__FILE__, __FUNCTION__);
231  if (values.size()==1){
232  //std::cerr << __FILE__ << ':' << __
233  mout.experimental("clearing a map of ", dst.size(), " elements");
234  dst.clear();
235  return;
236  }
237  else {
238  mout.warn("parameter list contained an empty value");
239  continue;
240  }
241  }
242  const size_t i = entry.find(equalSign);
243  if (i != std::string::npos){
244  if (i == (entry.length()-1)){
245  setValue<M,std::string,STRICT>(dst, entry, ""); // todo: touch
246  }
247  else {
248  setValue<M,std::string,STRICT>(dst, entry.substr(0, i), entry.substr(i+1));
249  }
250  }
251  else {
252  for (const std::string & e: values){
253  std::cerr << '"' << e << '"' << std::endl;
254  }
255  // TODO: warn dump
256  throw std::runtime_error(entry + ": positional args without keys");
257  }
258  }
259  }
260 
261 
262  template <class M, bool STRICT=true>
263  static
264  void setValues(M & dst, const std::initializer_list<Variable::init_pair_t > &l){
265  for (const auto & entry: l){
266  drain::SmartMapTools::setValue<M,Variable,STRICT>(dst, entry.first, entry.second);
267  }
268  }
269 
271 
276  template <class M>
277  static inline
278  void updateValues(M & dst, const std::list<std::string> & values, char equals='=') {
279  setValues<M,false>(dst, values, equals);
280  }
281 
283 
289  // Potential for allowed-keys-only policy (hidden/read-only entries)
290  template <class M, bool STRICT=true>
291  static
292  void setValues(M & dst, const std::list<std::string> & keys, const std::list<std::string> & entries, char assignmentSymbol='=') {
293 
294  Logger mout(__FILE__, __FUNCTION__);
295 
296 
297  const std::string assignmentSymbols(1, assignmentSymbol);
298 
299  //const std::list<std::string> & keys = getKeyList();
300  std::list<std::string>::const_iterator kit = keys.begin();
301 
302 
303  bool acceptOrderedParams = true;
304 
305  // mout.warn(" assignmentSymbol: " , assignmentSymbol );
306  // mout.warn(" size: " , this->size() );
307  for (const std::string & entry: entries){
308 
309  //for (std::list<std::string>::const_iterator pit = p.begin(); pit != p.end(); ++pit){
310  //mout.warn(" entry: " , *pit );
311 
312  // Check specific assignment, ie. check if the key=value is given explicitly.
313  if (assignmentSymbol){ // typically '='
314 
315  std::string key, value;
316 
317  if (StringTools::split2(entry, key, value, assignmentSymbols)){
318 
319  // mout.warn(" specified " , key , "=\t" , value );
320 
321  if (dst.size()==1){
322  /*
323  * This special handling is for single-element maps
324  * "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
325  */
326  typename M::iterator it = dst.begin();
327  if (key == it->first)
328  it->second = value;
329  else {
330  it->second = entry;
331  // mout.warn("is this in use?" , it->first , " <= '" , entry , "'" );
332  }
333  return;
334  }
335 
336  setValue<M,std::string,STRICT>(dst, key, value); //, criticality);
337  acceptOrderedParams = false;
338  continue;
339  }
340  else {
341  // mout.warn(" could not split: " , *pit );
342  }
343  }
344 
345  // Key and assignment symbol not given.
346 
347  if (kit != keys.end()){
348  // Assignment-by-order
349  if (!acceptOrderedParams){
350  mout.warn("positional arg '" , entry , "' for [", *kit , "] given after explicit args" );
351  }
352  //mout.warn(" ordered " , );
353  dst[*kit] = entry; // does not need to call import() because *kit exists.
354  ++kit; // NUEVO
355  }
356  else {
357  //mout.log(criticality)
358  // << "too many (over "<< this->size() << ") params, run out of keys with entry=" << *pit << mout.endl;
359  if (STRICT){
360  mout.error("too many (over ", dst.size() , ") params, run out of keys with entry=" , entry );
361  }
362 
363  }
364 
365 
366  }
367 
368  /* OLTTI
369  bool acceptOrderedParams = true;
370  std::list<std::string>::const_iterator kit = keys.begin();
371 
372  for (const std::string & entry: entries){
373  size_t i=entry.find(equals);
374  if (i != std::string::npos){
375  setValue<std::map<std::string,T>, std::string, STRICT>(dst, entry.substr(0, i), entry.substr(i+1));
376  acceptOrderedParams = false;
377  }
378  else if (kit != keys.end()){
379  // Assignment-by-order
380  if (!acceptOrderedParams){
381  mout.warn("positional arg '" , entry , "' for [", *kit , "] given after explicit args" );
382  }
383  setValue<std::map<std::string,T>, std::string, STRICT>(dst, *kit, entry);
384  ++kit;
385  }
386  else {
387  //throw std::runtime_error(values + ": run out of positional args at '" + entry + "'");
388  }
389  }
390  */
391 
392  }
393 
400  template <class M>
401  static inline
402  void updateValues(M & dst, const std::list<std::string> & keys, const std::list<std::string> & entries, char equals='=') {
403  setValues<false>(dst, keys, entries, equals);
404  }
405 
406 
408 
418  template <class M, bool STRICT=true>
419  static
420  void setValues(M & dst, const std::string & values, char split=',', char equals='=') {
421  std::list<std::string> l;
422  drain::StringTools::split(values, l, split);
423  setValues(dst, l, equals);
424  }
425 
432  template <class M>
433  static inline
434  void updateValues(M & dst, const std::string & values, char split=',', char equals='=') {
435  setValues<false>(dst, values, split, equals);
436  }
437 
439 
446  template <class M, bool STRICT=true>
447  static
448  void setValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
449  std::list<std::string> l;
450  drain::StringTools::split(values, l, split);
451  setValues(dst, keys, l, equals);
452  }
453 
454 
462  template <class M>
463  static inline
464  void updateValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
465  setValues<false>(dst, keys, values, split, equals);
466  }
467 
469 
477  template <class M, class V, bool STRICT=true>
478  static
479  void setValues(M & dst, const std::list<std::string> & keys, std::initializer_list<V> values) {
480 
481  std::list<std::string>::const_iterator kit = keys.begin();
482 
483  for (const V & value: values){
484  if (kit == keys.end()){
485  throw std::runtime_error(std::string(__FILE__) + " run out of keys");
486  }
487  setValue(dst, *kit, value);
488  ++kit;
489  }
490  }
491 
498  template <class M, class V>
499  static
500  void setValues(M & dst, std::initializer_list<V> values) {
501 
502  //typename std::map<std::string,T>::const_iterator it = dst.begin();
503  typename M::const_iterator it = dst.begin();
504 
505  for (const V & value: values){
506  if (it == dst.end()){
507  throw std::runtime_error(std::string(__FILE__) + " run out of keys");
508  }
509  setValue(dst, it->first, value);
510  ++it;
511  }
512  }
513 
514  /*
515  template <class T, class T2>
516  static inline
517  void updateValues(std::map<std::string,T> & dst, const std::list<std::string> & keys, std::initializer_list<T2> values) {
518  setValues<false>(dst, keys, values);
519  }
520  */
521 
522 
523 };
524 
525 
526 
527 
528 } // drain
529 
530 
531 #endif // Drain
Definition: Castable.h:76
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
General purpose tools for handling values and keys of std::map<>
Definition: SmartMapTools.h:56
static const M::mapped_type & get(const M &m, const typename M::key_type &key)
If the key is found, the value is returned as a reference.
Definition: SmartMapTools.h:69
static void get(const M &m, const typename M::key_type &key, F &value)
If the key is found, the value is assigned.
Definition: SmartMapTools.h:90
A base class for smart maps providing methods for importing and exporting values, among others.
Definition: SmartMapTools.h:106
static void setValue(M &dst, const std::string &key, const V &value)
Utility for "guessing" key order. Derived classes will redefine this e.g. for ordered maps.
Definition: SmartMapTools.h:133
static void setValues(M &dst, std::initializer_list< V > values)
Definition: SmartMapTools.h:500
static void updateValues(M &dst, const std::map< std::string, S > &src)
Definition: SmartMapTools.h:205
static void updateCastableValues(M &dst, const std::map< std::string, S > &src)
Definition: SmartMapTools.h:215
static void updateValues(M &dst, const std::list< std::string > &keys, const std::list< std::string > &entries, char equals='=')
Definition: SmartMapTools.h:402
static void setValues(M &dst, const std::list< std::string > &values, char equalSign='=')
Assign values from list, accepting strict "<key>=<value>" format, no positional arguments.
Definition: SmartMapTools.h:227
static void setValues(M &dst, const std::map< std::string, S > &srcMap)
Definition: SmartMapTools.h:176
static void updateValue(M &dst, const std::string &key, const V &value)
Set value only if key exists.
Definition: SmartMapTools.h:166
static void updateValues(M &dst, const std::string &values, char split=',', char equals='=')
Definition: SmartMapTools.h:434
static void setValues(M &dst, const std::string &values, char split=',', char equals='=')
Assign values from string, assuming strict "<key>=<value>" format, no positional arguments.
Definition: SmartMapTools.h:420
static void setValues(M &dst, const std::list< std::string > &keys, const std::list< std::string > &entries, char assignmentSymbol='=')
Assign values from list, accepting keyword arguments <key>=,<key2>=<value2> and positional arguments...
Definition: SmartMapTools.h:292
static void setValues(M &dst, const std::list< std::string > &keys, std::initializer_list< V > values)
Assign values from string, accepting keyword arguments <key>=,<key2>=<value2> and positional argumen...
Definition: SmartMapTools.h:479
static void updateValues(M &dst, const std::list< std::string > &values, char equals='=')
Assign values from list, accepting strict "<key>=<value>" format, no positional arguments.
Definition: SmartMapTools.h:278
static void updateValues(M &dst, const std::list< std::string > &keys, const std::string &values, char split=',', char equals='=')
Definition: SmartMapTools.h:464
static void setValues(M &dst, const std::list< std::string > &keys, const std::string &values, char split=',', char equals='=')
Assign values from string, accepting keyword arguments <key>=,<key2>=<value2> and positional argumen...
Definition: SmartMapTools.h:448
static bool split2(const std::string &s, T1 &first, T2 &second, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
static void split(const std::string &s, T &sequence, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
Definition: String.h:309
VariableT is a final class applied through typedefs Variable, Reference and FlexibleVariable.
Definition: VariableT.h:87
Definition: DataSelector.cpp:1277