| Index: third_party/protobuf/src/google/protobuf/extension_set.cc
|
| ===================================================================
|
| --- third_party/protobuf/src/google/protobuf/extension_set.cc (revision 216642)
|
| +++ third_party/protobuf/src/google/protobuf/extension_set.cc (working copy)
|
| @@ -71,7 +71,7 @@
|
|
|
| void InitRegistry() {
|
| registry_ = new ExtensionRegistry;
|
| - internal::OnShutdown(&DeleteRegistry);
|
| + OnShutdown(&DeleteRegistry);
|
| }
|
|
|
| // This function is only called at startup, so there is no need for thread-
|
| @@ -180,6 +180,17 @@
|
| 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;
|
| @@ -293,6 +304,14 @@
|
|
|
| #undef PRIMITIVE_ACCESSORS
|
|
|
| +void* ExtensionSet::MutableRawRepeatedField(int number) {
|
| + // We assume that all the RepeatedField<>* pointers have the same
|
| + // size and alignment within the anonymous union in Extension.
|
| + map<int, Extension>::const_iterator iter = extensions_.find(number);
|
| + GOOGLE_CHECK(iter != extensions_.end()) << "no extension numbered " << number;
|
| + return iter->second.repeated_int32_value;
|
| +}
|
| +
|
| // -------------------------------------------------------------------
|
| // Enums
|
|
|
| @@ -422,7 +441,11 @@
|
| return default_value;
|
| } else {
|
| GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
|
| - return *iter->second.message_value;
|
| + if (iter->second.is_lazy) {
|
| + return iter->second.lazymessage_value->GetMessage(default_value);
|
| + } else {
|
| + return *iter->second.message_value;
|
| + }
|
| }
|
| }
|
|
|
| @@ -439,12 +462,19 @@
|
| 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.
|
| @@ -452,6 +482,56 @@
|
| // 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);
|
| @@ -484,7 +564,7 @@
|
| // 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<internal::GenericTypeHandler<MessageLite> >();
|
| + ->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
| if (result == NULL) {
|
| result = prototype.New();
|
| extension->repeated_message_value->AddAllocated(result);
|
| @@ -540,6 +620,16 @@
|
| }
|
| }
|
|
|
| +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).";
|
| @@ -602,9 +692,11 @@
|
| 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);
|
| }
|
|
|
| @@ -675,12 +767,55 @@
|
| *other_extension.string_value,
|
| other_extension.descriptor);
|
| break;
|
| - case WireFormatLite::CPPTYPE_MESSAGE:
|
| - MutableMessage(iter->first, other_extension.type,
|
| - *other_extension.message_value,
|
| - other_extension.descriptor)
|
| - ->CheckTypeAndMergeFrom(*other_extension.message_value);
|
| + 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;
|
| break;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -706,7 +841,11 @@
|
| }
|
| } else {
|
| if (!extension.is_cleared) {
|
| - if (!extension.message_value->IsInitialized()) return false;
|
| + if (extension.is_lazy) {
|
| + if (!extension.lazymessage_value->IsInitialized()) return false;
|
| + } else {
|
| + if (!extension.message_value->IsInitialized()) return false;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -715,27 +854,42 @@
|
| return true;
|
| }
|
|
|
| -bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
|
| - ExtensionFinder* extension_finder,
|
| - FieldSkipper* field_skipper) {
|
| - int number = WireFormatLite::GetTagFieldNumber(tag);
|
| +bool ExtensionSet::FindExtensionInfoFromTag(
|
| + uint32 tag, ExtensionFinder* extension_finder,
|
| + int* field_number, ExtensionInfo* extension) {
|
| + *field_number = WireFormatLite::GetTagFieldNumber(tag);
|
| WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
|
|
|
| - ExtensionInfo extension;
|
| bool is_unknown;
|
| - if (!extension_finder->Find(number, &extension)) {
|
| + if (!extension_finder->Find(*field_number, extension)) {
|
| is_unknown = true;
|
| - } else if (extension.is_packed) {
|
| + } else if (extension->is_packed) {
|
| is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
|
| } else {
|
| WireFormatLite::WireType expected_wire_type =
|
| - WireFormatLite::WireTypeForFieldType(real_type(extension.type));
|
| + WireFormatLite::WireTypeForFieldType(real_type(extension->type));
|
| is_unknown = (wire_type != expected_wire_type);
|
| }
|
| + return !is_unknown;
|
| +}
|
|
|
| - if (is_unknown) {
|
| - field_skipper->SkipField(input, tag);
|
| - } else if (extension.is_packed) {
|
| +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
|
| + ExtensionFinder* extension_finder,
|
| + FieldSkipper* field_skipper) {
|
| + int number;
|
| + ExtensionInfo extension;
|
| + if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension)) {
|
| + return field_skipper->SkipField(input, tag);
|
| + } else {
|
| + return ParseFieldWithExtensionInfo(number, extension, input, field_skipper);
|
| + }
|
| +}
|
| +
|
| +bool ExtensionSet::ParseFieldWithExtensionInfo(
|
| + int number, const ExtensionInfo& extension,
|
| + io::CodedInputStream* input,
|
| + FieldSkipper* field_skipper) {
|
| + if (extension.is_packed) {
|
| uint32 size;
|
| if (!input->ReadVarint32(&size)) return false;
|
| io::CodedInputStream::Limit limit = input->PushLimit(size);
|
| @@ -852,8 +1006,8 @@
|
|
|
| case WireFormatLite::TYPE_BYTES: {
|
| string* value = extension.is_repeated ?
|
| - AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
|
| - MutableString(number, WireFormatLite::TYPE_STRING,
|
| + AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) :
|
| + MutableString(number, WireFormatLite::TYPE_BYTES,
|
| extension.descriptor);
|
| if (!WireFormatLite::ReadBytes(input, value)) return false;
|
| break;
|
| @@ -897,121 +1051,11 @@
|
| // const Message* 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,
|
| - UnknownFieldSet* unknown_fields) {
|
| - FieldSkipper skipper(unknown_fields);
|
| - GeneratedExtensionFinder finder(containing_type);
|
| - return ParseMessageSet(input, &finder, &skipper);
|
| -}
|
| -
|
| // Defined in extension_set_heavy.cc.
|
| // bool ExtensionSet::ParseMessageSetHeavy(io::CodedInputStream* input,
|
| // const Message* 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 {
|
| @@ -1023,14 +1067,6 @@
|
| }
|
| }
|
|
|
| -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;
|
|
|
| @@ -1042,17 +1078,6 @@
|
| 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
|
|
|
| @@ -1096,7 +1121,11 @@
|
| string_value->clear();
|
| break;
|
| case WireFormatLite::CPPTYPE_MESSAGE:
|
| - message_value->Clear();
|
| + if (is_lazy) {
|
| + lazymessage_value->Clear();
|
| + } else {
|
| + message_value->Clear();
|
| + }
|
| break;
|
| default:
|
| // No need to do anything. Get*() will return the default value
|
| @@ -1208,40 +1237,18 @@
|
| 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;
|
|
|
| @@ -1355,8 +1362,16 @@
|
| 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) \
|
| @@ -1377,29 +1392,6 @@
|
| 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)) {
|
| @@ -1450,7 +1442,11 @@
|
| delete string_value;
|
| break;
|
| case WireFormatLite::CPPTYPE_MESSAGE:
|
| - delete message_value;
|
| + if (is_lazy) {
|
| + delete lazymessage_value;
|
| + } else {
|
| + delete message_value;
|
| + }
|
| break;
|
| default:
|
| break;
|
|
|