diff options
author | W. J. van der Laan <laanwj@protonmail.com> | 2021-09-30 14:47:03 +0200 |
---|---|---|
committer | W. J. van der Laan <laanwj@protonmail.com> | 2021-09-30 15:14:58 +0200 |
commit | 2d8e0c0c3c0d3c4cee7bb52d1edf501f40c53463 (patch) | |
tree | 8266dac1d118b5985f5f84b1550752198bc21f38 /src/util/strencodings.h | |
parent | 1cf7fb9fd65820b298a0eb28f6e2c4c7409c78d1 (diff) | |
parent | 4747db876154ddd828c03d9eda10ecf8b25d8dc8 (diff) |
Merge bitcoin/bitcoin#20457: util: Make Parse{Int,UInt}{32,64} use locale independent std::from_chars(…) (C++17) instead of locale dependent strto{l,ll,ul,ull}
4747db876154ddd828c03d9eda10ecf8b25d8dc8 util: Introduce ToIntegral<T>(const std::string&) for locale independent parsing using std::from_chars(…) (C++17) (practicalswift)
Pull request description:
Make `Parse{Int,UInt}{32,64}` use locale independent `std::from_chars(…)` (C++17) instead of locale dependent `strto{l,ll,ul,ull}`.
[About `std::from_chars`](https://en.cppreference.com/w/cpp/utility/from_chars): _"Unlike other parsing functions in C++ and C libraries, `std::from_chars` is locale-independent, non-allocating, and non-throwing."_
ACKs for top commit:
laanwj:
Code review ACK 4747db876154ddd828c03d9eda10ecf8b25d8dc8
Tree-SHA512: 40f2cd582bc19ddcf2c498eca3379167619eff6aa047bbac2f73b8fd8ecaefe5947c66700a189f83848751f9f8c05645e83afd4a44a1679062aee5440dba880a
Diffstat (limited to 'src/util/strencodings.h')
-rw-r--r-- | src/util/strencodings.h | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 26dc0a0ce3..1217572c45 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -12,8 +12,10 @@ #include <attributes.h> #include <span.h> +#include <charconv> #include <cstdint> #include <iterator> +#include <optional> #include <string> #include <vector> @@ -95,6 +97,24 @@ constexpr inline bool IsSpace(char c) noexcept { } /** + * Convert string to integral type T. + * + * @returns std::nullopt if the entire string could not be parsed, or if the + * parsed value is not in the range representable by the type T. + */ +template <typename T> +std::optional<T> ToIntegral(const std::string& str) +{ + static_assert(std::is_integral<T>::value); + T result; + const auto [first_nonmatching, error_condition] = std::from_chars(str.data(), str.data() + str.size(), result); + if (first_nonmatching != str.data() + str.size() || error_condition != std::errc{}) { + return std::nullopt; + } + return {result}; +} + +/** * Convert string to signed 32-bit integer with strict parse error feedback. * @returns true if the entire string could be parsed as valid integer, * false if not the entire string could be parsed or when overflow or underflow occurred. |