summaryrefslogtreecommitdiff
path: root/absl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings')
-rw-r--r--absl/strings/numbers.cc10
-rw-r--r--absl/strings/numbers_test.cc22
2 files changed, 32 insertions, 0 deletions
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index e6bf44ce..966d94bd 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -46,8 +46,13 @@ ABSL_NAMESPACE_BEGIN
bool SimpleAtof(absl::string_view str, float* out) {
*out = 0.0;
str = StripAsciiWhitespace(str);
+ // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one
+ // is present, skip it, while avoiding accepting "+-0" as valid.
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
+ if (!str.empty() && str[0] == '-') {
+ return false;
+ }
}
auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
if (result.ec == std::errc::invalid_argument) {
@@ -72,8 +77,13 @@ bool SimpleAtof(absl::string_view str, float* out) {
bool SimpleAtod(absl::string_view str, double* out) {
*out = 0.0;
str = StripAsciiWhitespace(str);
+ // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one
+ // is present, skip it, while avoiding accepting "+-0" as valid.
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
+ if (!str.empty() && str[0] == '-') {
+ return false;
+ }
}
auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
if (result.ec == std::errc::invalid_argument) {
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 27616bf8..f3103106 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -392,6 +392,28 @@ TEST(NumbersTest, Atod) {
EXPECT_TRUE(std::isnan(d));
}
+TEST(NumbersTest, Prefixes) {
+ double d;
+ EXPECT_FALSE(absl::SimpleAtod("++1", &d));
+ EXPECT_FALSE(absl::SimpleAtod("+-1", &d));
+ EXPECT_FALSE(absl::SimpleAtod("-+1", &d));
+ EXPECT_FALSE(absl::SimpleAtod("--1", &d));
+ EXPECT_TRUE(absl::SimpleAtod("-1", &d));
+ EXPECT_EQ(d, -1.);
+ EXPECT_TRUE(absl::SimpleAtod("+1", &d));
+ EXPECT_EQ(d, +1.);
+
+ float f;
+ EXPECT_FALSE(absl::SimpleAtof("++1", &f));
+ EXPECT_FALSE(absl::SimpleAtof("+-1", &f));
+ EXPECT_FALSE(absl::SimpleAtof("-+1", &f));
+ EXPECT_FALSE(absl::SimpleAtof("--1", &f));
+ EXPECT_TRUE(absl::SimpleAtof("-1", &f));
+ EXPECT_EQ(f, -1.f);
+ EXPECT_TRUE(absl::SimpleAtof("+1", &f));
+ EXPECT_EQ(f, +1.f);
+}
+
TEST(NumbersTest, Atoenum) {
enum E01 {
E01_zero = 0,