A library for working with phylogenetic and population genetic data.
v0.32.0
convert.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_TEXT_CONVERT_H_
2 #define GENESIS_UTILS_TEXT_CONVERT_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2023 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
35 
36 #include <iostream>
37 #include <sstream>
38 #include <stdexcept>
39 #include <string>
40 #include <typeinfo>
41 #include <vector>
42 
43 namespace genesis {
44 namespace utils {
45 
46 // =================================================================================================
47 // Generic Conversion
48 // =================================================================================================
49 
58 template <typename T>
59 T convert_from_string( std::string const& str, bool trim = false )
60 {
61  T value;
62 
63  // Generic parser that just uses a string stream.
64  // Convert, and fail if there is more in the string that we expect.
65  bool good = true;
66  try {
67  std::stringstream ss( trim ? utils::trim(str) : str );
68  ss >> std::noskipws >> value;
69  ss.peek();
70  good = ss.eof();
71  } catch(...) {
72  good = false;
73  }
74 
75  // If we are here, either the string stream conversion itself failed (that's what the catch
76  // is for), or there was more data in the stream that we could convert. Either way, throw.
77  if( !good ) {
78  throw std::invalid_argument(
79  "Cannot convert string \"" + str + "\" to type " + std::string( typeid(T).name() )
80  );
81  }
82  return value;
83 }
84 
88 template <>
89 inline std::string convert_from_string<std::string>( std::string const& str, bool trim )
90 {
91  // We need special treatment of strings here, as the stringstream would only give
92  // us the first word of the input otherwise.
93  return (trim ? utils::trim(str) : str);
94 }
95 
100 template <>
101 inline double convert_from_string<double>( std::string const& str, bool trim )
102 {
103  // For double, we use a more fitting function that also parses inf and nan.
104  auto const input = (trim ? utils::trim(str) : str);
105  char* end = nullptr;
106  auto const value = std::strtod( input.c_str(), &end );
107  if( end == nullptr || *end != '\0' || end - input.c_str() != static_cast<long>( input.size() )) {
108  throw std::runtime_error(
109  "Cannot convert string \"" + input + "\" to type double"
110  );
111  }
112  return value;
113 }
114 
115 // =================================================================================================
116 // Bool Text Conversion
117 // =================================================================================================
118 
125 bool convert_to_bool( std::string const& str, bool& result );
126 
133 bool convert_to_bool( std::string const& str );
134 
141 bool is_convertible_to_bool( std::string const& str );
142 
143 template<typename ForwardIterator>
144 std::vector<bool> convert_to_bool(
145  ForwardIterator first,
146  ForwardIterator last,
147  size_t size = 0
148 ) {
149  // Prep.
150  std::vector<bool> ret;
151  ret.reserve( size );
152 
153  // Add all values. Throws on error.
154  while( first != last ) {
155  ret.push_back( convert_to_bool( *first ));
156  ++first;
157  }
158  return ret;
159 }
160 
161 template<typename ForwardIterator>
163  ForwardIterator first,
164  ForwardIterator last
165 ) {
166  while( first != last ) {
167  if( !is_convertible_to_bool( *first )) {
168  return false;
169  }
170  ++first;
171  }
172  return true;
173 }
174 
175 // =================================================================================================
176 // Bool Double Text Conversion
177 // =================================================================================================
178 
185 bool convert_to_bool_double( std::string const& str, double& result );
186 
193 double convert_to_bool_double( std::string const& str );
194 
204 bool is_convertible_to_bool_double( std::string const& str );
205 
206 template<typename ForwardIterator>
207 std::vector<double> convert_to_bool_double(
208  ForwardIterator first,
209  ForwardIterator last,
210  size_t size = 0
211 ) {
212  // Prep.
213  std::vector<double> ret;
214  ret.reserve( size );
215 
216  // Add all values. Throws on error.
217  while( first != last ) {
218  ret.push_back( convert_to_bool_double( *first ));
219  ++first;
220  }
221  return ret;
222 }
223 
224 template<typename ForwardIterator>
226  ForwardIterator first,
227  ForwardIterator last
228 ) {
229  while( first != last ) {
230  if( !is_convertible_to_bool_double( *first )) {
231  return false;
232  }
233  ++first;
234  }
235  return true;
236 }
237 
238 // =================================================================================================
239 // Double Text Conversion
240 // =================================================================================================
241 
246 bool convert_to_double( std::string const& str, double& result );
247 
252 double convert_to_double( std::string const& str );
253 
257 bool is_convertible_to_double( std::string const& str );
258 
259 template<typename ForwardIterator>
260 std::vector<double> convert_to_double(
261  ForwardIterator first,
262  ForwardIterator last,
263  size_t size = 0
264 ) {
265  // Prep.
266  std::vector<double> ret;
267  ret.reserve( size );
268 
269  // Add all values. Throws on error.
270  while( first != last ) {
271  ret.push_back( convert_to_double( *first ));
272  ++first;
273  }
274  return ret;
275 }
276 
277 template<typename ForwardIterator>
279  ForwardIterator first,
280  ForwardIterator last
281 ) {
282  while( first != last ) {
283  if( !is_convertible_to_double( *first )) {
284  return false;
285  }
286  ++first;
287  }
288  return true;
289 }
290 
291 // =================================================================================================
292 // Signed Integer Text Conversion
293 // =================================================================================================
294 
299 bool convert_to_signed_integer( std::string const& str, long long& result );
300 
305 long long convert_to_signed_integer( std::string const& str );
306 
310 bool is_convertible_to_signed_integer( std::string const& str );
311 
312 template<typename ForwardIterator>
313 std::vector<long long> convert_to_signed_integer(
314  ForwardIterator first,
315  ForwardIterator last,
316  size_t size = 0
317 ) {
318  // Prep.
319  std::vector<long long> ret;
320  ret.reserve( size );
321 
322  // Add all values. Throws on error.
323  while( first != last ) {
324  ret.push_back( convert_to_signed_integer( *first ));
325  ++first;
326  }
327  return ret;
328 }
329 
330 template<typename ForwardIterator>
332  ForwardIterator first,
333  ForwardIterator last
334 ) {
335  while( first != last ) {
336  if( !is_convertible_to_signed_integer( *first )) {
337  return false;
338  }
339  ++first;
340  }
341  return true;
342 }
343 
344 // =================================================================================================
345 // Unsigned Integer Text Conversion
346 // =================================================================================================
347 
352 bool convert_to_unsigned_integer( std::string const& str, unsigned long long& result );
353 
358 unsigned long long convert_to_unsigned_integer( std::string const& str );
359 
363 bool is_convertible_to_unsigned_integer( std::string const& str );
364 
365 template<typename ForwardIterator>
366 std::vector<unsigned long long> convert_to_unsigned_integer(
367  ForwardIterator first,
368  ForwardIterator last,
369  size_t size = 0
370 ) {
371  // Prep.
372  std::vector<unsigned long long> ret;
373  ret.reserve( size );
374 
375  // Add all values. Throws on error.
376  while( first != last ) {
377  ret.push_back( convert_to_unsigned_integer( *first ));
378  ++first;
379  }
380  return ret;
381 }
382 
383 template<typename ForwardIterator>
385  ForwardIterator first,
386  ForwardIterator last
387 ) {
388  while( first != last ) {
389  if( !is_convertible_to_unsigned_integer( *first )) {
390  return false;
391  }
392  ++first;
393  }
394  return true;
395 }
396 
397 } // namespace utils
398 } // namespace genesis
399 
400 #endif // include guard
genesis::utils::convert_from_string< double >
double convert_from_string< double >(std::string const &str, bool trim)
Specialization of the generic conversion function for double, which also takes nan and inf into accou...
Definition: convert.hpp:101
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::convert_from_string
T convert_from_string(std::string const &str, bool trim=false)
Generic conversion from string to any data type that is supported by std::stringsteam operator >>.
Definition: convert.hpp:59
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
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::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