cpp_primitive_field.cc revision d0332953cda33fb4f8e24ebff9c49159b69c43d6
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_primitive_field.h> 36#include <google/protobuf/compiler/cpp/cpp_helpers.h> 37#include <google/protobuf/io/printer.h> 38#include <google/protobuf/wire_format.h> 39#include <google/protobuf/stubs/strutil.h> 40 41namespace google { 42namespace protobuf { 43namespace compiler { 44namespace cpp { 45 46using internal::WireFormatLite; 47 48namespace { 49 50// For encodings with fixed sizes, returns that size in bytes. Otherwise 51// returns -1. 52int FixedSize(FieldDescriptor::Type type) { 53 switch (type) { 54 case FieldDescriptor::TYPE_INT32 : return -1; 55 case FieldDescriptor::TYPE_INT64 : return -1; 56 case FieldDescriptor::TYPE_UINT32 : return -1; 57 case FieldDescriptor::TYPE_UINT64 : return -1; 58 case FieldDescriptor::TYPE_SINT32 : return -1; 59 case FieldDescriptor::TYPE_SINT64 : return -1; 60 case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; 61 case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; 62 case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; 63 case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; 64 case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; 65 case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; 66 67 case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; 68 case FieldDescriptor::TYPE_ENUM : return -1; 69 70 case FieldDescriptor::TYPE_STRING : return -1; 71 case FieldDescriptor::TYPE_BYTES : return -1; 72 case FieldDescriptor::TYPE_GROUP : return -1; 73 case FieldDescriptor::TYPE_MESSAGE : return -1; 74 75 // No default because we want the compiler to complain if any new 76 // types are added. 77 } 78 GOOGLE_LOG(FATAL) << "Can't get here."; 79 return -1; 80} 81 82void SetPrimitiveVariables(const FieldDescriptor* descriptor, 83 map<string, string>* variables) { 84 SetCommonFieldVariables(descriptor, variables); 85 (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); 86 (*variables)["default"] = DefaultValue(descriptor); 87 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); 88 int fixed_size = FixedSize(descriptor->type()); 89 if (fixed_size != -1) { 90 (*variables)["fixed_size"] = SimpleItoa(fixed_size); 91 } 92 (*variables)["wire_format_field_type"] = 93 "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name( 94 static_cast<FieldDescriptorProto_Type>(descriptor->type())); 95} 96 97} // namespace 98 99// =================================================================== 100 101PrimitiveFieldGenerator:: 102PrimitiveFieldGenerator(const FieldDescriptor* descriptor) 103 : descriptor_(descriptor) { 104 SetPrimitiveVariables(descriptor, &variables_); 105} 106 107PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 108 109void PrimitiveFieldGenerator:: 110GeneratePrivateMembers(io::Printer* printer) const { 111 printer->Print(variables_, "$type$ $name$_;\n"); 112} 113 114void PrimitiveFieldGenerator:: 115GenerateAccessorDeclarations(io::Printer* printer) const { 116 printer->Print(variables_, 117 "inline $type$ $name$() const$deprecation$;\n" 118 "inline void set_$name$($type$ value)$deprecation$;\n"); 119} 120 121void PrimitiveFieldGenerator:: 122GenerateInlineAccessorDefinitions(io::Printer* printer) const { 123 printer->Print(variables_, 124 "inline $type$ $classname$::$name$() const {\n" 125 " return $name$_;\n" 126 "}\n" 127 "inline void $classname$::set_$name$($type$ value) {\n" 128 " _set_bit($index$);\n" 129 " $name$_ = value;\n" 130 "}\n"); 131} 132 133void PrimitiveFieldGenerator:: 134GenerateClearingCode(io::Printer* printer) const { 135 printer->Print(variables_, "$name$_ = $default$;\n"); 136} 137 138void PrimitiveFieldGenerator:: 139GenerateMergingCode(io::Printer* printer) const { 140 printer->Print(variables_, "set_$name$(from.$name$());\n"); 141} 142 143void PrimitiveFieldGenerator:: 144GenerateSwappingCode(io::Printer* printer) const { 145 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); 146} 147 148void PrimitiveFieldGenerator:: 149GenerateConstructorCode(io::Printer* printer) const { 150 printer->Print(variables_, "$name$_ = $default$;\n"); 151} 152 153void PrimitiveFieldGenerator:: 154GenerateMergeFromCodedStream(io::Printer* printer) const { 155 printer->Print(variables_, 156 "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" 157 " $type$, $wire_format_field_type$>(\n" 158 " input, &$name$_)));\n" 159 "_set_bit($index$);\n"); 160} 161 162void PrimitiveFieldGenerator:: 163GenerateSerializeWithCachedSizes(io::Printer* printer) const { 164 printer->Print(variables_, 165 "::google::protobuf::internal::WireFormatLite::Write$declared_type$(" 166 "$number$, this->$name$(), output);\n"); 167} 168 169void PrimitiveFieldGenerator:: 170GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 171 printer->Print(variables_, 172 "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(" 173 "$number$, this->$name$(), target);\n"); 174} 175 176void PrimitiveFieldGenerator:: 177GenerateByteSize(io::Printer* printer) const { 178 int fixed_size = FixedSize(descriptor_->type()); 179 if (fixed_size == -1) { 180 printer->Print(variables_, 181 "total_size += $tag_size$ +\n" 182 " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" 183 " this->$name$());\n"); 184 } else { 185 printer->Print(variables_, 186 "total_size += $tag_size$ + $fixed_size$;\n"); 187 } 188} 189 190// =================================================================== 191 192RepeatedPrimitiveFieldGenerator:: 193RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor) 194 : descriptor_(descriptor) { 195 SetPrimitiveVariables(descriptor, &variables_); 196 197 if (descriptor->options().packed()) { 198 variables_["packed_reader"] = "ReadPackedPrimitive"; 199 variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline"; 200 } else { 201 variables_["packed_reader"] = "ReadPackedPrimitiveNoInline"; 202 variables_["repeated_reader"] = "ReadRepeatedPrimitive"; 203 } 204} 205 206RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} 207 208void RepeatedPrimitiveFieldGenerator:: 209GeneratePrivateMembers(io::Printer* printer) const { 210 printer->Print(variables_, 211 "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); 212 if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { 213 printer->Print(variables_, 214 "mutable int _$name$_cached_byte_size_;\n"); 215 } 216} 217 218void RepeatedPrimitiveFieldGenerator:: 219GenerateAccessorDeclarations(io::Printer* printer) const { 220 printer->Print(variables_, 221 "inline $type$ $name$(int index) const$deprecation$;\n" 222 "inline void set_$name$(int index, $type$ value)$deprecation$;\n" 223 "inline void add_$name$($type$ value)$deprecation$;\n"); 224 printer->Print(variables_, 225 "inline const ::google::protobuf::RepeatedField< $type$ >&\n" 226 " $name$() const$deprecation$;\n" 227 "inline ::google::protobuf::RepeatedField< $type$ >*\n" 228 " mutable_$name$()$deprecation$;\n"); 229} 230 231void RepeatedPrimitiveFieldGenerator:: 232GenerateInlineAccessorDefinitions(io::Printer* printer) const { 233 printer->Print(variables_, 234 "inline $type$ $classname$::$name$(int index) const {\n" 235 " return $name$_.Get(index);\n" 236 "}\n" 237 "inline void $classname$::set_$name$(int index, $type$ value) {\n" 238 " $name$_.Set(index, value);\n" 239 "}\n" 240 "inline void $classname$::add_$name$($type$ value) {\n" 241 " $name$_.Add(value);\n" 242 "}\n"); 243 printer->Print(variables_, 244 "inline const ::google::protobuf::RepeatedField< $type$ >&\n" 245 "$classname$::$name$() const {\n" 246 " return $name$_;\n" 247 "}\n" 248 "inline ::google::protobuf::RepeatedField< $type$ >*\n" 249 "$classname$::mutable_$name$() {\n" 250 " return &$name$_;\n" 251 "}\n"); 252} 253 254void RepeatedPrimitiveFieldGenerator:: 255GenerateClearingCode(io::Printer* printer) const { 256 printer->Print(variables_, "$name$_.Clear();\n"); 257} 258 259void RepeatedPrimitiveFieldGenerator:: 260GenerateMergingCode(io::Printer* printer) const { 261 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); 262} 263 264void RepeatedPrimitiveFieldGenerator:: 265GenerateSwappingCode(io::Printer* printer) const { 266 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); 267} 268 269void RepeatedPrimitiveFieldGenerator:: 270GenerateConstructorCode(io::Printer* printer) const { 271 // Not needed for repeated fields. 272} 273 274void RepeatedPrimitiveFieldGenerator:: 275GenerateMergeFromCodedStream(io::Printer* printer) const { 276 printer->Print(variables_, 277 "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n" 278 " $type$, $wire_format_field_type$>(\n" 279 " $tag_size$, $tag$, input, this->mutable_$name$())));\n"); 280} 281 282void RepeatedPrimitiveFieldGenerator:: 283GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { 284 printer->Print(variables_, 285 "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n" 286 " $type$, $wire_format_field_type$>(\n" 287 " input, this->mutable_$name$())));\n"); 288} 289 290void RepeatedPrimitiveFieldGenerator:: 291GenerateSerializeWithCachedSizes(io::Printer* printer) const { 292 if (descriptor_->options().packed()) { 293 // Write the tag and the size. 294 printer->Print(variables_, 295 "if (this->$name$_size() > 0) {\n" 296 " ::google::protobuf::internal::WireFormatLite::WriteTag(" 297 "$number$, " 298 "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " 299 "output);\n" 300 " output->WriteVarint32(_$name$_cached_byte_size_);\n" 301 "}\n"); 302 } 303 printer->Print(variables_, 304 "for (int i = 0; i < this->$name$_size(); i++) {\n"); 305 if (descriptor_->options().packed()) { 306 printer->Print(variables_, 307 " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" 308 " this->$name$(i), output);\n"); 309 } else { 310 printer->Print(variables_, 311 " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" 312 " $number$, this->$name$(i), output);\n"); 313 } 314 printer->Print("}\n"); 315} 316 317void RepeatedPrimitiveFieldGenerator:: 318GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { 319 if (descriptor_->options().packed()) { 320 // Write the tag and the size. 321 printer->Print(variables_, 322 "if (this->$name$_size() > 0) {\n" 323 " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" 324 " $number$,\n" 325 " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" 326 " target);\n" 327 " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n" 328 " _$name$_cached_byte_size_, target);\n" 329 "}\n"); 330 } 331 printer->Print(variables_, 332 "for (int i = 0; i < this->$name$_size(); i++) {\n"); 333 if (descriptor_->options().packed()) { 334 printer->Print(variables_, 335 " target = ::google::protobuf::internal::WireFormatLite::\n" 336 " Write$declared_type$NoTagToArray(this->$name$(i), target);\n"); 337 } else { 338 printer->Print(variables_, 339 " target = ::google::protobuf::internal::WireFormatLite::\n" 340 " Write$declared_type$ToArray($number$, this->$name$(i), target);\n"); 341 } 342 printer->Print("}\n"); 343} 344 345void RepeatedPrimitiveFieldGenerator:: 346GenerateByteSize(io::Printer* printer) const { 347 printer->Print(variables_, 348 "{\n" 349 " int data_size = 0;\n"); 350 printer->Indent(); 351 int fixed_size = FixedSize(descriptor_->type()); 352 if (fixed_size == -1) { 353 printer->Print(variables_, 354 "for (int i = 0; i < this->$name$_size(); i++) {\n" 355 " data_size += ::google::protobuf::internal::WireFormatLite::\n" 356 " $declared_type$Size(this->$name$(i));\n" 357 "}\n"); 358 } else { 359 printer->Print(variables_, 360 "data_size = $fixed_size$ * this->$name$_size();\n"); 361 } 362 363 if (descriptor_->options().packed()) { 364 printer->Print(variables_, 365 "if (data_size > 0) {\n" 366 " total_size += $tag_size$ +\n" 367 " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" 368 "}\n" 369 "_$name$_cached_byte_size_ = data_size;\n" 370 "total_size += data_size;\n"); 371 } else { 372 printer->Print(variables_, 373 "total_size += $tag_size$ * this->$name$_size() + data_size;\n"); 374 } 375 printer->Outdent(); 376 printer->Print("}\n"); 377} 378 379} // namespace cpp 380} // namespace compiler 381} // namespace protobuf 382} // namespace google 383