1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 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 SetCommonFieldVariables(descriptor, variables); 50 (*variables)["type"] = FieldMessageTypeName(descriptor); 51 (*variables)["stream_writer"] = (*variables)["declared_type"] + 52 (HasFastArraySerialization(descriptor->message_type()->file()) ? 53 "MaybeToArray" : 54 ""); 55} 56 57} // namespace 58 59// =================================================================== 60 61MessageFieldGenerator:: 62MessageFieldGenerator(const FieldDescriptor* descriptor) 63 : descriptor_(descriptor) { 64 SetMessageVariables(descriptor, &variables_); 65} 66 67MessageFieldGenerator::~MessageFieldGenerator() {} 68 69void MessageFieldGenerator:: 70GeneratePrivateMembers(io::Printer* printer) const { 71 printer->Print(variables_, "$type$* $name$_;\n"); 72} 73 74void MessageFieldGenerator:: 75GenerateAccessorDeclarations(io::Printer* printer) const { 76 printer->Print(variables_, 77 "inline const $type$& $name$() const$deprecation$;\n" 78 "inline $type$* mutable_$name$()$deprecation$;\n"); 79} 80 81void MessageFieldGenerator:: 82GenerateInlineAccessorDefinitions(io::Printer* printer) const { 83 printer->Print(variables_, 84 "inline const $type$& $classname$::$name$() const {\n" 85 " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n" 86 "}\n" 87 "inline $type$* $classname$::mutable_$name$() {\n" 88 " _set_bit($index$);\n" 89 " if ($name$_ == NULL) $name$_ = new $type$;\n" 90 " return $name$_;\n" 91 "}\n"); 92} 93 94void MessageFieldGenerator:: 95GenerateClearingCode(io::Printer* printer) const { 96 printer->Print(variables_, 97 "if ($name$_ != NULL) $name$_->$type$::Clear();\n"); 98} 99 100void MessageFieldGenerator:: 101GenerateMergingCode(io::Printer* printer) const { 102 printer->Print(variables_, 103 "mutable_$name$()->$type$::MergeFrom(from.$name$());\n"); 104} 105 106void MessageFieldGenerator:: 107GenerateSwappingCode(io::Printer* printer) const { 108 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); 109} 110 111void MessageFieldGenerator:: 112GenerateConstructorCode(io::Printer* printer) const { 113 printer->Print(variables_, "$name$_ = NULL;\n"); 114} 115 116void MessageFieldGenerator:: 117GenerateMergeFromCodedStream(io::Printer* printer) const { 118 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { 119 printer->Print(variables_, 120 "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" 121 " input, mutable_$name$()));\n"); 122 } else { 123 printer->Print(variables_, 124 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" 125 " $number$, input, mutable_$name$()));\n"); 126 } 127} 128 129void MessageFieldGenerator:: 130GenerateSerializeWithCachedSizes(io::Printer* printer) const { 131 printer->Print(variables_, 132 "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" 133 " $number$, this->$name$(), output);\n"); 134} 135 136void MessageFieldGenerator:: 137GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 138 printer->Print(variables_, 139 "target = ::google::protobuf::internal::WireFormatLite::\n" 140 " Write$declared_type$NoVirtualToArray(\n" 141 " $number$, this->$name$(), target);\n"); 142} 143 144void MessageFieldGenerator:: 145GenerateByteSize(io::Printer* printer) const { 146 printer->Print(variables_, 147 "total_size += $tag_size$ +\n" 148 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" 149 " this->$name$());\n"); 150} 151 152// =================================================================== 153 154RepeatedMessageFieldGenerator:: 155RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor) 156 : descriptor_(descriptor) { 157 SetMessageVariables(descriptor, &variables_); 158} 159 160RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} 161 162void RepeatedMessageFieldGenerator:: 163GeneratePrivateMembers(io::Printer* printer) const { 164 printer->Print(variables_, 165 "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n"); 166} 167 168void RepeatedMessageFieldGenerator:: 169GenerateAccessorDeclarations(io::Printer* printer) const { 170 printer->Print(variables_, 171 "inline const $type$& $name$(int index) const$deprecation$;\n" 172 "inline $type$* mutable_$name$(int index)$deprecation$;\n" 173 "inline $type$* add_$name$()$deprecation$;\n"); 174 printer->Print(variables_, 175 "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 176 " $name$() const$deprecation$;\n" 177 "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" 178 " mutable_$name$()$deprecation$;\n"); 179} 180 181void RepeatedMessageFieldGenerator:: 182GenerateInlineAccessorDefinitions(io::Printer* printer) const { 183 printer->Print(variables_, 184 "inline const $type$& $classname$::$name$(int index) const {\n" 185 " return $name$_.Get(index);\n" 186 "}\n" 187 "inline $type$* $classname$::mutable_$name$(int index) {\n" 188 " return $name$_.Mutable(index);\n" 189 "}\n" 190 "inline $type$* $classname$::add_$name$() {\n" 191 " return $name$_.Add();\n" 192 "}\n"); 193 printer->Print(variables_, 194 "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" 195 "$classname$::$name$() const {\n" 196 " return $name$_;\n" 197 "}\n" 198 "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" 199 "$classname$::mutable_$name$() {\n" 200 " return &$name$_;\n" 201 "}\n"); 202} 203 204void RepeatedMessageFieldGenerator:: 205GenerateClearingCode(io::Printer* printer) const { 206 printer->Print(variables_, "$name$_.Clear();\n"); 207} 208 209void RepeatedMessageFieldGenerator:: 210GenerateMergingCode(io::Printer* printer) const { 211 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); 212} 213 214void RepeatedMessageFieldGenerator:: 215GenerateSwappingCode(io::Printer* printer) const { 216 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); 217} 218 219void RepeatedMessageFieldGenerator:: 220GenerateConstructorCode(io::Printer* printer) const { 221 // Not needed for repeated fields. 222} 223 224void RepeatedMessageFieldGenerator:: 225GenerateMergeFromCodedStream(io::Printer* printer) const { 226 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { 227 printer->Print(variables_, 228 "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" 229 " input, add_$name$()));\n"); 230 } else { 231 printer->Print(variables_, 232 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" 233 " $number$, input, add_$name$()));\n"); 234 } 235} 236 237void RepeatedMessageFieldGenerator:: 238GenerateSerializeWithCachedSizes(io::Printer* printer) const { 239 printer->Print(variables_, 240 "for (int i = 0; i < this->$name$_size(); i++) {\n" 241 " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" 242 " $number$, this->$name$(i), output);\n" 243 "}\n"); 244} 245 246void RepeatedMessageFieldGenerator:: 247GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 248 printer->Print(variables_, 249 "for (int i = 0; i < this->$name$_size(); i++) {\n" 250 " target = ::google::protobuf::internal::WireFormatLite::\n" 251 " Write$declared_type$NoVirtualToArray(\n" 252 " $number$, this->$name$(i), target);\n" 253 "}\n"); 254} 255 256void RepeatedMessageFieldGenerator:: 257GenerateByteSize(io::Printer* printer) const { 258 printer->Print(variables_, 259 "total_size += $tag_size$ * this->$name$_size();\n" 260 "for (int i = 0; i < this->$name$_size(); i++) {\n" 261 " total_size +=\n" 262 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" 263 " this->$name$(i));\n" 264 "}\n"); 265} 266 267} // namespace cpp 268} // namespace compiler 269} // namespace protobuf 270} // namespace google 271