OpenMS
Loading...
Searching...
No Matches
StringUtils.h
Go to the documentation of this file.
1// Copyright (c) 2002-present, OpenMS Inc. -- EKU Tuebingen, ETH Zurich, and FU Berlin
2// SPDX-License-Identifier: BSD-3-Clause
3//
4// --------------------------------------------------------------------------
5// $Maintainer: Timo Sachsenberg, Chris Bielow $
6// $Authors: Marc Sturm, Stephan Aiche, Chris Bielow $
7// --------------------------------------------------------------------------
8
9#pragma once
10
17
18#include <QtCore/QString>
19#include <boost/spirit/include/qi.hpp>
20#include <boost/spirit/include/karma.hpp>
21#include <boost/type_traits.hpp>
22
23#include <string>
24#include <vector>
25
26
27namespace OpenMS
28{
29 class String;
30
31 class OPENMS_DLLAPI StringUtilsHelper
32 {
33
34public:
35
36 //
38 //
39 static Int toInt32(const String& this_s)
40 {
41 Int ret;
42
43 // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
44 // so don't change this unless you have benchmarks for all platforms!
45 String::ConstIterator it = this_s.begin();
46 if (!boost::spirit::qi::phrase_parse(it, this_s.end(), boost::spirit::qi::int_, boost::spirit::ascii::space, ret))
47 {
48 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to an integer value");
49 }
50 // 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
51 if (it != this_s.end())
52 {
53 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Prefix of string '") + this_s + "' successfully converted to an int32 value. Additional characters found at position " + (int)(distance(this_s.begin(), it) + 1));
54 }
55 return ret;
56 }
57
58 static Int64 toInt64(const String& this_s)
59 {
60 Int64 ret;
61
62 // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
63 // so don't change this unless you have benchmarks for all platforms!
64 String::ConstIterator it = this_s.begin();
65 if (!boost::spirit::qi::phrase_parse(it, this_s.end(), boost::spirit::qi::long_long, boost::spirit::ascii::space, ret))
66 {
67 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to an int64 value");
68 }
69 // 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
70 if (it != this_s.end())
71 {
72 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
73 String("Prefix of string '") + this_s + "' successfully converted to an integer value. Additional characters found at position " +
74 (int)(distance(this_s.begin(), it) + 1));
75 }
76 return ret;
77 }
78
79 static float toFloat(const String& this_s)
80 {
81 float ret;
82
83 // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
84 // so don't change this unless you have benchmarks for all platforms!
85 String::ConstIterator it = this_s.begin();
86 if (!boost::spirit::qi::phrase_parse(it, this_s.end(), parse_float_, boost::spirit::ascii::space, ret))
87 {
88 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + this_s + "' to a float value");
89 }
90 // 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
91 if (it != this_s.end())
92 {
93 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));
94 }
95 return ret;
96 }
97
105 static double toDouble(const String& s)
106 {
107 double ret;
108 // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
109 // so don't change this unless you have benchmarks for all platforms!
110 String::ConstIterator it = s.begin();
111 if (!boost::spirit::qi::phrase_parse(it, s.end(), parse_double_, boost::spirit::ascii::space, ret))
112 {
113 throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Could not convert string '") + s + "' to a double value");
114 }
115 // 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
116 if (it != s.end())
117 {
118 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));
119 }
120 return ret;
121 }
122
127 template <typename IteratorT>
128 static bool extractDouble(IteratorT& begin, const IteratorT& end, double& target)
129 {
130 // boost::spirit::qi was found to be vastly superior to boost::lexical_cast or stringstream extraction (especially for VisualStudio),
131 // so don't change this unless you have benchmarks for all platforms!
132
133 // qi::parse() does not consume whitespace before or after the double (qi::parse_phrase() would).
134 return boost::spirit::qi::parse(begin, end, parse_double_, target);
135 }
136
141 template <typename IteratorT>
142 static bool extractInt(IteratorT& begin, const IteratorT& end, int& target)
143 {
144 // qi::parse() does not consume whitespace before or after the int (qi::parse_phrase() would).
145 return boost::spirit::qi::parse(begin, end, parse_int_, target);
146 }
147
148 private:
149
150 /*
151 @brief A fixed Boost:pi real parser policy, capable of dealing with 'nan' without crashing
152
153 The original Boost implementation has a bug, see https://svn.boost.org/trac/boost/ticket/6955.
154 Can be removed if Boost 1.60 or above is required
155
156 */
157 template <typename T>
159 {
160 template <typename Iterator, typename Attribute>
161 static bool
162 parse_nan(Iterator& first, Iterator const& last, Attribute& attr_)
163 {
164 if (first == last)
165 return false; // end of input reached
166
167 if (*first != 'n' && *first != 'N')
168 return false; // not "nan"
169
170 // nan[(...)] ?
171 if (boost::spirit::qi::detail::string_parse("nan", "NAN", first, last, boost::spirit::qi::unused))
172 {
173 if (first != last && *first == '(') /* this check is broken in boost 1.49 - (at least) 1.54; fixed in 1.60 */
174 {
175 // skip trailing (...) part
176 Iterator i = first;
177
178 while (++i != last && *i != ')')
179 ;
180 if (i == last)
181 return false; // no trailing ')' found, give up
182
183 first = ++i;
184 }
185 attr_ = std::numeric_limits<T>::quiet_NaN();
186 return true;
187 }
188 return false;
189 }
190 };
191
192 // Qi parsers using the 'real_policies_NANfixed_' template which allows for 'nan'
193 // (the original Boost implementation has a bug, see https://svn.boost.org/trac/boost/ticket/6955)
194 static boost::spirit::qi::real_parser<double, real_policies_NANfixed_<double> > parse_double_;
195 static boost::spirit::qi::real_parser<float, real_policies_NANfixed_<float> > parse_float_;
196 static boost::spirit::qi::int_parser<> parse_int_;
197
198 };
199
200 namespace StringUtils
201 {
202
203 [[maybe_unused]] static String number(double d, UInt n)
204 {
205 return QString::number(d, 'f', n);
206 }
207
208 [[maybe_unused]] static QString toQString(const String & this_s)
209 {
210 return QString(this_s.c_str());
211 }
212
213 [[maybe_unused]] static Int32 toInt32(const String & this_s)
214 {
215 return StringUtilsHelper::toInt32(this_s);
216 }
217
218 [[maybe_unused]] static Int64 toInt64(const String& this_s)
219 {
220 return StringUtilsHelper::toInt64(this_s);
221 }
222
223 [[maybe_unused]] static float toFloat(const String & this_s)
224 {
225 return StringUtilsHelper::toFloat(this_s);
226 }
227
228 [[maybe_unused]] static double toDouble(const String & this_s)
229 {
230 return StringUtilsHelper::toDouble(this_s);
231 }
232
233 template <typename IteratorT>
234 static bool extractDouble(IteratorT& begin, const IteratorT& end, double& target)
235 {
236 return StringUtilsHelper::extractDouble(begin, end, target);
237 }
238
239 template <typename IteratorT>
240 static bool extractInt(IteratorT& begin, const IteratorT& end, int& target)
241 {
242 return StringUtilsHelper::extractInt(begin, end, target);
243 }
244 }
245} // namespace OPENMS
246
Invalid conversion exception.
Definition Exception.h:331
Definition StringUtils.h:32
static double toDouble(const String &s)
convert String (leading and trailing whitespace allowed) to double
Definition StringUtils.h:105
static boost::spirit::qi::int_parser parse_int_
Definition StringUtils.h:196
static bool extractDouble(IteratorT &begin, const IteratorT &end, double &target)
Definition StringUtils.h:128
static Int64 toInt64(const String &this_s)
Definition StringUtils.h:58
static float toFloat(const String &this_s)
Definition StringUtils.h:79
static Int toInt32(const String &this_s)
Functions.
Definition StringUtils.h:39
static boost::spirit::qi::real_parser< double, real_policies_NANfixed_< double > > parse_double_
Definition StringUtils.h:194
static boost::spirit::qi::real_parser< float, real_policies_NANfixed_< float > > parse_float_
Definition StringUtils.h:195
static bool extractInt(IteratorT &begin, const IteratorT &end, int &target)
Definition StringUtils.h:142
A more convenient string class.
Definition String.h:34
const_iterator ConstIterator
Const Iterator.
Definition String.h:46
int32_t Int32
Signed integer type (32bit)
Definition Types.h:26
int64_t Int64
Signed integer type (64bit)
Definition Types.h:40
int Int
Signed integer type.
Definition Types.h:72
unsigned int UInt
Unsigned integer type.
Definition Types.h:64
static bool extractDouble(IteratorT &begin, const IteratorT &end, double &target)
Definition StringUtils.h:234
static QString toQString(const String &this_s)
Definition StringUtils.h:208
static Int64 toInt64(const String &this_s)
Definition StringUtils.h:218
static float toFloat(const String &this_s)
Definition StringUtils.h:223
static double toDouble(const String &this_s)
Definition StringUtils.h:228
static Int32 toInt32(const String &this_s)
Definition StringUtils.h:213
static bool extractInt(IteratorT &begin, const IteratorT &end, int &target)
Definition StringUtils.h:240
static String number(double d, UInt n)
Definition StringUtils.h:203
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19
static bool parse_nan(Iterator &first, Iterator const &last, Attribute &attr_)
Definition StringUtils.h:162