blob: bafa36f56d0743f33a87854bfef2703b55ec45cf [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <algorithm>
36#include <google/protobuf/stubs/hash.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000037#include <map>
jieluo@google.com4de8f552014-07-18 00:47:59 +000038#include <memory>
Feng Xiao6ef984a2014-11-10 17:34:54 -080039#ifndef _SHARED_PTR_H
40#include <google/protobuf/stubs/shared_ptr.h>
41#endif
jieluo@google.com4de8f552014-07-18 00:47:59 +000042#include <set>
liujisi@google.com33165fe2010-11-02 13:14:58 +000043#include <utility>
kenton@google.com80b1d622009-07-29 01:13:20 +000044#include <vector>
temporal40ee5512008-07-10 02:12:20 +000045#include <google/protobuf/compiler/cpp/cpp_message.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000046#include <google/protobuf/compiler/cpp/cpp_field.h>
temporal40ee5512008-07-10 02:12:20 +000047#include <google/protobuf/compiler/cpp/cpp_enum.h>
48#include <google/protobuf/compiler/cpp/cpp_extension.h>
49#include <google/protobuf/compiler/cpp/cpp_helpers.h>
50#include <google/protobuf/stubs/strutil.h>
51#include <google/protobuf/io/printer.h>
52#include <google/protobuf/io/coded_stream.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000053#include <google/protobuf/wire_format.h>
temporal40ee5512008-07-10 02:12:20 +000054#include <google/protobuf/descriptor.pb.h>
55
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000056
temporal40ee5512008-07-10 02:12:20 +000057namespace google {
58namespace protobuf {
59namespace compiler {
60namespace cpp {
61
62using internal::WireFormat;
kenton@google.com80b1d622009-07-29 01:13:20 +000063using internal::WireFormatLite;
temporal40ee5512008-07-10 02:12:20 +000064
65namespace {
66
67void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
68 // Print the field's proto-syntax definition as a comment. We don't want to
69 // print group bodies so we cut off after the first line.
70 string def = field->DebugString();
71 printer->Print("// $def$\n",
72 "def", def.substr(0, def.find_first_of('\n')));
73}
74
75struct FieldOrderingByNumber {
76 inline bool operator()(const FieldDescriptor* a,
77 const FieldDescriptor* b) const {
78 return a->number() < b->number();
79 }
80};
81
temporal40ee5512008-07-10 02:12:20 +000082// Sort the fields of the given Descriptor by number into a new[]'d array
83// and return it.
84const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
85 const FieldDescriptor** fields =
86 new const FieldDescriptor*[descriptor->field_count()];
87 for (int i = 0; i < descriptor->field_count(); i++) {
88 fields[i] = descriptor->field(i);
89 }
Jisi Liu885b6122015-02-28 14:51:22 -080090 std::sort(fields, fields + descriptor->field_count(),
91 FieldOrderingByNumber());
temporal40ee5512008-07-10 02:12:20 +000092 return fields;
93}
94
95// Functor for sorting extension ranges by their "start" field number.
96struct ExtensionRangeSorter {
97 bool operator()(const Descriptor::ExtensionRange* left,
98 const Descriptor::ExtensionRange* right) const {
99 return left->start < right->start;
100 }
101};
102
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000103// Returns true if the "required" restriction check should be ignored for the
104// given field.
105inline static bool ShouldIgnoreRequiredFieldCheck(
106 const FieldDescriptor* field) {
107 return false;
108}
109
temporal40ee5512008-07-10 02:12:20 +0000110// Returns true if the message type has any required fields. If it doesn't,
111// we can optimize out calls to its IsInitialized() method.
112//
113// already_seen is used to avoid checking the same type multiple times
114// (and also to protect against recursion).
115static bool HasRequiredFields(
116 const Descriptor* type,
117 hash_set<const Descriptor*>* already_seen) {
118 if (already_seen->count(type) > 0) {
119 // Since the first occurrence of a required field causes the whole
120 // function to return true, we can assume that if the type is already
121 // in the cache it didn't have any required fields.
122 return false;
123 }
124 already_seen->insert(type);
125
126 // If the type has extensions, an extension with message type could contain
127 // required fields, so we have to be conservative and assume such an
128 // extension exists.
129 if (type->extension_range_count() > 0) return true;
130
131 for (int i = 0; i < type->field_count(); i++) {
132 const FieldDescriptor* field = type->field(i);
133 if (field->is_required()) {
134 return true;
135 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000136 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
137 !ShouldIgnoreRequiredFieldCheck(field)) {
temporal40ee5512008-07-10 02:12:20 +0000138 if (HasRequiredFields(field->message_type(), already_seen)) {
139 return true;
140 }
141 }
142 }
143
144 return false;
145}
146
147static bool HasRequiredFields(const Descriptor* type) {
148 hash_set<const Descriptor*> already_seen;
149 return HasRequiredFields(type, &already_seen);
150}
151
liujisi@google.com33165fe2010-11-02 13:14:58 +0000152// This returns an estimate of the compiler's alignment for the field. This
153// can't guarantee to be correct because the generated code could be compiled on
154// different systems with different alignment rules. The estimates below assume
155// 64-bit pointers.
156int EstimateAlignmentSize(const FieldDescriptor* field) {
157 if (field == NULL) return 0;
158 if (field->is_repeated()) return 8;
159 switch (field->cpp_type()) {
160 case FieldDescriptor::CPPTYPE_BOOL:
161 return 1;
162
163 case FieldDescriptor::CPPTYPE_INT32:
164 case FieldDescriptor::CPPTYPE_UINT32:
165 case FieldDescriptor::CPPTYPE_ENUM:
166 case FieldDescriptor::CPPTYPE_FLOAT:
167 return 4;
168
169 case FieldDescriptor::CPPTYPE_INT64:
170 case FieldDescriptor::CPPTYPE_UINT64:
171 case FieldDescriptor::CPPTYPE_DOUBLE:
172 case FieldDescriptor::CPPTYPE_STRING:
173 case FieldDescriptor::CPPTYPE_MESSAGE:
174 return 8;
175 }
176 GOOGLE_LOG(FATAL) << "Can't get here.";
177 return -1; // Make compiler happy.
178}
179
180// FieldGroup is just a helper for OptimizePadding below. It holds a vector of
181// fields that are grouped together because they have compatible alignment, and
182// a preferred location in the final field ordering.
183class FieldGroup {
184 public:
185 FieldGroup()
186 : preferred_location_(0) {}
187
188 // A group with a single field.
189 FieldGroup(float preferred_location, const FieldDescriptor* field)
190 : preferred_location_(preferred_location),
191 fields_(1, field) {}
192
193 // Append the fields in 'other' to this group.
194 void Append(const FieldGroup& other) {
195 if (other.fields_.empty()) {
196 return;
197 }
198 // Preferred location is the average among all the fields, so we weight by
199 // the number of fields on each FieldGroup object.
200 preferred_location_ =
201 (preferred_location_ * fields_.size() +
202 (other.preferred_location_ * other.fields_.size())) /
203 (fields_.size() + other.fields_.size());
204 fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
205 }
206
207 void SetPreferredLocation(float location) { preferred_location_ = location; }
208 const vector<const FieldDescriptor*>& fields() const { return fields_; }
209
210 // FieldGroup objects sort by their preferred location.
211 bool operator<(const FieldGroup& other) const {
212 return preferred_location_ < other.preferred_location_;
213 }
214
215 private:
216 // "preferred_location_" is an estimate of where this group should go in the
217 // final list of fields. We compute this by taking the average index of each
218 // field in this group in the original ordering of fields. This is very
219 // approximate, but should put this group close to where its member fields
220 // originally went.
221 float preferred_location_;
222 vector<const FieldDescriptor*> fields_;
223 // We rely on the default copy constructor and operator= so this type can be
224 // used in a vector.
225};
226
227// Reorder 'fields' so that if the fields are output into a c++ class in the new
228// order, the alignment padding is minimized. We try to do this while keeping
229// each field as close as possible to its original position so that we don't
230// reduce cache locality much for function that access each field in order.
231void OptimizePadding(vector<const FieldDescriptor*>* fields) {
232 // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
233 vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8;
234 for (int i = 0; i < fields->size(); ++i) {
235 switch (EstimateAlignmentSize((*fields)[i])) {
236 case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break;
237 case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break;
238 case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break;
239 default:
240 GOOGLE_LOG(FATAL) << "Unknown alignment size.";
241 }
242 }
243
244 // Now group fields aligned to 1 byte into sets of 4, and treat those like a
245 // single field aligned to 4 bytes.
246 for (int i = 0; i < aligned_to_1.size(); i += 4) {
247 FieldGroup field_group;
248 for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) {
249 field_group.Append(aligned_to_1[j]);
250 }
251 aligned_to_4.push_back(field_group);
252 }
253 // Sort by preferred location to keep fields as close to their original
jieluo@google.com4de8f552014-07-18 00:47:59 +0000254 // location as possible. Using stable_sort ensures that the output is
255 // consistent across runs.
Jisi Liu885b6122015-02-28 14:51:22 -0800256 std::stable_sort(aligned_to_4.begin(), aligned_to_4.end());
liujisi@google.com33165fe2010-11-02 13:14:58 +0000257
258 // Now group fields aligned to 4 bytes (or the 4-field groups created above)
259 // into pairs, and treat those like a single field aligned to 8 bytes.
260 for (int i = 0; i < aligned_to_4.size(); i += 2) {
261 FieldGroup field_group;
262 for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) {
263 field_group.Append(aligned_to_4[j]);
264 }
265 if (i == aligned_to_4.size() - 1) {
266 // Move incomplete 4-byte block to the end.
267 field_group.SetPreferredLocation(fields->size() + 1);
268 }
269 aligned_to_8.push_back(field_group);
270 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000271 // Sort by preferred location.
Jisi Liu885b6122015-02-28 14:51:22 -0800272 std::stable_sort(aligned_to_8.begin(), aligned_to_8.end());
liujisi@google.com33165fe2010-11-02 13:14:58 +0000273
274 // Now pull out all the FieldDescriptors in order.
275 fields->clear();
276 for (int i = 0; i < aligned_to_8.size(); ++i) {
277 fields->insert(fields->end(),
278 aligned_to_8[i].fields().begin(),
279 aligned_to_8[i].fields().end());
280 }
281}
282
Feng Xiao6ef984a2014-11-10 17:34:54 -0800283// Emits an if-statement with a condition that evaluates to true if |field| is
284// considered non-default (will be sent over the wire), for message types
285// without true field presence. Should only be called if
286// !HasFieldPresence(message_descriptor).
287bool EmitFieldNonDefaultCondition(io::Printer* printer,
288 const string& prefix,
289 const FieldDescriptor* field) {
290 // Merge and serialize semantics: primitive fields are merged/serialized only
291 // if non-zero (numeric) or non-empty (string).
292 if (!field->is_repeated() && !field->containing_oneof()) {
293 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
294 printer->Print(
295 "if ($prefix$$name$().size() > 0) {\n",
296 "prefix", prefix,
297 "name", FieldName(field));
298 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
299 // Message fields still have has_$name$() methods.
300 printer->Print(
301 "if ($prefix$has_$name$()) {\n",
302 "prefix", prefix,
303 "name", FieldName(field));
304 } else {
305 printer->Print(
306 "if ($prefix$$name$() != 0) {\n",
307 "prefix", prefix,
308 "name", FieldName(field));
309 }
310 printer->Indent();
311 return true;
312 } else if (field->containing_oneof()) {
313 printer->Print(
314 "if (has_$name$()) {\n",
315 "name", FieldName(field));
316 printer->Indent();
317 return true;
318 }
319 return false;
temporal40ee5512008-07-10 02:12:20 +0000320}
321
Feng Xiao6ef984a2014-11-10 17:34:54 -0800322// Does the given field have a has_$name$() method?
323bool HasHasMethod(const FieldDescriptor* field) {
324 if (HasFieldPresence(field->file())) {
325 // In proto1/proto2, every field has a has_$name$() method.
326 return true;
327 }
328 // For message types without true field presence, only fields with a message
329 // type have a has_$name$() method.
330 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
331}
332
Feng Xiaof157a562014-11-14 11:50:31 -0800333// Collects map entry message type information.
334void CollectMapInfo(const Descriptor* descriptor,
335 map<string, string>* variables) {
336 GOOGLE_CHECK(IsMapEntryMessage(descriptor));
337 const FieldDescriptor* key = descriptor->FindFieldByName("key");
338 const FieldDescriptor* val = descriptor->FindFieldByName("value");
339 (*variables)["key"] = PrimitiveTypeName(key->cpp_type());
340 switch (val->cpp_type()) {
341 case FieldDescriptor::CPPTYPE_MESSAGE:
342 (*variables)["val"] = FieldMessageTypeName(val);
343 break;
344 case FieldDescriptor::CPPTYPE_ENUM:
345 (*variables)["val"] = ClassName(val->enum_type(), false);
346 break;
347 default:
348 (*variables)["val"] = PrimitiveTypeName(val->cpp_type());
349 }
Jisi Liu885b6122015-02-28 14:51:22 -0800350 (*variables)["key_wire_type"] =
351 "::google::protobuf::internal::WireFormatLite::TYPE_" +
Feng Xiaof157a562014-11-14 11:50:31 -0800352 ToUpper(DeclaredTypeMethodName(key->type()));
Jisi Liu885b6122015-02-28 14:51:22 -0800353 (*variables)["val_wire_type"] =
354 "::google::protobuf::internal::WireFormatLite::TYPE_" +
Feng Xiaof157a562014-11-14 11:50:31 -0800355 ToUpper(DeclaredTypeMethodName(val->type()));
356}
357
Feng Xiao6ef984a2014-11-10 17:34:54 -0800358// Does the given field have a private (internal helper only) has_$name$()
359// method?
360bool HasPrivateHasMethod(const FieldDescriptor* field) {
361 // Only for oneofs in message types with no field presence. has_$name$(),
362 // based on the oneof case, is still useful internally for generated code.
363 return (!HasFieldPresence(field->file()) &&
364 field->containing_oneof() != NULL);
365}
366
367} // anonymous namespace
368
temporal40ee5512008-07-10 02:12:20 +0000369// ===================================================================
370
371MessageGenerator::MessageGenerator(const Descriptor* descriptor,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000372 const Options& options)
jieluo@google.com4de8f552014-07-18 00:47:59 +0000373 : descriptor_(descriptor),
374 classname_(ClassName(descriptor, false)),
375 options_(options),
376 field_generators_(descriptor, options),
Feng Xiaof157a562014-11-14 11:50:31 -0800377 nested_generators_(new google::protobuf::scoped_ptr<
jieluo@google.com4de8f552014-07-18 00:47:59 +0000378 MessageGenerator>[descriptor->nested_type_count()]),
379 enum_generators_(
Feng Xiaof157a562014-11-14 11:50:31 -0800380 new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
381 extension_generators_(new google::protobuf::scoped_ptr<
jieluo@google.com4de8f552014-07-18 00:47:59 +0000382 ExtensionGenerator>[descriptor->extension_count()]) {
temporal40ee5512008-07-10 02:12:20 +0000383
384 for (int i = 0; i < descriptor->nested_type_count(); i++) {
385 nested_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000386 new MessageGenerator(descriptor->nested_type(i), options));
temporal40ee5512008-07-10 02:12:20 +0000387 }
388
389 for (int i = 0; i < descriptor->enum_type_count(); i++) {
390 enum_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000391 new EnumGenerator(descriptor->enum_type(i), options));
temporal40ee5512008-07-10 02:12:20 +0000392 }
393
394 for (int i = 0; i < descriptor->extension_count(); i++) {
395 extension_generators_[i].reset(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000396 new ExtensionGenerator(descriptor->extension(i), options));
temporal40ee5512008-07-10 02:12:20 +0000397 }
Feng Xiao6ef984a2014-11-10 17:34:54 -0800398
399 num_required_fields_ = 0;
400 for (int i = 0; i < descriptor->field_count(); i++) {
401 if (descriptor->field(i)->is_required()) {
402 ++num_required_fields_;
403 }
404 }
temporal40ee5512008-07-10 02:12:20 +0000405}
406
407MessageGenerator::~MessageGenerator() {}
408
409void MessageGenerator::
410GenerateForwardDeclaration(io::Printer* printer) {
411 printer->Print("class $classname$;\n",
412 "classname", classname_);
413
414 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -0800415 // map entry message doesn't need forward declaration. Since map entry
416 // message cannot be a top level class, we just need to avoid calling
417 // GenerateForwardDeclaration here.
418 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
temporal40ee5512008-07-10 02:12:20 +0000419 nested_generators_[i]->GenerateForwardDeclaration(printer);
420 }
421}
422
423void MessageGenerator::
424GenerateEnumDefinitions(io::Printer* printer) {
425 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
426 nested_generators_[i]->GenerateEnumDefinitions(printer);
427 }
428
429 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
430 enum_generators_[i]->GenerateDefinition(printer);
431 }
432}
433
434void MessageGenerator::
kenton@google.com80b1d622009-07-29 01:13:20 +0000435GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
436 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
437 nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
438 }
439 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
440 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
441 }
442}
443
444void MessageGenerator::
temporal40ee5512008-07-10 02:12:20 +0000445GenerateFieldAccessorDeclarations(io::Printer* printer) {
446 for (int i = 0; i < descriptor_->field_count(); i++) {
447 const FieldDescriptor* field = descriptor_->field(i);
448
449 PrintFieldComment(printer, field);
450
451 map<string, string> vars;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000452 SetCommonFieldVariables(field, &vars, options_);
kenton@google.comcfa2d8a2009-04-18 00:02:12 +0000453 vars["constant_name"] = FieldConstantName(field);
temporal40ee5512008-07-10 02:12:20 +0000454
455 if (field->is_repeated()) {
Jisi Liu885b6122015-02-28 14:51:22 -0800456 printer->Print(vars, "int $name$_size() const$deprecation$;\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -0800457 } else if (HasHasMethod(field)) {
Jisi Liu885b6122015-02-28 14:51:22 -0800458 printer->Print(vars, "bool has_$name$() const$deprecation$;\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -0800459 } else if (HasPrivateHasMethod(field)) {
460 printer->Print(vars,
461 "private:\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800462 "bool has_$name$() const$deprecation$;\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800463 "public:\n");
temporal40ee5512008-07-10 02:12:20 +0000464 }
465
Jisi Liu885b6122015-02-28 14:51:22 -0800466 printer->Print(vars, "void clear_$name$()$deprecation$;\n");
kenton@google.comcfa2d8a2009-04-18 00:02:12 +0000467 printer->Print(vars, "static const int $constant_name$ = $number$;\n");
temporal40ee5512008-07-10 02:12:20 +0000468
469 // Generate type-specific accessor declarations.
470 field_generators_.get(field).GenerateAccessorDeclarations(printer);
471
472 printer->Print("\n");
473 }
474
475 if (descriptor_->extension_range_count() > 0) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000476 // Generate accessors for extensions. We just call a macro located in
477 // extension_set.h since the accessors about 80 lines of static code.
temporal40ee5512008-07-10 02:12:20 +0000478 printer->Print(
kenton@google.comd37d46d2009-04-25 02:53:47 +0000479 "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n",
temporal40ee5512008-07-10 02:12:20 +0000480 "classname", classname_);
481 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000482
483 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
484 printer->Print(
Jisi Liu885b6122015-02-28 14:51:22 -0800485 "$camel_oneof_name$Case $oneof_name$_case() const;\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000486 "camel_oneof_name",
487 UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true),
488 "oneof_name", descriptor_->oneof_decl(i)->name());
489 }
temporal40ee5512008-07-10 02:12:20 +0000490}
491
492void MessageGenerator::
Jisi Liu885b6122015-02-28 14:51:22 -0800493GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
temporal40ee5512008-07-10 02:12:20 +0000494 printer->Print("// $classname$\n\n", "classname", classname_);
495
496 for (int i = 0; i < descriptor_->field_count(); i++) {
497 const FieldDescriptor* field = descriptor_->field(i);
498
499 PrintFieldComment(printer, field);
500
501 map<string, string> vars;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000502 SetCommonFieldVariables(field, &vars, options_);
Jisi Liu885b6122015-02-28 14:51:22 -0800503 vars["inline"] = is_inline ? "inline" : "";
temporal40ee5512008-07-10 02:12:20 +0000504
505 // Generate has_$name$() or $name$_size().
506 if (field->is_repeated()) {
507 printer->Print(vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800508 "$inline$ int $classname$::$name$_size() const {\n"
temporal40ee5512008-07-10 02:12:20 +0000509 " return $name$_.size();\n"
510 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000511 } else if (field->containing_oneof()) {
512 // Singular field in a oneof
Feng Xiao6ef984a2014-11-10 17:34:54 -0800513 // N.B.: Without field presence, we do not use has-bits or generate
514 // has_$name$() methods, but oneofs still have set_has_$name$().
515 // Oneofs also have has_$name$() but only as a private helper
516 // method, so that generated code is slightly cleaner (vs. comparing
517 // _oneof_case_[index] against a constant everywhere).
jieluo@google.com4de8f552014-07-18 00:47:59 +0000518 vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
519 vars["oneof_name"] = field->containing_oneof()->name();
520 vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
521 printer->Print(vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800522 "$inline$ bool $classname$::has_$name$() const {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000523 " return $oneof_name$_case() == k$field_name$;\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800524 "}\n");
525 printer->Print(vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800526 "$inline$ void $classname$::set_has_$name$() {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000527 " _oneof_case_[$oneof_index$] = k$field_name$;\n"
528 "}\n");
temporal40ee5512008-07-10 02:12:20 +0000529 } else {
530 // Singular field.
Feng Xiao6ef984a2014-11-10 17:34:54 -0800531 if (HasFieldPresence(descriptor_->file())) {
532 // N.B.: without field presence, we do not use has-bits or generate
533 // has_$name$() methods.
534 char buffer[kFastToBufferSize];
535 vars["has_array_index"] = SimpleItoa(field->index() / 32);
536 vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32),
537 buffer);
538 printer->Print(vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800539 "$inline$ bool $classname$::has_$name$() const {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800540 " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
541 "}\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800542 "$inline$ void $classname$::set_has_$name$() {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800543 " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
544 "}\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800545 "$inline$ void $classname$::clear_has_$name$() {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800546 " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
547 "}\n"
548 );
549 } else {
550 // Message fields have a has_$name$() method.
551 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
552 bool is_lazy = false;
553 if (is_lazy) {
554 printer->Print(vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800555 "$inline$ bool $classname$::has_$name$() const {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800556 " return !$name$_.IsCleared();\n"
557 "}\n");
558 } else {
559 printer->Print(vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800560 "$inline$ bool $classname$::has_$name$() const {\n"
Feng Xiaoc25d9fe2014-11-26 16:15:29 -0800561 " return !_is_default_instance_ && $name$_ != NULL;\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800562 "}\n");
563 }
564 }
565 }
temporal40ee5512008-07-10 02:12:20 +0000566 }
567
568 // Generate clear_$name$()
569 printer->Print(vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800570 "$inline$ void $classname$::clear_$name$() {\n");
temporal40ee5512008-07-10 02:12:20 +0000571
572 printer->Indent();
temporal40ee5512008-07-10 02:12:20 +0000573
jieluo@google.com4de8f552014-07-18 00:47:59 +0000574 if (field->containing_oneof()) {
575 // Clear this field only if it is the active field in this oneof,
576 // otherwise ignore
liujisi@google.com33165fe2010-11-02 13:14:58 +0000577 printer->Print(vars,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000578 "if (has_$name$()) {\n");
579 printer->Indent();
580 field_generators_.get(field).GenerateClearingCode(printer);
581 printer->Print(vars,
582 "clear_has_$oneof_name$();\n");
583 printer->Outdent();
584 printer->Print("}\n");
585 } else {
586 field_generators_.get(field).GenerateClearingCode(printer);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800587 if (HasFieldPresence(descriptor_->file())) {
588 if (!field->is_repeated()) {
589 printer->Print(vars,
590 "clear_has_$name$();\n");
591 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000592 }
temporal40ee5512008-07-10 02:12:20 +0000593 }
594
jieluo@google.com4de8f552014-07-18 00:47:59 +0000595 printer->Outdent();
temporal40ee5512008-07-10 02:12:20 +0000596 printer->Print("}\n");
597
598 // Generate type-specific accessors.
Jisi Liu885b6122015-02-28 14:51:22 -0800599 field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
600 is_inline);
temporal40ee5512008-07-10 02:12:20 +0000601
602 printer->Print("\n");
603 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000604
605 // Generate has_$name$() and clear_has_$name$() functions for oneofs
606 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
607 map<string, string> vars;
608 vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
609 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
610 vars["cap_oneof_name"] =
611 ToUpper(descriptor_->oneof_decl(i)->name());
612 vars["classname"] = classname_;
Jisi Liu885b6122015-02-28 14:51:22 -0800613 vars["inline"] = is_inline ? "inline" : "";
jieluo@google.com4de8f552014-07-18 00:47:59 +0000614 printer->Print(
615 vars,
Jisi Liu885b6122015-02-28 14:51:22 -0800616 "$inline$ bool $classname$::has_$oneof_name$() const {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000617 " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
618 "}\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800619 "$inline$ void $classname$::clear_has_$oneof_name$() {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000620 " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
621 "}\n");
622 }
623}
624
625// Helper for the code that emits the Clear() method.
626static bool CanClearByZeroing(const FieldDescriptor* field) {
627 if (field->is_repeated() || field->is_extension()) return false;
628 switch (field->cpp_type()) {
629 case internal::WireFormatLite::CPPTYPE_ENUM:
630 return field->default_value_enum()->number() == 0;
631 case internal::WireFormatLite::CPPTYPE_INT32:
632 return field->default_value_int32() == 0;
633 case internal::WireFormatLite::CPPTYPE_INT64:
634 return field->default_value_int64() == 0;
635 case internal::WireFormatLite::CPPTYPE_UINT32:
636 return field->default_value_uint32() == 0;
637 case internal::WireFormatLite::CPPTYPE_UINT64:
638 return field->default_value_uint64() == 0;
639 case internal::WireFormatLite::CPPTYPE_FLOAT:
640 return field->default_value_float() == 0;
641 case internal::WireFormatLite::CPPTYPE_DOUBLE:
642 return field->default_value_double() == 0;
643 case internal::WireFormatLite::CPPTYPE_BOOL:
644 return field->default_value_bool() == false;
645 default:
646 return false;
647 }
temporal40ee5512008-07-10 02:12:20 +0000648}
649
650void MessageGenerator::
651GenerateClassDefinition(io::Printer* printer) {
652 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -0800653 // map entry message doesn't need class definition. Since map entry message
654 // cannot be a top level class, we just need to avoid calling
655 // GenerateClassDefinition here.
656 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
temporal40ee5512008-07-10 02:12:20 +0000657 nested_generators_[i]->GenerateClassDefinition(printer);
658 printer->Print("\n");
659 printer->Print(kThinSeparator);
660 printer->Print("\n");
661 }
662
663 map<string, string> vars;
664 vars["classname"] = classname_;
665 vars["field_count"] = SimpleItoa(descriptor_->field_count());
jieluo@google.com4de8f552014-07-18 00:47:59 +0000666 vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count());
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000667 if (options_.dllexport_decl.empty()) {
temporal40ee5512008-07-10 02:12:20 +0000668 vars["dllexport"] = "";
669 } else {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000670 vars["dllexport"] = options_.dllexport_decl + " ";
temporal40ee5512008-07-10 02:12:20 +0000671 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000672 vars["superclass"] = SuperClassName(descriptor_);
temporal40ee5512008-07-10 02:12:20 +0000673
674 printer->Print(vars,
kenton@google.comfccb1462009-12-18 02:11:36 +0000675 "class $dllexport$$classname$ : public $superclass$ {\n"
temporal40ee5512008-07-10 02:12:20 +0000676 " public:\n");
677 printer->Indent();
678
679 printer->Print(vars,
680 "$classname$();\n"
681 "virtual ~$classname$();\n"
682 "\n"
683 "$classname$(const $classname$& from);\n"
684 "\n"
685 "inline $classname$& operator=(const $classname$& from) {\n"
686 " CopyFrom(from);\n"
687 " return *this;\n"
688 "}\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000689 "\n");
690
Feng Xiao6ef984a2014-11-10 17:34:54 -0800691 if (PreserveUnknownFields(descriptor_)) {
692 if (UseUnknownFieldSet(descriptor_->file())) {
693 printer->Print(
694 "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
695 " return _internal_metadata_.unknown_fields();\n"
696 "}\n"
697 "\n"
698 "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
699 " return _internal_metadata_.mutable_unknown_fields();\n"
700 "}\n"
701 "\n");
702 } else {
703 printer->Print(
704 "inline const ::std::string& unknown_fields() const {\n"
705 " return _unknown_fields_;\n"
706 "}\n"
707 "\n"
708 "inline ::std::string* mutable_unknown_fields() {\n"
709 " return &_unknown_fields_;\n"
710 "}\n"
711 "\n");
712 }
713 }
714
715 // N.B.: We exclude GetArena() when arena support is disabled, falling back on
716 // MessageLite's implementation which returns NULL rather than generating our
717 // own method which returns NULL, in order to reduce code size.
718 if (SupportsArenas(descriptor_)) {
719 // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a
720 // MessageLite* (e.g., in RepeatedField::AddAllocated()).
kenton@google.com80b1d622009-07-29 01:13:20 +0000721 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800722 "inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }\n"
723 "inline void* GetMaybeArenaPointer() const {\n"
724 " return MaybeArenaPtr();\n"
725 "}\n");
kenton@google.com80b1d622009-07-29 01:13:20 +0000726 }
727
728 // Only generate this member if it's not disabled.
729 if (HasDescriptorMethods(descriptor_->file()) &&
730 !descriptor_->options().no_standard_descriptor_accessor()) {
731 printer->Print(vars,
732 "static const ::google::protobuf::Descriptor* descriptor();\n");
733 }
734
735 printer->Print(vars,
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000736 "static const $classname$& default_instance();\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000737 "\n");
738
jieluo@google.com4de8f552014-07-18 00:47:59 +0000739 // Generate enum values for every field in oneofs. One list is generated for
740 // each oneof with an additional *_NOT_SET value.
741 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
742 printer->Print(
743 "enum $camel_oneof_name$Case {\n",
744 "camel_oneof_name",
745 UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
746 printer->Indent();
747 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
748 printer->Print(
749 "k$field_name$ = $field_number$,\n",
750 "field_name",
751 UnderscoresToCamelCase(
752 descriptor_->oneof_decl(i)->field(j)->name(), true),
753 "field_number",
754 SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number()));
755 }
756 printer->Print(
757 "$cap_oneof_name$_NOT_SET = 0,\n",
758 "cap_oneof_name",
759 ToUpper(descriptor_->oneof_decl(i)->name()));
760 printer->Outdent();
761 printer->Print(
762 "};\n"
763 "\n");
764 }
765
pliard@google.com6103d4e2012-05-04 11:16:09 +0000766 if (!StaticInitializersForced(descriptor_->file())) {
767 printer->Print(vars,
768 "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
769 "// Returns the internal default instance pointer. This function can\n"
770 "// return NULL thus should not be used by the user. This is intended\n"
771 "// for Protobuf internal code. Please use default_instance() declared\n"
772 "// above instead.\n"
773 "static inline const $classname$* internal_default_instance() {\n"
774 " return default_instance_;\n"
775 "}\n"
776 "#endif\n"
777 "\n");
778 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000779
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000780
Feng Xiao6ef984a2014-11-10 17:34:54 -0800781 if (SupportsArenas(descriptor_)) {
782 printer->Print(vars,
783 "void UnsafeArenaSwap($classname$* other);\n");
784 }
kenton@google.comfccb1462009-12-18 02:11:36 +0000785 printer->Print(vars,
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000786 "void Swap($classname$* other);\n"
temporal40ee5512008-07-10 02:12:20 +0000787 "\n"
788 "// implements Message ----------------------------------------------\n"
789 "\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800790 "inline $classname$* New() const { return New(NULL); }\n"
791 "\n"
792 "$classname$* New(::google::protobuf::Arena* arena) const;\n");
temporal40ee5512008-07-10 02:12:20 +0000793
kenton@google.com80b1d622009-07-29 01:13:20 +0000794 if (HasGeneratedMethods(descriptor_->file())) {
795 if (HasDescriptorMethods(descriptor_->file())) {
796 printer->Print(vars,
797 "void CopyFrom(const ::google::protobuf::Message& from);\n"
798 "void MergeFrom(const ::google::protobuf::Message& from);\n");
799 } else {
800 printer->Print(vars,
801 "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n");
802 }
803
temporal40ee5512008-07-10 02:12:20 +0000804 printer->Print(vars,
temporal40ee5512008-07-10 02:12:20 +0000805 "void CopyFrom(const $classname$& from);\n"
806 "void MergeFrom(const $classname$& from);\n"
807 "void Clear();\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000808 "bool IsInitialized() const;\n"
809 "\n"
810 "int ByteSize() const;\n"
811 "bool MergePartialFromCodedStream(\n"
812 " ::google::protobuf::io::CodedInputStream* input);\n"
813 "void SerializeWithCachedSizes(\n"
814 " ::google::protobuf::io::CodedOutputStream* output) const;\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000815 // DiscardUnknownFields() is implemented in message.cc using reflections. We
816 // need to implement this function in generated code for messages.
817 if (!UseUnknownFieldSet(descriptor_->file())) {
818 printer->Print(
819 "void DiscardUnknownFields();\n");
820 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000821 if (HasFastArraySerialization(descriptor_->file())) {
822 printer->Print(
kenton@google.comd37d46d2009-04-25 02:53:47 +0000823 "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
824 }
temporal40ee5512008-07-10 02:12:20 +0000825 }
826
jieluo@google.com4de8f552014-07-18 00:47:59 +0000827 // Check all FieldDescriptors including those in oneofs to estimate
828 // whether ::std::string is likely to be used, and depending on that
829 // estimate, set uses_string_ to true or false. That contols
830 // whether to force initialization of empty_string_ in SharedCtor().
831 // It's often advantageous to do so to keep "is empty_string_
832 // inited?" code from appearing all over the place.
833 vector<const FieldDescriptor*> descriptors;
834 for (int i = 0; i < descriptor_->field_count(); i++) {
835 descriptors.push_back(descriptor_->field(i));
836 }
837 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
838 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
839 descriptors.push_back(descriptor_->oneof_decl(i)->field(j));
840 }
841 }
842 uses_string_ = false;
843 for (int i = 0; i < descriptors.size(); i++) {
844 const FieldDescriptor* field = descriptors[i];
845 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
846 switch (field->options().ctype()) {
847 default: uses_string_ = true; break;
848 }
849 }
850 }
851
852 printer->Print(
temporal40ee5512008-07-10 02:12:20 +0000853 "int GetCachedSize() const { return _cached_size_; }\n"
854 "private:\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000855 "void SharedCtor();\n"
856 "void SharedDtor();\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000857 "void SetCachedSize(int size) const;\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800858 "void InternalSwap($classname$* other);\n",
859 "classname", classname_);
860 if (SupportsArenas(descriptor_)) {
861 printer->Print(
862 "protected:\n"
863 "explicit $classname$(::google::protobuf::Arena* arena);\n"
864 "private:\n"
865 "static void ArenaDtor(void* object);\n"
866 "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n",
867 "classname", classname_);
868 }
869
870 if (UseUnknownFieldSet(descriptor_->file())) {
871 printer->Print(
872 "private:\n"
873 "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
874 " return _internal_metadata_.arena();\n"
875 "}\n"
876 "inline void* MaybeArenaPtr() const {\n"
877 " return _internal_metadata_.raw_arena_ptr();\n"
878 "}\n"
879 "public:\n"
880 "\n");
881 } else {
882 printer->Print(
883 "private:\n"
884 "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
885 " return _arena_ptr_;\n"
886 "}\n"
887 "inline ::google::protobuf::Arena* MaybeArenaPtr() const {\n"
888 " return _arena_ptr_;\n"
889 "}\n"
890 "public:\n"
891 "\n");
892 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000893
894 if (HasDescriptorMethods(descriptor_->file())) {
895 printer->Print(
896 "::google::protobuf::Metadata GetMetadata() const;\n"
897 "\n");
898 } else {
899 printer->Print(
900 "::std::string GetTypeName() const;\n"
901 "\n");
902 }
903
904 printer->Print(
temporal40ee5512008-07-10 02:12:20 +0000905 "// nested types ----------------------------------------------------\n"
906 "\n");
907
908 // Import all nested message classes into this class's scope with typedefs.
909 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
910 const Descriptor* nested_type = descriptor_->nested_type(i);
Feng Xiaof157a562014-11-14 11:50:31 -0800911 if (!IsMapEntryMessage(nested_type)) {
912 printer->Print("typedef $nested_full_name$ $nested_name$;\n",
913 "nested_name", nested_type->name(),
914 "nested_full_name", ClassName(nested_type, false));
915 }
temporal40ee5512008-07-10 02:12:20 +0000916 }
917
918 if (descriptor_->nested_type_count() > 0) {
919 printer->Print("\n");
920 }
921
922 // Import all nested enums and their values into this class's scope with
923 // typedefs and constants.
924 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
925 enum_generators_[i]->GenerateSymbolImports(printer);
926 printer->Print("\n");
927 }
928
929 printer->Print(
930 "// accessors -------------------------------------------------------\n"
931 "\n");
932
933 // Generate accessor methods for all fields.
934 GenerateFieldAccessorDeclarations(printer);
935
936 // Declare extension identifiers.
937 for (int i = 0; i < descriptor_->extension_count(); i++) {
938 extension_generators_[i]->GenerateDeclaration(printer);
939 }
940
kenton@google.comfccb1462009-12-18 02:11:36 +0000941
942 printer->Print(
943 "// @@protoc_insertion_point(class_scope:$full_name$)\n",
944 "full_name", descriptor_->full_name());
945
liujisi@google.com33165fe2010-11-02 13:14:58 +0000946 // Generate private members.
temporal40ee5512008-07-10 02:12:20 +0000947 printer->Outdent();
948 printer->Print(" private:\n");
949 printer->Indent();
950
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000951
liujisi@google.com33165fe2010-11-02 13:14:58 +0000952 for (int i = 0; i < descriptor_->field_count(); i++) {
953 if (!descriptor_->field(i)->is_repeated()) {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800954 // set_has_***() generated in all proto1/2 code and in oneofs (only) for
955 // messages without true field presence.
956 if (HasFieldPresence(descriptor_->file()) ||
957 descriptor_->field(i)->containing_oneof()) {
958 printer->Print(
959 "inline void set_has_$name$();\n",
960 "name", FieldName(descriptor_->field(i)));
961 }
962 // clear_has_***() generated only for non-oneof fields
963 // in proto1/2.
964 if (!descriptor_->field(i)->containing_oneof() &&
965 HasFieldPresence(descriptor_->file())) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000966 printer->Print(
967 "inline void clear_has_$name$();\n",
968 "name", FieldName(descriptor_->field(i)));
969 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000970 }
971 }
972 printer->Print("\n");
973
jieluo@google.com4de8f552014-07-18 00:47:59 +0000974 // Generate oneof function declarations
975 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
976 printer->Print(
Feng Xiao99aa0f92014-11-20 16:18:53 -0800977 "inline bool has_$oneof_name$() const;\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000978 "void clear_$oneof_name$();\n"
979 "inline void clear_has_$oneof_name$();\n\n",
980 "oneof_name", descriptor_->oneof_decl(i)->name());
981 }
982
Feng Xiao6ef984a2014-11-10 17:34:54 -0800983 if (HasGeneratedMethods(descriptor_->file()) &&
984 !descriptor_->options().message_set_wire_format() &&
985 num_required_fields_ > 1) {
986 printer->Print(
987 "// helper for ByteSize()\n"
988 "int RequiredFieldsByteSizeFallback() const;\n\n");
989 }
990
jieluo@google.com4de8f552014-07-18 00:47:59 +0000991 // Prepare decls for _cached_size_ and _has_bits_. Their position in the
992 // output will be determined later.
993
994 bool need_to_emit_cached_size = true;
995 // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it.
996 const string cached_size_decl = "mutable int _cached_size_;\n";
997
998 // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields.
999 size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4;
1000 if (descriptor_->field_count() == 0) {
1001 // Zero-size arrays aren't technically allowed, and MSVC in particular
1002 // doesn't like them. We still need to declare these arrays to make
1003 // other code compile. Since this is an uncommon case, we'll just declare
1004 // them with size 1 and waste some space. Oh well.
1005 sizeof_has_bits = 4;
1006 }
1007 const string has_bits_decl = sizeof_has_bits == 0 ? "" :
1008 "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n";
1009
1010
liujisi@google.com33165fe2010-11-02 13:14:58 +00001011 // To minimize padding, data members are divided into three sections:
1012 // (1) members assumed to align to 8 bytes
1013 // (2) members corresponding to message fields, re-ordered to optimize
1014 // alignment.
1015 // (3) members assumed to align to 4 bytes.
1016
1017 // Members assumed to align to 8 bytes:
1018
temporal40ee5512008-07-10 02:12:20 +00001019 if (descriptor_->extension_range_count() > 0) {
1020 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001021 "::google::protobuf::internal::ExtensionSet _extensions_;\n"
1022 "\n");
temporal40ee5512008-07-10 02:12:20 +00001023 }
1024
jieluo@google.com4de8f552014-07-18 00:47:59 +00001025 if (UseUnknownFieldSet(descriptor_->file())) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001026 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001027 "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +00001028 } else {
1029 printer->Print(
1030 "::std::string _unknown_fields_;\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -08001031 "::google::protobuf::Arena* _arena_ptr_;\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001032 "\n");
1033 }
1034
Feng Xiao6ef984a2014-11-10 17:34:54 -08001035 if (SupportsArenas(descriptor_)) {
1036 printer->Print(
1037 "friend class ::google::protobuf::Arena;\n"
1038 "typedef void InternalArenaConstructable_;\n"
1039 "typedef void DestructorSkippable_;\n");
1040 }
1041
1042 if (HasFieldPresence(descriptor_->file())) {
1043 // _has_bits_ is frequently accessed, so to reduce code size and improve
1044 // speed, it should be close to the start of the object. But, try not to
1045 // waste space:_has_bits_ by itself always makes sense if its size is a
1046 // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together
1047 // will work well.
1048 printer->Print(has_bits_decl.c_str());
1049 if ((sizeof_has_bits % 8) != 0) {
1050 printer->Print(cached_size_decl.c_str());
1051 need_to_emit_cached_size = false;
1052 }
Feng Xiaoc25d9fe2014-11-26 16:15:29 -08001053 } else {
1054 // Without field presence, we need another way to disambiguate the default
1055 // instance, because the default instance's submessage fields (if any) store
1056 // pointers to the default instances of the submessages even when they
1057 // aren't present. Alternatives to this approach might be to (i) use a
1058 // tagged pointer on all message fields, setting a tag bit for "not really
1059 // present, just default instance"; or (ii) comparing |this| against the
1060 // return value from GeneratedMessageFactory::GetPrototype() in all
1061 // has_$field$() calls. However, both of these options are much more
1062 // expensive (in code size and CPU overhead) than just checking a field in
1063 // the message. Long-term, the best solution would be to rearchitect the
1064 // default instance design not to store pointers to submessage default
1065 // instances, and have reflection get those some other way; but that change
1066 // would have too much impact on proto2.
1067 printer->Print(
1068 "bool _is_default_instance_;\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00001069 }
1070
liujisi@google.com33165fe2010-11-02 13:14:58 +00001071 // Field members:
1072
jieluo@google.com4de8f552014-07-18 00:47:59 +00001073 // List fields which doesn't belong to any oneof
liujisi@google.com33165fe2010-11-02 13:14:58 +00001074 vector<const FieldDescriptor*> fields;
jieluo@google.com4de8f552014-07-18 00:47:59 +00001075 hash_map<string, int> fieldname_to_chunk;
liujisi@google.com33165fe2010-11-02 13:14:58 +00001076 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001077 if (!descriptor_->field(i)->containing_oneof()) {
1078 const FieldDescriptor* field = descriptor_->field(i);
1079 fields.push_back(field);
1080 fieldname_to_chunk[FieldName(field)] = i / 8;
1081 }
liujisi@google.com33165fe2010-11-02 13:14:58 +00001082 }
1083 OptimizePadding(&fields);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001084 // Emit some private and static members
1085 runs_of_fields_ = vector< vector<string> >(1);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001086 for (int i = 0; i < fields.size(); ++i) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001087 const FieldDescriptor* field = fields[i];
1088 const FieldGenerator& generator = field_generators_.get(field);
1089 generator.GenerateStaticMembers(printer);
1090 generator.GeneratePrivateMembers(printer);
1091 if (CanClearByZeroing(field)) {
1092 const string& fieldname = FieldName(field);
1093 if (!runs_of_fields_.back().empty() &&
1094 (fieldname_to_chunk[runs_of_fields_.back().back()] !=
1095 fieldname_to_chunk[fieldname])) {
1096 runs_of_fields_.push_back(vector<string>());
1097 }
1098 runs_of_fields_.back().push_back(fieldname);
1099 } else if (!runs_of_fields_.back().empty()) {
1100 runs_of_fields_.push_back(vector<string>());
1101 }
1102 }
1103
1104 // For each oneof generate a union
1105 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1106 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001107 "union $camel_oneof_name$Union {\n"
1108 // explicit empty constructor is needed when union contains
1109 // ArenaStringPtr members for string fields.
1110 " $camel_oneof_name$Union() {}\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001111 "camel_oneof_name",
1112 UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
1113 printer->Indent();
1114 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
1115 field_generators_.get(descriptor_->oneof_decl(i)->
1116 field(j)).GeneratePrivateMembers(printer);
1117 }
1118 printer->Outdent();
1119 printer->Print(
1120 "} $oneof_name$_;\n",
1121 "oneof_name", descriptor_->oneof_decl(i)->name());
1122 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
1123 field_generators_.get(descriptor_->oneof_decl(i)->
1124 field(j)).GenerateStaticMembers(printer);
1125 }
liujisi@google.com33165fe2010-11-02 13:14:58 +00001126 }
1127
1128 // Members assumed to align to 4 bytes:
1129
jieluo@google.com4de8f552014-07-18 00:47:59 +00001130 if (need_to_emit_cached_size) {
1131 printer->Print(cached_size_decl.c_str());
1132 need_to_emit_cached_size = false;
1133 }
liujisi@google.com33165fe2010-11-02 13:14:58 +00001134
jieluo@google.com4de8f552014-07-18 00:47:59 +00001135 // Generate _oneof_case_.
1136 if (descriptor_->oneof_decl_count() > 0) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001137 printer->Print(vars,
jieluo@google.com4de8f552014-07-18 00:47:59 +00001138 "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001139 "\n");
temporal40ee5512008-07-10 02:12:20 +00001140 }
1141
kenton@google.com63e646b2009-05-06 19:27:03 +00001142 // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
1143 // friends so that they can access private static variables like
1144 // default_instance_ and reflection_.
pliard@google.com6103d4e2012-05-04 11:16:09 +00001145 PrintHandlingOptionalStaticInitializers(
1146 descriptor_->file(), printer,
1147 // With static initializers.
kenton@google.comccc11672009-04-28 01:48:06 +00001148 "friend void $dllexport_decl$ $adddescriptorsname$();\n",
pliard@google.com6103d4e2012-05-04 11:16:09 +00001149 // Without.
1150 "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
1151 // Vars.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001152 "dllexport_decl", options_.dllexport_decl,
kenton@google.comd37d46d2009-04-25 02:53:47 +00001153 "adddescriptorsname",
pliard@google.com6103d4e2012-05-04 11:16:09 +00001154 GlobalAddDescriptorsName(descriptor_->file()->name()));
1155
kenton@google.comccc11672009-04-28 01:48:06 +00001156 printer->Print(
kenton@google.com63e646b2009-05-06 19:27:03 +00001157 "friend void $assigndescriptorsname$();\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001158 "friend void $shutdownfilename$();\n"
1159 "\n",
kenton@google.comd37d46d2009-04-25 02:53:47 +00001160 "assigndescriptorsname",
kenton@google.com63e646b2009-05-06 19:27:03 +00001161 GlobalAssignDescriptorsName(descriptor_->file()->name()),
1162 "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
temporal40ee5512008-07-10 02:12:20 +00001163
temporal40ee5512008-07-10 02:12:20 +00001164 printer->Print(
kenton@google.com24bf56f2008-09-24 20:31:01 +00001165 "void InitAsDefaultInstance();\n"
1166 "static $classname$* default_instance_;\n",
1167 "classname", classname_);
temporal40ee5512008-07-10 02:12:20 +00001168
1169 printer->Outdent();
1170 printer->Print(vars, "};");
jieluo@google.com4de8f552014-07-18 00:47:59 +00001171 GOOGLE_DCHECK(!need_to_emit_cached_size);
temporal40ee5512008-07-10 02:12:20 +00001172}
1173
1174void MessageGenerator::
Jisi Liu885b6122015-02-28 14:51:22 -08001175GenerateInlineMethods(io::Printer* printer, bool is_inline) {
temporal40ee5512008-07-10 02:12:20 +00001176 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -08001177 // map entry message doesn't need inline methods. Since map entry message
1178 // cannot be a top level class, we just need to avoid calling
1179 // GenerateInlineMethods here.
1180 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
Jisi Liu885b6122015-02-28 14:51:22 -08001181 nested_generators_[i]->GenerateInlineMethods(printer, is_inline);
temporal40ee5512008-07-10 02:12:20 +00001182 printer->Print(kThinSeparator);
1183 printer->Print("\n");
1184 }
1185
Jisi Liu885b6122015-02-28 14:51:22 -08001186 GenerateFieldAccessorDefinitions(printer, is_inline);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001187
1188 // Generate oneof_case() functions.
1189 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1190 map<string, string> vars;
1191 vars["class_name"] = classname_;
1192 vars["camel_oneof_name"] = UnderscoresToCamelCase(
1193 descriptor_->oneof_decl(i)->name(), true);
1194 vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
1195 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
Jisi Liu885b6122015-02-28 14:51:22 -08001196 vars["inline"] = is_inline ? "inline " : "";
jieluo@google.com4de8f552014-07-18 00:47:59 +00001197 printer->Print(
1198 vars,
Jisi Liu885b6122015-02-28 14:51:22 -08001199 "$inline$$class_name$::$camel_oneof_name$Case $class_name$::"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001200 "$oneof_name$_case() const {\n"
1201 " return $class_name$::$camel_oneof_name$Case("
1202 "_oneof_case_[$oneof_index$]);\n"
1203 "}\n");
1204 }
temporal40ee5512008-07-10 02:12:20 +00001205}
1206
1207void MessageGenerator::
1208GenerateDescriptorDeclarations(io::Printer* printer) {
Feng Xiaof157a562014-11-14 11:50:31 -08001209 if (!IsMapEntryMessage(descriptor_)) {
1210 printer->Print(
1211 "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
1212 "const ::google::protobuf::internal::GeneratedMessageReflection*\n"
1213 " $name$_reflection_ = NULL;\n",
1214 "name", classname_);
1215 } else {
1216 printer->Print(
1217 "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n",
1218 "name", classname_);
1219 }
temporal40ee5512008-07-10 02:12:20 +00001220
jieluo@google.com4de8f552014-07-18 00:47:59 +00001221 // Generate oneof default instance for reflection usage.
1222 if (descriptor_->oneof_decl_count() > 0) {
1223 printer->Print("struct $name$OneofInstance {\n",
1224 "name", classname_);
1225 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1226 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
1227 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
1228 printer->Print(" ");
Jisi Liu885b6122015-02-28 14:51:22 -08001229 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
1230 (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
1231 EffectiveStringCType(field) != FieldOptions::STRING)) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001232 printer->Print("const ");
1233 }
1234 field_generators_.get(field).GeneratePrivateMembers(printer);
1235 }
1236 }
1237
1238 printer->Print("}* $name$_default_oneof_instance_ = NULL;\n",
1239 "name", classname_);
1240 }
1241
temporal40ee5512008-07-10 02:12:20 +00001242 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1243 nested_generators_[i]->GenerateDescriptorDeclarations(printer);
1244 }
1245
1246 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
1247 printer->Print(
1248 "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
1249 "name", ClassName(descriptor_->enum_type(i), false));
1250 }
1251}
1252
1253void MessageGenerator::
1254GenerateDescriptorInitializer(io::Printer* printer, int index) {
1255 // TODO(kenton): Passing the index to this method is redundant; just use
1256 // descriptor_->index() instead.
1257 map<string, string> vars;
1258 vars["classname"] = classname_;
1259 vars["index"] = SimpleItoa(index);
1260
temporal779f61c2008-08-13 03:15:00 +00001261 // Obtain the descriptor from the parent's descriptor.
temporal40ee5512008-07-10 02:12:20 +00001262 if (descriptor_->containing_type() == NULL) {
1263 printer->Print(vars,
1264 "$classname$_descriptor_ = file->message_type($index$);\n");
1265 } else {
1266 vars["parent"] = ClassName(descriptor_->containing_type(), false);
1267 printer->Print(vars,
1268 "$classname$_descriptor_ = "
1269 "$parent$_descriptor_->nested_type($index$);\n");
1270 }
1271
Feng Xiaof157a562014-11-14 11:50:31 -08001272 if (IsMapEntryMessage(descriptor_)) return;
1273
kenton@google.com3e91fcd2008-11-06 04:37:30 +00001274 // Generate the offsets.
1275 GenerateOffsets(printer);
1276
Feng Xiaof157a562014-11-14 11:50:31 -08001277 const bool pass_pool_and_factory = false;
1278 vars["fn"] = pass_pool_and_factory ?
1279 "new ::google::protobuf::internal::GeneratedMessageReflection" :
1280 "::google::protobuf::internal::GeneratedMessageReflection"
1281 "::NewGeneratedMessageReflection";
temporal779f61c2008-08-13 03:15:00 +00001282 // Construct the reflection object.
1283 printer->Print(vars,
1284 "$classname$_reflection_ =\n"
Feng Xiaof157a562014-11-14 11:50:31 -08001285 " $fn$(\n"
temporal779f61c2008-08-13 03:15:00 +00001286 " $classname$_descriptor_,\n"
kenton@google.com24bf56f2008-09-24 20:31:01 +00001287 " $classname$::default_instance_,\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -08001288 " $classname$_offsets_,\n");
1289 if (!HasFieldPresence(descriptor_->file())) {
1290 // If we don't have field presence, then _has_bits_ does not exist.
1291 printer->Print(vars,
1292 " -1,\n");
1293 } else {
1294 printer->Print(vars,
1295 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n");
1296 }
1297
1298 // Unknown field offset: either points to the unknown field set if embedded
1299 // directly, or indicates that the unknown field set is stored as part of the
1300 // internal metadata if not.
1301 if (UseUnknownFieldSet(descriptor_->file())) {
1302 printer->Print(vars,
1303 " -1,\n");
1304 } else {
1305 printer->Print(vars,
temporal779f61c2008-08-13 03:15:00 +00001306 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
1307 "$classname$, _unknown_fields_),\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -08001308 }
1309
temporal779f61c2008-08-13 03:15:00 +00001310 if (descriptor_->extension_range_count() > 0) {
1311 printer->Print(vars,
1312 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
1313 "$classname$, _extensions_),\n");
1314 } else {
1315 // No extensions.
1316 printer->Print(vars,
1317 " -1,\n");
1318 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00001319
1320 if (descriptor_->oneof_decl_count() > 0) {
1321 printer->Print(vars,
1322 " $classname$_default_oneof_instance_,\n"
1323 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
1324 "$classname$, _oneof_case_[0]),\n");
1325 }
1326
Feng Xiaof157a562014-11-14 11:50:31 -08001327 if (pass_pool_and_factory) {
1328 printer->Print(
1329 " ::google::protobuf::DescriptorPool::generated_pool(),\n");
1330 printer->Print(vars,
1331 " ::google::protobuf::MessageFactory::generated_factory(),\n");
1332 }
Feng Xiao6ef984a2014-11-10 17:34:54 -08001333
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001334 printer->Print(vars,
Feng Xiao6ef984a2014-11-10 17:34:54 -08001335 " sizeof($classname$),\n");
1336
1337 // Arena offset: either an offset to the metadata struct that contains the
1338 // arena pointer and unknown field set (in a space-efficient way) if we use
1339 // that implementation strategy, or an offset directly to the arena pointer if
1340 // not (because e.g. we don't have an unknown field set).
1341 if (UseUnknownFieldSet(descriptor_->file())) {
1342 printer->Print(vars,
1343 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
Feng Xiaoc25d9fe2014-11-26 16:15:29 -08001344 "$classname$, _internal_metadata_),\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -08001345 } else {
1346 printer->Print(vars,
1347 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
Feng Xiaoc25d9fe2014-11-26 16:15:29 -08001348 "$classname$, _arena_),\n");
1349 }
1350
1351 // is_default_instance_ offset.
1352 if (HasFieldPresence(descriptor_->file())) {
1353 printer->Print(vars,
1354 " -1);\n");
1355 } else {
1356 printer->Print(vars,
1357 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
1358 "$classname$, _is_default_instance_));\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -08001359 }
temporal779f61c2008-08-13 03:15:00 +00001360
1361 // Handle nested types.
temporal40ee5512008-07-10 02:12:20 +00001362 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1363 nested_generators_[i]->GenerateDescriptorInitializer(printer, i);
1364 }
1365
1366 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
1367 enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
1368 }
kenton@google.comd37d46d2009-04-25 02:53:47 +00001369}
temporal40ee5512008-07-10 02:12:20 +00001370
kenton@google.comd37d46d2009-04-25 02:53:47 +00001371void MessageGenerator::
1372GenerateTypeRegistrations(io::Printer* printer) {
temporal40ee5512008-07-10 02:12:20 +00001373 // Register this message type with the message factory.
Feng Xiaof157a562014-11-14 11:50:31 -08001374 if (!IsMapEntryMessage(descriptor_)) {
1375 printer->Print(
1376 "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
1377 " $classname$_descriptor_, &$classname$::default_instance());\n",
1378 "classname", classname_);
1379 }
1380 else {
1381 map<string, string> vars;
1382 CollectMapInfo(descriptor_, &vars);
1383 vars["classname"] = classname_;
1384
1385 const FieldDescriptor* val = descriptor_->FindFieldByName("value");
1386 if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
1387 val->type() == FieldDescriptor::TYPE_ENUM) {
1388 const EnumValueDescriptor* default_value = val->default_value_enum();
1389 vars["default_enum_value"] = Int32ToString(default_value->number());
1390 } else {
1391 vars["default_enum_value"] = "0";
1392 }
1393
1394 printer->Print(vars,
1395 "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
1396 " $classname$_descriptor_,\n"
1397 " ::google::protobuf::internal::MapEntry<\n"
1398 " $key$,\n"
1399 " $val$,\n"
Jisi Liu885b6122015-02-28 14:51:22 -08001400 " $key_wire_type$,\n"
1401 " $val_wire_type$,\n"
Feng Xiaof157a562014-11-14 11:50:31 -08001402 " $default_enum_value$>::CreateDefaultInstance(\n"
1403 " $classname$_descriptor_));\n");
1404 }
kenton@google.comd37d46d2009-04-25 02:53:47 +00001405
1406 // Handle nested types.
1407 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1408 nested_generators_[i]->GenerateTypeRegistrations(printer);
1409 }
1410}
1411
1412void MessageGenerator::
1413GenerateDefaultInstanceAllocator(io::Printer* printer) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001414 // Construct the default instances of all fields, as they will be used
1415 // when creating the default instance of the entire message.
1416 for (int i = 0; i < descriptor_->field_count(); i++) {
1417 field_generators_.get(descriptor_->field(i))
1418 .GenerateDefaultInstanceAllocator(printer);
1419 }
1420
Feng Xiaof157a562014-11-14 11:50:31 -08001421 if (IsMapEntryMessage(descriptor_)) return;
1422
kenton@google.comd37d46d2009-04-25 02:53:47 +00001423 // Construct the default instance. We can't call InitAsDefaultInstance() yet
1424 // because we need to make sure all default instances that this one might
1425 // depend on are constructed first.
1426 printer->Print(
1427 "$classname$::default_instance_ = new $classname$();\n",
1428 "classname", classname_);
1429
jieluo@google.com4de8f552014-07-18 00:47:59 +00001430 if ((descriptor_->oneof_decl_count() > 0) &&
1431 HasDescriptorMethods(descriptor_->file())) {
1432 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001433 "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001434 "classname", classname_);
1435 }
1436
kenton@google.comd37d46d2009-04-25 02:53:47 +00001437 // Handle nested types.
1438 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1439 nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
1440 }
kenton@google.comfccb1462009-12-18 02:11:36 +00001441
kenton@google.com24bf56f2008-09-24 20:31:01 +00001442}
1443
1444void MessageGenerator::
1445GenerateDefaultInstanceInitializer(io::Printer* printer) {
1446 printer->Print(
1447 "$classname$::default_instance_->InitAsDefaultInstance();\n",
1448 "classname", classname_);
1449
kenton@google.comd37d46d2009-04-25 02:53:47 +00001450 // Register extensions.
1451 for (int i = 0; i < descriptor_->extension_count(); i++) {
1452 extension_generators_[i]->GenerateRegistration(printer);
1453 }
1454
kenton@google.com24bf56f2008-09-24 20:31:01 +00001455 // Handle nested types.
1456 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -08001457 // map entry message doesn't need to initialize default instance manually.
1458 // Since map entry message cannot be a top level class, we just need to
1459 // avoid calling DefaultInstanceInitializer here.
1460 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
kenton@google.com24bf56f2008-09-24 20:31:01 +00001461 nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
1462 }
temporal40ee5512008-07-10 02:12:20 +00001463}
1464
1465void MessageGenerator::
kenton@google.com63e646b2009-05-06 19:27:03 +00001466GenerateShutdownCode(io::Printer* printer) {
1467 printer->Print(
liujisi@google.com2273ee42012-12-05 23:47:43 +00001468 "delete $classname$::default_instance_;\n",
kenton@google.com63e646b2009-05-06 19:27:03 +00001469 "classname", classname_);
1470
kenton@google.com80b1d622009-07-29 01:13:20 +00001471 if (HasDescriptorMethods(descriptor_->file())) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001472 if (descriptor_->oneof_decl_count() > 0) {
1473 printer->Print(
1474 "delete $classname$_default_oneof_instance_;\n",
1475 "classname", classname_);
1476 }
kenton@google.com80b1d622009-07-29 01:13:20 +00001477 printer->Print(
liujisi@google.com2273ee42012-12-05 23:47:43 +00001478 "delete $classname$_reflection_;\n",
kenton@google.com80b1d622009-07-29 01:13:20 +00001479 "classname", classname_);
1480 }
1481
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001482 // Handle default instances of fields.
1483 for (int i = 0; i < descriptor_->field_count(); i++) {
1484 field_generators_.get(descriptor_->field(i))
1485 .GenerateShutdownCode(printer);
1486 }
1487
kenton@google.com63e646b2009-05-06 19:27:03 +00001488 // Handle nested types.
1489 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -08001490 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
kenton@google.com63e646b2009-05-06 19:27:03 +00001491 nested_generators_[i]->GenerateShutdownCode(printer);
1492 }
1493}
1494
1495void MessageGenerator::
temporal40ee5512008-07-10 02:12:20 +00001496GenerateClassMethods(io::Printer* printer) {
1497 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
1498 enum_generators_[i]->GenerateMethods(printer);
1499 }
1500
1501 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
Feng Xiaof157a562014-11-14 11:50:31 -08001502 // map entry message doesn't need class methods. Since map entry message
1503 // cannot be a top level class, we just need to avoid calling
1504 // GenerateClassMethods here.
1505 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
temporal40ee5512008-07-10 02:12:20 +00001506 nested_generators_[i]->GenerateClassMethods(printer);
1507 printer->Print("\n");
1508 printer->Print(kThinSeparator);
1509 printer->Print("\n");
1510 }
1511
temporal40ee5512008-07-10 02:12:20 +00001512 // Generate non-inline field definitions.
1513 for (int i = 0; i < descriptor_->field_count(); i++) {
1514 field_generators_.get(descriptor_->field(i))
1515 .GenerateNonInlineAccessorDefinitions(printer);
temporal40ee5512008-07-10 02:12:20 +00001516 }
1517
kenton@google.comcfa2d8a2009-04-18 00:02:12 +00001518 // Generate field number constants.
1519 printer->Print("#ifndef _MSC_VER\n");
1520 for (int i = 0; i < descriptor_->field_count(); i++) {
1521 const FieldDescriptor *field = descriptor_->field(i);
1522 printer->Print(
1523 "const int $classname$::$constant_name$;\n",
1524 "classname", ClassName(FieldScope(field), false),
1525 "constant_name", FieldConstantName(field));
1526 }
1527 printer->Print(
1528 "#endif // !_MSC_VER\n"
1529 "\n");
1530
temporal40ee5512008-07-10 02:12:20 +00001531 // Define extension identifiers.
1532 for (int i = 0; i < descriptor_->extension_count(); i++) {
1533 extension_generators_[i]->GenerateDefinition(printer);
1534 }
1535
temporal40ee5512008-07-10 02:12:20 +00001536 GenerateStructors(printer);
1537 printer->Print("\n");
1538
jieluo@google.com4de8f552014-07-18 00:47:59 +00001539 if (descriptor_->oneof_decl_count() > 0) {
1540 GenerateOneofClear(printer);
1541 printer->Print("\n");
1542 }
1543
kenton@google.com80b1d622009-07-29 01:13:20 +00001544 if (HasGeneratedMethods(descriptor_->file())) {
temporal40ee5512008-07-10 02:12:20 +00001545 GenerateClear(printer);
1546 printer->Print("\n");
1547
kenton@google.com80b1d622009-07-29 01:13:20 +00001548 GenerateMergeFromCodedStream(printer);
1549 printer->Print("\n");
temporal40ee5512008-07-10 02:12:20 +00001550
kenton@google.com80b1d622009-07-29 01:13:20 +00001551 GenerateSerializeWithCachedSizes(printer);
1552 printer->Print("\n");
temporal40ee5512008-07-10 02:12:20 +00001553
kenton@google.com80b1d622009-07-29 01:13:20 +00001554 if (HasFastArraySerialization(descriptor_->file())) {
kenton@google.comd37d46d2009-04-25 02:53:47 +00001555 GenerateSerializeWithCachedSizesToArray(printer);
1556 printer->Print("\n");
kenton@google.comd37d46d2009-04-25 02:53:47 +00001557 }
temporal40ee5512008-07-10 02:12:20 +00001558
kenton@google.com80b1d622009-07-29 01:13:20 +00001559 GenerateByteSize(printer);
1560 printer->Print("\n");
1561
temporal40ee5512008-07-10 02:12:20 +00001562 GenerateMergeFrom(printer);
1563 printer->Print("\n");
1564
1565 GenerateCopyFrom(printer);
1566 printer->Print("\n");
1567
1568 GenerateIsInitialized(printer);
1569 printer->Print("\n");
1570 }
1571
kenton@google.comceb561d2009-06-25 19:05:36 +00001572 GenerateSwap(printer);
1573 printer->Print("\n");
1574
kenton@google.com80b1d622009-07-29 01:13:20 +00001575 if (HasDescriptorMethods(descriptor_->file())) {
1576 printer->Print(
1577 "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
1578 " protobuf_AssignDescriptorsOnce();\n"
1579 " ::google::protobuf::Metadata metadata;\n"
1580 " metadata.descriptor = $classname$_descriptor_;\n"
1581 " metadata.reflection = $classname$_reflection_;\n"
1582 " return metadata;\n"
1583 "}\n"
1584 "\n",
1585 "classname", classname_);
1586 } else {
1587 printer->Print(
1588 "::std::string $classname$::GetTypeName() const {\n"
1589 " return \"$type_name$\";\n"
1590 "}\n"
1591 "\n",
1592 "classname", classname_,
1593 "type_name", descriptor_->full_name());
1594 }
kenton@google.comfccb1462009-12-18 02:11:36 +00001595
temporal40ee5512008-07-10 02:12:20 +00001596}
1597
1598void MessageGenerator::
1599GenerateOffsets(io::Printer* printer) {
1600 printer->Print(
kenton@google.com3e91fcd2008-11-06 04:37:30 +00001601 "static const int $classname$_offsets_[$field_count$] = {\n",
temporal40ee5512008-07-10 02:12:20 +00001602 "classname", classname_,
jieluo@google.com4de8f552014-07-18 00:47:59 +00001603 "field_count", SimpleItoa(max(
1604 1, descriptor_->field_count() + descriptor_->oneof_decl_count())));
temporal40ee5512008-07-10 02:12:20 +00001605 printer->Indent();
1606
1607 for (int i = 0; i < descriptor_->field_count(); i++) {
1608 const FieldDescriptor* field = descriptor_->field(i);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001609 if (field->containing_oneof()) {
1610 printer->Print(
1611 "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET("
1612 "$classname$_default_oneof_instance_, $name$_),\n",
1613 "classname", classname_,
1614 "name", FieldName(field));
1615 } else {
1616 printer->Print(
1617 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
1618 "$name$_),\n",
1619 "classname", classname_,
1620 "name", FieldName(field));
1621 }
1622 }
1623
1624 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1625 const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
temporal40ee5512008-07-10 02:12:20 +00001626 printer->Print(
1627 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
1628 "classname", classname_,
jieluo@google.com4de8f552014-07-18 00:47:59 +00001629 "name", oneof->name());
temporal40ee5512008-07-10 02:12:20 +00001630 }
1631
1632 printer->Outdent();
1633 printer->Print("};\n");
1634}
1635
1636void MessageGenerator::
kenton@google.comd37d46d2009-04-25 02:53:47 +00001637GenerateSharedConstructorCode(io::Printer* printer) {
1638 printer->Print(
1639 "void $classname$::SharedCtor() {\n",
1640 "classname", classname_);
1641 printer->Indent();
1642
Feng Xiaoc25d9fe2014-11-26 16:15:29 -08001643 if (!HasFieldPresence(descriptor_->file())) {
1644 printer->Print(
1645 " _is_default_instance_ = false;\n");
1646 }
1647
jieluo@google.com4de8f552014-07-18 00:47:59 +00001648 printer->Print(StrCat(
1649 uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "",
1650 "_cached_size_ = 0;\n").c_str());
kenton@google.comd37d46d2009-04-25 02:53:47 +00001651
1652 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001653 if (!descriptor_->field(i)->containing_oneof()) {
1654 field_generators_.get(descriptor_->field(i))
1655 .GenerateConstructorCode(printer);
1656 }
temporal40ee5512008-07-10 02:12:20 +00001657 }
1658
Feng Xiao6ef984a2014-11-10 17:34:54 -08001659 if (HasFieldPresence(descriptor_->file())) {
1660 printer->Print(
1661 "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
1662 }
temporal40ee5512008-07-10 02:12:20 +00001663
jieluo@google.com4de8f552014-07-18 00:47:59 +00001664 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1665 printer->Print(
1666 "clear_has_$oneof_name$();\n",
1667 "oneof_name", descriptor_->oneof_decl(i)->name());
1668 }
1669
kenton@google.comd37d46d2009-04-25 02:53:47 +00001670 printer->Outdent();
1671 printer->Print("}\n\n");
1672}
1673
1674void MessageGenerator::
1675GenerateSharedDestructorCode(io::Printer* printer) {
1676 printer->Print(
1677 "void $classname$::SharedDtor() {\n",
1678 "classname", classname_);
1679 printer->Indent();
Feng Xiao6ef984a2014-11-10 17:34:54 -08001680 if (SupportsArenas(descriptor_)) {
1681 // Do nothing when the message is allocated in an arena.
1682 printer->Print(
1683 "if (GetArenaNoVirtual() != NULL) {\n"
1684 " return;\n"
1685 "}\n"
1686 "\n");
1687 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00001688 // Write the destructors for each field except oneof members.
temporal40ee5512008-07-10 02:12:20 +00001689 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001690 if (!descriptor_->field(i)->containing_oneof()) {
1691 field_generators_.get(descriptor_->field(i))
1692 .GenerateDestructorCode(printer);
1693 }
1694 }
1695
1696 // Generate code to destruct oneofs. Clearing should do the work.
1697 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1698 printer->Print(
1699 "if (has_$oneof_name$()) {\n"
1700 " clear_$oneof_name$();\n"
1701 "}\n",
1702 "oneof_name", descriptor_->oneof_decl(i)->name());
kenton@google.comd37d46d2009-04-25 02:53:47 +00001703 }
1704
pliard@google.com6103d4e2012-05-04 11:16:09 +00001705 PrintHandlingOptionalStaticInitializers(
1706 descriptor_->file(), printer,
1707 // With static initializers.
1708 "if (this != default_instance_) {\n",
1709 // Without.
1710 "if (this != &default_instance()) {\n");
kenton@google.comd37d46d2009-04-25 02:53:47 +00001711
1712 // We need to delete all embedded messages.
1713 // TODO(kenton): If we make unset messages point at default instances
1714 // instead of NULL, then it would make sense to move this code into
1715 // MessageFieldGenerator::GenerateDestructorCode().
1716 for (int i = 0; i < descriptor_->field_count(); i++) {
1717 const FieldDescriptor* field = descriptor_->field(i);
1718
1719 if (!field->is_repeated() &&
1720 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001721 // Skip oneof members
1722 if (!field->containing_oneof()) {
1723 printer->Print(
1724 " delete $name$_;\n",
1725 "name", FieldName(field));
1726 }
kenton@google.comd37d46d2009-04-25 02:53:47 +00001727 }
temporal40ee5512008-07-10 02:12:20 +00001728 }
1729
1730 printer->Outdent();
kenton@google.comd37d46d2009-04-25 02:53:47 +00001731 printer->Print(
1732 " }\n"
1733 "}\n"
1734 "\n");
temporal40ee5512008-07-10 02:12:20 +00001735}
1736
1737void MessageGenerator::
Feng Xiao6ef984a2014-11-10 17:34:54 -08001738GenerateArenaDestructorCode(io::Printer* printer) {
1739 // Generate the ArenaDtor() method. Track whether any fields actually produced
1740 // code that needs to be called.
1741 printer->Print(
1742 "void $classname$::ArenaDtor(void* object) {\n",
1743 "classname", classname_);
1744 printer->Indent();
1745
1746 // This code is placed inside a static method, rather than an ordinary one,
1747 // since that simplifies Arena's destructor list (ordinary function pointers
1748 // rather than member function pointers). _this is the object being
1749 // destructed.
1750 printer->Print(
1751 "$classname$* _this = reinterpret_cast< $classname$* >(object);\n"
1752 // avoid an "unused variable" warning in case no fields have dtor code.
1753 "(void)_this;\n",
1754 "classname", classname_);
1755
1756 bool need_registration = false;
1757 for (int i = 0; i < descriptor_->field_count(); i++) {
1758 if (field_generators_.get(descriptor_->field(i))
1759 .GenerateArenaDestructorCode(printer)) {
1760 need_registration = true;
1761 }
1762 }
1763 printer->Outdent();
1764 printer->Print(
1765 "}\n");
1766
1767 if (need_registration) {
1768 printer->Print(
1769 "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
1770 " if (arena != NULL) {"
1771 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
1772 " }\n"
1773 "}\n",
1774 "classname", classname_);
1775 } else {
1776 printer->Print(
1777 "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
1778 "}\n",
1779 "classname", classname_);
1780 }
1781}
1782
1783void MessageGenerator::
temporal40ee5512008-07-10 02:12:20 +00001784GenerateStructors(io::Printer* printer) {
kenton@google.comfccb1462009-12-18 02:11:36 +00001785 string superclass = SuperClassName(descriptor_);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001786 string initializer_with_arena;
1787 if (UseUnknownFieldSet(descriptor_->file())) {
1788 initializer_with_arena = "_internal_metadata_(arena)";
1789 } else {
1790 initializer_with_arena = "_arena_ptr_(arena)";
1791 }
1792 if (descriptor_->extension_range_count() > 0) {
1793 initializer_with_arena = string("\n _extensions_(arena)") +
1794 (!initializer_with_arena.empty() ? ", " : "") + initializer_with_arena;
1795 } else {
1796 initializer_with_arena = "\n " + initializer_with_arena;
1797 }
kenton@google.comfccb1462009-12-18 02:11:36 +00001798
Feng Xiao6ef984a2014-11-10 17:34:54 -08001799 // Initialize member variables with arena constructor.
1800 for (int i = 0; i < descriptor_->field_count(); i++) {
1801 bool has_arena_constructor = descriptor_->field(i)->is_repeated();
1802 if (has_arena_constructor) {
1803 initializer_with_arena += string(",\n ") +
1804 FieldName(descriptor_->field(i)) + string("_(arena)");
1805 }
1806 }
1807 initializer_with_arena = superclass + "()" +
1808 (!initializer_with_arena.empty() ? "," : " ") + initializer_with_arena;
1809
1810 string initializer_null;
1811 initializer_null = (UseUnknownFieldSet(descriptor_->file()) ?
1812 ", _internal_metadata_(NULL) " : ", _arena_ptr_(NULL)");
1813
temporal40ee5512008-07-10 02:12:20 +00001814 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001815 "$classname$::$classname$()\n"
1816 " : $superclass$() $initializer$ {\n"
1817 " SharedCtor();\n"
1818 " // @@protoc_insertion_point(constructor:$full_name$)\n"
1819 "}\n",
1820 "classname", classname_,
1821 "superclass", superclass,
1822 "full_name", descriptor_->full_name(),
1823 "initializer", initializer_null);
1824
1825 if (SupportsArenas(descriptor_)) {
1826 printer->Print(
1827 "\n"
1828 "$classname$::$classname$(::google::protobuf::Arena* arena)\n"
1829 " : $initializer$ {\n"
1830 " SharedCtor();\n"
1831 " RegisterArenaDtor(arena);\n"
1832 " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
1833 "}\n",
1834 "initializer", initializer_with_arena,
1835 "classname", classname_,
1836 "superclass", superclass,
1837 "full_name", descriptor_->full_name());
1838 }
kenton@google.com24bf56f2008-09-24 20:31:01 +00001839
1840 printer->Print(
1841 "\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001842 "void $classname$::InitAsDefaultInstance() {\n",
kenton@google.com24bf56f2008-09-24 20:31:01 +00001843 "classname", classname_);
temporal40ee5512008-07-10 02:12:20 +00001844
Feng Xiaoc25d9fe2014-11-26 16:15:29 -08001845 if (!HasFieldPresence(descriptor_->file())) {
1846 printer->Print(
1847 " _is_default_instance_ = true;\n");
1848 }
1849
temporal40ee5512008-07-10 02:12:20 +00001850 // The default instance needs all of its embedded message pointers
kenton@google.com24bf56f2008-09-24 20:31:01 +00001851 // cross-linked to other default instances. We can't do this initialization
1852 // in the constructor because some other default instances may not have been
1853 // constructed yet at that time.
temporal40ee5512008-07-10 02:12:20 +00001854 // TODO(kenton): Maybe all message fields (even for non-default messages)
1855 // should be initialized to point at default instances rather than NULL?
1856 for (int i = 0; i < descriptor_->field_count(); i++) {
1857 const FieldDescriptor* field = descriptor_->field(i);
1858
1859 if (!field->is_repeated() &&
jieluo@google.com4de8f552014-07-18 00:47:59 +00001860 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
1861 (field->containing_oneof() == NULL ||
1862 HasDescriptorMethods(descriptor_->file()))) {
1863 string name;
1864 if (field->containing_oneof()) {
1865 name = classname_ + "_default_oneof_instance_->";
1866 }
1867 name += FieldName(field);
pliard@google.com6103d4e2012-05-04 11:16:09 +00001868 PrintHandlingOptionalStaticInitializers(
1869 descriptor_->file(), printer,
1870 // With static initializers.
1871 " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
1872 // Without.
1873 " $name$_ = const_cast< $type$*>(\n"
1874 " $type$::internal_default_instance());\n",
1875 // Vars.
jieluo@google.com4de8f552014-07-18 00:47:59 +00001876 "name", name,
pliard@google.com6103d4e2012-05-04 11:16:09 +00001877 "type", FieldMessageTypeName(field));
jieluo@google.com4de8f552014-07-18 00:47:59 +00001878 } else if (field->containing_oneof() &&
1879 HasDescriptorMethods(descriptor_->file())) {
1880 field_generators_.get(descriptor_->field(i))
1881 .GenerateConstructorCode(printer);
temporal40ee5512008-07-10 02:12:20 +00001882 }
1883 }
1884 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00001885 "}\n"
1886 "\n");
1887
1888 // Generate the copy constructor.
1889 printer->Print(
kenton@google.com573989f2009-10-30 22:02:17 +00001890 "$classname$::$classname$(const $classname$& from)\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -08001891 " : $superclass$()",
1892 "classname", classname_,
1893 "superclass", superclass,
1894 "full_name", descriptor_->full_name());
1895 if (UseUnknownFieldSet(descriptor_->file())) {
1896 printer->Print(
1897 ",\n _internal_metadata_(NULL) {\n");
1898 } else if (!UseUnknownFieldSet(descriptor_->file())) {
1899 printer->Print(",\n _arena_ptr_(NULL) {\n");
1900 }
1901 printer->Print(
kenton@google.comd37d46d2009-04-25 02:53:47 +00001902 " SharedCtor();\n"
temporal40ee5512008-07-10 02:12:20 +00001903 " MergeFrom(from);\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001904 " // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
temporal40ee5512008-07-10 02:12:20 +00001905 "}\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001906 "\n",
kenton@google.com573989f2009-10-30 22:02:17 +00001907 "classname", classname_,
jieluo@google.com4de8f552014-07-18 00:47:59 +00001908 "superclass", superclass,
1909 "full_name", descriptor_->full_name());
temporal40ee5512008-07-10 02:12:20 +00001910
kenton@google.comd37d46d2009-04-25 02:53:47 +00001911 // Generate the shared constructor code.
1912 GenerateSharedConstructorCode(printer);
1913
temporal40ee5512008-07-10 02:12:20 +00001914 // Generate the destructor.
1915 printer->Print(
kenton@google.comd37d46d2009-04-25 02:53:47 +00001916 "$classname$::~$classname$() {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001917 " // @@protoc_insertion_point(destructor:$full_name$)\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +00001918 " SharedDtor();\n"
1919 "}\n"
1920 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001921 "classname", classname_,
1922 "full_name", descriptor_->full_name());
temporal40ee5512008-07-10 02:12:20 +00001923
kenton@google.comd37d46d2009-04-25 02:53:47 +00001924 // Generate the shared destructor code.
1925 GenerateSharedDestructorCode(printer);
temporal40ee5512008-07-10 02:12:20 +00001926
Feng Xiao6ef984a2014-11-10 17:34:54 -08001927 // Generate the arena-specific destructor code.
1928 if (SupportsArenas(descriptor_)) {
1929 GenerateArenaDestructorCode(printer);
1930 }
1931
kenton@google.comfccb1462009-12-18 02:11:36 +00001932 // Generate SetCachedSize.
1933 printer->Print(
1934 "void $classname$::SetCachedSize(int size) const {\n"
1935 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
1936 " _cached_size_ = size;\n"
1937 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
1938 "}\n",
1939 "classname", classname_);
1940
kenton@google.com80b1d622009-07-29 01:13:20 +00001941 // Only generate this member if it's not disabled.
1942 if (HasDescriptorMethods(descriptor_->file()) &&
1943 !descriptor_->options().no_standard_descriptor_accessor()) {
1944 printer->Print(
1945 "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
1946 " protobuf_AssignDescriptorsOnce();\n"
1947 " return $classname$_descriptor_;\n"
1948 "}\n"
1949 "\n",
1950 "classname", classname_,
1951 "adddescriptorsname",
1952 GlobalAddDescriptorsName(descriptor_->file()->name()));
1953 }
1954
temporal40ee5512008-07-10 02:12:20 +00001955 printer->Print(
pliard@google.com6103d4e2012-05-04 11:16:09 +00001956 "const $classname$& $classname$::default_instance() {\n",
1957 "classname", classname_);
1958
1959 PrintHandlingOptionalStaticInitializers(
1960 descriptor_->file(), printer,
1961 // With static initializers.
1962 " if (default_instance_ == NULL) $adddescriptorsname$();\n",
1963 // Without.
1964 " $adddescriptorsname$();\n",
1965 // Vars.
1966 "adddescriptorsname",
1967 GlobalAddDescriptorsName(descriptor_->file()->name()));
1968
1969 printer->Print(
kenton@google.com24bf56f2008-09-24 20:31:01 +00001970 " return *default_instance_;\n"
1971 "}\n"
1972 "\n"
1973 "$classname$* $classname$::default_instance_ = NULL;\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001974 "\n",
1975 "classname", classname_);
1976
Feng Xiao6ef984a2014-11-10 17:34:54 -08001977 if (SupportsArenas(descriptor_)) {
1978 printer->Print(
1979 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
1980 " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n"
1981 "}\n",
1982 "classname", classname_);
1983 } else {
1984 printer->Print(
1985 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
1986 " $classname$* n = new $classname$;\n"
1987 " if (arena != NULL) {\n"
1988 " arena->Own(n);\n"
1989 " }\n"
1990 " return n;\n"
1991 "}\n",
1992 "classname", classname_);
1993 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00001994
1995}
1996
1997// Return the number of bits set in n, a non-negative integer.
1998static int popcnt(uint32 n) {
1999 int result = 0;
2000 while (n != 0) {
2001 result += (n & 1);
2002 n = n / 2;
2003 }
2004 return result;
temporal40ee5512008-07-10 02:12:20 +00002005}
2006
2007void MessageGenerator::
2008GenerateClear(io::Printer* printer) {
2009 printer->Print("void $classname$::Clear() {\n",
2010 "classname", classname_);
2011 printer->Indent();
2012
jieluo@google.com4de8f552014-07-18 00:47:59 +00002013 // Step 1: Extensions
temporal40ee5512008-07-10 02:12:20 +00002014 if (descriptor_->extension_range_count() > 0) {
2015 printer->Print("_extensions_.Clear();\n");
2016 }
2017
jieluo@google.com4de8f552014-07-18 00:47:59 +00002018 // Step 2: Everything but extensions, repeateds, unions.
2019 // These are handled in chunks of 8. The first chunk is
2020 // the non-extensions-non-repeateds-non-unions in
2021 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
2022 // and the second chunk is the same for
2023 // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15),
2024 // etc.
2025 set<int> step2_indices;
2026 hash_map<string, int> fieldname_to_chunk;
2027 hash_map<int, string> memsets_for_chunk;
2028 hash_map<int, int> memset_field_count_for_chunk;
2029 hash_set<string> handled; // fields that appear anywhere in memsets_for_chunk
2030 hash_map<int, uint32> fields_mask_for_chunk;
temporal40ee5512008-07-10 02:12:20 +00002031 for (int i = 0; i < descriptor_->field_count(); i++) {
2032 const FieldDescriptor* field = descriptor_->field(i);
jieluo@google.com4de8f552014-07-18 00:47:59 +00002033 if (!field->is_repeated() && !field->containing_oneof()) {
2034 step2_indices.insert(i);
2035 int chunk = i / 8;
2036 fieldname_to_chunk[FieldName(field)] = chunk;
2037 fields_mask_for_chunk[chunk] |= static_cast<uint32>(1) << (i % 32);
temporal40ee5512008-07-10 02:12:20 +00002038 }
2039 }
2040
jieluo@google.com4de8f552014-07-18 00:47:59 +00002041 // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0.
2042 // The generated code uses two macros to help it clear runs of fields:
Jisi Liu885b6122015-02-28 14:51:22 -08002043 // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the
2044 // positions of two fields in the Message.
jieluo@google.com4de8f552014-07-18 00:47:59 +00002045 // ZR_ zeroes a non-empty range of fields via memset.
2046 const char* macros =
Jisi Liu885b6122015-02-28 14:51:22 -08002047 "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
2048 " &reinterpret_cast<$classname$*>(16)->f)\n\n"
2049 "#define ZR_(first, last) do {\\\n"
2050 " ::memset(&first, 0,\\\n"
2051 " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
2052 "} while (0)\n\n";
jieluo@google.com4de8f552014-07-18 00:47:59 +00002053 for (int i = 0; i < runs_of_fields_.size(); i++) {
2054 const vector<string>& run = runs_of_fields_[i];
2055 if (run.size() < 2) continue;
2056 const string& first_field_name = run[0];
2057 const string& last_field_name = run.back();
2058 int chunk = fieldname_to_chunk[run[0]];
2059 memsets_for_chunk[chunk].append(
2060 "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n");
2061 for (int j = 0; j < run.size(); j++) {
2062 GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]);
2063 handled.insert(run[j]);
2064 }
2065 memset_field_count_for_chunk[chunk] += run.size();
2066 }
2067 const bool macros_are_needed = handled.size() > 0;
2068 if (macros_are_needed) {
2069 printer->Outdent();
2070 printer->Print(macros,
2071 "classname", classname_);
2072 printer->Indent();
2073 }
2074 // Step 2b: Finish step 2, ignoring fields handled in step 2a.
2075 int last_index = -1;
2076 bool chunk_block_in_progress = false;
2077 for (int i = 0; i < descriptor_->field_count(); i++) {
2078 if (step2_indices.count(i) == 0) continue;
2079 const FieldDescriptor* field = descriptor_->field(i);
2080 const string fieldname = FieldName(field);
2081 if (i / 8 != last_index / 8 || last_index < 0) {
2082 // End previous chunk, if there was one.
2083 if (chunk_block_in_progress) {
2084 printer->Outdent();
2085 printer->Print("}\n");
2086 chunk_block_in_progress = false;
2087 }
2088 // Start chunk.
2089 const string& memsets = memsets_for_chunk[i / 8];
2090 uint32 mask = fields_mask_for_chunk[i / 8];
2091 int count = popcnt(mask);
Feng Xiao6ef984a2014-11-10 17:34:54 -08002092 GOOGLE_DCHECK_GE(count, 1);
jieluo@google.com4de8f552014-07-18 00:47:59 +00002093 if (count == 1 ||
2094 (count <= 4 && count == memset_field_count_for_chunk[i / 8])) {
2095 // No "if" here because the chunk is trivial.
2096 } else {
Feng Xiao6ef984a2014-11-10 17:34:54 -08002097 if (HasFieldPresence(descriptor_->file())) {
2098 printer->Print(
2099 "if (_has_bits_[$index$ / 32] & $mask$) {\n",
2100 "index", SimpleItoa(i / 8 * 8),
2101 "mask", SimpleItoa(mask));
2102 printer->Indent();
2103 chunk_block_in_progress = true;
2104 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00002105 }
2106 printer->Print(memsets.c_str());
2107 }
2108 last_index = i;
2109 if (handled.count(fieldname) > 0) continue;
2110
2111 // It's faster to just overwrite primitive types, but we should
2112 // only clear strings and messages if they were set.
2113 // TODO(kenton): Let the CppFieldGenerator decide this somehow.
2114 bool should_check_bit =
2115 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
2116 field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
2117
Feng Xiao6ef984a2014-11-10 17:34:54 -08002118 bool have_enclosing_if = false;
2119 if (should_check_bit &&
2120 // If no field presence, then always clear strings/messages as well.
2121 HasFieldPresence(descriptor_->file())) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00002122 printer->Print("if (has_$name$()) {\n", "name", fieldname);
2123 printer->Indent();
Feng Xiao6ef984a2014-11-10 17:34:54 -08002124 have_enclosing_if = true;
jieluo@google.com4de8f552014-07-18 00:47:59 +00002125 }
2126
2127 field_generators_.get(field).GenerateClearingCode(printer);
2128
Feng Xiao6ef984a2014-11-10 17:34:54 -08002129 if (have_enclosing_if) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00002130 printer->Outdent();
2131 printer->Print("}\n");
2132 }
2133 }
2134
2135 if (chunk_block_in_progress) {
temporal40ee5512008-07-10 02:12:20 +00002136 printer->Outdent();
2137 printer->Print("}\n");
2138 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00002139 if (macros_are_needed) {
2140 printer->Outdent();
Jisi Liu885b6122015-02-28 14:51:22 -08002141 printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +00002142 printer->Indent();
2143 }
temporal40ee5512008-07-10 02:12:20 +00002144
jieluo@google.com4de8f552014-07-18 00:47:59 +00002145 // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here.
temporal40ee5512008-07-10 02:12:20 +00002146 for (int i = 0; i < descriptor_->field_count(); i++) {
2147 const FieldDescriptor* field = descriptor_->field(i);
2148
2149 if (field->is_repeated()) {
2150 field_generators_.get(field).GenerateClearingCode(printer);
2151 }
2152 }
2153
jieluo@google.com4de8f552014-07-18 00:47:59 +00002154 // Step 4: Unions.
2155 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
2156 printer->Print(
2157 "clear_$oneof_name$();\n",
2158 "oneof_name", descriptor_->oneof_decl(i)->name());
2159 }
2160
Feng Xiao6ef984a2014-11-10 17:34:54 -08002161 if (HasFieldPresence(descriptor_->file())) {
2162 // Step 5: Everything else.
2163 printer->Print(
2164 "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
2165 }
kenton@google.com80b1d622009-07-29 01:13:20 +00002166
Feng Xiao6ef984a2014-11-10 17:34:54 -08002167 if (PreserveUnknownFields(descriptor_)) {
2168 if (UseUnknownFieldSet(descriptor_->file())) {
2169 printer->Print(
2170 "if (_internal_metadata_.have_unknown_fields()) {\n"
2171 " mutable_unknown_fields()->Clear();\n"
2172 "}\n");
2173 } else {
2174 printer->Print(
2175 "mutable_unknown_fields()->clear();\n");
2176 }
kenton@google.com80b1d622009-07-29 01:13:20 +00002177 }
temporal40ee5512008-07-10 02:12:20 +00002178
2179 printer->Outdent();
2180 printer->Print("}\n");
2181}
2182
2183void MessageGenerator::
jieluo@google.com4de8f552014-07-18 00:47:59 +00002184GenerateOneofClear(io::Printer* printer) {
2185 // Generated function clears the active field and union case (e.g. foo_case_).
2186 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
2187 printer->Print(
2188 "void $classname$::clear_$oneofname$() {\n",
2189 "classname", classname_,
2190 "oneofname", descriptor_->oneof_decl(i)->name());
2191 printer->Indent();
2192 printer->Print(
2193 "switch($oneofname$_case()) {\n",
2194 "oneofname", descriptor_->oneof_decl(i)->name());
2195 printer->Indent();
2196 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
2197 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
2198 printer->Print(
2199 "case k$field_name$: {\n",
2200 "field_name", UnderscoresToCamelCase(field->name(), true));
2201 printer->Indent();
2202 // We clear only allocated objects in oneofs
2203 if (!IsStringOrMessage(field)) {
2204 printer->Print(
2205 "// No need to clear\n");
2206 } else {
2207 field_generators_.get(field).GenerateClearingCode(printer);
2208 }
2209 printer->Print(
2210 "break;\n");
2211 printer->Outdent();
2212 printer->Print(
2213 "}\n");
2214 }
2215 printer->Print(
2216 "case $cap_oneof_name$_NOT_SET: {\n"
2217 " break;\n"
2218 "}\n",
2219 "cap_oneof_name",
2220 ToUpper(descriptor_->oneof_decl(i)->name()));
2221 printer->Outdent();
2222 printer->Print(
2223 "}\n"
2224 "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n",
2225 "oneof_index", SimpleItoa(i),
2226 "cap_oneof_name",
2227 ToUpper(descriptor_->oneof_decl(i)->name()));
2228 printer->Outdent();
2229 printer->Print(
2230 "}\n"
2231 "\n");
2232 }
2233}
2234
2235void MessageGenerator::
kenton@google.com26bd9ee2008-11-21 00:06:27 +00002236GenerateSwap(io::Printer* printer) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08002237 if (SupportsArenas(descriptor_)) {
2238 // Generate the Swap member function. This is a lightweight wrapper around
2239 // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory
2240 // ownership situation: swapping across arenas or between an arena and a
2241 // heap requires copying.
2242 printer->Print(
2243 "void $classname$::Swap($classname$* other) {\n"
2244 " if (other == this) return;\n"
2245 " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n"
2246 " InternalSwap(other);\n"
2247 " } else {\n"
2248 " $classname$ temp;\n"
2249 " temp.MergeFrom(*this);\n"
2250 " CopyFrom(*other);\n"
2251 " other->CopyFrom(temp);\n"
2252 " }\n"
2253 "}\n"
2254 "void $classname$::UnsafeArenaSwap($classname$* other) {\n"
2255 " if (other == this) return;\n"
2256 " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n"
2257 " InternalSwap(other);\n"
2258 "}\n",
2259 "classname", classname_);
2260 } else {
2261 printer->Print(
2262 "void $classname$::Swap($classname$* other) {\n"
2263 " if (other == this) return;\n"
2264 " InternalSwap(other);\n"
2265 "}\n",
2266 "classname", classname_);
2267 }
2268
2269 // Generate the UnsafeArenaSwap member function.
2270 printer->Print("void $classname$::InternalSwap($classname$* other) {\n",
kenton@google.com26bd9ee2008-11-21 00:06:27 +00002271 "classname", classname_);
2272 printer->Indent();
kenton@google.com26bd9ee2008-11-21 00:06:27 +00002273
kenton@google.com80b1d622009-07-29 01:13:20 +00002274 if (HasGeneratedMethods(descriptor_->file())) {
kenton@google.comceb561d2009-06-25 19:05:36 +00002275 for (int i = 0; i < descriptor_->field_count(); i++) {
2276 const FieldDescriptor* field = descriptor_->field(i);
2277 field_generators_.get(field).GenerateSwappingCode(printer);
2278 }
2279
jieluo@google.com4de8f552014-07-18 00:47:59 +00002280 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
2281 printer->Print(
2282 "std::swap($oneof_name$_, other->$oneof_name$_);\n"
2283 "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n",
2284 "oneof_name", descriptor_->oneof_decl(i)->name(),
2285 "i", SimpleItoa(i));
2286 }
2287
Feng Xiao6ef984a2014-11-10 17:34:54 -08002288 if (HasFieldPresence(descriptor_->file())) {
2289 for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
2290 printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
2291 "i", SimpleItoa(i));
2292 }
kenton@google.comceb561d2009-06-25 19:05:36 +00002293 }
2294
Feng Xiao6ef984a2014-11-10 17:34:54 -08002295 if (PreserveUnknownFields(descriptor_)) {
2296 if (UseUnknownFieldSet(descriptor_->file())) {
2297 printer->Print(
2298 "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
2299 } else {
2300 printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n");
2301 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00002302 } else {
Feng Xiao6ef984a2014-11-10 17:34:54 -08002303 // Still swap internal_metadata as it may contain more than just
2304 // unknown fields.
2305 printer->Print(
2306 "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002307 }
kenton@google.comceb561d2009-06-25 19:05:36 +00002308 printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
2309 if (descriptor_->extension_range_count() > 0) {
2310 printer->Print("_extensions_.Swap(&other->_extensions_);\n");
2311 }
2312 } else {
2313 printer->Print("GetReflection()->Swap(this, other);");
kenton@google.com26bd9ee2008-11-21 00:06:27 +00002314 }
2315
kenton@google.com26bd9ee2008-11-21 00:06:27 +00002316 printer->Outdent();
2317 printer->Print("}\n");
kenton@google.com26bd9ee2008-11-21 00:06:27 +00002318}
2319
2320void MessageGenerator::
temporal40ee5512008-07-10 02:12:20 +00002321GenerateMergeFrom(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +00002322 if (HasDescriptorMethods(descriptor_->file())) {
2323 // Generate the generalized MergeFrom (aka that which takes in the Message
2324 // base class as a parameter).
2325 printer->Print(
2326 "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
Feng Xiaof157a562014-11-14 11:50:31 -08002327 " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
kenton@google.com80b1d622009-07-29 01:13:20 +00002328 "classname", classname_);
2329 printer->Indent();
temporal40ee5512008-07-10 02:12:20 +00002330
kenton@google.com80b1d622009-07-29 01:13:20 +00002331 // Cast the message to the proper type. If we find that the message is
2332 // *not* of the proper type, we can still call Merge via the reflection
2333 // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
2334 // for each message.
2335 printer->Print(
2336 "const $classname$* source =\n"
2337 " ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
2338 " &from);\n"
2339 "if (source == NULL) {\n"
2340 " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
2341 "} else {\n"
2342 " MergeFrom(*source);\n"
2343 "}\n",
2344 "classname", classname_);
temporal40ee5512008-07-10 02:12:20 +00002345
kenton@google.com80b1d622009-07-29 01:13:20 +00002346 printer->Outdent();
2347 printer->Print("}\n\n");
2348 } else {
2349 // Generate CheckTypeAndMergeFrom().
2350 printer->Print(
2351 "void $classname$::CheckTypeAndMergeFrom(\n"
2352 " const ::google::protobuf::MessageLite& from) {\n"
2353 " MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n"
2354 "}\n"
2355 "\n",
2356 "classname", classname_);
2357 }
temporal40ee5512008-07-10 02:12:20 +00002358
2359 // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
2360 printer->Print(
2361 "void $classname$::MergeFrom(const $classname$& from) {\n"
Feng Xiaof157a562014-11-14 11:50:31 -08002362 " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
temporal40ee5512008-07-10 02:12:20 +00002363 "classname", classname_);
2364 printer->Indent();
2365
2366 // Merge Repeated fields. These fields do not require a
2367 // check as we can simply iterate over them.
2368 for (int i = 0; i < descriptor_->field_count(); ++i) {
2369 const FieldDescriptor* field = descriptor_->field(i);
2370
2371 if (field->is_repeated()) {
2372 field_generators_.get(field).GenerateMergingCode(printer);
2373 }
2374 }
2375
jieluo@google.com4de8f552014-07-18 00:47:59 +00002376 // Merge oneof fields. Oneof field requires oneof case check.
2377 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
2378 printer->Print(
2379 "switch (from.$oneofname$_case()) {\n",
2380 "oneofname", descriptor_->oneof_decl(i)->name());
2381 printer->Indent();
2382 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
2383 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
2384 printer->Print(
2385 "case k$field_name$: {\n",
2386 "field_name", UnderscoresToCamelCase(field->name(), true));
2387 printer->Indent();
2388 field_generators_.get(field).GenerateMergingCode(printer);
2389 printer->Print(
2390 "break;\n");
2391 printer->Outdent();
2392 printer->Print(
2393 "}\n");
2394 }
2395 printer->Print(
2396 "case $cap_oneof_name$_NOT_SET: {\n"
2397 " break;\n"
2398 "}\n",
2399 "cap_oneof_name",
2400 ToUpper(descriptor_->oneof_decl(i)->name()));
2401 printer->Outdent();
2402 printer->Print(
2403 "}\n");
2404 }
2405
temporal40ee5512008-07-10 02:12:20 +00002406 // Merge Optional and Required fields (after a _has_bit check).
2407 int last_index = -1;
2408
2409 for (int i = 0; i < descriptor_->field_count(); ++i) {
2410 const FieldDescriptor* field = descriptor_->field(i);
2411
jieluo@google.com4de8f552014-07-18 00:47:59 +00002412 if (!field->is_repeated() && !field->containing_oneof()) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08002413 if (HasFieldPresence(descriptor_->file())) {
2414 // See above in GenerateClear for an explanation of this.
2415 if (i / 8 != last_index / 8 || last_index < 0) {
2416 if (last_index >= 0) {
2417 printer->Outdent();
2418 printer->Print("}\n");
2419 }
2420 printer->Print(
2421 "if (from._has_bits_[$index$ / 32] & "
2422 "(0xffu << ($index$ % 32))) {\n",
2423 "index", SimpleItoa(field->index()));
2424 printer->Indent();
temporal40ee5512008-07-10 02:12:20 +00002425 }
temporal40ee5512008-07-10 02:12:20 +00002426 }
2427
2428 last_index = i;
2429
Feng Xiao6ef984a2014-11-10 17:34:54 -08002430 bool have_enclosing_if = false;
2431 if (HasFieldPresence(descriptor_->file())) {
2432 printer->Print(
2433 "if (from.has_$name$()) {\n",
2434 "name", FieldName(field));
2435 printer->Indent();
2436 have_enclosing_if = true;
2437 } else {
2438 // Merge semantics without true field presence: primitive fields are
2439 // merged only if non-zero (numeric) or non-empty (string).
2440 have_enclosing_if = EmitFieldNonDefaultCondition(
2441 printer, "from.", field);
2442 }
temporal40ee5512008-07-10 02:12:20 +00002443
2444 field_generators_.get(field).GenerateMergingCode(printer);
2445
Feng Xiao6ef984a2014-11-10 17:34:54 -08002446 if (have_enclosing_if) {
2447 printer->Outdent();
2448 printer->Print("}\n");
2449 }
temporal40ee5512008-07-10 02:12:20 +00002450 }
2451 }
2452
Feng Xiao6ef984a2014-11-10 17:34:54 -08002453 if (HasFieldPresence(descriptor_->file()) &&
2454 last_index >= 0) {
temporal40ee5512008-07-10 02:12:20 +00002455 printer->Outdent();
2456 printer->Print("}\n");
2457 }
2458
2459 if (descriptor_->extension_range_count() > 0) {
2460 printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
2461 }
2462
Feng Xiao6ef984a2014-11-10 17:34:54 -08002463 if (PreserveUnknownFields(descriptor_)) {
2464 if (UseUnknownFieldSet(descriptor_->file())) {
2465 printer->Print(
2466 "if (from._internal_metadata_.have_unknown_fields()) {\n"
2467 " mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"
2468 "}\n");
2469 } else {
2470 printer->Print(
2471 "mutable_unknown_fields()->append(from.unknown_fields());\n");
2472 }
kenton@google.com80b1d622009-07-29 01:13:20 +00002473 }
temporal40ee5512008-07-10 02:12:20 +00002474
2475 printer->Outdent();
2476 printer->Print("}\n");
2477}
2478
2479void MessageGenerator::
2480GenerateCopyFrom(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +00002481 if (HasDescriptorMethods(descriptor_->file())) {
2482 // Generate the generalized CopyFrom (aka that which takes in the Message
2483 // base class as a parameter).
2484 printer->Print(
2485 "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
2486 "classname", classname_);
2487 printer->Indent();
temporal40ee5512008-07-10 02:12:20 +00002488
kenton@google.com80b1d622009-07-29 01:13:20 +00002489 printer->Print(
2490 "if (&from == this) return;\n"
2491 "Clear();\n"
2492 "MergeFrom(from);\n");
temporal40ee5512008-07-10 02:12:20 +00002493
kenton@google.com80b1d622009-07-29 01:13:20 +00002494 printer->Outdent();
2495 printer->Print("}\n\n");
2496 }
temporal40ee5512008-07-10 02:12:20 +00002497
2498 // Generate the class-specific CopyFrom.
2499 printer->Print(
2500 "void $classname$::CopyFrom(const $classname$& from) {\n",
2501 "classname", classname_);
2502 printer->Indent();
2503
2504 printer->Print(
2505 "if (&from == this) return;\n"
2506 "Clear();\n"
2507 "MergeFrom(from);\n");
2508
2509 printer->Outdent();
2510 printer->Print("}\n");
2511}
2512
2513void MessageGenerator::
2514GenerateMergeFromCodedStream(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +00002515 if (descriptor_->options().message_set_wire_format()) {
2516 // Special-case MessageSet.
2517 printer->Print(
2518 "bool $classname$::MergePartialFromCodedStream(\n"
pliard@google.com6103d4e2012-05-04 11:16:09 +00002519 " ::google::protobuf::io::CodedInputStream* input) {\n",
kenton@google.com80b1d622009-07-29 01:13:20 +00002520 "classname", classname_);
pliard@google.com6103d4e2012-05-04 11:16:09 +00002521
2522 PrintHandlingOptionalStaticInitializers(
2523 descriptor_->file(), printer,
2524 // With static initializers.
2525 " return _extensions_.ParseMessageSet(input, default_instance_,\n"
2526 " mutable_unknown_fields());\n",
2527 // Without.
2528 " return _extensions_.ParseMessageSet(input, &default_instance(),\n"
2529 " mutable_unknown_fields());\n",
2530 // Vars.
2531 "classname", classname_);
2532
2533 printer->Print(
2534 "}\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002535 return;
2536 }
2537
temporal40ee5512008-07-10 02:12:20 +00002538 printer->Print(
2539 "bool $classname$::MergePartialFromCodedStream(\n"
2540 " ::google::protobuf::io::CodedInputStream* input) {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00002541 "#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure\n"
2542 " ::google::protobuf::uint32 tag;\n",
temporal40ee5512008-07-10 02:12:20 +00002543 "classname", classname_);
2544
jieluo@google.com4de8f552014-07-18 00:47:59 +00002545 if (!UseUnknownFieldSet(descriptor_->file())) {
2546 printer->Print(
2547 " ::google::protobuf::io::StringOutputStream unknown_fields_string(\n"
2548 " mutable_unknown_fields());\n"
2549 " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
2550 " &unknown_fields_string);\n");
2551 }
2552
2553 printer->Print(
2554 " // @@protoc_insertion_point(parse_start:$full_name$)\n",
2555 "full_name", descriptor_->full_name());
2556
temporal40ee5512008-07-10 02:12:20 +00002557 printer->Indent();
jieluo@google.com4de8f552014-07-18 00:47:59 +00002558 printer->Print("for (;;) {\n");
temporal40ee5512008-07-10 02:12:20 +00002559 printer->Indent();
2560
Feng Xiaof157a562014-11-14 11:50:31 -08002561 google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
jieluo@google.com4de8f552014-07-18 00:47:59 +00002562 SortFieldsByNumber(descriptor_));
2563 uint32 maxtag = descriptor_->field_count() == 0 ? 0 :
2564 WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]);
2565 const int kCutoff0 = 127; // fits in 1-byte varint
2566 const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint
2567 printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = "
2568 "input->ReadTagWithCutoff($max$);\n"
2569 "tag = p.first;\n"
2570 "if (!p.second) goto handle_unusual;\n",
2571 "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 :
2572 (maxtag <= kCutoff1 ? kCutoff1 :
2573 maxtag)));
temporal40ee5512008-07-10 02:12:20 +00002574 if (descriptor_->field_count() > 0) {
2575 // We don't even want to print the switch() if we have no fields because
2576 // MSVC dislikes switch() statements that contain only a default value.
2577
2578 // Note: If we just switched on the tag rather than the field number, we
2579 // could avoid the need for the if() to check the wire type at the beginning
2580 // of each case. However, this is actually a bit slower in practice as it
2581 // creates a jump table that is 8x larger and sparser, and meanwhile the
2582 // if()s are highly predictable.
jieluo@google.com4de8f552014-07-18 00:47:59 +00002583 printer->Print("switch (::google::protobuf::internal::WireFormatLite::"
2584 "GetTagFieldNumber(tag)) {\n");
temporal40ee5512008-07-10 02:12:20 +00002585
2586 printer->Indent();
2587
temporal40ee5512008-07-10 02:12:20 +00002588 for (int i = 0; i < descriptor_->field_count(); i++) {
2589 const FieldDescriptor* field = ordered_fields[i];
2590
2591 PrintFieldComment(printer, field);
2592
2593 printer->Print(
kenton@google.comfccb1462009-12-18 02:11:36 +00002594 "case $number$: {\n",
2595 "number", SimpleItoa(field->number()));
2596 printer->Indent();
2597 const FieldGenerator& field_generator = field_generators_.get(field);
2598
2599 // Emit code to parse the common, expected case.
jieluo@google.com4de8f552014-07-18 00:47:59 +00002600 printer->Print("if (tag == $commontag$) {\n",
2601 "commontag", SimpleItoa(WireFormat::MakeTag(field)));
temporal40ee5512008-07-10 02:12:20 +00002602
kenton@google.com2d6daa72009-01-22 01:27:00 +00002603 if (i > 0 || (field->is_repeated() && !field->options().packed())) {
temporal40ee5512008-07-10 02:12:20 +00002604 printer->Print(
2605 " parse_$name$:\n",
2606 "name", field->name());
2607 }
2608
2609 printer->Indent();
kenton@google.comfccb1462009-12-18 02:11:36 +00002610 if (field->options().packed()) {
2611 field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
2612 } else {
2613 field_generator.GenerateMergeFromCodedStream(printer);
2614 }
2615 printer->Outdent();
temporal40ee5512008-07-10 02:12:20 +00002616
kenton@google.comfccb1462009-12-18 02:11:36 +00002617 // Emit code to parse unexpectedly packed or unpacked values.
2618 if (field->is_packable() && field->options().packed()) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00002619 internal::WireFormatLite::WireType wiretype =
2620 WireFormat::WireTypeForFieldType(field->type());
2621 printer->Print("} else if (tag == $uncommontag$) {\n",
2622 "uncommontag", SimpleItoa(
2623 internal::WireFormatLite::MakeTag(
2624 field->number(), wiretype)));
kenton@google.comfccb1462009-12-18 02:11:36 +00002625 printer->Indent();
2626 field_generator.GenerateMergeFromCodedStream(printer);
2627 printer->Outdent();
2628 } else if (field->is_packable() && !field->options().packed()) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00002629 internal::WireFormatLite::WireType wiretype =
2630 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
2631 printer->Print("} else if (tag == $uncommontag$) {\n",
2632 "uncommontag", SimpleItoa(
2633 internal::WireFormatLite::MakeTag(
2634 field->number(), wiretype)));
kenton@google.comfccb1462009-12-18 02:11:36 +00002635 printer->Indent();
2636 field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
2637 printer->Outdent();
2638 }
2639
2640 printer->Print(
2641 "} else {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00002642 " goto handle_unusual;\n"
kenton@google.comfccb1462009-12-18 02:11:36 +00002643 "}\n");
temporal40ee5512008-07-10 02:12:20 +00002644
2645 // switch() is slow since it can't be predicted well. Insert some if()s
2646 // here that attempt to predict the next tag.
kenton@google.com2d6daa72009-01-22 01:27:00 +00002647 if (field->is_repeated() && !field->options().packed()) {
temporal40ee5512008-07-10 02:12:20 +00002648 // Expect repeats of this field.
2649 printer->Print(
2650 "if (input->ExpectTag($tag$)) goto parse_$name$;\n",
2651 "tag", SimpleItoa(WireFormat::MakeTag(field)),
2652 "name", field->name());
2653 }
2654
2655 if (i + 1 < descriptor_->field_count()) {
2656 // Expect the next field in order.
2657 const FieldDescriptor* next_field = ordered_fields[i + 1];
2658 printer->Print(
2659 "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
2660 "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
2661 "next_name", next_field->name());
2662 } else {
2663 // Expect EOF.
2664 // TODO(kenton): Expect group end-tag?
2665 printer->Print(
jieluo@google.com4de8f552014-07-18 00:47:59 +00002666 "if (input->ExpectAtEnd()) goto success;\n");
temporal40ee5512008-07-10 02:12:20 +00002667 }
2668
2669 printer->Print(
2670 "break;\n");
2671
2672 printer->Outdent();
2673 printer->Print("}\n\n");
2674 }
2675
jieluo@google.com4de8f552014-07-18 00:47:59 +00002676 printer->Print("default: {\n");
temporal40ee5512008-07-10 02:12:20 +00002677 printer->Indent();
2678 }
2679
jieluo@google.com4de8f552014-07-18 00:47:59 +00002680 printer->Outdent();
2681 printer->Print("handle_unusual:\n");
2682 printer->Indent();
2683 // If tag is 0 or an end-group tag then this must be the end of the message.
temporal40ee5512008-07-10 02:12:20 +00002684 printer->Print(
jieluo@google.com4de8f552014-07-18 00:47:59 +00002685 "if (tag == 0 ||\n"
2686 " ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00002687 " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00002688 " goto success;\n"
temporal40ee5512008-07-10 02:12:20 +00002689 "}\n");
2690
2691 // Handle extension ranges.
2692 if (descriptor_->extension_range_count() > 0) {
2693 printer->Print(
2694 "if (");
2695 for (int i = 0; i < descriptor_->extension_range_count(); i++) {
2696 const Descriptor::ExtensionRange* range =
2697 descriptor_->extension_range(i);
kenton@google.com26bd9ee2008-11-21 00:06:27 +00002698 if (i > 0) printer->Print(" ||\n ");
temporal40ee5512008-07-10 02:12:20 +00002699
kenton@google.com80b1d622009-07-29 01:13:20 +00002700 uint32 start_tag = WireFormatLite::MakeTag(
2701 range->start, static_cast<WireFormatLite::WireType>(0));
2702 uint32 end_tag = WireFormatLite::MakeTag(
2703 range->end, static_cast<WireFormatLite::WireType>(0));
temporal40ee5512008-07-10 02:12:20 +00002704
2705 if (range->end > FieldDescriptor::kMaxNumber) {
2706 printer->Print(
2707 "($start$u <= tag)",
2708 "start", SimpleItoa(start_tag));
2709 } else {
2710 printer->Print(
2711 "($start$u <= tag && tag < $end$u)",
2712 "start", SimpleItoa(start_tag),
2713 "end", SimpleItoa(end_tag));
2714 }
2715 }
kenton@google.com80b1d622009-07-29 01:13:20 +00002716 printer->Print(") {\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -08002717 if (PreserveUnknownFields(descriptor_)) {
2718 if (UseUnknownFieldSet(descriptor_->file())) {
2719 PrintHandlingOptionalStaticInitializers(
2720 descriptor_->file(), printer,
2721 // With static initializers.
2722 " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
2723 " mutable_unknown_fields()));\n",
2724 // Without.
2725 " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
2726 " mutable_unknown_fields()));\n");
2727 } else {
2728 PrintHandlingOptionalStaticInitializers(
2729 descriptor_->file(), printer,
2730 // With static initializers.
2731 " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
2732 " &unknown_fields_stream));\n",
2733 // Without.
2734 " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
2735 " &unknown_fields_stream));\n");
2736 }
kenton@google.com80b1d622009-07-29 01:13:20 +00002737 } else {
pliard@google.com6103d4e2012-05-04 11:16:09 +00002738 PrintHandlingOptionalStaticInitializers(
2739 descriptor_->file(), printer,
2740 // With static initializers.
Feng Xiao6ef984a2014-11-10 17:34:54 -08002741 " DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
pliard@google.com6103d4e2012-05-04 11:16:09 +00002742 // Without.
Feng Xiao6ef984a2014-11-10 17:34:54 -08002743 " DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002744 }
2745 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00002746 " continue;\n"
2747 "}\n");
2748 }
2749
2750 // We really don't recognize this tag. Skip it.
Feng Xiao6ef984a2014-11-10 17:34:54 -08002751 if (PreserveUnknownFields(descriptor_)) {
2752 if (UseUnknownFieldSet(descriptor_->file())) {
2753 printer->Print(
2754 "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
2755 " input, tag, mutable_unknown_fields()));\n");
2756 } else {
2757 printer->Print(
2758 "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
2759 " input, tag, &unknown_fields_stream));\n");
2760 }
kenton@google.com80b1d622009-07-29 01:13:20 +00002761 } else {
2762 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08002763 "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002764 }
temporal40ee5512008-07-10 02:12:20 +00002765
2766 if (descriptor_->field_count() > 0) {
2767 printer->Print("break;\n");
2768 printer->Outdent();
2769 printer->Print("}\n"); // default:
2770 printer->Outdent();
2771 printer->Print("}\n"); // switch
2772 }
2773
2774 printer->Outdent();
2775 printer->Outdent();
2776 printer->Print(
jieluo@google.com4de8f552014-07-18 00:47:59 +00002777 " }\n" // for (;;)
2778 "success:\n"
2779 " // @@protoc_insertion_point(parse_success:$full_name$)\n"
temporal40ee5512008-07-10 02:12:20 +00002780 " return true;\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00002781 "failure:\n"
2782 " // @@protoc_insertion_point(parse_failure:$full_name$)\n"
2783 " return false;\n"
temporal40ee5512008-07-10 02:12:20 +00002784 "#undef DO_\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00002785 "}\n", "full_name", descriptor_->full_name());
temporal40ee5512008-07-10 02:12:20 +00002786}
2787
2788void MessageGenerator::GenerateSerializeOneField(
kenton@google.comd37d46d2009-04-25 02:53:47 +00002789 io::Printer* printer, const FieldDescriptor* field, bool to_array) {
temporal40ee5512008-07-10 02:12:20 +00002790 PrintFieldComment(printer, field);
2791
Feng Xiao6ef984a2014-11-10 17:34:54 -08002792 bool have_enclosing_if = false;
2793 if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) {
temporal40ee5512008-07-10 02:12:20 +00002794 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00002795 "if (has_$name$()) {\n",
2796 "name", FieldName(field));
kenton@google.com2d6daa72009-01-22 01:27:00 +00002797 printer->Indent();
Feng Xiao6ef984a2014-11-10 17:34:54 -08002798 have_enclosing_if = true;
2799 } else if (!HasFieldPresence(descriptor_->file())) {
2800 have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
temporal40ee5512008-07-10 02:12:20 +00002801 }
2802
kenton@google.comd37d46d2009-04-25 02:53:47 +00002803 if (to_array) {
2804 field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
2805 printer);
2806 } else {
2807 field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
2808 }
temporal40ee5512008-07-10 02:12:20 +00002809
Feng Xiao6ef984a2014-11-10 17:34:54 -08002810 if (have_enclosing_if) {
kenton@google.com2d6daa72009-01-22 01:27:00 +00002811 printer->Outdent();
2812 printer->Print("}\n");
2813 }
2814 printer->Print("\n");
temporal40ee5512008-07-10 02:12:20 +00002815}
2816
2817void MessageGenerator::GenerateSerializeOneExtensionRange(
kenton@google.comd37d46d2009-04-25 02:53:47 +00002818 io::Printer* printer, const Descriptor::ExtensionRange* range,
2819 bool to_array) {
temporal40ee5512008-07-10 02:12:20 +00002820 map<string, string> vars;
2821 vars["start"] = SimpleItoa(range->start);
2822 vars["end"] = SimpleItoa(range->end);
2823 printer->Print(vars,
kenton@google.comd37d46d2009-04-25 02:53:47 +00002824 "// Extension range [$start$, $end$)\n");
2825 if (to_array) {
2826 printer->Print(vars,
2827 "target = _extensions_.SerializeWithCachedSizesToArray(\n"
2828 " $start$, $end$, target);\n\n");
2829 } else {
2830 printer->Print(vars,
2831 "_extensions_.SerializeWithCachedSizes(\n"
2832 " $start$, $end$, output);\n\n");
2833 }
temporal40ee5512008-07-10 02:12:20 +00002834}
2835
2836void MessageGenerator::
2837GenerateSerializeWithCachedSizes(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +00002838 if (descriptor_->options().message_set_wire_format()) {
2839 // Special-case MessageSet.
2840 printer->Print(
2841 "void $classname$::SerializeWithCachedSizes(\n"
2842 " ::google::protobuf::io::CodedOutputStream* output) const {\n"
2843 " _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
2844 "classname", classname_);
jieluo@google.com4de8f552014-07-18 00:47:59 +00002845 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
2846 printer->Print(
2847 " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
2848 " unknown_fields(), output);\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002849 printer->Print(
2850 "}\n");
2851 return;
2852 }
2853
temporal40ee5512008-07-10 02:12:20 +00002854 printer->Print(
kenton@google.comd37d46d2009-04-25 02:53:47 +00002855 "void $classname$::SerializeWithCachedSizes(\n"
2856 " ::google::protobuf::io::CodedOutputStream* output) const {\n",
temporal40ee5512008-07-10 02:12:20 +00002857 "classname", classname_);
2858 printer->Indent();
2859
jieluo@google.com4de8f552014-07-18 00:47:59 +00002860 printer->Print(
2861 "// @@protoc_insertion_point(serialize_start:$full_name$)\n",
2862 "full_name", descriptor_->full_name());
2863
kenton@google.comd37d46d2009-04-25 02:53:47 +00002864 GenerateSerializeWithCachedSizesBody(printer, false);
2865
jieluo@google.com4de8f552014-07-18 00:47:59 +00002866 printer->Print(
2867 "// @@protoc_insertion_point(serialize_end:$full_name$)\n",
2868 "full_name", descriptor_->full_name());
2869
kenton@google.comd37d46d2009-04-25 02:53:47 +00002870 printer->Outdent();
2871 printer->Print(
2872 "}\n");
2873}
2874
2875void MessageGenerator::
2876GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +00002877 if (descriptor_->options().message_set_wire_format()) {
2878 // Special-case MessageSet.
2879 printer->Print(
2880 "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
2881 " ::google::protobuf::uint8* target) const {\n"
2882 " target =\n"
2883 " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
2884 "classname", classname_);
jieluo@google.com4de8f552014-07-18 00:47:59 +00002885 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
2886 printer->Print(
2887 " target = ::google::protobuf::internal::WireFormat::\n"
2888 " SerializeUnknownMessageSetItemsToArray(\n"
2889 " unknown_fields(), target);\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002890 printer->Print(
2891 " return target;\n"
2892 "}\n");
2893 return;
2894 }
2895
kenton@google.comd37d46d2009-04-25 02:53:47 +00002896 printer->Print(
2897 "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
2898 " ::google::protobuf::uint8* target) const {\n",
2899 "classname", classname_);
2900 printer->Indent();
2901
jieluo@google.com4de8f552014-07-18 00:47:59 +00002902 printer->Print(
2903 "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n",
2904 "full_name", descriptor_->full_name());
2905
kenton@google.comd37d46d2009-04-25 02:53:47 +00002906 GenerateSerializeWithCachedSizesBody(printer, true);
2907
jieluo@google.com4de8f552014-07-18 00:47:59 +00002908 printer->Print(
2909 "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n",
2910 "full_name", descriptor_->full_name());
2911
kenton@google.comd37d46d2009-04-25 02:53:47 +00002912 printer->Outdent();
2913 printer->Print(
2914 " return target;\n"
2915 "}\n");
2916}
2917
2918void MessageGenerator::
2919GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
Feng Xiaof157a562014-11-14 11:50:31 -08002920 google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
jieluo@google.com4de8f552014-07-18 00:47:59 +00002921 SortFieldsByNumber(descriptor_));
temporal40ee5512008-07-10 02:12:20 +00002922
2923 vector<const Descriptor::ExtensionRange*> sorted_extensions;
2924 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
2925 sorted_extensions.push_back(descriptor_->extension_range(i));
2926 }
Jisi Liu885b6122015-02-28 14:51:22 -08002927 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
2928 ExtensionRangeSorter());
temporal40ee5512008-07-10 02:12:20 +00002929
2930 // Merge the fields and the extension ranges, both sorted by field number.
2931 int i, j;
2932 for (i = 0, j = 0;
2933 i < descriptor_->field_count() || j < sorted_extensions.size();
2934 ) {
2935 if (i == descriptor_->field_count()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +00002936 GenerateSerializeOneExtensionRange(printer,
2937 sorted_extensions[j++],
2938 to_array);
temporal40ee5512008-07-10 02:12:20 +00002939 } else if (j == sorted_extensions.size()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +00002940 GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
temporal40ee5512008-07-10 02:12:20 +00002941 } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) {
kenton@google.comd37d46d2009-04-25 02:53:47 +00002942 GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
temporal40ee5512008-07-10 02:12:20 +00002943 } else {
kenton@google.comd37d46d2009-04-25 02:53:47 +00002944 GenerateSerializeOneExtensionRange(printer,
2945 sorted_extensions[j++],
2946 to_array);
temporal40ee5512008-07-10 02:12:20 +00002947 }
2948 }
2949
Feng Xiao6ef984a2014-11-10 17:34:54 -08002950 if (PreserveUnknownFields(descriptor_)) {
2951 if (UseUnknownFieldSet(descriptor_->file())) {
2952 printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n");
2953 printer->Indent();
2954 if (to_array) {
2955 printer->Print(
2956 "target = "
2957 "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
2958 " unknown_fields(), target);\n");
2959 } else {
2960 printer->Print(
2961 "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
2962 " unknown_fields(), output);\n");
2963 }
2964 printer->Outdent();
2965
kenton@google.com80b1d622009-07-29 01:13:20 +00002966 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08002967 "}\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002968 } else {
2969 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08002970 "output->WriteRaw(unknown_fields().data(),\n"
2971 " unknown_fields().size());\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00002972 }
kenton@google.com80b1d622009-07-29 01:13:20 +00002973 }
temporal40ee5512008-07-10 02:12:20 +00002974}
2975
Feng Xiao6ef984a2014-11-10 17:34:54 -08002976static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) {
2977 vector<uint32> result;
2978 uint32 mask = 0;
2979 for (int i = 0; i < desc->field_count(); i++) {
2980 if (i > 0 && i % 32 == 0) {
2981 result.push_back(mask);
2982 mask = 0;
2983 }
2984 if (desc->field(i)->is_required()) {
2985 mask |= (1 << (i & 31));
2986 }
2987 }
2988 if (mask != 0) {
2989 result.push_back(mask);
2990 }
2991 return result;
2992}
2993
2994// Create an expression that evaluates to
2995// "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
2996// masks is allowed to be shorter than _has_bits_, but at least one element of
2997// masks must be non-zero.
2998static string ConditionalToCheckBitmasks(const vector<uint32>& masks) {
2999 vector<string> parts;
3000 for (int i = 0; i < masks.size(); i++) {
3001 if (masks[i] == 0) continue;
3002 char buffer[kFastToBufferSize];
3003 FastHex32ToBuffer(masks[i], buffer);
3004 string m = StrCat("0x", buffer);
3005 // Each xor evaluates to 0 if the expected bits are present.
3006 parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")"));
3007 }
3008 GOOGLE_CHECK(!parts.empty());
3009 // If we have multiple parts, each expected to be 0, then bitwise-or them.
3010 string result = parts.size() == 1 ? parts[0] :
3011 StrCat("(", Join(parts, "\n | "), ")");
3012 return result + " == 0";
3013}
3014
temporal40ee5512008-07-10 02:12:20 +00003015void MessageGenerator::
3016GenerateByteSize(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +00003017 if (descriptor_->options().message_set_wire_format()) {
3018 // Special-case MessageSet.
3019 printer->Print(
3020 "int $classname$::ByteSize() const {\n"
3021 " int total_size = _extensions_.MessageSetByteSize();\n",
3022 "classname", classname_);
jieluo@google.com4de8f552014-07-18 00:47:59 +00003023 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
3024 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08003025 "if (_internal_metadata_.have_unknown_fields()) {\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00003026 " total_size += ::google::protobuf::internal::WireFormat::\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -08003027 " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"
3028 "}\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00003029 printer->Print(
kenton@google.comfccb1462009-12-18 02:11:36 +00003030 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00003031 " _cached_size_ = total_size;\n"
kenton@google.comfccb1462009-12-18 02:11:36 +00003032 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00003033 " return total_size;\n"
3034 "}\n");
3035 return;
3036 }
3037
Feng Xiao6ef984a2014-11-10 17:34:54 -08003038 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
3039 // Emit a function (rarely used, we hope) that handles the required fields
3040 // by checking for each one individually.
3041 printer->Print(
3042 "int $classname$::RequiredFieldsByteSizeFallback() const {\n",
3043 "classname", classname_);
3044 printer->Indent();
3045 printer->Print("int total_size = 0;\n");
3046 for (int i = 0; i < descriptor_->field_count(); i++) {
3047 const FieldDescriptor* field = descriptor_->field(i);
3048 if (field->is_required()) {
3049 printer->Print("\n"
3050 "if (has_$name$()) {\n",
3051 "name", FieldName(field));
3052 printer->Indent();
3053 PrintFieldComment(printer, field);
3054 field_generators_.get(field).GenerateByteSize(printer);
3055 printer->Outdent();
3056 printer->Print("}\n");
3057 }
3058 }
3059 printer->Print("\n"
3060 "return total_size;\n");
3061 printer->Outdent();
3062 printer->Print("}\n");
3063 }
3064
temporal40ee5512008-07-10 02:12:20 +00003065 printer->Print(
3066 "int $classname$::ByteSize() const {\n",
3067 "classname", classname_);
3068 printer->Indent();
3069 printer->Print(
3070 "int total_size = 0;\n"
3071 "\n");
3072
Feng Xiao6ef984a2014-11-10 17:34:54 -08003073 // Handle required fields (if any). We expect all of them to be
3074 // present, so emit one conditional that checks for that. If they are all
3075 // present then the fast path executes; otherwise the slow path executes.
3076 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
3077 // The fast path works if all required fields are present.
3078 vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_);
3079 printer->Print((string("if (") +
3080 ConditionalToCheckBitmasks(masks_for_has_bits) +
3081 ") { // All required fields are present.\n").c_str());
3082 printer->Indent();
3083 for (int i = 0; i < descriptor_->field_count(); i++) {
3084 const FieldDescriptor* field = descriptor_->field(i);
3085 if (!field->is_required()) continue;
3086 PrintFieldComment(printer, field);
3087 field_generators_.get(field).GenerateByteSize(printer);
3088 printer->Print("\n");
3089 }
3090 printer->Outdent();
3091 printer->Print("} else {\n" // the slow path
3092 " total_size += RequiredFieldsByteSizeFallback();\n"
3093 "}\n");
3094 } else {
3095 // num_required_fields_ <= 1: no need to be tricky
3096 for (int i = 0; i < descriptor_->field_count(); i++) {
3097 const FieldDescriptor* field = descriptor_->field(i);
3098 if (!field->is_required()) continue;
3099 PrintFieldComment(printer, field);
3100 printer->Print("if (has_$name$()) {\n",
3101 "name", FieldName(field));
3102 printer->Indent();
3103 field_generators_.get(field).GenerateByteSize(printer);
3104 printer->Outdent();
3105 printer->Print("}\n");
3106 }
3107 }
temporal40ee5512008-07-10 02:12:20 +00003108
Feng Xiao6ef984a2014-11-10 17:34:54 -08003109 // Handle optional fields (worry below about repeateds, oneofs, etc.).
3110 // These are handled in chunks of 8. The first chunk is
3111 // the non-requireds-non-repeateds-non-unions-non-extensions in
3112 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
3113 // and the second chunk is the same for
3114 // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15),
3115 // etc.
3116 hash_map<int, uint32> fields_mask_for_chunk;
temporal40ee5512008-07-10 02:12:20 +00003117 for (int i = 0; i < descriptor_->field_count(); i++) {
3118 const FieldDescriptor* field = descriptor_->field(i);
Feng Xiao6ef984a2014-11-10 17:34:54 -08003119 if (!field->is_required() && !field->is_repeated() &&
3120 !field->containing_oneof()) {
3121 fields_mask_for_chunk[i / 8] |= static_cast<uint32>(1) << (i % 32);
3122 }
3123 }
temporal40ee5512008-07-10 02:12:20 +00003124
Feng Xiao6ef984a2014-11-10 17:34:54 -08003125 int last_index = -1;
3126 bool chunk_block_in_progress = false;
3127 for (int i = 0; i < descriptor_->field_count(); i++) {
3128 const FieldDescriptor* field = descriptor_->field(i);
3129 if (!field->is_required() && !field->is_repeated() &&
3130 !field->containing_oneof()) {
temporal40ee5512008-07-10 02:12:20 +00003131 // See above in GenerateClear for an explanation of this.
3132 // TODO(kenton): Share code? Unclear how to do so without
3133 // over-engineering.
Feng Xiao6ef984a2014-11-10 17:34:54 -08003134 if (i / 8 != last_index / 8 || last_index < 0) {
3135 // End previous chunk, if there was one.
3136 if (chunk_block_in_progress) {
temporal40ee5512008-07-10 02:12:20 +00003137 printer->Outdent();
3138 printer->Print("}\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -08003139 chunk_block_in_progress = false;
temporal40ee5512008-07-10 02:12:20 +00003140 }
Feng Xiao6ef984a2014-11-10 17:34:54 -08003141 // Start chunk.
3142 uint32 mask = fields_mask_for_chunk[i / 8];
3143 int count = popcnt(mask);
3144 GOOGLE_DCHECK_GE(count, 1);
3145 if (count == 1) {
3146 // No "if" here because the chunk is trivial.
3147 } else {
3148 if (HasFieldPresence(descriptor_->file())) {
3149 printer->Print(
3150 "if (_has_bits_[$index$ / 32] & $mask$) {\n",
3151 "index", SimpleItoa(i),
3152 "mask", SimpleItoa(mask));
3153 printer->Indent();
3154 chunk_block_in_progress = true;
3155 }
3156 }
temporal40ee5512008-07-10 02:12:20 +00003157 }
3158 last_index = i;
3159
3160 PrintFieldComment(printer, field);
3161
Feng Xiao6ef984a2014-11-10 17:34:54 -08003162 bool have_enclosing_if = false;
3163 if (HasFieldPresence(descriptor_->file())) {
3164 printer->Print(
3165 "if (has_$name$()) {\n",
3166 "name", FieldName(field));
3167 printer->Indent();
3168 have_enclosing_if = true;
3169 } else {
3170 // Without field presence: field is serialized only if it has a
3171 // non-default value.
3172 have_enclosing_if = EmitFieldNonDefaultCondition(
3173 printer, "this->", field);
3174 }
temporal40ee5512008-07-10 02:12:20 +00003175
3176 field_generators_.get(field).GenerateByteSize(printer);
3177
Feng Xiao6ef984a2014-11-10 17:34:54 -08003178 if (have_enclosing_if) {
3179 printer->Outdent();
3180 printer->Print(
3181 "}\n"
3182 "\n");
3183 }
temporal40ee5512008-07-10 02:12:20 +00003184 }
3185 }
3186
Feng Xiao6ef984a2014-11-10 17:34:54 -08003187 if (chunk_block_in_progress) {
temporal40ee5512008-07-10 02:12:20 +00003188 printer->Outdent();
3189 printer->Print("}\n");
3190 }
3191
3192 // Repeated fields don't use _has_bits_ so we count them in a separate
3193 // pass.
3194 for (int i = 0; i < descriptor_->field_count(); i++) {
3195 const FieldDescriptor* field = descriptor_->field(i);
3196
3197 if (field->is_repeated()) {
3198 PrintFieldComment(printer, field);
3199 field_generators_.get(field).GenerateByteSize(printer);
3200 printer->Print("\n");
3201 }
3202 }
3203
jieluo@google.com4de8f552014-07-18 00:47:59 +00003204 // Fields inside a oneof don't use _has_bits_ so we count them in a separate
3205 // pass.
3206 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
3207 printer->Print(
3208 "switch ($oneofname$_case()) {\n",
3209 "oneofname", descriptor_->oneof_decl(i)->name());
3210 printer->Indent();
3211 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
3212 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
3213 PrintFieldComment(printer, field);
3214 printer->Print(
3215 "case k$field_name$: {\n",
3216 "field_name", UnderscoresToCamelCase(field->name(), true));
3217 printer->Indent();
3218 field_generators_.get(field).GenerateByteSize(printer);
3219 printer->Print(
3220 "break;\n");
3221 printer->Outdent();
3222 printer->Print(
3223 "}\n");
3224 }
3225 printer->Print(
3226 "case $cap_oneof_name$_NOT_SET: {\n"
3227 " break;\n"
3228 "}\n",
3229 "cap_oneof_name",
3230 ToUpper(descriptor_->oneof_decl(i)->name()));
3231 printer->Outdent();
3232 printer->Print(
3233 "}\n");
3234 }
3235
temporal40ee5512008-07-10 02:12:20 +00003236 if (descriptor_->extension_range_count() > 0) {
3237 printer->Print(
kenton@google.comd37d46d2009-04-25 02:53:47 +00003238 "total_size += _extensions_.ByteSize();\n"
temporal40ee5512008-07-10 02:12:20 +00003239 "\n");
3240 }
3241
Feng Xiao6ef984a2014-11-10 17:34:54 -08003242 if (PreserveUnknownFields(descriptor_)) {
3243 if (UseUnknownFieldSet(descriptor_->file())) {
3244 printer->Print(
3245 "if (_internal_metadata_.have_unknown_fields()) {\n"
3246 " total_size +=\n"
3247 " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
3248 " unknown_fields());\n"
3249 "}\n");
3250 } else {
3251 printer->Print(
3252 "total_size += unknown_fields().size();\n"
3253 "\n");
3254 }
kenton@google.com80b1d622009-07-29 01:13:20 +00003255 }
temporal40ee5512008-07-10 02:12:20 +00003256
3257 // We update _cached_size_ even though this is a const method. In theory,
3258 // this is not thread-compatible, because concurrent writes have undefined
3259 // results. In practice, since any concurrent writes will be writing the
3260 // exact same value, it works on all common processors. In a future version
3261 // of C++, _cached_size_ should be made into an atomic<int>.
3262 printer->Print(
kenton@google.comfccb1462009-12-18 02:11:36 +00003263 "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
temporal40ee5512008-07-10 02:12:20 +00003264 "_cached_size_ = total_size;\n"
kenton@google.comfccb1462009-12-18 02:11:36 +00003265 "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
temporal40ee5512008-07-10 02:12:20 +00003266 "return total_size;\n");
3267
3268 printer->Outdent();
3269 printer->Print("}\n");
3270}
3271
3272void MessageGenerator::
3273GenerateIsInitialized(io::Printer* printer) {
3274 printer->Print(
3275 "bool $classname$::IsInitialized() const {\n",
3276 "classname", classname_);
3277 printer->Indent();
3278
Feng Xiao6ef984a2014-11-10 17:34:54 -08003279 if (HasFieldPresence(descriptor_->file())) {
3280 // Check that all required fields in this message are set. We can do this
3281 // most efficiently by checking 32 "has bits" at a time.
3282 int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
3283 for (int i = 0; i < has_bits_array_size; i++) {
3284 uint32 mask = 0;
3285 for (int bit = 0; bit < 32; bit++) {
3286 int index = i * 32 + bit;
3287 if (index >= descriptor_->field_count()) break;
3288 const FieldDescriptor* field = descriptor_->field(index);
temporal40ee5512008-07-10 02:12:20 +00003289
Feng Xiao6ef984a2014-11-10 17:34:54 -08003290 if (field->is_required()) {
3291 mask |= 1 << bit;
3292 }
temporal40ee5512008-07-10 02:12:20 +00003293 }
temporal40ee5512008-07-10 02:12:20 +00003294
Feng Xiao6ef984a2014-11-10 17:34:54 -08003295 if (mask != 0) {
3296 char buffer[kFastToBufferSize];
3297 printer->Print(
3298 "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
3299 "i", SimpleItoa(i),
3300 "mask", FastHex32ToBuffer(mask, buffer));
3301 }
temporal40ee5512008-07-10 02:12:20 +00003302 }
3303 }
3304
3305 // Now check that all embedded messages are initialized.
3306 printer->Print("\n");
3307 for (int i = 0; i < descriptor_->field_count(); i++) {
3308 const FieldDescriptor* field = descriptor_->field(i);
3309 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00003310 !ShouldIgnoreRequiredFieldCheck(field) &&
temporal40ee5512008-07-10 02:12:20 +00003311 HasRequiredFields(field->message_type())) {
3312 if (field->is_repeated()) {
3313 printer->Print(
jieluo@google.com4de8f552014-07-18 00:47:59 +00003314 "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))"
3315 " return false;\n",
temporal40ee5512008-07-10 02:12:20 +00003316 "name", FieldName(field));
3317 } else {
Feng Xiaof157a562014-11-14 11:50:31 -08003318 if (field->options().weak() || !field->containing_oneof()) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08003319 // For weak fields, use the data member (::google::protobuf::Message*) instead
jieluo@google.com4de8f552014-07-18 00:47:59 +00003320 // of the getter to avoid a link dependency on the weak message type
3321 // which is only forward declared.
3322 printer->Print(
Feng Xiaof157a562014-11-14 11:50:31 -08003323 "if (has_$name$()) {\n"
3324 " if (!this->$name$_->IsInitialized()) return false;\n"
3325 "}\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00003326 "name", FieldName(field));
3327 } else {
3328 printer->Print(
3329 "if (has_$name$()) {\n"
3330 " if (!this->$name$().IsInitialized()) return false;\n"
3331 "}\n",
3332 "name", FieldName(field));
3333 }
temporal40ee5512008-07-10 02:12:20 +00003334 }
3335 }
3336 }
3337
3338 if (descriptor_->extension_range_count() > 0) {
3339 printer->Print(
3340 "\n"
3341 "if (!_extensions_.IsInitialized()) return false;");
3342 }
3343
3344 printer->Outdent();
3345 printer->Print(
3346 " return true;\n"
3347 "}\n");
3348}
3349
kenton@google.comfccb1462009-12-18 02:11:36 +00003350
temporal40ee5512008-07-10 02:12:20 +00003351} // namespace cpp
3352} // namespace compiler
3353} // namespace protobuf
3354} // namespace google