Handle empty strings in `SimpleAtof` after stripping whitespace

Add an explicit check for an empty string after `StripAsciiWhitespace` in `SimpleAtof` to avoid issues with `absl::from_chars`, which does not accept empty input.

PiperOrigin-RevId: 827589429
Change-Id: Iaf7e486d40d2c981a070aab912c7c61b72b33553
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index 01caf78..60e43e0 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -50,11 +50,15 @@
 bool SimpleAtof(absl::string_view str, float* absl_nonnull out) {
   *out = 0.0;
   str = StripAsciiWhitespace(str);
+  if (str.empty()) {
+    // absl::from_chars doesn't accept empty strings.
+    return false;
+  }
   // 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] == '+') {
+  if (str[0] == '+') {
     str.remove_prefix(1);
-    if (!str.empty() && str[0] == '-') {
+    if (str.empty() || str[0] == '-') {
       return false;
     }
   }
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 1a82087..ca13da0 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -451,6 +451,20 @@
   VerifySimpleAtoiGood<std::string::size_type>(42, 42);
 }
 
+TEST(NumbersTest, AtodEmpty) {
+  double d;
+  EXPECT_FALSE(absl::SimpleAtod("", &d));
+  // Empty string_view takes a different code path from "".
+  EXPECT_FALSE(absl::SimpleAtod({}, &d));
+}
+
+TEST(NumbersTest, AtofEmpty) {
+  float f;
+  EXPECT_FALSE(absl::SimpleAtof("", &f));
+  // Empty string_view takes a different code path from "".
+  EXPECT_FALSE(absl::SimpleAtof({}, &f));
+}
+
 TEST(NumbersTest, Atod) {
   // DBL_TRUE_MIN and FLT_TRUE_MIN were not mandated in <cfloat> before C++17.
 #if !defined(DBL_TRUE_MIN)