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#include <google/protobuf/stubs/strutil.h> 39 40namespace google { 41namespace protobuf { 42namespace compiler { 43namespace cpp { 44 45namespace { 46 47void SetMessageVariables(const FieldDescriptor* descriptor, 48 map<string, string>* variables, 49 const Options& options) { 50 SetCommonFieldVariables(descriptor, variables, options); 51 (*variables)["type"] = FieldMessageTypeName(descriptor); 52 if (descriptor->options().weak() || !descriptor->containing_oneof()) { 53 (*variables)["non_null_ptr_to_name"] = 54 StrCat("this->", (*variables)["name"], "_"); 55 } 56 (*variables)["stream_writer"] = 57 (*variables)["declared_type"] + 58 (HasFastArraySerialization(descriptor->message_type()->file(), options) 59 ? "MaybeToArray" 60 : ""); 61 // NOTE: Escaped here to unblock proto1->proto2 migration. 62 // TODO(liujisi): Extend this to apply for other conflicting methods. 63 (*variables)["release_name"] = 64 SafeFunctionName(descriptor->containing_type(), 65 descriptor, "release_"); 66 (*variables)["full_name"] = descriptor->full_name(); 67 if (options.proto_h && IsFieldDependent(descriptor)) { 68 (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor); 69 (*variables)["dependent_typename"] = 70 "typename T::" + DependentTypeName(descriptor); 71 } else { 72 (*variables)["dependent_type"] = FieldMessageTypeName(descriptor); 73 (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor); 74 } 75} 76 77} // namespace 78 79// =================================================================== 80 81MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, 82 const Options& options) 83 : FieldGenerator(options), 84 descriptor_(descriptor), 85 dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { 86 SetMessageVariables(descriptor, &variables_, options); 87} 88 89MessageFieldGenerator::~MessageFieldGenerator() {} 90 91void MessageFieldGenerator:: 92GeneratePrivateMembers(io::Printer* printer) const { 93 printer->Print(variables_, "$type$* $name$_;\n"); 94} 95 96void MessageFieldGenerator:: 97GenerateGetterDeclaration(io::Printer* printer) const { 98 printer->Print(variables_, 99 "$deprecated_attr$const $type$& $name$() const;\n"); 100} 101 102void MessageFieldGenerator:: 103GenerateDependentAccessorDeclarations(io::Printer* printer) const { 104 if (!dependent_field_) { 105 return; 106 } 107 // Arena manipulation code is out-of-line in the derived message class. 108 printer->Print(variables_, 109 "$deprecated_attr$$type$* mutable_$name$();\n" 110 "$deprecated_attr$$type$* $release_name$();\n" 111 "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n"); 112} 113 114void MessageFieldGenerator:: 115GenerateAccessorDeclarations(io::Printer* printer) const { 116 if (SupportsArenas(descriptor_)) { 117 printer->Print(variables_, 118 "private:\n" 119 "void _slow_mutable_$name$();\n"); 120 if (SupportsArenas(descriptor_->message_type())) { 121 printer->Print(variables_, 122 "void _slow_set_allocated_$name$(\n" 123 " ::google::protobuf::Arena* message_arena, $type$** $name$);\n"); 124 } 125 printer->Print(variables_, 126 "$type$* _slow_$release_name$();\n" 127 "public:\n"); 128 } 129 GenerateGetterDeclaration(printer); 130 if (!dependent_field_) { 131 printer->Print(variables_, 132 "$deprecated_attr$$type$* mutable_$name$();\n" 133 "$deprecated_attr$$type$* $release_name$();\n" 134 "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n"); 135 } 136 if (SupportsArenas(descriptor_)) { 137 printer->Print(variables_, 138 "$deprecated_attr$$type$* unsafe_arena_release_$name$();\n" 139 "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n" 140 " $type$* $name$);\n"); 141 } 142} 143 144void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( 145 io::Printer* printer) const { 146 if (SupportsArenas(descriptor_)) { 147 printer->Print(variables_, 148 "void $classname$::_slow_mutable_$name$() {\n"); 149 if (SupportsArenas(descriptor_->message_type())) { 150 printer->Print(variables_, 151 " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" 152 " GetArenaNoVirtual());\n"); 153 } else { 154 printer->Print(variables_, 155 " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" 156 " GetArenaNoVirtual());\n"); 157 } 158 printer->Print(variables_, 159 "}\n" 160 "$type$* $classname$::_slow_$release_name$() {\n" 161 " if ($name$_ == NULL) {\n" 162 " return NULL;\n" 163 " } else {\n" 164 " $type$* temp = new $type$;\n" 165 " temp->MergeFrom(*$name$_);\n" 166 " $name$_ = NULL;\n" 167 " return temp;\n" 168 " }\n" 169 "}\n" 170 "$type$* $classname$::unsafe_arena_release_$name$() {\n" 171 " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" 172 " $clear_hasbit$\n" 173 " $type$* temp = $name$_;\n" 174 " $name$_ = NULL;\n" 175 " return temp;\n" 176 "}\n"); 177 if (SupportsArenas(descriptor_->message_type())) { 178 // NOTE: the same logic is mirrored in weak_message_field.cc. Any 179 // arena-related semantics changes should be made in both places. 180 printer->Print(variables_, 181 "void $classname$::_slow_set_allocated_$name$(\n" 182 " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n" 183 " if (message_arena != NULL && \n" 184 " ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n" 185 " message_arena->Own(*$name$);\n" 186 " } else if (message_arena !=\n" 187 " ::google::protobuf::Arena::GetArena(*$name$)) {\n" 188 " $type$* new_$name$ = \n" 189 " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" 190 " message_arena);\n" 191 " new_$name$->CopyFrom(**$name$);\n" 192 " *$name$ = new_$name$;\n" 193 " }\n" 194 "}\n"); 195 } 196 printer->Print(variables_, 197 "void $classname$::unsafe_arena_set_allocated_$name$(\n" 198 " $type$* $name$) {\n" 199 // If we're not on an arena, free whatever we were holding before. 200 // (If we are on arena, we can just forget the earlier pointer.) 201 " if (GetArenaNoVirtual() == NULL) {\n" 202 " delete $name$_;\n" 203 " }\n" 204 " $name$_ = $name$;\n" 205 " if ($name$) {\n" 206 " $set_hasbit$\n" 207 " } else {\n" 208 " $clear_hasbit$\n" 209 " }\n" 210 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" 211 ":$full_name$)\n" 212 "}\n"); 213 } 214} 215 216void MessageFieldGenerator:: 217GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { 218 if (!dependent_field_) { 219 return; 220 } 221 222 map<string, string> variables(variables_); 223 // For the CRTP base class, all mutation methods are dependent, and so 224 // they must be in the header. 225 variables["dependent_classname"] = 226 DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>"; 227 variables["this_message"] = DependentBaseDownCast(); 228 if (!variables["set_hasbit"].empty()) { 229 variables["set_hasbit"] = 230 variables["this_message"] + variables["set_hasbit"]; 231 } 232 if (!variables["clear_hasbit"].empty()) { 233 variables["clear_hasbit"] = 234 variables["this_message"] + variables["clear_hasbit"]; 235 } 236 237 if (SupportsArenas(descriptor_)) { 238 printer->Print(variables, 239 "template <class T>\n" 240 "inline $type$* $dependent_classname$::mutable_$name$() {\n" 241 " $set_hasbit$\n" 242 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" 243 " if ($name$_ == NULL) {\n" 244 " $this_message$_slow_mutable_$name$();\n" 245 " }\n" 246 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 247 " return $name$_;\n" 248 "}\n" 249 "template <class T>\n" 250 "inline $type$* $dependent_classname$::$release_name$() {\n" 251 " // @@protoc_insertion_point(field_release:$full_name$)\n" 252 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" 253 " $clear_hasbit$\n" 254 " if ($this_message$GetArenaNoVirtual() != NULL) {\n" 255 " return $this_message$_slow_$release_name$();\n" 256 " } else {\n" 257 " $dependent_typename$* temp = $name$_;\n" 258 " $name$_ = NULL;\n" 259 " return temp;\n" 260 " }\n" 261 "}\n" 262 "template <class T>\n" 263 "inline void $dependent_classname$::" 264 "set_allocated_$name$($type$* $name$) {\n" 265 " ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n" 266 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" 267 " if (message_arena == NULL) {\n" 268 " delete $name$_;\n" 269 " }\n" 270 " if ($name$ != NULL) {\n"); 271 if (SupportsArenas(descriptor_->message_type())) { 272 // If we're on an arena and the incoming message is not, simply Own() it 273 // rather than copy to the arena -- either way we need a heap dealloc, 274 // so we might as well defer it. Otherwise, if incoming message is on a 275 // different ownership domain (specific arena, or the heap) than we are, 276 // copy to our arena (or heap, as the case may be). 277 printer->Print(variables, 278 " $this_message$_slow_set_allocated_$name$(message_arena, " 279 "&$name$);\n"); 280 } else { 281 printer->Print(variables, 282 " if (message_arena != NULL) {\n" 283 " message_arena->Own($name$);\n" 284 " }\n"); 285 } 286 printer->Print(variables, 287 " }\n" 288 " $name$_ = $name$;\n" 289 " if ($name$) {\n" 290 " $set_hasbit$\n" 291 " } else {\n" 292 " $clear_hasbit$\n" 293 " }\n" 294 // TODO(dlj): move insertion points to message class. 295 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" 296 "}\n"); 297 } else { 298 printer->Print(variables, 299 "template <class T>\n" 300 "inline $type$* $dependent_classname$::mutable_$name$() {\n" 301 " $set_hasbit$\n" 302 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" 303 " if ($name$_ == NULL) {\n" 304 " $name$_ = new $dependent_typename$;\n" 305 " }\n" 306 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 307 " return $name$_;\n" 308 "}\n" 309 "template <class T>\n" 310 "inline $type$* $dependent_classname$::$release_name$() {\n" 311 " // @@protoc_insertion_point(field_release:$full_name$)\n" 312 " $clear_hasbit$\n" 313 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" 314 " $dependent_typename$* temp = $name$_;\n" 315 " $name$_ = NULL;\n" 316 " return temp;\n" 317 "}\n" 318 "template <class T>\n" 319 "inline void $dependent_classname$::" 320 "set_allocated_$name$($type$* $name$) {\n" 321 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" 322 " delete $name$_;\n"); 323 324 if (SupportsArenas(descriptor_->message_type())) { 325 printer->Print(variables, 326 " if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)" 327 "->GetArena() != NULL) {\n" 328 " $dependent_typename$* new_$name$ = new $dependent_typename$;\n" 329 " new_$name$->CopyFrom(*$name$);\n" 330 " $name$ = new_$name$;\n" 331 " }\n"); 332 } 333 334 printer->Print(variables, 335 " $name$_ = $name$;\n" 336 " if ($name$) {\n" 337 " $set_hasbit$\n" 338 " } else {\n" 339 " $clear_hasbit$\n" 340 " }\n" 341 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" 342 "}\n"); 343 } 344} 345 346void MessageFieldGenerator:: 347GenerateInlineAccessorDefinitions(io::Printer* printer, 348 bool is_inline) const { 349 map<string, string> variables(variables_); 350 variables["inline"] = is_inline ? "inline " : ""; 351 printer->Print(variables, 352 "$inline$const $type$& $classname$::$name$() const {\n" 353 " // @@protoc_insertion_point(field_get:$full_name$)\n"); 354 355 PrintHandlingOptionalStaticInitializers( 356 variables, descriptor_->file(), options_, printer, 357 // With static initializers. 358 " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", 359 // Without. 360 " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); 361 printer->Print(variables, "}\n"); 362 363 if (dependent_field_) { 364 return; 365 } 366 367 if (SupportsArenas(descriptor_)) { 368 printer->Print(variables, 369 "$inline$" 370 "$type$* $classname$::mutable_$name$() {\n" 371 " $set_hasbit$\n" 372 " if ($name$_ == NULL) {\n" 373 " _slow_mutable_$name$();\n" 374 " }\n" 375 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 376 " return $name$_;\n" 377 "}\n" 378 "$inline$" 379 "$type$* $classname$::$release_name$() {\n" 380 " // @@protoc_insertion_point(field_release:$full_name$)\n" 381 " $clear_hasbit$\n" 382 " if (GetArenaNoVirtual() != NULL) {\n" 383 " return _slow_$release_name$();\n" 384 " } else {\n" 385 " $type$* temp = $name$_;\n" 386 " $name$_ = NULL;\n" 387 " return temp;\n" 388 " }\n" 389 "}\n" 390 "$inline$ " 391 "void $classname$::set_allocated_$name$($type$* $name$) {\n" 392 " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n" 393 " if (message_arena == NULL) {\n" 394 " delete $name$_;\n" 395 " }\n" 396 " if ($name$ != NULL) {\n"); 397 if (SupportsArenas(descriptor_->message_type())) { 398 // If we're on an arena and the incoming message is not, simply Own() it 399 // rather than copy to the arena -- either way we need a heap dealloc, 400 // so we might as well defer it. Otherwise, if incoming message is on a 401 // different ownership domain (specific arena, or the heap) than we are, 402 // copy to our arena (or heap, as the case may be). 403 printer->Print(variables, 404 " _slow_set_allocated_$name$(message_arena, &$name$);\n"); 405 } else { 406 printer->Print(variables, 407 " if (message_arena != NULL) {\n" 408 " message_arena->Own($name$);\n" 409 " }\n"); 410 } 411 printer->Print(variables, 412 " }\n" 413 " $name$_ = $name$;\n" 414 " if ($name$) {\n" 415 " $set_hasbit$\n" 416 " } else {\n" 417 " $clear_hasbit$\n" 418 " }\n" 419 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" 420 "}\n"); 421 } else { 422 printer->Print(variables, 423 "$inline$" 424 "$type$* $classname$::mutable_$name$() {\n" 425 " $set_hasbit$\n" 426 " if ($name$_ == NULL) {\n" 427 " $name$_ = new $type$;\n" 428 " }\n" 429 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 430 " return $name$_;\n" 431 "}\n" 432 "$inline$" 433 "$type$* $classname$::$release_name$() {\n" 434 " // @@protoc_insertion_point(field_release:$full_name$)\n" 435 " $clear_hasbit$\n" 436 " $type$* temp = $name$_;\n" 437 " $name$_ = NULL;\n" 438 " return temp;\n" 439 "}\n" 440 "$inline$" 441 "void $classname$::set_allocated_$name$($type$* $name$) {\n" 442 " delete $name$_;\n"); 443 444 if (SupportsArenas(descriptor_->message_type())) { 445 printer->Print(variables, 446 " if ($name$ != NULL && $name$->GetArena() != NULL) {\n" 447 " $type$* new_$name$ = new $type$;\n" 448 " new_$name$->CopyFrom(*$name$);\n" 449 " $name$ = new_$name$;\n" 450 " }\n"); 451 } 452 453 printer->Print(variables, 454 " $name$_ = $name$;\n" 455 " if ($name$) {\n" 456 " $set_hasbit$\n" 457 " } else {\n" 458 " $clear_hasbit$\n" 459 " }\n" 460 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" 461 "}\n"); 462 } 463} 464 465void MessageFieldGenerator:: 466GenerateClearingCode(io::Printer* printer) const { 467 map<string, string> variables(variables_); 468 variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; 469 if (!HasFieldPresence(descriptor_->file())) { 470 // If we don't have has-bits, message presence is indicated only by ptr != 471 // NULL. Thus on clear, we need to delete the object. 472 printer->Print(variables, 473 "if ($this_message$GetArenaNoVirtual() == NULL && " 474 "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n" 475 "$this_message$$name$_ = NULL;\n"); 476 } else { 477 printer->Print(variables, 478 "if ($this_message$$name$_ != NULL) $this_message$$name$_->" 479 "$dependent_type$::Clear();\n"); 480 } 481} 482 483void MessageFieldGenerator:: 484GenerateMergingCode(io::Printer* printer) const { 485 printer->Print(variables_, 486 "mutable_$name$()->$type$::MergeFrom(from.$name$());\n"); 487} 488 489void MessageFieldGenerator:: 490GenerateSwappingCode(io::Printer* printer) const { 491 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); 492} 493 494void MessageFieldGenerator:: 495GenerateConstructorCode(io::Printer* printer) const { 496 printer->Print(variables_, "$name$_ = NULL;\n"); 497} 498 499void MessageFieldGenerator:: 500GenerateMergeFromCodedStream(io::Printer* printer) const { 501 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { 502 printer->Print(variables_, 503 "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" 504 " input, mutable_$name$()));\n"); 505 } else { 506 printer->Print(variables_, 507 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" 508 " $number$, input, mutable_$name$()));\n"); 509 } 510} 511 512void MessageFieldGenerator:: 513GenerateSerializeWithCachedSizes(io::Printer* printer) const { 514 printer->Print(variables_, 515 "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" 516 " $number$, *$non_null_ptr_to_name$, output);\n"); 517} 518 519void MessageFieldGenerator:: 520GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 521 printer->Print(variables_, 522 "target = ::google::protobuf::internal::WireFormatLite::\n" 523 " Write$declared_type$NoVirtualToArray(\n" 524 " $number$, *$non_null_ptr_to_name$, target);\n"); 525} 526 527void MessageFieldGenerator:: 528GenerateByteSize(io::Printer* printer) const { 529 printer->Print(variables_, 530 "total_size += $tag_size$ +\n" 531 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" 532 " *$non_null_ptr_to_name$);\n"); 533} 534 535// =================================================================== 536 537MessageOneofFieldGenerator:: 538MessageOneofFieldGenerator(const FieldDescriptor* descriptor, 539 const Options& options) 540 : MessageFieldGenerator(descriptor, options), 541 dependent_base_(options.proto_h) { 542 SetCommonOneofFieldVariables(descriptor, &variables_); 543} 544 545MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} 546 547 548void MessageOneofFieldGenerator:: 549GenerateDependentAccessorDeclarations(io::Printer* printer) const { 550 // Oneof field getters must be dependent as they call default_instance(). 551 // Otherwise, the logic is the same as MessageFields. 552 if (!dependent_field_) { 553 return; 554 } 555 printer->Print(variables_, 556 "$deprecated_attr$const $type$& $name$() const;\n"); 557 MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer); 558} 559 560void MessageOneofFieldGenerator:: 561GenerateGetterDeclaration(io::Printer* printer) const { 562 // Oneof field getters must be dependent as they call default_instance(). 563 // Unlike MessageField, this means there is no (non-dependent) getter to 564 // generate. 565 if (dependent_field_) { 566 return; 567 } 568 printer->Print(variables_, 569 "$deprecated_attr$const $type$& $name$() const;\n"); 570} 571 572void MessageOneofFieldGenerator:: 573GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { 574 // For the CRTP base class, all mutation methods are dependent, and so 575 // they must be in the header. 576 if (!dependent_base_) { 577 return; 578 } 579 map<string, string> variables(variables_); 580 variables["inline"] = "inline "; 581 variables["dependent_classname"] = 582 DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>"; 583 variables["this_message"] = "reinterpret_cast<T*>(this)->"; 584 // Const message access is needed for the dependent getter. 585 variables["this_const_message"] = "reinterpret_cast<const T*>(this)->"; 586 variables["tmpl"] = "template <class T>\n"; 587 variables["field_member"] = variables["this_message"] + 588 variables["oneof_prefix"] + variables["name"] + 589 "_"; 590 InternalGenerateInlineAccessorDefinitions(variables, printer); 591} 592 593void MessageOneofFieldGenerator:: 594GenerateInlineAccessorDefinitions(io::Printer* printer, 595 bool is_inline) const { 596 if (dependent_base_) { 597 return; 598 } 599 map<string, string> variables(variables_); 600 variables["inline"] = is_inline ? "inline " : ""; 601 variables["dependent_classname"] = variables["classname"]; 602 variables["this_message"] = ""; 603 variables["this_const_message"] = ""; 604 variables["tmpl"] = ""; 605 variables["field_member"] = 606 variables["oneof_prefix"] + variables["name"] + "_"; 607 variables["dependent_type"] = variables["type"]; 608 InternalGenerateInlineAccessorDefinitions(variables, printer); 609} 610 611void MessageOneofFieldGenerator:: 612GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { 613 map<string, string> variables(variables_); 614 variables["field_member"] = 615 variables["oneof_prefix"] + variables["name"] + "_"; 616 617 //printer->Print(variables, 618} 619 620void MessageOneofFieldGenerator:: 621InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables, 622 io::Printer* printer) const { 623 printer->Print(variables, 624 "$tmpl$" 625 "$inline$ " 626 "const $type$& $dependent_classname$::$name$() const {\n" 627 " // @@protoc_insertion_point(field_get:$full_name$)\n" 628 " return $this_const_message$has_$name$()\n" 629 " ? *$this_const_message$$oneof_prefix$$name$_\n" 630 " : $dependent_type$::default_instance();\n" 631 "}\n"); 632 633 if (SupportsArenas(descriptor_)) { 634 printer->Print(variables, 635 "$tmpl$" 636 "$inline$" 637 "$type$* $dependent_classname$::mutable_$name$() {\n" 638 " if (!$this_message$has_$name$()) {\n" 639 " $this_message$clear_$oneof_name$();\n" 640 " $this_message$set_has_$name$();\n"); 641 if (SupportsArenas(descriptor_->message_type())) { 642 printer->Print(variables, 643 " $field_member$ = \n" 644 " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n" 645 " $this_message$GetArenaNoVirtual());\n"); 646 } else { 647 printer->Print(variables, 648 " $this_message$$oneof_prefix$$name$_ = \n" 649 " ::google::protobuf::Arena::Create< $dependent_typename$ >(\n" 650 " $this_message$GetArenaNoVirtual());\n"); 651 } 652 printer->Print(variables, 653 " }\n" 654 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 655 " return $field_member$;\n" 656 "}\n" 657 "$tmpl$" 658 "$inline$" 659 "$type$* $dependent_classname$::$release_name$() {\n" 660 " // @@protoc_insertion_point(field_release:$full_name$)\n" 661 " if ($this_message$has_$name$()) {\n" 662 " $this_message$clear_has_$oneof_name$();\n" 663 " if ($this_message$GetArenaNoVirtual() != NULL) {\n" 664 // N.B.: safe to use the underlying field pointer here because we are sure 665 // that it is non-NULL (because has_$name$() returned true). 666 " $dependent_typename$* temp = new $dependent_typename$;\n" 667 " temp->MergeFrom(*$field_member$);\n" 668 " $field_member$ = NULL;\n" 669 " return temp;\n" 670 " } else {\n" 671 " $dependent_typename$* temp = $field_member$;\n" 672 " $field_member$ = NULL;\n" 673 " return temp;\n" 674 " }\n" 675 " } else {\n" 676 " return NULL;\n" 677 " }\n" 678 "}\n" 679 "$tmpl$" 680 "$inline$" 681 "void $dependent_classname$::" 682 "set_allocated_$name$($type$* $name$) {\n" 683 " $this_message$clear_$oneof_name$();\n" 684 " if ($name$) {\n"); 685 686 if (SupportsArenas(descriptor_->message_type())) { 687 printer->Print(variables, 688 // If incoming message is on the heap and we are on an arena, just Own() 689 // it (see above). If it's on a different arena than we are or one of us 690 // is on the heap, we make a copy to our arena/heap. 691 " if ($this_message$GetArenaNoVirtual() != NULL &&\n" 692 " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n" 693 " $this_message$GetArenaNoVirtual()->Own($name$);\n" 694 " } else if ($this_message$GetArenaNoVirtual() !=\n" 695 " ::google::protobuf::Arena::GetArena($name$)) {\n" 696 " $dependent_typename$* new_$name$ = \n" 697 " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n" 698 " $this_message$GetArenaNoVirtual());\n" 699 " new_$name$->CopyFrom(*$name$);\n" 700 " $name$ = new_$name$;\n" 701 " }\n"); 702 } else { 703 printer->Print(variables, 704 " if ($this_message$GetArenaNoVirtual() != NULL) {\n" 705 " $this_message$GetArenaNoVirtual()->Own($name$);\n" 706 " }\n"); 707 } 708 709 printer->Print(variables, 710 " $this_message$set_has_$name$();\n" 711 " $field_member$ = $name$;\n" 712 " }\n" 713 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" 714 "}\n" 715 "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n" 716 " // @@protoc_insertion_point(field_unsafe_arena_release" 717 ":$full_name$)\n" 718 " if (has_$name$()) {\n" 719 " clear_has_$oneof_name$();\n" 720 " $type$* temp = $oneof_prefix$$name$_;\n" 721 " $oneof_prefix$$name$_ = NULL;\n" 722 " return temp;\n" 723 " } else {\n" 724 " return NULL;\n" 725 " }\n" 726 "}\n" 727 "$inline$ void $classname$::unsafe_arena_set_allocated_$name$" 728 "($type$* $name$) {\n" 729 // We rely on the oneof clear method to free the earlier contents of this 730 // oneof. We can directly use the pointer we're given to set the new 731 // value. 732 " clear_$oneof_name$();\n" 733 " if ($name$) {\n" 734 " set_has_$name$();\n" 735 " $oneof_prefix$$name$_ = $name$;\n" 736 " }\n" 737 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" 738 "$full_name$)\n" 739 "}\n"); 740 } else { 741 printer->Print(variables, 742 "$tmpl$" 743 "$inline$" 744 "$type$* $dependent_classname$::mutable_$name$() {\n" 745 " if (!$this_message$has_$name$()) {\n" 746 " $this_message$clear_$oneof_name$();\n" 747 " $this_message$set_has_$name$();\n" 748 " $field_member$ = new $dependent_typename$;\n" 749 " }\n" 750 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 751 " return $field_member$;\n" 752 "}\n" 753 "$tmpl$" 754 "$inline$" 755 "$type$* $dependent_classname$::$release_name$() {\n" 756 " // @@protoc_insertion_point(field_release:$full_name$)\n" 757 " if ($this_message$has_$name$()) {\n" 758 " $this_message$clear_has_$oneof_name$();\n" 759 " $dependent_typename$* temp = $field_member$;\n" 760 " $field_member$ = NULL;\n" 761 " return temp;\n" 762 " } else {\n" 763 " return NULL;\n" 764 " }\n" 765 "}\n" 766 "$tmpl$" 767 "$inline$" 768 "void $dependent_classname$::" 769 "set_allocated_$name$($type$* $name$) {\n" 770 " $this_message$clear_$oneof_name$();\n" 771 " if ($name$) {\n"); 772 if (SupportsArenas(descriptor_->message_type())) { 773 printer->Print(variables, 774 " if (static_cast< $dependent_typename$*>($name$)->" 775 "GetArena() != NULL) {\n" 776 " $dependent_typename$* new_$name$ = new $dependent_typename$;\n" 777 " new_$name$->CopyFrom(*$name$);\n" 778 " $name$ = new_$name$;\n" 779 " }\n"); 780 } 781 printer->Print(variables, 782 " $this_message$set_has_$name$();\n" 783 " $field_member$ = $name$;\n" 784 " }\n" 785 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" 786 "}\n"); 787 } 788} 789 790void MessageOneofFieldGenerator:: 791GenerateClearingCode(io::Printer* printer) const { 792 map<string, string> variables(variables_); 793 variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; 794 if (SupportsArenas(descriptor_)) { 795 printer->Print(variables, 796 "if ($this_message$GetArenaNoVirtual() == NULL) {\n" 797 " delete $this_message$$oneof_prefix$$name$_;\n" 798 "}\n"); 799 } else { 800 printer->Print(variables, 801 "delete $this_message$$oneof_prefix$$name$_;\n"); 802 } 803} 804 805void MessageOneofFieldGenerator:: 806GenerateSwappingCode(io::Printer* printer) const { 807 // Don't print any swapping code. Swapping the union will swap this field. 808} 809 810void MessageOneofFieldGenerator:: 811GenerateConstructorCode(io::Printer* printer) const { 812 // Don't print any constructor code. The field is in a union. We allocate 813 // space only when this field is used. 814} 815 816// =================================================================== 817 818RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( 819 const FieldDescriptor* descriptor, const Options& options) 820 : FieldGenerator(options), 821 descriptor_(descriptor), 822 dependent_field_(options.proto_h && IsFieldDependent(descriptor)), 823 dependent_getter_(dependent_field_ && options.safe_boundary_check) { 824 SetMessageVariables(descriptor, &variables_, options); 825} 826 827RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} 828 829void RepeatedMessageFieldGenerator:: 830GeneratePrivateMembers(io::Printer* printer) const { 831 printer->Print(variables_, 832 "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n"); 833} 834 835void RepeatedMessageFieldGenerator:: 836InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const { 837 printer->Print(variables_, 838 "$deprecated_attr$$type$* mutable_$name$(int index);\n" 839 "$deprecated_attr$$type$* add_$name$();\n"); 840 if (dependent_getter_) { 841 printer->Print(variables_, 842 "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 843 " $name$() const;\n"); 844 } 845 printer->Print(variables_, 846 "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n" 847 " mutable_$name$();\n"); 848} 849 850void RepeatedMessageFieldGenerator:: 851GenerateDependentAccessorDeclarations(io::Printer* printer) const { 852 if (dependent_getter_) { 853 printer->Print(variables_, 854 "$deprecated_attr$const $type$& $name$(int index) const;\n"); 855 } 856 if (dependent_field_) { 857 InternalGenerateTypeDependentAccessorDeclarations(printer); 858 } 859} 860 861void RepeatedMessageFieldGenerator:: 862GenerateAccessorDeclarations(io::Printer* printer) const { 863 if (!dependent_getter_) { 864 printer->Print(variables_, 865 "$deprecated_attr$const $type$& $name$(int index) const;\n"); 866 } 867 if (!dependent_field_) { 868 InternalGenerateTypeDependentAccessorDeclarations(printer); 869 } 870 if (!dependent_getter_) { 871 printer->Print(variables_, 872 "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 873 " $name$() const;\n"); 874 } 875} 876 877void RepeatedMessageFieldGenerator:: 878GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { 879 if (!dependent_field_) { 880 return; 881 } 882 map<string, string> variables(variables_); 883 // For the CRTP base class, all mutation methods are dependent, and so 884 // they must be in the header. 885 variables["dependent_classname"] = 886 DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>"; 887 variables["this_message"] = DependentBaseDownCast(); 888 variables["this_const_message"] = DependentBaseConstDownCast(); 889 890 if (dependent_getter_) { 891 printer->Print(variables, 892 "template <class T>\n" 893 "inline const $type$& $dependent_classname$::$name$(int index) const {\n" 894 " // @@protoc_insertion_point(field_get:$full_name$)\n" 895 " return $this_const_message$$name$_.$cppget$(index);\n" 896 "}\n"); 897 } 898 899 // Generate per-element accessors: 900 printer->Print(variables, 901 "template <class T>\n" 902 "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n" 903 // TODO(dlj): move insertion points 904 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 905 " return $this_message$$name$_.Mutable(index);\n" 906 "}\n" 907 "template <class T>\n" 908 "inline $type$* $dependent_classname$::add_$name$() {\n" 909 " // @@protoc_insertion_point(field_add:$full_name$)\n" 910 " return $this_message$$name$_.Add();\n" 911 "}\n"); 912 913 914 if (dependent_getter_) { 915 printer->Print(variables, 916 "template <class T>\n" 917 "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 918 "$dependent_classname$::$name$() const {\n" 919 " // @@protoc_insertion_point(field_list:$full_name$)\n" 920 " return $this_const_message$$name$_;\n" 921 "}\n"); 922 } 923 924 // Generate mutable access to the entire list: 925 printer->Print(variables, 926 "template <class T>\n" 927 "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" 928 "$dependent_classname$::mutable_$name$() {\n" 929 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" 930 " return &$this_message$$name$_;\n" 931 "}\n"); 932} 933 934void RepeatedMessageFieldGenerator:: 935GenerateInlineAccessorDefinitions(io::Printer* printer, 936 bool is_inline) const { 937 map<string, string> variables(variables_); 938 variables["inline"] = is_inline ? "inline " : ""; 939 940 if (!dependent_getter_) { 941 printer->Print(variables, 942 "$inline$" 943 "const $type$& $classname$::$name$(int index) const {\n" 944 " // @@protoc_insertion_point(field_get:$full_name$)\n" 945 " return $name$_.$cppget$(index);\n" 946 "}\n"); 947 } 948 949 if (!dependent_field_) { 950 printer->Print(variables, 951 "$inline$" 952 "$type$* $classname$::mutable_$name$(int index) {\n" 953 // TODO(dlj): move insertion points 954 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 955 " return $name$_.Mutable(index);\n" 956 "}\n" 957 "$inline$" 958 "$type$* $classname$::add_$name$() {\n" 959 " // @@protoc_insertion_point(field_add:$full_name$)\n" 960 " return $name$_.Add();\n" 961 "}\n"); 962 } 963 964 965 if (!dependent_field_) { 966 printer->Print(variables, 967 "$inline$" 968 "::google::protobuf::RepeatedPtrField< $type$ >*\n" 969 "$classname$::mutable_$name$() {\n" 970 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" 971 " return &$name$_;\n" 972 "}\n"); 973 } 974 if (!dependent_getter_) { 975 printer->Print(variables, 976 "$inline$" 977 "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 978 "$classname$::$name$() const {\n" 979 " // @@protoc_insertion_point(field_list:$full_name$)\n" 980 " return $name$_;\n" 981 "}\n"); 982 } 983} 984 985void RepeatedMessageFieldGenerator:: 986GenerateClearingCode(io::Printer* printer) const { 987 map<string, string> variables(variables_); 988 variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; 989 printer->Print(variables, "$this_message$$name$_.Clear();\n"); 990} 991 992void RepeatedMessageFieldGenerator:: 993GenerateMergingCode(io::Printer* printer) const { 994 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); 995} 996 997void RepeatedMessageFieldGenerator:: 998GenerateSwappingCode(io::Printer* printer) const { 999 printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n"); 1000} 1001 1002void RepeatedMessageFieldGenerator:: 1003GenerateConstructorCode(io::Printer* printer) const { 1004 // Not needed for repeated fields. 1005} 1006 1007void RepeatedMessageFieldGenerator:: 1008GenerateMergeFromCodedStream(io::Printer* printer) const { 1009 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { 1010 printer->Print(variables_, 1011 "DO_(::google::protobuf::internal::WireFormatLite::" 1012 "ReadMessageNoVirtualNoRecursionDepth(\n" 1013 " input, add_$name$()));\n"); 1014 } else { 1015 printer->Print(variables_, 1016 "DO_(::google::protobuf::internal::WireFormatLite::" 1017 "ReadGroupNoVirtualNoRecursionDepth(\n" 1018 " $number$, input, add_$name$()));\n"); 1019 } 1020} 1021 1022void RepeatedMessageFieldGenerator:: 1023GenerateSerializeWithCachedSizes(io::Printer* printer) const { 1024 printer->Print(variables_, 1025 "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n" 1026 " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" 1027 " $number$, this->$name$(i), output);\n" 1028 "}\n"); 1029} 1030 1031void RepeatedMessageFieldGenerator:: 1032GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 1033 printer->Print(variables_, 1034 "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n" 1035 " target = ::google::protobuf::internal::WireFormatLite::\n" 1036 " Write$declared_type$NoVirtualToArray(\n" 1037 " $number$, this->$name$(i), target);\n" 1038 "}\n"); 1039} 1040 1041void RepeatedMessageFieldGenerator:: 1042GenerateByteSize(io::Printer* printer) const { 1043 printer->Print(variables_, 1044 "total_size += $tag_size$ * this->$name$_size();\n" 1045 "for (int i = 0; i < this->$name$_size(); i++) {\n" 1046 " total_size +=\n" 1047 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" 1048 " this->$name$(i));\n" 1049 "}\n"); 1050} 1051 1052} // namespace cpp 1053} // namespace compiler 1054} // namespace protobuf 1055} // namespace google 1056