|
6 | 6 | #include <algorithm> |
7 | 7 | #include <array> |
8 | 8 | #include <charconv> |
| 9 | +#if __cpp_lib_to_chars < 201611L |
9 | 10 | #include <clocale> |
| 11 | +#endif |
10 | 12 | #include <cstdlib> |
11 | 13 | #include <cstring> |
12 | 14 | #include <tuple> |
@@ -197,26 +199,46 @@ uint32_t convertFromString<uint32_t>(StringView str) |
197 | 199 | template <> |
198 | 200 | double convertFromString<double>(StringView str) |
199 | 201 | { |
200 | | - // see issue #120 |
201 | | - // http://quick-bench.com/DWaXRWnxtxvwIMvZy2DxVPEKJnE |
202 | | - |
| 202 | +#if __cpp_lib_to_chars >= 201611L |
| 203 | + // from_chars is locale-independent and thread-safe |
| 204 | + double result = 0; |
| 205 | + const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result); |
| 206 | + if(ec != std::errc()) |
| 207 | + { |
| 208 | + throw RuntimeError(StrCat("Can't convert string [", str, "] to double")); |
| 209 | + } |
| 210 | + return result; |
| 211 | +#else |
| 212 | + // Fallback: stod is locale-dependent, so force "C" locale. |
| 213 | + // See issue #120. Note: setlocale is not thread-safe. |
203 | 214 | const std::string old_locale = setlocale(LC_NUMERIC, nullptr); |
204 | 215 | std::ignore = setlocale(LC_NUMERIC, "C"); |
205 | 216 | const std::string str_copy(str.data(), str.size()); |
206 | 217 | const double val = std::stod(str_copy); |
207 | 218 | std::ignore = setlocale(LC_NUMERIC, old_locale.c_str()); |
208 | 219 | return val; |
| 220 | +#endif |
209 | 221 | } |
210 | 222 |
|
211 | 223 | template <> |
212 | 224 | float convertFromString<float>(StringView str) |
213 | 225 | { |
| 226 | +#if __cpp_lib_to_chars >= 201611L |
| 227 | + float result = 0; |
| 228 | + const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result); |
| 229 | + if(ec != std::errc()) |
| 230 | + { |
| 231 | + throw RuntimeError(StrCat("Can't convert string [", str, "] to float")); |
| 232 | + } |
| 233 | + return result; |
| 234 | +#else |
214 | 235 | const std::string old_locale = setlocale(LC_NUMERIC, nullptr); |
215 | 236 | std::ignore = setlocale(LC_NUMERIC, "C"); |
216 | 237 | const std::string str_copy(str.data(), str.size()); |
217 | 238 | const double val = std::stod(str_copy); |
218 | 239 | std::ignore = setlocale(LC_NUMERIC, old_locale.c_str()); |
219 | 240 | return static_cast<float>(val); |
| 241 | +#endif |
220 | 242 | } |
221 | 243 |
|
222 | 244 | template <> |
|
0 commit comments