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 (*variables)["stream_writer"] = (*variables)["declared_type"] + 53 (HasFastArraySerialization(descriptor->message_type()->file()) ? 54 "MaybeToArray" : 55 ""); 56 // NOTE: Escaped here to unblock proto1->proto2 migration. 57 // TODO(liujisi): Extend this to apply for other conflicting methods. 58 (*variables)["release_name"] = 59 SafeFunctionName(descriptor->containing_type(), 60 descriptor, "release_"); 61 (*variables)["full_name"] = descriptor->full_name(); 62} 63 64} // namespace 65 66// =================================================================== 67 68MessageFieldGenerator:: 69MessageFieldGenerator(const FieldDescriptor* descriptor, 70 const Options& options) 71 : descriptor_(descriptor) { 72 SetMessageVariables(descriptor, &variables_, options); 73} 74 75MessageFieldGenerator::~MessageFieldGenerator() {} 76 77void MessageFieldGenerator:: 78GeneratePrivateMembers(io::Printer* printer) const { 79 printer->Print(variables_, "$type$* $name$_;\n"); 80} 81 82void MessageFieldGenerator:: 83GenerateAccessorDeclarations(io::Printer* printer) const { 84 printer->Print(variables_, 85 "inline const $type$& $name$() const$deprecation$;\n" 86 "inline $type$* mutable_$name$()$deprecation$;\n" 87 "inline $type$* $release_name$()$deprecation$;\n" 88 "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n"); 89} 90 91void MessageFieldGenerator:: 92GenerateInlineAccessorDefinitions(io::Printer* printer) const { 93 printer->Print(variables_, 94 "inline const $type$& $classname$::$name$() const {\n" 95 " // @@protoc_insertion_point(field_get:$full_name$)\n"); 96 97 PrintHandlingOptionalStaticInitializers( 98 variables_, descriptor_->file(), printer, 99 // With static initializers. 100 " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", 101 // Without. 102 " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); 103 104 printer->Print(variables_, 105 "}\n" 106 "inline $type$* $classname$::mutable_$name$() {\n" 107 " set_has_$name$();\n" 108 " if ($name$_ == NULL) $name$_ = new $type$;\n" 109 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 110 " return $name$_;\n" 111 "}\n" 112 "inline $type$* $classname$::$release_name$() {\n" 113 " clear_has_$name$();\n" 114 " $type$* temp = $name$_;\n" 115 " $name$_ = NULL;\n" 116 " return temp;\n" 117 "}\n" 118 "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" 119 " delete $name$_;\n" 120 " $name$_ = $name$;\n" 121 " if ($name$) {\n" 122 " set_has_$name$();\n" 123 " } else {\n" 124 " clear_has_$name$();\n" 125 " }\n" 126 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" 127 "}\n"); 128} 129 130void MessageFieldGenerator:: 131GenerateClearingCode(io::Printer* printer) const { 132 printer->Print(variables_, 133 "if ($name$_ != NULL) $name$_->$type$::Clear();\n"); 134} 135 136void MessageFieldGenerator:: 137GenerateMergingCode(io::Printer* printer) const { 138 printer->Print(variables_, 139 "mutable_$name$()->$type$::MergeFrom(from.$name$());\n"); 140} 141 142void MessageFieldGenerator:: 143GenerateSwappingCode(io::Printer* printer) const { 144 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); 145} 146 147void MessageFieldGenerator:: 148GenerateConstructorCode(io::Printer* printer) const { 149 printer->Print(variables_, "$name$_ = NULL;\n"); 150} 151 152void MessageFieldGenerator:: 153GenerateMergeFromCodedStream(io::Printer* printer) const { 154 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { 155 printer->Print(variables_, 156 "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" 157 " input, mutable_$name$()));\n"); 158 } else { 159 printer->Print(variables_, 160 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" 161 " $number$, input, mutable_$name$()));\n"); 162 } 163} 164 165void MessageFieldGenerator:: 166GenerateSerializeWithCachedSizes(io::Printer* printer) const { 167 printer->Print(variables_, 168 "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" 169 " $number$, this->$name$(), output);\n"); 170} 171 172void MessageFieldGenerator:: 173GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 174 printer->Print(variables_, 175 "target = ::google::protobuf::internal::WireFormatLite::\n" 176 " Write$declared_type$NoVirtualToArray(\n" 177 " $number$, this->$name$(), target);\n"); 178} 179 180void MessageFieldGenerator:: 181GenerateByteSize(io::Printer* printer) const { 182 printer->Print(variables_, 183 "total_size += $tag_size$ +\n" 184 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" 185 " this->$name$());\n"); 186} 187 188// =================================================================== 189 190MessageOneofFieldGenerator:: 191MessageOneofFieldGenerator(const FieldDescriptor* descriptor, 192 const Options& options) 193 : MessageFieldGenerator(descriptor, options) { 194 SetCommonOneofFieldVariables(descriptor, &variables_); 195} 196 197MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} 198 199void MessageOneofFieldGenerator:: 200GenerateInlineAccessorDefinitions(io::Printer* printer) const { 201 printer->Print(variables_, 202 "inline const $type$& $classname$::$name$() const {\n" 203 " return has_$name$() ? *$oneof_prefix$$name$_\n" 204 " : $type$::default_instance();\n" 205 "}\n" 206 "inline $type$* $classname$::mutable_$name$() {\n" 207 " if (!has_$name$()) {\n" 208 " clear_$oneof_name$();\n" 209 " set_has_$name$();\n" 210 " $oneof_prefix$$name$_ = new $type$;\n" 211 " }\n" 212 " return $oneof_prefix$$name$_;\n" 213 "}\n" 214 "inline $type$* $classname$::$release_name$() {\n" 215 " if (has_$name$()) {\n" 216 " clear_has_$oneof_name$();\n" 217 " $type$* temp = $oneof_prefix$$name$_;\n" 218 " $oneof_prefix$$name$_ = NULL;\n" 219 " return temp;\n" 220 " } else {\n" 221 " return NULL;\n" 222 " }\n" 223 "}\n" 224 "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" 225 " clear_$oneof_name$();\n" 226 " if ($name$) {\n" 227 " set_has_$name$();\n" 228 " $oneof_prefix$$name$_ = $name$;\n" 229 " }\n" 230 "}\n"); 231} 232 233void MessageOneofFieldGenerator:: 234GenerateClearingCode(io::Printer* printer) const { 235 // if it is the active field, it cannot be NULL. 236 printer->Print(variables_, 237 "delete $oneof_prefix$$name$_;\n"); 238} 239 240void MessageOneofFieldGenerator:: 241GenerateSwappingCode(io::Printer* printer) const { 242 // Don't print any swapping code. Swapping the union will swap this field. 243} 244 245void MessageOneofFieldGenerator:: 246GenerateConstructorCode(io::Printer* printer) const { 247 // Don't print any constructor code. The field is in a union. We allocate 248 // space only when this field is used. 249} 250 251// =================================================================== 252 253RepeatedMessageFieldGenerator:: 254RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, 255 const Options& options) 256 : descriptor_(descriptor) { 257 SetMessageVariables(descriptor, &variables_, options); 258} 259 260RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} 261 262void RepeatedMessageFieldGenerator:: 263GeneratePrivateMembers(io::Printer* printer) const { 264 printer->Print(variables_, 265 "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n"); 266} 267 268void RepeatedMessageFieldGenerator:: 269GenerateAccessorDeclarations(io::Printer* printer) const { 270 printer->Print(variables_, 271 "inline const $type$& $name$(int index) const$deprecation$;\n" 272 "inline $type$* mutable_$name$(int index)$deprecation$;\n" 273 "inline $type$* add_$name$()$deprecation$;\n"); 274 printer->Print(variables_, 275 "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 276 " $name$() const$deprecation$;\n" 277 "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" 278 " mutable_$name$()$deprecation$;\n"); 279} 280 281void RepeatedMessageFieldGenerator:: 282GenerateInlineAccessorDefinitions(io::Printer* printer) const { 283 printer->Print(variables_, 284 "inline const $type$& $classname$::$name$(int index) const {\n" 285 " // @@protoc_insertion_point(field_get:$full_name$)\n" 286 " return $name$_.$cppget$(index);\n" 287 "}\n" 288 "inline $type$* $classname$::mutable_$name$(int index) {\n" 289 " // @@protoc_insertion_point(field_mutable:$full_name$)\n" 290 " return $name$_.Mutable(index);\n" 291 "}\n" 292 "inline $type$* $classname$::add_$name$() {\n" 293 " // @@protoc_insertion_point(field_add:$full_name$)\n" 294 " return $name$_.Add();\n" 295 "}\n"); 296 printer->Print(variables_, 297 "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 298 "$classname$::$name$() const {\n" 299 " // @@protoc_insertion_point(field_list:$full_name$)\n" 300 " return $name$_;\n" 301 "}\n" 302 "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" 303 "$classname$::mutable_$name$() {\n" 304 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" 305 " return &$name$_;\n" 306 "}\n"); 307} 308 309void RepeatedMessageFieldGenerator:: 310GenerateClearingCode(io::Printer* printer) const { 311 printer->Print(variables_, "$name$_.Clear();\n"); 312} 313 314void RepeatedMessageFieldGenerator:: 315GenerateMergingCode(io::Printer* printer) const { 316 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); 317} 318 319void RepeatedMessageFieldGenerator:: 320GenerateSwappingCode(io::Printer* printer) const { 321 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); 322} 323 324void RepeatedMessageFieldGenerator:: 325GenerateConstructorCode(io::Printer* printer) const { 326 // Not needed for repeated fields. 327} 328 329void RepeatedMessageFieldGenerator:: 330GenerateMergeFromCodedStream(io::Printer* printer) const { 331 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { 332 printer->Print(variables_, 333 "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" 334 " input, add_$name$()));\n"); 335 } else { 336 printer->Print(variables_, 337 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" 338 " $number$, input, add_$name$()));\n"); 339 } 340} 341 342void RepeatedMessageFieldGenerator:: 343GenerateSerializeWithCachedSizes(io::Printer* printer) const { 344 printer->Print(variables_, 345 "for (int i = 0; i < this->$name$_size(); i++) {\n" 346 " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" 347 " $number$, this->$name$(i), output);\n" 348 "}\n"); 349} 350 351void RepeatedMessageFieldGenerator:: 352GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 353 printer->Print(variables_, 354 "for (int i = 0; i < this->$name$_size(); i++) {\n" 355 " target = ::google::protobuf::internal::WireFormatLite::\n" 356 " Write$declared_type$NoVirtualToArray(\n" 357 " $number$, this->$name$(i), target);\n" 358 "}\n"); 359} 360 361void RepeatedMessageFieldGenerator:: 362GenerateByteSize(io::Printer* printer) const { 363 printer->Print(variables_, 364 "total_size += $tag_size$ * this->$name$_size();\n" 365 "for (int i = 0; i < this->$name$_size(); i++) {\n" 366 " total_size +=\n" 367 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" 368 " this->$name$(i));\n" 369 "}\n"); 370} 371 372} // namespace cpp 373} // namespace compiler 374} // namespace protobuf 375} // namespace google 376