Loading...
Searching...
No Matches
MapTools.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#ifndef DRAIN_MAP_TOOLS_H
32#define DRAIN_MAP_TOOLS_H
33
34#include <iostream>
35#include <string>
36#include <set>
37#include <list>
38#include <vector>
39#include <map>
40// #include <stdlib.h>
41// #include <sys/syslog.h>
42// #include <syslog.h>
43
44#include "Log.h"
45#include "Sprinter.h"
46#include "StringTools.h"
47
48
49namespace drain {
50
52class MapTools {
53
54public:
55
57 template <class K,class V>
58 static inline
59 typename std::map<K,V>::const_iterator findEntryByKey(const std::map<K,V> & m, const K & key){
60 return m.find(key);
61 }
62
64 template <class K,class V>
65 static inline
66 typename std::list<K,V>::const_iterator findEntryByKey(const std::list<K,V> & l, const K & key){
67 for (typename std::list<K,V>::const_iterator it=l.begin(); it!=l.end(); ++it){
68 if (it->first == key){
69 return it;
70 }
71 }
72 return l.end();
73 }
74
75 template <class M>
76 static
77 bool hasKey(const M & m, const typename M::key_type & key){
78 typename M::const_iterator it = findEntryByKey(m, key);
79 return it != m.end();
80 }
81
82
84
90 template <class M>
91 static
92 const typename M::mapped_type & get(const M & m, const typename M::key_type & key){
93 typename M::const_iterator it = m.find(key);
94 if (it != m.end()){
95 return it->second;
96 }
97 else {
98 static const typename M::mapped_type empty;
99 return empty;
100 }
101 }
102
103 // NEW
104 template <class M>
105 static
106 typename M::mapped_type & get(M & m, const typename M::key_type & key){
107 return m[key];
108 }
109
110 /*
111 template <class M, class T>
112 static
113 const T & get(const M & m, const typename M::key_type & key, const T & defaultValue){ // todo: const char *
114 typename M::const_iterator it = m.find(key);
115 if (it != m.end()){
116 return static_cast<T>(it->second);
117 }
118 else {
119 return defaultValue;
120 //static const typename M::mapped_type empty;
121 //return empty;
122 }
123 }
124 */
125
126 // Universal (map and list compatible)
130 template <class M>
131 static
132 const typename M::value_type::second_type & get(const M & m, const typename M::value_type::first_type & key, const typename M::value_type::second_type & defaultValue){ // todo: const char *
133 typename M::const_iterator it = findEntryByKey(m, key);
134 if (it != m.end()){
135 return it->second;
136 }
137 else {
138 return defaultValue;
139 }
140 }
141
142 template <class M>
143 static
144 std::string get(const M & m, const typename M::key_type & key, const char * defaultValue){ // todo: const char *
145 typename M::const_iterator it = m.find(key);
146 if (it != m.end()){
147 //return static_cast<std::string>(it->second);
148 return it->second;
149 }
150 else {
151 return defaultValue;
152 //static const typename M::mapped_type empty;
153 //return empty;
154 }
155 }
156
157
158
159 typedef std::list<std::string> keylist_t;
160
161
162
164
168 template <class M,class V,bool STRICT=true>
169 static
170 void setValue(M & dst, const std::string & key, const V & value) {
171 if (STRICT){
172 dst[key] = value; // throws exception in derived classes!
173 }
174 else {
175 //typename std::map<std::string,T>::iterator it = dst.find(key);
176 typename M::iterator it = dst.find(key);
177 if (it != dst.end()){
178 it->second = value;
179 }
180 else {
181 //std::cerr << __FILE__ << ':' << __FUNCTION__ << ": key '" << key << "' not found\n";
182 }
183 }
184 }
185
186 template <class M,class V>
187 static inline
188 void setValue(M & dst, const std::string & key, const V & value, bool STRICT) {
189 if (STRICT)
190 setValue<M,V,true>(dst, key, value);
191 else
192 setValue<M,V,false>(dst, key, value);
193 }
194
195
197
201 template <class M,class V>
202 static inline
203 void updateValue(M & dst, const std::string & key, const V & value) {
204 setValue<M,V,false>(dst, key, value);
205 }
206
207
211 template <class M,class S,bool STRICT=true>
212 static
213 void setValues(M & dst, const std::map<std::string,S> & srcMap) {
214 // std::cerr << __FUNCTION__ << ':' << typeid(M).name() << " <= map<str," << typeid(S).name() << ">\n";
215 for (const typename std::map<std::string,S>::value_type & entry: srcMap){
216 setValue<M,S,STRICT>(dst, entry.first, entry.second);
217 }
218 }
219
220
221
222
227 template <class M,class S>
228 static inline
229 void updateValues(M & dst, const std::map<std::string,S> & src) {
230 setValues<M,S,false>(dst, src);
231 }
232
233
235
242 template <class M, bool STRICT=true>
243 static
244 void setValues(M & dst, const std::list<std::string> & values, char equalSign='=', const std::string & trimChars = "") {
245
246 const bool TRIM = !trimChars.empty();
247
248 for (const std::string & entry: values){
249
250 if (entry.empty()){
251
252 Logger mout(__FILE__, __FUNCTION__);
253 if (values.size()==1){
254 //std::cerr << __FILE__ << ':' << __
255 mout.experimental("clearing a map of ", dst.size(), " elements");
256 dst.clear();
257 return;
258 }
259 else {
260 mout.debug("parameter list contained an empty value (ok)");
261 continue;
262 }
263
264 }
265
266 const size_t i = entry.find(equalSign);
267 if (i != std::string::npos){
268 if (i == (entry.length()-1)){
269 if (TRIM){
270 setValue<M,std::string,STRICT>(dst, StringTools::trim(entry, trimChars), ""); // todo: touch
271 }
272 else {
273 setValue<M,std::string,STRICT>(dst, entry, ""); // todo: touch
274 }
275 }
276 else {
277 if (TRIM){
278 setValue<M,std::string,STRICT>(dst, StringTools::trim(entry.substr(0, i)), StringTools::trim(entry.substr(i+1)));
279 }
280 else {
281 setValue<M,std::string,STRICT>(dst, entry.substr(0, i), entry.substr(i+1));
282 }
283 }
284 }
285 else {
286 for (const std::string & e: values){
287 std::cerr << '"' << e << '"' << std::endl;
288 }
289 // TODO: warn dump
290 throw std::runtime_error(entry + ": positional args without keys");
291 }
292 }
293 }
294
295
296
298
303 template <class M>
304 static inline
305 void updateValues(M & dst, const std::list<std::string> & values, char equals='=') {
306 setValues<M,false>(dst, values, equals);
307 }
308
310
316 // Potential for allowed-keys-only policy (hidden/read-only entries)
317 template <class M, bool STRICT=true>
318 static
319 void setValues(M & dst, const std::list<std::string> & keys, const std::list<std::string> & entries, char assignmentChar='=') {
320
321 Logger mout(__FILE__, __FUNCTION__);
322
323
324 // 2026: use char in split2
325 //const std::string assignmentSymbols(1, assignmentSymbol);
326
327 std::list<std::string>::const_iterator kit = keys.begin();
328
329 bool acceptOrderedParams = true;
330
331 // mout.warn(" assignmentSymbol: " , assignmentSymbol );
332 // mout.warn(" size: " , this->size() );
333 for (const std::string & entry: entries){
334
335 //for (std::list<std::string>::const_iterator pit = p.begin(); pit != p.end(); ++pit){
336 //mout.warn(" entry: " , *pit );
337
338 // Check specific assignment, ie. check if the key=value is given explicitly.
339 if (assignmentChar){ // typically '='
340
341 std::string key, value;
342
343 //if (StringTools::split2(entry, key, value, assignmentSymbols)){
344 if (StringTools::split2(entry, key, value, assignmentChar)){
345
346 // mout.warn(" specified " , key , "=\t" , value );
347
348 if (dst.size()==1){
349 /*
350 * This special handling is for single-element maps
351 * "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
352 */
353 typename M::iterator it = dst.begin();
354 if (key == it->first)
355 it->second = value;
356 else {
357 it->second = entry;
358 // mout.warn("is this in use?" , it->first , " <= '" , entry , "'" );
359 }
360 return;
361 }
362
363 setValue<M,std::string,STRICT>(dst, key, value); //, criticality);
364 acceptOrderedParams = false;
365 continue;
366 }
367 else {
368 // mout.warn(" could not split: " , *pit );
369 }
370 }
371
372 // Key and assignment symbol not given.
373
374 if (kit != keys.end()){
375 // Assignment-by-order
376 if (!acceptOrderedParams){
377 mout.warn("positional arg '" , entry , "' for [", *kit , "] given after explicit args" );
378 }
379 //mout.warn(" ordered " , );
380 dst[*kit] = entry; // does not need to call import() because *kit exists.
381 ++kit; // NUEVO
382 }
383 else {
384 //mout.log(criticality)
385 // << "too many (over "<< this->size() << ") params, run out of keys with entry=" << *pit << mout.endl;
386 if (STRICT){
387 mout.warn(DRAIN_LOG(sprinter(entries)));
388 mout.warn(DRAIN_LOG(sprinter(keys)));
389 mout.warn(DRAIN_LOG(sprinter(dst)));
390 mout.error("too many (over ", dst.size() , ") params, run out of keys with entry=" , entry );
391 }
392
393 }
394
395
396 }
397
398
399 }
400
407 template <class M>
408 static inline
409 void updateValues(M & dst, const std::list<std::string> & keys, const std::list<std::string> & entries, char equals='=') {
410 setValues<false>(dst, keys, entries, equals);
411 }
412
413
415
425 template <class M, bool STRICT=true>
426 static
427 void setValues(M & dst, const std::string & values, char split=',', char equals='=', const std::string & trimChars = "") {
428 std::list<std::string> l;
429 drain::StringTools::split(values, l, split);
430 setValues<M,STRICT>(dst, l, equals, trimChars);
431 }
432
439 template <class M>
440 static inline
441 void updateValues(M & dst, const std::string & values, char split=',', char equals='=') {
442 setValues<false>(dst, values, split, equals);
443 }
444
446
453 template <class M, bool STRICT=true>
454 static
455 void setValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
456 std::list<std::string> l;
457 drain::StringTools::split(values, l, split);
458 setValues(dst, keys, l, equals);
459 }
460
461
469 template <class M>
470 static inline
471 void updateValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
472 setValues<false>(dst, keys, values, split, equals);
473 }
474
476
484 template <class M, class V, bool STRICT=true>
485 static
486 void setValues(M & dst, const std::list<std::string> & keys, std::initializer_list<V> values) {
487
488 std::list<std::string>::const_iterator kit = keys.begin();
489
490 for (const V & value: values){
491 if (kit == keys.end()){
492 throw std::runtime_error(std::string(__FILE__) + " run out of keys");
493 }
494 setValue(dst, *kit, value);
495 ++kit;
496 }
497 }
498
505 template <class M, class V>
506 static
507 void setValues(M & dst, std::initializer_list<V> values) {
508
509 //typename std::map<std::string,T>::const_iterator it = dst.begin();
510 typename M::const_iterator it = dst.begin();
511
512 for (const V & value: values){
513 if (it == dst.end()){
514 throw std::runtime_error(std::string(__FILE__) + " run out of keys");
515 }
516 setValue(dst, it->first, value);
517 ++it;
518 }
519 }
520
522 // Designed for: const std::initializer_list<std::pair<const char *,const char *> >
523 template <class M, typename K, typename V>
524 static
525 void setValues(M & dst, std::initializer_list<std::pair<K,V> > values) {
526 for (const auto & entry: values){
527 setValue(dst, entry.first, entry.second);
528 }
529 }
530
531
532 /*
533 template <class T, class T2>
534 static inline
535 void updateValues(std::map<std::string,T> & dst, const std::list<std::string> & keys, std::initializer_list<T2> values) {
536 setValues<false>(dst, keys, values);
537 }
538 */
539
540
541};
542
543
544
545
546} // drain
547
548
549#endif // Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:431
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:667
Logger & error(const TT &... args)
Echoes.
Definition Log.h:417
General purpose tools for handling values and keys of std::map<>
Definition MapTools.h:52
static void setValue(M &dst, const std::string &key, const V &value)
Set value of an element. If not STRICT, set only if key exists ie update.
Definition MapTools.h:170
static void setValues(M &dst, std::initializer_list< V > values)
Definition MapTools.h:507
static void updateValues(M &dst, const std::map< std::string, S > &src)
Definition MapTools.h:229
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 MapTools.h:244
static void updateValues(M &dst, const std::list< std::string > &keys, const std::list< std::string > &entries, char equals='=')
Definition MapTools.h:409
static void setValues(M &dst, const std::map< std::string, S > &srcMap)
Definition MapTools.h:213
static void updateValue(M &dst, const std::string &key, const V &value)
Set value only if key exists.
Definition MapTools.h:203
static std::list< K, V >::const_iterator findEntryByKey(const std::list< K, V > &l, const K &key)
Slow (exhaustive) search for std::list.
Definition MapTools.h:66
static void updateValues(M &dst, const std::string &values, char split=',', char equals='=')
Definition MapTools.h:441
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 MapTools.h:486
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 MapTools.h:305
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 MapTools.h:92
static void setValues(M &dst, const std::list< std::string > &keys, const std::list< std::string > &entries, char assignmentChar='=')
Assign values from list, accepting keyword arguments <key>=,<key2>=<value2> and positional arguments...
Definition MapTools.h:319
static void updateValues(M &dst, const std::list< std::string > &keys, const std::string &values, char split=',', char equals='=')
Definition MapTools.h:471
static void setValues(M &dst, std::initializer_list< std::pair< K, V > > values)
NEW 2025.
Definition MapTools.h:525
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 MapTools.h:427
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 MapTools.h:455
static std::map< K, V >::const_iterator findEntryByKey(const std::map< K, V > &m, const K &key)
Quick search for std::map.
Definition MapTools.h:59
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 StringTools.cpp:252
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 StringTools.h:487
Definition DataSelector.cpp:1277