| 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/primitive_field.h> | 
| 36 |  | 
| 37 | #include <google/protobuf/io/printer.h> | 
| 38 | #include <google/protobuf/wire_format.h> | 
| 39 | #include <google/protobuf/stubs/strutil.h> | 
| 40 | #include <google/protobuf/compiler/cpp/helpers.h> | 
| 41 |  | 
| 42 | namespace google { | 
| 43 | namespace protobuf { | 
| 44 | namespace compiler { | 
| 45 | namespace cpp { | 
| 46 |  | 
| 47 | using internal::WireFormatLite; | 
| 48 |  | 
| 49 | namespace { | 
| 50 |  | 
| 51 | // For encodings with fixed sizes, returns that size in bytes.  Otherwise | 
| 52 | // returns -1. | 
| 53 | int FixedSize(FieldDescriptor::Type type) { | 
| 54 |   switch (type) { | 
| 55 |     case FieldDescriptor::TYPE_INT32: | 
| 56 |       return -1; | 
| 57 |     case FieldDescriptor::TYPE_INT64: | 
| 58 |       return -1; | 
| 59 |     case FieldDescriptor::TYPE_UINT32: | 
| 60 |       return -1; | 
| 61 |     case FieldDescriptor::TYPE_UINT64: | 
| 62 |       return -1; | 
| 63 |     case FieldDescriptor::TYPE_SINT32: | 
| 64 |       return -1; | 
| 65 |     case FieldDescriptor::TYPE_SINT64: | 
| 66 |       return -1; | 
| 67 |     case FieldDescriptor::TYPE_FIXED32: | 
| 68 |       return WireFormatLite::kFixed32Size; | 
| 69 |     case FieldDescriptor::TYPE_FIXED64: | 
| 70 |       return WireFormatLite::kFixed64Size; | 
| 71 |     case FieldDescriptor::TYPE_SFIXED32: | 
| 72 |       return WireFormatLite::kSFixed32Size; | 
| 73 |     case FieldDescriptor::TYPE_SFIXED64: | 
| 74 |       return WireFormatLite::kSFixed64Size; | 
| 75 |     case FieldDescriptor::TYPE_FLOAT: | 
| 76 |       return WireFormatLite::kFloatSize; | 
| 77 |     case FieldDescriptor::TYPE_DOUBLE: | 
| 78 |       return WireFormatLite::kDoubleSize; | 
| 79 |  | 
| 80 |     case FieldDescriptor::TYPE_BOOL: | 
| 81 |       return WireFormatLite::kBoolSize; | 
| 82 |     case FieldDescriptor::TYPE_ENUM: | 
| 83 |       return -1; | 
| 84 |  | 
| 85 |     case FieldDescriptor::TYPE_STRING: | 
| 86 |       return -1; | 
| 87 |     case FieldDescriptor::TYPE_BYTES: | 
| 88 |       return -1; | 
| 89 |     case FieldDescriptor::TYPE_GROUP: | 
| 90 |       return -1; | 
| 91 |     case FieldDescriptor::TYPE_MESSAGE: | 
| 92 |       return -1; | 
| 93 |  | 
| 94 |       // No default because we want the compiler to complain if any new | 
| 95 |       // types are added. | 
| 96 |   } | 
| 97 |   GOOGLE_LOG(FATAL) << "Can't get here." ; | 
| 98 |   return -1; | 
| 99 | } | 
| 100 |  | 
| 101 | void SetPrimitiveVariables(const FieldDescriptor* descriptor, | 
| 102 |                            std::map<std::string, std::string>* variables, | 
| 103 |                            const Options& options) { | 
| 104 |   SetCommonFieldVariables(descriptor, variables, options); | 
| 105 |   (*variables)["type" ] = PrimitiveTypeName(options, type: descriptor->cpp_type()); | 
| 106 |   (*variables)["default" ] = DefaultValue(options, field: descriptor); | 
| 107 |   (*variables)["cached_byte_size_name" ] = MakeVarintCachedSizeName(field: descriptor); | 
| 108 |   bool cold = ShouldSplit(field: descriptor, options); | 
| 109 |   (*variables)["cached_byte_size_field" ] = | 
| 110 |       MakeVarintCachedSizeFieldName(field: descriptor, split: cold); | 
| 111 |   (*variables)["tag" ] = StrCat(a: internal::WireFormat::MakeTag(field: descriptor)); | 
| 112 |   int fixed_size = FixedSize(type: descriptor->type()); | 
| 113 |   if (fixed_size != -1) { | 
| 114 |     (*variables)["fixed_size" ] = StrCat(a: fixed_size); | 
| 115 |   } | 
| 116 |   (*variables)["wire_format_field_type" ] = FieldDescriptorProto_Type_Name( | 
| 117 |       enum_t_value: static_cast<FieldDescriptorProto_Type>(descriptor->type())); | 
| 118 |   (*variables)["full_name" ] = descriptor->full_name(); | 
| 119 | } | 
| 120 |  | 
| 121 | }  // namespace | 
| 122 |  | 
| 123 | // =================================================================== | 
| 124 |  | 
| 125 | PrimitiveFieldGenerator::PrimitiveFieldGenerator( | 
| 126 |     const FieldDescriptor* descriptor, const Options& options) | 
| 127 |     : FieldGenerator(descriptor, options) { | 
| 128 |   SetPrimitiveVariables(descriptor, variables: &variables_, options); | 
| 129 | } | 
| 130 |  | 
| 131 | PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} | 
| 132 |  | 
| 133 | void PrimitiveFieldGenerator::GeneratePrivateMembers( | 
| 134 |     io::Printer* printer) const { | 
| 135 |   Formatter format(printer, variables_); | 
| 136 |   format("$type$ $name$_;\n" ); | 
| 137 | } | 
| 138 |  | 
| 139 | void PrimitiveFieldGenerator::GenerateAccessorDeclarations( | 
| 140 |     io::Printer* printer) const { | 
| 141 |   Formatter format(printer, variables_); | 
| 142 |   format( | 
| 143 |       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"  | 
| 144 |       "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"  | 
| 145 |       "private:\n"  | 
| 146 |       "$type$ ${1$_internal_$name$$}$() const;\n"  | 
| 147 |       "void ${1$_internal_set_$name$$}$($type$ value);\n"  | 
| 148 |       "public:\n" , | 
| 149 |       descriptor_); | 
| 150 | } | 
| 151 |  | 
| 152 | void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions( | 
| 153 |     io::Printer* printer) const { | 
| 154 |   Formatter format(printer, variables_); | 
| 155 |   format( | 
| 156 |       "inline $type$ $classname$::_internal_$name$() const {\n"  | 
| 157 |       "  return $field$;\n"  | 
| 158 |       "}\n"  | 
| 159 |       "inline $type$ $classname$::$name$() const {\n"  | 
| 160 |       "$annotate_get$"  | 
| 161 |       "  // @@protoc_insertion_point(field_get:$full_name$)\n"  | 
| 162 |       "  return _internal_$name$();\n"  | 
| 163 |       "}\n"  | 
| 164 |       "inline void $classname$::_internal_set_$name$($type$ value) {\n"  | 
| 165 |       "  $set_hasbit$\n"  | 
| 166 |       "  $field$ = value;\n"  | 
| 167 |       "}\n"  | 
| 168 |       "inline void $classname$::set_$name$($type$ value) {\n"  | 
| 169 |       "$maybe_prepare_split_message$"  | 
| 170 |       "  _internal_set_$name$(value);\n"  | 
| 171 |       "$annotate_set$"  | 
| 172 |       "  // @@protoc_insertion_point(field_set:$full_name$)\n"  | 
| 173 |       "}\n" ); | 
| 174 | } | 
| 175 |  | 
| 176 | void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const { | 
| 177 |   Formatter format(printer, variables_); | 
| 178 |   format("$field$ = $default$;\n" ); | 
| 179 | } | 
| 180 |  | 
| 181 | void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const { | 
| 182 |   Formatter format(printer, variables_); | 
| 183 |   format("_this->_internal_set_$name$(from._internal_$name$());\n" ); | 
| 184 | } | 
| 185 |  | 
| 186 | void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { | 
| 187 |   Formatter format(printer, variables_); | 
| 188 |   format("swap($field$, other->$field$);\n" ); | 
| 189 | } | 
| 190 |  | 
| 191 | void PrimitiveFieldGenerator::GenerateCopyConstructorCode( | 
| 192 |     io::Printer* printer) const { | 
| 193 |   Formatter format(printer, variables_); | 
| 194 |   format("_this->$field$ = from.$field$;\n" ); | 
| 195 | } | 
| 196 |  | 
| 197 | void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray( | 
| 198 |     io::Printer* printer) const { | 
| 199 |   Formatter format(printer, variables_); | 
| 200 |   format( | 
| 201 |       "target = stream->EnsureSpace(target);\n"  | 
| 202 |       "target = "  | 
| 203 |       "::_pbi::WireFormatLite::Write$declared_type$ToArray("  | 
| 204 |       "$number$, this->_internal_$name$(), target);\n" ); | 
| 205 | } | 
| 206 |  | 
| 207 | void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const { | 
| 208 |   Formatter format(printer, variables_); | 
| 209 |   int fixed_size = FixedSize(type: descriptor_->type()); | 
| 210 |   if (fixed_size == -1) { | 
| 211 |     if (internal::WireFormat::TagSize(field_number: descriptor_->number(), | 
| 212 |                                       type: descriptor_->type()) == 1) { | 
| 213 |       // Adding one is very common and it turns out it can be done for | 
| 214 |       // free inside of WireFormatLite, so we can save an instruction here. | 
| 215 |       format( | 
| 216 |           "total_size += ::_pbi::WireFormatLite::"  | 
| 217 |           "$declared_type$SizePlusOne(this->_internal_$name$());\n" ); | 
| 218 |     } else { | 
| 219 |       format( | 
| 220 |           "total_size += $tag_size$ +\n"  | 
| 221 |           "  ::_pbi::WireFormatLite::$declared_type$Size(\n"  | 
| 222 |           "    this->_internal_$name$());\n" ); | 
| 223 |     } | 
| 224 |   } else { | 
| 225 |     format("total_size += $tag_size$ + $fixed_size$;\n" ); | 
| 226 |   } | 
| 227 | } | 
| 228 |  | 
| 229 | void PrimitiveFieldGenerator::GenerateConstexprAggregateInitializer( | 
| 230 |     io::Printer* printer) const { | 
| 231 |   Formatter format(printer, variables_); | 
| 232 |   format("/*decltype($field$)*/$default$" ); | 
| 233 | } | 
| 234 |  | 
| 235 | void PrimitiveFieldGenerator::GenerateAggregateInitializer( | 
| 236 |     io::Printer* printer) const { | 
| 237 |   Formatter format(printer, variables_); | 
| 238 |   if (ShouldSplit(field: descriptor_, options: options_)) { | 
| 239 |     format("decltype(Impl_::Split::$name$_){$default$}" ); | 
| 240 |     return; | 
| 241 |   } | 
| 242 |   format("decltype($field$){$default$}" ); | 
| 243 | } | 
| 244 |  | 
| 245 | void PrimitiveFieldGenerator::GenerateCopyAggregateInitializer( | 
| 246 |     io::Printer* printer) const { | 
| 247 |   Formatter format(printer, variables_); | 
| 248 |   format("decltype($field$){}" ); | 
| 249 | } | 
| 250 |  | 
| 251 | // =================================================================== | 
| 252 |  | 
| 253 | PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( | 
| 254 |     const FieldDescriptor* descriptor, const Options& options) | 
| 255 |     : PrimitiveFieldGenerator(descriptor, options) { | 
| 256 |   SetCommonOneofFieldVariables(descriptor, variables: &variables_); | 
| 257 | } | 
| 258 |  | 
| 259 | PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} | 
| 260 |  | 
| 261 | void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions( | 
| 262 |     io::Printer* printer) const { | 
| 263 |   Formatter format(printer, variables_); | 
| 264 |   format( | 
| 265 |       "inline $type$ $classname$::_internal_$name$() const {\n"  | 
| 266 |       "  if (_internal_has_$name$()) {\n"  | 
| 267 |       "    return $field$;\n"  | 
| 268 |       "  }\n"  | 
| 269 |       "  return $default$;\n"  | 
| 270 |       "}\n"  | 
| 271 |       "inline void $classname$::_internal_set_$name$($type$ value) {\n"  | 
| 272 |       "  if (!_internal_has_$name$()) {\n"  | 
| 273 |       "    clear_$oneof_name$();\n"  | 
| 274 |       "    set_has_$name$();\n"  | 
| 275 |       "  }\n"  | 
| 276 |       "  $field$ = value;\n"  | 
| 277 |       "}\n"  | 
| 278 |       "inline $type$ $classname$::$name$() const {\n"  | 
| 279 |       "$annotate_get$"  | 
| 280 |       "  // @@protoc_insertion_point(field_get:$full_name$)\n"  | 
| 281 |       "  return _internal_$name$();\n"  | 
| 282 |       "}\n"  | 
| 283 |       "inline void $classname$::set_$name$($type$ value) {\n"  | 
| 284 |       "  _internal_set_$name$(value);\n"  | 
| 285 |       "$annotate_set$"  | 
| 286 |       "  // @@protoc_insertion_point(field_set:$full_name$)\n"  | 
| 287 |       "}\n" ); | 
| 288 | } | 
| 289 |  | 
| 290 | void PrimitiveOneofFieldGenerator::GenerateClearingCode( | 
| 291 |     io::Printer* printer) const { | 
| 292 |   Formatter format(printer, variables_); | 
| 293 |   format("$field$ = $default$;\n" ); | 
| 294 | } | 
| 295 |  | 
| 296 | void PrimitiveOneofFieldGenerator::GenerateSwappingCode( | 
| 297 |     io::Printer* printer) const { | 
| 298 |   // Don't print any swapping code. Swapping the union will swap this field. | 
| 299 | } | 
| 300 |  | 
| 301 | void PrimitiveOneofFieldGenerator::GenerateConstructorCode( | 
| 302 |     io::Printer* printer) const { | 
| 303 |   Formatter format(printer, variables_); | 
| 304 |   format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n" ); | 
| 305 | } | 
| 306 |  | 
| 307 | // =================================================================== | 
| 308 |  | 
| 309 | RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( | 
| 310 |     const FieldDescriptor* descriptor, const Options& options) | 
| 311 |     : FieldGenerator(descriptor, options) { | 
| 312 |   SetPrimitiveVariables(descriptor, variables: &variables_, options); | 
| 313 |  | 
| 314 |   if (descriptor->is_packed()) { | 
| 315 |     variables_["packed_reader" ] = "ReadPackedPrimitive" ; | 
| 316 |     variables_["repeated_reader" ] = "ReadRepeatedPrimitiveNoInline" ; | 
| 317 |   } else { | 
| 318 |     variables_["packed_reader" ] = "ReadPackedPrimitiveNoInline" ; | 
| 319 |     variables_["repeated_reader" ] = "ReadRepeatedPrimitive" ; | 
| 320 |   } | 
| 321 | } | 
| 322 |  | 
| 323 | RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} | 
| 324 |  | 
| 325 | void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers( | 
| 326 |     io::Printer* printer) const { | 
| 327 |   Formatter format(printer, variables_); | 
| 328 |   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n" ); | 
| 329 |   if (descriptor_->is_packed() && FixedSize(type: descriptor_->type()) == -1 && | 
| 330 |       HasGeneratedMethods(file: descriptor_->file(), options: options_)) { | 
| 331 |     format("mutable std::atomic<int> $cached_byte_size_name$;\n" ); | 
| 332 |   } | 
| 333 | } | 
| 334 |  | 
| 335 | void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations( | 
| 336 |     io::Printer* printer) const { | 
| 337 |   Formatter format(printer, variables_); | 
| 338 |   format( | 
| 339 |       "private:\n"  | 
| 340 |       "$type$ ${1$_internal_$name$$}$(int index) const;\n"  | 
| 341 |       "const ::$proto_ns$::RepeatedField< $type$ >&\n"  | 
| 342 |       "    ${1$_internal_$name$$}$() const;\n"  | 
| 343 |       "void ${1$_internal_add_$name$$}$($type$ value);\n"  | 
| 344 |       "::$proto_ns$::RepeatedField< $type$ >*\n"  | 
| 345 |       "    ${1$_internal_mutable_$name$$}$();\n"  | 
| 346 |       "public:\n"  | 
| 347 |       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"  | 
| 348 |       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"  | 
| 349 |       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"  | 
| 350 |       "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"  | 
| 351 |       "    ${1$$name$$}$() const;\n"  | 
| 352 |       "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"  | 
| 353 |       "    ${1$mutable_$name$$}$();\n" , | 
| 354 |       descriptor_); | 
| 355 | } | 
| 356 |  | 
| 357 | void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions( | 
| 358 |     io::Printer* printer) const { | 
| 359 |   Formatter format(printer, variables_); | 
| 360 |   format( | 
| 361 |       "inline $type$ $classname$::_internal_$name$(int index) const {\n"  | 
| 362 |       "  return $field$.Get(index);\n"  | 
| 363 |       "}\n"  | 
| 364 |       "inline $type$ $classname$::$name$(int index) const {\n"  | 
| 365 |       "$annotate_get$"  | 
| 366 |       "  // @@protoc_insertion_point(field_get:$full_name$)\n"  | 
| 367 |       "  return _internal_$name$(index);\n"  | 
| 368 |       "}\n"  | 
| 369 |       "inline void $classname$::set_$name$(int index, $type$ value) {\n"  | 
| 370 |       "$annotate_set$"  | 
| 371 |       "  $field$.Set(index, value);\n"  | 
| 372 |       "  // @@protoc_insertion_point(field_set:$full_name$)\n"  | 
| 373 |       "}\n"  | 
| 374 |       "inline void $classname$::_internal_add_$name$($type$ value) {\n"  | 
| 375 |       "  $field$.Add(value);\n"  | 
| 376 |       "}\n"  | 
| 377 |       "inline void $classname$::add_$name$($type$ value) {\n"  | 
| 378 |       "  _internal_add_$name$(value);\n"  | 
| 379 |       "$annotate_add$"  | 
| 380 |       "  // @@protoc_insertion_point(field_add:$full_name$)\n"  | 
| 381 |       "}\n"  | 
| 382 |       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"  | 
| 383 |       "$classname$::_internal_$name$() const {\n"  | 
| 384 |       "  return $field$;\n"  | 
| 385 |       "}\n"  | 
| 386 |       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"  | 
| 387 |       "$classname$::$name$() const {\n"  | 
| 388 |       "$annotate_list$"  | 
| 389 |       "  // @@protoc_insertion_point(field_list:$full_name$)\n"  | 
| 390 |       "  return _internal_$name$();\n"  | 
| 391 |       "}\n"  | 
| 392 |       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"  | 
| 393 |       "$classname$::_internal_mutable_$name$() {\n"  | 
| 394 |       "  return &$field$;\n"  | 
| 395 |       "}\n"  | 
| 396 |       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"  | 
| 397 |       "$classname$::mutable_$name$() {\n"  | 
| 398 |       "$annotate_mutable_list$"  | 
| 399 |       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"  | 
| 400 |       "  return _internal_mutable_$name$();\n"  | 
| 401 |       "}\n" ); | 
| 402 | } | 
| 403 |  | 
| 404 | void RepeatedPrimitiveFieldGenerator::GenerateClearingCode( | 
| 405 |     io::Printer* printer) const { | 
| 406 |   Formatter format(printer, variables_); | 
| 407 |   format("$field$.Clear();\n" ); | 
| 408 | } | 
| 409 |  | 
| 410 | void RepeatedPrimitiveFieldGenerator::GenerateMergingCode( | 
| 411 |     io::Printer* printer) const { | 
| 412 |   Formatter format(printer, variables_); | 
| 413 |   format("_this->$field$.MergeFrom(from.$field$);\n" ); | 
| 414 | } | 
| 415 |  | 
| 416 | void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode( | 
| 417 |     io::Printer* printer) const { | 
| 418 |   Formatter format(printer, variables_); | 
| 419 |   format("$field$.InternalSwap(&other->$field$);\n" ); | 
| 420 | } | 
| 421 |  | 
| 422 | void RepeatedPrimitiveFieldGenerator::GenerateDestructorCode( | 
| 423 |     io::Printer* printer) const { | 
| 424 |   Formatter format(printer, variables_); | 
| 425 |   format("$field$.~RepeatedField();\n" ); | 
| 426 | } | 
| 427 |  | 
| 428 | void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray( | 
| 429 |     io::Printer* printer) const { | 
| 430 |   Formatter format(printer, variables_); | 
| 431 |   if (descriptor_->is_packed()) { | 
| 432 |     if (FixedSize(type: descriptor_->type()) == -1) { | 
| 433 |       format( | 
| 434 |           "{\n"  | 
| 435 |           "  int byte_size = "  | 
| 436 |           "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"  | 
| 437 |           "  if (byte_size > 0) {\n"  | 
| 438 |           "    target = stream->Write$declared_type$Packed(\n"  | 
| 439 |           "        $number$, _internal_$name$(), byte_size, target);\n"  | 
| 440 |           "  }\n"  | 
| 441 |           "}\n" ); | 
| 442 |     } else { | 
| 443 |       format( | 
| 444 |           "if (this->_internal_$name$_size() > 0) {\n"  | 
| 445 |           "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "  | 
| 446 |           "target);\n"  | 
| 447 |           "}\n" ); | 
| 448 |     } | 
| 449 |   } else { | 
| 450 |     format( | 
| 451 |         "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"  | 
| 452 |         "  target = stream->EnsureSpace(target);\n"  | 
| 453 |         "  target = ::_pbi::WireFormatLite::"  | 
| 454 |         "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "  | 
| 455 |         "target);\n"  | 
| 456 |         "}\n" ); | 
| 457 |   } | 
| 458 | } | 
| 459 |  | 
| 460 | void RepeatedPrimitiveFieldGenerator::GenerateByteSize( | 
| 461 |     io::Printer* printer) const { | 
| 462 |   Formatter format(printer, variables_); | 
| 463 |   format("{\n" ); | 
| 464 |   format.Indent(); | 
| 465 |   int fixed_size = FixedSize(type: descriptor_->type()); | 
| 466 |   if (fixed_size == -1) { | 
| 467 |     format( | 
| 468 |         "size_t data_size = ::_pbi::WireFormatLite::\n"  | 
| 469 |         "  $declared_type$Size(this->$field$);\n" ); | 
| 470 |   } else { | 
| 471 |     format( | 
| 472 |         "unsigned int count = static_cast<unsigned "  | 
| 473 |         "int>(this->_internal_$name$_size());\n"  | 
| 474 |         "size_t data_size = $fixed_size$UL * count;\n" ); | 
| 475 |   } | 
| 476 |  | 
| 477 |   if (descriptor_->is_packed()) { | 
| 478 |     format( | 
| 479 |         "if (data_size > 0) {\n"  | 
| 480 |         "  total_size += $tag_size$ +\n"  | 
| 481 |         "    "  | 
| 482 |         "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"  | 
| 483 |         "}\n" ); | 
| 484 |     if (FixedSize(type: descriptor_->type()) == -1) { | 
| 485 |       format( | 
| 486 |           "int cached_size = ::_pbi::ToCachedSize(data_size);\n"  | 
| 487 |           "$cached_byte_size_field$.store(cached_size,\n"  | 
| 488 |           "                                std::memory_order_relaxed);\n" ); | 
| 489 |     } | 
| 490 |     format("total_size += data_size;\n" ); | 
| 491 |   } else { | 
| 492 |     format( | 
| 493 |         "total_size += $tag_size$ *\n"  | 
| 494 |         "              "  | 
| 495 |         "::_pbi::FromIntSize(this->_internal_$name$_size());\n"  | 
| 496 |         "total_size += data_size;\n" ); | 
| 497 |   } | 
| 498 |   format.Outdent(); | 
| 499 |   format("}\n" ); | 
| 500 | } | 
| 501 |  | 
| 502 | void RepeatedPrimitiveFieldGenerator::GenerateConstexprAggregateInitializer( | 
| 503 |     io::Printer* printer) const { | 
| 504 |   Formatter format(printer, variables_); | 
| 505 |   format("/*decltype($field$)*/{}" ); | 
| 506 |   if (descriptor_->is_packed() && FixedSize(type: descriptor_->type()) == -1 && | 
| 507 |       HasGeneratedMethods(file: descriptor_->file(), options: options_)) { | 
| 508 |     format("\n, /*decltype($cached_byte_size_field$)*/{0}" ); | 
| 509 |   } | 
| 510 | } | 
| 511 |  | 
| 512 | void RepeatedPrimitiveFieldGenerator::GenerateAggregateInitializer( | 
| 513 |     io::Printer* printer) const { | 
| 514 |   Formatter format(printer, variables_); | 
| 515 |   format("decltype($field$){arena}" ); | 
| 516 |   if (descriptor_->is_packed() && FixedSize(type: descriptor_->type()) == -1 && | 
| 517 |       HasGeneratedMethods(file: descriptor_->file(), options: options_)) { | 
| 518 |     // std::atomic has no move constructor, which prevents explicit aggregate | 
| 519 |     // initialization pre-C++17. | 
| 520 |     format("\n, /*decltype($cached_byte_size_field$)*/{0}" ); | 
| 521 |   } | 
| 522 | } | 
| 523 |  | 
| 524 | void RepeatedPrimitiveFieldGenerator::GenerateCopyAggregateInitializer( | 
| 525 |     io::Printer* printer) const { | 
| 526 |  | 
| 527 |   Formatter format(printer, variables_); | 
| 528 |   format("decltype($field$){from.$field$}" ); | 
| 529 |   if (descriptor_->is_packed() && FixedSize(type: descriptor_->type()) == -1 && | 
| 530 |       HasGeneratedMethods(file: descriptor_->file(), options: options_)) { | 
| 531 |     // std::atomic has no move constructor. | 
| 532 |     format("\n, /*decltype($cached_byte_size_field$)*/{0}" ); | 
| 533 |   } | 
| 534 | } | 
| 535 |  | 
| 536 | }  // namespace cpp | 
| 537 | }  // namespace compiler | 
| 538 | }  // namespace protobuf | 
| 539 | }  // namespace google | 
| 540 |  |