summaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/cpp/cpp_message.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/cpp/cpp_message.cc')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc99
1 files changed, 70 insertions, 29 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 4967b898..27c9156e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -1,18 +1,32 @@
// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.
+// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
@@ -393,10 +407,6 @@ GenerateClassDefinition(io::Printer* printer) {
" return *this;\n"
"}\n"
"\n"
- "inline static const $classname$& default_instance() {\n"
- " return default_instance_;\n"
- "}\n"
- "\n"
"inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
" return _unknown_fields_;\n"
"}\n"
@@ -406,6 +416,7 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"\n"
"static const ::google::protobuf::Descriptor* descriptor();\n"
+ "static const $classname$& default_instance();"
"\n"
"// implements Message ----------------------------------------------\n"
"\n"
@@ -492,8 +503,8 @@ GenerateClassDefinition(io::Printer* printer) {
// Generate offsets and _has_bits_ boilerplate.
printer->Print(vars,
- "friend void $builddescriptorsname$();\n"
- "static const $classname$ default_instance_;\n");
+ "friend void $builddescriptorsname$_AssignGlobalDescriptors(\n"
+ " const ::google::protobuf::FileDescriptor* file);\n");
if (descriptor_->field_count() > 0) {
printer->Print(vars,
@@ -522,7 +533,11 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"inline void _clear_bit(int index) {\n"
" _has_bits_[index / 32] &= ~(1u << (index % 32));\n"
- "}\n");
+ "}\n"
+ "\n"
+ "void InitAsDefaultInstance();\n"
+ "static $classname$* default_instance_;\n",
+ "classname", classname_);
printer->Outdent();
printer->Print(vars, "};");
@@ -577,12 +592,18 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
"$parent$_descriptor_->nested_type($index$);\n");
}
+ // Construct the default instance. We can't call InitAsDefaultInstance() yet
+ // because we need to make sure all default instances that this one might
+ // depend on are constructed first.
+ printer->Print(vars,
+ "$classname$::default_instance_ = new $classname$();\n");
+
// Construct the reflection object.
printer->Print(vars,
"$classname$_reflection_ =\n"
" new ::google::protobuf::internal::GeneratedMessageReflection(\n"
" $classname$_descriptor_,\n"
- " &$classname$::default_instance(),\n"
+ " $classname$::default_instance_,\n"
" $classname$::_offsets_,\n"
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n"
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
@@ -611,7 +632,19 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
// Register this message type with the message factory.
printer->Print(vars,
"::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
- " $classname$_descriptor_, &$classname$::default_instance());\n");
+ " $classname$_descriptor_, $classname$::default_instance_);\n");
+}
+
+void MessageGenerator::
+GenerateDefaultInstanceInitializer(io::Printer* printer) {
+ printer->Print(
+ "$classname$::default_instance_->InitAsDefaultInstance();\n",
+ "classname", classname_);
+
+ // Handle nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
+ }
}
void MessageGenerator::
@@ -627,11 +660,6 @@ GenerateClassMethods(io::Printer* printer) {
printer->Print("\n");
}
- printer->Print(
- "const $classname$ $classname$::default_instance_;\n"
- "\n",
- "classname", classname_);
-
// Generate non-inline field definitions.
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i))
@@ -746,10 +774,17 @@ GenerateStructors(io::Printer* printer) {
GenerateInitializerList(printer);
printer->Print(" {\n"
" ::memset(_has_bits_, 0, sizeof(_has_bits_));\n"
- " if (this == &default_instance_) {\n");
+ "}\n");
+
+ printer->Print(
+ "\n"
+ "void $classname$::InitAsDefaultInstance() {",
+ "classname", classname_);
// The default instance needs all of its embedded message pointers
- // cross-linked to other default instances.
+ // cross-linked to other default instances. We can't do this initialization
+ // in the constructor because some other default instances may not have been
+ // constructed yet at that time.
// TODO(kenton): Maybe all message fields (even for non-default messages)
// should be initialized to point at default instances rather than NULL?
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -758,13 +793,12 @@ GenerateStructors(io::Printer* printer) {
if (!field->is_repeated() &&
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
printer->Print(
- " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
+ " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
"name", FieldName(field),
"type", ClassName(field->message_type(), true));
}
}
printer->Print(
- " }\n"
"}\n"
"\n");
@@ -794,7 +828,7 @@ GenerateStructors(io::Printer* printer) {
}
printer->Print(
- "if (this != &default_instance_) {\n");
+ "if (this != default_instance_) {\n");
// We need to delete all embedded messages.
// TODO(kenton): If we make unset messages point at default instances
@@ -821,6 +855,13 @@ GenerateStructors(io::Printer* printer) {
" return $classname$_descriptor_;\n"
"}\n"
"\n"
+ "const $classname$& $classname$::default_instance() {\n"
+ " if (default_instance_ == NULL) $builddescriptorsname$();\n"
+ " return *default_instance_;\n"
+ "}\n"
+ "\n"
+ "$classname$* $classname$::default_instance_ = NULL;\n"
+ "\n"
"$classname$* $classname$::New() const {\n"
" return new $classname$;\n"
"}\n",