| Index: third_party/protobuf/src/google/protobuf/util/internal/datapiece.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/util/internal/datapiece.cc b/third_party/protobuf/src/google/protobuf/util/internal/datapiece.cc
|
| index 72c0aca6090f6a5f288fabec1c06be4717911d48..213c2c40c0aadd6861588faa9fc4deaacab34ff1 100644
|
| --- a/third_party/protobuf/src/google/protobuf/util/internal/datapiece.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/util/internal/datapiece.cc
|
| @@ -94,19 +94,24 @@ StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
|
| }
|
|
|
| // For conversion between double and float only.
|
| -template <typename To, typename From>
|
| -StatusOr<To> FloatingPointConvertAndCheck(From before) {
|
| - if (MathLimits<From>::IsNaN(before)) {
|
| - return std::numeric_limits<To>::quiet_NaN();
|
| - }
|
| +StatusOr<double> FloatToDouble(float before) {
|
| + // Casting float to double should just work as double has more precision
|
| + // than float.
|
| + return static_cast<double>(before);
|
| +}
|
|
|
| - To after = static_cast<To>(before);
|
| - if (MathUtil::AlmostEquals<To>(after, before)) {
|
| - return after;
|
| +StatusOr<float> DoubleToFloat(double before) {
|
| + if (MathLimits<double>::IsNaN(before)) {
|
| + return std::numeric_limits<float>::quiet_NaN();
|
| + } else if (!MathLimits<double>::IsFinite(before)) {
|
| + // Converting a double +inf/-inf to float should just work.
|
| + return static_cast<float>(before);
|
| + } else if (before > std::numeric_limits<float>::max() ||
|
| + before < -std::numeric_limits<float>::max()) {
|
| + // Double value outside of the range of float.
|
| + return InvalidArgument(DoubleAsString(before));
|
| } else {
|
| - return InvalidArgument(::google::protobuf::internal::is_same<From, double>::value
|
| - ? DoubleAsString(before)
|
| - : FloatAsString(before));
|
| + return static_cast<float>(before);
|
| }
|
| }
|
|
|
| @@ -162,20 +167,27 @@ StatusOr<uint64> DataPiece::ToUint64() const {
|
|
|
| StatusOr<double> DataPiece::ToDouble() const {
|
| if (type_ == TYPE_FLOAT) {
|
| - return FloatingPointConvertAndCheck<double, float>(float_);
|
| + return FloatToDouble(float_);
|
| }
|
| if (type_ == TYPE_STRING) {
|
| if (str_ == "Infinity") return std::numeric_limits<double>::infinity();
|
| if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
|
| if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
|
| - return StringToNumber<double>(safe_strtod);
|
| + StatusOr<double> value = StringToNumber<double>(safe_strtod);
|
| + if (value.ok() && !MathLimits<double>::IsFinite(value.ValueOrDie())) {
|
| + // safe_strtod converts out-of-range values to +inf/-inf, but we want
|
| + // to report them as errors.
|
| + return InvalidArgument(StrCat("\"", str_, "\""));
|
| + } else {
|
| + return value;
|
| + }
|
| }
|
| return GenericConvert<double>();
|
| }
|
|
|
| StatusOr<float> DataPiece::ToFloat() const {
|
| if (type_ == TYPE_DOUBLE) {
|
| - return FloatingPointConvertAndCheck<float, double>(double_);
|
| + return DoubleToFloat(double_);
|
| }
|
| if (type_ == TYPE_STRING) {
|
| if (str_ == "Infinity") return std::numeric_limits<float>::infinity();
|
| @@ -259,7 +271,8 @@ StatusOr<string> DataPiece::ToBytes() const {
|
| }
|
| }
|
|
|
| -StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type) const {
|
| +StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
|
| + bool use_lower_camel_for_enums) const {
|
| if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE;
|
|
|
| if (type_ == TYPE_STRING) {
|
| @@ -268,20 +281,34 @@ StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type) const {
|
| const google::protobuf::EnumValue* value =
|
| FindEnumValueByNameOrNull(enum_type, enum_name);
|
| if (value != NULL) return value->number();
|
| +
|
| + // Check if int version of enum is sent as string.
|
| + StatusOr<int32> int_value = ToInt32();
|
| + if (int_value.ok()) {
|
| + if (const google::protobuf::EnumValue* enum_value =
|
| + FindEnumValueByNumberOrNull(enum_type, int_value.ValueOrDie())) {
|
| + return enum_value->number();
|
| + }
|
| + }
|
| +
|
| // Next try a normalized name.
|
| for (string::iterator it = enum_name.begin(); it != enum_name.end(); ++it) {
|
| *it = *it == '-' ? '_' : ascii_toupper(*it);
|
| }
|
| value = FindEnumValueByNameOrNull(enum_type, enum_name);
|
| if (value != NULL) return value->number();
|
| - } else {
|
| - StatusOr<int32> value = ToInt32();
|
| - if (value.ok()) {
|
| - if (const google::protobuf::EnumValue* enum_value =
|
| - FindEnumValueByNumberOrNull(enum_type, value.ValueOrDie())) {
|
| - return enum_value->number();
|
| - }
|
| +
|
| + // If use_lower_camel_for_enums is true try with enum name without
|
| + // underscore. This will also accept camel case names as the enum_name has
|
| + // been normalized before.
|
| + if (use_lower_camel_for_enums) {
|
| + value = FindEnumValueByNameWithoutUnderscoreOrNull(enum_type, enum_name);
|
| + if (value != NULL) return value->number();
|
| }
|
| + } else {
|
| + // We don't need to check whether the value is actually declared in the
|
| + // enum because we preserve unknown enum values as well.
|
| + return ToInt32();
|
| }
|
| return InvalidArgument(
|
| ValueAsStringOrDefault("Cannot find enum with given value."));
|
| @@ -329,9 +356,8 @@ bool DataPiece::DecodeBase64(StringPiece src, string* dest) const {
|
| // WebSafeBase64Escape does no padding by default.
|
| WebSafeBase64Escape(*dest, &encoded);
|
| // Remove trailing padding '=' characters before comparison.
|
| - StringPiece src_no_padding(src, 0, src.ends_with("=")
|
| - ? src.find_last_not_of('=') + 1
|
| - : src.length());
|
| + StringPiece src_no_padding = StringPiece(src).substr(
|
| + 0, src.ends_with("=") ? src.find_last_not_of('=') + 1 : src.length());
|
| return encoded == src_no_padding;
|
| }
|
| return true;
|
| @@ -343,9 +369,8 @@ bool DataPiece::DecodeBase64(StringPiece src, string* dest) const {
|
| Base64Escape(
|
| reinterpret_cast<const unsigned char*>(dest->data()), dest->length(),
|
| &encoded, false);
|
| - StringPiece src_no_padding(src, 0, src.ends_with("=")
|
| - ? src.find_last_not_of('=') + 1
|
| - : src.length());
|
| + StringPiece src_no_padding = StringPiece(src).substr(
|
| + 0, src.ends_with("=") ? src.find_last_not_of('=') + 1 : src.length());
|
| return encoded == src_no_padding;
|
| }
|
| return true;
|
| @@ -354,6 +379,27 @@ bool DataPiece::DecodeBase64(StringPiece src, string* dest) const {
|
| return false;
|
| }
|
|
|
| +void DataPiece::InternalCopy(const DataPiece& other) {
|
| + type_ = other.type_;
|
| + use_strict_base64_decoding_ = other.use_strict_base64_decoding_;
|
| + switch (type_) {
|
| + case TYPE_INT32:
|
| + case TYPE_INT64:
|
| + case TYPE_UINT32:
|
| + case TYPE_UINT64:
|
| + case TYPE_DOUBLE:
|
| + case TYPE_FLOAT:
|
| + case TYPE_BOOL:
|
| + case TYPE_ENUM:
|
| + case TYPE_NULL:
|
| + case TYPE_BYTES:
|
| + case TYPE_STRING: {
|
| + str_ = other.str_;
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace converter
|
| } // namespace util
|
| } // namespace protobuf
|
|
|