OpenMS  2.4.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-2018.
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>
41 
42 #include <QtCore/QString>
43 #include <boost/spirit/include/qi.hpp>
44 
45 #include <string>
46 #include <vector>
47 
48 
49 namespace OpenMS
50 {
51  class String;
52 
53  namespace StringConversions
54  {
55 
57  template <typename T>
58  inline String floatToString(T f)
59  {
60  std::stringstream s;
61  s.precision(writtenDigits(f));
62  s << f;
63  return s.str();
64  }
65 
67  template <typename T>
68  inline String toString(T i)
69  {
70  std::stringstream s;
71  s << i;
72  return s.str();
73  }
74 
75  template <>
76  inline String toString<const char>(const char c)
77  {
78  return std::string(1,c);
79  }
80 
81  template <>
82  inline String toString(const std::string& s)
83  {
84  return s;
85  }
86 
87  template <>
88  inline String toString(const char* s)
89  {
90  return std::string(s);
91  }
92 
93  template <>
94  inline String toString(float f)
95  {
96  return floatToString(f);
97  }
98 
99  template <>
100  inline String toString(double f)
101  {
102  return floatToString(f);
103  }
104 
105  template <>
106  inline String toString(long double f)
107  {
108  return floatToString(f);
109  }
110 
111  template <>
112  inline String toString(const DataValue& d)
113  {
114  return d.toString();
115  }
116 
118  inline String toString()
119  {
120  return String();
121  }
122 
123  inline String toString(const char* s, size_t length)
124  {
125  String res;
126  size_t count = 0;
127  while (count < length && *(s + count) != 0)
128  {
129  res += *(s + count);
130  ++count;
131  }
132  return res;
133  }
134  }
135 
136  class OPENMS_DLLAPI StringUtils
137  {
138 
139 public:
140 
141  //
143  //
144  static String numberLength(double d, UInt n)
145  {
146  std::stringstream s;
147  //reserve one space for the minus sign
148  Int sign = 0;
149  if (d < 0)
150  sign = 1;
151  d = fabs(d);
152 
153  if (d < pow(10.0, Int(n - sign - 2)))
154  {
155  s.precision(writtenDigits(d));
156  if (sign == 1)
157  s << "-";
158  s << d;
159  }
160  else
161  {
162  UInt exp = 0;
163  while (d > pow(10.0, Int(n - sign - 4)))
164  {
165  d /= 10;
166  ++exp;
167  }
168  d = Int(d) / 10.0;
169  exp += 1;
170  if (sign == 1)
171  s << "-";
172  s << d << "e";
173  if (exp < 10)
174  s << "0";
175  s << exp;
176  }
177  return s.str().substr(0, n);
178  }
179 
180  static String number(double d, UInt n)
181  {
182  return QString::number(d, 'f', n);
183  }
184 
185  static String& fillLeft(String & this_s, char c, UInt size)
186  {
187  if (this_s.size() < size)
188  {
189  this_s.std::string::operator=(String(size - this_s.size(), c) + this_s);
190  }
191  return this_s;
192  }
193 
194  static String& fillRight(String & this_s, char c, UInt size)
195  {
196  if (this_s.size() < size)
197  {
198  this_s.std::string::operator=(this_s + String(size - this_s.size(), c));
199  }
200  return this_s;
201  }
202 
203  /*
205  static String toString(const char * s, size_t length)
206  {
207  std::string res;
208  size_t count = 0;
209  while (count < length && *(s + count) != 0)
210  {
211  res += *(s + count);
212  ++count;
213  }
214  return String(res);
215  }
216 
218  static String toString(size_t len, char c)
219  {
220  return String(std::string(len, c));
221  }
222  */
223 
224  static bool hasPrefix(const String & this_s, const String & string)
225  {
226  if (string.size() > this_s.size())
227  {
228  return false;
229  }
230  if (string.empty())
231  {
232  return true;
233  }
234  return this_s.compare(0, string.size(), string) == 0;
235  }
236 
237  static bool hasSuffix(const String & this_s, const String& string)
238  {
239  if (string.size() > this_s.size())
240  {
241  return false;
242  }
243  if (string.empty())
244  {
245  return true;
246  }
247  return this_s.compare(this_s.size() - string.size(), string.size(), string) == 0;
248  }
249 
250  static bool hasSubstring(const String & this_s, const String& string)
251  {
252  return this_s.find(string) != std::string::npos;
253  }
254 
255  static bool has(const String & this_s, Byte byte)
256  {
257  return this_s.find(char(byte)) != std::string::npos;
258  }
259 
260  static String prefix(const String & this_s, size_t length)
261  {
262  if (length > this_s.size())
263  {
264  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
265  }
266  return this_s.substr(0, length);
267  }
268 
269  static String suffix(const String & this_s, size_t length)
270  {
271  if (length > this_s.size())
272  {
273  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
274  }
275  return this_s.substr(this_s.size() - length, length);
276  }
277 
278  static String prefix(const String & this_s, Int length)
279  {
280  if (length < 0)
281  {
282  throw Exception::IndexUnderflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, 0);
283  }
284  if (length > Int(this_s.size()))
285  {
286  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
287  }
288  return this_s.substr(0, length);
289  }
290 
291  static String suffix(const String & this_s, Int length)
292  {
293  if (length < 0)
294  {
295  throw Exception::IndexUnderflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, 0);
296  }
297  if (length > Int(this_s.size()))
298  {
299  throw Exception::IndexOverflow(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, length, this_s.size());
300  }
301  return this_s.substr(this_s.size() - length, length);
302  }
303 
304  static String prefix(const String & this_s, char delim)
305  {
306  Size pos = this_s.find(delim);
307  if (pos == std::string::npos) //char not found
308  {
309  throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
310  String(delim));
311  }
312  return this_s.substr(0, pos);
313  }
314 
315  static String suffix(const String & this_s, char delim)
316  {
317  Size pos = this_s.rfind(delim);
318  if (pos == std::string::npos) //char not found
319  {
320  throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
321  String(delim));
322  }
323  return this_s.substr(++pos);
324  }
325 
326  static String substr(const String & this_s, size_t pos, size_t n)
327  {
328  Size begin = std::min(pos, this_s.size());
329  return static_cast<String>(this_s.std::string::substr(begin, n));
330  }
331 
332  static String chop(const String & this_s, Size n)
333  {
334  Size end = 0;
335  if (n < this_s.size())
336  {
337  end = this_s.size() - n;
338  }
339  return String(this_s.begin(), this_s.begin() + end);
340  }
341 
342  static String& trim(String & this_s)
343  {
344  //search for the begin of truncated string
345  std::string::iterator begin = this_s.begin();
346  while (begin != this_s.end() && (*begin == ' ' || *begin == '\t' || *begin == '\n' || *begin == '\r'))
347  {
348  ++begin;
349  }
350 
351  //all characters are whitespaces
352  if (begin == this_s.end())
353  {
354  this_s.clear();
355  return this_s;
356  }
357 
358  //search for the end of truncated string
359  std::string::iterator end = this_s.end();
360  end--;
361  while (end != begin && (*end == ' ' || *end == '\n' || *end == '\t' || *end == '\r'))
362  {
363  --end;
364  }
365  ++end;
366 
367  //no characters are whitespaces
368  if (begin == this_s.begin() && end == this_s.end())
369  {
370  return this_s;
371  }
372 
373  // TODO:
374  // string::operator=(std::string(begin, end));
375  this_s.std::string::operator=(std::string(begin, end));
376 
377  return this_s;
378  }
379 
380  static String& quote(String & this_s, char q, String::QuotingMethod method)
381  {
382  if (method == String::ESCAPE)
383  {
384  this_s.substitute(String("\\"), String("\\\\"));
385  this_s.substitute(String(q), "\\" + String(q));
386  }
387  else if (method == String::DOUBLE)
388  this_s.substitute(String(q), String(q) + String(q));
389  this_s.std::string::operator=(q + this_s + q);
390  return this_s;
391  }
392 
393  static String& unquote(String & this_s, char q, String::QuotingMethod method)
394  {
395  // check if input string matches output format of the "quote" method:
396  if ((this_s.size() < 2) || (this_s[0] != q) || (this_s[this_s.size() - 1] != q))
397  {
399  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
400  "'" + this_s + "' does not have the expected format of a quoted string");
401  }
402  this_s.std::string::operator=(this_s.substr(1, this_s.size() - 2)); // remove quotation marks
403  if (method == String::ESCAPE)
404  {
405  this_s.substitute("\\" + String(q), String(q));
406  this_s.substitute(String("\\\\"), String("\\"));
407  }
408  else if (method == String::DOUBLE)
409  this_s.substitute(String(q) + String(q), String(q));
410  return this_s;
411  }
412 
413  static String& simplify(String & this_s)
414  {
415  String simple;
416 
417  bool last_was_whitespace = false;
418  for (std::string::iterator it = this_s.begin(); it != this_s.end(); ++it)
419  {
420  if (*it == ' ' || *it == '\n' || *it == '\t' || *it == '\r')
421  {
422  if (!last_was_whitespace)
423  {
424  simple += ' ';
425  }
426  last_was_whitespace = true;
427  }
428  else
429  {
430  simple += *it;
431  last_was_whitespace = false;
432  }
433  }
434 
435  this_s.swap(simple);
436  return this_s;
437  }
438 
439  static String random(UInt length)
440  {
441  srand(time(nullptr));
442  String tmp(length, '.');
443  size_t random;
444  for (Size i = 0; i < length; ++i)
445  {
446  random = static_cast<size_t>(floor((static_cast<double>(rand()) / (double(RAND_MAX) + 1)) * 62.0));
447  if (random < 10)
448  {
449  tmp[i] = static_cast<char>(random + 48);
450  }
451  else if (random < 36)
452  {
453  tmp[i] = static_cast<char>(random + 55);
454  }
455  else
456  {
457  tmp[i] = static_cast<char>(random + 61);
458  }
459  }
460  return tmp;
461  }
462 
463  static String& reverse(String & this_s)
464  {
465  String tmp = this_s;
466  for (Size i = 0; i != this_s.size(); ++i)
467  {
468  this_s[i] = tmp[this_s.size() - 1 - i];
469  }
470  return this_s;
471  }
472 
473  static bool split(const String & this_s, const char splitter, std::vector<String>& substrings,
474  bool quote_protect)
475  {
476  substrings.clear();
477  if (this_s.empty())
478  return false;
479 
480  Size nsplits = count(this_s.begin(), this_s.end(), splitter);
481 
482  if (!quote_protect && (nsplits == 0))
483  {
484  substrings.push_back(this_s);
485  return false;
486  }
487 
488  // splitter(s) found
489  substrings.reserve(nsplits + 1);
490 
491  // why is "this_s." needed here?
492  std::string::const_iterator begin = this_s.begin();
493  std::string::const_iterator end = this_s.begin();
494 
495  if (quote_protect)
496  {
497  Int quote_count(0);
498  for (; end != this_s.end(); ++end)
499  {
500  if (*end == '"')
501  {
502  ++quote_count;
503  }
504  if ((quote_count % 2 == 0) && (*end == splitter))
505  {
506  String block = String(begin, end);
507  block.trim();
508  if ((block.size() >= 2) && ((block.prefix(1) == String("\"")) ^
509  (block.suffix(1) == String("\""))))
510  { // block has start or end quote, but not both
511  // (one quote is somewhere in the middle)
513  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
514  String("Could not dequote string '") + block +
515  "' due to wrongly placed '\"'.");
516  }
517  else if ((block.size() >= 2) && (block.prefix(1) == String("\"")) &&
518  (block.suffix(1) == String("\"")))
519  { // block has start and end quotes --> remove them
520  block = block.substr(1, block.size() - 2);
521  }
522  substrings.push_back(block);
523  begin = end + 1;
524  }
525  }
526  // no valid splitter found - return empty list
527  if (substrings.empty())
528  {
529  substrings.push_back(this_s);
530  return false;
531  }
532 
533  String block = String(begin, end);
534  block.trim();
535  if ((block.size() >= 2) && ((block.prefix(1) == String("\"")) ^
536  (block.suffix(1) == String("\""))))
537  { // block has start or end quote but not both
538  // (one quote is somewhere in the middle)
540  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
541  String("Could not dequote string '") + block +
542  "' due to wrongly placed '\"'.");
543  }
544  else if ((block.size() >= 2) && (block.prefix(1) == String("\"")) &&
545  (block.suffix(1) == String("\"")))
546  { // block has start and end quotes --> remove them
547  block = block.substr(1, block.size() - 2);
548  }
549  substrings.push_back(block);
550  }
551  else // do not honor quotes
552  {
553  for (; end != this_s.end(); ++end)
554  {
555  if (*end == splitter)
556  {
557  substrings.push_back(String(begin, end));
558  begin = end + 1;
559  }
560  }
561  substrings.push_back(String(begin, end));
562  }
563 
564  // at this point we are sure that there are at least two components
565  return true;
566  }
567 
568  static bool split(const String & this_s, const String& splitter, std::vector<String>& substrings)
569  {
570  substrings.clear();
571  if (this_s.empty())
572  return false;
573 
574  if (splitter.empty()) // split after every character:
575  {
576  substrings.resize(this_s.size());
577  for (Size i = 0; i < this_s.size(); ++i)
578  substrings[i] = this_s[i];
579  return true;
580  }
581 
582  Size len = splitter.size(), start = 0, pos = this_s.find(splitter);
583  if (len == 0)
584  len = 1;
585  while (pos != std::string::npos)
586  {
587  substrings.push_back(this_s.substr(start, pos - start));
588  start = pos + len;
589  pos = this_s.find(splitter, start);
590  }
591  substrings.push_back(this_s.substr(start, this_s.size() - start));
592  return substrings.size() > 1;
593  }
594 
595  static bool split_quoted(const String & this_s, const String& splitter, std::vector<String>& substrings,
596  char q, String::QuotingMethod method)
597  {
598  substrings.clear();
599  if (this_s.empty() || splitter.empty())
600  return false;
601 
602  bool in_quote = false;
603  char targets[2] = {q, splitter[0]}; // targets for "find_first_of"
604  std::string rest = splitter.substr(1, splitter.size() - 1);
605  Size start = 0;
606  for (Size i = 0; i < this_s.size(); ++i)
607  {
608  if (in_quote) // skip to closing quotation mark
609  {
610  bool embedded = false;
611  if (method == String::ESCAPE)
612  {
613  for (; i < this_s.size(); ++i)
614  {
615  if (this_s[i] == '\\')
616  embedded = !embedded;
617  else if ((this_s[i] == q) && !embedded)
618  break;
619  else
620  embedded = false;
621  }
622  }
623  else // method: NONE or DOUBLE
624  {
625  for (; i < this_s.size(); ++i)
626  {
627  if (this_s[i] == q)
628  {
629  if (method == String::NONE)
630  break; // found
631  // next character is also closing quotation mark:
632  if ((i < this_s.size() - 1) && (this_s[i + 1] == q))
633  embedded = !embedded;
634  // even number of subsequent quotes (doubled) => found
635  else if (!embedded)
636  break;
637  // odd number of subsequent quotes => belongs to a pair
638  else
639  embedded = false;
640  }
641  }
642  }
643  in_quote = false; // end of quote reached
644  }
645  else
646  {
647  i = this_s.find_first_of(targets, i, 2);
648  if (i == std::string::npos)
649  break; // nothing found
650  if (this_s[i] == q)
651  in_quote = true;
652  else if (this_s.compare(i + 1, rest.size(), rest) == 0) // splitter found
653  {
654  substrings.push_back(this_s.substr(start, i - start));
655  start = i + splitter.size();
656  i = start - 1; // increased by loop
657  }
658  }
659  }
660  if (in_quote) // reached end without finding closing quotation mark
661  {
663  __FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
664  "unbalanced quotation marks in string '" + this_s + "'");
665  }
666  substrings.push_back(this_s.substr(start, this_s.size() - start));
667  return substrings.size() > 1;
668  }
669 
670  static QString toQString(const String & this_s)
671  {
672  return QString(this_s.c_str());
673  }
674 
675  static Int toInt(const String & this_s)
676  {
677  Int ret;
678 
679  // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
680  // so don't change this unless you have benchmarks for all platforms!
681  String::ConstIterator it = this_s.begin();
682  if (!boost::spirit::qi::phrase_parse(it, this_s.end(), boost::spirit::qi::int_, boost::spirit::ascii::space, ret))
683  {
684  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to an integer value");
685  }
686  // 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
687  if (it != this_s.end())
688  {
689  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));
690  }
691  return ret;
692  }
693 
694  static float toFloat(const String& this_s)
695  {
696  float ret;
697 
698  // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
699  // so don't change this unless you have benchmarks for all platforms!
700  String::ConstIterator it = this_s.begin();
701  if (!boost::spirit::qi::phrase_parse(it, this_s.end(), parse_float_, boost::spirit::ascii::space, ret))
702  {
703  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to a float value");
704  }
705  // 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
706  if (it != this_s.end())
707  {
708  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));
709  }
710  return ret;
711  }
712 
713  static double toDouble(const String& this_s)
714  {
715  double ret;
716  // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
717  // so don't change this unless you have benchmarks for all platforms!
718  String::ConstIterator it = this_s.begin();
719  if (!boost::spirit::qi::phrase_parse(it, this_s.end(), parse_double_, boost::spirit::ascii::space, ret))
720  {
721  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to a double value");
722  }
723  // 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
724  if (it != this_s.end())
725  {
726  throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Prefix of string '") + this_s + "' successfully converted to a double value. Additional characters found at position " + (int)(distance(this_s.begin(), it) + 1));
727  }
728  return ret;
729  }
730 
731 
732  static String& toUpper(String & this_s)
733  {
734  std::transform(this_s.begin(), this_s.end(), this_s.begin(), (int (*)(int))toupper);
735  return this_s;
736  }
737 
738  static String& firstToUpper(String & this_s)
739  {
740  if (this_s.size() != 0)
741  {
742  this_s[0] = toupper(this_s[0]);
743  }
744  return this_s;
745  }
746 
747  static String& toLower(String & this_s)
748  {
749  std::transform(this_s.begin(), this_s.end(), this_s.begin(), (int (*)(int))tolower);
750  return this_s;
751  }
752 
753  static String& substitute(String & this_s, char from, char to)
754  {
755  std::replace(this_s.begin(), this_s.end(), from, to);
756  return this_s;
757  }
758 
759  static String& substitute(String & this_s, const String& from, const String& to)
760  {
761  if (!from.empty())
762  {
763  std::vector<String> parts;
764  this_s.split(from, parts);
765  this_s.concatenate(parts.begin(), parts.end(), to);
766  }
767  return this_s;
768  }
769 
770  static String& remove(String & this_s, char what)
771  {
772  this_s.erase(std::remove(this_s.begin(), this_s.end(), what), this_s.end());
773  return this_s;
774  }
775 
776  static String& ensureLastChar(String & this_s, char end)
777  {
778  if (!this_s.hasSuffix(end))
779  this_s.append(1, end);
780  return this_s;
781  }
782 
783  static String& removeWhitespaces(String& this_s)
784  {
785  std::string::const_iterator it = this_s.begin();
786  std::string::iterator dest = this_s.begin();
787  std::string::const_iterator it_end = this_s.end();
788  bool has_spaces(false);
789  while (it != it_end)
790  {
791  const char c = *it;
792  if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
793  {
794  ++it;
795  has_spaces = true;
796  continue; // no need to copy a whitespace
797  }
798  // copy to the left, if we had a whitespace before
799  if (has_spaces) *dest = *it;
800  // advance both
801  ++dest;
802  ++it;
803  }
804 
805  // shorten result
806  if (has_spaces) this_s.resize(dest - this_s.begin());
807 
808  return this_s;
809  }
810 
811  private:
812 
813  /*
814  @brief A fixed Boost:pi real parser policy, capable of dealing with 'nan' without crashing
815 
816  The original Boost implementation has a bug, see https://svn.boost.org/trac/boost/ticket/6955.
817  Can be removed if Boost 1.60 or above is required
818 
819  */
820  template <typename T>
821  struct real_policies_NANfixed_ : boost::spirit::qi::real_policies<T>
822  {
823  template <typename Iterator, typename Attribute>
824  static bool
825  parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
826  {
827  if (first == last)
828  return false; // end of input reached
829 
830  if (*first != 'n' && *first != 'N')
831  return false; // not "nan"
832 
833  // nan[(...)] ?
834  if (boost::spirit::qi::detail::string_parse("nan", "NAN", first, last, boost::spirit::qi::unused))
835  {
836  if (first != last && *first == '(') /* this check is broken in boost 1.49 - (at least) 1.54; fixed in 1.60 */
837  {
838  // skip trailing (...) part
839  Iterator i = first;
840 
841  while (++i != last && *i != ')')
842  ;
843  if (i == last)
844  return false; // no trailing ')' found, give up
845 
846  first = ++i;
847  }
848  attr_ = std::numeric_limits<T>::quiet_NaN();
849  return true;
850  }
851  return false;
852  }
853  };
854 
855  // Qi parsers using the 'real_policies_NANfixed_' template which allows for 'nan'
856  // (the original Boost implementation has a bug, see https://svn.boost.org/trac/boost/ticket/6955)
857  static boost::spirit::qi::real_parser<double, real_policies_NANfixed_<double> > parse_double_;
858  static boost::spirit::qi::real_parser<float, real_policies_NANfixed_<float> > parse_float_;
859 
860  };
861 
862 } // namespace OPENMS
863 
static bool split(const String &this_s, const String &splitter, std::vector< String > &substrings)
Definition: StringUtils.h:568
static boost::spirit::qi::real_parser< float, real_policies_NANfixed_< float > > parse_float_
Definition: StringUtils.h:858
Int underflow exception.
Definition: Exception.h:216
static String numberLength(double d, UInt n)
Functions.
Definition: StringUtils.h:144
static String & fillRight(String &this_s, char c, UInt size)
Definition: StringUtils.h:194
A more convenient string class.
Definition: String.h:57
static String number(double d, UInt n)
Definition: StringUtils.h:180
Definition: StringUtils.h:136
Element could not be found exception.
Definition: Exception.h:662
static String & fillLeft(String &this_s, char c, UInt size)
Definition: StringUtils.h:185
static bool hasPrefix(const String &this_s, const String &string)
Definition: StringUtils.h:224
Int overflow exception.
Definition: Exception.h:254
String floatToString(T f)
toString functions (for floating point types)
Definition: StringUtils.h:58
Definition: String.h:80
unsigned int UInt
Unsigned integer type.
Definition: Types.h:94
Int writtenDigits(const FloatingPointType &=FloatingPointType())
Number of digits commonly used for writing a floating point type (a.k.a. precision). Specializations are defined for float, double, long double.
Definition: Types.h:294
static String & removeWhitespaces(String &this_s)
Definition: StringUtils.h:783
static QString toQString(const String &this_s)
Definition: StringUtils.h:670
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:458
const double c
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:46
static String & trim(String &this_s)
Definition: StringUtils.h:342
static String & substitute(String &this_s, char from, char to)
Definition: StringUtils.h:753
String toString() const
Conversion to String.
static String suffix(const String &this_s, Int length)
Definition: StringUtils.h:291
static double toDouble(const String &this_s)
Definition: StringUtils.h:713
Class to hold strings, numeric values, lists of strings and lists of numeric values.
Definition: DataValue.h:56
static bool split(const String &this_s, const char splitter, std::vector< String > &substrings, bool quote_protect)
Definition: StringUtils.h:473
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...
static bool split_quoted(const String &this_s, const String &splitter, std::vector< String > &substrings, char q, String::QuotingMethod method)
Definition: StringUtils.h:595
static boost::spirit::qi::real_parser< double, real_policies_NANfixed_< double > > parse_double_
Definition: StringUtils.h:857
QuotingMethod
How to handle embedded quotes when quoting strings.
Definition: String.h:80
const_iterator ConstIterator
Const Iterator.
Definition: String.h:71
static bool parse_nan(Iterator &first, Iterator const &last, Attribute &attr_)
Definition: StringUtils.h:825
static String prefix(const String &this_s, char delim)
Definition: StringUtils.h:304
static String & toLower(String &this_s)
Definition: StringUtils.h:747
String suffix(SizeType length) const
returns the suffix of length length
static String random(UInt length)
Definition: StringUtils.h:439
static String substr(const String &this_s, size_t pos, size_t n)
Definition: StringUtils.h:326
static String prefix(const String &this_s, Int length)
Definition: StringUtils.h:278
Definition: String.h:80
String & trim()
removes whitespaces (space, tab, line feed, carriage return) at the beginning and the end of the stri...
static String suffix(const String &this_s, size_t length)
Definition: StringUtils.h:269
static bool hasSubstring(const String &this_s, const String &string)
Definition: StringUtils.h:250
static String chop(const String &this_s, Size n)
Definition: StringUtils.h:332
static String & toUpper(String &this_s)
Definition: StringUtils.h:732
static String & substitute(String &this_s, const String &from, const String &to)
Definition: StringUtils.h:759
static String & ensureLastChar(String &this_s, char end)
Definition: StringUtils.h:776
static String & quote(String &this_s, char q, String::QuotingMethod method)
Definition: StringUtils.h:380
Invalid conversion exception.
Definition: Exception.h:362
static String & firstToUpper(String &this_s)
Definition: StringUtils.h:738
static bool has(const String &this_s, Byte byte)
Definition: StringUtils.h:255
Definition: String.h:80
static String & reverse(String &this_s)
Definition: StringUtils.h:463
static String suffix(const String &this_s, char delim)
Definition: StringUtils.h:315
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:127
static float toFloat(const String &this_s)
Definition: StringUtils.h:694
static String & unquote(String &this_s, char q, String::QuotingMethod method)
Definition: StringUtils.h:393
String & substitute(char from, char to)
Replaces all occurrences of the character from by the character to.
String prefix(SizeType length) const
returns the prefix of length length
OPENMS_BYTE_TYPE Byte
Byte type.
Definition: Types.h:111
static String prefix(const String &this_s, size_t length)
Definition: StringUtils.h:260
static String & simplify(String &this_s)
Definition: StringUtils.h:413
String toString(T i)
toString functions (single argument)
Definition: StringUtils.h:68
int Int
Signed integer type.
Definition: Types.h:102
bool split(const char splitter, std::vector< String > &substrings, bool quote_protect=false) const
Splits a string into substrings using splitter as delimiter.
static Int toInt(const String &this_s)
Definition: StringUtils.h:675
String toString< const char >(const char c)
Definition: StringUtils.h:76
bool hasSuffix(const String &string) const
true if String ends with string, false otherwise
static bool hasSuffix(const String &this_s, const String &string)
Definition: StringUtils.h:237