aboutsummaryrefslogtreecommitdiff
path: root/src/util/strencodings.h
diff options
context:
space:
mode:
authorpracticalswift <practicalswift@users.noreply.github.com>2021-09-30 14:18:50 +0000
committerpracticalswift <practicalswift@users.noreply.github.com>2021-09-30 14:21:17 +0000
commit4343f114cc661cf031ec915538c11b9b030e2e15 (patch)
tree0b0cc9ec8fbea9cc65490dd2ae437478b78c3a72 /src/util/strencodings.h
parent2d8e0c0c3c0d3c4cee7bb52d1edf501f40c53463 (diff)
Replace use of locale dependent atoi(…) with locale-independent std::from_chars(…) (C++17)
test: Add test cases for LocaleIndependentAtoi fuzz: Assert legacy atoi(s) == LocaleIndependentAtoi<int>(s) fuzz: Assert legacy atoi64(s) == LocaleIndependentAtoi<int64_t>(s)
Diffstat (limited to 'src/util/strencodings.h')
-rw-r--r--src/util/strencodings.h30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 1217572c45..166352c42f 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -11,6 +11,7 @@
#include <attributes.h>
#include <span.h>
+#include <util/string.h>
#include <charconv>
#include <cstdint>
@@ -68,8 +69,33 @@ std::string EncodeBase32(Span<const unsigned char> input, bool pad = true);
std::string EncodeBase32(const std::string& str, bool pad = true);
void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut);
-int64_t atoi64(const std::string& str);
-int atoi(const std::string& str);
+
+// LocaleIndependentAtoi is provided for backwards compatibility reasons.
+//
+// New code should use the ParseInt64/ParseUInt64/ParseInt32/ParseUInt32 functions
+// which provide parse error feedback.
+//
+// The goal of LocaleIndependentAtoi is to replicate the exact defined behaviour
+// of atoi and atoi64 as they behave under the "C" locale.
+template <typename T>
+T LocaleIndependentAtoi(const std::string& str)
+{
+ static_assert(std::is_integral<T>::value);
+ T result;
+ // Emulate atoi(...) handling of white space and leading +/-.
+ std::string s = TrimString(str);
+ if (!s.empty() && s[0] == '+') {
+ if (s.length() >= 2 && s[1] == '-') {
+ return 0;
+ }
+ s = s.substr(1);
+ }
+ auto [_, error_condition] = std::from_chars(s.data(), s.data() + s.size(), result);
+ if (error_condition != std::errc{}) {
+ return 0;
+ }
+ return result;
+}
/**
* Tests if the given character is a decimal digit.