aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/util/internal/datapiece.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/util/internal/datapiece.cc')
-rw-r--r--src/google/protobuf/util/internal/datapiece.cc74
1 files changed, 55 insertions, 19 deletions
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index ea360798..b557429f 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -35,8 +35,8 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/mathutil.h>
#include <google/protobuf/stubs/mathlimits.h>
+#include <google/protobuf/stubs/mathutil.h>
namespace google {
namespace protobuf {
@@ -57,13 +57,8 @@ inline Status InvalidArgument(StringPiece value_str) {
return Status(util::error::INVALID_ARGUMENT, value_str);
}
-// For general conversion between
-// int32, int64, uint32, uint64, double and float
-// except conversion between double and float.
template <typename To, typename From>
-StatusOr<To> NumberConvertAndCheck(From before) {
- if (::google::protobuf::internal::is_same<From, To>::value) return before;
- To after = static_cast<To>(before);
+StatusOr<To> ValidateNumberConversion(To after, From before) {
if (after == before &&
MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
return after;
@@ -76,6 +71,27 @@ StatusOr<To> NumberConvertAndCheck(From before) {
}
}
+// For general conversion between
+// int32, int64, uint32, uint64, double and float
+// except conversion between double and float.
+template <typename To, typename From>
+StatusOr<To> NumberConvertAndCheck(From before) {
+ if (::google::protobuf::internal::is_same<From, To>::value) return before;
+
+ To after = static_cast<To>(before);
+ return ValidateNumberConversion(after, before);
+}
+
+// For conversion to integer types (int32, int64, uint32, uint64) from floating
+// point types (double, float) only.
+template <typename To, typename From>
+StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
+ if (::google::protobuf::internal::is_same<From, To>::value) return before;
+
+ To after = static_cast<To>(before);
+ return ValidateNumberConversion(after, before);
+}
+
// For conversion between double and float only.
template <typename To, typename From>
StatusOr<To> FloatingPointConvertAndCheck(From before) {
@@ -96,30 +112,50 @@ StatusOr<To> FloatingPointConvertAndCheck(From before) {
} // namespace
StatusOr<int32> DataPiece::ToInt32() const {
- if (type_ == TYPE_STRING) {
- return StringToNumber<int32>(safe_strto32);
- }
+ if (type_ == TYPE_STRING) return StringToNumber<int32>(safe_strto32);
+
+ if (type_ == TYPE_DOUBLE)
+ return FloatingPointToIntConvertAndCheck<int32, double>(double_);
+
+ if (type_ == TYPE_FLOAT)
+ return FloatingPointToIntConvertAndCheck<int32, float>(float_);
+
return GenericConvert<int32>();
}
StatusOr<uint32> DataPiece::ToUint32() const {
- if (type_ == TYPE_STRING) {
- return StringToNumber<uint32>(safe_strtou32);
- }
+ if (type_ == TYPE_STRING) return StringToNumber<uint32>(safe_strtou32);
+
+ if (type_ == TYPE_DOUBLE)
+ return FloatingPointToIntConvertAndCheck<uint32, double>(double_);
+
+ if (type_ == TYPE_FLOAT)
+ return FloatingPointToIntConvertAndCheck<uint32, float>(float_);
+
return GenericConvert<uint32>();
}
StatusOr<int64> DataPiece::ToInt64() const {
- if (type_ == TYPE_STRING) {
- return StringToNumber<int64>(safe_strto64);
- }
+ if (type_ == TYPE_STRING) return StringToNumber<int64>(safe_strto64);
+
+ if (type_ == TYPE_DOUBLE)
+ return FloatingPointToIntConvertAndCheck<int64, double>(double_);
+
+ if (type_ == TYPE_FLOAT)
+ return FloatingPointToIntConvertAndCheck<int64, float>(float_);
+
return GenericConvert<int64>();
}
StatusOr<uint64> DataPiece::ToUint64() const {
- if (type_ == TYPE_STRING) {
- return StringToNumber<uint64>(safe_strtou64);
- }
+ if (type_ == TYPE_STRING) return StringToNumber<uint64>(safe_strtou64);
+
+ if (type_ == TYPE_DOUBLE)
+ return FloatingPointToIntConvertAndCheck<uint64, double>(double_);
+
+ if (type_ == TYPE_FLOAT)
+ return FloatingPointToIntConvertAndCheck<uint64, float>(float_);
+
return GenericConvert<uint64>();
}