A library for working with phylogenetic and population genetic data.
v0.32.0
convert.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2022 Lucas Czech
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lczech@carnegiescience.edu>
20  Department of Plant Biology, Carnegie Institution For Science
21  260 Panama Street, Stanford, CA 94305, USA
22 */
23 
32 
34 
35 #include <algorithm>
36 #include <cctype>
37 #include <limits>
38 #include <string>
39 #include <stdexcept>
40 #include <vector>
41 
42 namespace genesis {
43 namespace utils {
44 
45 // =================================================================================================
46 // Bool Text Conversion
47 // =================================================================================================
48 
49 bool convert_to_bool( std::string const& str, bool& result )
50 {
51  // Prep.
52  auto const cont = to_lower_ascii( trim( str ));
53 
54  // Value check.
55  if( cont == "true" || cont == "yes" || cont == "on" || cont == "1" ) {
56  result = true;
57  return true;
58  } else if( cont.empty() || cont == "false" || cont == "no" || cont == "off" || cont == "0" ) {
59  result = false;
60  return true;
61  }
62  return false;
63 }
64 
65 bool convert_to_bool( std::string const& str )
66 {
67  bool result;
68  if( !convert_to_bool( str, result )) {
69  throw std::runtime_error( "String is not convertible to bool: \"" + str + "\"" );
70  }
71  return result;
72 }
73 
74 bool is_convertible_to_bool( std::string const& str )
75 {
76  bool result;
77  return convert_to_bool( str, result );
78 }
79 
80 // =================================================================================================
81 // Bool Double Text Conversion
82 // =================================================================================================
83 
84 bool convert_to_bool_double( std::string const& str, double& result )
85 {
86  // Prep.
87  auto const cont = to_lower_ascii( trim( str ));
88 
89  // Value check. Need a bit of code duplciation here in order to catch the empty case.
90  if( cont == "true" || cont == "yes" || cont == "on" || cont == "1" ) {
91  result = 1.0;
92  return true;
93  } else if( cont == "false" || cont == "no" || cont == "off" || cont == "0" ) {
94  result = 0.0;
95  return true;
96  } else if( cont.empty() ) {
97  result = std::numeric_limits<double>::quiet_NaN();
98  return true;
99  }
100  return false;
101 }
102 
103 double convert_to_bool_double( std::string const& str )
104 {
105  double result;
106  if( !convert_to_bool_double( str, result )) {
107  throw std::runtime_error( "String is not convertible to bool: \"" + str + "\"" );
108  }
109  return result;
110 }
111 
112 bool is_convertible_to_bool_double( std::string const& str )
113 {
114  double result;
115  return convert_to_bool_double( str, result );
116 }
117 
118 // =================================================================================================
119 // Conversion Helper
120 // =================================================================================================
121 
122 template<typename T, class F>
123 bool convert_to_numeric_( std::string const& str, T& result, T initial, F conversion )
124 {
125  // Some default cases. Ignore whitespace. Accepty emptry string.
126  bool err = false;
127  result = initial;
128  auto const lower = trim( str );
129  if( lower.empty() ) {
130  return true;
131  }
132 
133  try{
134  // Try conversion. Throws on failure, which we catch.
135  std::size_t pos;
136  result = conversion( lower, &pos );
137  if( pos != lower.size() ) {
138  err = true;
139  }
140  } catch(...) {
141  err = true;
142  }
143  return !err;
144 }
145 
146 // =================================================================================================
147 // Double Text Conversion
148 // =================================================================================================
149 
150 bool convert_to_double( std::string const& str, double& result )
151 {
152  // Need to use a lambda here, see https://stackoverflow.com/a/71310216/4184258
153  return convert_to_numeric_(
154  str, result, std::numeric_limits<double>::quiet_NaN(),
155  []( std::string const& str, std::size_t* pos ){
156  return std::stod( str, pos );
157  }
158  );
159 }
160 
161 double convert_to_double( std::string const& str )
162 {
163  double result;
164  if( !convert_to_double( str, result )) {
165  throw std::runtime_error(
166  "String is not convertible to double: \"" + str + "\""
167  );
168  }
169  return result;
170 }
171 
172 bool is_convertible_to_double( std::string const& str )
173 {
174  double result;
175  return convert_to_double( str, result );
176 }
177 
178 // =================================================================================================
179 // Signed Integer Text Conversion
180 // =================================================================================================
181 
182 bool convert_to_signed_integer( std::string const& str, long long& result )
183 {
184  // Need to use a lambda here, see https://stackoverflow.com/a/71310216/4184258
185  return convert_to_numeric_(
186  str, result, static_cast<long long>(0),
187  []( std::string const& str, std::size_t* pos ){
188  return std::stoll( str, pos );
189  }
190  );
191 }
192 
193 long long convert_to_signed_integer( std::string const& str )
194 {
195  long long result;
196  if( !convert_to_signed_integer( str, result )) {
197  throw std::runtime_error(
198  "String is not convertible to signed integer (long long): \"" + str + "\""
199  );
200  }
201  return result;
202 }
203 
204 bool is_convertible_to_signed_integer( std::string const& str )
205 {
206  long long result;
207  return convert_to_signed_integer( str, result );
208 }
209 
210 // =================================================================================================
211 // Unsigned Integer Text Conversion
212 // =================================================================================================
213 
214 bool convert_to_unsigned_integer( std::string const& str, unsigned long long& result )
215 {
216  // Need to use a lambda here, see https://stackoverflow.com/a/71310216/4184258
217  return convert_to_numeric_(
218  str, result, static_cast<unsigned long long>(0),
219  []( std::string const& str, std::size_t* pos ){
220  return std::stoull( str, pos );
221  }
222  );
223 }
224 
225 unsigned long long convert_to_unsigned_integer( std::string const& str )
226 {
227  unsigned long long result;
228  if( !convert_to_unsigned_integer( str, result )) {
229  throw std::runtime_error(
230  "String is not convertible to unsigned integer (unsigned long long): \"" + str + "\""
231  );
232  }
233  return result;
234 }
235 
236 bool is_convertible_to_unsigned_integer( std::string const& str )
237 {
238  unsigned long long result;
239  return convert_to_unsigned_integer( str, result );
240 }
241 
242 } // namespace utils
243 } // namespace genesis
genesis::utils::is_convertible_to_unsigned_integer
bool is_convertible_to_unsigned_integer(std::string const &str)
Return whether a string can be converted to unsigned integer.
Definition: convert.cpp:236
genesis::utils::is_convertible_to_bool
bool is_convertible_to_bool(Dataframe const &df, size_t col_index)
Definition: utils/containers/dataframe/operators.cpp:61
genesis::utils::trim
std::string trim(std::string const &s, std::string const &delimiters)
Return a copy of the input string, with trimmed white spaces (or any other delimiters).
Definition: string.cpp:827
genesis::utils::convert_to_double
void convert_to_double(Dataframe &df, size_t col_index)
Definition: utils/containers/dataframe/operators.cpp:192
string.hpp
Provides some commonly used string utility functions.
genesis::utils::convert_to_unsigned_integer
bool convert_to_unsigned_integer(std::string const &str, unsigned long long &result)
Convert a string to unsigned integer, store the result in result, and return whether the conversion a...
Definition: convert.cpp:214
genesis::utils::is_convertible_to_bool_double
bool is_convertible_to_bool_double(std::string const &str)
Return whether a string can be converted to bool (and stored as a double).
Definition: convert.cpp:112
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
convert.hpp
genesis::utils::is_convertible_to_double
bool is_convertible_to_double(Dataframe const &df, size_t col_index)
Definition: utils/containers/dataframe/operators.cpp:84
genesis::utils::to_lower_ascii
std::string to_lower_ascii(std::string const &str)
Return an all-lowercase copy of the given string, ASCII-only.
Definition: string.cpp:895
genesis::utils::convert_to_bool
void convert_to_bool(Dataframe &df, size_t col_index)
Definition: utils/containers/dataframe/operators.cpp:156
genesis::utils::is_convertible_to_signed_integer
bool is_convertible_to_signed_integer(std::string const &str)
Return whether a string can be converted to signed integer.
Definition: convert.cpp:204
genesis::utils::convert_to_signed_integer
bool convert_to_signed_integer(std::string const &str, long long &result)
Convert a string to signed integer, store the result in result, and return whether the conversion as ...
Definition: convert.cpp:182
genesis::utils::convert_to_bool_double
bool convert_to_bool_double(std::string const &str, double &result)
Convert a string to bool, but store the result as a double in result, and return whether the conversi...
Definition: convert.cpp:84
genesis::utils::convert_to_numeric_
bool convert_to_numeric_(std::string const &str, T &result, T initial, F conversion)
Definition: convert.cpp:123