Index: third_party/protobuf/src/google/protobuf/extension_set.cc |
diff --git a/third_party/protobuf/src/google/protobuf/extension_set.cc b/third_party/protobuf/src/google/protobuf/extension_set.cc |
index 418e068407b03f61231840fa43a586458bfb547d..9afb236147c0cfd60c4d60b5d3bd55a833052161 100644 |
--- a/third_party/protobuf/src/google/protobuf/extension_set.cc |
+++ b/third_party/protobuf/src/google/protobuf/extension_set.cc |
@@ -1,6 +1,6 @@ |
// Protocol Buffers - Google's data interchange format |
// Copyright 2008 Google Inc. All rights reserved. |
-// http://code.google.com/p/protobuf/ |
+// https://developers.google.com/protocol-buffers/ |
// |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
@@ -38,10 +38,9 @@ |
#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 { |
@@ -58,6 +57,24 @@ 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. |
+ } |
+ GOOGLE_LOG(FATAL) << "can't reach here."; |
+ return false; |
+} |
+ |
// Registry stuff. |
typedef hash_map<pair<const MessageLite*, int>, |
ExtensionInfo> ExtensionRegistry; |
@@ -80,7 +97,7 @@ void Register(const MessageLite* containing_type, |
int number, ExtensionInfo info) { |
::google::protobuf::GoogleOnceInit(®istry_init_, &InitRegistry); |
- if (!InsertIfNotPresent(registry_, make_pair(containing_type, number), |
+ if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number), |
info)) { |
GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" |
<< containing_type->GetTypeName() |
@@ -90,8 +107,9 @@ void Register(const MessageLite* containing_type, |
const ExtensionInfo* FindRegisteredExtension( |
const MessageLite* containing_type, int number) { |
- return (registry_ == NULL) ? NULL : |
- FindOrNull(*registry_, make_pair(containing_type, number)); |
+ return (registry_ == NULL) |
+ ? NULL |
+ : FindOrNull(*registry_, std::make_pair(containing_type, number)); |
} |
} // namespace |
@@ -159,12 +177,21 @@ void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type, |
// =================================================================== |
// Constructors and basic methods. |
-ExtensionSet::ExtensionSet() {} |
+ExtensionSet::ExtensionSet(::google::protobuf::Arena* arena) : arena_(arena) { |
+ if (arena_ != NULL) { |
+ arena_->OwnDestructor(&extensions_); |
+ } |
+} |
+ |
+ExtensionSet::ExtensionSet() : arena_(NULL) {} |
ExtensionSet::~ExtensionSet() { |
- for (map<int, Extension>::iterator iter = extensions_.begin(); |
- iter != extensions_.end(); ++iter) { |
- iter->second.Free(); |
+ // Deletes all allocated extensions. |
+ if (arena_ == NULL) { |
+ for (map<int, Extension>::iterator iter = extensions_.begin(); |
+ iter != extensions_.end(); ++iter) { |
+ iter->second.Free(); |
+ } |
} |
} |
@@ -286,7 +313,8 @@ void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \ |
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \ |
extension->is_repeated = true; \ |
extension->is_packed = packed; \ |
- extension->repeated_##LOWERCASE##_value = new RepeatedField<LOWERCASE>(); \ |
+ extension->repeated_##LOWERCASE##_value = \ |
+ Arena::CreateMessage<RepeatedField<LOWERCASE> >(arena_); \ |
} else { \ |
GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \ |
GOOGLE_DCHECK_EQ(extension->is_packed, packed); \ |
@@ -304,14 +332,90 @@ 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 = |
+ Arena::CreateMessage<RepeatedField<int32> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_INT64: |
+ extension->repeated_int64_value = |
+ Arena::CreateMessage<RepeatedField<int64> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_UINT32: |
+ extension->repeated_uint32_value = |
+ Arena::CreateMessage<RepeatedField<uint32> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_UINT64: |
+ extension->repeated_uint64_value = |
+ Arena::CreateMessage<RepeatedField<uint64> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_DOUBLE: |
+ extension->repeated_double_value = |
+ Arena::CreateMessage<RepeatedField<double> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_FLOAT: |
+ extension->repeated_float_value = |
+ Arena::CreateMessage<RepeatedField<float> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_BOOL: |
+ extension->repeated_bool_value = |
+ Arena::CreateMessage<RepeatedField<bool> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_ENUM: |
+ extension->repeated_enum_value = |
+ Arena::CreateMessage<RepeatedField<int> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_STRING: |
+ extension->repeated_string_value = |
+ Arena::CreateMessage<RepeatedPtrField< ::std::string> >(arena_); |
+ break; |
+ case WireFormatLite::CPPTYPE_MESSAGE: |
+ extension->repeated_message_value = |
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_); |
+ 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. |
- 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 |
@@ -363,7 +467,8 @@ void ExtensionSet::AddEnum(int number, FieldType type, |
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); |
extension->is_repeated = true; |
extension->is_packed = packed; |
- extension->repeated_enum_value = new RepeatedField<int>(); |
+ extension->repeated_enum_value = |
+ Arena::CreateMessage<RepeatedField<int> >(arena_); |
} else { |
GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM); |
GOOGLE_DCHECK_EQ(extension->is_packed, packed); |
@@ -393,7 +498,7 @@ string* ExtensionSet::MutableString(int number, FieldType type, |
extension->type = type; |
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); |
extension->is_repeated = false; |
- extension->string_value = new string; |
+ extension->string_value = Arena::Create<string>(arena_); |
} else { |
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, STRING); |
} |
@@ -423,7 +528,8 @@ string* ExtensionSet::AddString(int number, FieldType type, |
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); |
extension->is_repeated = true; |
extension->is_packed = false; |
- extension->repeated_string_value = new RepeatedPtrField<string>(); |
+ extension->repeated_string_value = |
+ Arena::CreateMessage<RepeatedPtrField<string> >(arena_); |
} else { |
GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING); |
} |
@@ -463,7 +569,7 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType 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->message_value = prototype.New(arena_); |
extension->is_cleared = false; |
return extension->message_value; |
} else { |
@@ -489,25 +595,73 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type, |
ClearExtension(number); |
return; |
} |
+ ::google::protobuf::Arena* message_arena = message->GetArena(); |
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; |
+ if (message_arena == arena_) { |
+ extension->message_value = message; |
+ } else if (message_arena == NULL) { |
+ extension->message_value = message; |
+ arena_->Own(message); // not NULL because not equal to message_arena |
+ } else { |
+ extension->message_value = message->New(arena_); |
+ extension->message_value->CheckTypeAndMergeFrom(*message); |
+ } |
} else { |
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); |
if (extension->is_lazy) { |
extension->lazymessage_value->SetAllocatedMessage(message); |
} else { |
- delete extension->message_value; |
+ if (arena_ == NULL) { |
+ delete extension->message_value; |
+ } |
+ if (message_arena == arena_) { |
+ extension->message_value = message; |
+ } else if (message_arena == NULL) { |
+ extension->message_value = message; |
+ arena_->Own(message); // not NULL because not equal to message_arena |
+ } else { |
+ extension->message_value = message->New(arena_); |
+ extension->message_value->CheckTypeAndMergeFrom(*message); |
+ } |
+ } |
+ } |
+ extension->is_cleared = false; |
+} |
+ |
+void ExtensionSet::UnsafeArenaSetAllocatedMessage( |
+ 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->UnsafeArenaSetAllocatedMessage(message); |
+ } else { |
+ if (arena_ == NULL) { |
+ 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); |
@@ -519,7 +673,39 @@ MessageLite* ExtensionSet::ReleaseMessage(int number, |
MessageLite* ret = NULL; |
if (iter->second.is_lazy) { |
ret = iter->second.lazymessage_value->ReleaseMessage(prototype); |
- delete iter->second.lazymessage_value; |
+ if (arena_ == NULL) { |
+ delete iter->second.lazymessage_value; |
+ } |
+ } else { |
+ if (arena_ == NULL) { |
+ ret = iter->second.message_value; |
+ } else { |
+ // ReleaseMessage() always returns a heap-allocated message, and we are |
+ // on an arena, so we need to make a copy of this message to return. |
+ ret = (iter->second.message_value)->New(); |
+ ret->CheckTypeAndMergeFrom(*iter->second.message_value); |
+ } |
+ } |
+ extensions_.erase(number); |
+ return ret; |
+ } |
+} |
+ |
+MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( |
+ 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->UnsafeArenaReleaseMessage(prototype); |
+ if (arena_ == NULL) { |
+ delete iter->second.lazymessage_value; |
+ } |
} else { |
ret = iter->second.message_value; |
} |
@@ -556,7 +742,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, |
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); |
extension->is_repeated = true; |
extension->repeated_message_value = |
- new RepeatedPtrField<MessageLite>(); |
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_); |
} else { |
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); |
} |
@@ -566,7 +752,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, |
MessageLite* result = extension->repeated_message_value |
->AddFromCleared<GenericTypeHandler<MessageLite> >(); |
if (result == NULL) { |
- result = prototype.New(); |
+ result = prototype.New(arena_); |
extension->repeated_message_value->AddAllocated(result); |
} |
return result; |
@@ -684,138 +870,142 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { |
for (map<int, Extension>::const_iterator iter = other.extensions_.begin(); |
iter != other.extensions_.end(); ++iter) { |
const Extension& other_extension = iter->second; |
+ InternalExtensionMergeFrom(iter->first, other_extension); |
+ } |
+} |
- if (other_extension.is_repeated) { |
- Extension* extension; |
- bool is_new = MaybeNewExtension(iter->first, other_extension.descriptor, |
- &extension); |
- 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); |
- } |
+void ExtensionSet::InternalExtensionMergeFrom( |
+ int number, const Extension& other_extension) { |
+ if (other_extension.is_repeated) { |
+ Extension* extension; |
+ bool is_new = MaybeNewExtension(number, other_extension.descriptor, |
+ &extension); |
+ 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); |
+ } |
- switch (cpp_type(other_extension.type)) { |
-#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ |
- case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
- if (is_new) { \ |
- extension->repeated_##LOWERCASE##_value = \ |
- new REPEATED_TYPE; \ |
- } \ |
- extension->repeated_##LOWERCASE##_value->MergeFrom( \ |
- *other_extension.repeated_##LOWERCASE##_value); \ |
- break; |
+ switch (cpp_type(other_extension.type)) { |
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ |
+ case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
+ if (is_new) { \ |
+ extension->repeated_##LOWERCASE##_value = \ |
+ Arena::CreateMessage<REPEATED_TYPE >(arena_); \ |
+ } \ |
+ extension->repeated_##LOWERCASE##_value->MergeFrom( \ |
+ *other_extension.repeated_##LOWERCASE##_value); \ |
+ break; |
- HANDLE_TYPE( INT32, int32, RepeatedField < int32>); |
- HANDLE_TYPE( INT64, int64, RepeatedField < int64>); |
- HANDLE_TYPE( UINT32, uint32, RepeatedField < uint32>); |
- HANDLE_TYPE( UINT64, uint64, RepeatedField < uint64>); |
- HANDLE_TYPE( FLOAT, float, RepeatedField < float>); |
- HANDLE_TYPE( DOUBLE, double, RepeatedField < double>); |
- HANDLE_TYPE( BOOL, bool, RepeatedField < bool>); |
- HANDLE_TYPE( ENUM, enum, RepeatedField < int>); |
- HANDLE_TYPE( STRING, string, RepeatedPtrField< string>); |
+ HANDLE_TYPE( INT32, int32, RepeatedField < int32>); |
+ HANDLE_TYPE( INT64, int64, RepeatedField < int64>); |
+ HANDLE_TYPE( UINT32, uint32, RepeatedField < uint32>); |
+ HANDLE_TYPE( UINT64, uint64, RepeatedField < uint64>); |
+ HANDLE_TYPE( FLOAT, float, RepeatedField < float>); |
+ HANDLE_TYPE( DOUBLE, double, RepeatedField < double>); |
+ HANDLE_TYPE( BOOL, bool, RepeatedField < bool>); |
+ HANDLE_TYPE( ENUM, enum, RepeatedField < int>); |
+ HANDLE_TYPE( STRING, string, RepeatedPtrField< string>); |
#undef HANDLE_TYPE |
- case WireFormatLite::CPPTYPE_MESSAGE: |
- if (is_new) { |
- extension->repeated_message_value = |
- new RepeatedPtrField<MessageLite>(); |
- } |
- // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because |
- // it would attempt to allocate new objects. |
- RepeatedPtrField<MessageLite>* other_repeated_message = |
- other_extension.repeated_message_value; |
- for (int i = 0; i < other_repeated_message->size(); i++) { |
- const MessageLite& other_message = other_repeated_message->Get(i); |
- MessageLite* target = extension->repeated_message_value |
- ->AddFromCleared<GenericTypeHandler<MessageLite> >(); |
- if (target == NULL) { |
- target = other_message.New(); |
- extension->repeated_message_value->AddAllocated(target); |
- } |
- target->CheckTypeAndMergeFrom(other_message); |
+ case WireFormatLite::CPPTYPE_MESSAGE: |
+ if (is_new) { |
+ extension->repeated_message_value = |
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_); |
+ } |
+ // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because |
+ // it would attempt to allocate new objects. |
+ RepeatedPtrField<MessageLite>* other_repeated_message = |
+ other_extension.repeated_message_value; |
+ for (int i = 0; i < other_repeated_message->size(); i++) { |
+ const MessageLite& other_message = other_repeated_message->Get(i); |
+ MessageLite* target = extension->repeated_message_value |
+ ->AddFromCleared<GenericTypeHandler<MessageLite> >(); |
+ if (target == NULL) { |
+ target = other_message.New(arena_); |
+ extension->repeated_message_value->AddAllocated(target); |
} |
+ target->CheckTypeAndMergeFrom(other_message); |
+ } |
+ break; |
+ } |
+ } else { |
+ if (!other_extension.is_cleared) { |
+ switch (cpp_type(other_extension.type)) { |
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ |
+ case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
+ Set##CAMELCASE(number, other_extension.type, \ |
+ other_extension.LOWERCASE##_value, \ |
+ other_extension.descriptor); \ |
break; |
- } |
- } else { |
- if (!other_extension.is_cleared) { |
- switch (cpp_type(other_extension.type)) { |
-#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ |
- case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
- Set##CAMELCASE(iter->first, other_extension.type, \ |
- other_extension.LOWERCASE##_value, \ |
- other_extension.descriptor); \ |
- break; |
- |
- HANDLE_TYPE( INT32, int32, Int32); |
- HANDLE_TYPE( INT64, int64, Int64); |
- HANDLE_TYPE(UINT32, uint32, UInt32); |
- HANDLE_TYPE(UINT64, uint64, UInt64); |
- HANDLE_TYPE( FLOAT, float, Float); |
- HANDLE_TYPE(DOUBLE, double, Double); |
- HANDLE_TYPE( BOOL, bool, Bool); |
- HANDLE_TYPE( ENUM, enum, Enum); |
+ |
+ HANDLE_TYPE( INT32, int32, Int32); |
+ HANDLE_TYPE( INT64, int64, Int64); |
+ HANDLE_TYPE(UINT32, uint32, UInt32); |
+ HANDLE_TYPE(UINT64, uint64, UInt64); |
+ HANDLE_TYPE( FLOAT, float, Float); |
+ HANDLE_TYPE(DOUBLE, double, Double); |
+ HANDLE_TYPE( BOOL, bool, Bool); |
+ HANDLE_TYPE( ENUM, enum, Enum); |
#undef HANDLE_TYPE |
- case WireFormatLite::CPPTYPE_STRING: |
- SetString(iter->first, other_extension.type, |
- *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(); |
+ case WireFormatLite::CPPTYPE_STRING: |
+ SetString(number, other_extension.type, |
+ *other_extension.string_value, |
+ other_extension.descriptor); |
+ break; |
+ case WireFormatLite::CPPTYPE_MESSAGE: { |
+ Extension* extension; |
+ bool is_new = MaybeNewExtension(number, |
+ 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(arena_); |
+ extension->lazymessage_value->MergeFrom( |
+ *other_extension.lazymessage_value); |
+ } else { |
+ extension->is_lazy = false; |
+ extension->message_value = |
+ other_extension.message_value->New(arena_); |
+ 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->is_lazy = false; |
- extension->message_value = |
- other_extension.message_value->New(); |
extension->message_value->CheckTypeAndMergeFrom( |
- *other_extension.message_value); |
+ other_extension.lazymessage_value->GetMessage( |
+ *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)); |
- } |
+ if (extension->is_lazy) { |
+ extension->lazymessage_value->MutableMessage( |
+ *other_extension.message_value)->CheckTypeAndMergeFrom( |
+ *other_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->message_value->CheckTypeAndMergeFrom( |
+ *other_extension.message_value); |
} |
} |
- extension->is_cleared = false; |
- break; |
} |
+ extension->is_cleared = false; |
+ break; |
} |
} |
} |
@@ -823,7 +1013,73 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { |
} |
void ExtensionSet::Swap(ExtensionSet* x) { |
- extensions_.swap(x->extensions_); |
+ if (GetArenaNoVirtual() == x->GetArenaNoVirtual()) { |
+ extensions_.swap(x->extensions_); |
+ } else { |
+ // TODO(cfallin, rohananil): We maybe able to optimize a case where we are |
+ // swapping from heap to arena-allocated extension set, by just Own()'ing |
+ // the extensions. |
+ ExtensionSet extension_set; |
+ extension_set.MergeFrom(*x); |
+ x->Clear(); |
+ x->MergeFrom(*this); |
+ Clear(); |
+ MergeFrom(extension_set); |
+ } |
+} |
+ |
+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()) { |
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { |
+ using std::swap; |
+ swap(this_iter->second, other_iter->second); |
+ } else { |
+ // TODO(cfallin, rohananil): We could further optimize these cases, |
+ // especially avoid creation of ExtensionSet, and move MergeFrom logic |
+ // into Extensions itself (which takes arena as an argument). |
+ // We do it this way to reuse the copy-across-arenas logic already |
+ // implemented in ExtensionSet's MergeFrom. |
+ ExtensionSet temp; |
+ temp.InternalExtensionMergeFrom(number, other_iter->second); |
+ map<int, Extension>::iterator temp_iter = temp.extensions_.find(number); |
+ other_iter->second.Clear(); |
+ other->InternalExtensionMergeFrom(number, this_iter->second); |
+ this_iter->second.Clear(); |
+ InternalExtensionMergeFrom(number, temp_iter->second); |
+ } |
+ return; |
+ } |
+ |
+ if (this_iter == extensions_.end()) { |
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { |
+ extensions_.insert(std::make_pair(number, other_iter->second)); |
+ } else { |
+ InternalExtensionMergeFrom(number, other_iter->second); |
+ } |
+ other->extensions_.erase(number); |
+ return; |
+ } |
+ |
+ if (other_iter == other->extensions_.end()) { |
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { |
+ other->extensions_.insert(std::make_pair(number, this_iter->second)); |
+ } else { |
+ other->InternalExtensionMergeFrom(number, this_iter->second); |
+ } |
+ extensions_.erase(number); |
+ return; |
+ } |
} |
bool ExtensionSet::IsInitialized() const { |
@@ -855,41 +1111,59 @@ bool ExtensionSet::IsInitialized() const { |
} |
bool ExtensionSet::FindExtensionInfoFromTag( |
- uint32 tag, ExtensionFinder* extension_finder, |
- int* field_number, ExtensionInfo* extension) { |
+ 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 is_unknown; |
- if (!extension_finder->Find(*field_number, extension)) { |
- is_unknown = true; |
- } 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)); |
- is_unknown = (wire_type != expected_wire_type); |
+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; |
} |
- return !is_unknown; |
+ // 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; |
ExtensionInfo extension; |
- if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension)) { |
+ if (!FindExtensionInfoFromTag( |
+ tag, extension_finder, &number, &extension, &was_packed_on_wire)) { |
return field_skipper->SkipField(input, tag); |
} else { |
- return ParseFieldWithExtensionInfo(number, extension, input, field_skipper); |
+ return ParseFieldWithExtensionInfo( |
+ number, was_packed_on_wire, extension, input, field_skipper); |
} |
} |
bool ExtensionSet::ParseFieldWithExtensionInfo( |
- int number, const ExtensionInfo& extension, |
+ int number, bool was_packed_on_wire, const ExtensionInfo& extension, |
io::CodedInputStream* input, |
FieldSkipper* field_skipper) { |
- if (extension.is_packed) { |
+ // Explicitly not read extension.is_packed, instead check whether the field |
+ // was encoded in packed form on the wire. |
+ if (was_packed_on_wire) { |
uint32 size; |
if (!input->ReadVarint32(&size)) return false; |
io::CodedInputStream::Limit limit = input->PushLimit(size); |
@@ -903,7 +1177,8 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( |
CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ |
input, &value)) return false; \ |
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ |
- true, value, extension.descriptor); \ |
+ extension.is_packed, value, \ |
+ extension.descriptor); \ |
} \ |
break |
@@ -929,8 +1204,11 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( |
input, &value)) return false; |
if (extension.enum_validity_check.func( |
extension.enum_validity_check.arg, value)) { |
- AddEnum(number, WireFormatLite::TYPE_ENUM, true, value, |
- extension.descriptor); |
+ AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, |
+ value, extension.descriptor); |
+ } else { |
+ // Invalid value. Treat as unknown. |
+ field_skipper->SkipUnknownEnum(number, value); |
} |
} |
break; |
@@ -952,9 +1230,10 @@ 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, \ |
- false, value, extension.descriptor); \ |
+ extension.is_packed, value, \ |
+ extension.descriptor); \ |
} else { \ |
Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ |
extension.descriptor); \ |
@@ -986,7 +1265,7 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( |
// Invalid value. Treat as unknown. |
field_skipper->SkipUnknownEnum(number, value); |
} else if (extension.is_repeated) { |
- AddEnum(number, WireFormatLite::TYPE_ENUM, false, value, |
+ AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, |
extension.descriptor); |
} else { |
SetEnum(number, WireFormatLite::TYPE_ENUM, value, |
@@ -1039,22 +1318,29 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( |
} |
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, |
+ const MessageLite* containing_type) { |
+ FieldSkipper skipper; |
+ GeneratedExtensionFinder finder(containing_type); |
+ return ParseField(tag, input, &finder, &skipper); |
+} |
+ |
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, |
const MessageLite* containing_type, |
- UnknownFieldSet* unknown_fields) { |
- FieldSkipper skipper(unknown_fields); |
+ 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::ParseFieldHeavy(uint32 tag, io::CodedInputStream* input, |
-// const Message* containing_type, |
-// UnknownFieldSet* unknown_fields) |
+// bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, |
+// const MessageLite* containing_type, |
+// UnknownFieldSet* unknown_fields) |
// Defined in extension_set_heavy.cc. |
-// bool ExtensionSet::ParseMessageSetHeavy(io::CodedInputStream* input, |
-// const Message* containing_type, |
-// UnknownFieldSet* unknown_fields); |
+// bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, |
+// const MessageLite* containing_type, |
+// UnknownFieldSet* unknown_fields); |
void ExtensionSet::SerializeWithCachedSizes( |
int start_field_number, int end_field_number, |
@@ -1085,7 +1371,7 @@ bool ExtensionSet::MaybeNewExtension(int number, |
const FieldDescriptor* descriptor, |
Extension** result) { |
pair<map<int, Extension>::iterator, bool> insert_result = |
- extensions_.insert(make_pair(number, Extension())); |
+ extensions_.insert(std::make_pair(number, Extension())); |
*result = &insert_result.first->second; |
(*result)->descriptor = descriptor; |
return insert_result.second; |
@@ -1416,6 +1702,8 @@ int ExtensionSet::Extension::GetSize() const { |
return 0; |
} |
+// This function deletes all allocated objects. This function should be only |
+// called if the Extension was created with an arena. |
void ExtensionSet::Extension::Free() { |
if (is_repeated) { |
switch (cpp_type(type)) { |
@@ -1457,6 +1745,71 @@ void ExtensionSet::Extension::Free() { |
// Defined in extension_set_heavy.cc. |
// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const |
+// ================================================================== |
+// Default repeated field instances for iterator-compatible accessors |
+ |
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_primitive_generic_type_traits_once_init_); |
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_string_type_traits_once_init_); |
+GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_message_generic_type_traits_once_init_); |
+ |
+void RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields() { |
+ default_repeated_field_int32_ = new RepeatedField<int32>; |
+ default_repeated_field_int64_ = new RepeatedField<int64>; |
+ default_repeated_field_uint32_ = new RepeatedField<uint32>; |
+ default_repeated_field_uint64_ = new RepeatedField<uint64>; |
+ default_repeated_field_double_ = new RepeatedField<double>; |
+ default_repeated_field_float_ = new RepeatedField<float>; |
+ default_repeated_field_bool_ = new RepeatedField<bool>; |
+ OnShutdown(&DestroyDefaultRepeatedFields); |
+} |
+ |
+void RepeatedPrimitiveGenericTypeTraits::DestroyDefaultRepeatedFields() { |
+ delete default_repeated_field_int32_; |
+ delete default_repeated_field_int64_; |
+ delete default_repeated_field_uint32_; |
+ delete default_repeated_field_uint64_; |
+ delete default_repeated_field_double_; |
+ delete default_repeated_field_float_; |
+ delete default_repeated_field_bool_; |
+} |
+ |
+void RepeatedStringTypeTraits::InitializeDefaultRepeatedFields() { |
+ default_repeated_field_ = new RepeatedFieldType; |
+ OnShutdown(&DestroyDefaultRepeatedFields); |
+} |
+ |
+void RepeatedStringTypeTraits::DestroyDefaultRepeatedFields() { |
+ delete default_repeated_field_; |
+} |
+ |
+void RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields() { |
+ default_repeated_field_ = new RepeatedFieldType; |
+ OnShutdown(&DestroyDefaultRepeatedFields); |
+} |
+ |
+void RepeatedMessageGenericTypeTraits::DestroyDefaultRepeatedFields() { |
+ delete default_repeated_field_; |
+} |
+ |
+const RepeatedField<int32>* |
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = NULL; |
+const RepeatedField<int64>* |
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = NULL; |
+const RepeatedField<uint32>* |
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = NULL; |
+const RepeatedField<uint64>* |
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = NULL; |
+const RepeatedField<double>* |
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = NULL; |
+const RepeatedField<float>* |
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = NULL; |
+const RepeatedField<bool>* |
+RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = NULL; |
+const RepeatedStringTypeTraits::RepeatedFieldType* |
+RepeatedStringTypeTraits::default_repeated_field_ = NULL; |
+const RepeatedMessageGenericTypeTraits::RepeatedFieldType* |
+RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL; |
+ |
} // namespace internal |
} // namespace protobuf |
} // namespace google |