aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <nobody@tensorflow.org>2016-04-05 14:42:45 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2016-04-05 15:51:36 -0700
commit1d004f969867ee38c5398d68574e141ce8de86cb (patch)
treea10822e17b47992312f87043e508b967a7519569 /tensorflow
parenta8f0dd875b86e0dcefbd978441f79c51f3cc241e (diff)
Add safe_strtou32, safe_strtou64, and safe_strtod to numbers.h.
Change: 119099796
Diffstat (limited to 'tensorflow')
-rw-r--r--tensorflow/core/lib/strings/numbers.cc66
-rw-r--r--tensorflow/core/lib/strings/numbers.h15
-rw-r--r--tensorflow/core/lib/strings/numbers_test.cc96
3 files changed, 169 insertions, 8 deletions
diff --git a/tensorflow/core/lib/strings/numbers.cc b/tensorflow/core/lib/strings/numbers.cc
index 9e3a6d5458..38a4b6698b 100644
--- a/tensorflow/core/lib/strings/numbers.cc
+++ b/tensorflow/core/lib/strings/numbers.cc
@@ -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
diff --git a/tensorflow/core/lib/strings/numbers.h b/tensorflow/core/lib/strings/numbers.h
index 68ddc68ebb..69a9a78fde 100644
--- a/tensorflow/core/lib/strings/numbers.h
+++ b/tensorflow/core/lib/strings/numbers.h
@@ -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".
diff --git a/tensorflow/core/lib/strings/numbers_test.cc b/tensorflow/core/lib/strings/numbers_test.cc
index 88acd57852..52b77ac2f9 100644
--- a/tensorflow/core/lib/strings/numbers_test.cc
+++ b/tensorflow/core/lib/strings/numbers_test.cc
@@ -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