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; |