提交 1d004f96 编写于 作者: A A. Unique TensorFlower 提交者: TensorFlower Gardener

Add safe_strtou32, safe_strtou64, and safe_strtod to numbers.h.

Change: 119099796
上级 a8f0dd87
......@@ -108,11 +108,13 @@ char SafeFirstChar(StringPiece str) {
if (str.empty()) return '\0';
return str[0];
}
void SkipSpaces(StringPiece* str) {
while (isspace(SafeFirstChar(*str))) str->remove_prefix(1);
}
} // namespace
bool safe_strto64(StringPiece str, int64* value) {
// Skip leading space.
while (isspace(SafeFirstChar(str))) str.remove_prefix(1);
SkipSpaces(&str);
int64 vlimit = kint64max;
int sign = 1;
......@@ -145,9 +147,28 @@ bool safe_strto64(StringPiece str, int64* value) {
} while (isdigit(SafeFirstChar(str)));
}
// Skip trailing space.
while (isspace(SafeFirstChar(str))) str.remove_prefix(1);
SkipSpaces(&str);
if (!str.empty()) return false;
*value = result;
return true;
}
bool safe_strtou64(StringPiece str, uint64* value) {
SkipSpaces(&str);
if (!isdigit(SafeFirstChar(str))) return false;
int64 result = 0;
do {
int digit = SafeFirstChar(str) - '0';
if ((kuint64max - digit) / 10 < result) {
return false;
}
result = result * 10 + digit;
str.remove_prefix(1);
} while (isdigit(SafeFirstChar(str)));
SkipSpaces(&str);
if (!str.empty()) return false;
*value = result;
......@@ -155,8 +176,7 @@ bool safe_strto64(StringPiece str, int64* value) {
}
bool safe_strto32(StringPiece str, int32* value) {
// Skip leading space.
while (isspace(SafeFirstChar(str))) str.remove_prefix(1);
SkipSpaces(&str);
int64 vmax = kint32max;
int sign = 1;
......@@ -177,8 +197,7 @@ bool safe_strto32(StringPiece str, int32* value) {
str.remove_prefix(1);
} while (isdigit(SafeFirstChar(str)));
// Skip trailing space.
while (isspace(SafeFirstChar(str))) str.remove_prefix(1);
SkipSpaces(&str);
if (!str.empty()) return false;
......@@ -186,6 +205,26 @@ bool safe_strto32(StringPiece str, int32* value) {
return true;
}
bool safe_strtou32(StringPiece str, uint32* value) {
SkipSpaces(&str);
if (!isdigit(SafeFirstChar(str))) return false;
int64 result = 0;
do {
result = result * 10 + SafeFirstChar(str) - '0';
if (result > kuint32max) {
return false;
}
str.remove_prefix(1);
} while (isdigit(SafeFirstChar(str)));
SkipSpaces(&str);
if (!str.empty()) return false;
*value = result;
return true;
}
bool safe_strtof(const char* str, float* value) {
char* endptr;
*value = strtof(str, &endptr);
......@@ -197,6 +236,17 @@ bool safe_strtof(const char* str, float* value) {
return *str != '\0' && *endptr == '\0';
}
bool safe_strtod(const char* str, double* value) {
char* endptr;
*value = strtod(str, &endptr);
while (isspace(*endptr)) ++endptr;
// Ignore range errors from strtod/strtof.
// The values it returns on underflow and
// overflow are the right fallback in a
// robust setting.
return *str != '\0' && *endptr == '\0';
}
char* FloatToBuffer(float value, char* buffer) {
// FLT_DIG is 6 for IEEE-754 floats, which are used on almost all
// platforms these days. Just in case some system exists where FLT_DIG
......
......@@ -97,16 +97,31 @@ bool HexStringToUint64(const StringPiece& s, uint64* v);
// Return false with overflow or invalid input.
bool safe_strto32(StringPiece str, int32* value);
// Convert strings to unsigned 32bit integer values.
// Leading and trailing spaces are allowed.
// Return false with overflow or invalid input.
bool safe_strtou32(StringPiece str, uint32* value);
// Convert strings to 64bit integer values.
// Leading and trailing spaces are allowed.
// Return false with overflow or invalid input.
bool safe_strto64(StringPiece str, int64* value);
// Convert strings to unsigned 64bit integer values.
// Leading and trailing spaces are allowed.
// Return false with overflow or invalid input.
bool safe_strtou64(StringPiece str, uint64* value);
// Convert strings to floating point values.
// Leading and trailing spaces are allowed.
// Values may be rounded on over- and underflow.
bool safe_strtof(const char* str, float* value);
// Convert strings to double precision floating point values.
// Leading and trailing spaces are allowed.
// Values may be rounded on over- and underflow.
bool safe_strtod(const char* str, double* value);
// Converts from an int64 representing a number of bytes to a
// human readable string representing the same number.
// e.g. 12345678 -> "11.77MiB".
......
......@@ -119,6 +119,39 @@ TEST(safe_strto32, Int32s) {
EXPECT_EQ(false, safe_strto32(StringPiece(nullptr, 0), &result));
}
TEST(safe_strtou32, UInt32s) {
uint32 result;
EXPECT_TRUE(safe_strtou32("0", &result));
EXPECT_EQ(0, result);
EXPECT_TRUE(safe_strtou32("1", &result));
EXPECT_EQ(1, result);
EXPECT_TRUE(safe_strtou32("123", &result));
EXPECT_EQ(123, result);
EXPECT_TRUE(safe_strtou32("4294967295", &result));
EXPECT_EQ(4294967295, result);
// Invalid argument
EXPECT_FALSE(safe_strtou32(" 132as ", &result));
EXPECT_FALSE(safe_strtou32(" 132.2 ", &result));
EXPECT_FALSE(safe_strtou32(" -", &result));
EXPECT_FALSE(safe_strtou32("", &result));
EXPECT_FALSE(safe_strtou32(" ", &result));
EXPECT_FALSE(safe_strtou32("123 a", &result));
EXPECT_FALSE(safe_strtou32("123 456", &result));
// Overflow
EXPECT_FALSE(safe_strtou32("4294967296", &result));
EXPECT_FALSE(safe_strtou32("-1", &result));
// Check that the StringPiece's length is respected.
EXPECT_TRUE(safe_strtou32(StringPiece("123", 1), &result));
EXPECT_EQ(1, result);
EXPECT_TRUE(safe_strtou32(StringPiece(" 123", 3), &result));
EXPECT_EQ(12, result);
EXPECT_FALSE(safe_strtou32(StringPiece(nullptr, 0), &result));
}
TEST(safe_strto64, Int64s) {
int64 result;
......@@ -155,5 +188,68 @@ TEST(safe_strto64, Int64s) {
EXPECT_EQ(false, safe_strto64(StringPiece(nullptr, 0), &result));
}
TEST(safe_strtou64, UInt64s) {
uint64 result;
EXPECT_TRUE(safe_strtou64("0", &result));
EXPECT_EQ(0, result);
EXPECT_TRUE(safe_strtou64("1", &result));
EXPECT_EQ(1, result);
EXPECT_TRUE(safe_strtou64("123", &result));
EXPECT_EQ(123, result);
EXPECT_TRUE(safe_strtou64(" 345 ", &result));
EXPECT_EQ(345, result);
EXPECT_TRUE(safe_strtou64("18446744073709551615", &result));
EXPECT_EQ(18446744073709551615UL, result);
// Invalid argument
EXPECT_FALSE(safe_strtou64(" 132.2 ", &result));
EXPECT_FALSE(safe_strtou64(" 132.2 ", &result));
EXPECT_FALSE(safe_strtou64(" -", &result));
EXPECT_FALSE(safe_strtou64("", &result));
EXPECT_FALSE(safe_strtou64(" ", &result));
EXPECT_FALSE(safe_strtou64("123 a", &result));
EXPECT_FALSE(safe_strtou64("123 456", &result));
// Overflow
EXPECT_FALSE(safe_strtou64("18446744073709551616", &result));
EXPECT_FALSE(safe_strtou64("-1", &result));
// Check that the StringPiece's length is respected.
EXPECT_TRUE(safe_strtou64(StringPiece("123", 1), &result));
EXPECT_EQ(1, result);
EXPECT_TRUE(safe_strtou64(StringPiece(" 123", 3), &result));
EXPECT_EQ(12, result);
EXPECT_FALSE(safe_strtou64(StringPiece(nullptr, 0), &result));
}
TEST(safe_strtof, Float) {
float result = 0;
EXPECT_TRUE(safe_strtof("0.123456", &result));
EXPECT_EQ(0.123456f, result);
EXPECT_FALSE(safe_strtof("0.12345abc", &result));
// Overflow to infinity, underflow to 0.
EXPECT_TRUE(safe_strtof("1e39", &result));
EXPECT_EQ(std::numeric_limits<float>::infinity(), result);
EXPECT_TRUE(safe_strtof("1e-50", &result));
EXPECT_EQ(0, result);
}
TEST(safe_strtod, Double) {
double result = 0;
EXPECT_TRUE(safe_strtod("0.1234567890123", &result));
EXPECT_EQ(0.1234567890123, result);
EXPECT_FALSE(safe_strtod("0.1234567890123abc", &result));
// Overflow to infinity, underflow to 0.
EXPECT_TRUE(safe_strtod("1e310", &result));
EXPECT_EQ(std::numeric_limits<double>::infinity(), result);
EXPECT_TRUE(safe_strtod("1e-325", &result));
EXPECT_EQ(0, result);
}
} // namespace strings
} // namespace tensorflow
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册