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 
227  template <class M, bool STRICT=true>
228  static
229  void setValues(M & dst, const std::list<std::string> & values, char equalSign='=', const std::string & trimChars = "") {
230 
231  const bool TRIM = !trimChars.empty();
232 
233  for (const std::string & entry: values){
234 
235  if (entry.empty()){
236 
237  Logger mout(__FILE__, __FUNCTION__);
238  if (values.size()==1){
239  //std::cerr << __FILE__ << ':' << __
240  mout.experimental("clearing a map of ", dst.size(), " elements");
241  dst.clear();
242  return;
243  }
244  else {
245  mout.debug("parameter list contained an empty value (ok)");
246  continue;
247  }
248 
249  }
250 
251  const size_t i = entry.find(equalSign);
252  if (i != std::string::npos){
253  if (i == (entry.length()-1)){
254  if (TRIM){
255  setValue<M,std::string,STRICT>(dst, StringTools::trim(entry, trimChars), ""); // todo: touch
256  }
257  else {
258  setValue<M,std::string,STRICT>(dst, entry, ""); // todo: touch
259  }
260  }
261  else {
262  if (TRIM){
263  setValue<M,std::string,STRICT>(dst, StringTools::trim(entry.substr(0, i)), StringTools::trim(entry.substr(i+1)));
264  }
265  else {
266  setValue<M,std::string,STRICT>(dst, entry.substr(0, i), entry.substr(i+1));
267  }
268  }
269  }
270  else {
271  for (const std::string & e: values){
272  std::cerr << '"' << e << '"' << std::endl;
273  }
274  // TODO: warn dump
275  throw std::runtime_error(entry + ": positional args without keys");
276  }
277  }
278  }
279 
280 
281  template <class M, bool STRICT=true>
282  static
283  void setValues(M & dst, const std::initializer_list<Variable::init_pair_t > &l){
284  for (const auto & entry: l){
285  drain::SmartMapTools::setValue<M,Variable,STRICT>(dst, entry.first, entry.second);
286  }
287  }
288 
290 
295  template <class M>
296  static inline
297  void updateValues(M & dst, const std::list<std::string> & values, char equals='=') {
298  setValues<M,false>(dst, values, equals);
299  }
300 
302 
308  // Potential for allowed-keys-only policy (hidden/read-only entries)
309  template <class M, bool STRICT=true>
310  static
311  void setValues(M & dst, const std::list<std::string> & keys, const std::list<std::string> & entries, char assignmentSymbol='=') {
312 
313  Logger mout(__FILE__, __FUNCTION__);
314 
315 
316  const std::string assignmentSymbols(1, assignmentSymbol);
317 
318  //const std::list<std::string> & keys = getKeyList();
319  std::list<std::string>::const_iterator kit = keys.begin();
320 
321 
322  bool acceptOrderedParams = true;
323 
324  // mout.warn(" assignmentSymbol: " , assignmentSymbol );
325  // mout.warn(" size: " , this->size() );
326  for (const std::string & entry: entries){
327 
328  //for (std::list<std::string>::const_iterator pit = p.begin(); pit != p.end(); ++pit){
329  //mout.warn(" entry: " , *pit );
330 
331  // Check specific assignment, ie. check if the key=value is given explicitly.
332  if (assignmentSymbol){ // typically '='
333 
334  std::string key, value;
335 
336  if (StringTools::split2(entry, key, value, assignmentSymbols)){
337 
338  // mout.warn(" specified " , key , "=\t" , value );
339 
340  if (dst.size()==1){
341  /*
342  * This special handling is for single-element maps
343  * "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
344  */
345  typename M::iterator it = dst.begin();
346  if (key == it->first)
347  it->second = value;
348  else {
349  it->second = entry;
350  // mout.warn("is this in use?" , it->first , " <= '" , entry , "'" );
351  }
352  return;
353  }
354 
355  setValue<M,std::string,STRICT>(dst, key, value); //, criticality);
356  acceptOrderedParams = false;
357  continue;
358  }
359  else {
360  // mout.warn(" could not split: " , *pit );
361  }
362  }
363 
364  // Key and assignment symbol not given.
365 
366  if (kit != keys.end()){
367  // Assignment-by-order
368  if (!acceptOrderedParams){
369  mout.warn("positional arg '" , entry , "' for [", *kit , "] given after explicit args" );
370  }
371  //mout.warn(" ordered " , );
372  dst[*kit] = entry; // does not need to call import() because *kit exists.
373  ++kit; // NUEVO
374  }
375  else {
376  //mout.log(criticality)
377  // << "too many (over "<< this->size() << ") params, run out of keys with entry=" << *pit << mout.endl;
378  if (STRICT){
379  mout.error("too many (over ", dst.size() , ") params, run out of keys with entry=" , entry );
380  }
381 
382  }
383 
384 
385  }
386 
387  /* OLTTI
388  bool acceptOrderedParams = true;
389  std::list<std::string>::const_iterator kit = keys.begin();
390 
391  for (const std::string & entry: entries){
392  size_t i=entry.find(equals);
393  if (i != std::string::npos){
394  setValue<std::map<std::string,T>, std::string, STRICT>(dst, entry.substr(0, i), entry.substr(i+1));
395  acceptOrderedParams = false;
396  }
397  else if (kit != keys.end()){
398  // Assignment-by-order
399  if (!acceptOrderedParams){
400  mout.warn("positional arg '" , entry , "' for [", *kit , "] given after explicit args" );
401  }
402  setValue<std::map<std::string,T>, std::string, STRICT>(dst, *kit, entry);
403  ++kit;
404  }
405  else {
406  //throw std::runtime_error(values + ": run out of positional args at '" + entry + "'");
407  }
408  }
409  */
410 
411  }
412 
419  template <class M>
420  static inline
421  void updateValues(M & dst, const std::list<std::string> & keys, const std::list<std::string> & entries, char equals='=') {
422  setValues<false>(dst, keys, entries, equals);
423  }
424 
425 
427 
437  template <class M, bool STRICT=true>
438  static
439  void setValues(M & dst, const std::string & values, char split=',', char equals='=', const std::string & trimChars = "") {
440  std::list<std::string> l;
441  drain::StringTools::split(values, l, split);
442  setValues(dst, l, equals, trimChars);
443  }
444 
451  template <class M>
452  static inline
453  void updateValues(M & dst, const std::string & values, char split=',', char equals='=') {
454  setValues<false>(dst, values, split, equals);
455  }
456 
458 
465  template <class M, bool STRICT=true>
466  static
467  void setValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
468  std::list<std::string> l;
469  drain::StringTools::split(values, l, split);
470  setValues(dst, keys, l, equals);
471  }
472 
473 
481  template <class M>
482  static inline
483  void updateValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
484  setValues<false>(dst, keys, values, split, equals);
485  }
486 
488 
496  template <class M, class V, bool STRICT=true>
497  static
498  void setValues(M & dst, const std::list<std::string> & keys, std::initializer_list<V> values) {
499 
500  std::list<std::string>::const_iterator kit = keys.begin();
501 
502  for (const V & value: values){
503  if (kit == keys.end()){
504  throw std::runtime_error(std::string(__FILE__) + " run out of keys");
505  }
506  setValue(dst, *kit, value);
507  ++kit;
508  }
509  }
510 
517  template <class M, class V>
518  static
519  void setValues(M & dst, std::initializer_list<V> values) {
520 
521  //typename std::map<std::string,T>::const_iterator it = dst.begin();
522  typename M::const_iterator it = dst.begin();
523 
524  for (const V & value: values){
525  if (it == dst.end()){
526  throw std::runtime_error(std::string(__FILE__) + " run out of keys");
527  }
528  setValue(dst, it->first, value);
529  ++it;
530  }
531  }
532 
534  // Designed for: const std::initializer_list<std::pair<const char *,const char *> >
535  template <class M, typename K, typename V>
536  static
537  void setValues(M & dst, std::initializer_list<std::pair<K,V> > values) {
538  for (const auto & entry: values){
539  setValue(dst, entry.first, entry.second);
540  }
541  }
542 
543 
544  /*
545  template <class T, class T2>
546  static inline
547  void updateValues(std::map<std::string,T> & dst, const std::list<std::string> & keys, std::initializer_list<T2> values) {
548  setValues<false>(dst, keys, values);
549  }
550  */
551 
552 
553 };
554 
555 
556 
557 
558 } // drain
559 
560 
561 #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: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
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:519
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 setValues(M &dst, const std::list< std::string > &values, char equalSign='=', const std::string &trimChars="")
Assign values from list, accepting strict "<key>=<value>" format, no positional arguments.
Definition: SmartMapTools.h:229
static void updateValues(M &dst, const std::list< std::string > &keys, const std::list< std::string > &entries, char equals='=')
Definition: SmartMapTools.h:421
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:453
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:311
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:498
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:297
static void updateValues(M &dst, const std::list< std::string > &keys, const std::string &values, char split=',', char equals='=')
Definition: SmartMapTools.h:483
static void setValues(M &dst, std::initializer_list< std::pair< K, V > > values)
NEW 2025.
Definition: SmartMapTools.h:537
static void setValues(M &dst, const std::string &values, char split=',', char equals='=', const std::string &trimChars="")
Assign values from string, assuming strict "<key>=<value>" format, no positional arguments.
Definition: SmartMapTools.h:439
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:467
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 std::string trim(const std::string &s, const std::string &trimChars=" \t\n\r")
Returns a string without leading and trailing whitespace (or str undesired chars).
Definition: String.cpp:149
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:318
VariableT is a final class applied through typedefs Variable, Reference and FlexibleVariable.
Definition: VariableT.h:87
Definition: DataSelector.cpp:1277