String.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood 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 
51 namespace drain {
52 
53 class StringTools {
54 
55 public:
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 
123  static
124  void replace(const std::string &src, const std::string &from, const std::string & to, std::string & dst);
125 
126 
128  static
129  std::string trim(const std::string &s, const std::string &trimChars=" \t\n\r");
130 
132 
139  static
140  std::string trimSymmetric(const std::string &s, const std::string &leading= "'\"", const std::string & trailing="");
141 
142 
144 
155  static
156  bool trimScan(const std::string &s, size_t & pos1, size_t & pos2, const std::string &trimChars=" \t\n");
157 
159 
172  template <class T, class C>
173  static
174  void split(const std::string & s, T & sequence, const C &separators, const std::string & trimChars=" \t\n");
175 
177  /*
178  template <class T>
179  static inline
180  void split(const std::string & s, T & sequence, char separator=',', const std::string & trimChars=" \t\n"){
181  StringTools::split(s, sequence, std::string(1,separator), trimChars);
182  }
183  */
184 
186 
201  template <class T1, class T2, class C>
202  static
203  bool split2(const std::string & s, T1 & first, T2 & second, const C &separators, const std::string & trimChars=" \t\n");
204 
206 
209  template <class T>
210  static
211  std::ostream & join(const T & container, std::ostream & ostr, char separator = 0){
212  char sep = 0;
213  for (typename T::const_iterator it = container.begin(); it != container.end(); ++it){
214  if (sep)
215  ostr << sep;
216  ostr << *it;
217  sep = separator;
218  }
219  return ostr;
220  }
221 
223 
226  template <class T>
227  static inline
228  std::string join(T & container, char separator = 0){
229  std::stringstream sstr;
230  StringTools::join(container, sstr, separator);
231  return sstr.str();
232  }
233 
235  template <unsigned int S>
236  static
237  void read(std::istream &istr, std::string & s){
238  char buffer[S];
239  while (istr.read(buffer, S)){
240  s.append(buffer, S);
241  }
242  s.append(buffer, istr.gcount());
243  }
244 
245 
247 
255  template <class T>
256  static
257  void convert(const std::string &s, T & dst);
258 
260 
266  template <class T>
267  static
268  T convert(const std::string &s);
269 
270  template <class T>
271  static
272  std::string & import(const T & src, std::string & target);
273 
274 
275 //private: CONSIDER!
276 
278 
288  template <class T>
289  static
290  const T & lazyConvert(const std::string &s, T & tmp);
291 
292 private:
293 
294  template <class T>
295  static
296  void appendString(T & sequence, const std::string & str){
297  typename T::value_type tmp;
298  sequence.insert(sequence.end(), StringTools::lazyConvert(str, tmp));
299  }
300 
301  template <class T>
302  static
303  void appendSubstring(T & sequence, const std::string & str, std::string::size_type pos, std::string::size_type n){
304 
305  if (n > 0){
306  appendString(sequence, str.substr(pos, n));
307  }
308  else {
309  appendString(sequence, "");
310  }
311 
312  }
313 
314 };
315 
316 
317 template <class T, class C>
318 void StringTools::split(const std::string & str, T & sequence, const C & separators, const std::string & trimChars){
319 
320  sequence.clear();
321 
322  const bool TRIM = !trimChars.empty();
323  const std::string::size_type n = str.size();
324 
325  std::string::size_type pos1 = 0; // Start of segment
326  std::string::size_type pos2 = n; // std::string::npos; // End of segment (index of last char + 1)
327 
328  if (false){ //separators.empty()){ // = no split! :-)
329 
330  if (TRIM){
331  StringTools::trimScan(str, pos1, pos2, trimChars);
332  appendSubstring(sequence, str, pos1, pos2-pos1);
333  }
334  else
335  appendString(sequence, str);
336 
337  return;
338  }
339  else {
340 
341  // Index of the next separator position
342  std::string::size_type pos = pos1; // "irreversible"
343 
344  while (true) {
345 
346  pos1 = pos;
347  pos = str.find_first_of(separators, pos);
348  if (pos == std::string::npos){
349  pos2 = n;
350  if (TRIM)
351  StringTools::trimScan(str, pos1, pos2, trimChars);
352  appendSubstring(sequence, str, pos1, pos2-pos1);
353  return;
354  }
355  else {
356  pos2 = pos;
357  if (TRIM)
358  StringTools::trimScan(str, pos1, pos2, trimChars);
359  appendSubstring(sequence, str, pos1, pos2-pos1);
360  pos = str.find_first_not_of(trimChars, pos+1); // if separator is space, or other also in trimChars
361  //pos = str.find_last_not_of(trimChars, pos);
362  //++pos; // for the next round
363  }
364 
365  }
366  }
367 }
368 
369 /*
370 template <>
371 bool StringTools::split2(const std::string & s, std::string & first, std::string & second, const char *separators, const std::string & trimChars);
372 */
373 
374 template <class T1, class T2, class S>
375 bool StringTools::split2(const std::string & s, T1 & first, T2 & second, const S & separators, const std::string & trimChars){
376 
377  std::size_t i = s.find_first_of(separators);
378 
379  if (i != std::string::npos){ // input of type "key=value" found
380 
381  std::string srcFirst(s, 0, i);
382  ++i;
383  std::string srcSecond(s, std::min(s.size(), i));
384 
385  if (!trimChars.empty()){
386  first = lazyConvert(StringTools::trim(srcFirst, trimChars), first); // first=first should not clear the object!
387  }
388  else {
389  first = lazyConvert(srcFirst, first); // Note: first=first should not clear the object!
390  }
391 
392  if (!srcSecond.empty()){
393  if (!trimChars.empty()){
394  second = lazyConvert(StringTools::trim(srcSecond), second);
395  }
396  else {
397  second = lazyConvert(srcSecond, second);
398  }
399  }
400 
401  /*
402  ++i;
403  if (i<s.size()){
404  //std::cerr << "toka " << s.substr(i) << '\n';
405  if (!trimChars.empty()){
406  // sstr2 << StringTools::trim(s.substr(i), trimChars);
407  // sstr2 >> second;
408  second = lazyConvert(StringTools::trim(s.substr(i), trimChars), second);
409  }
410  else {
411  // sstr2 << s.substr(i);
412  // sstr2 >> second;
413  second = lazyConvert(s.substr(i), second);
414  }
415  }
416  */
417  return true;
418  }
419  else {
420  // std::stringstream sstr;
421  if (trimChars.empty()){
422  //sstr << s;
423  //sstr >> first;
424  first = lazyConvert(s, first);
425  }
426  else {
427  // sstr << StringTools::trim(s, trimChars);
428  // sstr >> first;
429  first = lazyConvert(StringTools::trim(s, trimChars), first);
430  }
431  return false;
432  }
433 
434 
435 }
436 
437 
438 
439 
440 
441 
442 
443 template <>
444 inline
445 const std::string & StringTools::lazyConvert(const std::string &str, std::string & tmp){
446  return str;
447 }
448 
449 
450 template <class T>
451 inline
452 const T & StringTools::lazyConvert(const std::string &str, T & dst){
453  std::stringstream sstr(str);
454  sstr >> dst;
455  return dst;
456 }
457 
458 template <class T>
459 inline
460 void StringTools::convert(const std::string &str, T & dst){
461  dst = lazyConvert(str, dst);
462 }
463 
464 
465 template <class T>
466 inline
467 T StringTools::convert(const std::string &s){
468  T tmp;
469  tmp = lazyConvert(s, tmp);
470  return tmp;
471 }
472 
473 
474 
475 
476 template <>
477 inline
478 std::string & StringTools::import(const std::string & src, std::string & dst){
479  dst = src;
480  return dst;
481 }
482 
483 template <class T>
484 std::string & StringTools::import(const T & x, std::string & dst){
485  std::stringstream sstr;
486  sstr << x;
487  dst.assign(sstr.str());
488  //std::cerr << __FUNCTION__ << ": " << str << '>' << target << '\n';
489  return dst;
490 }
491 
492 
493 } // drain::
494 
495 #endif /* STRING_H_ */
496 
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:460
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:282
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:452
static void read(std::istream &istr, std::string &s)
Read input stream and append it to s.
Definition: String.h:237
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:149
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:211
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:261
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:191
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:318
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:163
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:228
Definition: DataSelector.cpp:1277