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