OpenMS
StringConversions.h
Go to the documentation of this file.
1 // Copyright (c) 2002-2023, 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 <string>
22 #include <vector>
23 
24 
25 namespace OpenMS
26 {
27  class String;
28 
29  namespace StringConversions
30  {
31 
32  // Karma full precision float policy
33  template <typename T>
34  class BK_PrecPolicy : public boost::spirit::karma::real_policies<T>
35  {
36  typedef boost::spirit::karma::real_policies<T> base_policy_type;
37  public:
38  static unsigned precision(T /*n*/)
39  {
40  /* The following would be the only way for a lossless double-string-double
41  * roundtrip but:
42  * a) We only care about speed
43  * b) Many tests have to be changed
44  * c) In the end boost::karma is bugged and hard limits the fractional digits
45  * even though you have leading zeros (basically forcing scientific notation)
46  * for full precision https://github.com/boostorg/spirit/issues/585
47  if (BK_PrecPolicy::floatfield(n))
48  {
49  T abs_n = boost::spirit::traits::get_absolute_value(n);
50  if (abs_n >= 1)
51  {
52  return std::numeric_limits<T>::max_digits10 - (floor(log10(abs_n)) + 1);
53  }
54  else
55  {
56  return std::numeric_limits<T>::max_digits10 - (floor(log10(abs_n)));
57  }
58  }
59  else
60  {
61  return std::numeric_limits<T>::max_digits10 - 1;
62  }
63  */
64  return writtenDigits<T>();
65  }
66 
67  // we want the numbers always to be in scientific format
68  static unsigned floatfield(T n)
69  {
70  if (boost::spirit::traits::test_zero(n))
71  return base_policy_type::fmtflags::fixed;
72 
73  T abs_n = boost::spirit::traits::get_absolute_value(n);
74  // this is due to a bug in downstream thirdparty tools that only can read
75  // up to 19 digits. https://github.com/OpenMS/OpenMS/issues/4627
76  return (abs_n >= 1e4 || abs_n < 1e-2)
77  ? base_policy_type::fmtflags::scientific : base_policy_type::fmtflags::fixed;
78  }
79  };
80  typedef boost::spirit::karma::real_generator<float, BK_PrecPolicy<float> > BK_PrecPolicyFloat_type;
82  typedef boost::spirit::karma::real_generator<double, BK_PrecPolicy<double> > BK_PrecPolicyDouble_type;
84  typedef boost::spirit::karma::real_generator<long double, BK_PrecPolicy<long double> > BK_PrecPolicyLongDouble_type;
86 
87  // toString functions (single argument)
88 
91  template <typename T>
92  inline void append(const T& i, String& target)
93  {
94  std::back_insert_iterator<std::string> sink(target);
95  boost::spirit::karma::generate(sink, i);
96  }
97 
99  template <typename T>
100  inline String toString(const T& i)
101  {
102  //std::stringstream s;
103  //s << i;
104  //return s.str();
105  String str;
106  append(i, str);
107  return str;
108  }
109 
110 
113  inline void appendLowP(float f, String& target)
114  {
115  std::back_insert_iterator<std::string> sink(target);
116  boost::spirit::karma::generate(sink, f);
117  }
119  inline String toStringLowP(float f)
120  {
121  String str;
122  appendLowP(f, str);
123  return str;
124  }
125 
126 
129  inline void appendLowP(double d, String& target)
130  {
131  std::back_insert_iterator<std::string> sink(target);
132  boost::spirit::karma::generate(sink, d);
133  }
135  inline String toStringLowP(double d)
136  {
137  String str;
138  appendLowP(d, str);
139  return str;
140  }
141 
142 
144  inline void appendLowP(long double ld, String& target)
145  {
146  std::back_insert_iterator<std::string> sink(target);
147  boost::spirit::karma::generate(sink, ld);
148  }
150  inline String toStringLowP(long double ld)
151  {
152  String str;
153  appendLowP(ld, str);
154  return str;
155  }
156 
157 
158 
160  inline void append(float f, String& target)
161  {
162  std::back_insert_iterator<std::string> sink(target);
163  boost::spirit::karma::generate(sink, BK_PrecPolicyFloat, f);
164  }
166  inline String toString(float f)
167  {
168  String str;
169  append(f, str);
170  return str;
171  }
172 
173 
174 
176  inline void append(double d, String& target)
177  {
178  std::back_insert_iterator<std::string> sink(target);
179  boost::spirit::karma::generate(sink, BK_PrecPolicyDouble, d);
180  }
182  inline String toString(double d)
183  {
184  String str;
185  append(d, str);
186  return str;
187  }
188 
189 
191  inline void append(long double ld, String& target)
192  {
193  std::back_insert_iterator<std::string> sink(target);
194  boost::spirit::karma::generate(sink, BK_PrecPolicyLongDouble, ld);
195  }
197  inline String toString(long double ld)
198  {
199  String str;
200  append(ld, str);
201  return str;
202  }
203 
204 
205  inline void append(const DataValue& d, bool full_precision, String& target)
206  {
207  target += d.toString(full_precision);
208  }
209  inline String toString(const DataValue& d, bool full_precision)
210  {
211  return d.toString(full_precision);
212  }
213 
214 
215 
216  inline String toString(const char c)
217  {
218  return std::string(1, c);
219  }
220 
221  inline String toString(const std::string& s)
222  {
223  return s;
224  }
225 
226  inline String toString(const char* s)
227  {
228  return std::string(s);
229  }
230 
232  inline String toString()
233  {
234  return String();
235  }
236 
237  }
238 
239 } // namespace OPENMS
240 
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...
Definition: StringConversions.h:35
static unsigned precision(T)
Definition: StringConversions.h:38
static unsigned floatfield(T n)
Definition: StringConversions.h:68
boost::spirit::karma::real_policies< T > base_policy_type
Definition: StringConversions.h:36
A more convenient string class.
Definition: String.h:34
const double c
Definition: Constants.h:188
boost::spirit::karma::real_generator< long double, BK_PrecPolicy< long double > > BK_PrecPolicyLongDouble_type
Definition: StringConversions.h:84
boost::spirit::karma::real_generator< float, BK_PrecPolicy< float > > BK_PrecPolicyFloat_type
Definition: StringConversions.h:80
const BK_PrecPolicyLongDouble_type BK_PrecPolicyLongDouble
Definition: StringConversions.h:85
String toStringLowP(float f)
low precision (3 fractional digits) conversion to string (Karma default)
Definition: StringConversions.h:119
void appendLowP(float f, String &target)
Definition: StringConversions.h:113
const BK_PrecPolicyDouble_type BK_PrecPolicyDouble
Definition: StringConversions.h:83
String toString(const T &i)
fallback template for general purpose using Boost::Karma; more specializations below
Definition: StringConversions.h:100
void append(const T &i, String &target)
Definition: StringConversions.h:92
const BK_PrecPolicyFloat_type BK_PrecPolicyFloat
Definition: StringConversions.h:81
boost::spirit::karma::real_generator< double, BK_PrecPolicy< double > > BK_PrecPolicyDouble_type
Definition: StringConversions.h:82
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:22