From 4747db876154ddd828c03d9eda10ecf8b25d8dc8 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sat, 18 Sep 2021 04:30:30 +0000 Subject: =?UTF-8?q?util:=20Introduce=20ToIntegral(const=20std::string&)?= =?UTF-8?q?=20for=20locale=20independent=20parsing=20using=20std::from=5Fc?= =?UTF-8?q?hars(=E2=80=A6)=20(C++17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit util: Avoid locale dependent functions strtol/strtoll/strtoul/strtoull in ParseInt32/ParseInt64/ParseUInt32/ParseUInt64 fuzz: Assert equivalence between new and old Parse{Int,Uint}{8,32,64} functions test: Add unit tests for ToIntegral(const std::string&) --- src/util/strencodings.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/util/strencodings.h') 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 #include +#include #include #include +#include #include #include @@ -94,6 +96,24 @@ constexpr inline bool IsSpace(char c) noexcept { return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; } +/** + * 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 +std::optional ToIntegral(const std::string& str) +{ + static_assert(std::is_integral::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, -- cgit v1.2.3