Loading...
Searching...
No Matches
StringTools.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/*
32 * StringTools.h
33 *
34 * Created on: Jul 21, 2010
35 * Author: mpeura
36 */
37
38#ifndef DRAIN_STRING_TOOLS
39#define DRAIN_STRING_TOOLS
40
41#include <limits>
42#include <map>
43#include <string>
44#include <sstream>
45
46
47
48namespace drain {
49
50
52
53public:
54
55 static
56 bool startsWith(const std::string &s, const std::string & substring);
57
58
59 static
60 bool endsWith(const std::string &s, const std::string & substring);
61
62
64
66 static
67 std::string & upperCase(std::string & s, size_t n = std::numeric_limits<size_t>::max());
68
70
72 static
73 char upperCase(char c);
74
76
79 static
80 std::string & lowerCase(std::string & s, size_t n = std::numeric_limits<size_t>::max());
81
83
85 static
86 char lowerCase(char c);
87
88
89
91
94 static
95 void replace(const std::string &src, char search, char repl, std::ostream & ostr);
96
98
101 static
102 void replace(const std::string &src, char from, char repl, std::string &dst);
103
105
108 template <typename S, typename R>
109 static
110 void replace(const std::string &src, const S & search, const R & repl, std::ostream & ostr){
111
112 const size_t length = getLength(search);
113 std::string::size_type i = 0;
114 std::string::size_type pos;
115
116 while (true) {
117 pos = src.find(search, i);
118 if (pos == std::string::npos){
119 ostr << src.substr(i);
120 return;
121 }
122
123 // String was found
124 ostr << src.substr(i, pos-i) << repl;
125
126 // Jump over <search>: move forward len(search) chars
127 i = pos + length;
128 }
129 }
130
131
133
136 template <typename T1, typename T2>
137 static inline
138 void replace(const std::string &src, const T1 &search, const T2 & repl, std::string & dst){
139 std::stringstream result;
140 replace(src, search, repl, result);
141 dst = result.str();
142 }
143
144
146
152 /*
153 template <typename T1, typename T2>
154 static inline
155 std::string replace(const std::string &src, const T1 & search, const T2 & repl){
156 std::string dst;
157 replace(src, search, repl, dst);
158 return dst;
159 }
160 */
161
162 // MAP VERSIONS
163
165 template <typename T>
166 static
167 void replace(const std::string & src, const std::map<char,T> & m, std::ostream & ostr){
168 typename std::map<char,T>::const_iterator it;
169 for (char c: src){
170 it = m.find(c);
171 if (it == m.end()){
172 ostr << c;
173 }
174 else {
175 ostr << it->second;
176 }
177 }
178 };
179
180 template <typename T>
181 static inline
182 void replace(const std::string & src, const std::map<char,T> & m, std::string & dst){
183 std::stringstream result;
184 replace(src, m, result);
185 dst = result.str();
186 }
187
189
192 static
193 void replace(const std::string & src, const std::map<char,char> & m, std::string & dst);
194
200 template <class K, class V>
201 static inline
202 void replace(const std::string & src, const std::map<K,V> & m, std::string & dst){
203 replaceWithMap(src, m, dst);
204 };
205
206 template <class K, class V>
207 static inline
208 void replace(const std::string & src, const std::initializer_list<std::pair<K,V> > & m, std::string & dst){
209 replaceWithMap(src, m, dst);
210 };
211
213 static
214 std::string & convertEscaped(std::string &s);
215
216
217private:
218
219 static inline
220 size_t getLength(char c){
221 return 1;
222 };
223
224 static inline
225 size_t getLength(const std::string & s){
226 return s.length();
227 };
228
229 template <class M>
230 static inline
231 void replaceWithMap(const std::string & src, const M & m, std::string & dst){
232
233 if (m.empty()){
234 // Replace nothing in src, hence assign it directly to result.
235 if (&dst != &src){
236 dst = src; // clumsy?
237 }
238 return;
239 }
240
241 for (const auto & entry: m){
242 // std::cerr << "replacing " << entry.first << " -> " << entry.second << " in " << dst << std::endl;
243 replace(dst, entry.first, entry.second, dst);
244 }
245 };
246
247
248public:
249
250
251
253 static
254 std::string trim(const std::string &s, const std::string &trimChars=" \t\n\r");
255
257
264 static
265 std::string trimSymmetric(const std::string &s, const std::string &leading= "'\"", const std::string & trailing="");
266
267
269
280 static
281 bool trimScan(const std::string &s, std::size_t & pos1, std::size_t & pos2, const std::string &trimChars=" \t\n");
282
284
297 template <class T, class C>
298 static
299 void split(const std::string & s, T & sequence, const C &separators, const std::string & trimChars=" \t\n");
300
302 /*
303 template <class T>
304 static inline
305 void split(const std::string & s, T & sequence, char separator=',', const std::string & trimChars=" \t\n"){
306 StringTools::split(s, sequence, std::string(1,separator), trimChars);
307 }
308 */
309
311
326 template <class T1, class T2, class C>
327 static
328 bool split2(const std::string & s, T1 & first, T2 & second, const C &separators, const std::string & trimChars=" \t\n");
329
331
337 static
338 size_t extractPrefixLength(const std::string & src1, const std::string & src2, size_t step = 1);
339
341
349 static
350 size_t extractPrefix(const std::string & src1, const std::string & src2,
351 std::string & prefix, std::string & dst1, std::string & dst2, size_t step = 1);
352
354
360 static inline
361 size_t extractPrefix(std::string & s1, std::string & s2, std::string & prefix, size_t step = 1){
362 return extractPrefix(s1, s2, prefix, s1, s2, step);
363 }
364
365
367
370 template <class T>
371 static
372 std::ostream & join(const T & container, std::ostream & ostr, char separator = 0){
373 char sep = 0;
374 for (typename T::const_iterator it = container.begin(); it != container.end(); ++it){
375 if (sep)
376 ostr << sep;
377 ostr << *it;
378 sep = separator;
379 }
380 return ostr;
381 }
382
384
387 template <class T>
388 static inline
389 std::string join(T & container, char separator = 0){
390 std::stringstream sstr;
391 StringTools::join(container, sstr, separator);
392 return sstr.str();
393 }
394
396 template <unsigned int S>
397 static
398 void read(std::istream &istr, std::string & s){
399 char buffer[S];
400 while (istr.read(buffer, S)){
401 s.append(buffer, S);
402 }
403 s.append(buffer, istr.gcount());
404 }
405
406
408
416 template <class T>
417 static
418 void convert(const std::string &s, T & dst);
419
421
427 template <class T>
428 static
429 T convert(const std::string &s);
430
431
432 template <class T>
433 static
434 std::string & import(const T & src, std::string & target);
435
436
437
438
439//private: CONSIDER!
440
442
452 template <class T>
453 static
454 const T & lazyConvert(const std::string &s, T & tmp);
455
456private:
457
458 template <class T>
459 static
460 void appendString(T & sequence, const std::string & str){
461 typename T::value_type tmp;
462 sequence.insert(sequence.end(), StringTools::lazyConvert(str, tmp));
463 }
464
465 template <class T>
466 static
467 void appendSubstring(T & sequence, const std::string & str, std::string::size_type pos, std::string::size_type n){
468
469 if (n > 0){
470 appendString(sequence, str.substr(pos, n));
471 }
472 else {
473 appendString(sequence, "");
474 }
475
476 }
477
478};
479
480
481template <class T, class C>
482void StringTools::split(const std::string & str, T & sequence, const C & separators, const std::string & trimChars){
483
484 sequence.clear();
485
486 const bool TRIM = !trimChars.empty();
487 const std::string::size_type n = str.size();
488
489 std::string::size_type pos1 = 0; // Start of segment
490 std::string::size_type pos2 = n; // std::string::npos; // End of segment (index of last char + 1)
491
492 if (false){ //separators.empty()){ // = no split! :-)
493
494 if (TRIM){
495 StringTools::trimScan(str, pos1, pos2, trimChars);
496 appendSubstring(sequence, str, pos1, pos2-pos1);
497 }
498 else
499 appendString(sequence, str);
500
501 return;
502 }
503 else {
504
505 // Index of the next separator position
506 std::string::size_type pos = pos1; // "irreversible"
507
508 while (true) {
509
510 pos1 = pos;
511 pos = str.find_first_of(separators, pos);
512 if (pos == std::string::npos){
513 pos2 = n;
514 if (TRIM)
515 StringTools::trimScan(str, pos1, pos2, trimChars);
516 appendSubstring(sequence, str, pos1, pos2-pos1);
517 return;
518 }
519 else {
520 pos2 = pos;
521 if (TRIM)
522 StringTools::trimScan(str, pos1, pos2, trimChars);
523 appendSubstring(sequence, str, pos1, pos2-pos1);
524 pos = str.find_first_not_of(trimChars, pos+1); // if separator is space, or other also in trimChars
525 //pos = str.find_last_not_of(trimChars, pos);
526 //++pos; // for the next round
527 }
528
529 }
530 }
531}
532
533/*
534template <>
535bool StringTools::split2(const std::string & s, std::string & first, std::string & second, const char *separators, const std::string & trimChars);
536*/
537
538template <class T1, class T2, class S>
539bool StringTools::split2(const std::string & s, T1 & first, T2 & second, const S & separators, const std::string & trimChars){
540
541 std::size_t i = s.find_first_of(separators);
542
543 if (i != std::string::npos){ // input of type "key=value" found
544
545 std::string srcFirst(s, 0, i);
546 ++i;
547 std::string srcSecond(s, std::min(s.size(), i));
548
549 if (!trimChars.empty()){
550 first = lazyConvert(StringTools::trim(srcFirst, trimChars), first); // first=first should not clear the object!
551 }
552 else {
553 first = lazyConvert(srcFirst, first); // Note: first=first should not clear the object!
554 }
555
556 if (!srcSecond.empty()){
557 if (!trimChars.empty()){
558 second = lazyConvert(StringTools::trim(srcSecond), second);
559 }
560 else {
561 second = lazyConvert(srcSecond, second);
562 }
563 }
564
565 /*
566 ++i;
567 if (i<s.size()){
568 //std::cerr << "toka " << s.substr(i) << '\n';
569 if (!trimChars.empty()){
570 // sstr2 << StringTools::trim(s.substr(i), trimChars);
571 // sstr2 >> second;
572 second = lazyConvert(StringTools::trim(s.substr(i), trimChars), second);
573 }
574 else {
575 // sstr2 << s.substr(i);
576 // sstr2 >> second;
577 second = lazyConvert(s.substr(i), second);
578 }
579 }
580 */
581 return true;
582 }
583 else {
584 // std::stringstream sstr;
585 if (trimChars.empty()){
586 //sstr << s;
587 //sstr >> first;
588 first = lazyConvert(s, first);
589 }
590 else {
591 // sstr << StringTools::trim(s, trimChars);
592 // sstr >> first;
593 first = lazyConvert(StringTools::trim(s, trimChars), first);
594 }
595 return false;
596 }
597
598
599}
600
601
602
603
604
605
606
607template <>
608inline
609const std::string & StringTools::lazyConvert(const std::string &str, std::string & tmp){
610 return str;
611}
612
613
614template <class T>
615inline
616const T & StringTools::lazyConvert(const std::string &str, T & dst){
617 std::stringstream sstr(str);
618 sstr >> dst;
619 return dst;
620}
621
622template <class T>
623inline
624void StringTools::convert(const std::string &str, T & dst){
625 dst = lazyConvert(str, dst);
626}
627
628
629template <class T>
630inline
631T StringTools::convert(const std::string &s){
632 T tmp;
633 tmp = lazyConvert(s, tmp);
634 return tmp;
635}
636
637
638
639
640template <>
641inline
642std::string & StringTools::import(const std::string & src, std::string & dst){
643 dst = src;
644 return dst;
645}
646
647template <class T>
648std::string & StringTools::import(const T & x, std::string & dst){
649 std::stringstream sstr;
650 sstr << x;
651 dst.assign(sstr.str());
652 //std::cerr << __FUNCTION__ << ": " << str << '>' << target << '\n';
653 return dst;
654}
655
656
657} // drain::
658
659#endif /* STRING_H_ */
660
Definition StringTools.h:51
static void convert(const std::string &s, T &dst)
Conversion from std::string to basic types, including std::string.
Definition StringTools.h:624
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 bool trimScan(const std::string &s, std::size_t &pos1, std::size_t &pos2, const std::string &trimChars=" \t\n")
Returns indices to trimmed segment of s such that it can be extracted as s.substr(pos1,...
Definition StringTools.cpp:294
static void replace(const std::string &src, const T1 &search, const T2 &repl, std::string &dst)
In src, replaces instances of 'from' to 'to', storing the result in dst.
Definition StringTools.h:138
static std::string & lowerCase(std::string &s, size_t n=std::numeric_limits< size_t >::max())
Turns n first characters lowercase. ASCII only.
Definition StringTools.cpp:412
static void replace(const std::string &src, const std::map< K, V > &m, std::string &dst)
Definition StringTools.h:202
static const T & lazyConvert(const std::string &s, T &tmp)
Convert only if needed. If T is std::string, returns s directly.
Definition StringTools.h:616
static std::ostream & join(const T &container, std::ostream &ostr, char separator=0)
Writes a STL Container (list, vector, set) to a stream, using an optional separator char (e....
Definition StringTools.h:372
static void read(std::istream &istr, std::string &s)
Read input stream and append it to s.
Definition StringTools.h:398
static std::string & convertEscaped(std::string &s)
Interpret commond special chars: tab '\t', newline ' ' and carriage return '\r'.
Definition StringTools.cpp:123
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 replace(const std::string &src, const std::map< char, T > &m, std::ostream &ostr)
Convenience using copying of string.
Definition StringTools.h:167
static std::string & upperCase(std::string &s, size_t n=std::numeric_limits< size_t >::max())
Turns n first characters uppercase. ASCII only.
Definition StringTools.cpp:391
static void replace(const std::string &src, const S &search, const R &repl, std::ostream &ostr)
In src, replaces instances of 'search' to 'repl', storing the result in dst.
Definition StringTools.h:110
static size_t extractPrefixLength(const std::string &src1, const std::string &src2, size_t step=1)
Determine the length of a common leading part, rounding up the result with step.
Definition StringTools.cpp:355
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
static size_t extractPrefix(std::string &s1, std::string &s2, std::string &prefix, size_t step=1)
Extract common leading part, truncating the input strings.
Definition StringTools.h:361
static std::string trimSymmetric(const std::string &s, const std::string &leading="'\"", const std::string &trailing="")
Coupled trimming: remove a single leading and trailing char, if both found.
Definition StringTools.cpp:266
static size_t extractPrefix(const std::string &src1, const std::string &src2, std::string &prefix, std::string &dst1, std::string &dst2, size_t step=1)
Extract common leading part, truncating the source strings.
Definition StringTools.cpp:371
static void replace(const std::string &src, char search, char repl, std::ostream &ostr)
Replaces instances of 'search' to 'repl' in src.
Definition StringTools.cpp:94
static std::string join(T &container, char separator=0)
Writes a STL Container (list, vector, set) to a string, using an optional separator char (like ',...
Definition StringTools.h:389
Definition DataSelector.cpp:1277