aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/extension_set_heavy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/extension_set_heavy.cc')
-rw-r--r--src/google/protobuf/extension_set_heavy.cc272
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;
}