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 <set>
38#include <list>
39#include <vector>
40#include <map>
41#include <sys/syslog.h>
42#include <syslog.h>
43
44#include <drain/Castable.h>
45#include <drain/SmartMapTools.h>
46#include <drain/Sprinter.h>
47#include <drain/String.h>
48
49
50
51// TODO: use SmartMapTools for assignments
52
53namespace drain {
54
56
65template<class T>
66class SmartMap : public std::map<std::string, T> {
67
68public:
69
70 typedef SmartMap<T> smap_t;
71
72 typedef std::map<std::string, T> map_t;
73 typedef typename map_t::key_type key_t;
74 typedef typename map_t::mapped_type value_t; // == T
75 typedef typename map_t::value_type entry_t; // pair<key_t,value_t>
76
77 typedef std::list<std::string> keylist_t;
78
80 typedef typename map_t::iterator iterator;
81 typedef typename map_t::const_iterator const_iterator;
82
83
86
89
94 inline
96
97 // Copy constructor. Does not copy items.
100 inline
101 SmartMap(const SmartMap & smap) : separator(smap.separator), arraySeparator(smap.arraySeparator){};
102
103
104 virtual
105 inline
106 ~SmartMap(){};
107
108
109 virtual inline
110 void clear(){
111 map_t::clear();
112 keyList.clear();
113 }
114
115 inline
116 bool hasKey(const std::string &key) const {
117 return (this->find(key) != this->end());
118 }
119
121
126 inline
127 std::string get(const std::string &key, const std::string & defaultValue) const {
128 const_iterator it = this->find(key);
129 if (it == this->end())
130 return defaultValue;
131 else {
132 // return static_cast<std::string>(it->second); DOES NOT WORK, http://stackoverflow.com/questions/7741531/conversion-operator-template-specialization
133 return it->second;
134 }
135 }
136
137
138 inline
139 std::string get(const std::string & key, const char *defaultValue) const {
140 return get(key, std::string(defaultValue));
141 }
142
143
145
150 template <class T2>
151 T2 get(const std::string &key, const T2 &defaultValue) const { //T2 defaultValue) const {
152 const_iterator it = this->find(key);
153 if (it == this->end())
154 return defaultValue;
155 else
156 return static_cast<T2>(it->second);
157 }
158
160
165 inline
166 virtual
167 T & operator[](const std::string &key){
168
169 iterator it = this->find(key);
170 if (it != this->end()) {
171 return it->second;
172 }
173 else {
174 // Create:
175 keyList.push_back(key);
176 T & element = map_t::operator[](key);
177 //element.setSeparator(arraySeparator);
178 return element;
179 }
180 }
181
183 inline
184 virtual
185 const T & operator[](const std::string &key) const {
186
187 const_iterator it = this->find(key);
188 if (it != this->end()) {
189 return it->second;
190 }
191 else {
192 static const T empty;
193 return empty;
194 }
195 }
196
197
199 virtual inline
200 const keylist_t & getKeyList() const {
201 return keyList;
202 }
203
204
205 inline
206 const map_t & getMap() const {
207 return *this;
208 };
209
211 template <class T2>
212 void exportMap(std::map<std::string,T2> & m) const {
213 for (const_iterator it = this->begin(); it != this->end(); ++it)
214 m[it->first] = it->second;
215 }
216
218
221 /*
222 template <class V,bool STRICT=false> // TODO: true...
223 //void importEntry(const std::string & key, const T2 & value, bool updateOnly = true){
224 void importEntry(const std::string & key, const V & value){ //, bool updateOnly = true) { //, unsigned int criticality = LOG_DEBUG){
225 */
226
230 template <bool STRICT=true>
231 void importEntries(const std::string & entries, char assignmentSymbol='=', char separatorSymbol=0); //, bool updateOnly = false);
232 //, unsigned int criticality = LOG_ERR);
233
234
239 template <bool STRICT=true>
240 void importEntries(const std::list<std::string> & entries, char assignmentSymbol='='){ //; //, bool updateOnly = false);
241 //SmartMapTools::setValues<T,STRICT>(*this, getKeyList(), entries, assignmentSymbol);
242 SmartMapTools::setValues<smap_t,STRICT>(*this, getKeyList(), entries, assignmentSymbol);
243 }
244
246
251 template <class S,bool STRICT=true>
252 void importMap(const std::map<std::string,S> & m){ //, bool updateOnly = false){ //, unsigned int criticality = LOG_ERR){
253 // SmartMapTools::setValues<map_t,S,STRICT>(*this, m);
254 // SmartMapTools::setValues(*this, m);
255 SmartMapTools::setValues<smap_t,S,STRICT>(*this, m);
256 //new
257 //for (typename std::map<std::string,S>::const_iterator it = m.begin(); it != m.end(); ++it)
258 // importEntry(it->first, it->second); //, updateOnly); //, criticality); // false);
259
260 }
261
263
270 template <class T2,bool STRICT=true>
271 void importCastableMap(const drain::SmartMap<T2> & m){ //, bool updateOnly = false, unsigned int criticality = LOG_ERR){
272 // NUOEVO:
273 SmartMapTools::setCastableValues<smap_t,T2,STRICT>(*this, m);
274 // SmartMapTools::setValues<smap_t,T2,STRICT>(*this, m);
275 //SmartMapTools::setValues<map_t,T2,STRICT>(*this, m);
276 /*
277 for (const typename SmartMap<T2>::keylist_t::value_type &key : m.getKeyList()){
278 importEntry(key, (const Castable &)m[key]); //, updateOnly);
279 }
280 */
281 // for (typename SmartMap<T2>::const_iterator it = m.begin(); it != m.end(); ++it)
282 // importEntry(it->first, (const Castable &)it->second, updateOnly); //, criticality); // false);
283 }
284
285
286
288
292 template <class T2>
293 inline
294 void updateFromMap(const std::map<std::string,T2> & m){
295 importMap<T2,false>(m); //, LOG_DEBUG);
296 }
297
299 template <class T2>
300 inline
302 importCastableMap<T2,false>(m); //, true);
303 // for (typename SmartMap<T2>::const_iterator it = m.begin(); it != m.end(); ++it)
304 // importEntry(it->first, (const Castable &)it->second, LOG_DEBUG); //true);
305 }
306
307
309 // TODO: consider: std::string assignmentSymbols="=:", std::string separatorSymbols=", ", std::string trimSymbols=" \t\n\r",
310 inline
311 void setValues(const std::string & entries, char assignmentSymbol='=', char separatorSymbol=0){ // char separatorSymbol=','
312 importEntries<true>(entries, assignmentSymbol, separatorSymbol); //, false); //, LOG_ERR);
313 }
314
315 inline
316 void setValues(const char * entries, char assignmentSymbol='=', char separatorSymbol=0){
317 importEntries<true>(entries, assignmentSymbol, separatorSymbol); //, false); //, LOG_ERR);
318 }
319
320 // status?
321 template <class S>
322 void setValuesSEQ(const S & sequence);
323
325 inline
326 void updateValues(const std::string & entries, char assignmentSymbol='=', char separatorSymbol=0){// char separatorSymbol=','
327 importEntries<false>(entries, assignmentSymbol, separatorSymbol); //, true); //, LOG_DEBUG);
328 }
329
330
331 inline
332 void getKeys(std::ostream &ostr) const {
333
334 const keylist_t & l = getKeyList();
335 for (keylist_t::const_iterator it = l.begin(); it != l.end(); ++it ){
336 if (it != l.begin())
337 ostr << ',';
338 ostr << *it;
339 }
340
341 }
342
344 inline
345 std::string getKeys() const {
346 std::stringstream s;
347 getKeys((std::ostream &)s);
348 return s.str();
349 };
350
352 inline
353 void getValues(std::ostream &ostr) const {
354
355 const keylist_t & l = getKeyList();
356 for (keylist_t::const_iterator it = l.begin(); it != l.end(); ++it ){
357 if (it != l.begin())
358 ostr << ',';
359 if (this->find(*it) != this->end())
360 ostr << (*this)[*it]; // << this->find(*it).getType();
361 else {
362 ostr << "*SMARTMAP::FAIL* " << __FUNCTION__;
363 }
364 }
365
366 }
367
369 inline
370 std::string getValues() const {
371 std::stringstream s;
372 getValues(s);
373 return s.str();
374 };
375
376
378 /*
379 * \param equal - typically =, :, or -
380 * \param start - typically hyphen or leading parenthesis (, {, [
381 * \param end - typically hyphen or trailing parenthesis ), }, [
382 * \param separator - typically comma or semicolon
383 */
384 // template <class S>
385 // S & toStream(S & ostr, char equal='=', char startChar=0, char endChar=0, char separatorChar=0) const;
386 std::ostream & toStream(std::ostream & ostr, char equal='=', char startChar='{', char endChar='}', char separatorChar=',') const {
387 //drain::TypeLayout pairLayout(equal);
388 drain::TypeLayout mainLayout(startChar, separatorChar, endChar);
390 //layout.pairChars.separator = equal;
391 layout.pairChars.separator = equal;
392 //layout.arrayChars.setLayout();
393 return Sprinter::sequenceToStream(ostr, getMap(), mainLayout, layout);
394 //return Sprinter::sequenceToStream(ostr, vmap.getMap(), layout.mapChars, layout);
395 //return Sprinter::mapToStream(ostr, *this, Sprinter::jsonLayout, this->getKeyList());
396 }
397
398 //std::string toStr(char equal='=', char start='{', char end='}', char separator=0) const {
399 std::string toStr(char equal='=', char start=0, char end=0, char separator=0) const {
400 std::stringstream sstr;
401 toStream(sstr, equal, start, end, separator);
402 return sstr.str();
403 }
404
406 //void toJSON(std::ostream & ostr = std::cout, size_t indent = 0) const;
407
409 // void valuesToJSON(std::ostream & ostr = std::cout) const;
410
412 void dump(std::ostream & ostr = std::cout) const;
413
414
415
417 // ?? If specific, allows also "key=value,key1=value2,...".
429 // \param updateOnly - if true, skip non-existing entries silently
430 //void assignEntries2(const std::string & entries, bool updateOnly = false, char assignmentSymbol='=', char separatorSymbol=0){
431
432protected:
433
434
436 // std::list<std::string> orderedKeyList;
437
438 mutable std::list<std::string> keyList;
439
440};
441
442template <class T>
443template <bool STRICT>
444void SmartMap<T>::importEntries(const std::string & entries, char assignmentSymbol, char separatorSymbol){ //, bool updateOnly){
445
446 Logger mout(__FILE__, __FUNCTION__);
447 //mout.debug(10) << entries << mout.endl;
448
449 if (entries.empty()){ //old
450 return;
451 }
452
453 separatorSymbol = separatorSymbol ? separatorSymbol : separator;
454
455 // Input parameter assignments, separated by the separator: "a=1", "b=2", "c=3", ...
456 std::list<std::string> p;
457 // separatorSymbol = separatorSymbol ? separatorSymbol : separator;
458 if (separatorSymbol)
459 drain::StringTools::split(entries, p, std::string(1, separatorSymbol)); // separators);
460 else {
461 // no separator => single-param cmd, BUT explicit key=value possible
462 // mout.warn("push back entries:" , entries );
463 p.push_back(entries);
464 }
465 importEntries<STRICT>(p, assignmentSymbol);
466
467}
468
469/*
470
471template <class T>
472template <bool STRICT>
473void SmartMap<T>::importEntries(const std::list<std::string> & p, char assignmentSymbol){ // , bool updateOnly){
474
475 Logger mout(__FILE__, __FUNCTION__);
476
477 // NUEVO3 SmartMapTools::setValues<T,STRICT>(*this, p, assignmentSymbol);
478
479 //SmartMapTools::setValues<T,STRICT>(*this, getKeyList(), p, assignmentSymbol);
480
481 const std::string assignmentSymbols(1, assignmentSymbol);
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(" assignmentSymbol: " , assignmentSymbol );
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 (assignmentSymbol){ // typically '='
498 std::string key;
499 std::string value;
500 if (StringTools::split2(*pit, key, value, assignmentSymbols)){
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:312
A base class for smart maps providing methods for importing and exporting values, among others.
Definition SmartMap.h:66
map_t::iterator iterator
Needed?
Definition SmartMap.h:80
void importEntries(const std::string &entries, char assignmentSymbol='=', char separatorSymbol=0)
Assigns a value to given key; if the entry does not exist, tries to create it with directly with oper...
Definition SmartMap.h:444
char arraySeparator
Default separator character for array elements (std::vector's)
Definition SmartMap.h:88
std::string getKeys() const
Convenience function for std::string output.
Definition SmartMap.h:345
std::list< std::string > keyList
Assigns values from std::string of type "value,value2,...valueN".
Definition SmartMap.h:438
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:185
void importEntries(const std::list< std::string > &entries, char assignmentSymbol='=')
Definition SmartMap.h:240
char separator
Default character used for splitting input and output. See setValues.
Definition SmartMap.h:85
void setValues(const std::string &entries, char assignmentSymbol='=', char separatorSymbol=0)
Sets values. If strictness==STRICTLY_CLOSED, throws exception if tries to assign a non-existing entry...
Definition SmartMap.h:311
virtual const keylist_t & getKeyList() const
Derived versions may produce an ordered set of keys.
Definition SmartMap.h:200
void importCastableMap(const drain::SmartMap< T2 > &m)
Assign values from a map, possibly extending the map.
Definition SmartMap.h:271
std::string getValues() const
Convenience function for std::string output.
Definition SmartMap.h:370
void exportMap(std::map< std::string, T2 > &m) const
Copies the contents to another map.
Definition SmartMap.h:212
virtual T & operator[](const std::string &key)
Returns an element. Creates one, conditionally.
Definition SmartMap.h:167
void getValues(std::ostream &ostr) const
Dumps the values.
Definition SmartMap.h:353
void updateFromMap(const std::map< std::string, T2 > &m)
Assign values from a map. Updates existing entries only.
Definition SmartMap.h:294
const map_t & getMap() const
Definition SmartMap.h:206
void updateFromCastableMap(const drain::SmartMap< T2 > &m)
Convenience.
Definition SmartMap.h:301
void updateValues(const std::string &entries, char assignmentSymbol='=', char separatorSymbol=0)
Sets applicable values ie. modifies existing entries only. In ordered maps, skips extra entries silen...
Definition SmartMap.h:326
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:127
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:151
SmartMap(char separator='\0', char arraySeparator=':')
Definition SmartMap.h:95
std::ostream & toStream(std::ostream &ostr, char equal='=', char startChar='{', char endChar='}', char separatorChar=',') const
Note: parameters discarded.
Definition SmartMap.h:386
void importMap(const std::map< std::string, S > &m)
Assign values from a map, overriding existing entries.
Definition SmartMap.h:252
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:321
static const SprinterLayout jsonLayout
Resembles JSON structure: {"a":1,"b":22,"c":3}.
Definition Sprinter.h:221
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 String.h:380
Definition DataSelector.cpp:1277
Definition Sprinter.h:137
Definition Sprinter.h:80