diff options
Diffstat (limited to 'src/google/protobuf/extension_set.cc')
-rw-r--r-- | src/google/protobuf/extension_set.cc | 649 |
1 files changed, 219 insertions, 430 deletions
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 274554b..6084885 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ +// http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -38,9 +38,10 @@ #include <google/protobuf/extension_set.h> #include <google/protobuf/message_lite.h> #include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/wire_format_lite_inl.h> #include <google/protobuf/repeated_field.h> -#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/map-util.h> namespace google { namespace protobuf { @@ -57,22 +58,6 @@ inline WireFormatLite::CppType cpp_type(FieldType type) { return WireFormatLite::FieldTypeToCppType(real_type(type)); } -inline bool is_packable(WireFormatLite::WireType type) { - switch (type) { - case WireFormatLite::WIRETYPE_VARINT: - case WireFormatLite::WIRETYPE_FIXED64: - case WireFormatLite::WIRETYPE_FIXED32: - return true; - case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: - case WireFormatLite::WIRETYPE_START_GROUP: - case WireFormatLite::WIRETYPE_END_GROUP: - return false; - - // Do not add a default statement. Let the compiler complain when someone - // adds a new wire type. - } -} - // Registry stuff. typedef hash_map<pair<const MessageLite*, int>, ExtensionInfo> ExtensionRegistry; @@ -86,7 +71,7 @@ void DeleteRegistry() { void InitRegistry() { registry_ = new ExtensionRegistry; - OnShutdown(&DeleteRegistry); + internal::OnShutdown(&DeleteRegistry); } // This function is only called at startup, so there is no need for thread- @@ -195,35 +180,12 @@ bool ExtensionSet::Has(int number) const { return !iter->second.is_cleared; } -int ExtensionSet::NumExtensions() const { - int result = 0; - for (map<int, Extension>::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - if (!iter->second.is_cleared) { - ++result; - } - } - return result; -} - int ExtensionSet::ExtensionSize(int number) const { map<int, Extension>::const_iterator iter = extensions_.find(number); if (iter == extensions_.end()) return false; return iter->second.GetSize(); } -FieldType ExtensionSet::ExtensionType(int number) const { - map<int, Extension>::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { - GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). "; - return 0; - } - if (iter->second.is_cleared) { - GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). "; - } - return iter->second.type; -} - void ExtensionSet::ClearExtension(int number) { map<int, Extension>::iterator iter = extensions_.find(number); if (iter == extensions_.end()) return; @@ -319,80 +281,6 @@ PRIMITIVE_ACCESSORS( BOOL, bool, Bool) #undef PRIMITIVE_ACCESSORS -const void* ExtensionSet::GetRawRepeatedField(int number, - const void* default_value) const { - map<int, Extension>::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { - return default_value; - } - // We assume that all the RepeatedField<>* pointers have the same - // size and alignment within the anonymous union in Extension. - return iter->second.repeated_int32_value; -} - -void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, - bool packed, - const FieldDescriptor* desc) { - Extension* extension; - - // We instantiate an empty Repeated{,Ptr}Field if one doesn't exist for this - // extension. - if (MaybeNewExtension(number, desc, &extension)) { - extension->is_repeated = true; - extension->type = field_type; - extension->is_packed = packed; - - switch (WireFormatLite::FieldTypeToCppType( - static_cast<WireFormatLite::FieldType>(field_type))) { - case WireFormatLite::CPPTYPE_INT32: - extension->repeated_int32_value = new RepeatedField<int32>(); - break; - case WireFormatLite::CPPTYPE_INT64: - extension->repeated_int64_value = new RepeatedField<int64>(); - break; - case WireFormatLite::CPPTYPE_UINT32: - extension->repeated_uint32_value = new RepeatedField<uint32>(); - break; - case WireFormatLite::CPPTYPE_UINT64: - extension->repeated_uint64_value = new RepeatedField<uint64>(); - break; - case WireFormatLite::CPPTYPE_DOUBLE: - extension->repeated_double_value = new RepeatedField<double>(); - break; - case WireFormatLite::CPPTYPE_FLOAT: - extension->repeated_float_value = new RepeatedField<float>(); - break; - case WireFormatLite::CPPTYPE_BOOL: - extension->repeated_bool_value = new RepeatedField<bool>(); - break; - case WireFormatLite::CPPTYPE_ENUM: - extension->repeated_enum_value = new RepeatedField<int>(); - break; - case WireFormatLite::CPPTYPE_STRING: - extension->repeated_string_value = new RepeatedPtrField< ::std::string>(); - break; - case WireFormatLite::CPPTYPE_MESSAGE: - extension->repeated_message_value = new RepeatedPtrField<MessageLite>(); - break; - } - } - - // We assume that all the RepeatedField<>* pointers have the same - // size and alignment within the anonymous union in Extension. - return extension->repeated_int32_value; -} - -// Compatible version using old call signature. Does not create extensions when -// the don't already exist; instead, just GOOGLE_CHECK-fails. -void* ExtensionSet::MutableRawRepeatedField(int number) { - map<int, Extension>::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter == extensions_.end()) << "Extension not found."; - // We assume that all the RepeatedField<>* pointers have the same - // size and alignment within the anonymous union in Extension. - return iter->second.repeated_int32_value; -} - - // ------------------------------------------------------------------- // Enums @@ -522,11 +410,7 @@ const MessageLite& ExtensionSet::GetMessage( return default_value; } else { GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - if (iter->second.is_lazy) { - return iter->second.lazymessage_value->GetMessage(default_value); - } else { - return *iter->second.message_value; - } + return *iter->second.message_value; } } @@ -543,19 +427,12 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, extension->type = type; GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = false; - extension->is_lazy = false; extension->message_value = prototype.New(); - extension->is_cleared = false; - return extension->message_value; } else { GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); - extension->is_cleared = false; - if (extension->is_lazy) { - return extension->lazymessage_value->MutableMessage(prototype); - } else { - return extension->message_value; - } } + extension->is_cleared = false; + return extension->message_value; } // Defined in extension_set_heavy.cc. @@ -563,56 +440,6 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, // const Descriptor* message_type, // MessageFactory* factory) -void ExtensionSet::SetAllocatedMessage(int number, FieldType type, - const FieldDescriptor* descriptor, - MessageLite* message) { - if (message == NULL) { - ClearExtension(number); - return; - } - Extension* extension; - if (MaybeNewExtension(number, descriptor, &extension)) { - extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); - extension->is_repeated = false; - extension->is_lazy = false; - extension->message_value = message; - } else { - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); - if (extension->is_lazy) { - extension->lazymessage_value->SetAllocatedMessage(message); - } else { - delete extension->message_value; - extension->message_value = message; - } - } - extension->is_cleared = false; -} - -MessageLite* ExtensionSet::ReleaseMessage(int number, - const MessageLite& prototype) { - map<int, Extension>::iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { - // Not present. Return NULL. - return NULL; - } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - MessageLite* ret = NULL; - if (iter->second.is_lazy) { - ret = iter->second.lazymessage_value->ReleaseMessage(prototype); - delete iter->second.lazymessage_value; - } else { - ret = iter->second.message_value; - } - extensions_.erase(number); - return ret; - } -} - -// Defined in extension_set_heavy.cc. -// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, -// MessageFactory* factory); - const MessageLite& ExtensionSet::GetRepeatedMessage( int number, int index) const { map<int, Extension>::const_iterator iter = extensions_.find(number); @@ -645,7 +472,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, // RepeatedPtrField<MessageLite> does not know how to Add() since it cannot // allocate an abstract object, so we have to be tricky. MessageLite* result = extension->repeated_message_value - ->AddFromCleared<GenericTypeHandler<MessageLite> >(); + ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >(); if (result == NULL) { result = prototype.New(); extension->repeated_message_value->AddAllocated(result); @@ -701,16 +528,6 @@ void ExtensionSet::RemoveLast(int number) { } } -MessageLite* ExtensionSet::ReleaseLast(int number) { - map<int, Extension>::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - - Extension* extension = &iter->second; - GOOGLE_DCHECK(extension->is_repeated); - GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); - return extension->repeated_message_value->ReleaseLast(); -} - void ExtensionSet::SwapElements(int number, int index1, int index2) { map<int, Extension>::iterator iter = extensions_.find(number); GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; @@ -773,11 +590,9 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { if (is_new) { // Extension did not already exist in set. extension->type = other_extension.type; - extension->is_packed = other_extension.is_packed; extension->is_repeated = true; } else { GOOGLE_DCHECK_EQ(extension->type, other_extension.type); - GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); GOOGLE_DCHECK(extension->is_repeated); } @@ -848,55 +663,12 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { *other_extension.string_value, other_extension.descriptor); break; - case WireFormatLite::CPPTYPE_MESSAGE: { - Extension* extension; - bool is_new = MaybeNewExtension(iter->first, - other_extension.descriptor, - &extension); - if (is_new) { - extension->type = other_extension.type; - extension->is_packed = other_extension.is_packed; - extension->is_repeated = false; - if (other_extension.is_lazy) { - extension->is_lazy = true; - extension->lazymessage_value = - other_extension.lazymessage_value->New(); - extension->lazymessage_value->MergeFrom( - *other_extension.lazymessage_value); - } else { - extension->is_lazy = false; - extension->message_value = - other_extension.message_value->New(); - extension->message_value->CheckTypeAndMergeFrom( - *other_extension.message_value); - } - } else { - GOOGLE_DCHECK_EQ(extension->type, other_extension.type); - GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed); - GOOGLE_DCHECK(!extension->is_repeated); - if (other_extension.is_lazy) { - if (extension->is_lazy) { - extension->lazymessage_value->MergeFrom( - *other_extension.lazymessage_value); - } else { - extension->message_value->CheckTypeAndMergeFrom( - other_extension.lazymessage_value->GetMessage( - *extension->message_value)); - } - } else { - if (extension->is_lazy) { - extension->lazymessage_value->MutableMessage( - *other_extension.message_value)->CheckTypeAndMergeFrom( - *other_extension.message_value); - } else { - extension->message_value->CheckTypeAndMergeFrom( - *other_extension.message_value); - } - } - } - extension->is_cleared = false; + case WireFormatLite::CPPTYPE_MESSAGE: + MutableMessage(iter->first, other_extension.type, + *other_extension.message_value, + other_extension.descriptor) + ->CheckTypeAndMergeFrom(*other_extension.message_value); break; - } } } } @@ -907,36 +679,6 @@ void ExtensionSet::Swap(ExtensionSet* x) { extensions_.swap(x->extensions_); } -void ExtensionSet::SwapExtension(ExtensionSet* other, - int number) { - if (this == other) return; - map<int, Extension>::iterator this_iter = extensions_.find(number); - map<int, Extension>::iterator other_iter = other->extensions_.find(number); - - if (this_iter == extensions_.end() && - other_iter == other->extensions_.end()) { - return; - } - - if (this_iter != extensions_.end() && - other_iter != other->extensions_.end()) { - std::swap(this_iter->second, other_iter->second); - return; - } - - if (this_iter == extensions_.end()) { - extensions_.insert(make_pair(number, other_iter->second)); - other->extensions_.erase(number); - return; - } - - if (other_iter == other->extensions_.end()) { - other->extensions_.insert(make_pair(number, this_iter->second)); - extensions_.erase(number); - return; - } -} - bool ExtensionSet::IsInitialized() const { // Extensions are never required. However, we need to check that all // embedded messages are initialized. @@ -952,11 +694,7 @@ bool ExtensionSet::IsInitialized() const { } } else { if (!extension.is_cleared) { - if (extension.is_lazy) { - if (!extension.lazymessage_value->IsInitialized()) return false; - } else { - if (!extension.message_value->IsInitialized()) return false; - } + if (!extension.message_value->IsInitialized()) return false; } } } @@ -965,60 +703,27 @@ bool ExtensionSet::IsInitialized() const { return true; } -bool ExtensionSet::FindExtensionInfoFromTag( - uint32 tag, ExtensionFinder* extension_finder, int* field_number, - ExtensionInfo* extension, bool* was_packed_on_wire) { - *field_number = WireFormatLite::GetTagFieldNumber(tag); - WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); - return FindExtensionInfoFromFieldNumber(wire_type, *field_number, - extension_finder, extension, - was_packed_on_wire); -} - -bool ExtensionSet::FindExtensionInfoFromFieldNumber( - int wire_type, int field_number, ExtensionFinder* extension_finder, - ExtensionInfo* extension, bool* was_packed_on_wire) { - if (!extension_finder->Find(field_number, extension)) { - return false; - } - - WireFormatLite::WireType expected_wire_type = - WireFormatLite::WireTypeForFieldType(real_type(extension->type)); - - // Check if this is a packed field. - *was_packed_on_wire = false; - if (extension->is_repeated && - wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED && - is_packable(expected_wire_type)) { - *was_packed_on_wire = true; - return true; - } - // Otherwise the wire type must match. - return expected_wire_type == wire_type; -} - bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, ExtensionFinder* extension_finder, FieldSkipper* field_skipper) { - int number; - bool was_packed_on_wire; + int number = WireFormatLite::GetTagFieldNumber(tag); + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + ExtensionInfo extension; - if (!FindExtensionInfoFromTag( - tag, extension_finder, &number, &extension, &was_packed_on_wire)) { - return field_skipper->SkipField(input, tag); + bool is_unknown; + if (!extension_finder->Find(number, &extension)) { + is_unknown = true; + } else if (extension.is_packed) { + is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); } else { - return ParseFieldWithExtensionInfo( - number, was_packed_on_wire, extension, input, field_skipper); + WireFormatLite::WireType expected_wire_type = + WireFormatLite::WireTypeForFieldType(real_type(extension.type)); + is_unknown = (wire_type != expected_wire_type); } -} -bool ExtensionSet::ParseFieldWithExtensionInfo( - int number, bool was_packed_on_wire, const ExtensionInfo& extension, - io::CodedInputStream* input, - FieldSkipper* field_skipper) { - // Explicitly not read extension.is_packed, instead check whether the field - // was encoded in packed form on the wire. - if (was_packed_on_wire) { + if (is_unknown) { + field_skipper->SkipField(input, tag); + } else if (extension.is_packed) { uint32 size; if (!input->ReadVarint32(&size)) return false; io::CodedInputStream::Limit limit = input->PushLimit(size); @@ -1032,8 +737,7 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ input, &value)) return false; \ Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - extension.is_packed, value, \ - extension.descriptor); \ + true, value, extension.descriptor); \ } \ break @@ -1059,8 +763,8 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( input, &value)) return false; if (extension.enum_validity_check.func( extension.enum_validity_check.arg, value)) { - AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, - value, extension.descriptor); + AddEnum(number, WireFormatLite::TYPE_ENUM, true, value, + extension.descriptor); } } break; @@ -1082,10 +786,9 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( if (!WireFormatLite::ReadPrimitive< \ CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ input, &value)) return false; \ - if (extension.is_repeated) { \ + if (extension.is_repeated) { \ Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - extension.is_packed, value, \ - extension.descriptor); \ + false, value, extension.descriptor); \ } else { \ Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ extension.descriptor); \ @@ -1117,7 +820,7 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( // Invalid value. Treat as unknown. field_skipper->SkipUnknownEnum(number, value); } else if (extension.is_repeated) { - AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, + AddEnum(number, WireFormatLite::TYPE_ENUM, false, value, extension.descriptor); } else { SetEnum(number, WireFormatLite::TYPE_ENUM, value, @@ -1137,8 +840,8 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( case WireFormatLite::TYPE_BYTES: { string* value = extension.is_repeated ? - AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) : - MutableString(number, WireFormatLite::TYPE_BYTES, + AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) : + MutableString(number, WireFormatLite::TYPE_STRING, extension.descriptor); if (!WireFormatLite::ReadBytes(input, value)) return false; break; @@ -1176,24 +879,125 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, return ParseField(tag, input, &finder, &skipper); } -bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, - const MessageLite* containing_type, - io::CodedOutputStream* unknown_fields) { - CodedOutputStreamFieldSkipper skipper(unknown_fields); - GeneratedExtensionFinder finder(containing_type); - return ParseField(tag, input, &finder, &skipper); -} - // Defined in extension_set_heavy.cc. // bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, // const MessageLite* containing_type, // UnknownFieldSet* unknown_fields) +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + while (true) { + uint32 tag = input->ReadTag(); + switch (tag) { + case 0: + return true; + case WireFormatLite::kMessageSetItemStartTag: + if (!ParseMessageSetItem(input, extension_finder, field_skipper)) { + return false; + } + break; + default: + if (!ParseField(tag, input, extension_finder, field_skipper)) { + return false; + } + break; + } + } +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type) { + FieldSkipper skipper; + GeneratedExtensionFinder finder(containing_type); + return ParseMessageSet(input, &finder, &skipper); +} + // Defined in extension_set_heavy.cc. // bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, // const MessageLite* containing_type, // UnknownFieldSet* unknown_fields); +bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + // TODO(kenton): It would be nice to share code between this and + // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the + // differences would be hard to factor out. + + // This method parses a group which should contain two fields: + // required int32 type_id = 2; + // required data message = 3; + + // Once we see a type_id, we'll construct a fake tag for this extension + // which is the tag it would have had under the proto2 extensions wire + // format. + uint32 fake_tag = 0; + + // If we see message data before the type_id, we'll append it to this so + // we can parse it later. This will probably never happen in practice, + // as no MessageSet encoder I know of writes the message before the type ID. + // But, it's technically valid so we should allow it. + // TODO(kenton): Use a Cord instead? Do I care? + string message_data; + + while (true) { + uint32 tag = input->ReadTag(); + if (tag == 0) return false; + + switch (tag) { + case WireFormatLite::kMessageSetTypeIdTag: { + uint32 type_id; + if (!input->ReadVarint32(&type_id)) return false; + fake_tag = WireFormatLite::MakeTag(type_id, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + if (!message_data.empty()) { + // We saw some message data before the type_id. Have to parse it + // now. + io::CodedInputStream sub_input( + reinterpret_cast<const uint8*>(message_data.data()), + message_data.size()); + if (!ParseField(fake_tag, &sub_input, + extension_finder, field_skipper)) { + return false; + } + message_data.clear(); + } + + break; + } + + case WireFormatLite::kMessageSetMessageTag: { + if (fake_tag == 0) { + // We haven't seen a type_id yet. Append this data to message_data. + string temp; + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->ReadString(&temp, length)) return false; + message_data.append(temp); + } else { + // Already saw type_id, so we can parse this directly. + if (!ParseField(fake_tag, input, + extension_finder, field_skipper)) { + return false; + } + } + + break; + } + + case WireFormatLite::kMessageSetItemEndTag: { + return true; + } + + default: { + if (!field_skipper->SkipField(input, tag)) return false; + } + } + } +} + void ExtensionSet::SerializeWithCachedSizes( int start_field_number, int end_field_number, io::CodedOutputStream* output) const { @@ -1205,6 +1009,14 @@ void ExtensionSet::SerializeWithCachedSizes( } } +void ExtensionSet::SerializeMessageSetWithCachedSizes( + io::CodedOutputStream* output) const { + map<int, Extension>::const_iterator iter; + for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { + iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); + } +} + int ExtensionSet::ByteSize() const { int total_size = 0; @@ -1216,6 +1028,17 @@ int ExtensionSet::ByteSize() const { return total_size; } +int ExtensionSet::MessageSetByteSize() const { + int total_size = 0; + + for (map<int, Extension>::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + total_size += iter->second.MessageSetItemByteSize(iter->first); + } + + return total_size; +} + // Defined in extension_set_heavy.cc. // int ExtensionSet::SpaceUsedExcludingSelf() const @@ -1259,11 +1082,7 @@ void ExtensionSet::Extension::Clear() { string_value->clear(); break; case WireFormatLite::CPPTYPE_MESSAGE: - if (is_lazy) { - lazymessage_value->Clear(); - } else { - message_value->Clear(); - } + message_value->Clear(); break; default: // No need to do anything. Get*() will return the default value @@ -1375,18 +1194,40 @@ void ExtensionSet::Extension::SerializeFieldWithCachedSizes( HANDLE_TYPE( BYTES, Bytes, *string_value); HANDLE_TYPE( ENUM, Enum, enum_value); HANDLE_TYPE( GROUP, Group, *message_value); + HANDLE_TYPE( MESSAGE, Message, *message_value); #undef HANDLE_TYPE - case WireFormatLite::TYPE_MESSAGE: - if (is_lazy) { - lazymessage_value->WriteMessage(number, output); - } else { - WireFormatLite::WriteMessage(number, *message_value, output); - } - break; } } } +void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( + int number, + io::CodedOutputStream* output) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but serialize it the normal way. + SerializeFieldWithCachedSizes(number, output); + return; + } + + if (is_cleared) return; + + // Start group. + output->WriteTag(WireFormatLite::kMessageSetItemStartTag); + + // Write type ID. + WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, + number, + output); + // Write message. + WireFormatLite::WriteMessageMaybeToArray( + WireFormatLite::kMessageSetMessageNumber, + *message_value, + output); + + // End group. + output->WriteTag(WireFormatLite::kMessageSetItemEndTag); +} + int ExtensionSet::Extension::ByteSize(int number) const { int result = 0; @@ -1500,16 +1341,8 @@ int ExtensionSet::Extension::ByteSize(int number) const { HANDLE_TYPE( BYTES, Bytes, *string_value); HANDLE_TYPE( ENUM, Enum, enum_value); HANDLE_TYPE( GROUP, Group, *message_value); + HANDLE_TYPE( MESSAGE, Message, *message_value); #undef HANDLE_TYPE - case WireFormatLite::TYPE_MESSAGE: { - if (is_lazy) { - int size = lazymessage_value->ByteSize(); - result += io::CodedOutputStream::VarintSize32(size) + size; - } else { - result += WireFormatLite::MessageSize(*message_value); - } - break; - } // Stuff with fixed size. #define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ @@ -1530,6 +1363,29 @@ int ExtensionSet::Extension::ByteSize(int number) const { return result; } +int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but compute the byte size for it the + // normal way. + return ByteSize(number); + } + + if (is_cleared) return 0; + + int our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(number); + + // message + int message_size = message_value->ByteSize(); + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + int ExtensionSet::Extension::GetSize() const { GOOGLE_DCHECK(is_repeated); switch (cpp_type(type)) { @@ -1580,11 +1436,7 @@ void ExtensionSet::Extension::Free() { delete string_value; break; case WireFormatLite::CPPTYPE_MESSAGE: - if (is_lazy) { - delete lazymessage_value; - } else { - delete message_value; - } + delete message_value; break; default: break; @@ -1595,69 +1447,6 @@ void ExtensionSet::Extension::Free() { // Defined in extension_set_heavy.cc. // int ExtensionSet::Extension::SpaceUsedExcludingSelf() const -// ================================================================== -// Default repeated field instances for iterator-compatible accessors - -const RepeatedStringTypeTraits::RepeatedFieldType* -RepeatedStringTypeTraits::default_repeated_field_ = NULL; - -const RepeatedMessageGenericTypeTraits::RepeatedFieldType* -RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL; - -#define PROTOBUF_DEFINE_DEFAULT_REPEATED(TYPE) \ - const RepeatedField<TYPE>* \ - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_##TYPE##_ = NULL; - -PROTOBUF_DEFINE_DEFAULT_REPEATED(int32) -PROTOBUF_DEFINE_DEFAULT_REPEATED(int64) -PROTOBUF_DEFINE_DEFAULT_REPEATED(uint32) -PROTOBUF_DEFINE_DEFAULT_REPEATED(uint64) -PROTOBUF_DEFINE_DEFAULT_REPEATED(double) -PROTOBUF_DEFINE_DEFAULT_REPEATED(float) -PROTOBUF_DEFINE_DEFAULT_REPEATED(bool) - -#undef PROTOBUF_DEFINE_DEFAULT_REPEATED - -struct StaticDefaultRepeatedFieldsInitializer { - StaticDefaultRepeatedFieldsInitializer() { - InitializeDefaultRepeatedFields(); - OnShutdown(&DestroyDefaultRepeatedFields); - } -} static_repeated_fields_initializer; - -void InitializeDefaultRepeatedFields() { - RepeatedStringTypeTraits::default_repeated_field_ = - new RepeatedStringTypeTraits::RepeatedFieldType; - RepeatedMessageGenericTypeTraits::default_repeated_field_ = - new RepeatedMessageGenericTypeTraits::RepeatedFieldType; - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = - new RepeatedField<int32>; - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = - new RepeatedField<int64>; - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = - new RepeatedField<uint32>; - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = - new RepeatedField<uint64>; - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = - new RepeatedField<double>; - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = - new RepeatedField<float>; - RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = - new RepeatedField<bool>; -} - -void DestroyDefaultRepeatedFields() { - delete RepeatedStringTypeTraits::default_repeated_field_; - delete RepeatedMessageGenericTypeTraits::default_repeated_field_; - delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_; - delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_; - delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_; - delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_; - delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_; - delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_; - delete RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_; -} - } // namespace internal } // namespace protobuf } // namespace google |