Loading base/include/android-base/parsedouble.h +22 −5 Original line number Diff line number Diff line Loading @@ -24,15 +24,14 @@ namespace android { namespace base { // Parse double value in the string 's' and sets 'out' to that value if it exists. // Parse floating value in the string 's' and sets 'out' to that value if it exists. // Optionally allows the caller to define a 'min' and 'max' beyond which // otherwise valid values will be rejected. Returns boolean success. static inline bool ParseDouble(const char* s, double* out, double min = std::numeric_limits<double>::lowest(), double max = std::numeric_limits<double>::max()) { template <typename T, T (*strtox)(const char* str, char** endptr)> static inline bool ParseFloatingPoint(const char* s, T* out, T min, T max) { errno = 0; char* end; double result = strtod(s, &end); T result = strtox(s, &end); if (errno != 0 || s == end || *end != '\0') { return false; } Loading @@ -45,5 +44,23 @@ static inline bool ParseDouble(const char* s, double* out, return true; } // Parse double value in the string 's' and sets 'out' to that value if it exists. // Optionally allows the caller to define a 'min' and 'max' beyond which // otherwise valid values will be rejected. Returns boolean success. static inline bool ParseDouble(const char* s, double* out, double min = std::numeric_limits<double>::lowest(), double max = std::numeric_limits<double>::max()) { return ParseFloatingPoint<double, strtod>(s, out, min, max); } // Parse float value in the string 's' and sets 'out' to that value if it exists. // Optionally allows the caller to define a 'min' and 'max' beyond which // otherwise valid values will be rejected. Returns boolean success. static inline bool ParseFloat(const char* s, float* out, float min = std::numeric_limits<float>::lowest(), float max = std::numeric_limits<float>::max()) { return ParseFloatingPoint<float, strtof>(s, out, min, max); } } // namespace base } // namespace android base/parsedouble_test.cpp +25 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <gtest/gtest.h> TEST(parsedouble, smoke) { TEST(parsedouble, double_smoke) { double d; ASSERT_FALSE(android::base::ParseDouble("", &d)); ASSERT_FALSE(android::base::ParseDouble("x", &d)); Loading @@ -41,3 +41,27 @@ TEST(parsedouble, smoke) { ASSERT_FALSE(android::base::ParseDouble("3.0", nullptr, -1.0, 2.0)); ASSERT_TRUE(android::base::ParseDouble("1.0", nullptr, 0.0, 2.0)); } TEST(parsedouble, float_smoke) { float f; ASSERT_FALSE(android::base::ParseFloat("", &f)); ASSERT_FALSE(android::base::ParseFloat("x", &f)); ASSERT_FALSE(android::base::ParseFloat("123.4x", &f)); ASSERT_TRUE(android::base::ParseFloat("123.4", &f)); ASSERT_FLOAT_EQ(123.4, f); ASSERT_TRUE(android::base::ParseFloat("-123.4", &f)); ASSERT_FLOAT_EQ(-123.4, f); ASSERT_TRUE(android::base::ParseFloat("0", &f, 0.0)); ASSERT_FLOAT_EQ(0.0, f); ASSERT_FALSE(android::base::ParseFloat("0", &f, 1e-9)); ASSERT_FALSE(android::base::ParseFloat("3.0", &f, -1.0, 2.0)); ASSERT_TRUE(android::base::ParseFloat("1.0", &f, 0.0, 2.0)); ASSERT_FLOAT_EQ(1.0, f); ASSERT_FALSE(android::base::ParseFloat("123.4x", nullptr)); ASSERT_TRUE(android::base::ParseFloat("-123.4", nullptr)); ASSERT_FALSE(android::base::ParseFloat("3.0", nullptr, -1.0, 2.0)); ASSERT_TRUE(android::base::ParseFloat("1.0", nullptr, 0.0, 2.0)); } Loading
base/include/android-base/parsedouble.h +22 −5 Original line number Diff line number Diff line Loading @@ -24,15 +24,14 @@ namespace android { namespace base { // Parse double value in the string 's' and sets 'out' to that value if it exists. // Parse floating value in the string 's' and sets 'out' to that value if it exists. // Optionally allows the caller to define a 'min' and 'max' beyond which // otherwise valid values will be rejected. Returns boolean success. static inline bool ParseDouble(const char* s, double* out, double min = std::numeric_limits<double>::lowest(), double max = std::numeric_limits<double>::max()) { template <typename T, T (*strtox)(const char* str, char** endptr)> static inline bool ParseFloatingPoint(const char* s, T* out, T min, T max) { errno = 0; char* end; double result = strtod(s, &end); T result = strtox(s, &end); if (errno != 0 || s == end || *end != '\0') { return false; } Loading @@ -45,5 +44,23 @@ static inline bool ParseDouble(const char* s, double* out, return true; } // Parse double value in the string 's' and sets 'out' to that value if it exists. // Optionally allows the caller to define a 'min' and 'max' beyond which // otherwise valid values will be rejected. Returns boolean success. static inline bool ParseDouble(const char* s, double* out, double min = std::numeric_limits<double>::lowest(), double max = std::numeric_limits<double>::max()) { return ParseFloatingPoint<double, strtod>(s, out, min, max); } // Parse float value in the string 's' and sets 'out' to that value if it exists. // Optionally allows the caller to define a 'min' and 'max' beyond which // otherwise valid values will be rejected. Returns boolean success. static inline bool ParseFloat(const char* s, float* out, float min = std::numeric_limits<float>::lowest(), float max = std::numeric_limits<float>::max()) { return ParseFloatingPoint<float, strtof>(s, out, min, max); } } // namespace base } // namespace android
base/parsedouble_test.cpp +25 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <gtest/gtest.h> TEST(parsedouble, smoke) { TEST(parsedouble, double_smoke) { double d; ASSERT_FALSE(android::base::ParseDouble("", &d)); ASSERT_FALSE(android::base::ParseDouble("x", &d)); Loading @@ -41,3 +41,27 @@ TEST(parsedouble, smoke) { ASSERT_FALSE(android::base::ParseDouble("3.0", nullptr, -1.0, 2.0)); ASSERT_TRUE(android::base::ParseDouble("1.0", nullptr, 0.0, 2.0)); } TEST(parsedouble, float_smoke) { float f; ASSERT_FALSE(android::base::ParseFloat("", &f)); ASSERT_FALSE(android::base::ParseFloat("x", &f)); ASSERT_FALSE(android::base::ParseFloat("123.4x", &f)); ASSERT_TRUE(android::base::ParseFloat("123.4", &f)); ASSERT_FLOAT_EQ(123.4, f); ASSERT_TRUE(android::base::ParseFloat("-123.4", &f)); ASSERT_FLOAT_EQ(-123.4, f); ASSERT_TRUE(android::base::ParseFloat("0", &f, 0.0)); ASSERT_FLOAT_EQ(0.0, f); ASSERT_FALSE(android::base::ParseFloat("0", &f, 1e-9)); ASSERT_FALSE(android::base::ParseFloat("3.0", &f, -1.0, 2.0)); ASSERT_TRUE(android::base::ParseFloat("1.0", &f, 0.0, 2.0)); ASSERT_FLOAT_EQ(1.0, f); ASSERT_FALSE(android::base::ParseFloat("123.4x", nullptr)); ASSERT_TRUE(android::base::ParseFloat("-123.4", nullptr)); ASSERT_FALSE(android::base::ParseFloat("3.0", nullptr, -1.0, 2.0)); ASSERT_TRUE(android::base::ParseFloat("1.0", nullptr, 0.0, 2.0)); }