diff options
Diffstat (limited to 'src/google/protobuf/util/internal/datapiece.cc')
-rw-r--r-- | src/google/protobuf/util/internal/datapiece.cc | 74 |
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>(); } |