diff options
Diffstat (limited to 'src/google/protobuf/util/internal/protostream_objectsource.cc')
-rw-r--r-- | src/google/protobuf/util/internal/protostream_objectsource.cc | 171 |
1 files changed, 96 insertions, 75 deletions
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 0048d75b..56e6db12 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -73,19 +73,19 @@ namespace { static int kDefaultMaxRecursionDepth = 64; -// Finds a field with the given number. NULL if none found. +// Finds a field with the given number. nullptr if none found. const google::protobuf::Field* FindFieldByNumber( const google::protobuf::Type& type, int number); // Returns true if the field is packable. bool IsPackable(const google::protobuf::Field& field); -// Finds an enum value with the given number. NULL if none found. +// Finds an enum value with the given number. nullptr if none found. const google::protobuf::EnumValue* FindEnumValueByNumber( const google::protobuf::Enum& tech_enum, int number); // Utility function to format nanos. -const string FormatNanos(uint32 nanos); +const string FormatNanos(uint32 nanos, bool with_trailing_zeros); StatusOr<string> MapKeyDefaultValueAsString( const google::protobuf::Field& field) { @@ -120,10 +120,14 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( own_typeinfo_(true), type_(type), use_lower_camel_for_enums_(false), + use_ints_for_enums_(false), + preserve_proto_field_names_(false), recursion_depth_(0), max_recursion_depth_(kDefaultMaxRecursionDepth), - render_unknown_fields_(false) { - GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; + render_unknown_fields_(false), + render_unknown_enum_values_(true), + add_trailing_zeros_for_timestamp_and_duration_(false) { + GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr."; } ProtoStreamObjectSource::ProtoStreamObjectSource( @@ -134,10 +138,14 @@ ProtoStreamObjectSource::ProtoStreamObjectSource( own_typeinfo_(false), type_(type), use_lower_camel_for_enums_(false), + use_ints_for_enums_(false), + preserve_proto_field_names_(false), recursion_depth_(0), max_recursion_depth_(kDefaultMaxRecursionDepth), - render_unknown_fields_(false) { - GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; + render_unknown_fields_(false), + render_unknown_enum_values_(true), + add_trailing_zeros_for_timestamp_and_duration_(false) { + GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr."; } ProtoStreamObjectSource::~ProtoStreamObjectSource() { @@ -157,7 +165,7 @@ const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3); // Verify if the field corresponds to the wire type in tag. // If there is any discrepancy, mark the field as not found. - if (field != NULL) { + if (field != nullptr) { WireFormatLite::WireType expected_type = WireFormatLite::WireTypeForFieldType( static_cast<WireFormatLite::FieldType>(field->kind())); @@ -165,7 +173,7 @@ const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( if (actual_type != expected_type && (!IsPackable(*field) || actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { - field = NULL; + field = nullptr; } } return field; @@ -178,11 +186,11 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, ObjectWriter* ow) const { const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); - if (type_renderer != NULL) { + if (type_renderer != nullptr) { return (*type_renderer)(this, type, name, ow); } - const google::protobuf::Field* field = NULL; + const google::protobuf::Field* field = nullptr; string field_name; // last_tag set to dummy value that is different from tag. uint32 tag = stream_->ReadTag(), last_tag = tag + 1; @@ -195,15 +203,19 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, if (tag != last_tag) { // Update field only if tag is changed. last_tag = tag; field = FindAndVerifyField(type, tag); - if (field != NULL) { - field_name = field->json_name(); + if (field != nullptr) { + if (preserve_proto_field_names_) { + field_name = field->name(); + } else { + field_name = field->json_name(); + } } } - if (field == NULL) { + if (field == nullptr) { // If we didn't find a field, skip this unknown tag. // TODO(wpoon): Check return boolean value. WireFormat::SkipField(stream_, tag, - render_unknown_fields_ ? &unknown_fields : NULL); + render_unknown_fields_ ? &unknown_fields : nullptr); tag = stream_->ReadTag(); continue; } @@ -230,7 +242,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, if (include_start_and_end) { ow->EndObject(); } - return Status::OK; + return util::Status(); } StatusOr<uint32> ProtoStreamObjectSource::RenderList( @@ -270,8 +282,8 @@ StatusOr<uint32> ProtoStreamObjectSource::RenderMap( for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { const google::protobuf::Field* field = FindAndVerifyField(*field_type, tag); - if (field == NULL) { - WireFormat::SkipField(stream_, tag, NULL); + if (field == nullptr) { + WireFormat::SkipField(stream_, tag, nullptr); continue; } // Map field numbers are key = 1 and value = 2 @@ -282,7 +294,7 @@ StatusOr<uint32> ProtoStreamObjectSource::RenderMap( // An absent map key is treated as the default. const google::protobuf::Field* key_field = FindFieldByNumber(*field_type, 1); - if (key_field == NULL) { + if (key_field == nullptr) { // The Type info for this map entry is incorrect. It should always // have a field named "key" and with field number 1. return Status(util::error::INTERNAL, "Invalid map entry."); @@ -310,13 +322,13 @@ Status ProtoStreamObjectSource::RenderPacked( RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); } stream_->PopLimit(old_limit); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderTimestamp( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { - pair<int64, int32> p = os->ReadSecondsAndNanos(type); + std::pair<int64, int32> p = os->ReadSecondsAndNanos(type); int64 seconds = p.first; int32 nanos = p.second; if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) { @@ -334,13 +346,13 @@ Status ProtoStreamObjectSource::RenderTimestamp( ow->RenderString(field_name, ::google::protobuf::internal::FormatTime(seconds, nanos)); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderDuration( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { - pair<int64, int32> p = os->ReadSecondsAndNanos(type); + std::pair<int64, int32> p = os->ReadSecondsAndNanos(type); int64 seconds = p.first; int32 nanos = p.second; if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) { @@ -370,10 +382,12 @@ Status ProtoStreamObjectSource::RenderDuration( sign = "-"; nanos = -nanos; } - string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds, - FormatNanos(nanos).c_str()); + string formatted_duration = StringPrintf( + "%s%lld%ss", sign.c_str(), seconds, + FormatNanos(nanos, os->add_trailing_zeros_for_timestamp_and_duration_) + .c_str()); ow->RenderString(field_name, formatted_duration); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, @@ -387,7 +401,7 @@ Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderDouble(field_name, bit_cast<double>(buffer64)); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, @@ -401,7 +415,7 @@ Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderFloat(field_name, bit_cast<float>(buffer32)); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, @@ -415,7 +429,7 @@ Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderInt64(field_name, bit_cast<int64>(buffer64)); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, @@ -429,7 +443,7 @@ Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderUint64(field_name, bit_cast<uint64>(buffer64)); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, @@ -443,7 +457,7 @@ Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderInt32(field_name, bit_cast<int32>(buffer32)); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, @@ -457,7 +471,7 @@ Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderUint32(field_name, bit_cast<uint32>(buffer32)); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os, @@ -472,7 +486,7 @@ Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderBool(field_name, buffer64 != 0); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os, @@ -488,7 +502,7 @@ Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderString(field_name, str); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os, @@ -504,14 +518,14 @@ Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os, os->stream_->ReadTag(); } ow->RenderBytes(field_name, str); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { - const google::protobuf::Field* field = NULL; + const google::protobuf::Field* field = nullptr; uint32 tag = os->stream_->ReadTag(); ow->StartObject(field_name); while (tag != 0) { @@ -523,23 +537,23 @@ Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os, } } ow->EndObject(); - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderStructValue( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { - const google::protobuf::Field* field = NULL; + const google::protobuf::Field* field = nullptr; for (uint32 tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) { field = os->FindAndVerifyField(type, tag); - if (field == NULL) { - WireFormat::SkipField(os->stream_, tag, NULL); + if (field == nullptr) { + WireFormat::SkipField(os->stream_, tag, nullptr); continue; } RETURN_IF_ERROR(os->RenderField(field, field_name, ow)); } - return Status::OK; + return util::Status(); } // TODO(skarvaje): Avoid code duplication of for loops and SkipField logic. @@ -552,19 +566,19 @@ Status ProtoStreamObjectSource::RenderStructListValue( if (tag == 0) { ow->StartList(field_name); ow->EndList(); - return Status::OK; + return util::Status(); } while (tag != 0) { const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); - if (field == NULL) { - WireFormat::SkipField(os->stream_, tag, NULL); + if (field == nullptr) { + WireFormat::SkipField(os->stream_, tag, nullptr); tag = os->stream_->ReadTag(); continue; } ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow)); } - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, @@ -579,8 +593,8 @@ Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, // First read out the type_url and value from the proto stream for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) { const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); - if (field == NULL) { - WireFormat::SkipField(os->stream_, tag, NULL); + if (field == nullptr) { + WireFormat::SkipField(os->stream_, tag, nullptr); continue; } // 'type_url' has field number of 1 and 'value' has field number 2 @@ -606,7 +620,7 @@ Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, ow->RenderString("@type", type_url); } ow->EndObject(); - return util::Status::OK; + return util::Status(); } // If there is a value but no type, we cannot render it, so report an error. @@ -653,7 +667,7 @@ Status ProtoStreamObjectSource::RenderFieldMask( tag = os->stream_->ReadTag()) { if (paths_field_tag == 0) { const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); - if (field != NULL && field->number() == 1 && + if (field != nullptr && field->number() == 1 && field->name() == "paths") { paths_field_tag = tag; } @@ -671,7 +685,7 @@ Status ProtoStreamObjectSource::RenderFieldMask( combined.append(ConvertFieldMaskPath(str, &ToCamelCase)); } ow->RenderString(field_name, combined); - return Status::OK; + return util::Status(); } @@ -740,7 +754,7 @@ Status ProtoStreamObjectSource::RenderField( // Get the nested message type for this field. const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(field->type_url()); - if (type == NULL) { + if (type == nullptr) { return Status(util::error::INTERNAL, StrCat("Invalid configuration. Could not find the type: ", field->type_url())); @@ -749,7 +763,7 @@ Status ProtoStreamObjectSource::RenderField( // Short-circuit any special type rendering to save call-stack space. const TypeRenderer* type_renderer = FindTypeRenderer(type->name()); - bool use_type_renderer = type_renderer != NULL; + bool use_type_renderer = type_renderer != nullptr; if (use_type_renderer) { RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow)); @@ -767,7 +781,7 @@ Status ProtoStreamObjectSource::RenderField( // Render all other non-message types. return RenderNonMessageField(field, field_name, ow); } - return Status::OK; + return util::Status(); } Status ProtoStreamObjectSource::RenderNonMessageField( @@ -857,18 +871,25 @@ Status ProtoStreamObjectSource::RenderNonMessageField( // up. const google::protobuf::Enum* en = typeinfo_->GetEnumByTypeUrl(field->type_url()); - // Lookup the name of the enum, and render that. Skips unknown enums. - if (en != NULL) { + // Lookup the name of the enum, and render that. Unknown enum values + // are printed as integers. + if (en != nullptr) { const google::protobuf::EnumValue* enum_value = FindEnumValueByNumber(*en, buffer32); - if (enum_value != NULL) { - if (use_lower_camel_for_enums_) - ow->RenderString(field_name, ToCamelCase(enum_value->name())); - else + if (enum_value != nullptr) { + if (use_ints_for_enums_) { + ow->RenderInt32(field_name, buffer32); + } else if (use_lower_camel_for_enums_) { + ow->RenderString(field_name, + EnumValueNameToLowerCamelCase(enum_value->name())); + } else { ow->RenderString(field_name, enum_value->name()); + } + } else if (render_unknown_enum_values_) { + ow->RenderInt32(field_name, buffer32); } - } else { - GOOGLE_LOG(INFO) << "Unknown enum skipped: " << field->type_url(); + } else if (render_unknown_enum_values_) { + ow->RenderInt32(field_name, buffer32); } break; } @@ -887,7 +908,7 @@ Status ProtoStreamObjectSource::RenderNonMessageField( default: break; } - return Status::OK; + return util::Status(); } // TODO(skarvaje): Fix this to avoid code duplication. @@ -982,10 +1003,10 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString( const google::protobuf::Enum* en = typeinfo_->GetEnumByTypeUrl(field.type_url()); // Lookup the name of the enum, and render that. Skips unknown enums. - if (en != NULL) { + if (en != nullptr) { const google::protobuf::EnumValue* enum_value = FindEnumValueByNumber(*en, buffer32); - if (enum_value != NULL) { + if (enum_value != nullptr) { result = enum_value->name(); } } @@ -1015,12 +1036,8 @@ bool ProtoStreamObjectSource::IsMap( const google::protobuf::Field& field) const { const google::protobuf::Type* field_type = typeinfo_->GetTypeByTypeUrl(field.type_url()); - - // TODO(xiaofeng): Unify option names. return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && - (GetBoolOptionOrDefault(field_type->options(), - "google.protobuf.MessageOptions.map_entry", false) || - GetBoolOptionOrDefault(field_type->options(), "map_entry", false)); + google::protobuf::util::converter::IsMap(field, *field_type); } std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( @@ -1033,8 +1050,8 @@ std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos( for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { const google::protobuf::Field* field = FindAndVerifyField(type, tag); - if (field == NULL) { - WireFormat::SkipField(stream_, tag, NULL); + if (field == nullptr) { + WireFormat::SkipField(stream_, tag, nullptr); continue; } // 'seconds' has field number of 1 and 'nanos' has field number 2 @@ -1060,7 +1077,7 @@ Status ProtoStreamObjectSource::IncrementRecursionDepth( StrCat("Message too deep. Max recursion depth reached for type '", type_name, "', field '", field_name, "'")); } - return Status::OK; + return util::Status(); } namespace { @@ -1072,7 +1089,7 @@ const google::protobuf::Field* FindFieldByNumber( return &type.fields(i); } } - return NULL; + return nullptr; } // TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable() @@ -1093,12 +1110,16 @@ const google::protobuf::EnumValue* FindEnumValueByNumber( return &ev; } } - return NULL; + return nullptr; } // TODO(skarvaje): Look into optimizing this by not doing computation on // double. -const string FormatNanos(uint32 nanos) { +const string FormatNanos(uint32 nanos, bool with_trailing_zeros) { + if (nanos == 0) { + return with_trailing_zeros ? ".000" : ""; + } + const char* format = (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f"; string formatted = |