aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-06-25 19:05:36 +0000
committerkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-06-25 19:05:36 +0000
commitceb561d65bfe234a301979a7e3f7ddc244d349b3 (patch)
tree8b86ec6fda6f7bcce0f214940dcaea5fb73c7d9f
parentf22943c7d0ce19b35a1e3d7f33c8ede3b6fed485 (diff)
downloadprotobuf-ceb561d65bfe234a301979a7e3f7ddc244d349b3.tar.gz
protobuf-ceb561d65bfe234a301979a7e3f7ddc244d349b3.tar.bz2
protobuf-ceb561d65bfe234a301979a7e3f7ddc244d349b3.zip
Add Swap(), SwapElements(), and RemoveLast() to Reflection. Patch by Scott Stafford.
-rw-r--r--CHANGES.txt10
-rw-r--r--CONTRIBUTORS.txt2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc35
-rw-r--r--src/google/protobuf/descriptor.pb.cc334
-rw-r--r--src/google/protobuf/extension_set.cc82
-rw-r--r--src/google/protobuf/extension_set.h3
-rw-r--r--src/google/protobuf/generated_message_reflection.cc89
-rw-r--r--src/google/protobuf/generated_message_reflection.h4
-rw-r--r--src/google/protobuf/generated_message_reflection_unittest.cc116
-rw-r--r--src/google/protobuf/message.h21
-rw-r--r--src/google/protobuf/repeated_field.h57
-rw-r--r--src/google/protobuf/test_util.cc315
-rw-r--r--src/google/protobuf/test_util.h14
13 files changed, 896 insertions, 186 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index f62c6632..76e401fc 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,13 @@
+????-??-?? version 2.1.1:
+
+ C++
+ * Fixed bug where Message.Swap(Message) was only implemented for
+ optimize_for_speed. Swap now properly implemented in both modes
+ (Issue 91).
+ * Added RemoveLast and SwapElements(index1, index2) to Reflection
+ interface for repeated elements.
+ * Added Swap(Message) to Reflection interface.
+
2009-05-13 version 2.1.0:
General
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 7dd17d0d..f9f2a6a2 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -70,3 +70,5 @@ Patch contributors:
* Small patch improving performance of in Python serialization.
Alexandre Vassalotti <alexandre@peadrop.com>
* Emacs mode for Protocol Buffers (editors/protobuf-mode.el).
+ Scott Stafford <scott.stafford@gmail.com>
+ * Added Swap(), SwapElements(), and RemoveLast() to Reflection interface.
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 95f20a60..9852ee91 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -684,13 +684,13 @@ GenerateClassMethods(io::Printer* printer) {
GenerateCopyFrom(printer);
printer->Print("\n");
- GenerateSwap(printer);
- printer->Print("\n");
-
GenerateIsInitialized(printer);
printer->Print("\n");
}
+ GenerateSwap(printer);
+ printer->Print("\n");
+
printer->Print(
"const ::google::protobuf::Descriptor* $classname$::GetDescriptor() const {\n"
" return descriptor();\n"
@@ -967,22 +967,27 @@ GenerateSwap(io::Printer* printer) {
printer->Print("if (other != this) {\n");
printer->Indent();
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
- field_generators_.get(field).GenerateSwappingCode(printer);
- }
+ if ( descriptor_->file()->options().optimize_for() == FileOptions::SPEED ) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ field_generators_.get(field).GenerateSwappingCode(printer);
+ }
- for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
- printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
- "i", SimpleItoa(i));
- }
+ for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
+ printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
+ "i", SimpleItoa(i));
+ }
- printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
- printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
- if (descriptor_->extension_range_count() > 0) {
- printer->Print("_extensions_.Swap(&other->_extensions_);\n");
+ printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
+ printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print("_extensions_.Swap(&other->_extensions_);\n");
+ }
+ } else {
+ printer->Print("GetReflection()->Swap(this, other);");
}
+
printer->Outdent();
printer->Print("}\n");
printer->Outdent();
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index d4a7666b..0caed839 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -807,6 +807,14 @@ void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) {
MergeFrom(from);
}
+bool FileDescriptorSet::IsInitialized() const {
+
+ for (int i = 0; i < file_size(); i++) {
+ if (!this->file(i).IsInitialized()) return false;
+ }
+ return true;
+}
+
void FileDescriptorSet::Swap(FileDescriptorSet* other) {
if (other != this) {
file_.Swap(&other->file_);
@@ -816,14 +824,6 @@ void FileDescriptorSet::Swap(FileDescriptorSet* other) {
}
}
-bool FileDescriptorSet::IsInitialized() const {
-
- for (int i = 0; i < file_size(); i++) {
- if (!this->file(i).IsInitialized()) return false;
- }
- return true;
-}
-
const ::google::protobuf::Descriptor* FileDescriptorSet::GetDescriptor() const {
return descriptor();
}
@@ -1274,22 +1274,6 @@ void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) {
MergeFrom(from);
}
-void FileDescriptorProto::Swap(FileDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- std::swap(package_, other->package_);
- dependency_.Swap(&other->dependency_);
- message_type_.Swap(&other->message_type_);
- enum_type_.Swap(&other->enum_type_);
- service_.Swap(&other->service_);
- extension_.Swap(&other->extension_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- }
-}
-
bool FileDescriptorProto::IsInitialized() const {
for (int i = 0; i < message_type_size(); i++) {
@@ -1310,6 +1294,22 @@ bool FileDescriptorProto::IsInitialized() const {
return true;
}
+void FileDescriptorProto::Swap(FileDescriptorProto* other) {
+ if (other != this) {
+ std::swap(name_, other->name_);
+ std::swap(package_, other->package_);
+ dependency_.Swap(&other->dependency_);
+ message_type_.Swap(&other->message_type_);
+ enum_type_.Swap(&other->enum_type_);
+ service_.Swap(&other->service_);
+ extension_.Swap(&other->extension_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
const ::google::protobuf::Descriptor* FileDescriptorProto::GetDescriptor() const {
return descriptor();
}
@@ -1536,6 +1536,11 @@ void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRan
MergeFrom(from);
}
+bool DescriptorProto_ExtensionRange::IsInitialized() const {
+
+ return true;
+}
+
void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) {
if (other != this) {
std::swap(start_, other->start_);
@@ -1546,11 +1551,6 @@ void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other)
}
}
-bool DescriptorProto_ExtensionRange::IsInitialized() const {
-
- return true;
-}
-
const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::GetDescriptor() const {
return descriptor();
}
@@ -1960,21 +1960,6 @@ void DescriptorProto::CopyFrom(const DescriptorProto& from) {
MergeFrom(from);
}
-void DescriptorProto::Swap(DescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- field_.Swap(&other->field_);
- extension_.Swap(&other->extension_);
- nested_type_.Swap(&other->nested_type_);
- enum_type_.Swap(&other->enum_type_);
- extension_range_.Swap(&other->extension_range_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- }
-}
-
bool DescriptorProto::IsInitialized() const {
for (int i = 0; i < field_size(); i++) {
@@ -1995,6 +1980,21 @@ bool DescriptorProto::IsInitialized() const {
return true;
}
+void DescriptorProto::Swap(DescriptorProto* other) {
+ if (other != this) {
+ std::swap(name_, other->name_);
+ field_.Swap(&other->field_);
+ extension_.Swap(&other->extension_);
+ nested_type_.Swap(&other->nested_type_);
+ enum_type_.Swap(&other->enum_type_);
+ extension_range_.Swap(&other->extension_range_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
const ::google::protobuf::Descriptor* DescriptorProto::GetDescriptor() const {
return descriptor();
}
@@ -2546,6 +2546,14 @@ void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) {
MergeFrom(from);
}
+bool FieldDescriptorProto::IsInitialized() const {
+
+ if (has_options()) {
+ if (!this->options().IsInitialized()) return false;
+ }
+ return true;
+}
+
void FieldDescriptorProto::Swap(FieldDescriptorProto* other) {
if (other != this) {
std::swap(name_, other->name_);
@@ -2562,14 +2570,6 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) {
}
}
-bool FieldDescriptorProto::IsInitialized() const {
-
- if (has_options()) {
- if (!this->options().IsInitialized()) return false;
- }
- return true;
-}
-
const ::google::protobuf::Descriptor* FieldDescriptorProto::GetDescriptor() const {
return descriptor();
}
@@ -2839,17 +2839,6 @@ void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) {
MergeFrom(from);
}
-void EnumDescriptorProto::Swap(EnumDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- value_.Swap(&other->value_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- }
-}
-
bool EnumDescriptorProto::IsInitialized() const {
for (int i = 0; i < value_size(); i++) {
@@ -2861,6 +2850,17 @@ bool EnumDescriptorProto::IsInitialized() const {
return true;
}
+void EnumDescriptorProto::Swap(EnumDescriptorProto* other) {
+ if (other != this) {
+ std::swap(name_, other->name_);
+ value_.Swap(&other->value_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
const ::google::protobuf::Descriptor* EnumDescriptorProto::GetDescriptor() const {
return descriptor();
}
@@ -3132,6 +3132,14 @@ void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) {
MergeFrom(from);
}
+bool EnumValueDescriptorProto::IsInitialized() const {
+
+ if (has_options()) {
+ if (!this->options().IsInitialized()) return false;
+ }
+ return true;
+}
+
void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) {
if (other != this) {
std::swap(name_, other->name_);
@@ -3143,14 +3151,6 @@ void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) {
}
}
-bool EnumValueDescriptorProto::IsInitialized() const {
-
- if (has_options()) {
- if (!this->options().IsInitialized()) return false;
- }
- return true;
-}
-
const ::google::protobuf::Descriptor* EnumValueDescriptorProto::GetDescriptor() const {
return descriptor();
}
@@ -3420,17 +3420,6 @@ void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) {
MergeFrom(from);
}
-void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- method_.Swap(&other->method_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- }
-}
-
bool ServiceDescriptorProto::IsInitialized() const {
for (int i = 0; i < method_size(); i++) {
@@ -3442,6 +3431,17 @@ bool ServiceDescriptorProto::IsInitialized() const {
return true;
}
+void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) {
+ if (other != this) {
+ std::swap(name_, other->name_);
+ method_.Swap(&other->method_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
const ::google::protobuf::Descriptor* ServiceDescriptorProto::GetDescriptor() const {
return descriptor();
}
@@ -3760,6 +3760,14 @@ void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) {
MergeFrom(from);
}
+bool MethodDescriptorProto::IsInitialized() const {
+
+ if (has_options()) {
+ if (!this->options().IsInitialized()) return false;
+ }
+ return true;
+}
+
void MethodDescriptorProto::Swap(MethodDescriptorProto* other) {
if (other != this) {
std::swap(name_, other->name_);
@@ -3772,14 +3780,6 @@ void MethodDescriptorProto::Swap(MethodDescriptorProto* other) {
}
}
-bool MethodDescriptorProto::IsInitialized() const {
-
- if (has_options()) {
- if (!this->options().IsInitialized()) return false;
- }
- return true;
-}
-
const ::google::protobuf::Descriptor* MethodDescriptorProto::GetDescriptor() const {
return descriptor();
}
@@ -4163,6 +4163,15 @@ void FileOptions::CopyFrom(const FileOptions& from) {
MergeFrom(from);
}
+bool FileOptions::IsInitialized() const {
+
+ for (int i = 0; i < uninterpreted_option_size(); i++) {
+ if (!this->uninterpreted_option(i).IsInitialized()) return false;
+ }
+
+ if (!_extensions_.IsInitialized()) return false; return true;
+}
+
void FileOptions::Swap(FileOptions* other) {
if (other != this) {
std::swap(java_package_, other->java_package_);
@@ -4177,15 +4186,6 @@ void FileOptions::Swap(FileOptions* other) {
}
}
-bool FileOptions::IsInitialized() const {
-
- for (int i = 0; i < uninterpreted_option_size(); i++) {
- if (!this->uninterpreted_option(i).IsInitialized()) return false;
- }
-
- if (!_extensions_.IsInitialized()) return false; return true;
-}
-
const ::google::protobuf::Descriptor* FileOptions::GetDescriptor() const {
return descriptor();
}
@@ -4425,6 +4425,15 @@ void MessageOptions::CopyFrom(const MessageOptions& from) {
MergeFrom(from);
}
+bool MessageOptions::IsInitialized() const {
+
+ for (int i = 0; i < uninterpreted_option_size(); i++) {
+ if (!this->uninterpreted_option(i).IsInitialized()) return false;
+ }
+
+ if (!_extensions_.IsInitialized()) return false; return true;
+}
+
void MessageOptions::Swap(MessageOptions* other) {
if (other != this) {
std::swap(message_set_wire_format_, other->message_set_wire_format_);
@@ -4436,15 +4445,6 @@ void MessageOptions::Swap(MessageOptions* other) {
}
}
-bool MessageOptions::IsInitialized() const {
-
- for (int i = 0; i < uninterpreted_option_size(); i++) {
- if (!this->uninterpreted_option(i).IsInitialized()) return false;
- }
-
- if (!_extensions_.IsInitialized()) return false; return true;
-}
-
const ::google::protobuf::Descriptor* MessageOptions::GetDescriptor() const {
return descriptor();
}
@@ -4821,6 +4821,15 @@ void FieldOptions::CopyFrom(const FieldOptions& from) {
MergeFrom(from);
}
+bool FieldOptions::IsInitialized() const {
+
+ for (int i = 0; i < uninterpreted_option_size(); i++) {
+ if (!this->uninterpreted_option(i).IsInitialized()) return false;
+ }
+
+ if (!_extensions_.IsInitialized()) return false; return true;
+}
+
void FieldOptions::Swap(FieldOptions* other) {
if (other != this) {
std::swap(ctype_, other->ctype_);
@@ -4835,15 +4844,6 @@ void FieldOptions::Swap(FieldOptions* other) {
}
}
-bool FieldOptions::IsInitialized() const {
-
- for (int i = 0; i < uninterpreted_option_size(); i++) {
- if (!this->uninterpreted_option(i).IsInitialized()) return false;
- }
-
- if (!_extensions_.IsInitialized()) return false; return true;
-}
-
const ::google::protobuf::Descriptor* FieldOptions::GetDescriptor() const {
return descriptor();
}
@@ -5043,6 +5043,15 @@ void EnumOptions::CopyFrom(const EnumOptions& from) {
MergeFrom(from);
}
+bool EnumOptions::IsInitialized() const {
+
+ for (int i = 0; i < uninterpreted_option_size(); i++) {
+ if (!this->uninterpreted_option(i).IsInitialized()) return false;
+ }
+
+ if (!_extensions_.IsInitialized()) return false; return true;
+}
+
void EnumOptions::Swap(EnumOptions* other) {
if (other != this) {
uninterpreted_option_.Swap(&other->uninterpreted_option_);
@@ -5053,15 +5062,6 @@ void EnumOptions::Swap(EnumOptions* other) {
}
}
-bool EnumOptions::IsInitialized() const {
-
- for (int i = 0; i < uninterpreted_option_size(); i++) {
- if (!this->uninterpreted_option(i).IsInitialized()) return false;
- }
-
- if (!_extensions_.IsInitialized()) return false; return true;
-}
-
const ::google::protobuf::Descriptor* EnumOptions::GetDescriptor() const {
return descriptor();
}
@@ -5261,6 +5261,15 @@ void EnumValueOptions::CopyFrom(const EnumValueOptions& from) {
MergeFrom(from);
}
+bool EnumValueOptions::IsInitialized() const {
+
+ for (int i = 0; i < uninterpreted_option_size(); i++) {
+ if (!this->uninterpreted_option(i).IsInitialized()) return false;
+ }
+
+ if (!_extensions_.IsInitialized()) return false; return true;
+}
+
void EnumValueOptions::Swap(EnumValueOptions* other) {
if (other != this) {
uninterpreted_option_.Swap(&other->uninterpreted_option_);
@@ -5271,15 +5280,6 @@ void EnumValueOptions::Swap(EnumValueOptions* other) {
}
}
-bool EnumValueOptions::IsInitialized() const {
-
- for (int i = 0; i < uninterpreted_option_size(); i++) {
- if (!this->uninterpreted_option(i).IsInitialized()) return false;
- }
-
- if (!_extensions_.IsInitialized()) return false; return true;
-}
-
const ::google::protobuf::Descriptor* EnumValueOptions::GetDescriptor() const {
return descriptor();
}
@@ -5479,6 +5479,15 @@ void ServiceOptions::CopyFrom(const ServiceOptions& from) {
MergeFrom(from);
}
+bool ServiceOptions::IsInitialized() const {
+
+ for (int i = 0; i < uninterpreted_option_size(); i++) {
+ if (!this->uninterpreted_option(i).IsInitialized()) return false;
+ }
+
+ if (!_extensions_.IsInitialized()) return false; return true;
+}
+
void ServiceOptions::Swap(ServiceOptions* other) {
if (other != this) {
uninterpreted_option_.Swap(&other->uninterpreted_option_);
@@ -5489,15 +5498,6 @@ void ServiceOptions::Swap(ServiceOptions* other) {
}
}
-bool ServiceOptions::IsInitialized() const {
-
- for (int i = 0; i < uninterpreted_option_size(); i++) {
- if (!this->uninterpreted_option(i).IsInitialized()) return false;
- }
-
- if (!_extensions_.IsInitialized()) return false; return true;
-}
-
const ::google::protobuf::Descriptor* ServiceOptions::GetDescriptor() const {
return descriptor();
}
@@ -5697,6 +5697,15 @@ void MethodOptions::CopyFrom(const MethodOptions& from) {
MergeFrom(from);
}
+bool MethodOptions::IsInitialized() const {
+
+ for (int i = 0; i < uninterpreted_option_size(); i++) {
+ if (!this->uninterpreted_option(i).IsInitialized()) return false;
+ }
+
+ if (!_extensions_.IsInitialized()) return false; return true;
+}
+
void MethodOptions::Swap(MethodOptions* other) {
if (other != this) {
uninterpreted_option_.Swap(&other->uninterpreted_option_);
@@ -5707,15 +5716,6 @@ void MethodOptions::Swap(MethodOptions* other) {
}
}
-bool MethodOptions::IsInitialized() const {
-
- for (int i = 0; i < uninterpreted_option_size(); i++) {
- if (!this->uninterpreted_option(i).IsInitialized()) return false;
- }
-
- if (!_extensions_.IsInitialized()) return false; return true;
-}
-
const ::google::protobuf::Descriptor* MethodOptions::GetDescriptor() const {
return descriptor();
}
@@ -5945,6 +5945,12 @@ void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart&
MergeFrom(from);
}
+bool UninterpretedOption_NamePart::IsInitialized() const {
+ if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
+
+ return true;
+}
+
void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) {
if (other != this) {
std::swap(name_part_, other->name_part_);
@@ -5955,12 +5961,6 @@ void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) {
}
}
-bool UninterpretedOption_NamePart::IsInitialized() const {
- if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
-
- return true;
-}
-
const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::GetDescriptor() const {
return descriptor();
}
@@ -6342,6 +6342,14 @@ void UninterpretedOption::CopyFrom(const UninterpretedOption& from) {
MergeFrom(from);
}
+bool UninterpretedOption::IsInitialized() const {
+
+ for (int i = 0; i < name_size(); i++) {
+ if (!this->name(i).IsInitialized()) return false;
+ }
+ return true;
+}
+
void UninterpretedOption::Swap(UninterpretedOption* other) {
if (other != this) {
name_.Swap(&other->name_);
@@ -6356,14 +6364,6 @@ void UninterpretedOption::Swap(UninterpretedOption* other) {
}
}
-bool UninterpretedOption::IsInitialized() const {
-
- for (int i = 0; i < name_size(); i++) {
- if (!this->name(i).IsInitialized()) return false;
- }
- return true;
-}
-
const ::google::protobuf::Descriptor* UninterpretedOption::GetDescriptor() const {
return descriptor();
}
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index f45eafa5..61b8daae 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -497,6 +497,88 @@ Message* ExtensionSet::AddMessage(int number, FieldType type,
#undef GOOGLE_DCHECK_TYPE
+void ExtensionSet::RemoveLast(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);
+
+ switch(cpp_type(extension->type)) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ extension->repeated_int32_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_INT64:
+ extension->repeated_int64_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ extension->repeated_uint32_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ extension->repeated_uint64_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ extension->repeated_float_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ extension->repeated_double_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ extension->repeated_bool_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ extension->repeated_enum_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_STRING:
+ extension->repeated_string_value->RemoveLast();
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ extension->repeated_message_value->RemoveLast();
+ break;
+ }
+}
+
+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).";
+
+ Extension* extension = &iter->second;
+ GOOGLE_DCHECK(extension->is_repeated);
+
+ switch(cpp_type(extension->type)) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ extension->repeated_int32_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_INT64:
+ extension->repeated_int64_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ extension->repeated_uint32_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ extension->repeated_uint64_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ extension->repeated_float_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ extension->repeated_double_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ extension->repeated_bool_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ extension->repeated_enum_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_STRING:
+ extension->repeated_string_value->SwapElements(index1, index2);
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ extension->repeated_message_value->SwapElements(index1, index2);
+ break;
+ }
+}
+
// ===================================================================
void ExtensionSet::Clear() {
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index a99b17cb..e04614cc 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -228,6 +228,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const Descriptor* message_type,
MessageFactory* factory);
+ void RemoveLast(int number);
+ void SwapElements(int number, int index1, int index2);
+
// -----------------------------------------------------------------
// TODO(kenton): Hardcore memory management accessors
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index ffeaf62d..0cd367de 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -269,6 +269,61 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
return total_size;
}
+void GeneratedMessageReflection::Swap(
+ Message* message1,
+ Message* message2) const {
+ if (message1 == message2) return;
+
+ GOOGLE_CHECK_EQ(message1->GetReflection(), this)
+ << "Tried to swap using reflection object incompatible with message1.";
+
+ GOOGLE_CHECK_EQ(message2->GetReflection(), this)
+ << "Tried to swap using reflection object incompatible with message2.";
+
+ uint32* has_bits1 = MutableHasBits(message1);
+ uint32* has_bits2 = MutableHasBits(message2);
+ int has_bits_size = (descriptor_->field_count() + 31) / 32;
+
+ for (int i = 0; i < has_bits_size; i++) {
+ std::swap(has_bits1[i], has_bits2[i]);
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->is_repeated()) {
+ MutableRaw<GenericRepeatedField>(message1, field)->GenericSwap(
+ MutableRaw<GenericRepeatedField>(message2, field));
+ } else {
+ switch (field->cpp_type()) {
+#define SWAP_VALUES(CPPTYPE, TYPE) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ swap(*MutableRaw<TYPE>(message1, field), \
+ *MutableRaw<TYPE>(message2, field)); \
+ break;
+ SWAP_VALUES(INT32 , int32 );
+ SWAP_VALUES(INT64 , int64 );
+ SWAP_VALUES(UINT32, uint32);
+ SWAP_VALUES(UINT64, uint64);
+ SWAP_VALUES(FLOAT , float );
+ SWAP_VALUES(DOUBLE, double);
+ SWAP_VALUES(BOOL , bool );
+ SWAP_VALUES(ENUM , int32 );
+ SWAP_VALUES(STRING, string*);
+ SWAP_VALUES(MESSAGE, Message*);
+#undef SWAP_PRIMITIVE_VALUES
+ default:
+ GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+ }
+ }
+ }
+
+ if (extensions_offset_ != -1) {
+ MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2));
+ }
+
+ MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
+}
+
// -------------------------------------------------------------------
bool GeneratedMessageReflection::HasField(const Message& message,
@@ -285,8 +340,8 @@ bool GeneratedMessageReflection::HasField(const Message& message,
int GeneratedMessageReflection::FieldSize(const Message& message,
const FieldDescriptor* field) const {
- USAGE_CHECK_MESSAGE_TYPE(HasField);
- USAGE_CHECK_REPEATED(HasField);
+ USAGE_CHECK_MESSAGE_TYPE(FieldSize);
+ USAGE_CHECK_REPEATED(FieldSize);
if (field->is_extension()) {
return GetExtensionSet(message).ExtensionSize(field->number());
@@ -350,6 +405,36 @@ void GeneratedMessageReflection::ClearField(
}
}
+void GeneratedMessageReflection::RemoveLast(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK_MESSAGE_TYPE(RemoveLast);
+ USAGE_CHECK_REPEATED(RemoveLast);
+
+ if (field->is_extension()) {
+ MutableExtensionSet(message)->RemoveLast(field->number());
+ } else {
+ MutableRaw<GenericRepeatedField>(message, field)->GenericRemoveLast();
+ }
+}
+
+void GeneratedMessageReflection::SwapElements(
+ Message* message,
+ const FieldDescriptor* field,
+ int index1,
+ int index2) const {
+ USAGE_CHECK_MESSAGE_TYPE(Swap);
+ USAGE_CHECK_REPEATED(Swap);
+
+ if (field->is_extension()) {
+ MutableExtensionSet(message)->SwapElements(
+ field->number(), index1, index2);
+ } else {
+ MutableRaw<GenericRepeatedField>(message, field)->GenericSwapElements(
+ index1, index2);
+ }
+}
+
namespace {
// Comparison functor for sorting FieldDescriptors by field number.
struct FieldNumberSorter {
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 66f8c474..702f189e 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -140,6 +140,10 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
bool HasField(const Message& message, const FieldDescriptor* field) const;
int FieldSize(const Message& message, const FieldDescriptor* field) const;
void ClearField(Message* message, const FieldDescriptor* field) const;
+ void RemoveLast(Message* message, const FieldDescriptor* field) const;
+ void Swap(Message* message1, Message* message2) const;
+ void SwapElements(Message* message, const FieldDescriptor* field,
+ int index1, int index2) const;
void ListFields(const Message& message,
vector<const FieldDescriptor*>* output) const;
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index 8e4ae96f..a03bcdb7 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -146,6 +146,122 @@ TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) {
&reflection->GetMessage(message, F("optional_import_message")));
}
+
+TEST(GeneratedMessageReflectionTest, Swap) {
+ unittest::TestAllTypes message1;
+ unittest::TestAllTypes message2;
+
+ TestUtil::SetAllFields(&message1);
+
+ const Reflection* reflection = message1.GetReflection();
+ reflection->Swap(&message1, &message2);
+
+ TestUtil::ExpectClear(message1);
+ TestUtil::ExpectAllFieldsSet(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapWithBothSet) {
+ unittest::TestAllTypes message1;
+ unittest::TestAllTypes message2;
+
+ TestUtil::SetAllFields(&message1);
+ TestUtil::SetAllFields(&message2);
+ TestUtil::ModifyRepeatedFields(&message2);
+
+ const Reflection* reflection = message1.GetReflection();
+ reflection->Swap(&message1, &message2);
+
+ TestUtil::ExpectRepeatedFieldsModified(message1);
+ TestUtil::ExpectAllFieldsSet(message2);
+
+ message1.set_optional_int32(532819);
+
+ reflection->Swap(&message1, &message2);
+
+ EXPECT_EQ(532819, message2.optional_int32());
+}
+
+TEST(GeneratedMessageReflectionTest, SwapExtensions) {
+ unittest::TestAllExtensions message1;
+ unittest::TestAllExtensions message2;
+
+ TestUtil::SetAllExtensions(&message1);
+
+ const Reflection* reflection = message1.GetReflection();
+ reflection->Swap(&message1, &message2);
+
+ TestUtil::ExpectExtensionsClear(message1);
+ TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapUnknown) {
+ unittest::TestEmptyMessage message1, message2;
+
+ message1.mutable_unknown_fields()->AddVarint(1234, 1);
+
+ EXPECT_EQ(1, message1.unknown_fields().field_count());
+ EXPECT_EQ(0, message2.unknown_fields().field_count());
+ const Reflection* reflection = message1.GetReflection();
+ reflection->Swap(&message1, &message2);
+ EXPECT_EQ(0, message1.unknown_fields().field_count());
+ EXPECT_EQ(1, message2.unknown_fields().field_count());
+}
+
+TEST(GeneratedMessageReflectionTest, RemoveLast) {
+ unittest::TestAllTypes message;
+ TestUtil::ReflectionTester reflection_tester(
+ unittest::TestAllTypes::descriptor());
+
+ TestUtil::SetAllFields(&message);
+
+ reflection_tester.RemoveLastRepeatedsViaReflection(&message);
+
+ TestUtil::ExpectLastRepeatedsRemoved(message);
+}
+
+TEST(GeneratedMessageReflectionTest, RemoveLastExtensions) {
+ unittest::TestAllExtensions message;
+ TestUtil::ReflectionTester reflection_tester(
+ unittest::TestAllExtensions::descriptor());
+
+ TestUtil::SetAllExtensions(&message);
+ reflection_tester.RemoveLastRepeatedsViaReflection(&message);
+
+ TestUtil::ExpectLastRepeatedExtensionsRemoved(message);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) {
+ unittest::TestAllTypes message;
+ TestUtil::ReflectionTester reflection_tester(
+ unittest::TestAllTypes::descriptor());
+
+ TestUtil::SetAllFields(&message);
+
+ // Swap and test that fields are all swapped.
+ reflection_tester.SwapRepeatedsViaReflection(&message);
+ TestUtil::ExpectRepeatedsSwapped(message);
+
+ // Swap back and test that fields are all back to original values.
+ reflection_tester.SwapRepeatedsViaReflection(&message);
+ TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GeneratedMessageReflectionTest, SwapRepeatedElementsExtension) {
+ unittest::TestAllExtensions message;
+ TestUtil::ReflectionTester reflection_tester(
+ unittest::TestAllExtensions::descriptor());
+
+ TestUtil::SetAllExtensions(&message);
+
+ // Swap and test that fields are all swapped.
+ reflection_tester.SwapRepeatedsViaReflection(&message);
+ TestUtil::ExpectRepeatedExtensionsSwapped(message);
+
+ // Swap back and test that fields are all back to original values.
+ reflection_tester.SwapRepeatedsViaReflection(&message);
+ TestUtil::ExpectAllExtensionsSet(message);
+}
+
TEST(GeneratedMessageReflectionTest, Extensions) {
// Set every extension to a unique value then go back and check all those
// values.
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index b05ea954..0f0ef887 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -97,7 +97,7 @@
// // Use the reflection interface to examine the contents.
// const Reflection* reflection = foo->GetReflection();
// assert(reflection->GetString(foo, text_field) == "Hello World!");
-// assert(reflection->CountField(foo, numbers_field) == 3);
+// assert(reflection->FieldSize(foo, numbers_field) == 3);
// assert(reflection->GetInt32(foo, numbers_field, 0) == 1);
// assert(reflection->GetInt32(foo, numbers_field, 1) == 5);
// assert(reflection->GetInt32(foo, numbers_field, 2) == 42);
@@ -494,6 +494,25 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void ClearField(Message* message,
const FieldDescriptor* field) const = 0;
+ // Remove the last element of a repeated field.
+ // We don't provide a way to remove any element other than the last
+ // because it invites inefficient use, such as O(n^2) filtering loops
+ // that should have been O(n). If you want to remove an element other
+ // than the last, the best way to do it is to re-arrange the elements
+ // (using Swap()) so that the one you want removed is at the end, then
+ // call RemoveLast().
+ virtual void RemoveLast(Message* message,
+ const FieldDescriptor* field) const = 0;
+
+ // Swap the complete contents of two messages.
+ virtual void Swap(Message* message1, Message* message2) const = 0;
+
+ // Swap two elements of a repeated field.
+ virtual void SwapElements(Message* message,
+ const FieldDescriptor* field,
+ int index1,
+ int index2) const = 0;
+
// List all fields of the message which are currently set. This includes
// extensions. Singular fields will only be listed if HasField(field) would
// return true and repeated fields will only be listed if FieldSize(field)
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index e12224fb..4446eaf7 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -86,6 +86,9 @@ class LIBPROTOBUF_EXPORT GenericRepeatedField {
virtual void* GenericMutable(int index) = 0;
virtual void* GenericAdd() = 0;
virtual void GenericClear() = 0;
+ virtual void GenericRemoveLast() = 0;
+ virtual void GenericSwap(GenericRepeatedField *other) = 0;
+ virtual void GenericSwapElements(int index1, int index2) = 0;
virtual int GenericSize() const = 0;
virtual int GenericSpaceUsedExcludingSelf() const = 0;
@@ -135,6 +138,9 @@ class RepeatedField : public internal::GenericRepeatedField {
// Swap entire contents with "other".
void Swap(RepeatedField* other);
+ // Swap two elements of a repeated field.
+ void SwapElements(int index1, int index2);
+
// STL-like iterator support
typedef Element* iterator;
typedef const Element* const_iterator;
@@ -154,6 +160,9 @@ class RepeatedField : public internal::GenericRepeatedField {
void* GenericMutable(int index);
void* GenericAdd();
void GenericClear();
+ void GenericRemoveLast();
+ void GenericSwap(GenericRepeatedField *other);
+ void GenericSwapElements(int index1, int index2);
int GenericSize() const;
int GenericSpaceUsedExcludingSelf() const;
@@ -214,6 +223,9 @@ class RepeatedPtrField : public internal::GenericRepeatedField {
// Swap entire contents with "other".
void Swap(RepeatedPtrField* other);
+ // Swap two elements of a repeated field.
+ void SwapElements(int index1, int index2);
+
// STL-like iterator support
typedef internal::RepeatedPtrIterator<Element**> iterator;
typedef internal::RepeatedPtrIterator<const Element* const*> const_iterator;
@@ -266,6 +278,9 @@ class RepeatedPtrField : public internal::GenericRepeatedField {
void* GenericMutable(int index);
void* GenericAdd();
void GenericClear();
+ void GenericRemoveLast();
+ void GenericSwap(GenericRepeatedField *other);
+ void GenericSwapElements(int index1, int index2);
int GenericSize() const;
int GenericSpaceUsedExcludingSelf() const;
@@ -396,6 +411,11 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
}
template <typename Element>
+void RepeatedField<Element>::SwapElements(int index1, int index2) {
+ swap(*Mutable(index1), *Mutable(index2));
+}
+
+template <typename Element>
inline typename RepeatedField<Element>::iterator
RepeatedField<Element>::begin() {
return elements_;
@@ -444,6 +464,21 @@ void RepeatedField<Element>::GenericClear() {
}
template <typename Element>
+void RepeatedField<Element>::GenericRemoveLast() {
+ RemoveLast();
+}
+
+template <typename Element>
+void RepeatedField<Element>::GenericSwap(GenericRepeatedField *other) {
+ Swap(down_cast<RepeatedField<Element>*>(other));
+}
+
+template <typename Element>
+void RepeatedField<Element>::GenericSwapElements(int index1, int index2) {
+ SwapElements(index1, index2);
+}
+
+template <typename Element>
int RepeatedField<Element>::GenericSize() const {
return size();
}
@@ -623,6 +658,11 @@ void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
}
template <typename Element>
+void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
+ swap(elements_[index1], elements_[index2]);
+}
+
+template <typename Element>
inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
int allocated_bytes =
(elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
@@ -708,6 +748,21 @@ void RepeatedPtrField<Element>::GenericClear() {
}
template <typename Element>
+void RepeatedPtrField<Element>::GenericRemoveLast() {
+ RemoveLast();
+}
+
+template <typename Element>
+void RepeatedPtrField<Element>::GenericSwap(GenericRepeatedField *other) {
+ Swap(down_cast<RepeatedPtrField<Element>*>(other));
+}
+
+template <typename Element>
+void RepeatedPtrField<Element>::GenericSwapElements(int index1, int index2) {
+ SwapElements(index1, index2);
+}
+
+template <typename Element>
int RepeatedPtrField<Element>::GenericSize() const {
return size();
}
@@ -736,7 +791,7 @@ inline Element* RepeatedPtrField<Element>::NewElement() {
return new Element;
}
-// RepeatedPtrField<Message> is alowed but requires a prototype since Message
+// RepeatedPtrField<Message> is allowed but requires a prototype since Message
// is abstract.
template <>
inline Message* RepeatedPtrField<Message>::NewElement() {
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index 7cf5cc2f..e3e67f67 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -1644,6 +1644,295 @@ void TestUtil::ExpectAllFieldsAndExtensionsInOrder(const string& serialized) {
EXPECT_TRUE(serialized == expected);
}
+void TestUtil::ExpectLastRepeatedsRemoved(
+ const unittest::TestAllTypes& message) {
+ ASSERT_EQ(1, message.repeated_int32_size ());
+ ASSERT_EQ(1, message.repeated_int64_size ());
+ ASSERT_EQ(1, message.repeated_uint32_size ());
+ ASSERT_EQ(1, message.repeated_uint64_size ());
+ ASSERT_EQ(1, message.repeated_sint32_size ());
+ ASSERT_EQ(1, message.repeated_sint64_size ());
+ ASSERT_EQ(1, message.repeated_fixed32_size ());
+ ASSERT_EQ(1, message.repeated_fixed64_size ());
+ ASSERT_EQ(1, message.repeated_sfixed32_size());
+ ASSERT_EQ(1, message.repeated_sfixed64_size());
+ ASSERT_EQ(1, message.repeated_float_size ());
+ ASSERT_EQ(1, message.repeated_double_size ());
+ ASSERT_EQ(1, message.repeated_bool_size ());
+ ASSERT_EQ(1, message.repeated_string_size ());
+ ASSERT_EQ(1, message.repeated_bytes_size ());
+
+ ASSERT_EQ(1, message.repeatedgroup_size ());
+ ASSERT_EQ(1, message.repeated_nested_message_size ());
+ ASSERT_EQ(1, message.repeated_foreign_message_size());
+ ASSERT_EQ(1, message.repeated_import_message_size ());
+ ASSERT_EQ(1, message.repeated_nested_enum_size ());
+ ASSERT_EQ(1, message.repeated_foreign_enum_size ());
+ ASSERT_EQ(1, message.repeated_import_enum_size ());
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+ ASSERT_EQ(1, message.repeated_string_piece_size());
+ ASSERT_EQ(1, message.repeated_cord_size());
+#endif
+
+ // Test that the remaining element is the correct one.
+ EXPECT_EQ(201 , message.repeated_int32 (0));
+ EXPECT_EQ(202 , message.repeated_int64 (0));
+ EXPECT_EQ(203 , message.repeated_uint32 (0));
+ EXPECT_EQ(204 , message.repeated_uint64 (0));
+ EXPECT_EQ(205 , message.repeated_sint32 (0));
+ EXPECT_EQ(206 , message.repeated_sint64 (0));
+ EXPECT_EQ(207 , message.repeated_fixed32 (0));
+ EXPECT_EQ(208 , message.repeated_fixed64 (0));
+ EXPECT_EQ(209 , message.repeated_sfixed32(0));
+ EXPECT_EQ(210 , message.repeated_sfixed64(0));
+ EXPECT_EQ(211 , message.repeated_float (0));
+ EXPECT_EQ(212 , message.repeated_double (0));
+ EXPECT_EQ(true , message.repeated_bool (0));
+ EXPECT_EQ("215", message.repeated_string (0));
+ EXPECT_EQ("216", message.repeated_bytes (0));
+
+ EXPECT_EQ(217, message.repeatedgroup (0).a());
+ EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+ EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+ EXPECT_EQ(220, message.repeated_import_message (0).d());
+
+ EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
+ EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0));
+ EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (0));
+}
+
+void TestUtil::ExpectLastRepeatedExtensionsRemoved(
+ const unittest::TestAllExtensions& message) {
+
+ // Test that one element was removed.
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_int32_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_int64_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_uint32_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_uint64_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sint32_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sint64_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_fixed32_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_fixed64_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sfixed32_extension));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sfixed64_extension));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_float_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_double_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_bool_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_bytes_extension ));
+
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_enum_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_enum_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_enum_extension ));
+
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_piece_extension));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_cord_extension));
+
+ // Test that the remaining element is the correct one.
+ EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension , 0));
+ EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension , 0));
+ EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension , 0));
+ EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension , 0));
+ EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension , 0));
+ EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension , 0));
+ EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension , 0));
+ EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension , 0));
+ EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension, 0));
+ EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 0));
+ EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 0));
+ EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 0));
+ EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension , 0));
+ EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 0));
+ EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 0));
+
+ EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 0).a());
+ EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+ EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+ EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+
+ EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
+ EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
+ EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 0));
+
+ EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 0));
+ EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0));
+}
+
+void TestUtil::ExpectRepeatedsSwapped(
+ const unittest::TestAllTypes& message) {
+ ASSERT_EQ(2, message.repeated_int32_size ());
+ ASSERT_EQ(2, message.repeated_int64_size ());
+ ASSERT_EQ(2, message.repeated_uint32_size ());
+ ASSERT_EQ(2, message.repeated_uint64_size ());
+ ASSERT_EQ(2, message.repeated_sint32_size ());
+ ASSERT_EQ(2, message.repeated_sint64_size ());
+ ASSERT_EQ(2, message.repeated_fixed32_size ());
+ ASSERT_EQ(2, message.repeated_fixed64_size ());
+ ASSERT_EQ(2, message.repeated_sfixed32_size());
+ ASSERT_EQ(2, message.repeated_sfixed64_size());
+ ASSERT_EQ(2, message.repeated_float_size ());
+ ASSERT_EQ(2, message.repeated_double_size ());
+ ASSERT_EQ(2, message.repeated_bool_size ());
+ ASSERT_EQ(2, message.repeated_string_size ());
+ ASSERT_EQ(2, message.repeated_bytes_size ());
+
+ ASSERT_EQ(2, message.repeatedgroup_size ());
+ ASSERT_EQ(2, message.repeated_nested_message_size ());
+ ASSERT_EQ(2, message.repeated_foreign_message_size());
+ ASSERT_EQ(2, message.repeated_import_message_size ());
+ ASSERT_EQ(2, message.repeated_nested_enum_size ());
+ ASSERT_EQ(2, message.repeated_foreign_enum_size ());
+ ASSERT_EQ(2, message.repeated_import_enum_size ());
+
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+ ASSERT_EQ(2, message.repeated_string_piece_size());
+ ASSERT_EQ(2, message.repeated_cord_size());
+#endif
+
+ // Test that the first element and second element are flipped.
+ EXPECT_EQ(201 , message.repeated_int32 (1));
+ EXPECT_EQ(202 , message.repeated_int64 (1));
+ EXPECT_EQ(203 , message.repeated_uint32 (1));
+ EXPECT_EQ(204 , message.repeated_uint64 (1));
+ EXPECT_EQ(205 , message.repeated_sint32 (1));
+ EXPECT_EQ(206 , message.repeated_sint64 (1));
+ EXPECT_EQ(207 , message.repeated_fixed32 (1));
+ EXPECT_EQ(208 , message.repeated_fixed64 (1));
+ EXPECT_EQ(209 , message.repeated_sfixed32(1));
+ EXPECT_EQ(210 , message.repeated_sfixed64(1));
+ EXPECT_EQ(211 , message.repeated_float (1));
+ EXPECT_EQ(212 , message.repeated_double (1));
+ EXPECT_EQ(true , message.repeated_bool (1));
+ EXPECT_EQ("215", message.repeated_string (1));
+ EXPECT_EQ("216", message.repeated_bytes (1));
+
+ EXPECT_EQ(217, message.repeatedgroup (1).a());
+ EXPECT_EQ(218, message.repeated_nested_message (1).bb());
+ EXPECT_EQ(219, message.repeated_foreign_message(1).c());
+ EXPECT_EQ(220, message.repeated_import_message (1).d());
+
+ EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (1));
+ EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(1));
+ EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (1));
+
+ EXPECT_EQ(301 , message.repeated_int32 (0));
+ EXPECT_EQ(302 , message.repeated_int64 (0));
+ EXPECT_EQ(303 , message.repeated_uint32 (0));
+ EXPECT_EQ(304 , message.repeated_uint64 (0));
+ EXPECT_EQ(305 , message.repeated_sint32 (0));
+ EXPECT_EQ(306 , message.repeated_sint64 (0));
+ EXPECT_EQ(307 , message.repeated_fixed32 (0));
+ EXPECT_EQ(308 , message.repeated_fixed64 (0));
+ EXPECT_EQ(309 , message.repeated_sfixed32(0));
+ EXPECT_EQ(310 , message.repeated_sfixed64(0));
+ EXPECT_EQ(311 , message.repeated_float (0));
+ EXPECT_EQ(312 , message.repeated_double (0));
+ EXPECT_EQ(false, message.repeated_bool (0));
+ EXPECT_EQ("315", message.repeated_string (0));
+ EXPECT_EQ("316", message.repeated_bytes (0));
+
+ EXPECT_EQ(317, message.repeatedgroup (0).a());
+ EXPECT_EQ(318, message.repeated_nested_message (0).bb());
+ EXPECT_EQ(319, message.repeated_foreign_message(0).c());
+ EXPECT_EQ(320, message.repeated_import_message (0).d());
+
+ EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (0));
+ EXPECT_EQ(unittest::FOREIGN_BAZ , message.repeated_foreign_enum(0));
+ EXPECT_EQ(unittest_import::IMPORT_BAZ, message.repeated_import_enum (0));
+}
+
+void TestUtil::ExpectRepeatedExtensionsSwapped(
+ const unittest::TestAllExtensions& message) {
+
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension ));
+
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension ));
+
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_piece_extension));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_cord_extension));
+
+ EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension , 1));
+ EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension , 1));
+ EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension , 1));
+ EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension , 1));
+ EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension , 1));
+ EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension , 1));
+ EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension , 1));
+ EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension , 1));
+ EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension, 1));
+ EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 1));
+ EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 1));
+ EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 1));
+ EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension , 1));
+ EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 1));
+ EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 1));
+
+ EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 1).a());
+ EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
+ EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
+ EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+
+ EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
+ EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
+ EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 1));
+
+ EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 1));
+ EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 1));
+
+ EXPECT_EQ(301 , message.GetExtension(unittest::repeated_int32_extension , 0));
+ EXPECT_EQ(302 , message.GetExtension(unittest::repeated_int64_extension , 0));
+ EXPECT_EQ(303 , message.GetExtension(unittest::repeated_uint32_extension , 0));
+ EXPECT_EQ(304 , message.GetExtension(unittest::repeated_uint64_extension , 0));
+ EXPECT_EQ(305 , message.GetExtension(unittest::repeated_sint32_extension , 0));
+ EXPECT_EQ(306 , message.GetExtension(unittest::repeated_sint64_extension , 0));
+ EXPECT_EQ(307 , message.GetExtension(unittest::repeated_fixed32_extension , 0));
+ EXPECT_EQ(308 , message.GetExtension(unittest::repeated_fixed64_extension , 0));
+ EXPECT_EQ(309 , message.GetExtension(unittest::repeated_sfixed32_extension, 0));
+ EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension, 0));
+ EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension , 0));
+ EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension , 0));
+ EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension , 0));
+ EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension , 0));
+ EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension , 0));
+
+ EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension , 0).a());
+ EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+ EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+ EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+
+ EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
+ EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
+ EXPECT_EQ(unittest_import::IMPORT_BAZ, message.GetExtension(unittest::repeated_import_enum_extension , 0));
+
+ EXPECT_EQ("324", message.GetExtension(unittest::repeated_string_piece_extension, 0));
+ EXPECT_EQ("325", message.GetExtension(unittest::repeated_cord_extension, 0));
+}
+
// ===================================================================
TestUtil::ReflectionTester::ReflectionTester(
@@ -2451,5 +2740,31 @@ void TestUtil::ReflectionTester::ModifyPackedFieldsViaReflection(
reflection->SetRepeatedEnum (message, F("packed_enum" ), 1, foreign_foo_);
}
+void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(Message* message) {
+ const Reflection* reflection = message->GetReflection();
+
+ vector<const FieldDescriptor*> output;
+ reflection->ListFields(*message, &output);
+ for (int i=0; i<output.size(); ++i) {
+ const FieldDescriptor* field = output[i];
+ if (!field->is_repeated()) continue;
+
+ reflection->RemoveLast(message, field);
+ }
+}
+
+void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) {
+ const Reflection* reflection = message->GetReflection();
+
+ vector<const FieldDescriptor*> output;
+ reflection->ListFields(*message, &output);
+ for (int i=0; i<output.size(); ++i) {
+ const FieldDescriptor* field = output[i];
+ if (!field->is_repeated()) continue;
+
+ reflection->SwapElements(message, field, 0, 1);
+ }
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index 1bedb788..e581f419 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -96,6 +96,17 @@ class TestUtil {
// SetAllFieldsAndExtensions().
static void ExpectAllFieldsAndExtensionsInOrder(const string& serialized);
+ // Check that all repeated fields have had their last elements removed.
+ static void ExpectLastRepeatedsRemoved(
+ const unittest::TestAllTypes& message);
+ static void ExpectLastRepeatedExtensionsRemoved(
+ const unittest::TestAllExtensions& message);
+
+ // Check that all repeated fields have had their first and last elements swapped.
+ static void ExpectRepeatedsSwapped(const unittest::TestAllTypes& message);
+ static void ExpectRepeatedExtensionsSwapped(
+ const unittest::TestAllExtensions& message);
+
// Like above, but use the reflection interface.
class ReflectionTester {
public:
@@ -116,6 +127,9 @@ class TestUtil {
void ExpectPackedFieldsSetViaReflection(const Message& message);
void ExpectPackedClearViaReflection(const Message& message);
+ void RemoveLastRepeatedsViaReflection(Message* message);
+ void SwapRepeatedsViaReflection(Message* message);
+
private:
const FieldDescriptor* F(const string& name);