diff options
Diffstat (limited to 'src/google/protobuf/extension_set_heavy.cc')
-rw-r--r-- | src/google/protobuf/extension_set_heavy.cc | 272 |
1 files changed, 167 insertions, 105 deletions
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 82e3e099..a3c84167 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -35,11 +35,15 @@ // Contains methods defined in extension_set.h which cannot be part of the // lite library because they use descriptors or reflection. +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl_lite.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/extension_set.h> #include <google/protobuf/message.h> #include <google/protobuf/repeated_field.h> +#include <google/protobuf/unknown_field_set.h> #include <google/protobuf/wire_format.h> #include <google/protobuf/wire_format_lite_inl.h> @@ -92,16 +96,14 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder { }; void ExtensionSet::AppendToList( - const Descriptor* containing_type, - const DescriptorPool* pool, + const Descriptor* containing_type, const DescriptorPool* pool, std::vector<const FieldDescriptor*>* output) const { - for (map<int, Extension>::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { + ForEach([containing_type, pool, &output](int number, const Extension& ext) { bool has = false; - if (iter->second.is_repeated) { - has = iter->second.GetSize() > 0; + if (ext.is_repeated) { + has = ext.GetSize() > 0; } else { - has = !iter->second.is_cleared; + has = !ext.is_cleared; } if (has) { @@ -110,14 +112,13 @@ void ExtensionSet::AppendToList( // initialized, so they might not even be constructed until // AppendToList() is called. - if (iter->second.descriptor == NULL) { - output->push_back(pool->FindExtensionByNumber( - containing_type, iter->first)); + if (ext.descriptor == NULL) { + output->push_back(pool->FindExtensionByNumber(containing_type, number)); } else { - output->push_back(iter->second.descriptor); + output->push_back(ext.descriptor); } } - } + }); } inline FieldDescriptor::Type real_type(FieldType type) { @@ -144,17 +145,17 @@ inline WireFormatLite::FieldType field_type(FieldType type) { const MessageLite& ExtensionSet::GetMessage(int number, const Descriptor* message_type, MessageFactory* factory) const { - map<int, Extension>::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end() || iter->second.is_cleared) { + const Extension* extension = FindOrNull(number); + if (extension == NULL || extension->is_cleared) { // Not present. Return the default value. return *factory->GetPrototype(message_type); } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - if (iter->second.is_lazy) { - return iter->second.lazymessage_value->GetMessage( + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + if (extension->is_lazy) { + return extension->lazymessage_value->GetMessage( *factory->GetPrototype(message_type)); } else { - return *iter->second.message_value; + return *extension->message_value; } } } @@ -187,28 +188,51 @@ MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor, MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, MessageFactory* factory) { - map<int, Extension>::iterator iter = extensions_.find(descriptor->number()); - if (iter == extensions_.end()) { + Extension* extension = FindOrNull(descriptor->number()); + if (extension == NULL) { // Not present. Return NULL. return NULL; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); MessageLite* ret = NULL; - if (iter->second.is_lazy) { - ret = iter->second.lazymessage_value->ReleaseMessage( + if (extension->is_lazy) { + ret = extension->lazymessage_value->ReleaseMessage( *factory->GetPrototype(descriptor->message_type())); if (arena_ == NULL) { - delete iter->second.lazymessage_value; + delete extension->lazymessage_value; } } else { if (arena_ != NULL) { - ret = (iter->second.message_value)->New(); - ret->CheckTypeAndMergeFrom(*(iter->second.message_value)); + ret = extension->message_value->New(); + ret->CheckTypeAndMergeFrom(*extension->message_value); } else { - ret = iter->second.message_value; + ret = extension->message_value; + } + } + Erase(descriptor->number()); + return ret; + } +} + +MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( + const FieldDescriptor* descriptor, MessageFactory* factory) { + Extension* extension = FindOrNull(descriptor->number()); + if (extension == NULL) { + // Not present. Return NULL. + return NULL; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + MessageLite* ret = NULL; + if (extension->is_lazy) { + ret = extension->lazymessage_value->UnsafeArenaReleaseMessage( + *factory->GetPrototype(descriptor->message_type())); + if (arena_ == NULL) { + delete extension->lazymessage_value; } + } else { + ret = extension->message_value; } - extensions_.erase(descriptor->number()); + Erase(descriptor->number()); return ret; } } @@ -233,8 +257,10 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, // RepeatedPtrField<Message> 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> >(); + MessageLite* result = + reinterpret_cast<::google::protobuf::internal::RepeatedPtrFieldBase*>( + extension->repeated_message_value) + ->AddFromCleared<GenericTypeHandler<MessageLite> >(); if (result == NULL) { const MessageLite* prototype; if (extension->repeated_message_value->size() == 0) { @@ -317,31 +343,31 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, } int ExtensionSet::SpaceUsedExcludingSelf() const { - int total_size = - extensions_.size() * sizeof(map<int, Extension>::value_type); - for (map<int, Extension>::const_iterator iter = extensions_.begin(), - end = extensions_.end(); - iter != end; - ++iter) { - total_size += iter->second.SpaceUsedExcludingSelf(); - } + return internal::FromIntSize(SpaceUsedExcludingSelfLong()); +} + +size_t ExtensionSet::SpaceUsedExcludingSelfLong() const { + size_t total_size = Size() * sizeof(KeyValue); + ForEach([&total_size](int /* number */, const Extension& ext) { + total_size += ext.SpaceUsedExcludingSelfLong(); + }); return total_size; } -inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf( +inline size_t ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelfLong( RepeatedPtrFieldBase* field) { - return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >(); + return field->SpaceUsedExcludingSelfLong<GenericTypeHandler<Message> >(); } -int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { - int total_size = 0; +size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const { + size_t total_size = 0; if (is_repeated) { switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ - total_size += sizeof(*repeated_##LOWERCASE##_value) + \ - repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\ - break +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + total_size += sizeof(*repeated_##LOWERCASE##_value) + \ + repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \ + break HANDLE_TYPE( INT32, int32); HANDLE_TYPE( INT64, int64); @@ -356,24 +382,27 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { case FieldDescriptor::CPPTYPE_MESSAGE: // repeated_message_value is actually a RepeatedPtrField<MessageLite>, - // but MessageLite has no SpaceUsed(), so we must directly call - // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type - // handler. - total_size += sizeof(*repeated_message_value) + - RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value); + // but MessageLite has no SpaceUsedLong(), so we must directly call + // RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different + // type handler. + total_size += + sizeof(*repeated_message_value) + + RepeatedMessage_SpaceUsedExcludingSelfLong( + reinterpret_cast<::google::protobuf::internal::RepeatedPtrFieldBase*>( + repeated_message_value)); break; } } else { switch (cpp_type(type)) { case FieldDescriptor::CPPTYPE_STRING: total_size += sizeof(*string_value) + - StringSpaceUsedExcludingSelf(*string_value); + StringSpaceUsedExcludingSelfLong(*string_value); break; case FieldDescriptor::CPPTYPE_MESSAGE: if (is_lazy) { - total_size += lazymessage_value->SpaceUsed(); + total_size += lazymessage_value->SpaceUsedLong(); } else { - total_size += down_cast<Message*>(message_value)->SpaceUsed(); + total_size += down_cast<Message*>(message_value)->SpaceUsedLong(); } break; default: @@ -386,31 +415,55 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { // The Serialize*ToArray methods are only needed in the heavy library, as // the lite library only generates SerializeWithCachedSizes. -uint8* ExtensionSet::SerializeWithCachedSizesToArray( - int start_field_number, int end_field_number, - uint8* target) const { - map<int, Extension>::const_iterator iter; - for (iter = extensions_.lower_bound(start_field_number); - iter != extensions_.end() && iter->first < end_field_number; - ++iter) { - target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first, - target); - } - return target; +uint8* ExtensionSet::SerializeWithCachedSizesToArray(int start_field_number, + int end_field_number, + uint8* target) const { + return InternalSerializeWithCachedSizesToArray( + start_field_number, end_field_number, + google::protobuf::io::CodedOutputStream::IsDefaultSerializationDeterministic(), + target); } uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray( uint8* target) const { - map<int, Extension>::const_iterator iter; - for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { - target = iter->second.SerializeMessageSetItemWithCachedSizesToArray( - iter->first, target); + return InternalSerializeMessageSetWithCachedSizesToArray( + google::protobuf::io::CodedOutputStream::IsDefaultSerializationDeterministic(), + target); +} + +uint8* ExtensionSet::InternalSerializeWithCachedSizesToArray( + int start_field_number, int end_field_number, bool deterministic, + uint8* target) const { + if (GOOGLE_PREDICT_FALSE(is_large())) { + const auto& end = map_.large->end(); + for (auto it = map_.large->lower_bound(start_field_number); + it != end && it->first < end_field_number; ++it) { + target = it->second.InternalSerializeFieldWithCachedSizesToArray( + it->first, deterministic, target); + } + return target; } + const KeyValue* end = flat_end(); + for (const KeyValue* it = std::lower_bound( + flat_begin(), end, start_field_number, KeyValue::FirstComparator()); + it != end && it->first < end_field_number; ++it) { + target = it->second.InternalSerializeFieldWithCachedSizesToArray( + it->first, deterministic, target); + } + return target; +} + +uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray( + bool deterministic, uint8* target) const { + ForEach([deterministic, &target](int number, const Extension& ext) { + target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray( + number, deterministic, target); + }); return target; } -uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( - int number, uint8* target) const { +uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( + int number, bool deterministic, uint8* target) const { if (is_repeated) { if (is_packed) { if (cached_size == 0) return target; @@ -444,10 +497,10 @@ uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( HANDLE_TYPE( ENUM, Enum, enum); #undef HANDLE_TYPE - case WireFormatLite::TYPE_STRING: - case WireFormatLite::TYPE_BYTES: - case WireFormatLite::TYPE_GROUP: - case WireFormatLite::TYPE_MESSAGE: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; break; } @@ -477,6 +530,16 @@ uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( HANDLE_TYPE( STRING, String, string); HANDLE_TYPE( BYTES, Bytes, string); HANDLE_TYPE( ENUM, Enum, enum); +#undef HANDLE_TYPE +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case FieldDescriptor::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = WireFormatLite::InternalWrite##CAMELCASE##ToArray( \ + number, repeated_##LOWERCASE##_value->Get(i), \ + deterministic, target); \ + } \ + break + HANDLE_TYPE( GROUP, Group, message); HANDLE_TYPE( MESSAGE, Message, message); #undef HANDLE_TYPE @@ -510,10 +573,11 @@ uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( #undef HANDLE_TYPE case FieldDescriptor::TYPE_MESSAGE: if (is_lazy) { - target = lazymessage_value->WriteMessageToArray(number, target); + target = lazymessage_value->InternalWriteMessageToArray( + number, deterministic, target); } else { - target = WireFormatLite::WriteMessageToArray( - number, *message_value, target); + target = WireFormatLite::InternalWriteMessageToArray( + number, *message_value, deterministic, target); } break; } @@ -521,13 +585,14 @@ uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( return target; } -uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray( - int number, - uint8* target) const { +uint8* +ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray( + int number, bool deterministic, uint8* target) const { if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { // Not a valid MessageSet extension, but serialize it the normal way. GOOGLE_LOG(WARNING) << "Invalid message set extension."; - return SerializeFieldWithCachedSizesToArray(number, target); + return InternalSerializeFieldWithCachedSizesToArray(number, deterministic, + target); } if (is_cleared) return target; @@ -540,11 +605,12 @@ uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray( WireFormatLite::kMessageSetTypeIdNumber, number, target); // Write message. if (is_lazy) { - target = lazymessage_value->WriteMessageToArray( - WireFormatLite::kMessageSetMessageNumber, target); + target = lazymessage_value->InternalWriteMessageToArray( + WireFormatLite::kMessageSetMessageNumber, deterministic, target); } else { - target = WireFormatLite::WriteMessageToArray( - WireFormatLite::kMessageSetMessageNumber, *message_value, target); + target = WireFormatLite::InternalWriteMessageToArray( + WireFormatLite::kMessageSetMessageNumber, *message_value, deterministic, + target); } // End group. target = io::CodedOutputStream::WriteTagToArray( @@ -609,7 +675,7 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, string message_data; while (true) { - const uint32 tag = input->ReadTag(); + const uint32 tag = input->ReadTagNoLastTag(); if (tag == 0) return false; switch (tag) { @@ -702,7 +768,7 @@ void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( output->WriteTag(WireFormatLite::kMessageSetItemEndTag); } -int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { +size_t 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. @@ -711,17 +777,17 @@ int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { if (is_cleared) return 0; - int our_size = WireFormatLite::kMessageSetItemTagsSize; + size_t our_size = WireFormatLite::kMessageSetItemTagsSize; // type_id our_size += io::CodedOutputStream::VarintSize32(number); // message - int message_size = 0; + size_t message_size = 0; if (is_lazy) { - message_size = lazymessage_value->ByteSize(); + message_size = lazymessage_value->ByteSizeLong(); } else { - message_size = message_value->ByteSize(); + message_size = message_value->ByteSizeLong(); } our_size += io::CodedOutputStream::VarintSize32(message_size); @@ -732,20 +798,16 @@ int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { void ExtensionSet::SerializeMessageSetWithCachedSizes( io::CodedOutputStream* output) const { - for (map<int, Extension>::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); - } + ForEach([output](int number, const Extension& ext) { + ext.SerializeMessageSetItemWithCachedSizes(number, output); + }); } -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); - } - +size_t ExtensionSet::MessageSetByteSize() const { + size_t total_size = 0; + ForEach([&total_size](int number, const Extension& ext) { + total_size += ext.MessageSetItemByteSize(number); + }); return total_size; } |