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.error("too many (over ", dst.size() , ") params, run out of keys with entry=" , entry );
388 }
389
390 }
391
392
393 }
394
395
396 }
397
404 template <class M>
405 static inline
406 void updateValues(M & dst, const std::list<std::string> & keys, const std::list<std::string> & entries, char equals='=') {
407 setValues<false>(dst, keys, entries, equals);
408 }
409
410
412
422 template <class M, bool STRICT=true>
423 static
424 void setValues(M & dst, const std::string & values, char split=',', char equals='=', const std::string & trimChars = "") {
425 std::list<std::string> l;
426 drain::StringTools::split(values, l, split);
427 setValues<M,STRICT>(dst, l, equals, trimChars);
428 }
429
436 template <class M>
437 static inline
438 void updateValues(M & dst, const std::string & values, char split=',', char equals='=') {
439 setValues<false>(dst, values, split, equals);
440 }
441
443
450 template <class M, bool STRICT=true>
451 static
452 void setValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
453 std::list<std::string> l;
454 drain::StringTools::split(values, l, split);
455 setValues(dst, keys, l, equals);
456 }
457
458
466 template <class M>
467 static inline
468 void updateValues(M & dst, const std::list<std::string> & keys, const std::string & values, char split=',', char equals='=') {
469 setValues<false>(dst, keys, values, split, equals);
470 }
471
473
481 template <class M, class V, bool STRICT=true>
482 static
483 void setValues(M & dst, const std::list<std::string> & keys, std::initializer_list<V> values) {
484
485 std::list<std::string>::const_iterator kit = keys.begin();
486
487 for (const V & value: values){
488 if (kit == keys.end()){
489 throw std::runtime_error(std::string(__FILE__) + " run out of keys");
490 }
491 setValue(dst, *kit, value);
492 ++kit;
493 }
494 }
495
502 template <class M, class V>
503 static
504 void setValues(M & dst, std::initializer_list<V> values) {
505
506 //typename std::map<std::string,T>::const_iterator it = dst.begin();
507 typename M::const_iterator it = dst.begin();
508
509 for (const V & value: values){
510 if (it == dst.end()){
511 throw std::runtime_error(std::string(__FILE__) + " run out of keys");
512 }
513 setValue(dst, it->first, value);
514 ++it;
515 }
516 }
517
519 // Designed for: const std::initializer_list<std::pair<const char *,const char *> >
520 template <class M, typename K, typename V>
521 static
522 void setValues(M & dst, std::initializer_list<std::pair<K,V> > values) {
523 for (const auto & entry: values){
524 setValue(dst, entry.first, entry.second);
525 }
526 }
527
528
529 /*
530 template <class T, class T2>
531 static inline
532 void updateValues(std::map<std::string,T> & dst, const std::list<std::string> & keys, std::initializer_list<T2> values) {
533 setValues<false>(dst, keys, values);
534 }
535 */
536
537
538};
539
540
541
542
543} // drain
544
545
546#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:504
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:406
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:438
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:483
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:468
static void setValues(M &dst, std::initializer_list< std::pair< K, V > > values)
NEW 2025.
Definition MapTools.h:522
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:424
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:452
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:482
Definition DataSelector.cpp:1277