summaryrefslogtreecommitdiffstats
path: root/src/google/protobuf/extension_set.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/extension_set.cc')
-rw-r--r--src/google/protobuf/extension_set.cc649
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