Loading...
Searching...
No Matches
SmartMap.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 SMARTMAP_H
32#define SMARTMAP_H
33
34#include <drain/Log.h>
35#include <iostream>
36#include <string>
37#include <list>
38#include <map>
39#include <syslog.h>
40
41#include <drain/SmartMapTools.h>
42#include <drain/Sprinter.h>
43#include <drain/StringTools.h>
44
45
46
47// TODO: use SmartMapTools for assignments
48
49namespace drain {
50
52
61template<class T>
62class SmartMap : public std::map<std::string, T> {
63
64public:
65
66 typedef SmartMap<T> smap_t;
67
68 typedef std::map<std::string, T> map_t;
69 typedef typename map_t::key_type key_t;
70 typedef typename map_t::mapped_type value_t; // == T
71 typedef typename map_t::value_type entry_t; // pair<key_t,value_t>
72
73 typedef std::list<std::string> keylist_t;
74
76 typedef typename map_t::iterator iterator;
77 typedef typename map_t::const_iterator const_iterator;
78
79
82
85
90 inline
92
93 // Copy constructor. Does not copy items.
96 // TODO: CHECK: -Wdeprecated-copy fires because this copy constructor is user-declared but
97 // operator= is not; the implicit copy-assignment operator does a full memberwise/base copy
98 // (i.e. it DOES copy items, via std::map's own operator=), which is inconsistent with this
99 // constructor's documented "does not copy items" behavior. Confirm whether that asymmetry
100 // between construction and assignment is intentional.
101 inline
102 SmartMap(const SmartMap & smap) : separator(smap.separator), arraySeparator(smap.arraySeparator){};
103
104
105 virtual
106 inline
107 ~SmartMap(){};
108
109
110 virtual inline
111 void clear(){
112 map_t::clear();
113 keyList.clear();
114 }
115
116 inline
117 bool hasKey(const std::string &key) const {
118 return (this->find(key) != this->end());
119 }
120
122
127 inline
128 std::string get(const std::string &key, const std::string & defaultValue) const {
129 const_iterator it = this->find(key);
130 if (it == this->end())
131 return defaultValue;
132 else {
133 // return static_cast<std::string>(it->second); DOES NOT WORK, http://stackoverflow.com/questions/7741531/conversion-operator-template-specialization
134 return it->second;
135 }
136 }
137
138
139 inline
140 std::string get(const std::string & key, const char *defaultValue) const {
141 return get(key, std::string(defaultValue));
142 }
143
144
146
151 template <class T2>
152 T2 get(const std::string &key, const T2 &defaultValue) const { //T2 defaultValue) const {
153 const_iterator it = this->find(key);
154 if (it == this->end())
155 return defaultValue;
156 else
157 return static_cast<T2>(it->second);
158 }
159
161
166 inline
167 virtual
168 T & operator[](const std::string &key){
169
170 iterator it = this->find(key);
171 if (it != this->end()) {
172 return it->second;
173 }
174 else {
175 // Create:
176 keyList.push_back(key);
177 T & element = map_t::operator[](key);
178 //element.setSeparator(arraySeparator);
179 return element;
180 }
181 }
182
184 inline
185 virtual
186 const T & operator[](const std::string &key) const {
187
188 const_iterator it = this->find(key);
189 if (it != this->end()) {
190 return it->second;
191 }
192 else {
193 static const T empty;
194 return empty;
195 }
196 }
197
198
200 virtual inline
201 const keylist_t & getKeyList() const {
202 return keyList;
203 }
204
205
206 inline
207 const map_t & getMap() const { // ? but templated on \c T ?
208 return *this;
209 };
210
212 template <class T2>
213 void exportMap(std::map<std::string,T2> & m) const {
214 for (const_iterator it = this->begin(); it != this->end(); ++it)
215 m[it->first] = it->second;
216 }
217
219 /*
220 template <class V,bool STRICT=false> // TODO: true...
221 //void importEntry(const std::string & key, const T2 & value, bool updateOnly = true){
222 void importEntry(const std::string & key, const V & value){ //, bool updateOnly = true) { //, unsigned int criticality = LOG_DEBUG){
223 */
224
228 template <bool STRICT=true>
229 inline
230 void importEntries(const std::string & entries, char assignmentChar='=', char separatorChar=0); // { //, bool updateOnly = false);
231 // MapTools::setValues<smap_t,STRICT>(*this, entries, separatorChar, assignmentChar); // const std::string & trimChars = ""
232 //}
233 //, unsigned int criticality = LOG_ERR);
234
235
240 template <bool STRICT=true>
241 void importEntries(const std::list<std::string> & entries, char assignmentChar='='){ //; //, bool updateOnly = false);
242 //SmartMapTools::setValues<T,STRICT>(*this, getKeyList(), entries, assignmentChar);
243 MapTools::setValues<smap_t,STRICT>(*this, getKeyList(), entries, assignmentChar);
244 }
245
247
252 template <class S,bool STRICT=true>
253 void importMap(const std::map<std::string,S> & m){ //, bool updateOnly = false){ //, unsigned int criticality = LOG_ERR){
254 // SmartMapTools::setValues<map_t,S,STRICT>(*this, m);
255 // SmartMapTools::setValues(*this, m);
256 MapTools::setValues<smap_t,S,STRICT>(*this, m);
257 //new
258 //for (typename std::map<std::string,S>::const_iterator it = m.begin(); it != m.end(); ++it)
259 // importEntry(it->first, it->second); //, updateOnly); //, criticality); // false);
260
261 }
262
264
269 template <class T2,bool STRICT=true>
270 void importCastableMap(const drain::SmartMap<T2> & m){ //, bool updateOnly = false, unsigned int criticality = LOG_ERR){
271 SmartMapTools::setCastableValues<smap_t,T2,STRICT>(*this, m);
272 }
273
274
275
277
280 template <class T2>
281 inline
282 void updateFromMap(const std::map<std::string,T2> & m){
283 importMap<T2,false>(m); //, LOG_DEBUG);
284 }
285
287 template <class T2>
288 inline
290 importCastableMap<T2,false>(m); //, true);
291 // for (typename SmartMap<T2>::const_iterator it = m.begin(); it != m.end(); ++it)
292 // importEntry(it->first, (const Castable &)it->second, LOG_DEBUG); //true);
293 }
294
295
297 // TODO: consider: std::string assignmentChars="=:", std::string separatorChars=", ", std::string trimChars=" \t\n\r",
298 inline
299 void setValues(const std::string & entries, char assignmentChar='=', char separatorChar=0){ // char separatorChar=','
300 importEntries<true>(entries, assignmentChar, separatorChar); //, false); //, LOG_ERR);
301 }
302
303 inline
304 void setValues(const char * entries, char assignmentChar='=', char separatorChar=0){
305 importEntries<true>(entries, assignmentChar, separatorChar); //, false); //, LOG_ERR);
306 }
307
308 // status?
309 template <class S>
310 void setValuesSEQ(const S & sequence);
311
313 inline
314 void updateValues(const std::string & entries, char assignmentChar='=', char separatorChar=0){// char separatorChar=','
315 importEntries<false>(entries, assignmentChar, separatorChar); //, true); //, LOG_DEBUG);
316 }
317
318
319 inline
320 void getKeys(std::ostream &ostr) const {
321
322 const keylist_t & l = getKeyList();
323 for (keylist_t::const_iterator it = l.begin(); it != l.end(); ++it ){
324 if (it != l.begin())
325 ostr << ',';
326 ostr << *it;
327 }
328
329 }
330
332 inline
333 std::string getKeys() const {
334 std::stringstream s;
335 getKeys((std::ostream &)s);
336 return s.str();
337 };
338
340 inline
341 void getValues(std::ostream &ostr) const {
342
343 const keylist_t & l = getKeyList();
344 for (keylist_t::const_iterator it = l.begin(); it != l.end(); ++it ){
345 if (it != l.begin())
346 ostr << ',';
347 if (this->find(*it) != this->end())
348 ostr << (*this)[*it]; // << this->find(*it).getType();
349 else {
350 ostr << "*SMARTMAP::FAIL* " << __FUNCTION__;
351 }
352 }
353
354 }
355
357 inline
358 std::string getValues() const {
359 std::stringstream s;
360 getValues(s);
361 return s.str();
362 };
363
364
366 /*
367 * \param equal - typically =, :, or -
368 * \param start - typically hyphen or leading parenthesis (, {, [
369 * \param end - typically hyphen or trailing parenthesis ), }, [
370 * \param separator - typically comma or semicolon
371 */
372 // template <class S>
373 // S & toStream(S & ostr, char equal='=', char startChar=0, char endChar=0, char separatorChar=0) const;
374 std::ostream & toStream(std::ostream & ostr, char equal='=', char startChar='{', char endChar='}', char separatorChar=',') const {
375 //drain::TypeLayout pairLayout(equal);
376 drain::TypeLayout mainLayout(startChar, separatorChar, endChar);
378 //layout.pairChars.separator = equal;
379 layout.pairChars.separator = equal;
380 //layout.arrayChars.setLayout();
381 return Sprinter::sequenceToStream(ostr, getMap(), mainLayout, layout);
382 //return Sprinter::sequenceToStream(ostr, vmap.getMap(), layout.mapChars, layout);
383 //return Sprinter::mapToStream(ostr, *this, Sprinter::jsonLayout, this->getKeyList());
384 }
385
386 //std::string toStr(char equal='=', char start='{', char end='}', char separator=0) const {
387 std::string toStr(char equal='=', char start=0, char end=0, char separator=0) const {
388 std::stringstream sstr;
389 toStream(sstr, equal, start, end, separator);
390 return sstr.str();
391 }
392
394 //void toJSON(std::ostream & ostr = std::cout, size_t indent = 0) const;
395
397 // void valuesToJSON(std::ostream & ostr = std::cout) const;
398
400 void dump(std::ostream & ostr = std::cout) const;
401
402
403
405 // ?? If specific, allows also "key=value,key1=value2,...".
417 // \param updateOnly - if true, skip non-existing entries silently
418 //void assignEntries2(const std::string & entries, bool updateOnly = false, char assignmentChar='=', char separatorChar=0){
419
420protected:
421
422
424 // std::list<std::string> orderedKeyList;
425
426 mutable std::list<std::string> keyList;
427
428};
429
430
431// to be Replaced by MapTools:
432// MapTools::setValues<smap_t,STRICT>(*this, entries, separatorChar, assignmentChar);
433template <class T>
434template <bool STRICT>
435void SmartMap<T>::importEntries(const std::string & entries, char assignmentChar, char separatorChar){ //, bool updateOnly){
436
437 // void importEntries(const std::string & entries, char assignmentChar='=', char separatorChar=0);
438
439 Logger mout(__FILE__, __FUNCTION__);
440 //mout.debug(10) << entries << mout.endl;
441
442 if (entries.empty()){ //old
443 return;
444 }
445
446
447 separatorChar = separatorChar ? separatorChar : separator;
448
449 std::list<std::string> l;
450 drain::StringTools::split(entries, l, separatorChar);
451 MapTools::setValues<smap_t,STRICT>(*this, this->getKeyList(), l, assignmentChar);
452
453 /*
454 // Input parameter assignments, separated by the separator: "a=1", "b=2", "c=3", ...
455 std::list<std::string> p;
456 // separatorChar = separatorChar ? separatorChar : separator;
457 if (separatorChar)
458 drain::StringTools::split(entries, p, std::string(1, separatorChar)); // separators);
459 else {
460 // no separator => single-param cmd, BUT explicit key=value possible
461 // mout.warn("push back entries:" , entries );
462 p.push_back(entries);
463 }
464 importEntries<STRICT>(p, assignmentChar);
465 */
466}
467
468
469/*
470
471template <class T>
472template <bool STRICT>
473void SmartMap<T>::importEntries(const std::list<std::string> & p, char assignmentChar){ // , bool updateOnly){
474
475 Logger mout(__FILE__, __FUNCTION__);
476
477 // NUEVO3 SmartMapTools::setValues<T,STRICT>(*this, p, assignmentChar);
478
479 //SmartMapTools::setValues<T,STRICT>(*this, getKeyList(), p, assignmentChar);
480
481 const std::string assignmentChars(1, assignmentChar);
482
483 const std::list<std::string> & keys = getKeyList();
484 std::list<std::string>::const_iterator kit = keys.begin();
485
486
487 bool acceptOrderedParams = true;
488
489 // mout.warn(" assignmentChar: " , assignmentChar );
490 // mout.warn(" size: " , this->size() );
491
492 for (std::list<std::string>::const_iterator pit = p.begin(); pit != p.end(); ++pit){
493
494 //mout.warn(" entry: " , *pit );
495
496 // Check specific assignment, ie. check if the key=value is given explicitly.
497 if (assignmentChar){ // typically '='
498 std::string key;
499 std::string value;
500 if (StringTools::split2(*pit, key, value, assignmentChars)){
501 // mout.warn(" specified " , key , "=\t" , value );
502 if (this->size()==1){
503 iterator it = this->begin();
504 if (key == it->first)
505 it->second = value;
506 else
507 it->second = *pit;
508 return;
509 }
510
511 importEntry<std::string,STRICT>(key, value); //, criticality);
512 acceptOrderedParams = false;
513 continue;
514 }
515 else {
516 // mout.warn(" could not split: " , *pit );
517 }
518 }
519
520 // Key and assignment symbol not given.
521
522 if (kit != keys.end()){
523 // Assignment-by-order
524 if (!acceptOrderedParams){
525 mout.warn("positional arg '" , *pit , "' for [", *kit , "] given after explicit args" );
526 }
527 //mout.warn(" ordered " , );
528 (*this)[*kit] = *pit; // does not need to call import() because *kit exists.
529 ++kit; // NUEVO
530 }
531 else {
532 //mout.log(criticality)
533 // << "too many (over "<< this->size() << ") params, run out of keys with entry=" << *pit << mout.endl;
534 if (STRICT){
535 mout.error("too many (over ", this->size() , ") params, run out of keys with entry=" , *pit );
536 }
537
538 }
539
540 }
541
542}
543*/
544
545
546template <class T>
547template <class S>
548void SmartMap<T>::setValuesSEQ(const S & sequence){
549
550 Logger log(__FILE__, __FUNCTION__);
551
552 const std::list<std::string> & keys = getKeyList();
553 std::list<std::string>::const_iterator kit = keys.begin();
554
555 for (typename S::const_iterator it = sequence.begin(); it != sequence.end(); ++it){
556
557 if (kit != keys.end()){
558 // Assignment-by-order
559 (*this)[*kit] = *it; // does not need to call import() because *kit exists.
560 ++kit; // NUEVO
561 }
562 else {
563 log.error() << "too many ("<< sequence.size() << ") params for map of size ("<< this->size() << "), run out of keys with entry=" << *it << log.endl;
564 }
565
566 }
567
568}
569
570/*
571template <class T>
572std::ostream & SmartMap<T>::toStream(std::ostream & ostr, char equal, char startChar, char endChar, char separatorChar) const {
573
574 // Otherways ok, but key order not used: Sprinter::sequenceToStream(ostr, *this, Sprinter::jsonLayout);
575 //return Sprinter::mapToStream(ostr, *this, Sprinter::jsonLayout, this->getKeyList());
576
577
578 const std::list<std::string> & keys = this->getKeyList();
579
580 separatorChar = separatorChar ? separatorChar : this->separator;
581 //separatorChar = separatorChar ? separatorChar : ','; // needed?
582 char sep = 0;
583
584 for (std::list<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it){
585
586 if (sep){
587 //if (it != keys.begin())
588 ostr << sep;
589 }
590 else {
591 sep = separator;
592 }
593
594 ostr << *it << equal;
595 if (startChar)
596 ostr << startChar;
597 ostr << (*this)[*it];
598 if (endChar)
599 ostr << endChar;
600
601 }
602}
603 */
604
605/*
606template <class T>
607void SmartMap<T>::toJSON(std::ostream & ostr, size_t indent) const {
608
609 const std::string space(indent, ' ');
610
611 char sep = 0;
612 ostr << "{\n";
613
614 // NOTE: alphabetic order. Should JSON dump have orig. order?
615 for (const_iterator it = this->begin(); it != this->end(); ++it){
616
617 const std::string & key = it->first;
618 const T & item = it->second; //(*this)[key];
619
620 if (sep){
621 ostr << sep;
622 ostr << '\n';
623 }
624 else {
625 sep = ',';
626 }
627 //ostr << '\n';
628 ostr << space << "\"" << key << "\" : ";
629
630 //if (item.getType() == typeid(std::string)){
631 if (item.T::isString()){
632 //
633 ostr << '"';
634 // ostr << '"' << item.getCharArray() << '"';
635 const char *c = item.getCharArray();
636 while (*c != '\0'){
637 if (*c == '"')
638 ostr << '\\'; // TODO; implement also \n \t ...
639 ostr << *c;
640 ++c;
641 }
642 ostr << '"';
643 //ostr << '"' << item << '"';
644 }
645 else {
646 switch (item.T::getElementCount()) {
647 case 0:
648 ostr << '[' << ']'; // or NaN?
649 break;
650 case 1:
651 ostr << item;
652 break;
653 default:
654 Sprinter::toStream(ostr, item, Sprinter::plainLayout);
655 // JSONwriter::toStream(item, ostr); // Better! Forces commas.
656 // ostr << '[' << item << ']';
657 }
658 }
659 }
660 // ostr << "{\n \"value\":" << *this << ",\n";
661 // ostr << " \"type\":" << drain::Type::getTypeChar(getType()) << ",\n";
662 ostr << "\n" << space << "}\n"; // \n needed?
663}
664
665template <class T>
666void SmartMap<T>::valuesToJSON(std::ostream & ostr) const {
667
668
669 char sep = 0;
670
671 if (this->size() > 1)
672 ostr << "[";
673
674 // NOTE: alphabetic order. Should JSON dump have orig. order?
675 for (const_iterator it = this->begin(); it != this->end(); ++it){
676
677 //const std::string & key = it->first;
678 const T & item = it->second; //(*this)[key];
679
680 if (sep){
681 ostr << sep;
682 ostr << ' ';
683 }
684 else {
685 sep = ',';
686 }
687
688 if (item.T::isString()){
689 ostr << '"';
690 const char *c = item.getCharArray();
691 while (*c != '\0'){
692 if (*c == '"')
693 ostr << '\\'; // TODO; implement also \n \t ...
694 ostr << *c;
695 ++c;
696 }
697 ostr << '"';
698 //ostr << '"' << item << '"';
699 }
700 else {
701 switch (item.T::getElementCount()) {
702 case 0:
703 ostr << '[' << ']'; // or NaN?
704 break;
705 case 1:
706 ostr << item;
707 break;
708 default:
709 ostr << '[' << item << ']';
710 }
711 }
712
713 }
714
715 if (this->size() > 1)
716 ostr << "]";
717
718}
719*/
720
721
722template <class T>
723void SmartMap<T>::dump(std::ostream & ostr) const {
724
725 //const std::string space(indent, ' ');
726 for (const_iterator it = this->begin(); it != this->end(); ++it){
727 ostr << it->first << ':' << ' ';
728 it->second.info(ostr);
729 ostr << '\n';
730 }
731
732}
733
734template<class T>
735std::ostream &operator<<(std::ostream &ostr, const SmartMap<T> & m){
736 m.toStream(ostr, '=', 0, 0, m.separator);
737 return ostr;
738}
739
740/*
741template <class T>
742//template <>
743inline
744std::ostream & Sprinter::toStream(std::ostream & ostr, const SmartMap<T> & smap, const SprinterLayout & layout){
745 return Sprinter::mapToStream(ostr, smap.getMap(), layout, smap.getKeys());
746}
747*/
748
749} // drain
750
751
752#endif // Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
A base class for smart maps providing methods for importing and exporting values, among others.
Definition SmartMap.h:62
map_t::iterator iterator
Needed?
Definition SmartMap.h:76
void importEntries(const std::list< std::string > &entries, char assignmentChar='=')
Definition SmartMap.h:241
char arraySeparator
Default separator character for array elements (std::vector's)
Definition SmartMap.h:84
std::string getKeys() const
Convenience function for std::string output.
Definition SmartMap.h:333
std::list< std::string > keyList
Assigns values from std::string of type "value,value2,...valueN".
Definition SmartMap.h:426
virtual const T & operator[](const std::string &key) const
Unlike with std::map, operator[] const is defined, returning reference to a static empty instance.
Definition SmartMap.h:186
char separator
Default character used for splitting input and output. See setValues.
Definition SmartMap.h:81
virtual const keylist_t & getKeyList() const
Derived versions may produce an ordered set of keys.
Definition SmartMap.h:201
void importCastableMap(const drain::SmartMap< T2 > &m)
Assign values from a map, possibly extending the map.
Definition SmartMap.h:270
std::string getValues() const
Convenience function for std::string output.
Definition SmartMap.h:358
void exportMap(std::map< std::string, T2 > &m) const
Copies the contents to another map.
Definition SmartMap.h:213
virtual T & operator[](const std::string &key)
Returns an element. Creates one, conditionally.
Definition SmartMap.h:168
void getValues(std::ostream &ostr) const
Dumps the values.
Definition SmartMap.h:341
void updateFromMap(const std::map< std::string, T2 > &m)
Assign values from a map. Updates existing entries only.
Definition SmartMap.h:282
void updateFromCastableMap(const drain::SmartMap< T2 > &m)
Convenience.
Definition SmartMap.h:289
void importEntries(const std::string &entries, char assignmentChar='=', char separatorChar=0)
Assigns a value to given key; if the entry does not exist, tries to create it with directly with oper...
Definition SmartMap.h:435
std::string get(const std::string &key, const std::string &defaultValue) const
Retrieves a value, or default value if value is unset.
Definition SmartMap.h:128
void updateValues(const std::string &entries, char assignmentChar='=', char separatorChar=0)
Sets applicable values ie. modifies existing entries only. In ordered maps, skips extra entries silen...
Definition SmartMap.h:314
void dump(std::ostream &ostr=std::cout) const
Write map as a JSON code.
Definition SmartMap.h:723
T2 get(const std::string &key, const T2 &defaultValue) const
Retrieves a value, if set, else returns the given default value.
Definition SmartMap.h:152
SmartMap(char separator='\0', char arraySeparator=':')
Definition SmartMap.h:91
std::ostream & toStream(std::ostream &ostr, char equal='=', char startChar='{', char endChar='}', char separatorChar=',') const
Note: parameters discarded.
Definition SmartMap.h:374
void setValues(const std::string &entries, char assignmentChar='=', char separatorChar=0)
Sets values. If strictness==STRICTLY_CLOSED, throws exception if tries to assign a non-existing entry...
Definition SmartMap.h:299
void importMap(const std::map< std::string, S > &m)
Assign values from a map, overriding existing entries.
Definition SmartMap.h:253
static std::ostream & sequenceToStream(std::ostream &ostr, const T &x, const SprinterLayout &layout)
Convenience: if sequence type (array, list, set, map) not given, assume array.
Definition Sprinter.h:324
static const SprinterLayout jsonLayout
Resembles JSON structure: {"a":1,"b":22,"c":3}.
Definition Sprinter.h:224
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
Definition Sprinter.h:136
Definition Sprinter.h:79