1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * 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.
18 //
19 // 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.
30
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 <google/protobuf/compiler/cpp/cpp_message_field.h>
36 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
37 #include <google/protobuf/io/printer.h>
38
39 #include <google/protobuf/stubs/strutil.h>
40
41 namespace google {
42 namespace protobuf {
43 namespace compiler {
44 namespace cpp {
45
46 namespace {
ReinterpretCast(const string & type,const string & expression,bool implicit_weak_field)47 string ReinterpretCast(const string& type, const string& expression,
48 bool implicit_weak_field) {
49 if (implicit_weak_field) {
50 return "reinterpret_cast< " + type + " >(" + expression + ")";
51 } else {
52 return expression;
53 }
54 }
55
SetMessageVariables(const FieldDescriptor * descriptor,const Options & options,bool implicit_weak,std::map<std::string,std::string> * variables)56 void SetMessageVariables(const FieldDescriptor* descriptor,
57 const Options& options, bool implicit_weak,
58 std::map<std::string, std::string>* variables) {
59 SetCommonFieldVariables(descriptor, variables, options);
60 (*variables)["type"] = FieldMessageTypeName(descriptor, options);
61 (*variables)["casted_member"] = ReinterpretCast(
62 (*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak);
63 (*variables)["type_default_instance"] =
64 QualifiedDefaultInstanceName(descriptor->message_type(), options);
65 (*variables)["type_reference_function"] =
66 implicit_weak
67 ? (" " + ReferenceFunctionName(descriptor->message_type(), options) +
68 "();\n")
69 : "";
70 (*variables)["stream_writer"] =
71 (*variables)["declared_type"] +
72 (HasFastArraySerialization(descriptor->message_type()->file(), options)
73 ? "MaybeToArray"
74 : "");
75 // NOTE: Escaped here to unblock proto1->proto2 migration.
76 // TODO(liujisi): Extend this to apply for other conflicting methods.
77 (*variables)["release_name"] =
78 SafeFunctionName(descriptor->containing_type(), descriptor, "release_");
79 (*variables)["full_name"] = descriptor->full_name();
80 }
81
82 } // namespace
83
84 // ===================================================================
85
MessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)86 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
87 const Options& options,
88 MessageSCCAnalyzer* scc_analyzer)
89 : FieldGenerator(descriptor, options),
90 implicit_weak_field_(
91 IsImplicitWeakField(descriptor, options, scc_analyzer)) {
92 SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
93 }
94
~MessageFieldGenerator()95 MessageFieldGenerator::~MessageFieldGenerator() {}
96
GeneratePrivateMembers(io::Printer * printer) const97 void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
98 Formatter format(printer, variables_);
99 if (implicit_weak_field_) {
100 format("::$proto_ns$::MessageLite* $name$_;\n");
101 } else {
102 format("$type$* $name$_;\n");
103 }
104 }
105
GenerateAccessorDeclarations(io::Printer * printer) const106 void MessageFieldGenerator::GenerateAccessorDeclarations(
107 io::Printer* printer) const {
108 Formatter format(printer, variables_);
109 format(
110 "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n"
111 "$deprecated_attr$$type$* ${1$$release_name$$}$();\n"
112 "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n"
113 "$deprecated_attr$void ${1$set_allocated_$name$$}$"
114 "($type$* $name$);\n",
115 descriptor_);
116 if (SupportsArenas(descriptor_)) {
117 format(
118 "$deprecated_attr$void "
119 "${1$unsafe_arena_set_allocated_$name$$}$(\n"
120 " $type$* $name$);\n"
121 "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n",
122 descriptor_);
123 }
124 }
125
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const126 void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
127 io::Printer* printer) const {
128 Formatter format(printer, variables_);
129 if (SupportsArenas(descriptor_)) {
130 format(
131 "void $classname$::unsafe_arena_set_allocated_$name$(\n"
132 " $type$* $name$) {\n"
133 // If we're not on an arena, free whatever we were holding before.
134 // (If we are on arena, we can just forget the earlier pointer.)
135 " if (GetArenaNoVirtual() == nullptr) {\n"
136 " delete $name$_;\n"
137 " }\n"
138 " $name$_ = $name$;\n"
139 " if ($name$) {\n"
140 " $set_hasbit$\n"
141 " } else {\n"
142 " $clear_hasbit$\n"
143 " }\n"
144 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
145 ":$full_name$)\n"
146 "}\n");
147 }
148 }
149
GenerateInlineAccessorDefinitions(io::Printer * printer) const150 void MessageFieldGenerator::GenerateInlineAccessorDefinitions(
151 io::Printer* printer) const {
152 Formatter format(printer, variables_);
153 format(
154 "inline const $type$& $classname$::$name$() const {\n"
155 " const $type$* p = $casted_member$;\n"
156 " // @@protoc_insertion_point(field_get:$full_name$)\n"
157 " return p != nullptr ? *p : *reinterpret_cast<const $type$*>(\n"
158 " &$type_default_instance$);\n"
159 "}\n");
160
161 format(
162 "inline $type$* $classname$::$release_name$() {\n"
163 " // @@protoc_insertion_point(field_release:$full_name$)\n"
164 "$type_reference_function$"
165 " $clear_hasbit$\n"
166 " $type$* temp = $casted_member$;\n");
167 if (SupportsArenas(descriptor_)) {
168 format(
169 " if (GetArenaNoVirtual() != nullptr) {\n"
170 " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
171 " }\n");
172 }
173 format(
174 " $name$_ = nullptr;\n"
175 " return temp;\n"
176 "}\n");
177
178 if (SupportsArenas(descriptor_)) {
179 format(
180 "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
181 " // "
182 "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
183 "$type_reference_function$"
184 " $clear_hasbit$\n"
185 " $type$* temp = $casted_member$;\n"
186 " $name$_ = nullptr;\n"
187 " return temp;\n"
188 "}\n");
189 }
190
191 format(
192 "inline $type$* $classname$::mutable_$name$() {\n"
193 " $set_hasbit$\n"
194 " if ($name$_ == nullptr) {\n"
195 " auto* p = CreateMaybeMessage<$type$>(GetArenaNoVirtual());\n");
196 if (implicit_weak_field_) {
197 format(" $name$_ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n");
198 } else {
199 format(" $name$_ = p;\n");
200 }
201 format(
202 " }\n"
203 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
204 " return $casted_member$;\n"
205 "}\n");
206
207 // We handle the most common case inline, and delegate less common cases to
208 // the slow fallback function.
209 format(
210 "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
211 " ::$proto_ns$::Arena* message_arena = GetArenaNoVirtual();\n");
212 format(" if (message_arena == nullptr) {\n");
213 if (IsCrossFileMessage(descriptor_)) {
214 format(
215 " delete reinterpret_cast< ::$proto_ns$::MessageLite*>($name$_);\n");
216 } else {
217 format(" delete $name$_;\n");
218 }
219 format(
220 " }\n"
221 " if ($name$) {\n");
222 if (SupportsArenas(descriptor_->message_type()) &&
223 IsCrossFileMessage(descriptor_)) {
224 // We have to read the arena through the virtual method, because the type
225 // isn't defined in this file.
226 format(
227 " ::$proto_ns$::Arena* submessage_arena =\n"
228 " "
229 "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n");
230 } else if (!SupportsArenas(descriptor_->message_type())) {
231 format(" ::$proto_ns$::Arena* submessage_arena = nullptr;\n");
232 } else {
233 format(
234 " ::$proto_ns$::Arena* submessage_arena =\n"
235 " ::$proto_ns$::Arena::GetArena($name$);\n");
236 }
237 format(
238 " if (message_arena != submessage_arena) {\n"
239 " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
240 " message_arena, $name$, submessage_arena);\n"
241 " }\n"
242 " $set_hasbit$\n"
243 " } else {\n"
244 " $clear_hasbit$\n"
245 " }\n");
246 if (implicit_weak_field_) {
247 format(" $name$_ = reinterpret_cast<MessageLite*>($name$);\n");
248 } else {
249 format(" $name$_ = $name$;\n");
250 }
251 format(
252 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
253 "}\n");
254 }
255
GenerateInternalAccessorDeclarations(io::Printer * printer) const256 void MessageFieldGenerator::GenerateInternalAccessorDeclarations(
257 io::Printer* printer) const {
258 Formatter format(printer, variables_);
259 if (implicit_weak_field_) {
260 format(
261 "static const ::$proto_ns$::MessageLite& $name$("
262 "const $classname$* msg);\n"
263 "static ::$proto_ns$::MessageLite* mutable_$name$("
264 "$classname$* msg);\n");
265 } else {
266 format("static const $type$& $name$(const $classname$* msg);\n");
267 }
268 }
269
GenerateInternalAccessorDefinitions(io::Printer * printer) const270 void MessageFieldGenerator::GenerateInternalAccessorDefinitions(
271 io::Printer* printer) const {
272 // In theory, these accessors could be inline in _Internal. However, in
273 // practice, the linker is then not able to throw them out making implicit
274 // weak dependencies not work at all.
275 Formatter format(printer, variables_);
276 if (implicit_weak_field_) {
277 // These private accessors are used by MergeFrom and
278 // MergePartialFromCodedStream, and their purpose is to provide access to
279 // the field without creating a strong dependency on the message type.
280 format(
281 "const ::$proto_ns$::MessageLite& $classname$::_Internal::$name$(\n"
282 " const $classname$* msg) {\n"
283 " if (msg->$name$_ != nullptr) {\n"
284 " return *msg->$name$_;\n"
285 " } else if (&$type_default_instance$ != nullptr) {\n"
286 " return *reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
287 " &$type_default_instance$);\n"
288 " } else {\n"
289 " return "
290 "*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n"
291 " }\n"
292 "}\n");
293 if (SupportsArenas(descriptor_)) {
294 format(
295 "::$proto_ns$::MessageLite*\n"
296 "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
297 if (HasFieldPresence(descriptor_->file())) {
298 format(" msg->$set_hasbit$\n");
299 }
300 format(
301 " if (msg->$name$_ == nullptr) {\n"
302 " if (&$type_default_instance$ == nullptr) {\n"
303 " msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n"
304 " ::$proto_ns$::internal::ImplicitWeakMessage>(\n"
305 " msg->GetArenaNoVirtual());\n"
306 " } else {\n"
307 " msg->$name$_ = reinterpret_cast<const "
308 "::$proto_ns$::MessageLite*>(\n"
309 " &$type_default_instance$)->New("
310 "msg->GetArenaNoVirtual());\n"
311 " }\n"
312 " }\n"
313 " return msg->$name$_;\n"
314 "}\n");
315 } else {
316 format(
317 "::$proto_ns$::MessageLite*\n"
318 "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
319 if (HasFieldPresence(descriptor_->file())) {
320 format(" msg->$set_hasbit$\n");
321 }
322 format(
323 " if (msg->$name$_ == nullptr) {\n"
324 " if (&$type_default_instance$ == nullptr) {\n"
325 " msg->$name$_ = "
326 "new ::$proto_ns$::internal::ImplicitWeakMessage;\n"
327 " } else {\n"
328 " msg->$name$_ = "
329 "reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
330 " &$type_default_instance$)->New();\n"
331 " }\n"
332 " }\n"
333 " return msg->$name$_;\n"
334 "}\n");
335 }
336 } else {
337 // This inline accessor directly returns member field and is used in
338 // Serialize such that AFDO profile correctly captures access information to
339 // message fields under serialize.
340 format(
341 "const $type$&\n"
342 "$classname$::_Internal::$name$(const $classname$* msg) {\n"
343 " return *msg->$field_member$;\n"
344 "}\n");
345 }
346 }
347
GenerateClearingCode(io::Printer * printer) const348 void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
349 Formatter format(printer, variables_);
350 if (!HasFieldPresence(descriptor_->file())) {
351 // If we don't have has-bits, message presence is indicated only by ptr !=
352 // NULL. Thus on clear, we need to delete the object.
353 format(
354 "if (GetArenaNoVirtual() == nullptr && $name$_ != nullptr) {\n"
355 " delete $name$_;\n"
356 "}\n"
357 "$name$_ = nullptr;\n");
358 } else {
359 format("if ($name$_ != nullptr) $name$_->Clear();\n");
360 }
361 }
362
GenerateMessageClearingCode(io::Printer * printer) const363 void MessageFieldGenerator::GenerateMessageClearingCode(
364 io::Printer* printer) const {
365 Formatter format(printer, variables_);
366 if (!HasFieldPresence(descriptor_->file())) {
367 // If we don't have has-bits, message presence is indicated only by ptr !=
368 // NULL. Thus on clear, we need to delete the object.
369 format(
370 "if (GetArenaNoVirtual() == nullptr && $name$_ != nullptr) {\n"
371 " delete $name$_;\n"
372 "}\n"
373 "$name$_ = nullptr;\n");
374 } else {
375 format(
376 "$DCHK$($name$_ != nullptr);\n"
377 "$name$_->Clear();\n");
378 }
379 }
380
GenerateMergingCode(io::Printer * printer) const381 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
382 Formatter format(printer, variables_);
383 if (implicit_weak_field_) {
384 format(
385 "_Internal::mutable_$name$(this)->CheckTypeAndMergeFrom(\n"
386 " _Internal::$name$(&from));\n");
387 } else {
388 format("mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
389 }
390 }
391
GenerateSwappingCode(io::Printer * printer) const392 void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
393 Formatter format(printer, variables_);
394 format("swap($name$_, other->$name$_);\n");
395 }
396
GenerateDestructorCode(io::Printer * printer) const397 void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
398 Formatter format(printer, variables_);
399 if (options_.opensource_runtime) {
400 // TODO(gerbens) Remove this when we don't need to destruct default
401 // instances. In google3 a default instance will never get deleted so we
402 // don't need to worry about that but in opensource protobuf default
403 // instances are deleted in shutdown process and we need to take special
404 // care when handling them.
405 format("if (this != internal_default_instance()) ");
406 }
407 format("delete $name$_;\n");
408 }
409
GenerateConstructorCode(io::Printer * printer) const410 void MessageFieldGenerator::GenerateConstructorCode(
411 io::Printer* printer) const {
412 Formatter format(printer, variables_);
413 format("$name$_ = nullptr;\n");
414 }
415
GenerateCopyConstructorCode(io::Printer * printer) const416 void MessageFieldGenerator::GenerateCopyConstructorCode(
417 io::Printer* printer) const {
418 Formatter format(printer, variables_);
419 format(
420 "if (from.has_$name$()) {\n"
421 " $name$_ = new $type$(*from.$name$_);\n"
422 "} else {\n"
423 " $name$_ = nullptr;\n"
424 "}\n");
425 }
426
GenerateMergeFromCodedStream(io::Printer * printer) const427 void MessageFieldGenerator::GenerateMergeFromCodedStream(
428 io::Printer* printer) const {
429 Formatter format(printer, variables_);
430 if (implicit_weak_field_) {
431 format(
432 "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessage(\n"
433 " input, _Internal::mutable_$name$(this)));\n");
434 } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
435 format(
436 "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessage(\n"
437 " input, mutable_$name$()));\n");
438 } else {
439 format(
440 "DO_(::$proto_ns$::internal::WireFormatLite::ReadGroup(\n"
441 " $number$, input, mutable_$name$()));\n");
442 }
443 }
444
GenerateSerializeWithCachedSizes(io::Printer * printer) const445 void MessageFieldGenerator::GenerateSerializeWithCachedSizes(
446 io::Printer* printer) const {
447 Formatter format(printer, variables_);
448 format(
449 "::$proto_ns$::internal::WireFormatLite::Write$stream_writer$(\n"
450 " $number$, _Internal::$name$(this), output);\n");
451 }
452
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const453 void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
454 io::Printer* printer) const {
455 Formatter format(printer, variables_);
456 format(
457 "target = ::$proto_ns$::internal::WireFormatLite::\n"
458 " InternalWrite$declared_type$ToArray(\n"
459 " $number$, _Internal::$name$(this), target);\n");
460 }
461
GenerateByteSize(io::Printer * printer) const462 void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const {
463 Formatter format(printer, variables_);
464 format(
465 "total_size += $tag_size$ +\n"
466 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
467 " *$field_member$);\n");
468 }
469
470 // ===================================================================
471
MessageOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)472 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
473 const FieldDescriptor* descriptor, const Options& options,
474 MessageSCCAnalyzer* scc_analyzer)
475 : MessageFieldGenerator(descriptor, options, scc_analyzer) {
476 SetCommonOneofFieldVariables(descriptor, &variables_);
477 }
478
~MessageOneofFieldGenerator()479 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
480
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const481 void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
482 io::Printer* printer) const {
483 Formatter format(printer, variables_);
484 format(
485 "void $classname$::set_allocated_$name$($type$* $name$) {\n"
486 " ::$proto_ns$::Arena* message_arena = GetArenaNoVirtual();\n"
487 " clear_$oneof_name$();\n"
488 " if ($name$) {\n");
489 if (SupportsArenas(descriptor_->message_type()) &&
490 descriptor_->file() != descriptor_->message_type()->file()) {
491 // We have to read the arena through the virtual method, because the type
492 // isn't defined in this file.
493 format(
494 " ::$proto_ns$::Arena* submessage_arena =\n"
495 " "
496 "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n");
497 } else if (!SupportsArenas(descriptor_->message_type())) {
498 format(" ::$proto_ns$::Arena* submessage_arena = nullptr;\n");
499 } else {
500 format(
501 " ::$proto_ns$::Arena* submessage_arena =\n"
502 " ::$proto_ns$::Arena::GetArena($name$);\n");
503 }
504 format(
505 " if (message_arena != submessage_arena) {\n"
506 " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n"
507 " message_arena, $name$, submessage_arena);\n"
508 " }\n"
509 " set_has_$name$();\n"
510 " $field_member$ = $name$;\n"
511 " }\n"
512 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
513 "}\n");
514 }
515
GenerateInlineAccessorDefinitions(io::Printer * printer) const516 void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions(
517 io::Printer* printer) const {
518 Formatter format(printer, variables_);
519 format(
520 "inline $type$* $classname$::$release_name$() {\n"
521 " // @@protoc_insertion_point(field_release:$full_name$)\n"
522 " if (has_$name$()) {\n"
523 " clear_has_$oneof_name$();\n"
524 " $type$* temp = $field_member$;\n");
525 if (SupportsArenas(descriptor_)) {
526 format(
527 " if (GetArenaNoVirtual() != nullptr) {\n"
528 " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n"
529 " }\n");
530 }
531 format(
532 " $field_member$ = nullptr;\n"
533 " return temp;\n"
534 " } else {\n"
535 " return nullptr;\n"
536 " }\n"
537 "}\n");
538
539 format(
540 "inline const $type$& $classname$::$name$() const {\n"
541 " // @@protoc_insertion_point(field_get:$full_name$)\n"
542 " return has_$name$()\n"
543 " ? *$field_member$\n"
544 " : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
545 "}\n");
546
547 if (SupportsArenas(descriptor_)) {
548 format(
549 "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
550 " // @@protoc_insertion_point(field_unsafe_arena_release"
551 ":$full_name$)\n"
552 " if (has_$name$()) {\n"
553 " clear_has_$oneof_name$();\n"
554 " $type$* temp = $field_member$;\n"
555 " $field_member$ = nullptr;\n"
556 " return temp;\n"
557 " } else {\n"
558 " return nullptr;\n"
559 " }\n"
560 "}\n"
561 "inline void $classname$::unsafe_arena_set_allocated_$name$"
562 "($type$* $name$) {\n"
563 // We rely on the oneof clear method to free the earlier contents of
564 // this oneof. We can directly use the pointer we're given to set the
565 // new value.
566 " clear_$oneof_name$();\n"
567 " if ($name$) {\n"
568 " set_has_$name$();\n"
569 " $field_member$ = $name$;\n"
570 " }\n"
571 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
572 "$full_name$)\n"
573 "}\n");
574 }
575
576 format(
577 "inline $type$* $classname$::mutable_$name$() {\n"
578 " if (!has_$name$()) {\n"
579 " clear_$oneof_name$();\n"
580 " set_has_$name$();\n"
581 " $field_member$ = CreateMaybeMessage< $type$ >(\n"
582 " GetArenaNoVirtual());\n"
583 " }\n"
584 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
585 " return $field_member$;\n"
586 "}\n");
587 }
588
GenerateClearingCode(io::Printer * printer) const589 void MessageOneofFieldGenerator::GenerateClearingCode(
590 io::Printer* printer) const {
591 Formatter format(printer, variables_);
592 if (SupportsArenas(descriptor_)) {
593 format(
594 "if (GetArenaNoVirtual() == nullptr) {\n"
595 " delete $field_member$;\n"
596 "}\n");
597 } else {
598 format("delete $field_member$;\n");
599 }
600 }
601
GenerateMessageClearingCode(io::Printer * printer) const602 void MessageOneofFieldGenerator::GenerateMessageClearingCode(
603 io::Printer* printer) const {
604 GenerateClearingCode(printer);
605 }
606
GenerateSwappingCode(io::Printer * printer) const607 void MessageOneofFieldGenerator::GenerateSwappingCode(
608 io::Printer* printer) const {
609 // Don't print any swapping code. Swapping the union will swap this field.
610 }
611
GenerateDestructorCode(io::Printer * printer) const612 void MessageOneofFieldGenerator::GenerateDestructorCode(
613 io::Printer* printer) const {
614 // We inherit from MessageFieldGenerator, so we need to override the default
615 // behavior.
616 }
617
GenerateConstructorCode(io::Printer * printer) const618 void MessageOneofFieldGenerator::GenerateConstructorCode(
619 io::Printer* printer) const {
620 // Don't print any constructor code. The field is in a union. We allocate
621 // space only when this field is used.
622 }
623
624 // ===================================================================
625
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options,MessageSCCAnalyzer * scc_analyzer)626 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
627 const FieldDescriptor* descriptor, const Options& options,
628 MessageSCCAnalyzer* scc_analyzer)
629 : FieldGenerator(descriptor, options),
630 implicit_weak_field_(
631 IsImplicitWeakField(descriptor, options, scc_analyzer)) {
632 SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_);
633 }
634
~RepeatedMessageFieldGenerator()635 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
636
GeneratePrivateMembers(io::Printer * printer) const637 void RepeatedMessageFieldGenerator::GeneratePrivateMembers(
638 io::Printer* printer) const {
639 Formatter format(printer, variables_);
640 format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n");
641 }
642
GenerateAccessorDeclarations(io::Printer * printer) const643 void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations(
644 io::Printer* printer) const {
645 Formatter format(printer, variables_);
646 format(
647 "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n"
648 "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n"
649 " ${1$mutable_$name$$}$();\n"
650 "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n"
651 "$deprecated_attr$$type$* ${1$add_$name$$}$();\n"
652 "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
653 " ${1$$name$$}$() const;\n",
654 descriptor_);
655 }
656
GenerateInlineAccessorDefinitions(io::Printer * printer) const657 void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions(
658 io::Printer* printer) const {
659 Formatter format(printer, variables_);
660 format(
661 "inline $type$* $classname$::mutable_$name$(int index) {\n"
662 // TODO(dlj): move insertion points
663 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
664 "$type_reference_function$"
665 " return $name$_.Mutable(index);\n"
666 "}\n"
667 "inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n"
668 "$classname$::mutable_$name$() {\n"
669 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
670 "$type_reference_function$"
671 " return &$name$_;\n"
672 "}\n");
673
674 if (options_.safe_boundary_check) {
675 format(
676 "inline const $type$& $classname$::$name$(int index) const {\n"
677 " // @@protoc_insertion_point(field_get:$full_name$)\n"
678 " return $name$_.InternalCheckedGet(index,\n"
679 " *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
680 "}\n");
681 } else {
682 format(
683 "inline const $type$& $classname$::$name$(int index) const {\n"
684 " // @@protoc_insertion_point(field_get:$full_name$)\n"
685 "$type_reference_function$"
686 " return $name$_.Get(index);\n"
687 "}\n");
688 }
689
690 format(
691 "inline $type$* $classname$::add_$name$() {\n"
692 " // @@protoc_insertion_point(field_add:$full_name$)\n"
693 " return $name$_.Add();\n"
694 "}\n");
695
696 format(
697 "inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n"
698 "$classname$::$name$() const {\n"
699 " // @@protoc_insertion_point(field_list:$full_name$)\n"
700 "$type_reference_function$"
701 " return $name$_;\n"
702 "}\n");
703 }
704
GenerateClearingCode(io::Printer * printer) const705 void RepeatedMessageFieldGenerator::GenerateClearingCode(
706 io::Printer* printer) const {
707 Formatter format(printer, variables_);
708 if (implicit_weak_field_) {
709 format(
710 "CastToBase(&$name$_)->Clear<"
711 "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>();\n");
712 } else {
713 format("$name$_.Clear();\n");
714 }
715 }
716
GenerateMergingCode(io::Printer * printer) const717 void RepeatedMessageFieldGenerator::GenerateMergingCode(
718 io::Printer* printer) const {
719 Formatter format(printer, variables_);
720 if (implicit_weak_field_) {
721 format(
722 "CastToBase(&$name$_)->MergeFrom<"
723 "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase("
724 "from.$name$_));\n");
725 } else {
726 format("$name$_.MergeFrom(from.$name$_);\n");
727 }
728 }
729
GenerateSwappingCode(io::Printer * printer) const730 void RepeatedMessageFieldGenerator::GenerateSwappingCode(
731 io::Printer* printer) const {
732 Formatter format(printer, variables_);
733 format("CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n");
734 }
735
GenerateConstructorCode(io::Printer * printer) const736 void RepeatedMessageFieldGenerator::GenerateConstructorCode(
737 io::Printer* printer) const {
738 // Not needed for repeated fields.
739 }
740
GenerateMergeFromCodedStream(io::Printer * printer) const741 void RepeatedMessageFieldGenerator::GenerateMergeFromCodedStream(
742 io::Printer* printer) const {
743 Formatter format(printer, variables_);
744 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
745 if (implicit_weak_field_) {
746 format(
747 "DO_(::$proto_ns$::internal::WireFormatLite::"
748 "ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n"
749 " reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n"
750 " &$type_default_instance$))));\n");
751 } else {
752 format(
753 "DO_(::$proto_ns$::internal::WireFormatLite::"
754 "ReadMessage(\n"
755 " input, add_$name$()));\n");
756 }
757 } else {
758 format(
759 "DO_(::$proto_ns$::internal::WireFormatLite::"
760 "ReadGroup($number$, input, add_$name$()));\n");
761 }
762 }
763
GenerateSerializeWithCachedSizes(io::Printer * printer) const764 void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizes(
765 io::Printer* printer) const {
766 Formatter format(printer, variables_);
767 format(
768 "for (unsigned int i = 0,\n"
769 " n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
770 " ::$proto_ns$::internal::WireFormatLite::Write$stream_writer$(\n"
771 " $number$,\n");
772 if (implicit_weak_field_) {
773 format(
774 " CastToBase($name$_).Get<"
775 "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>("
776 "static_cast<int>(i)),\n");
777 } else {
778 format(" this->$name$(static_cast<int>(i)),\n");
779 }
780 format(
781 " output);\n"
782 "}\n");
783 }
784
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const785 void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
786 io::Printer* printer) const {
787 Formatter format(printer, variables_);
788 format(
789 "for (unsigned int i = 0,\n"
790 " n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
791 " target = ::$proto_ns$::internal::WireFormatLite::\n"
792 " InternalWrite$declared_type$ToArray(\n"
793 " $number$, this->$name$(static_cast<int>(i)), target);\n"
794 "}\n");
795 }
796
GenerateByteSize(io::Printer * printer) const797 void RepeatedMessageFieldGenerator::GenerateByteSize(
798 io::Printer* printer) const {
799 Formatter format(printer, variables_);
800 format(
801 "{\n"
802 " unsigned int count = static_cast<unsigned "
803 "int>(this->$name$_size());\n");
804 format.Indent();
805 format(
806 "total_size += $tag_size$UL * count;\n"
807 "for (unsigned int i = 0; i < count; i++) {\n"
808 " total_size +=\n"
809 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n");
810 if (implicit_weak_field_) {
811 format(
812 " CastToBase($name$_).Get<"
813 "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>("
814 "static_cast<int>(i)));\n");
815 } else {
816 format(" this->$name$(static_cast<int>(i)));\n");
817 }
818 format("}\n");
819 format.Outdent();
820 format("}\n");
821 }
822
823 } // namespace cpp
824 } // namespace compiler
825 } // namespace protobuf
826 } // namespace google
827