aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/cpp/cpp_message.cc
diff options
context:
space:
mode:
authorkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2008-11-21 00:06:27 +0000
committerkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2008-11-21 00:06:27 +0000
commit26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45 (patch)
treed35cca89e0da44f136090a554ff9abc93a794fa8 /src/google/protobuf/compiler/cpp/cpp_message.cc
parenta2a32c20434807e9966e3f48375f9419134d1b55 (diff)
downloadprotobuf-26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45.tar.gz
protobuf-26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45.tar.bz2
protobuf-26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45.zip
Integrate changes from internal code.
protoc * Enum values may now have custom options, using syntax similar to field options. * Fixed bug where .proto files which use custom options but don't actually define them (i.e. they import another .proto file defining the options) had to explicitly import descriptor.proto. * Adjacent string literals in .proto files will now be concatenated, like in C. C++ * Generated message classes now have a Swap() method which efficiently swaps the contents of two objects. * All message classes now have a SpaceUsed() method which returns an estimate of the number of bytes of allocated memory currently owned by the object. This is particularly useful when you are reusing a single message object to improve performance but want to make sure it doesn't bloat up too large. * New method Message::SerializeAsString() returns a string containing the serialized data. May be more convenient than calling SerializeToString(string*). * In debug mode, log error messages when string-type fields are found to contain bytes that are not valid UTF-8. * Fixed bug where a message with multiple extension ranges couldn't parse extensions. * Fixed bug where MergeFrom(const Message&) didn't do anything if invoked on a message that contained no fields (but possibly contained extensions). * Fixed ShortDebugString() to not be O(n^2). Durr. * Fixed crash in TextFormat parsing if the first token in the input caused a tokenization error. Java * New overload of mergeFrom() which parses a slice of a byte array instead of the whole thing. * New method ByteString.asReadOnlyByteBuffer() does what it sounds like. * Improved performance of isInitialized() when optimizing for code size. Python * Corrected ListFields() signature in Message base class to match what subclasses actually implement. * Some minor refactoring.
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_message.cc')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc72
1 files changed, 53 insertions, 19 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index f3fd48d1..eacceeaf 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -416,7 +416,8 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"\n"
"static const ::google::protobuf::Descriptor* descriptor();\n"
- "static const $classname$& default_instance();"
+ "static const $classname$& default_instance();\n"
+ "void Swap($classname$* other);\n"
"\n"
"// implements Message ----------------------------------------------\n"
"\n"
@@ -617,7 +618,8 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
" -1,\n");
}
printer->Print(vars,
- " ::google::protobuf::DescriptorPool::generated_pool());\n");
+ " ::google::protobuf::DescriptorPool::generated_pool(),\n"
+ " sizeof($classname$));\n");
// Handle nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -693,6 +695,9 @@ GenerateClassMethods(io::Printer* printer) {
GenerateCopyFrom(printer);
printer->Print("\n");
+ GenerateSwap(printer);
+ printer->Print("\n");
+
GenerateIsInitialized(printer);
printer->Print("\n");
}
@@ -947,6 +952,37 @@ GenerateClear(io::Printer* printer) {
}
void MessageGenerator::
+GenerateSwap(io::Printer* printer) {
+ // Generate the Swap member function.
+ printer->Print("void $classname$::Swap($classname$* other) {\n",
+ "classname", classname_);
+ printer->Indent();
+ 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);
+ }
+
+ 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->Outdent();
+ printer->Print("}\n");
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void MessageGenerator::
GenerateMergeFrom(io::Printer* printer) {
// Generate the generalized MergeFrom (aka that which takes in the Message
// base class as a parameter).
@@ -956,22 +992,20 @@ GenerateMergeFrom(io::Printer* printer) {
"classname", classname_);
printer->Indent();
- if (descriptor_->field_count() > 0) {
- // Cast the message to the proper type. If we find that the message is
- // *not* of the proper type, we can still call Merge via the reflection
- // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
- // for each message.
- printer->Print(
- "const $classname$* source =\n"
- " ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
- " &from);\n"
- "if (source == NULL) {\n"
- " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
- "} else {\n"
- " MergeFrom(*source);\n"
- "}\n",
- "classname", classname_);
- }
+ // Cast the message to the proper type. If we find that the message is
+ // *not* of the proper type, we can still call Merge via the reflection
+ // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
+ // for each message.
+ printer->Print(
+ "const $classname$* source =\n"
+ " ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
+ " &from);\n"
+ "if (source == NULL) {\n"
+ " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
+ "} else {\n"
+ " MergeFrom(*source);\n"
+ "}\n",
+ "classname", classname_);
printer->Outdent();
printer->Print("}\n\n");
@@ -1199,7 +1233,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
for (int i = 0; i < descriptor_->extension_range_count(); i++) {
const Descriptor::ExtensionRange* range =
descriptor_->extension_range(i);
- if (i > 0) printer->Print(" &&\n ");
+ if (i > 0) printer->Print(" ||\n ");
uint32 start_tag = WireFormat::MakeTag(
range->start, static_cast<WireFormat::WireType>(0));