Loading...
Searching...
No Matches
String.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_H_
39#define DRAIN_STRING_H_
40
41#include <limits>
42#include <iterator>
43#include <string>
44#include <sstream>
45#include <iostream>
46#include <list>
47#include <map>
48
49//#include "RegExp.h"
50
51namespace drain {
52
54
55public:
56
57 static
58 bool startsWith(const std::string &s, const std::string & substring);
59
60
61 static
62 bool endsWith(const std::string &s, const std::string & substring);
63
64
66
68 static
69 std::string & upperCase(std::string & s, size_t n = std::numeric_limits<size_t>::max());
70
72
74 static
75 char upperCase(char c);
76
78
81 static
82 std::string & lowerCase(std::string & s, size_t n = std::numeric_limits<size_t>::max());
83
85
87 static
88 char lowerCase(char c);
89
90
91
94
109 static
110 void replace(const std::string &src, char from, char to, std::ostream & ostr);
111
113
117 static
118 void replace(const std::string &src, char from, char to, std::string &dst);
119
120
122
126 static
127 void replace(const std::string &src, const std::string &from, const std::string & to, std::string & dst);
128
129
131
134 template <typename T1, typename T2>
135 static inline
136 void replace(std::string &src, const T1 &from, const T2 &to){
137 replace(src, from, to, src);
138 }
139
141
146 template <typename T1, typename T2>
147 static inline
148 std::string replace(const std::string &src, const T1 &from, const T2 &to){
149 std::string dst;
150 replace(src, from, to, dst);
151 return dst;
152 }
153
154 // MAP VERSIONS
155 // remove this:
156 typedef std::map<std::string,std::string> conv_map_t;
157
159
162 static
163 void replace(const conv_map_t & m, std::string &s, std::size_t pos = 0);
164
165 //typedef std::map<char,std::string> _map_t;
166
168
171 // std::map<std::string,std::string>
172 // static
173 // void replace(const std::map<char,std::string> & m, const std::string & src, std::ostream & ostr);
174
175 /*
176 static inline
177 void replace(const std::map<char,std::string> & m, const std::string & src, std::string & dst){
178 std::stringstream result;
179 replace(m, src, result);
180 dst = result.str();
181
182 }
183 */
184
186 template <typename T>
187 static
188 void replace(const std::map<char,T> & m, const std::string & src, std::ostream & ostr){
189 typename std::map<char,T>::const_iterator it;
190 for (char c: src){
191 it = m.find(c);
192 if (it == m.end()){
193 ostr << c;
194 }
195 else {
196 ostr << it->second;
197 }
198 }
199 };
200
202
205 static
206 void replace(const std::map<char,char> & m, const std::string & src, std::string & dst);
207
213 template <class T1, class T2>
214 static inline
215 void replace(const std::map<T1,T2> & m, const std::string & src, std::string & dst){
216 std::stringstream result;
217 replace(m, src, result);
218 dst = result.str();
219 };
220
221
222 static inline
223 void replace(const std::map<char,std::string> & m, std::string & src){
224 replace(m, src, src);
225 }
226
227
228
229
230
232 static
233 std::string trim(const std::string &s, const std::string &trimChars=" \t\n\r");
234
236
243 static
244 std::string trimSymmetric(const std::string &s, const std::string &leading= "'\"", const std::string & trailing="");
245
246
248
259 static
260 bool trimScan(const std::string &s, size_t & pos1, size_t & pos2, const std::string &trimChars=" \t\n");
261
263
276 template <class T, class C>
277 static
278 void split(const std::string & s, T & sequence, const C &separators, const std::string & trimChars=" \t\n");
279
281 /*
282 template <class T>
283 static inline
284 void split(const std::string & s, T & sequence, char separator=',', const std::string & trimChars=" \t\n"){
285 StringTools::split(s, sequence, std::string(1,separator), trimChars);
286 }
287 */
288
290
305 template <class T1, class T2, class C>
306 static
307 bool split2(const std::string & s, T1 & first, T2 & second, const C &separators, const std::string & trimChars=" \t\n");
308
310
316 static
317 size_t extractPrefixLength(const std::string & src1, const std::string & src2, size_t step = 1);
318
320
328 static
329 size_t extractPrefix(const std::string & src1, const std::string & src2,
330 std::string & prefix, std::string & dst1, std::string & dst2, size_t step = 1);
331
333
339 static inline
340 size_t extractPrefix(std::string & s1, std::string & s2, std::string & prefix, size_t step = 1){
341 return extractPrefix(s1, s2, prefix, s1, s2, step);
342 }
343
344
346
349 template <class T>
350 static
351 std::ostream & join(const T & container, std::ostream & ostr, char separator = 0){
352 char sep = 0;
353 for (typename T::const_iterator it = container.begin(); it != container.end(); ++it){
354 if (sep)
355 ostr << sep;
356 ostr << *it;
357 sep = separator;
358 }
359 return ostr;
360 }
361
363
366 template <class T>
367 static inline
368 std::string join(T & container, char separator = 0){
369 std::stringstream sstr;
370 StringTools::join(container, sstr, separator);
371 return sstr.str();
372 }
373
375 template <unsigned int S>
376 static
377 void read(std::istream &istr, std::string & s){
378 char buffer[S];
379 while (istr.read(buffer, S)){
380 s.append(buffer, S);
381 }
382 s.append(buffer, istr.gcount());
383 }
384
385
387
395 template <class T>
396 static
397 void convert(const std::string &s, T & dst);
398
400
406 template <class T>
407 static
408 T convert(const std::string &s);
409
410 template <class T>
411 static
412 std::string & import(const T & src, std::string & target);
413
414
415
416
417//private: CONSIDER!
418
420
430 template <class T>
431 static
432 const T & lazyConvert(const std::string &s, T & tmp);
433
434private:
435
436 template <class T>
437 static
438 void appendString(T & sequence, const std::string & str){
439 typename T::value_type tmp;
440 sequence.insert(sequence.end(), StringTools::lazyConvert(str, tmp));
441 }
442
443 template <class T>
444 static
445 void appendSubstring(T & sequence, const std::string & str, std::string::size_type pos, std::string::size_type n){
446
447 if (n > 0){
448 appendString(sequence, str.substr(pos, n));
449 }
450 else {
451 appendString(sequence, "");
452 }
453
454 }
455
456};
457
458
459template <class T, class C>
460void StringTools::split(const std::string & str, T & sequence, const C & separators, const std::string & trimChars){
461
462 sequence.clear();
463
464 const bool TRIM = !trimChars.empty();
465 const std::string::size_type n = str.size();
466
467 std::string::size_type pos1 = 0; // Start of segment
468 std::string::size_type pos2 = n; // std::string::npos; // End of segment (index of last char + 1)
469
470 if (false){ //separators.empty()){ // = no split! :-)
471
472 if (TRIM){
473 StringTools::trimScan(str, pos1, pos2, trimChars);
474 appendSubstring(sequence, str, pos1, pos2-pos1);
475 }
476 else
477 appendString(sequence, str);
478
479 return;
480 }
481 else {
482
483 // Index of the next separator position
484 std::string::size_type pos = pos1; // "irreversible"
485
486 while (true) {
487
488 pos1 = pos;
489 pos = str.find_first_of(separators, pos);
490 if (pos == std::string::npos){
491 pos2 = n;
492 if (TRIM)
493 StringTools::trimScan(str, pos1, pos2, trimChars);
494 appendSubstring(sequence, str, pos1, pos2-pos1);
495 return;
496 }
497 else {
498 pos2 = pos;
499 if (TRIM)
500 StringTools::trimScan(str, pos1, pos2, trimChars);
501 appendSubstring(sequence, str, pos1, pos2-pos1);
502 pos = str.find_first_not_of(trimChars, pos+1); // if separator is space, or other also in trimChars
503 //pos = str.find_last_not_of(trimChars, pos);
504 //++pos; // for the next round
505 }
506
507 }
508 }
509}
510
511/*
512template <>
513bool StringTools::split2(const std::string & s, std::string & first, std::string & second, const char *separators, const std::string & trimChars);
514*/
515
516template <class T1, class T2, class S>
517bool StringTools::split2(const std::string & s, T1 & first, T2 & second, const S & separators, const std::string & trimChars){
518
519 std::size_t i = s.find_first_of(separators);
520
521 if (i != std::string::npos){ // input of type "key=value" found
522
523 std::string srcFirst(s, 0, i);
524 ++i;
525 std::string srcSecond(s, std::min(s.size(), i));
526
527 if (!trimChars.empty()){
528 first = lazyConvert(StringTools::trim(srcFirst, trimChars), first); // first=first should not clear the object!
529 }
530 else {
531 first = lazyConvert(srcFirst, first); // Note: first=first should not clear the object!
532 }
533
534 if (!srcSecond.empty()){
535 if (!trimChars.empty()){
536 second = lazyConvert(StringTools::trim(srcSecond), second);
537 }
538 else {
539 second = lazyConvert(srcSecond, second);
540 }
541 }
542
543 /*
544 ++i;
545 if (i<s.size()){
546 //std::cerr << "toka " << s.substr(i) << '\n';
547 if (!trimChars.empty()){
548 // sstr2 << StringTools::trim(s.substr(i), trimChars);
549 // sstr2 >> second;
550 second = lazyConvert(StringTools::trim(s.substr(i), trimChars), second);
551 }
552 else {
553 // sstr2 << s.substr(i);
554 // sstr2 >> second;
555 second = lazyConvert(s.substr(i), second);
556 }
557 }
558 */
559 return true;
560 }
561 else {
562 // std::stringstream sstr;
563 if (trimChars.empty()){
564 //sstr << s;
565 //sstr >> first;
566 first = lazyConvert(s, first);
567 }
568 else {
569 // sstr << StringTools::trim(s, trimChars);
570 // sstr >> first;
571 first = lazyConvert(StringTools::trim(s, trimChars), first);
572 }
573 return false;
574 }
575
576
577}
578
579
580
581
582
583
584
585template <>
586inline
587const std::string & StringTools::lazyConvert(const std::string &str, std::string & tmp){
588 return str;
589}
590
591
592template <class T>
593inline
594const T & StringTools::lazyConvert(const std::string &str, T & dst){
595 std::stringstream sstr(str);
596 sstr >> dst;
597 return dst;
598}
599
600template <class T>
601inline
602void StringTools::convert(const std::string &str, T & dst){
603 dst = lazyConvert(str, dst);
604}
605
606
607template <class T>
608inline
609T StringTools::convert(const std::string &s){
610 T tmp;
611 tmp = lazyConvert(s, tmp);
612 return tmp;
613}
614
615
616
617
618template <>
619inline
620std::string & StringTools::import(const std::string & src, std::string & dst){
621 dst = src;
622 return dst;
623}
624
625template <class T>
626std::string & StringTools::import(const T & x, std::string & dst){
627 std::stringstream sstr;
628 sstr << x;
629 dst.assign(sstr.str());
630 //std::cerr << __FUNCTION__ << ": " << str << '>' << target << '\n';
631 return dst;
632}
633
634
635} // drain::
636
637#endif /* STRING_H_ */
638
Definition String.h:53
static void convert(const std::string &s, T &dst)
Conversion from std::string to basic types, including std::string.
Definition String.h:602
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 & lowerCase(std::string &s, size_t n=std::numeric_limits< size_t >::max())
Turns n first characters lowercase. ASCII only.
Definition String.cpp:365
static const T & lazyConvert(const std::string &s, T &tmp)
Convert only if needed. If T is std::string, returns s directly.
Definition String.h:594
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 String.h:351
static void replace(const std::map< T1, T2 > &m, const std::string &src, std::string &dst)
Definition String.h:215
static void read(std::istream &istr, std::string &s)
Read input stream and append it to s.
Definition String.h:377
static void replace(const std::map< char, T > &m, const std::string &src, std::ostream &ostr)
Replaces instances appearing as map keys to map values.
Definition String.h:188
static std::string replace(const std::string &src, const T1 &from, const T2 &to)
Convenience using copying of string.
Definition String.h:148
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 String.cpp:205
static void replace(const std::map< char, char > &m, const std::string &src, std::string &dst)
NEW Fast (in-place) implementation of char-to-char replace.
static void replace(const std::string &src, char from, char to, std::ostream &ostr)
Definition String.cpp:94
static std::string & upperCase(std::string &s, size_t n=std::numeric_limits< size_t >::max())
Turns n first characters uppercase. ASCII only.
Definition String.cpp:344
static bool trimScan(const std::string &s, size_t &pos1, 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 String.cpp:247
static void replace(std::string &src, const T1 &from, const T2 &to)
Replaces a char or a substring in the argument itself.
Definition String.h:136
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 String.cpp:308
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:460
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 String.h:340
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 String.cpp:219
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 String.cpp:324
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 String.h:368
Definition DataSelector.cpp:1277