| 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>
38 #include <OpenMS/DATASTRUCTURES/String.h>
39 #include <OpenMS/CONCEPT/Exception.h>
40 #include <OpenMS/DATASTRUCTURES/DataValue.h>
41 #include <OpenMS/CONCEPT/PrecisionWrapper.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;
66 const BK_PrecPolicyFloat_type BK_PrecPolicyFloat;
67 typedef boost::spirit::karma::real_generator<double, BK_PrecPolicy<double> > BK_PrecPolicyDouble_type;
68 const BK_PrecPolicyDouble_type BK_PrecPolicyDouble;
69 typedef boost::spirit::karma::real_generator<long double, BK_PrecPolicy<long double> > BK_PrecPolicyLongDouble_type;
70 const BK_PrecPolicyLongDouble_type BK_PrecPolicyLongDouble;
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 {
477 throw Exception::ConversionError(
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)
591 throw Exception::ConversionError(
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)
618 throw Exception::ConversionError(
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 {
741 throw Exception::ConversionError(
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::parse_float_
static boost::spirit::qi::real_parser< float, real_policies_NANfixed_< float > > parse_float_
Definition: StringUtils.h:958
OpenMS::StringConversions::BK_PrecPolicyLongDouble
const BK_PrecPolicyLongDouble_type BK_PrecPolicyLongDouble
Definition: StringUtils.h:70
OpenMS::String
A more convenient string class.
Definition: String.h:58
OpenMS::DataValue
Class to hold strings, numeric values, lists of strings and lists of numeric values.
Definition: DataValue.h:56
OpenMS::StringUtils::toFloat
static float toFloat(const String &this_s)
Definition: StringUtils.h:773
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::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::String::hasSuffix
bool hasSuffix(const String &string) const
true if String ends with string, false otherwise
OpenMS::StringUtils::simplify
static String & simplify(String &this_s)
Definition: StringUtils.h:492
OpenMS::StringUtils
Definition: StringUtils.h:235
OpenMS::String::QuotingMethod
QuotingMethod
How to handle embedded quotes when quoting strings.
Definition: String.h:81
OpenMS::Byte
OPENMS_BYTE_TYPE Byte
Byte type.
Definition: Types.h:111
OpenMS::StringUtils::suffix
static String suffix(const String &this_s, size_t length)
Definition: StringUtils.h:348
OpenMS::StringUtils::ensureLastChar
static String & ensureLastChar(String &this_s, char end)
Definition: StringUtils.h:876
OpenMS::StringUtils::parse_double_
static boost::spirit::qi::real_parser< double, real_policies_NANfixed_< double > > parse_double_
Definition: StringUtils.h:957
OpenMS::String::substitute
String & substitute(char from, char to)
Replaces all occurrences of the character from by the character to.
OpenMS::StringConversions::toString
String toString(const T &i)
fallback template for general purpose using Boost::Karma; more specializations below ...
Definition: StringUtils.h:85
OpenMS::String::ConstIterator
const_iterator ConstIterator
Const Iterator.
Definition: String.h:72
Exception.h
OpenMS::StringUtils::real_policies_NANfixed_::parse_nan
static bool parse_nan(Iterator &first, Iterator const &last, Attribute &attr_)
Definition: StringUtils.h:925
OpenMS::String::ESCAPE
Definition: String.h:81
OpenMS::StringUtils::removeWhitespaces
static String & removeWhitespaces(String &this_s)
Definition: StringUtils.h:883
OpenMS::StringUtils::toInt
static Int toInt(const String &this_s)
Definition: StringUtils.h:754
OpenMS::StringUtils::unquote
static String & unquote(String &this_s, char q, String::QuotingMethod method)
Definition: StringUtils.h:472
OpenMS::StringUtils::prefix
static String prefix(const String &this_s, char delim)
Definition: StringUtils.h:383
Types.h
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::hasSubstring
static bool hasSubstring(const String &this_s, const String &string)
Definition: StringUtils.h:329
OpenMS::StringUtils::fillRight
static String & fillRight(String &this_s, char c, UInt size)
Definition: StringUtils.h:293
Iterator
OpenMS::StringUtils::hasSuffix
static bool hasSuffix(const String &this_s, const String &string)
Definition: StringUtils.h:316
OpenMS::StringConversions::BK_PrecPolicyFloat
const BK_PrecPolicyFloat_type BK_PrecPolicyFloat
Definition: StringUtils.h:66
OpenMS::StringUtils::quote
static String & quote(String &this_s, char q, String::QuotingMethod method)
Definition: StringUtils.h:459
OpenMS::Int
int Int
Signed integer type.
Definition: Types.h:102
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::StringConversions::BK_PrecPolicyDouble
const BK_PrecPolicyDouble_type BK_PrecPolicyDouble
Definition: StringUtils.h:68
OpenMS::StringConversions::BK_PrecPolicy::precision
static unsigned int precision(T)
Definition: StringUtils.h:63
PrecisionWrapper.h
OpenMS::Exception::IndexUnderflow
Int underflow exception.
Definition: Exception.h:216
OpenMS::StringUtils::trim
static String & trim(String &this_s)
Definition: StringUtils.h:421
OpenMS::StringConversions::BK_PrecPolicy
Definition: StringUtils.h:60
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::StringConversions::BK_PrecPolicyFloat_type
boost::spirit::karma::real_generator< float, BK_PrecPolicy< float > > BK_PrecPolicyFloat_type
Definition: StringUtils.h:65
OpenMS::String::NONE
Definition: String.h:81
String.h
OpenMS::StringUtils::split
static bool split(const String &this_s, const String &splitter, std::vector< String > &substrings)
Definition: StringUtils.h:647
OpenMS::StringConversions::append
void append(const T &i, String &target)
Definition: StringUtils.h:77
OpenMS::StringUtils::toDouble
static double toDouble(const String &s)
convert String (leading and trailing whitespace allowed) to double
Definition: StringUtils.h:799
OpenMS::Exception::ElementNotFound
Element could not be found exception.
Definition: Exception.h:662
OpenMS::StringUtils::substitute
static String & substitute(String &this_s, const String &from, const String &to)
Definition: StringUtils.h:859
OpenMS
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:46
OpenMS::StringUtils::fillLeft
static String & fillLeft(String &this_s, char c, UInt size)
Definition: StringUtils.h:284
OpenMS::Exception::IndexOverflow
Int overflow exception.
Definition: Exception.h:254
OpenMS::StringUtils::hasPrefix
static bool hasPrefix(const String &this_s, const String &string)
Definition: StringUtils.h:303
OpenMS::StringUtils::real_policies_NANfixed_
Definition: StringUtils.h:921
OpenMS::StringUtils::random
static String random(UInt length)
Definition: StringUtils.h:518
OpenMS::StringUtils::chop
static String chop(const String &this_s, Size n)
Definition: StringUtils.h:411
OpenMS::StringUtils::reverse
static String & reverse(String &this_s)
Definition: StringUtils.h:542
OpenMS::StringConversions::BK_PrecPolicyLongDouble_type
boost::spirit::karma::real_generator< long double, BK_PrecPolicy< long double > > BK_PrecPolicyLongDouble_type
Definition: StringUtils.h:69
OpenMS::StringConversions::appendLowP
void appendLowP(float f, String &target)
Definition: StringUtils.h:98
OpenMS::UInt
unsigned int UInt
Unsigned integer type.
Definition: Types.h:94
OpenMS::StringUtils::extractDouble
static bool extractDouble(IteratorT &begin, const IteratorT &end, double &target)
Definition: StringUtils.h:822
OpenMS::StringUtils::suffix
static String suffix(const String &this_s, char delim)
Definition: StringUtils.h:394
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::String::prefix
String prefix(SizeType length) const
returns the prefix of length length
OpenMS::StringUtils::has
static bool has(const String &this_s, Byte byte)
Definition: StringUtils.h:334
OpenMS::StringConversions::BK_PrecPolicyDouble_type
boost::spirit::karma::real_generator< double, BK_PrecPolicy< double > > BK_PrecPolicyDouble_type
Definition: StringUtils.h:67
OpenMS::StringUtils::prefix
static String prefix(const String &this_s, Int length)
Definition: StringUtils.h:357
OpenMS::Constants::c
const double c
OpenMS::writtenDigits
constexpr 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
OpenMS::StringUtils::number
static String number(double d, UInt n)
Definition: StringUtils.h:279
OpenMS::String::suffix
String suffix(SizeType length) const
returns the suffix of length length
int
OpenMS::Exception::ConversionError
Invalid conversion exception.
Definition: Exception.h:362
OpenMS::StringUtils::substr
static String substr(const String &this_s, size_t pos, size_t n)
Definition: StringUtils.h:405
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.
DataValue.h
OpenMS::StringUtils::firstToUpper
static String & firstToUpper(String &this_s)
Definition: StringUtils.h:838
OpenMS::StringUtils::toLower
static String & toLower(String &this_s)
Definition: StringUtils.h:847
OpenMS::String::DOUBLE
Definition: String.h:81
OpenMS::StringUtils::prefix
static String prefix(const String &this_s, size_t length)
Definition: StringUtils.h:339
OpenMS::StringUtils::numberLength
static String numberLength(double d, UInt n)
Functions.
Definition: StringUtils.h:243
OpenMS::StringUtils::toUpper
static String & toUpper(String &this_s)
Definition: StringUtils.h:832
OpenMS::StringUtils::toQString
static QString toQString(const String &this_s)
Definition: StringUtils.h:749
OpenMS::Size
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:127
OpenMS::StringConversions::toStringLowP
String toStringLowP(float f)
low precision (3 fractional digits) conversion to string (Karma default)
Definition: StringUtils.h:104
OpenMS::String::trim
String & trim()
removes whitespaces (space, tab, line feed, carriage return) at the beginning and the end of the stri...