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
92
95 static inline
96 std::string replace(const std::string &src, const std::string &from, const std::string & to){
97 std::string dst;
98 StringTools::replace(src, from, to, dst);
99 return dst;
100 }
101
102 static inline
103 void replace(std::string &src, char from, char to){
104 replace(src, from, to, src);
105 }
106
107 static
108 void replace(const std::string &src, char from, char to, std::string &dst);
109
110
111 typedef std::map<std::string,std::string> conv_map_t;
112
114
117 // std::map<std::string,std::string>
118 static
119 void replace(const conv_map_t & m, std::string &s, std::size_t pos = 0);
120
121 //typedef std::map<char,std::string> _map_t;
122
124
127 // std::map<std::string,std::string>
128 static
129 void replace(const std::map<char,std::string> & m, const std::string & src, std::ostream & ostr);
130
131 static inline
132 void replace(const std::map<char,std::string> & m, const std::string & src, std::string & dst){
133 std::stringstream result;
134 replace(m, src, dst);
135 dst = result.str();
136
137 }
138
139
140 static inline
141 void replace(const std::map<char,std::string> & m, std::string & src){
142 replace(m, src, src);
143 }
144
145
147 static
148 void replace(const std::string &src, const std::string &from, const std::string & to, std::string & dst);
149
150
152 static
153 std::string trim(const std::string &s, const std::string &trimChars=" \t\n\r");
154
156
163 static
164 std::string trimSymmetric(const std::string &s, const std::string &leading= "'\"", const std::string & trailing="");
165
166
168
179 static
180 bool trimScan(const std::string &s, size_t & pos1, size_t & pos2, const std::string &trimChars=" \t\n");
181
183
196 template <class T, class C>
197 static
198 void split(const std::string & s, T & sequence, const C &separators, const std::string & trimChars=" \t\n");
199
201 /*
202 template <class T>
203 static inline
204 void split(const std::string & s, T & sequence, char separator=',', const std::string & trimChars=" \t\n"){
205 StringTools::split(s, sequence, std::string(1,separator), trimChars);
206 }
207 */
208
210
225 template <class T1, class T2, class C>
226 static
227 bool split2(const std::string & s, T1 & first, T2 & second, const C &separators, const std::string & trimChars=" \t\n");
228
230
236 static
237 size_t extractPrefixLength(const std::string & src1, const std::string & src2, size_t step = 1);
238
240
248 static
249 size_t extractPrefix(const std::string & src1, const std::string & src2,
250 std::string & prefix, std::string & dst1, std::string & dst2, size_t step = 1);
251
253
259 static inline
260 size_t extractPrefix(std::string & s1, std::string & s2, std::string & prefix, size_t step = 1){
261 return extractPrefix(s1, s2, prefix, s1, s2, step);
262 }
263
264
266
269 template <class T>
270 static
271 std::ostream & join(const T & container, std::ostream & ostr, char separator = 0){
272 char sep = 0;
273 for (typename T::const_iterator it = container.begin(); it != container.end(); ++it){
274 if (sep)
275 ostr << sep;
276 ostr << *it;
277 sep = separator;
278 }
279 return ostr;
280 }
281
283
286 template <class T>
287 static inline
288 std::string join(T & container, char separator = 0){
289 std::stringstream sstr;
290 StringTools::join(container, sstr, separator);
291 return sstr.str();
292 }
293
295 template <unsigned int S>
296 static
297 void read(std::istream &istr, std::string & s){
298 char buffer[S];
299 while (istr.read(buffer, S)){
300 s.append(buffer, S);
301 }
302 s.append(buffer, istr.gcount());
303 }
304
305
307
315 template <class T>
316 static
317 void convert(const std::string &s, T & dst);
318
320
326 template <class T>
327 static
328 T convert(const std::string &s);
329
330 template <class T>
331 static
332 std::string & import(const T & src, std::string & target);
333
334
335
336
337//private: CONSIDER!
338
340
350 template <class T>
351 static
352 const T & lazyConvert(const std::string &s, T & tmp);
353
354private:
355
356 template <class T>
357 static
358 void appendString(T & sequence, const std::string & str){
359 typename T::value_type tmp;
360 sequence.insert(sequence.end(), StringTools::lazyConvert(str, tmp));
361 }
362
363 template <class T>
364 static
365 void appendSubstring(T & sequence, const std::string & str, std::string::size_type pos, std::string::size_type n){
366
367 if (n > 0){
368 appendString(sequence, str.substr(pos, n));
369 }
370 else {
371 appendString(sequence, "");
372 }
373
374 }
375
376};
377
378
379template <class T, class C>
380void StringTools::split(const std::string & str, T & sequence, const C & separators, const std::string & trimChars){
381
382 sequence.clear();
383
384 const bool TRIM = !trimChars.empty();
385 const std::string::size_type n = str.size();
386
387 std::string::size_type pos1 = 0; // Start of segment
388 std::string::size_type pos2 = n; // std::string::npos; // End of segment (index of last char + 1)
389
390 if (false){ //separators.empty()){ // = no split! :-)
391
392 if (TRIM){
393 StringTools::trimScan(str, pos1, pos2, trimChars);
394 appendSubstring(sequence, str, pos1, pos2-pos1);
395 }
396 else
397 appendString(sequence, str);
398
399 return;
400 }
401 else {
402
403 // Index of the next separator position
404 std::string::size_type pos = pos1; // "irreversible"
405
406 while (true) {
407
408 pos1 = pos;
409 pos = str.find_first_of(separators, pos);
410 if (pos == std::string::npos){
411 pos2 = n;
412 if (TRIM)
413 StringTools::trimScan(str, pos1, pos2, trimChars);
414 appendSubstring(sequence, str, pos1, pos2-pos1);
415 return;
416 }
417 else {
418 pos2 = pos;
419 if (TRIM)
420 StringTools::trimScan(str, pos1, pos2, trimChars);
421 appendSubstring(sequence, str, pos1, pos2-pos1);
422 pos = str.find_first_not_of(trimChars, pos+1); // if separator is space, or other also in trimChars
423 //pos = str.find_last_not_of(trimChars, pos);
424 //++pos; // for the next round
425 }
426
427 }
428 }
429}
430
431/*
432template <>
433bool StringTools::split2(const std::string & s, std::string & first, std::string & second, const char *separators, const std::string & trimChars);
434*/
435
436template <class T1, class T2, class S>
437bool StringTools::split2(const std::string & s, T1 & first, T2 & second, const S & separators, const std::string & trimChars){
438
439 std::size_t i = s.find_first_of(separators);
440
441 if (i != std::string::npos){ // input of type "key=value" found
442
443 std::string srcFirst(s, 0, i);
444 ++i;
445 std::string srcSecond(s, std::min(s.size(), i));
446
447 if (!trimChars.empty()){
448 first = lazyConvert(StringTools::trim(srcFirst, trimChars), first); // first=first should not clear the object!
449 }
450 else {
451 first = lazyConvert(srcFirst, first); // Note: first=first should not clear the object!
452 }
453
454 if (!srcSecond.empty()){
455 if (!trimChars.empty()){
456 second = lazyConvert(StringTools::trim(srcSecond), second);
457 }
458 else {
459 second = lazyConvert(srcSecond, second);
460 }
461 }
462
463 /*
464 ++i;
465 if (i<s.size()){
466 //std::cerr << "toka " << s.substr(i) << '\n';
467 if (!trimChars.empty()){
468 // sstr2 << StringTools::trim(s.substr(i), trimChars);
469 // sstr2 >> second;
470 second = lazyConvert(StringTools::trim(s.substr(i), trimChars), second);
471 }
472 else {
473 // sstr2 << s.substr(i);
474 // sstr2 >> second;
475 second = lazyConvert(s.substr(i), second);
476 }
477 }
478 */
479 return true;
480 }
481 else {
482 // std::stringstream sstr;
483 if (trimChars.empty()){
484 //sstr << s;
485 //sstr >> first;
486 first = lazyConvert(s, first);
487 }
488 else {
489 // sstr << StringTools::trim(s, trimChars);
490 // sstr >> first;
491 first = lazyConvert(StringTools::trim(s, trimChars), first);
492 }
493 return false;
494 }
495
496
497}
498
499
500
501
502
503
504
505template <>
506inline
507const std::string & StringTools::lazyConvert(const std::string &str, std::string & tmp){
508 return str;
509}
510
511
512template <class T>
513inline
514const T & StringTools::lazyConvert(const std::string &str, T & dst){
515 std::stringstream sstr(str);
516 sstr >> dst;
517 return dst;
518}
519
520template <class T>
521inline
522void StringTools::convert(const std::string &str, T & dst){
523 dst = lazyConvert(str, dst);
524}
525
526
527template <class T>
528inline
529T StringTools::convert(const std::string &s){
530 T tmp;
531 tmp = lazyConvert(s, tmp);
532 return tmp;
533}
534
535
536
537
538template <>
539inline
540std::string & StringTools::import(const std::string & src, std::string & dst){
541 dst = src;
542 return dst;
543}
544
545template <class T>
546std::string & StringTools::import(const T & x, std::string & dst){
547 std::stringstream sstr;
548 sstr << x;
549 dst.assign(sstr.str());
550 //std::cerr << __FUNCTION__ << ": " << str << '>' << target << '\n';
551 return dst;
552}
553
554
555} // drain::
556
557#endif /* STRING_H_ */
558
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:522
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:330
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:514
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:271
static void read(std::istream &istr, std::string &s)
Read input stream and append it to s.
Definition String.h:297
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:170
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:309
static std::string replace(const std::string &src, const std::string &from, const std::string &to)
Definition String.h:96
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:212
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:273
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
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:260
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:184
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:289
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:288
Definition DataSelector.cpp:1277