The Battle for Wesnoth  1.19.7+dev
charconv.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
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 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "utils/charconv.hpp"
16 #include <cctype>
17 #include <cstdlib>
18 #include <cassert>
19 #include <string>
20 
21 #ifdef USE_FALLBACK_CHARCONV
22 
23 namespace
24 {
25  template<typename T>
26  T string_to_floating_point(const char* str, char** str_end) = delete;
27  template<>
28  float string_to_floating_point(const char* str, char** str_end)
29  {
30  return std::strtof(str, str_end);
31  }
32  template<>
33  double string_to_floating_point(const char* str, char** str_end)
34  {
35  return std::strtod(str, str_end);
36  }
37  template<>
38  long double string_to_floating_point(const char* str, char** str_end)
39  {
40  return std::strtold(str, str_end);
41  }
42 }
43 namespace utils::charconv
44 {
45  template<typename T>
46  std::enable_if_t<std::is_same_v<T, double> || std::is_same_v<T, float> || std::is_same_v<T, long double>, from_chars_result> from_chars(const char* first, const char* last, T& value, chars_format fmt)
47  {
48  // We don't need the other formats.
49  assert(fmt = chars_format::general);
50 
51  // Make a copy to make sure its null terminated.
52  std::string buffer = std::string(first, last);
53  // from_chars doesnt support leading whitespace or plus signs.
54  if(buffer.empty() || std::isspace(buffer.front()) || buffer.front() == '+' ) {
55  return { first, std::errc::invalid_argument };
56  }
57 
58 
59  locale_t l = newlocale(LC_ALL, "C", static_cast<locale_t>(0));
60  locale_t l_prev = uselocale(l);
61 
62  //initilize this to silence a warning.
63  char* str_end = nullptr;
64  value = string_to_floating_point<T>( buffer.data(), &str_end );
65 
66  uselocale(l_prev);
67  freelocale(l);
68 
69  if(str_end == buffer.data()) {
70  return { first, std::errc::invalid_argument };
71  }
72  return { first + (str_end - buffer.data()), std::errc() };
73  }
74  template from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt);
75  template from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt);
76  template from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt);
77 }
78 
79 #endif
log_domain & general()
Definition: log.cpp:333
std::enable_if_t< std::is_integral_v< T >, from_chars_result > from_chars(const char *first, const char *last, T &value, int base=10)
Definition: charconv.hpp:61
charconv_impl::from_chars_result from_chars_result
Definition: charconv.hpp:51
charconv_impl::chars_format chars_format
Definition: charconv.hpp:50