OpenMS  2.5.0
StringUtils.h
Go to the documentation of this file.
1 // --------------------------------------------------------------------------
2 // OpenMS -- Open-Source Mass Spectrometry
3 // --------------------------------------------------------------------------
4 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5 // ETH Zurich, and Freie Universitaet Berlin 2002-2020.
6 //
7 // This software is released under a three-clause BSD license:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of any author or any participating institution
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 // For a full list of authors, refer to the file AUTHORS.
17 // --------------------------------------------------------------------------
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // --------------------------------------------------------------------------
31 // $Maintainer: Timo Sachsenberg, Chris Bielow $
32 // $Authors: Marc Sturm, Stephan Aiche, Chris Bielow $
33 // --------------------------------------------------------------------------
34 
35 #pragma once
36 
37 #include <OpenMS/CONCEPT/Types.h>
42 
43 #include <QtCore/QString>
44 #include <boost/spirit/include/qi.hpp>
45 #include <boost/spirit/include/karma.hpp>
46 
47 #include <string>
48 #include <vector>
49 
50 
51 namespace OpenMS
52 {
53  class String;
54 
55  namespace StringConversions
56  {
57 
58  // Karma full precision float policy
59  template <typename T>
60  class BK_PrecPolicy : public boost::spirit::karma::real_policies<T>
61  {
62  public:
63  static unsigned int precision(T) { return writtenDigits<T>(T()); }
64  };
65  typedef boost::spirit::karma::real_generator<float, BK_PrecPolicy<float> > BK_PrecPolicyFloat_type;
67  typedef boost::spirit::karma::real_generator<double, BK_PrecPolicy<double> > BK_PrecPolicyDouble_type;
69  typedef boost::spirit::karma::real_generator<long double, BK_PrecPolicy<long double> > BK_PrecPolicyLongDouble_type;
71 
72  // toString functions (single argument)
73 
76  template <typename T>
77  inline void append(const T& i, String& target)
78  {
79  std::back_insert_iterator<std::string> sink(target);
80  boost::spirit::karma::generate(sink, i);
81  }
82 
84  template <typename T>
85  inline String toString(const T& i)
86  {
87  //std::stringstream s;
88  //s << i;
89  //return s.str();
90  String str;
91  append(i, str);
92  return str;
93  }
94 
95 
98  inline void appendLowP(float f, String& target)
99  {
100  std::back_insert_iterator<std::string> sink(target);
101  boost::spirit::karma::generate(sink, f);
102  }
104  inline String toStringLowP(float f)
105  {
106  String str;
107  appendLowP(f, str);
108  return str;
109  }
110 
111 
114  inline void appendLowP(double d, String& target)
115  {
116  std::back_insert_iterator<std::string> sink(target);
117  boost::spirit::karma::generate(sink, d);
118  }
120  inline String toStringLowP(double d)
121  {
122  String str;
123  appendLowP(d, str);
124  return str;
125  }
126 
127 
129  inline void appendLowP(long double ld, String& target)
130  {
131  std::back_insert_iterator<std::string> sink(target);
132  boost::spirit::karma::generate(sink, ld);
133  }
135  inline String toStringLowP(long double ld)
136  {
137  String str;
138  appendLowP(ld, str);
139  return str;
140  }
141 
142 
143 
145  inline void append(float f, String& target)
146  {
147  std::back_insert_iterator<std::string> sink(target);
148  boost::spirit::karma::generate(sink, BK_PrecPolicyFloat, f);
149  }
151  inline String toString(float f)
152  {
153  String str;
154  append(f, str);
155  return str;
156  }
157 
158 
159 
161  inline void append(double d, String& target)
162  {
163  std::back_insert_iterator<std::string> sink(target);
164  boost::spirit::karma::generate(sink, BK_PrecPolicyDouble, d);
165  }
167  inline String toString(double d)
168  {
169  String str;
170  append(d, str);
171  return str;
172  }
173 
174 
176  inline void append(long double ld, String& target)
177  {
178  std::back_insert_iterator<std::string> sink(target);
179  boost::spirit::karma::generate(sink, BK_PrecPolicyLongDouble, ld);
180  }
182  inline String toString(long double ld)
183  {
184  String str;
185  append(ld, str);
186  return str;
187  }
188 
189 
190  inline void append(const DataValue& d, bool full_precision, String& target)
191  {
192  target += d.toString(full_precision);
193  }
194  inline String toString(const DataValue& d, bool full_precision)
195  {
196  return d.toString(full_precision);
197  }
198 
199 
200 
201  inline String toString(const char c)
202  {
203  return std::string(1, c);
204  }
205 
206  inline String toString(const std::string& s)
207  {
208  return s;
209  }
210 
211  inline String toString(const char* s)
212  {
213  return std::string(s);
214  }
215 
217  inline String toString()
218  {
219  return String();
220  }
221 
222  inline String toString(const char* s, size_t length)
223  {
224  String res;
225  size_t count = 0;
226  while (count < length)
227  {
228  res += *(s + count);
229  ++count;
230  }
231  return res;
232  }
233  }
234 
235  class OPENMS_DLLAPI StringUtils
236  {
237 
238 public:
239 
240  //
242  //
243  static String numberLength(double d, UInt n)
244  {
245  std::stringstream s;
246  //reserve one space for the minus sign
247  Int sign = 0;
248  if (d < 0)
249  sign = 1;
250  d = fabs(d);
251 
252  if (d < pow(10.0, Int(n - sign - 2)))
253  {
254  s.precision(writtenDigits(d));
255  if (sign == 1)
256  s << "-";
257  s << d;
258  }
259  else
260  {
261  UInt exp = 0;
262  while (d > pow(10.0, Int(n - sign - 4)))
263  {
264  d /= 10;
265  ++exp;
266  }
267  d = Int(d) / 10.0;
268  exp += 1;
269  if (sign == 1)
270  s << "-";
271  s << d << "e";
272  if (exp < 10)
273  s << "0";
274  s << exp;
275  }
276  return s.str().substr(0, n);
277  }
278 
279  static String number(double d, UInt n)
280  {
281  return QString::number(d, 'f', n);
282  }
283 
284  static String& fillLeft(String & this_s, char c, UInt size)
285  {
286  if (this_s.size() < size)
287  {
288  this_s.std::string::operator=(String(size - this_s.size(), c) + this_s);
289  }
290  return this_s;
291  }
292 
293  static String& fillRight(String & this_s, char c, UInt size)
294  {
295  if (this_s.size() < size)
296  {
297  this_s.std::string::operator=(this_s + String(size - this_s.size(), c));
298  }
299  return this_s;
300  }
301 
302 
303  static bool hasPrefix(const String & this_s, const String & string)
304  {
305  if (string.size() > this_s.size())
306  {
307  return false;
308  }
309  if (string.empty())
310  {
311  return true;
312  }
313  return this_s.compare(0, string.size(), string) == 0;
314  }
315 
316  static bool hasSuffix(const String & this_s, const String& string)
317  {
318  if (string.size() > this_s.size())
319  {
320  return false;
321  }
322  if (string.empty())
323  {
324  return true;
325  }
326  return this_s.compare(this_s.size() - string.size(), string.size(), string) == 0;
327  }
328 
329  static bool hasSubstring(const String & this_s, const String& string)
330  {
331  return this_s.find(string) != std::string::npos;
332  }
333 
334  static bool has(const String & this_s, Byte byte)
335  {
336  return this_s.find(char(byte)) != std::string::npos;
337  }
338 
339  static String prefix(const String & this_s, size_t length)
340  {
341  if (length > this_s.size())
342  {
343  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
344  }
345  return this_s.substr(0, length);
346  }
347 
348  static String suffix(const String & this_s, size_t length)
349  {
350  if (length > this_s.size())
351  {
352  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
353  }
354  return this_s.substr(this_s.size() - length, length);
355  }
356 
357  static String prefix(const String & this_s, Int length)
358  {
359  if (length < 0)
360  {
361  throw Exception::IndexUnderflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, 0);
362  }
363  if (length > Int(this_s.size()))
364  {
365  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
366  }
367  return this_s.substr(0, length);
368  }
369 
370  static String suffix(const String & this_s, Int length)
371  {
372  if (length < 0)
373  {
374  throw Exception::IndexUnderflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, 0);
375  }
376  if (length > Int(this_s.size()))
377  {
378  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
379  }
380  return this_s.substr(this_s.size() - length, length);
381  }
382 
383  static String prefix(const String & this_s, char delim)
384  {
385  Size pos = this_s.find(delim);
386  if (pos == std::string::npos) //char not found
387  {
388  throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
389  String(delim));
390  }
391  return this_s.substr(0, pos);
392  }
393 
394  static String suffix(const String & this_s, char delim)
395  {
396  Size pos = this_s.rfind(delim);
397  if (pos == std::string::npos) //char not found
398  {
399  throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
400  String(delim));
401  }
402  return this_s.substr(++pos);
403  }
404 
405  static String substr(const String & this_s, size_t pos, size_t n)
406  {
407  Size begin = std::min(pos, this_s.size());
408  return static_cast<String>(this_s.std::string::substr(begin, n));
409  }
410 
411  static String chop(const String & this_s, Size n)
412  {
413  Size end = 0;
414  if (n < this_s.size())
415  {
416  end = this_s.size() - n;
417  }
418  return String(this_s.begin(), this_s.begin() + end);
419  }
420 
421  static String& trim(String & this_s)
422  {
423  //search for the begin of truncated string
424  std::string::iterator begin = this_s.begin();
425  while (begin != this_s.end() && (*begin == ' ' || *begin == '\t' || *begin == '\n' || *begin == '\r'))
426  {
427  ++begin;
428  }
429 
430  //all characters are whitespaces
431  if (begin == this_s.end())
432  {
433  this_s.clear();
434  return this_s;
435  }
436 
437  //search for the end of truncated string
438  std::string::iterator end = this_s.end();
439  end--;
440  while (end != begin && (*end == ' ' || *end == '\n' || *end == '\t' || *end == '\r'))
441  {
442  --end;
443  }
444  ++end;
445 
446  //no characters are whitespaces
447  if (begin == this_s.begin() && end == this_s.end())
448  {
449  return this_s;
450  }
451 
452  // TODO:
453  // string::operator=(std::string(begin, end));
454  this_s.std::string::operator=(std::string(begin, end));
455 
456  return this_s;
457  }
458 
459  static String& quote(String & this_s, char q, String::QuotingMethod method)
460  {
461  if (method == String::ESCAPE)
462  {
463  this_s.substitute(String("\\"), String("\\\\"));
464  this_s.substitute(String(q), "\\" + String(q));
465  }
466  else if (method == String::DOUBLE)
467  this_s.substitute(String(q), String(q) + String(q));
468  this_s.std::string::operator=(q + this_s + q);
469  return this_s;
470  }
471 
472  static String& unquote(String & this_s, char q, String::QuotingMethod method)
473  {
474  // check if input string matches output format of the "quote" method:
475  if ((this_s.size() < 2) || (this_s[0] != q) || (this_s[this_s.size() - 1] != q))
476  {
478  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
479  "'" + this_s + "' does not have the expected format of a quoted string");
480  }
481  this_s.std::string::operator=(this_s.substr(1, this_s.size() - 2)); // remove quotation marks
482  if (method == String::ESCAPE)
483  {
484  this_s.substitute("\\" + String(q), String(q));
485  this_s.substitute(String("\\\\"), String("\\"));
486  }
487  else if (method == String::DOUBLE)
488  this_s.substitute(String(q) + String(q), String(q));
489  return this_s;
490  }
491 
492  static String& simplify(String & this_s)
493  {
494  String simple;
495 
496  bool last_was_whitespace = false;
497  for (std::string::iterator it = this_s.begin(); it != this_s.end(); ++it)
498  {
499  if (*it == ' ' || *it == '\n' || *it == '\t' || *it == '\r')
500  {
501  if (!last_was_whitespace)
502  {
503  simple += ' ';
504  }
505  last_was_whitespace = true;
506  }
507  else
508  {
509  simple += *it;
510  last_was_whitespace = false;
511  }
512  }
513 
514  this_s.swap(simple);
515  return this_s;
516  }
517 
518  static String random(UInt length)
519  {
520  srand(time(nullptr));
521  String tmp(length, '.');
522  size_t random;
523  for (Size i = 0; i < length; ++i)
524  {
525  random = static_cast<size_t>(floor((static_cast<double>(rand()) / (double(RAND_MAX) + 1)) * 62.0));
526  if (random < 10)
527  {
528  tmp[i] = static_cast<char>(random + 48);
529  }
530  else if (random < 36)
531  {
532  tmp[i] = static_cast<char>(random + 55);
533  }
534  else
535  {
536  tmp[i] = static_cast<char>(random + 61);
537  }
538  }
539  return tmp;
540  }
541 
542  static String& reverse(String & this_s)
543  {
544  String tmp = this_s;
545  for (Size i = 0; i != this_s.size(); ++i)
546  {
547  this_s[i] = tmp[this_s.size() - 1 - i];
548  }
549  return this_s;
550  }
551 
552  static bool split(const String & this_s, const char splitter, std::vector<String>& substrings,
553  bool quote_protect)
554  {
555  substrings.clear();
556  if (this_s.empty())
557  return false;
558 
559  Size nsplits = count(this_s.begin(), this_s.end(), splitter);
560 
561  if (!quote_protect && (nsplits == 0))
562  {
563  substrings.push_back(this_s);
564  return false;
565  }
566 
567  // splitter(s) found
568  substrings.reserve(nsplits + 1);
569 
570  // why is "this_s." needed here?
571  std::string::const_iterator begin = this_s.begin();
572  std::string::const_iterator end = this_s.begin();
573 
574  if (quote_protect)
575  {
576  Int quote_count(0);
577  for (; end != this_s.end(); ++end)
578  {
579  if (*end == '"')
580  {
581  ++quote_count;
582  }
583  if ((quote_count % 2 == 0) && (*end == splitter))
584  {
585  String block = String(begin, end);
586  block.trim();
587  if ((block.size() >= 2) && ((block.prefix(1) == String("\"")) ^
588  (block.suffix(1) == String("\""))))
589  { // block has start or end quote, but not both
590  // (one quote is somewhere in the middle)
592  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
593  String("Could not dequote string '") + block +
594  "' due to wrongly placed '\"'.");
595  }
596  else if ((block.size() >= 2) && (block.prefix(1) == String("\"")) &&
597  (block.suffix(1) == String("\"")))
598  { // block has start and end quotes --> remove them
599  block = block.substr(1, block.size() - 2);
600  }
601  substrings.push_back(block);
602  begin = end + 1;
603  }
604  }
605  // no valid splitter found - return empty list
606  if (substrings.empty())
607  {
608  substrings.push_back(this_s);
609  return false;
610  }
611 
612  String block = String(begin, end);
613  block.trim();
614  if ((block.size() >= 2) && ((block.prefix(1) == String("\"")) ^
615  (block.suffix(1) == String("\""))))
616  { // block has start or end quote but not both
617  // (one quote is somewhere in the middle)
619  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
620  String("Could not dequote string '") + block +
621  "' due to wrongly placed '\"'.");
622  }
623  else if ((block.size() >= 2) && (block.prefix(1) == String("\"")) &&
624  (block.suffix(1) == String("\"")))
625  { // block has start and end quotes --> remove them
626  block = block.substr(1, block.size() - 2);
627  }
628  substrings.push_back(block);
629  }
630  else // do not honor quotes
631  {
632  for (; end != this_s.end(); ++end)
633  {
634  if (*end == splitter)
635  {
636  substrings.push_back(String(begin, end));
637  begin = end + 1;
638  }
639  }
640  substrings.push_back(String(begin, end));
641  }
642 
643  // at this point we are sure that there are at least two components
644  return true;
645  }
646 
647  static bool split(const String & this_s, const String& splitter, std::vector<String>& substrings)
648  {
649  substrings.clear();
650  if (this_s.empty())
651  return false;
652 
653  if (splitter.empty()) // split after every character:
654  {
655  substrings.resize(this_s.size());
656  for (Size i = 0; i < this_s.size(); ++i)
657  substrings[i] = this_s[i];
658  return true;
659  }
660 
661  Size len = splitter.size(), start = 0, pos = this_s.find(splitter);
662  if (len == 0)
663  len = 1;
664  while (pos != std::string::npos)
665  {
666  substrings.push_back(this_s.substr(start, pos - start));
667  start = pos + len;
668  pos = this_s.find(splitter, start);
669  }
670  substrings.push_back(this_s.substr(start, this_s.size() - start));
671  return substrings.size() > 1;
672  }
673 
674  static bool split_quoted(const String & this_s, const String& splitter, std::vector<String>& substrings,
675  char q, String::QuotingMethod method)
676  {
677  substrings.clear();
678  if (this_s.empty() || splitter.empty())
679  return false;
680 
681  bool in_quote = false;
682  char targets[2] = {q, splitter[0]}; // targets for "find_first_of"
683  std::string rest = splitter.substr(1, splitter.size() - 1);
684  Size start = 0;
685  for (Size i = 0; i < this_s.size(); ++i)
686  {
687  if (in_quote) // skip to closing quotation mark
688  {
689  bool embedded = false;
690  if (method == String::ESCAPE)
691  {
692  for (; i < this_s.size(); ++i)
693  {
694  if (this_s[i] == '\\')
695  embedded = !embedded;
696  else if ((this_s[i] == q) && !embedded)
697  break;
698  else
699  embedded = false;
700  }
701  }
702  else // method: NONE or DOUBLE
703  {
704  for (; i < this_s.size(); ++i)
705  {
706  if (this_s[i] == q)
707  {
708  if (method == String::NONE)
709  break; // found
710  // next character is also closing quotation mark:
711  if ((i < this_s.size() - 1) && (this_s[i + 1] == q))
712  embedded = !embedded;
713  // even number of subsequent quotes (doubled) => found
714  else if (!embedded)
715  break;
716  // odd number of subsequent quotes => belongs to a pair
717  else
718  embedded = false;
719  }
720  }
721  }
722  in_quote = false; // end of quote reached
723  }
724  else
725  {
726  i = this_s.find_first_of(targets, i, 2);
727  if (i == std::string::npos)
728  break; // nothing found
729  if (this_s[i] == q)
730  in_quote = true;
731  else if (this_s.compare(i + 1, rest.size(), rest) == 0) // splitter found
732  {
733  substrings.push_back(this_s.substr(start, i - start));
734  start = i + splitter.size();
735  i = start - 1; // increased by loop
736  }
737  }
738  }
739  if (in_quote) // reached end without finding closing quotation mark
740  {
742  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
743  "unbalanced quotation marks in string '" + this_s + "'");
744  }
745  substrings.push_back(this_s.substr(start, this_s.size() - start));
746  return substrings.size() > 1;
747  }
748 
749  static QString toQString(const String & this_s)
750  {
751  return QString(this_s.c_str());
752  }
753 
754  static Int toInt(const String & this_s)
755  {
756  Int ret;
757 
758  // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
759  // so don't change this unless you have benchmarks for all platforms!
760  String::ConstIterator it = this_s.begin();
761  if (!boost::spirit::qi::phrase_parse(it, this_s.end(), boost::spirit::qi::int_, boost::spirit::ascii::space, ret))
762  {
763  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to an integer value");
764  }
765  // was the string parsed (white spaces are skipped automatically!) completely? If not, we have a problem because a previous split might have used the wrong split char
766  if (it != this_s.end())
767  {
768  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Prefix of string '") + this_s + "' successfully converted to an integer value. Additional characters found at position " + (int)(distance(this_s.begin(), it) + 1));
769  }
770  return ret;
771  }
772 
773  static float toFloat(const String& this_s)
774  {
775  float ret;
776 
777  // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
778  // so don't change this unless you have benchmarks for all platforms!
779  String::ConstIterator it = this_s.begin();
780  if (!boost::spirit::qi::phrase_parse(it, this_s.end(), parse_float_, boost::spirit::ascii::space, ret))
781  {
782  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to a float value");
783  }
784  // was the string parsed (white spaces are skipped automatically!) completely? If not, we have a problem because a previous split might have used the wrong split char
785  if (it != this_s.end())
786  {
787  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Prefix of string '") + this_s + "' successfully converted to a float value. Additional characters found at position " + (int)(distance(this_s.begin(), it) + 1));
788  }
789  return ret;
790  }
791 
799  static double toDouble(const String& s)
800  {
801  double ret;
802  // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
803  // so don't change this unless you have benchmarks for all platforms!
804  String::ConstIterator it = s.begin();
805  if (!boost::spirit::qi::phrase_parse(it, s.end(), parse_double_, boost::spirit::ascii::space, ret))
806  {
807  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + s + "' to a double value");
808  }
809  // was the string parsed (white spaces are skipped automatically!) completely? If not, we have a problem because a previous split might have used the wrong split char
810  if (it != s.end())
811  {
812  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Prefix of string '") + s + "' successfully converted to a double value. Additional characters found at position " + (int)(distance(s.begin(), it) + 1));
813  }
814  return ret;
815  }
816 
821  template <typename IteratorT>
822  static bool extractDouble(IteratorT& begin, const IteratorT& end, double& target)
823  {
824  // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
825  // so don't change this unless you have benchmarks for all platforms!
826 
827  // qi::parse() does not consume whitespace before or after the double (qi::parse_phrase() would).
828  return boost::spirit::qi::parse(begin, end, parse_double_, target);
829  }
830 
831 
832  static String& toUpper(String & this_s)
833  {
834  std::transform(this_s.begin(), this_s.end(), this_s.begin(), (int (*)(int))toupper);
835  return this_s;
836  }
837 
838  static String& firstToUpper(String & this_s)
839  {
840  if (this_s.size() != 0)
841  {
842  this_s[0] = toupper(this_s[0]);
843  }
844  return this_s;
845  }
846 
847  static String& toLower(String & this_s)
848  {
849  std::transform(this_s.begin(), this_s.end(), this_s.begin(), (int (*)(int))tolower);
850  return this_s;
851  }
852 
853  static String& substitute(String & this_s, char from, char to)
854  {
855  std::replace(this_s.begin(), this_s.end(), from, to);
856  return this_s;
857  }
858 
859  static String& substitute(String & this_s, const String& from, const String& to)
860  {
861  if (!from.empty())
862  {
863  std::vector<String> parts;
864  this_s.split(from, parts);
865  this_s.concatenate(parts.begin(), parts.end(), to);
866  }
867  return this_s;
868  }
869 
870  static String& remove(String & this_s, char what)
871  {
872  this_s.erase(std::remove(this_s.begin(), this_s.end(), what), this_s.end());
873  return this_s;
874  }
875 
876  static String& ensureLastChar(String & this_s, char end)
877  {
878  if (!this_s.hasSuffix(end))
879  this_s.append(1, end);
880  return this_s;
881  }
882 
883  static String& removeWhitespaces(String& this_s)
884  {
885  std::string::const_iterator it = this_s.begin();
886  std::string::iterator dest = this_s.begin();
887  std::string::const_iterator it_end = this_s.end();
888  bool has_spaces(false);
889  while (it != it_end)
890  {
891  const char c = *it;
892  if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
893  {
894  ++it;
895  has_spaces = true;
896  continue; // no need to copy a whitespace
897  }
898  // copy to the left, if we had a whitespace before
899  if (has_spaces) *dest = *it;
900  // advance both
901  ++dest;
902  ++it;
903  }
904 
905  // shorten result
906  if (has_spaces) this_s.resize(dest - this_s.begin());
907 
908  return this_s;
909  }
910 
911  private:
912 
913  /*
914  @brief A fixed Boost:pi real parser policy, capable of dealing with 'nan' without crashing
915 
916  The original Boost implementation has a bug, see https://svn.boost.org/trac/boost/ticket/6955.
917  Can be removed if Boost 1.60 or above is required
918 
919  */
920  template <typename T>
921  struct real_policies_NANfixed_ : boost::spirit::qi::real_policies<T>
922  {
923  template <typename Iterator, typename Attribute>
924  static bool
925  parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
926  {
927  if (first == last)
928  return false; // end of input reached
929 
930  if (*first != 'n' && *first != 'N')
931  return false; // not "nan"
932 
933  // nan[(...)] ?
934  if (boost::spirit::qi::detail::string_parse("nan", "NAN", first, last, boost::spirit::qi::unused))
935  {
936  if (first != last && *first == '(') /* this check is broken in boost 1.49 - (at least) 1.54; fixed in 1.60 */
937  {
938  // skip trailing (...) part
939  Iterator i = first;
940 
941  while (++i != last && *i != ')')
942  ;
943  if (i == last)
944  return false; // no trailing ')' found, give up
945 
946  first = ++i;
947  }
948  attr_ = std::numeric_limits<T>::quiet_NaN();
949  return true;
950  }
951  return false;
952  }
953  };
954 
955  // Qi parsers using the 'real_policies_NANfixed_' template which allows for 'nan'
956  // (the original Boost implementation has a bug, see https://svn.boost.org/trac/boost/ticket/6955)
957  static boost::spirit::qi::real_parser<double, real_policies_NANfixed_<double> > parse_double_;
958  static boost::spirit::qi::real_parser<float, real_policies_NANfixed_<float> > parse_float_;
959 
960  };
961 
962 } // namespace OPENMS
963 
OpenMS::StringUtils::toInt
static Int toInt(const String &this_s)
Definition: StringUtils.h:754
OpenMS::StringConversions::BK_PrecPolicyDouble
const BK_PrecPolicyDouble_type BK_PrecPolicyDouble
Definition: StringUtils.h:68
OpenMS::StringUtils::substr
static String substr(const String &this_s, size_t pos, size_t n)
Definition: StringUtils.h:405
OpenMS::String::QuotingMethod
QuotingMethod
How to handle embedded quotes when quoting strings.
Definition: String.h:81
OpenMS::StringUtils::hasSubstring
static bool hasSubstring(const String &this_s, const String &string)
Definition: StringUtils.h:329
OpenMS::writtenDigits
constexpr Int writtenDigits(const FloatingPointType &=FloatingPointType())
Number of digits commonly used for writing a floating point type (a.k.a. precision)....
Definition: Types.h:294
OpenMS::StringUtils::remove
static String & remove(String &this_s, char what)
Definition: StringUtils.h:870
OpenMS::StringUtils::chop
static String chop(const String &this_s, Size n)
Definition: StringUtils.h:411
OpenMS::StringConversions::BK_PrecPolicyFloat_type
boost::spirit::karma::real_generator< float, BK_PrecPolicy< float > > BK_PrecPolicyFloat_type
Definition: StringUtils.h:65
OpenMS::StringUtils::ensureLastChar
static String & ensureLastChar(String &this_s, char end)
Definition: StringUtils.h:876
OpenMS::StringConversions::toStringLowP
String toStringLowP(float f)
low precision (3 fractional digits) conversion to string (Karma default)
Definition: StringUtils.h:104
Types.h
PrecisionWrapper.h
OpenMS::StringUtils::numberLength
static String numberLength(double d, UInt n)
Functions.
Definition: StringUtils.h:243
OpenMS::StringConversions::BK_PrecPolicyLongDouble_type
boost::spirit::karma::real_generator< long double, BK_PrecPolicy< long double > > BK_PrecPolicyLongDouble_type
Definition: StringUtils.h:69
OpenMS::String::substitute
String & substitute(char from, char to)
Replaces all occurrences of the character from by the character to.
OpenMS::StringUtils::prefix
static String prefix(const String &this_s, char delim)
Definition: StringUtils.h:383
OpenMS::String::NONE
Definition: String.h:81
OpenMS::String
A more convenient string class.
Definition: String.h:58
OpenMS::String::trim
String & trim()
removes whitespaces (space, tab, line feed, carriage return) at the beginning and the end of the stri...
OpenMS::Exception::ConversionError
Invalid conversion exception.
Definition: Exception.h:362
OpenMS::Size
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:127
OpenMS::DataValue::toString
String toString(bool full_precision=true) const
Conversion to String full_precision Controls number of fractional digits for all double types or list...
OpenMS::Constants::c
const double c
OpenMS::StringUtils::reverse
static String & reverse(String &this_s)
Definition: StringUtils.h:542
OpenMS::String::prefix
String prefix(SizeType length) const
returns the prefix of length length
OpenMS::StringUtils::hasSuffix
static bool hasSuffix(const String &this_s, const String &string)
Definition: StringUtils.h:316
OpenMS::StringConversions::BK_PrecPolicyDouble_type
boost::spirit::karma::real_generator< double, BK_PrecPolicy< double > > BK_PrecPolicyDouble_type
Definition: StringUtils.h:67
OpenMS::String::DOUBLE
Definition: String.h:81
OpenMS::StringUtils::substitute
static String & substitute(String &this_s, const String &from, const String &to)
Definition: StringUtils.h:859
OpenMS::StringUtils::toDouble
static double toDouble(const String &s)
convert String (leading and trailing whitespace allowed) to double
Definition: StringUtils.h:799
OpenMS::StringUtils::split
static bool split(const String &this_s, const char splitter, std::vector< String > &substrings, bool quote_protect)
Definition: StringUtils.h:552
OpenMS::StringUtils::parse_double_
static boost::spirit::qi::real_parser< double, real_policies_NANfixed_< double > > parse_double_
Definition: StringUtils.h:957
OpenMS::StringUtils::prefix
static String prefix(const String &this_s, size_t length)
Definition: StringUtils.h:339
OpenMS::StringUtils::toQString
static QString toQString(const String &this_s)
Definition: StringUtils.h:749
OpenMS::StringUtils::real_policies_NANfixed_
Definition: StringUtils.h:921
OpenMS::StringUtils::fillRight
static String & fillRight(String &this_s, char c, UInt size)
Definition: StringUtils.h:293
OpenMS::Byte
OPENMS_BYTE_TYPE Byte
Byte type.
Definition: Types.h:111
OpenMS::StringUtils::fillLeft
static String & fillLeft(String &this_s, char c, UInt size)
Definition: StringUtils.h:284
OpenMS::Int
int Int
Signed integer type.
Definition: Types.h:102
OpenMS
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:46
OpenMS::StringConversions::BK_PrecPolicyFloat
const BK_PrecPolicyFloat_type BK_PrecPolicyFloat
Definition: StringUtils.h:66
OpenMS::StringUtils::hasPrefix
static bool hasPrefix(const String &this_s, const String &string)
Definition: StringUtils.h:303
Exception.h
OpenMS::DataValue
Class to hold strings, numeric values, lists of strings and lists of numeric values.
Definition: DataValue.h:56
OpenMS::StringUtils::suffix
static String suffix(const String &this_s, size_t length)
Definition: StringUtils.h:348
int
OpenMS::StringUtils::split
static bool split(const String &this_s, const String &splitter, std::vector< String > &substrings)
Definition: StringUtils.h:647
OpenMS::StringConversions::BK_PrecPolicy::precision
static unsigned int precision(T)
Definition: StringUtils.h:63
OpenMS::StringUtils::removeWhitespaces
static String & removeWhitespaces(String &this_s)
Definition: StringUtils.h:883
OpenMS::String::split
bool split(const char splitter, std::vector< String > &substrings, bool quote_protect=false) const
Splits a string into substrings using splitter as delimiter.
OpenMS::StringUtils::number
static String number(double d, UInt n)
Definition: StringUtils.h:279
OpenMS::StringUtils::trim
static String & trim(String &this_s)
Definition: StringUtils.h:421
OpenMS::String::hasSuffix
bool hasSuffix(const String &string) const
true if String ends with string, false otherwise
OpenMS::StringConversions::append
void append(const T &i, String &target)
Definition: StringUtils.h:77
OpenMS::UInt
unsigned int UInt
Unsigned integer type.
Definition: Types.h:94
Iterator
OpenMS::String::ESCAPE
Definition: String.h:81
OpenMS::StringUtils::substitute
static String & substitute(String &this_s, char from, char to)
Definition: StringUtils.h:853
OpenMS::StringUtils::suffix
static String suffix(const String &this_s, Int length)
Definition: StringUtils.h:370
OpenMS::Exception::IndexOverflow
Int overflow exception.
Definition: Exception.h:254
OpenMS::StringConversions::toString
String toString(const T &i)
fallback template for general purpose using Boost::Karma; more specializations below
Definition: StringUtils.h:85
OpenMS::StringUtils::toFloat
static float toFloat(const String &this_s)
Definition: StringUtils.h:773
OpenMS::StringUtils::quote
static String & quote(String &this_s, char q, String::QuotingMethod method)
Definition: StringUtils.h:459
OpenMS::StringConversions::BK_PrecPolicyLongDouble
const BK_PrecPolicyLongDouble_type BK_PrecPolicyLongDouble
Definition: StringUtils.h:70
OpenMS::StringUtils::parse_float_
static boost::spirit::qi::real_parser< float, real_policies_NANfixed_< float > > parse_float_
Definition: StringUtils.h:958
OpenMS::String::substr
String substr(size_t pos=0, size_t n=npos) const
Wrapper for the STL substr() method. Returns a String object with its contents initialized to a subst...
OpenMS::StringUtils::extractDouble
static bool extractDouble(IteratorT &begin, const IteratorT &end, double &target)
Definition: StringUtils.h:822
OpenMS::StringUtils::toLower
static String & toLower(String &this_s)
Definition: StringUtils.h:847
OpenMS::StringUtils::random
static String random(UInt length)
Definition: StringUtils.h:518
OpenMS::StringUtils::has
static bool has(const String &this_s, Byte byte)
Definition: StringUtils.h:334
DataValue.h
String.h
OpenMS::StringUtils::suffix
static String suffix(const String &this_s, char delim)
Definition: StringUtils.h:394
OpenMS::String::concatenate
void concatenate(StringIterator first, StringIterator last, const String &glue="")
Concatenates all elements from first to last-1 and inserts glue between the elements.
Definition: String.h:466
OpenMS::StringUtils::prefix
static String prefix(const String &this_s, Int length)
Definition: StringUtils.h:357
OpenMS::StringUtils
Definition: StringUtils.h:235
OpenMS::StringUtils::unquote
static String & unquote(String &this_s, char q, String::QuotingMethod method)
Definition: StringUtils.h:472
OpenMS::StringUtils::split_quoted
static bool split_quoted(const String &this_s, const String &splitter, std::vector< String > &substrings, char q, String::QuotingMethod method)
Definition: StringUtils.h:674
OpenMS::Exception::ElementNotFound
Element could not be found exception.
Definition: Exception.h:662
OpenMS::StringUtils::toUpper
static String & toUpper(String &this_s)
Definition: StringUtils.h:832
OpenMS::String::suffix
String suffix(SizeType length) const
returns the suffix of length length
OpenMS::String::ConstIterator
const_iterator ConstIterator
Const Iterator.
Definition: String.h:72
OpenMS::StringConversions::appendLowP
void appendLowP(float f, String &target)
Definition: StringUtils.h:98
OpenMS::StringUtils::simplify
static String & simplify(String &this_s)
Definition: StringUtils.h:492
OpenMS::StringUtils::real_policies_NANfixed_::parse_nan
static bool parse_nan(Iterator &first, Iterator const &last, Attribute &attr_)
Definition: StringUtils.h:925
OpenMS::Exception::IndexUnderflow
Int underflow exception.
Definition: Exception.h:216
OpenMS::StringUtils::firstToUpper
static String & firstToUpper(String &this_s)
Definition: StringUtils.h:838
OpenMS::StringConversions::BK_PrecPolicy
Definition: StringUtils.h:60