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  typedef std::map<std::string,std::string> conv_map_t;
103 
105 
108  // std::map<std::string,std::string>
109  static
110  void replace(const conv_map_t & m, std::string &s, std::size_t pos = 0);
111 
112 
114  static
115  void replace(const std::string &src, const std::string &from, const std::string & to, std::string & dst);
116 
117 
119  static
120  std::string trim(const std::string &s, const std::string &trimChars=" \t\n\r");
121 
123 
130  static
131  std::string trimSymmetric(const std::string &s, const std::string &leading= "'\"", const std::string & trailing="");
132 
133 
135 
146  static
147  bool trimScan(const std::string &s, size_t & pos1, size_t & pos2, const std::string &trimChars=" \t\n");
148 
150 
163  template <class T, class C>
164  static
165  void split(const std::string & s, T & sequence, const C &separators, const std::string & trimChars=" \t\n");
166 
168  /*
169  template <class T>
170  static inline
171  void split(const std::string & s, T & sequence, char separator=',', const std::string & trimChars=" \t\n"){
172  StringTools::split(s, sequence, std::string(1,separator), trimChars);
173  }
174  */
175 
177 
192  template <class T1, class T2, class C>
193  static
194  bool split2(const std::string & s, T1 & first, T2 & second, const C &separators, const std::string & trimChars=" \t\n");
195 
197 
200  template <class T>
201  static
202  std::ostream & join(const T & container, std::ostream & ostr, char separator = 0){
203  char sep = 0;
204  for (typename T::const_iterator it = container.begin(); it != container.end(); ++it){
205  if (sep)
206  ostr << sep;
207  ostr << *it;
208  sep = separator;
209  }
210  return ostr;
211  }
212 
214 
217  template <class T>
218  static inline
219  std::string join(T & container, char separator = 0){
220  std::stringstream sstr;
221  StringTools::join(container, sstr, separator);
222  return sstr.str();
223  }
224 
226  template <unsigned int S>
227  static
228  void read(std::istream &istr, std::string & s){
229  char buffer[S];
230  while (istr.read(buffer, S)){
231  s.append(buffer, S);
232  }
233  s.append(buffer, istr.gcount());
234  }
235 
236 
238 
246  template <class T>
247  static
248  void convert(const std::string &s, T & dst);
249 
251 
257  template <class T>
258  static
259  T convert(const std::string &s);
260 
261  template <class T>
262  static
263  std::string & import(const T & src, std::string & target);
264 
265 
266 //private: CONSIDER!
267 
269 
279  template <class T>
280  static
281  const T & lazyConvert(const std::string &s, T & tmp);
282 
283 private:
284 
285  template <class T>
286  static
287  void appendString(T & sequence, const std::string & str){
288  typename T::value_type tmp;
289  sequence.insert(sequence.end(), StringTools::lazyConvert(str, tmp));
290  }
291 
292  template <class T>
293  static
294  void appendSubstring(T & sequence, const std::string & str, std::string::size_type pos, std::string::size_type n){
295 
296  if (n > 0){
297  appendString(sequence, str.substr(pos, n));
298  }
299  else {
300  appendString(sequence, "");
301  }
302 
303  }
304 
305 };
306 
307 
308 template <class T, class C>
309 void StringTools::split(const std::string & str, T & sequence, const C & separators, const std::string & trimChars){
310 
311  sequence.clear();
312 
313  const bool TRIM = !trimChars.empty();
314  const std::string::size_type n = str.size();
315 
316  std::string::size_type pos1 = 0; // Start of segment
317  std::string::size_type pos2 = n; // std::string::npos; // End of segment (index of last char + 1)
318 
319  if (false){ //separators.empty()){ // = no split! :-)
320 
321  if (TRIM){
322  StringTools::trimScan(str, pos1, pos2, trimChars);
323  appendSubstring(sequence, str, pos1, pos2-pos1);
324  }
325  else
326  appendString(sequence, str);
327 
328  return;
329  }
330  else {
331 
332  // Index of the next separator position
333  std::string::size_type pos = pos1; // "irreversible"
334 
335  while (true) {
336 
337  pos1 = pos;
338  pos = str.find_first_of(separators, pos);
339  if (pos == std::string::npos){
340  pos2 = n;
341  if (TRIM)
342  StringTools::trimScan(str, pos1, pos2, trimChars);
343  appendSubstring(sequence, str, pos1, pos2-pos1);
344  return;
345  }
346  else {
347  pos2 = pos;
348  if (TRIM)
349  StringTools::trimScan(str, pos1, pos2, trimChars);
350  appendSubstring(sequence, str, pos1, pos2-pos1);
351  pos = str.find_first_not_of(trimChars, pos+1); // if separator is space, or other also in trimChars
352  //pos = str.find_last_not_of(trimChars, pos);
353  //++pos; // for the next round
354  }
355 
356  }
357  }
358 }
359 
360 /*
361 template <>
362 bool StringTools::split2(const std::string & s, std::string & first, std::string & second, const char *separators, const std::string & trimChars);
363 */
364 
365 template <class T1, class T2, class S>
366 bool StringTools::split2(const std::string & s, T1 & first, T2 & second, const S & separators, const std::string & trimChars){
367 
368  std::size_t i = s.find_first_of(separators);
369 
370  if (i != std::string::npos){ // input of type "key=value" found
371 
372  std::string srcFirst(s, 0, i);
373  ++i;
374  std::string srcSecond(s, std::min(s.size(), i));
375 
376  if (!trimChars.empty()){
377  first = lazyConvert(StringTools::trim(srcFirst, trimChars), first); // first=first should not clear the object!
378  }
379  else {
380  first = lazyConvert(srcFirst, first); // Note: first=first should not clear the object!
381  }
382 
383  if (!srcSecond.empty()){
384  if (!trimChars.empty()){
385  second = lazyConvert(StringTools::trim(srcSecond), second);
386  }
387  else {
388  second = lazyConvert(srcSecond, second);
389  }
390  }
391 
392  /*
393  ++i;
394  if (i<s.size()){
395  //std::cerr << "toka " << s.substr(i) << '\n';
396  if (!trimChars.empty()){
397  // sstr2 << StringTools::trim(s.substr(i), trimChars);
398  // sstr2 >> second;
399  second = lazyConvert(StringTools::trim(s.substr(i), trimChars), second);
400  }
401  else {
402  // sstr2 << s.substr(i);
403  // sstr2 >> second;
404  second = lazyConvert(s.substr(i), second);
405  }
406  }
407  */
408  return true;
409  }
410  else {
411  // std::stringstream sstr;
412  if (trimChars.empty()){
413  //sstr << s;
414  //sstr >> first;
415  first = lazyConvert(s, first);
416  }
417  else {
418  // sstr << StringTools::trim(s, trimChars);
419  // sstr >> first;
420  first = lazyConvert(StringTools::trim(s, trimChars), first);
421  }
422  return false;
423  }
424 
425 
426 }
427 
428 
429 
430 
431 
432 
433 
434 template <>
435 inline
436 const std::string & StringTools::lazyConvert(const std::string &str, std::string & tmp){
437  return str;
438 }
439 
440 
441 template <class T>
442 inline
443 const T & StringTools::lazyConvert(const std::string &str, T & dst){
444  std::stringstream sstr(str);
445  sstr >> dst;
446  return dst;
447 }
448 
449 template <class T>
450 inline
451 void StringTools::convert(const std::string &str, T & dst){
452  dst = lazyConvert(str, dst);
453 }
454 
455 
456 template <class T>
457 inline
458 T StringTools::convert(const std::string &s){
459  T tmp;
460  tmp = lazyConvert(s, tmp);
461  return tmp;
462 }
463 
464 
465 
466 
467 template <>
468 inline
469 std::string & StringTools::import(const std::string & src, std::string & dst){
470  dst = src;
471  return dst;
472 }
473 
474 template <class T>
475 std::string & StringTools::import(const T & x, std::string & dst){
476  std::stringstream sstr;
477  sstr << x;
478  dst.assign(sstr.str());
479  //std::cerr << __FUNCTION__ << ": " << str << '>' << target << '\n';
480  return dst;
481 }
482 
483 
484 } // drain::
485 
486 #endif /* STRING_H_ */
487 
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:451
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:270
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:443
static void read(std::istream &istr, std::string &s)
Read input stream and append it to s.
Definition: String.h:228
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:137
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:202
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:249
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:179
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:309
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:151
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:219
Definition: DataSelector.cpp:1277