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
423 template <class M, bool STRICT=true>
424 static
425 void setValues(M & dst, const std::string & values, char split=',', char equals='=', const std::string & trimChars = "") {
426 std::list<std::string> l;
427 drain::StringTools::split(values, l, split);
428 setValues<M,STRICT>(dst, l, equals, trimChars);
429 }
430
437 template <class M>
438 static inline
439 void updateValues(M & dst, const std::string & values, char split=',', char equals='=') {
440 setValues<false>(dst, values, split, equals);
441 }
442
444
451 template <class M, bool STRICT=true>
452 static
453 void setValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
454 std::list<std::string> l;
455 drain::StringTools::split(values, l, split);
456 setValues(dst, keys, l, equals);
457 }
458
459
467 template <class M>
468 static inline
469 void updateValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
470 setValues<false>(dst, keys, values, split, equals);
471 }
472
474
482 template <class M, class V, bool STRICT=true>
483 static
484 void setValues(M & dst, const std::list<std::string> & keys, std::initializer_list<V> values) {
485
486 std::list<std::string>::const_iterator kit = keys.begin();
487
488 for (const V & value: values){
489 if (kit == keys.end()){
490 throw std::runtime_error(std::string(__FILE__) + " run out of keys");
491 }
492 setValue(dst, *kit, value);
493 ++kit;
494 }
495 }
496
503 template <class M, class V>
504 static
505 void setValues(M & dst, std::initializer_list<V> values) {
506
507 //typename std::map<std::string,T>::const_iterator it = dst.begin();
508 typename M::const_iterator it = dst.begin();
509
510 for (const V & value: values){
511 if (it == dst.end()){
512 throw std::runtime_error(std::string(__FILE__) + " run out of keys");
513 }
514 setValue(dst, it->first, value);
515 ++it;
516 }
517 }
518
520 // Designed for: const std::initializer_list<std::pair<const char *,const char *> >
521 template <class M, typename K, typename V>
522 static
523 void setValues(M & dst, std::initializer_list<std::pair<K,V> > values) {
524 for (const auto & entry: values){
525 setValue(dst, entry.first, entry.second);
526 }
527 }
528
529
530 /*
531 template <class T, class T2>
532 static inline
533 void updateValues(std::map<std::string,T> & dst, const std::list<std::string> & keys, std::initializer_list<T2> values) {
534 setValues<false>(dst, keys, values);
535 }
536 */
537
538
539};
540
541
542
543
544} // drain
545
546
547#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: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:505
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:439
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:484
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 <key>=,<key2>=<value2> and positional arguments...
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:469
static void setValues(M &dst, std::initializer_list< std::pair< K, V > > values)
NEW 2025.
Definition MapTools.h:523
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:425
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:453
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:251
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