OpenMS
StringConversions.h
Go to the documentation of this file.
1 // Copyright (c) 2002-present, The OpenMS Team -- 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 
11 #include <OpenMS/CONCEPT/Types.h>
16 
17 #include <boost/spirit/include/qi.hpp>
18 #include <boost/spirit/include/karma.hpp>
19 #include <boost/type_traits.hpp>
20 
21 #include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
22 
23 #include <string>
24 #include <vector>
25 
26 
27 namespace OpenMS
28 {
29  class String;
30 
31  namespace StringConversions
32  {
33 
34  namespace Detail
35  {
36  // Karma full precision float policy
37  template<typename T>
38  class BK_PrecPolicyFull : public boost::spirit::karma::real_policies<T>
39  {
40  typedef boost::spirit::karma::real_policies<T> base_policy_type;
41 
42  public:
43  static unsigned precision(T /*n*/)
44  {
45  /* The following would be the only way for a lossless double-string-double
46  * roundtrip but:
47  * a) We only care about speed
48  * b) Many tests have to be changed
49  * c) In the end boost::karma is bugged and hard limits the fractional digits
50  * even though you have leading zeros (basically forcing scientific notation)
51  * for full precision https://github.com/boostorg/spirit/issues/585
52  if (BK_PrecPolicyFull::floatfield(n))
53  {
54  T abs_n = boost::spirit::traits::get_absolute_value(n);
55  if (abs_n >= 1)
56  {
57  return std::numeric_limits<T>::max_digits10 - (floor(log10(abs_n)) + 1);
58  }
59  else
60  {
61  return std::numeric_limits<T>::max_digits10 - (floor(log10(abs_n)));
62  }
63  }
64  else
65  {
66  return std::numeric_limits<T>::max_digits10 - 1;
67  }
68  */
69  return writtenDigits<T>();
70  }
71 
72  // we want the numbers always to be in scientific format
73  static unsigned floatfield(T n)
74  {
75  if (boost::spirit::traits::test_zero(n)) return base_policy_type::fmtflags::fixed;
76 
77  T abs_n = boost::spirit::traits::get_absolute_value(n);
78  // this is due to a bug in downstream thirdparty tools that only can read
79  // up to 19 digits. https://github.com/OpenMS/OpenMS/issues/4627
80  return (abs_n >= 1e4 || abs_n < 1e-2) ? base_policy_type::fmtflags::scientific : base_policy_type::fmtflags::fixed;
81  }
82 
83  // we need this special 'NaN' since the default 'nan' is not recognized by downstream tools such as any Java-based tool (e.g. KNIME) trying to
84  // parse our output files
85  template<typename CharEncoding, typename Tag, typename OutputIterator>
86  static bool nan(OutputIterator& sink, T n, bool force_sign)
87  {
88  return boost::spirit::karma::sign_inserter::call(sink, false, boost::spirit::traits::test_negative(n), force_sign)
89  && boost::spirit::karma::string_inserter<CharEncoding, Tag>::call(sink, "NaN");
90  }
91  };
92 
93  // Karma default (3-digits) precision float policy
94  template<typename T>
95  class BK_PrecPolicyShort : public boost::spirit::karma::real_policies<T>
96  {
97  typedef boost::spirit::karma::real_policies<T> base_policy_type;
98 
99  public:
100  // we need this special 'NaN' since the default 'nan' is not recognized by downstream tools such as any Java-based tool (e.g. KNIME) trying to
101  // parse our output files
102  template<typename CharEncoding, typename Tag, typename OutputIterator>
103  static bool nan(OutputIterator& sink, T n, bool force_sign)
104  {
105  return boost::spirit::karma::sign_inserter::call(sink, false, boost::spirit::traits::test_negative(n), force_sign)
106  && boost::spirit::karma::string_inserter<CharEncoding, Tag>::call(sink, "NaN");
107  }
108  };
109 
110  using BK_PrecPolicyFloatFull_type = boost::spirit::karma::real_generator<float, BK_PrecPolicyFull<float>>;
112  using BK_PrecPolicyDoubleFull_type = boost::spirit::karma::real_generator<double, BK_PrecPolicyFull<double>>;
114  using BK_PrecPolicyLongDoubleFull_type = boost::spirit::karma::real_generator<long double, BK_PrecPolicyFull<long double>>;
116 
117  using BK_PrecPolicyFloatShort_type = boost::spirit::karma::real_generator<float, BK_PrecPolicyShort<float>>;
119  using BK_PrecPolicyDoubleShort_type = boost::spirit::karma::real_generator<double, BK_PrecPolicyShort<double>>;
121  using BK_PrecPolicyLongDoubleShort_type = boost::spirit::karma::real_generator<long double, BK_PrecPolicyShort<long double>>;
123 
124  } // namespace Detail
125 
126 
127 
128  // toString functions (single argument)
129 
132  template <typename T>
133  inline void append(const T& i, String& target)
134  {
135  std::back_insert_iterator<std::string> sink(target);
136  boost::spirit::karma::generate(sink, i);
137  }
138 
140  template <typename T>
141  inline String toString(const T& i)
142  {
143  //std::stringstream s;
144  //s << i;
145  //return s.str();
146  String str;
147  append(i, str);
148  return str;
149  }
150 
151 
154  inline void appendLowP(float f, String& target)
155  {
156  std::back_insert_iterator<std::string> sink(target);
157  boost::spirit::karma::generate(sink, Detail::BK_PrecPolicyFloatShort, f);
158  }
160  inline String toStringLowP(float f)
161  {
162  String str;
163  appendLowP(f, str);
164  return str;
165  }
166 
167 
170  inline void appendLowP(double d, String& target)
171  {
172  std::back_insert_iterator<std::string> sink(target);
173  boost::spirit::karma::generate(sink, Detail::BK_PrecPolicyDoubleShort, d);
174  }
176  inline String toStringLowP(double d)
177  {
178  String str;
179  appendLowP(d, str);
180  return str;
181  }
182 
183 
185  inline void appendLowP(long double ld, String& target)
186  {
187  std::back_insert_iterator<std::string> sink(target);
188  boost::spirit::karma::generate(sink, Detail::BK_PrecPolicyLongDoubleShort, ld);
189  }
191  inline String toStringLowP(long double ld)
192  {
193  String str;
194  appendLowP(ld, str);
195  return str;
196  }
197 
198 
199 
201  inline void append(float f, String& target)
202  {
203  std::back_insert_iterator<std::string> sink(target);
204  boost::spirit::karma::generate(sink, Detail::BK_PrecPolicyFloatFull, f);
205  }
207  inline String toString(float f)
208  {
209  String str;
210  append(f, str);
211  return str;
212  }
213 
214 
215 
217  inline void append(double d, String& target)
218  {
219  std::back_insert_iterator<std::string> sink(target);
220  boost::spirit::karma::generate(sink, Detail::BK_PrecPolicyDoubleFull, d);
221  }
223  inline String toString(double d)
224  {
225  String str;
226  append(d, str);
227  return str;
228  }
229 
230 
232  inline void append(long double ld, String& target)
233  {
234  std::back_insert_iterator<std::string> sink(target);
235  boost::spirit::karma::generate(sink, Detail::BK_PrecPolicyLongDoubleFull, ld);
236  }
238  inline String toString(long double ld)
239  {
240  String str;
241  append(ld, str);
242  return str;
243  }
244 
245 
246  inline void append(const DataValue& d, bool full_precision, String& target)
247  {
248  target += d.toString(full_precision);
249  }
250  inline String toString(const DataValue& d, bool full_precision)
251  {
252  return d.toString(full_precision);
253  }
254 
255 
256 
257  inline String toString(const char c)
258  {
259  return std::string(1, c);
260  }
261 
262  inline String toString(const std::string& s)
263  {
264  return s;
265  }
266 
267  inline String toString(const char* s)
268  {
269  return std::string(s);
270  }
271 
273  inline String toString()
274  {
275  return String();
276  }
277 
278  }
279 
280 } // namespace OPENMS
281 
Class to hold strings, numeric values, lists of strings and lists of numeric values.
Definition: DataValue.h:33
String toString(bool full_precision=true) const
Conversion to String full_precision Controls number of fractional digits for all double types or list...
static unsigned precision(T)
Definition: StringConversions.h:43
static unsigned floatfield(T n)
Definition: StringConversions.h:73
static bool nan(OutputIterator &sink, T n, bool force_sign)
Definition: StringConversions.h:86
boost::spirit::karma::real_policies< T > base_policy_type
Definition: StringConversions.h:40
static bool nan(OutputIterator &sink, T n, bool force_sign)
Definition: StringConversions.h:103
boost::spirit::karma::real_policies< T > base_policy_type
Definition: StringConversions.h:97
A more convenient string class.
Definition: String.h:34
const double c
Definition: Constants.h:188
const BK_PrecPolicyFloatShort_type BK_PrecPolicyFloatShort
Definition: StringConversions.h:118
boost::spirit::karma::real_generator< double, BK_PrecPolicyFull< double > > BK_PrecPolicyDoubleFull_type
Definition: StringConversions.h:112
const BK_PrecPolicyDoubleFull_type BK_PrecPolicyDoubleFull
Definition: StringConversions.h:113
const BK_PrecPolicyDoubleShort_type BK_PrecPolicyDoubleShort
Definition: StringConversions.h:120
const BK_PrecPolicyLongDoubleFull_type BK_PrecPolicyLongDoubleFull
Definition: StringConversions.h:115
boost::spirit::karma::real_generator< double, BK_PrecPolicyShort< double > > BK_PrecPolicyDoubleShort_type
Definition: StringConversions.h:119
boost::spirit::karma::real_generator< long double, BK_PrecPolicyFull< long double > > BK_PrecPolicyLongDoubleFull_type
Definition: StringConversions.h:114
boost::spirit::karma::real_generator< float, BK_PrecPolicyShort< float > > BK_PrecPolicyFloatShort_type
Definition: StringConversions.h:117
const BK_PrecPolicyFloatFull_type BK_PrecPolicyFloatFull
Definition: StringConversions.h:111
boost::spirit::karma::real_generator< float, BK_PrecPolicyFull< float > > BK_PrecPolicyFloatFull_type
Definition: StringConversions.h:110
const BK_PrecPolicyLongDoubleShort_type BK_PrecPolicyLongDoubleShort
Definition: StringConversions.h:122
boost::spirit::karma::real_generator< long double, BK_PrecPolicyShort< long double > > BK_PrecPolicyLongDoubleShort_type
Definition: StringConversions.h:121
String toStringLowP(float f)
low precision (3 fractional digits) conversion to string (Karma default)
Definition: StringConversions.h:160
void appendLowP(float f, String &target)
Definition: StringConversions.h:154
String toString(const T &i)
fallback template for general purpose using Boost::Karma; more specializations below
Definition: StringConversions.h:141
void append(const T &i, String &target)
Definition: StringConversions.h:133
Main OpenMS namespace.
Definition: openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19