| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 | 78 |
| 79 struct FieldOrderingByNumber { | 79 struct FieldOrderingByNumber { |
| 80 inline bool operator()(const FieldDescriptor* a, | 80 inline bool operator()(const FieldDescriptor* a, |
| 81 const FieldDescriptor* b) const { | 81 const FieldDescriptor* b) const { |
| 82 return a->number() < b->number(); | 82 return a->number() < b->number(); |
| 83 } | 83 } |
| 84 }; | 84 }; |
| 85 | 85 |
| 86 // Sort the fields of the given Descriptor by number into a new[]'d array | 86 // Sort the fields of the given Descriptor by number into a new[]'d array |
| 87 // and return it. | 87 // and return it. |
| 88 std::vector<const FieldDescriptor*> SortFieldsByNumber( | 88 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { |
| 89 const Descriptor* descriptor) { | 89 const FieldDescriptor** fields = |
| 90 std::vector<const FieldDescriptor*> fields(descriptor->field_count()); | 90 new const FieldDescriptor*[descriptor->field_count()]; |
| 91 for (int i = 0; i < descriptor->field_count(); i++) { | 91 for (int i = 0; i < descriptor->field_count(); i++) { |
| 92 fields[i] = descriptor->field(i); | 92 fields[i] = descriptor->field(i); |
| 93 } | 93 } |
| 94 std::sort(fields.begin(), fields.end(), FieldOrderingByNumber()); | 94 std::sort(fields, fields + descriptor->field_count(), |
| 95 FieldOrderingByNumber()); |
| 95 return fields; | 96 return fields; |
| 96 } | 97 } |
| 97 | 98 |
| 98 // Functor for sorting extension ranges by their "start" field number. | 99 // Functor for sorting extension ranges by their "start" field number. |
| 99 struct ExtensionRangeSorter { | 100 struct ExtensionRangeSorter { |
| 100 bool operator()(const Descriptor::ExtensionRange* left, | 101 bool operator()(const Descriptor::ExtensionRange* left, |
| 101 const Descriptor::ExtensionRange* right) const { | 102 const Descriptor::ExtensionRange* right) const { |
| 102 return left->start < right->start; | 103 return left->start < right->start; |
| 103 } | 104 } |
| 104 }; | 105 }; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 // Preferred location is the average among all the fields, so we weight by | 201 // Preferred location is the average among all the fields, so we weight by |
| 201 // the number of fields on each FieldGroup object. | 202 // the number of fields on each FieldGroup object. |
| 202 preferred_location_ = | 203 preferred_location_ = |
| 203 (preferred_location_ * fields_.size() + | 204 (preferred_location_ * fields_.size() + |
| 204 (other.preferred_location_ * other.fields_.size())) / | 205 (other.preferred_location_ * other.fields_.size())) / |
| 205 (fields_.size() + other.fields_.size()); | 206 (fields_.size() + other.fields_.size()); |
| 206 fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); | 207 fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); |
| 207 } | 208 } |
| 208 | 209 |
| 209 void SetPreferredLocation(float location) { preferred_location_ = location; } | 210 void SetPreferredLocation(float location) { preferred_location_ = location; } |
| 210 const std::vector<const FieldDescriptor*>& fields() const { return fields_; } | 211 const vector<const FieldDescriptor*>& fields() const { return fields_; } |
| 211 | 212 |
| 212 // FieldGroup objects sort by their preferred location. | 213 // FieldGroup objects sort by their preferred location. |
| 213 bool operator<(const FieldGroup& other) const { | 214 bool operator<(const FieldGroup& other) const { |
| 214 return preferred_location_ < other.preferred_location_; | 215 return preferred_location_ < other.preferred_location_; |
| 215 } | 216 } |
| 216 | 217 |
| 217 private: | 218 private: |
| 218 // "preferred_location_" is an estimate of where this group should go in the | 219 // "preferred_location_" is an estimate of where this group should go in the |
| 219 // final list of fields. We compute this by taking the average index of each | 220 // final list of fields. We compute this by taking the average index of each |
| 220 // field in this group in the original ordering of fields. This is very | 221 // field in this group in the original ordering of fields. This is very |
| 221 // approximate, but should put this group close to where its member fields | 222 // approximate, but should put this group close to where its member fields |
| 222 // originally went. | 223 // originally went. |
| 223 float preferred_location_; | 224 float preferred_location_; |
| 224 std::vector<const FieldDescriptor*> fields_; | 225 vector<const FieldDescriptor*> fields_; |
| 225 // We rely on the default copy constructor and operator= so this type can be | 226 // We rely on the default copy constructor and operator= so this type can be |
| 226 // used in a vector. | 227 // used in a vector. |
| 227 }; | 228 }; |
| 228 | 229 |
| 229 // Helper for the code that emits the Clear() method. | |
| 230 bool CanInitializeByZeroing(const FieldDescriptor* field) { | |
| 231 if (field->is_repeated() || field->is_extension()) return false; | |
| 232 switch (field->cpp_type()) { | |
| 233 case internal::WireFormatLite::CPPTYPE_ENUM: | |
| 234 return field->default_value_enum()->number() == 0; | |
| 235 case internal::WireFormatLite::CPPTYPE_INT32: | |
| 236 return field->default_value_int32() == 0; | |
| 237 case internal::WireFormatLite::CPPTYPE_INT64: | |
| 238 return field->default_value_int64() == 0; | |
| 239 case internal::WireFormatLite::CPPTYPE_UINT32: | |
| 240 return field->default_value_uint32() == 0; | |
| 241 case internal::WireFormatLite::CPPTYPE_UINT64: | |
| 242 return field->default_value_uint64() == 0; | |
| 243 case internal::WireFormatLite::CPPTYPE_FLOAT: | |
| 244 return field->default_value_float() == 0; | |
| 245 case internal::WireFormatLite::CPPTYPE_DOUBLE: | |
| 246 return field->default_value_double() == 0; | |
| 247 case internal::WireFormatLite::CPPTYPE_BOOL: | |
| 248 return field->default_value_bool() == false; | |
| 249 default: | |
| 250 return false; | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 bool IsPOD(const FieldDescriptor* field) { | |
| 255 if (field->is_repeated() || field->is_extension()) return false; | |
| 256 switch (field->cpp_type()) { | |
| 257 case internal::WireFormatLite::CPPTYPE_ENUM: | |
| 258 case internal::WireFormatLite::CPPTYPE_INT32: | |
| 259 case internal::WireFormatLite::CPPTYPE_INT64: | |
| 260 case internal::WireFormatLite::CPPTYPE_UINT32: | |
| 261 case internal::WireFormatLite::CPPTYPE_UINT64: | |
| 262 case internal::WireFormatLite::CPPTYPE_FLOAT: | |
| 263 case internal::WireFormatLite::CPPTYPE_DOUBLE: | |
| 264 case internal::WireFormatLite::CPPTYPE_BOOL: | |
| 265 return true; | |
| 266 case internal::WireFormatLite::CPPTYPE_STRING: | |
| 267 return false; | |
| 268 default: | |
| 269 return false; | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 // Helper for the code that emits the SharedCtor() method. | |
| 274 bool CanConstructByZeroing(const FieldDescriptor* field, | |
| 275 const Options& options) { | |
| 276 bool ret = CanInitializeByZeroing(field); | |
| 277 | |
| 278 // Non-repeated, non-lazy message fields are simply raw pointers, so we can | |
| 279 // use memset to initialize these in SharedCtor. We cannot use this in | |
| 280 // Clear, as we need to potentially delete the existing value. | |
| 281 ret = ret || | |
| 282 (!field->is_repeated() && | |
| 283 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); | |
| 284 return ret; | |
| 285 } | |
| 286 | |
| 287 // Reorder 'fields' so that if the fields are output into a c++ class in the new | 230 // Reorder 'fields' so that if the fields are output into a c++ class in the new |
| 288 // order, fields of similiar family (see below) are together and within each | 231 // order, the alignment padding is minimized. We try to do this while keeping |
| 289 // family, alignment padding is minimized. | 232 // each field as close as possible to its original position so that we don't |
| 290 // | 233 // reduce cache locality much for function that access each field in order. |
| 291 // We try to do this while keeping each field as close as possible to its | 234 void OptimizePadding(vector<const FieldDescriptor*>* fields) { |
| 292 // declaration order (from the .proto file) so that we don't reduce cache | |
| 293 // locality much for function that access each field in order. This is also the | |
| 294 // only (weak) signal we have for author intent concerning field layout. | |
| 295 // | |
| 296 // TODO(ckennelly): If/when we have profiles available for the compiler, use | |
| 297 // those rather than respect declaration order. | |
| 298 // | |
| 299 // We classify each field into a particular "family" of fields, that we perform | |
| 300 // the same operation on in our generated functions. | |
| 301 // | |
| 302 // REPEATED is placed first, as the C++ compiler automatically initializes | |
| 303 // these fields in layout order. | |
| 304 // | |
| 305 // STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and | |
| 306 // calls ArenaStringPtr::Destroy on each. | |
| 307 // | |
| 308 // | |
| 309 // MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls | |
| 310 // delete on each. We initialize these fields with a NULL pointer (see | |
| 311 // MessageFieldGenerator::GenerateConstructorCode), which allows them to be | |
| 312 // memset. | |
| 313 // | |
| 314 // ZERO_INITIALIZABLE is memset in Clear/SharedCtor | |
| 315 // | |
| 316 // OTHER these fields are initialized one-by-one. | |
| 317 void OptimizePadding(std::vector<const FieldDescriptor*>* fields, | |
| 318 const Options& options) { | |
| 319 // The sorted numeric order of Family determines the declaration order in the | |
| 320 // memory layout. | |
| 321 enum Family { | |
| 322 REPEATED = 0, | |
| 323 STRING = 1, | |
| 324 MESSAGE = 2, | |
| 325 ZERO_INITIALIZABLE = 4, | |
| 326 OTHER = 5, | |
| 327 kMaxFamily | |
| 328 }; | |
| 329 | |
| 330 // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. | 235 // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. |
| 331 std::vector<FieldGroup> aligned_to_1[kMaxFamily]; | 236 vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8; |
| 332 std::vector<FieldGroup> aligned_to_4[kMaxFamily]; | |
| 333 std::vector<FieldGroup> aligned_to_8[kMaxFamily]; | |
| 334 for (int i = 0; i < fields->size(); ++i) { | 237 for (int i = 0; i < fields->size(); ++i) { |
| 335 const FieldDescriptor* field = (*fields)[i]; | 238 switch (EstimateAlignmentSize((*fields)[i])) { |
| 336 | 239 case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break; |
| 337 Family f = OTHER; | 240 case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break; |
| 338 if (field->is_repeated()) { | 241 case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break; |
| 339 f = REPEATED; | |
| 340 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { | |
| 341 f = STRING; | |
| 342 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | |
| 343 f = MESSAGE; | |
| 344 | |
| 345 } else if (CanInitializeByZeroing(field)) { | |
| 346 f = ZERO_INITIALIZABLE; | |
| 347 } | |
| 348 | |
| 349 switch (EstimateAlignmentSize(field)) { | |
| 350 case 1: aligned_to_1[f].push_back(FieldGroup(i, field)); break; | |
| 351 case 4: aligned_to_4[f].push_back(FieldGroup(i, field)); break; | |
| 352 case 8: aligned_to_8[f].push_back(FieldGroup(i, field)); break; | |
| 353 default: | 242 default: |
| 354 GOOGLE_LOG(FATAL) << "Unknown alignment size."; | 243 GOOGLE_LOG(FATAL) << "Unknown alignment size."; |
| 355 } | 244 } |
| 356 } | 245 } |
| 357 | 246 |
| 358 // For each family, group fields to optimize padding. | 247 // Now group fields aligned to 1 byte into sets of 4, and treat those like a |
| 359 for (int f = 0; f < kMaxFamily; f++) { | 248 // single field aligned to 4 bytes. |
| 360 // Now group fields aligned to 1 byte into sets of 4, and treat those like a | 249 for (int i = 0; i < aligned_to_1.size(); i += 4) { |
| 361 // single field aligned to 4 bytes. | 250 FieldGroup field_group; |
| 362 for (int i = 0; i < aligned_to_1[f].size(); i += 4) { | 251 for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) { |
| 363 FieldGroup field_group; | 252 field_group.Append(aligned_to_1[j]); |
| 364 for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) { | |
| 365 field_group.Append(aligned_to_1[f][j]); | |
| 366 } | |
| 367 aligned_to_4[f].push_back(field_group); | |
| 368 } | 253 } |
| 369 // Sort by preferred location to keep fields as close to their declaration | 254 aligned_to_4.push_back(field_group); |
| 370 // order as possible. Using stable_sort ensures that the output is | 255 } |
| 371 // consistent across runs. | 256 // Sort by preferred location to keep fields as close to their original |
| 372 std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end()); | 257 // location as possible. Using stable_sort ensures that the output is |
| 258 // consistent across runs. |
| 259 std::stable_sort(aligned_to_4.begin(), aligned_to_4.end()); |
| 373 | 260 |
| 374 // Now group fields aligned to 4 bytes (or the 4-field groups created above) | 261 // Now group fields aligned to 4 bytes (or the 4-field groups created above) |
| 375 // into pairs, and treat those like a single field aligned to 8 bytes. | 262 // into pairs, and treat those like a single field aligned to 8 bytes. |
| 376 for (int i = 0; i < aligned_to_4[f].size(); i += 2) { | 263 for (int i = 0; i < aligned_to_4.size(); i += 2) { |
| 377 FieldGroup field_group; | 264 FieldGroup field_group; |
| 378 for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) { | 265 for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) { |
| 379 field_group.Append(aligned_to_4[f][j]); | 266 field_group.Append(aligned_to_4[j]); |
| 380 } | |
| 381 if (i == aligned_to_4[f].size() - 1) { | |
| 382 if (f == OTHER) { | |
| 383 // Move incomplete 4-byte block to the beginning. This is done to | |
| 384 // pair with the (possible) leftover blocks from the | |
| 385 // ZERO_INITIALIZABLE family. | |
| 386 field_group.SetPreferredLocation(-1); | |
| 387 } else { | |
| 388 // Move incomplete 4-byte block to the end. | |
| 389 field_group.SetPreferredLocation(fields->size() + 1); | |
| 390 } | |
| 391 } | |
| 392 aligned_to_8[f].push_back(field_group); | |
| 393 } | 267 } |
| 394 // Sort by preferred location. | 268 if (i == aligned_to_4.size() - 1) { |
| 395 std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end()); | 269 // Move incomplete 4-byte block to the end. |
| 270 field_group.SetPreferredLocation(fields->size() + 1); |
| 271 } |
| 272 aligned_to_8.push_back(field_group); |
| 396 } | 273 } |
| 274 // Sort by preferred location. |
| 275 std::stable_sort(aligned_to_8.begin(), aligned_to_8.end()); |
| 397 | 276 |
| 398 // Now pull out all the FieldDescriptors in order. | 277 // Now pull out all the FieldDescriptors in order. |
| 399 fields->clear(); | 278 fields->clear(); |
| 400 for (int f = 0; f < kMaxFamily; ++f) { | 279 for (int i = 0; i < aligned_to_8.size(); ++i) { |
| 401 for (int i = 0; i < aligned_to_8[f].size(); ++i) { | 280 fields->insert(fields->end(), |
| 402 fields->insert(fields->end(), | 281 aligned_to_8[i].fields().begin(), |
| 403 aligned_to_8[f][i].fields().begin(), | 282 aligned_to_8[i].fields().end()); |
| 404 aligned_to_8[f][i].fields().end()); | |
| 405 } | |
| 406 } | 283 } |
| 407 } | 284 } |
| 408 | 285 |
| 409 string MessageTypeProtoName(const FieldDescriptor* field) { | 286 string MessageTypeProtoName(const FieldDescriptor* field) { |
| 410 return field->message_type()->full_name(); | 287 return field->message_type()->full_name(); |
| 411 } | 288 } |
| 412 | 289 |
| 413 // Emits an if-statement with a condition that evaluates to true if |field| is | 290 // Emits an if-statement with a condition that evaluates to true if |field| is |
| 414 // considered non-default (will be sent over the wire), for message types | 291 // considered non-default (will be sent over the wire), for message types |
| 415 // without true field presence. Should only be called if | 292 // without true field presence. Should only be called if |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 // In proto1/proto2, every field has a has_$name$() method. | 332 // In proto1/proto2, every field has a has_$name$() method. |
| 456 return true; | 333 return true; |
| 457 } | 334 } |
| 458 // For message types without true field presence, only fields with a message | 335 // For message types without true field presence, only fields with a message |
| 459 // type have a has_$name$() method. | 336 // type have a has_$name$() method. |
| 460 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; | 337 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; |
| 461 } | 338 } |
| 462 | 339 |
| 463 // Collects map entry message type information. | 340 // Collects map entry message type information. |
| 464 void CollectMapInfo(const Descriptor* descriptor, | 341 void CollectMapInfo(const Descriptor* descriptor, |
| 465 std::map<string, string>* variables) { | 342 map<string, string>* variables) { |
| 466 GOOGLE_CHECK(IsMapEntryMessage(descriptor)); | 343 GOOGLE_CHECK(IsMapEntryMessage(descriptor)); |
| 467 const FieldDescriptor* key = descriptor->FindFieldByName("key"); | 344 const FieldDescriptor* key = descriptor->FindFieldByName("key"); |
| 468 const FieldDescriptor* val = descriptor->FindFieldByName("value"); | 345 const FieldDescriptor* val = descriptor->FindFieldByName("value"); |
| 469 (*variables)["key"] = PrimitiveTypeName(key->cpp_type()); | 346 (*variables)["key"] = PrimitiveTypeName(key->cpp_type()); |
| 470 switch (val->cpp_type()) { | 347 switch (val->cpp_type()) { |
| 471 case FieldDescriptor::CPPTYPE_MESSAGE: | 348 case FieldDescriptor::CPPTYPE_MESSAGE: |
| 472 (*variables)["val"] = FieldMessageTypeName(val); | 349 (*variables)["val"] = FieldMessageTypeName(val); |
| 473 break; | 350 break; |
| 474 case FieldDescriptor::CPPTYPE_ENUM: | 351 case FieldDescriptor::CPPTYPE_ENUM: |
| 475 (*variables)["val"] = ClassName(val->enum_type(), true); | 352 (*variables)["val"] = ClassName(val->enum_type(), true); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 487 | 364 |
| 488 // Does the given field have a private (internal helper only) has_$name$() | 365 // Does the given field have a private (internal helper only) has_$name$() |
| 489 // method? | 366 // method? |
| 490 bool HasPrivateHasMethod(const FieldDescriptor* field) { | 367 bool HasPrivateHasMethod(const FieldDescriptor* field) { |
| 491 // Only for oneofs in message types with no field presence. has_$name$(), | 368 // Only for oneofs in message types with no field presence. has_$name$(), |
| 492 // based on the oneof case, is still useful internally for generated code. | 369 // based on the oneof case, is still useful internally for generated code. |
| 493 return (!HasFieldPresence(field->file()) && | 370 return (!HasFieldPresence(field->file()) && |
| 494 field->containing_oneof() != NULL); | 371 field->containing_oneof() != NULL); |
| 495 } | 372 } |
| 496 | 373 |
| 497 | |
| 498 } // anonymous namespace | 374 } // anonymous namespace |
| 499 | 375 |
| 500 // =================================================================== | 376 // =================================================================== |
| 501 | 377 |
| 502 MessageGenerator::MessageGenerator(const Descriptor* descriptor, | 378 MessageGenerator::MessageGenerator(const Descriptor* descriptor, |
| 503 const Options& options) | 379 const Options& options) |
| 504 : descriptor_(descriptor), | 380 : descriptor_(descriptor), |
| 505 classname_(ClassName(descriptor, false)), | 381 classname_(ClassName(descriptor, false)), |
| 506 options_(options), | 382 options_(options), |
| 507 field_generators_(descriptor, options), | 383 field_generators_(descriptor, options), |
| 508 nested_generators_(new google::protobuf::scoped_ptr< | 384 nested_generators_(new google::protobuf::scoped_ptr< |
| 509 MessageGenerator>[descriptor->nested_type_count()]), | 385 MessageGenerator>[descriptor->nested_type_count()]), |
| 510 enum_generators_( | 386 enum_generators_( |
| 511 new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_
count()]), | 387 new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_
count()]), |
| 512 extension_generators_(new google::protobuf::scoped_ptr< | 388 extension_generators_(new google::protobuf::scoped_ptr< |
| 513 ExtensionGenerator>[descriptor->extension_count()]), | 389 ExtensionGenerator>[descriptor->extension_count()]), |
| 514 use_dependent_base_(false) { | 390 use_dependent_base_(false) { |
| 515 | 391 |
| 516 // Compute optimized field order to be used for layout and initialization | |
| 517 // purposes. | |
| 518 for (int i = 0; i < descriptor_->field_count(); i++) { | |
| 519 if (!descriptor_->field(i)->containing_oneof()) { | |
| 520 optimized_order_.push_back(descriptor_->field(i)); | |
| 521 } | |
| 522 } | |
| 523 OptimizePadding(&optimized_order_, options_); | |
| 524 | |
| 525 if (HasFieldPresence(descriptor_->file())) { | |
| 526 int has_bit_index = 0; | |
| 527 has_bit_indices_.resize(descriptor_->field_count(), -1); | |
| 528 for (int i = 0; i < optimized_order_.size(); i++) { | |
| 529 const FieldDescriptor* field = optimized_order_[i]; | |
| 530 // Skip fields that do not have has bits. | |
| 531 if (field->is_repeated()) { | |
| 532 continue; | |
| 533 } | |
| 534 | |
| 535 has_bit_indices_[field->index()] = has_bit_index; | |
| 536 has_bit_index++; | |
| 537 } | |
| 538 | |
| 539 // Assign fields that do not use has bits to be at the end. This can be | |
| 540 // removed once we shrink the has bits we assign. | |
| 541 // | |
| 542 // TODO(ckennelly): Shrink the has bits for these fields. | |
| 543 for (int i = 0; i < descriptor_->field_count(); i++) { | |
| 544 const FieldDescriptor* field = descriptor_->field(i); | |
| 545 if (has_bit_indices_[field->index()] < 0) { | |
| 546 has_bit_indices_[field->index()] = has_bit_index++; | |
| 547 } | |
| 548 } | |
| 549 } | |
| 550 | |
| 551 for (int i = 0; i < descriptor->nested_type_count(); i++) { | 392 for (int i = 0; i < descriptor->nested_type_count(); i++) { |
| 552 nested_generators_[i].reset( | 393 nested_generators_[i].reset( |
| 553 new MessageGenerator(descriptor->nested_type(i), options)); | 394 new MessageGenerator(descriptor->nested_type(i), options)); |
| 554 } | 395 } |
| 555 | 396 |
| 556 for (int i = 0; i < descriptor->enum_type_count(); i++) { | 397 for (int i = 0; i < descriptor->enum_type_count(); i++) { |
| 557 enum_generators_[i].reset( | 398 enum_generators_[i].reset( |
| 558 new EnumGenerator(descriptor->enum_type(i), options)); | 399 new EnumGenerator(descriptor->enum_type(i), options)); |
| 559 } | 400 } |
| 560 | 401 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 573 } | 414 } |
| 574 } | 415 } |
| 575 if (options.proto_h && descriptor->oneof_decl_count() > 0) { | 416 if (options.proto_h && descriptor->oneof_decl_count() > 0) { |
| 576 // Always make oneofs dependent. | 417 // Always make oneofs dependent. |
| 577 use_dependent_base_ = true; | 418 use_dependent_base_ = true; |
| 578 } | 419 } |
| 579 } | 420 } |
| 580 | 421 |
| 581 MessageGenerator::~MessageGenerator() {} | 422 MessageGenerator::~MessageGenerator() {} |
| 582 | 423 |
| 583 size_t MessageGenerator::HasBitsSize() const { | 424 void MessageGenerator:: |
| 584 // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields. | 425 FillMessageForwardDeclarations(map<string, const Descriptor*>* class_names) { |
| 585 size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4; | 426 (*class_names)[classname_] = descriptor_; |
| 586 if (descriptor_->field_count() == 0) { | |
| 587 // Zero-size arrays aren't technically allowed, and MSVC in particular | |
| 588 // doesn't like them. We still need to declare these arrays to make | |
| 589 // other code compile. Since this is an uncommon case, we'll just declare | |
| 590 // them with size 1 and waste some space. Oh well. | |
| 591 sizeof_has_bits = 4; | |
| 592 } | |
| 593 | 427 |
| 594 return sizeof_has_bits; | |
| 595 } | |
| 596 | |
| 597 void MessageGenerator::Flatten(std::vector<MessageGenerator*>* list) { | |
| 598 for (int i = 0; i < descriptor_->nested_type_count(); i++) { | 428 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 599 nested_generators_[i]->Flatten(list); | 429 // map entry message doesn't need forward declaration. Since map entry |
| 600 } | 430 // message cannot be a top level class, we just need to avoid calling |
| 601 list->push_back(this); | 431 // GenerateForwardDeclaration here. |
| 602 } | 432 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; |
| 603 | 433 nested_generators_[i]->FillMessageForwardDeclarations(class_names); |
| 604 void MessageGenerator::AddGenerators( | |
| 605 std::vector<EnumGenerator*>* enum_generators, | |
| 606 std::vector<ExtensionGenerator*>* extension_generators) { | |
| 607 for (int i = 0; i < descriptor_->enum_type_count(); i++) { | |
| 608 enum_generators->push_back(enum_generators_[i].get()); | |
| 609 } | |
| 610 for (int i = 0; i < descriptor_->extension_count(); i++) { | |
| 611 extension_generators->push_back(extension_generators_[i].get()); | |
| 612 } | 434 } |
| 613 } | 435 } |
| 614 | 436 |
| 615 void MessageGenerator::FillMessageForwardDeclarations( | 437 void MessageGenerator:: |
| 616 std::map<string, const Descriptor*>* class_names) { | 438 FillEnumForwardDeclarations(map<string, const EnumDescriptor*>* enum_names) { |
| 617 if (IsMapEntryMessage(descriptor_)) return; | 439 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 618 (*class_names)[classname_] = descriptor_; | 440 nested_generators_[i]->FillEnumForwardDeclarations(enum_names); |
| 441 } |
| 442 for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
| 443 enum_generators_[i]->FillForwardDeclaration(enum_names); |
| 444 } |
| 619 } | 445 } |
| 620 | 446 |
| 621 void MessageGenerator:: | 447 void MessageGenerator:: |
| 448 GenerateEnumDefinitions(io::Printer* printer) { |
| 449 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 450 nested_generators_[i]->GenerateEnumDefinitions(printer); |
| 451 } |
| 452 |
| 453 for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
| 454 enum_generators_[i]->GenerateDefinition(printer); |
| 455 } |
| 456 } |
| 457 |
| 458 void MessageGenerator:: |
| 459 GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { |
| 460 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 461 nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); |
| 462 } |
| 463 for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
| 464 enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); |
| 465 } |
| 466 } |
| 467 |
| 468 void MessageGenerator:: |
| 622 GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { | 469 GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { |
| 623 for (int i = 0; i < descriptor_->field_count(); i++) { | 470 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 624 const FieldDescriptor* field = descriptor_->field(i); | 471 const FieldDescriptor* field = descriptor_->field(i); |
| 625 | 472 |
| 626 PrintFieldComment(printer, field); | 473 PrintFieldComment(printer, field); |
| 627 | 474 |
| 628 std::map<string, string> vars; | 475 map<string, string> vars; |
| 629 SetCommonFieldVariables(field, &vars, options_); | 476 SetCommonFieldVariables(field, &vars, options_); |
| 630 | 477 |
| 631 if (use_dependent_base_ && IsFieldDependent(field)) { | 478 if (use_dependent_base_ && IsFieldDependent(field)) { |
| 632 // If the message is dependent, the inline clear_*() method will need | 479 // If the message is dependent, the inline clear_*() method will need |
| 633 // to delete the message type, so it must be in the dependent base | 480 // to delete the message type, so it must be in the dependent base |
| 634 // class. (See also GenerateFieldAccessorDeclarations.) | 481 // class. (See also GenerateFieldAccessorDeclarations.) |
| 635 printer->Print(vars, "$deprecated_attr$void clear_$name$();\n"); | 482 printer->Print(vars, "$deprecated_attr$void clear_$name$();\n"); |
| 636 } | 483 } |
| 637 // Generate type-specific accessor declarations. | 484 // Generate type-specific accessor declarations. |
| 638 field_generators_.get(field).GenerateDependentAccessorDeclarations(printer); | 485 field_generators_.get(field).GenerateDependentAccessorDeclarations(printer); |
| 639 printer->Print("\n"); | 486 printer->Print("\n"); |
| 640 } | 487 } |
| 641 } | 488 } |
| 642 | 489 |
| 643 void MessageGenerator:: | 490 void MessageGenerator:: |
| 644 GenerateFieldAccessorDeclarations(io::Printer* printer) { | 491 GenerateFieldAccessorDeclarations(io::Printer* printer) { |
| 645 for (int i = 0; i < descriptor_->field_count(); i++) { | 492 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 646 const FieldDescriptor* field = descriptor_->field(i); | 493 const FieldDescriptor* field = descriptor_->field(i); |
| 647 | 494 |
| 648 PrintFieldComment(printer, field); | 495 PrintFieldComment(printer, field); |
| 649 | 496 |
| 650 std::map<string, string> vars; | 497 map<string, string> vars; |
| 651 SetCommonFieldVariables(field, &vars, options_); | 498 SetCommonFieldVariables(field, &vars, options_); |
| 652 vars["constant_name"] = FieldConstantName(field); | 499 vars["constant_name"] = FieldConstantName(field); |
| 653 | 500 |
| 654 bool dependent_field = use_dependent_base_ && IsFieldDependent(field); | 501 bool dependent_field = use_dependent_base_ && IsFieldDependent(field); |
| 655 if (dependent_field && | 502 if (dependent_field && |
| 656 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && | 503 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && |
| 657 !field->is_map()) { | 504 !field->is_map()) { |
| 658 // If this field is dependent, the dependent base class determines | 505 // If this field is dependent, the dependent base class determines |
| 659 // the message type from the derived class (which is a template | 506 // the message type from the derived class (which is a template |
| 660 // parameter). This typedef is for that: | 507 // parameter). This typedef is for that: |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 void MessageGenerator:: | 559 void MessageGenerator:: |
| 713 GenerateDependentFieldAccessorDefinitions(io::Printer* printer) { | 560 GenerateDependentFieldAccessorDefinitions(io::Printer* printer) { |
| 714 if (!use_dependent_base_) return; | 561 if (!use_dependent_base_) return; |
| 715 | 562 |
| 716 printer->Print("// $classname$\n\n", "classname", | 563 printer->Print("// $classname$\n\n", "classname", |
| 717 DependentBaseClassTemplateName(descriptor_)); | 564 DependentBaseClassTemplateName(descriptor_)); |
| 718 | 565 |
| 719 for (int i = 0; i < descriptor_->field_count(); i++) { | 566 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 720 const FieldDescriptor* field = descriptor_->field(i); | 567 const FieldDescriptor* field = descriptor_->field(i); |
| 721 | 568 |
| 722 if (field->options().weak()) continue; | |
| 723 | |
| 724 PrintFieldComment(printer, field); | 569 PrintFieldComment(printer, field); |
| 725 | 570 |
| 726 // These functions are not really dependent: they are part of the | 571 // These functions are not really dependent: they are part of the |
| 727 // (non-dependent) derived class. However, they need to live outside | 572 // (non-dependent) derived class. However, they need to live outside |
| 728 // any #ifdef guards, so we treat them as if they were dependent. | 573 // any #ifdef guards, so we treat them as if they were dependent. |
| 729 // | 574 // |
| 730 // See the comment in FileGenerator::GenerateInlineFunctionDefinitions | 575 // See the comment in FileGenerator::GenerateInlineFunctionDefinitions |
| 731 // for a more complete explanation. | 576 // for a more complete explanation. |
| 732 if (use_dependent_base_ && IsFieldDependent(field)) { | 577 if (use_dependent_base_ && IsFieldDependent(field)) { |
| 733 std::map<string, string> vars; | 578 map<string, string> vars; |
| 734 SetCommonFieldVariables(field, &vars, options_); | 579 SetCommonFieldVariables(field, &vars, options_); |
| 735 vars["inline"] = "inline "; | 580 vars["inline"] = "inline "; |
| 736 if (field->containing_oneof()) { | 581 if (field->containing_oneof()) { |
| 737 vars["field_name"] = UnderscoresToCamelCase(field->name(), true); | 582 vars["field_name"] = UnderscoresToCamelCase(field->name(), true); |
| 738 vars["oneof_name"] = field->containing_oneof()->name(); | 583 vars["oneof_name"] = field->containing_oneof()->name(); |
| 739 vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); | 584 vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); |
| 740 GenerateOneofMemberHasBits(field, vars, printer); | 585 GenerateOneofMemberHasBits(field, vars, printer); |
| 741 } else if (!field->is_repeated()) { | 586 } else if (!field->is_repeated()) { |
| 742 // There will be no header guard, so this always has to be inline. | 587 // There will be no header guard, so this always has to be inline. |
| 743 GenerateSingularFieldHasBits(field, vars, printer); | 588 GenerateSingularFieldHasBits(field, vars, printer); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 760 } | 605 } |
| 761 | 606 |
| 762 // Generate has_$name$() and clear_has_$name$() functions for oneofs | 607 // Generate has_$name$() and clear_has_$name$() functions for oneofs |
| 763 // Similar to other has-bits, these must always be in the header if we | 608 // Similar to other has-bits, these must always be in the header if we |
| 764 // are using a dependent base class. | 609 // are using a dependent base class. |
| 765 GenerateOneofHasBits(printer, true /* is_inline */); | 610 GenerateOneofHasBits(printer, true /* is_inline */); |
| 766 } | 611 } |
| 767 | 612 |
| 768 void MessageGenerator:: | 613 void MessageGenerator:: |
| 769 GenerateSingularFieldHasBits(const FieldDescriptor* field, | 614 GenerateSingularFieldHasBits(const FieldDescriptor* field, |
| 770 std::map<string, string> vars, | 615 map<string, string> vars, |
| 771 io::Printer* printer) { | 616 io::Printer* printer) { |
| 772 if (HasFieldPresence(descriptor_->file())) { | 617 if (HasFieldPresence(descriptor_->file())) { |
| 773 // N.B.: without field presence, we do not use has-bits or generate | 618 // N.B.: without field presence, we do not use has-bits or generate |
| 774 // has_$name$() methods. | 619 // has_$name$() methods. |
| 775 int has_bit_index = has_bit_indices_[field->index()]; | 620 vars["has_array_index"] = SimpleItoa(field->index() / 32); |
| 776 GOOGLE_CHECK_GE(has_bit_index, 0); | 621 vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32), |
| 777 | |
| 778 vars["has_array_index"] = SimpleItoa(has_bit_index / 32); | |
| 779 vars["has_mask"] = StrCat(strings::Hex(1u << (has_bit_index % 32), | |
| 780 strings::ZERO_PAD_8)); | 622 strings::ZERO_PAD_8)); |
| 781 printer->Print(vars, | 623 printer->Print(vars, |
| 782 "$inline$" | 624 "$inline$" |
| 783 "bool $classname$::has_$name$() const {\n" | 625 "bool $classname$::has_$name$() const {\n" |
| 784 " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" | 626 " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" |
| 785 "}\n" | 627 "}\n" |
| 786 "$inline$" | 628 "$inline$" |
| 787 "void $classname$::set_has_$name$() {\n" | 629 "void $classname$::set_has_$name$() {\n" |
| 788 " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" | 630 " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" |
| 789 "}\n" | 631 "}\n" |
| 790 "$inline$" | 632 "$inline$" |
| 791 "void $classname$::clear_has_$name$() {\n" | 633 "void $classname$::clear_has_$name$() {\n" |
| 792 " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" | 634 " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" |
| 793 "}\n"); | 635 "}\n"); |
| 794 } else { | 636 } else { |
| 795 // Message fields have a has_$name$() method. | 637 // Message fields have a has_$name$() method. |
| 796 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 638 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
| 797 bool is_lazy = false; | 639 bool is_lazy = false; |
| 798 if (is_lazy) { | 640 if (is_lazy) { |
| 799 printer->Print(vars, | 641 printer->Print(vars, |
| 800 "$inline$" | 642 "$inline$" |
| 801 "bool $classname$::has_$name$() const {\n" | 643 "bool $classname$::has_$name$() const {\n" |
| 802 " return !$name$_.IsCleared();\n" | 644 " return !$name$_.IsCleared();\n" |
| 803 "}\n"); | 645 "}\n"); |
| 804 } else { | 646 } else { |
| 805 printer->Print( | 647 printer->Print(vars, |
| 806 vars, | 648 "$inline$" |
| 807 "$inline$" | 649 "bool $classname$::has_$name$() const {\n" |
| 808 "bool $classname$::has_$name$() const {\n" | 650 " return !_is_default_instance_ && $name$_ != NULL;\n" |
| 809 " return this != internal_default_instance() && $name$_ != NULL;\n" | 651 "}\n"); |
| 810 "}\n"); | |
| 811 } | 652 } |
| 812 } | 653 } |
| 813 } | 654 } |
| 814 } | 655 } |
| 815 | 656 |
| 816 void MessageGenerator:: | 657 void MessageGenerator:: |
| 817 GenerateOneofHasBits(io::Printer* printer, bool is_inline) { | 658 GenerateOneofHasBits(io::Printer* printer, bool is_inline) { |
| 818 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 659 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 819 std::map<string, string> vars; | 660 map<string, string> vars; |
| 820 vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); | 661 vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); |
| 821 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); | 662 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); |
| 822 vars["cap_oneof_name"] = | 663 vars["cap_oneof_name"] = |
| 823 ToUpper(descriptor_->oneof_decl(i)->name()); | 664 ToUpper(descriptor_->oneof_decl(i)->name()); |
| 824 vars["classname"] = classname_; | 665 vars["classname"] = classname_; |
| 825 vars["inline"] = (is_inline ? "inline " : ""); | 666 vars["inline"] = (is_inline ? "inline " : ""); |
| 826 printer->Print( | 667 printer->Print( |
| 827 vars, | 668 vars, |
| 828 "$inline$" | 669 "$inline$" |
| 829 "bool $classname$::has_$oneof_name$() const {\n" | 670 "bool $classname$::has_$oneof_name$() const {\n" |
| 830 " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" | 671 " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" |
| 831 "}\n" | 672 "}\n" |
| 832 "$inline$" | 673 "$inline$" |
| 833 "void $classname$::clear_has_$oneof_name$() {\n" | 674 "void $classname$::clear_has_$oneof_name$() {\n" |
| 834 " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" | 675 " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" |
| 835 "}\n"); | 676 "}\n"); |
| 836 } | 677 } |
| 837 } | 678 } |
| 838 | 679 |
| 839 void MessageGenerator:: | 680 void MessageGenerator:: |
| 840 GenerateOneofMemberHasBits(const FieldDescriptor* field, | 681 GenerateOneofMemberHasBits(const FieldDescriptor* field, |
| 841 const std::map<string, string>& vars, | 682 const map<string, string>& vars, |
| 842 io::Printer* printer) { | 683 io::Printer* printer) { |
| 843 // Singular field in a oneof | 684 // Singular field in a oneof |
| 844 // N.B.: Without field presence, we do not use has-bits or generate | 685 // N.B.: Without field presence, we do not use has-bits or generate |
| 845 // has_$name$() methods, but oneofs still have set_has_$name$(). | 686 // has_$name$() methods, but oneofs still have set_has_$name$(). |
| 846 // Oneofs also have has_$name$() but only as a private helper | 687 // Oneofs also have has_$name$() but only as a private helper |
| 847 // method, so that generated code is slightly cleaner (vs. comparing | 688 // method, so that generated code is slightly cleaner (vs. comparing |
| 848 // _oneof_case_[index] against a constant everywhere). | 689 // _oneof_case_[index] against a constant everywhere). |
| 849 printer->Print(vars, | 690 printer->Print(vars, |
| 850 "$inline$" | 691 "$inline$" |
| 851 "bool $classname$::has_$name$() const {\n" | 692 "bool $classname$::has_$name$() const {\n" |
| 852 " return $oneof_name$_case() == k$field_name$;\n" | 693 " return $oneof_name$_case() == k$field_name$;\n" |
| 853 "}\n"); | 694 "}\n"); |
| 854 printer->Print(vars, | 695 printer->Print(vars, |
| 855 "$inline$" | 696 "$inline$" |
| 856 "void $classname$::set_has_$name$() {\n" | 697 "void $classname$::set_has_$name$() {\n" |
| 857 " _oneof_case_[$oneof_index$] = k$field_name$;\n" | 698 " _oneof_case_[$oneof_index$] = k$field_name$;\n" |
| 858 "}\n"); | 699 "}\n"); |
| 859 } | 700 } |
| 860 | 701 |
| 861 void MessageGenerator:: | 702 void MessageGenerator:: |
| 862 GenerateFieldClear(const FieldDescriptor* field, | 703 GenerateFieldClear(const FieldDescriptor* field, |
| 863 const std::map<string, string>& vars, | 704 const map<string, string>& vars, |
| 864 io::Printer* printer) { | 705 io::Printer* printer) { |
| 865 // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and | 706 // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and |
| 866 // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is | 707 // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is |
| 867 // set by the Generate*Definitions functions.) | 708 // set by the Generate*Definitions functions.) |
| 868 printer->Print(vars, | 709 printer->Print(vars, |
| 869 "$tmpl$" | 710 "$tmpl$" |
| 870 "$inline$" | 711 "$inline$" |
| 871 "void $dependent_classname$::clear_$name$() {\n"); | 712 "void $dependent_classname$::clear_$name$() {\n"); |
| 872 | 713 |
| 873 printer->Indent(); | 714 printer->Indent(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 901 | 742 |
| 902 void MessageGenerator:: | 743 void MessageGenerator:: |
| 903 GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { | 744 GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { |
| 904 printer->Print("// $classname$\n\n", "classname", classname_); | 745 printer->Print("// $classname$\n\n", "classname", classname_); |
| 905 | 746 |
| 906 for (int i = 0; i < descriptor_->field_count(); i++) { | 747 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 907 const FieldDescriptor* field = descriptor_->field(i); | 748 const FieldDescriptor* field = descriptor_->field(i); |
| 908 | 749 |
| 909 PrintFieldComment(printer, field); | 750 PrintFieldComment(printer, field); |
| 910 | 751 |
| 911 std::map<string, string> vars; | 752 map<string, string> vars; |
| 912 SetCommonFieldVariables(field, &vars, options_); | 753 SetCommonFieldVariables(field, &vars, options_); |
| 913 vars["inline"] = is_inline ? "inline " : ""; | 754 vars["inline"] = is_inline ? "inline " : ""; |
| 914 if (use_dependent_base_ && IsFieldDependent(field)) { | 755 if (use_dependent_base_ && IsFieldDependent(field)) { |
| 915 vars["tmpl"] = "template<class T>\n"; | 756 vars["tmpl"] = "template<class T>\n"; |
| 916 vars["dependent_classname"] = | 757 vars["dependent_classname"] = |
| 917 DependentBaseClassTemplateName(descriptor_) + "<T>"; | 758 DependentBaseClassTemplateName(descriptor_) + "<T>"; |
| 918 vars["this_message"] = "reinterpret_cast<T*>(this)->"; | 759 vars["this_message"] = "reinterpret_cast<T*>(this)->"; |
| 919 vars["this_const_message"] = "reinterpret_cast<const T*>(this)->"; | 760 vars["this_const_message"] = "reinterpret_cast<const T*>(this)->"; |
| 920 } else { | 761 } else { |
| 921 vars["tmpl"] = ""; | 762 vars["tmpl"] = ""; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 } | 798 } |
| 958 | 799 |
| 959 if (!use_dependent_base_) { | 800 if (!use_dependent_base_) { |
| 960 // Generate has_$name$() and clear_has_$name$() functions for oneofs | 801 // Generate has_$name$() and clear_has_$name$() functions for oneofs |
| 961 // If we aren't using a dependent base, they can be with the other functions | 802 // If we aren't using a dependent base, they can be with the other functions |
| 962 // that are #ifdef-guarded. | 803 // that are #ifdef-guarded. |
| 963 GenerateOneofHasBits(printer, is_inline); | 804 GenerateOneofHasBits(printer, is_inline); |
| 964 } | 805 } |
| 965 } | 806 } |
| 966 | 807 |
| 808 // Helper for the code that emits the Clear() method. |
| 809 static bool CanClearByZeroing(const FieldDescriptor* field) { |
| 810 if (field->is_repeated() || field->is_extension()) return false; |
| 811 switch (field->cpp_type()) { |
| 812 case internal::WireFormatLite::CPPTYPE_ENUM: |
| 813 return field->default_value_enum()->number() == 0; |
| 814 case internal::WireFormatLite::CPPTYPE_INT32: |
| 815 return field->default_value_int32() == 0; |
| 816 case internal::WireFormatLite::CPPTYPE_INT64: |
| 817 return field->default_value_int64() == 0; |
| 818 case internal::WireFormatLite::CPPTYPE_UINT32: |
| 819 return field->default_value_uint32() == 0; |
| 820 case internal::WireFormatLite::CPPTYPE_UINT64: |
| 821 return field->default_value_uint64() == 0; |
| 822 case internal::WireFormatLite::CPPTYPE_FLOAT: |
| 823 return field->default_value_float() == 0; |
| 824 case internal::WireFormatLite::CPPTYPE_DOUBLE: |
| 825 return field->default_value_double() == 0; |
| 826 case internal::WireFormatLite::CPPTYPE_BOOL: |
| 827 return field->default_value_bool() == false; |
| 828 default: |
| 829 return false; |
| 830 } |
| 831 } |
| 832 |
| 967 void MessageGenerator:: | 833 void MessageGenerator:: |
| 968 GenerateDependentBaseClassDefinition(io::Printer* printer) { | 834 GenerateDependentBaseClassDefinition(io::Printer* printer) { |
| 969 if (!use_dependent_base_) { | 835 if (!use_dependent_base_) { |
| 970 return; | 836 return; |
| 971 } | 837 } |
| 972 | 838 |
| 973 std::map<string, string> vars; | 839 map<string, string> vars; |
| 974 vars["classname"] = DependentBaseClassTemplateName(descriptor_); | 840 vars["classname"] = DependentBaseClassTemplateName(descriptor_); |
| 975 vars["full_name"] = descriptor_->full_name(); | |
| 976 vars["superclass"] = SuperClassName(descriptor_, options_); | 841 vars["superclass"] = SuperClassName(descriptor_, options_); |
| 977 | 842 |
| 978 printer->Print(vars, | 843 printer->Print(vars, |
| 979 "template <class T>\n" | 844 "template <class T>\n" |
| 980 "class $classname$ : public $superclass$ " | 845 "class $classname$ : public $superclass$ {\n" |
| 981 "/* @@protoc_insertion_point(dep_base_class_definition:$full_name$) */ {\n" | |
| 982 " public:\n"); | 846 " public:\n"); |
| 983 printer->Indent(); | 847 printer->Indent(); |
| 984 | 848 |
| 985 printer->Print(vars, | 849 printer->Print(vars, |
| 986 "$classname$() {}\n" | 850 "$classname$() {}\n" |
| 987 "virtual ~$classname$() {}\n" | 851 "virtual ~$classname$() {}\n" |
| 988 "\n"); | 852 "\n"); |
| 989 | 853 |
| 990 // Generate dependent accessor methods for all fields. | 854 // Generate dependent accessor methods for all fields. |
| 991 GenerateDependentFieldAccessorDeclarations(printer); | 855 GenerateDependentFieldAccessorDeclarations(printer); |
| 992 | 856 |
| 993 printer->Outdent(); | 857 printer->Outdent(); |
| 994 printer->Print("};\n"); | 858 printer->Print("};\n"); |
| 995 } | 859 } |
| 996 | 860 |
| 997 void MessageGenerator:: | 861 void MessageGenerator:: |
| 998 GenerateClassDefinition(io::Printer* printer) { | 862 GenerateClassDefinition(io::Printer* printer) { |
| 999 if (IsMapEntryMessage(descriptor_)) return; | 863 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 864 // map entry message doesn't need class definition. Since map entry message |
| 865 // cannot be a top level class, we just need to avoid calling |
| 866 // GenerateClassDefinition here. |
| 867 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; |
| 868 nested_generators_[i]->GenerateClassDefinition(printer); |
| 869 printer->Print("\n"); |
| 870 printer->Print(kThinSeparator); |
| 871 printer->Print("\n"); |
| 872 } |
| 873 |
| 1000 if (use_dependent_base_) { | 874 if (use_dependent_base_) { |
| 1001 GenerateDependentBaseClassDefinition(printer); | 875 GenerateDependentBaseClassDefinition(printer); |
| 1002 printer->Print("\n"); | 876 printer->Print("\n"); |
| 1003 } | 877 } |
| 1004 | 878 |
| 1005 std::map<string, string> vars; | 879 map<string, string> vars; |
| 1006 vars["classname"] = classname_; | 880 vars["classname"] = classname_; |
| 1007 vars["full_name"] = descriptor_->full_name(); | |
| 1008 vars["field_count"] = SimpleItoa(descriptor_->field_count()); | 881 vars["field_count"] = SimpleItoa(descriptor_->field_count()); |
| 1009 vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); | 882 vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); |
| 1010 if (options_.dllexport_decl.empty()) { | 883 if (options_.dllexport_decl.empty()) { |
| 1011 vars["dllexport"] = ""; | 884 vars["dllexport"] = ""; |
| 1012 } else { | 885 } else { |
| 1013 vars["dllexport"] = options_.dllexport_decl + " "; | 886 vars["dllexport"] = options_.dllexport_decl + " "; |
| 1014 } | 887 } |
| 1015 if (use_dependent_base_) { | 888 if (use_dependent_base_) { |
| 1016 vars["superclass"] = | 889 vars["superclass"] = |
| 1017 DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; | 890 DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; |
| 1018 } else { | 891 } else { |
| 1019 vars["superclass"] = SuperClassName(descriptor_, options_); | 892 vars["superclass"] = SuperClassName(descriptor_, options_); |
| 1020 } | 893 } |
| 1021 printer->Print(vars, | 894 printer->Print(vars, |
| 1022 "class $dllexport$$classname$ : public $superclass$ " | 895 "class $dllexport$$classname$ : public $superclass$ {\n"); |
| 1023 "/* @@protoc_insertion_point(class_definition:$full_name$) */ " | |
| 1024 "{\n"); | |
| 1025 printer->Annotate("classname", descriptor_); | 896 printer->Annotate("classname", descriptor_); |
| 1026 if (use_dependent_base_) { | 897 if (use_dependent_base_) { |
| 1027 printer->Print(vars, " friend class $superclass$;\n"); | 898 printer->Print(vars, " friend class $superclass$;\n"); |
| 1028 } | 899 } |
| 1029 printer->Print(" public:\n"); | 900 printer->Print(" public:\n"); |
| 1030 printer->Indent(); | 901 printer->Indent(); |
| 1031 | 902 |
| 1032 printer->Print(vars, | 903 printer->Print(vars, |
| 1033 "$classname$();\n" | 904 "$classname$();\n" |
| 1034 "virtual ~$classname$();\n" | 905 "virtual ~$classname$();\n" |
| 1035 "\n" | 906 "\n" |
| 1036 "$classname$(const $classname$& from);\n" | 907 "$classname$(const $classname$& from);\n" |
| 1037 "\n" | 908 "\n" |
| 1038 "inline $classname$& operator=(const $classname$& from) {\n" | 909 "inline $classname$& operator=(const $classname$& from) {\n" |
| 1039 " CopyFrom(from);\n" | 910 " CopyFrom(from);\n" |
| 1040 " return *this;\n" | 911 " return *this;\n" |
| 1041 "}\n" | 912 "}\n" |
| 1042 "\n"); | 913 "\n"); |
| 1043 | 914 |
| 1044 if (PreserveUnknownFields(descriptor_)) { | 915 if (PreserveUnknownFields(descriptor_)) { |
| 1045 string type = UseUnknownFieldSet(descriptor_->file(), options_) | 916 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1046 ? "::google::protobuf::UnknownFieldSet" | 917 printer->Print( |
| 1047 : "::std::string"; | 918 "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() cons
t {\n" |
| 1048 printer->Print( | 919 " return _internal_metadata_.unknown_fields();\n" |
| 1049 "inline const $type$& unknown_fields() const {\n" | 920 "}\n" |
| 1050 " return _internal_metadata_.unknown_fields();\n" | 921 "\n" |
| 1051 "}\n" | 922 "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\
n" |
| 1052 "\n" | 923 " return _internal_metadata_.mutable_unknown_fields();\n" |
| 1053 "inline $type$* mutable_unknown_fields() {\n" | 924 "}\n" |
| 1054 " return _internal_metadata_.mutable_unknown_fields();\n" | 925 "\n"); |
| 1055 "}\n" | 926 } else { |
| 1056 "\n", | 927 if (SupportsArenas(descriptor_)) { |
| 1057 "type", type ); | 928 printer->Print( |
| 929 "inline const ::std::string& unknown_fields() const {\n" |
| 930 " return _unknown_fields_.Get(\n" |
| 931 " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\
n" |
| 932 "}\n" |
| 933 "\n" |
| 934 "inline ::std::string* mutable_unknown_fields() {\n" |
| 935 " return _unknown_fields_.Mutable(\n" |
| 936 " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n
" |
| 937 " GetArenaNoVirtual());\n" |
| 938 "}\n" |
| 939 "\n"); |
| 940 } else { |
| 941 printer->Print( |
| 942 "inline const ::std::string& unknown_fields() const {\n" |
| 943 " return _unknown_fields_.GetNoArena(\n" |
| 944 " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\
n" |
| 945 "}\n" |
| 946 "\n" |
| 947 "inline ::std::string* mutable_unknown_fields() {\n" |
| 948 " return _unknown_fields_.MutableNoArena(\n" |
| 949 " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\
n" |
| 950 "}\n" |
| 951 "\n"); |
| 952 } |
| 953 } |
| 1058 } | 954 } |
| 1059 | 955 |
| 1060 // N.B.: We exclude GetArena() when arena support is disabled, falling back on | 956 // N.B.: We exclude GetArena() when arena support is disabled, falling back on |
| 1061 // MessageLite's implementation which returns NULL rather than generating our | 957 // MessageLite's implementation which returns NULL rather than generating our |
| 1062 // own method which returns NULL, in order to reduce code size. | 958 // own method which returns NULL, in order to reduce code size. |
| 1063 if (SupportsArenas(descriptor_)) { | 959 if (SupportsArenas(descriptor_)) { |
| 1064 // virtual method version of GetArenaNoVirtual(), required for generic dispa
tch given a | 960 // virtual method version of GetArenaNoVirtual(), required for generic dispa
tch given a |
| 1065 // MessageLite* (e.g., in RepeatedField::AddAllocated()). | 961 // MessageLite* (e.g., in RepeatedField::AddAllocated()). |
| 1066 printer->Print( | 962 printer->Print( |
| 1067 "inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {\n" | 963 "inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoV
irtual(); }\n" |
| 1068 " return GetArenaNoVirtual();\n" | 964 "inline void* GetMaybeArenaPointer() const {\n" |
| 1069 "}\n" | |
| 1070 "inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL {\n" | |
| 1071 " return MaybeArenaPtr();\n" | 965 " return MaybeArenaPtr();\n" |
| 1072 "}\n"); | 966 "}\n"); |
| 1073 } | 967 } |
| 1074 | 968 |
| 1075 // Only generate this member if it's not disabled. | 969 // Only generate this member if it's not disabled. |
| 1076 if (HasDescriptorMethods(descriptor_->file(), options_) && | 970 if (HasDescriptorMethods(descriptor_->file(), options_) && |
| 1077 !descriptor_->options().no_standard_descriptor_accessor()) { | 971 !descriptor_->options().no_standard_descriptor_accessor()) { |
| 1078 printer->Print(vars, | 972 printer->Print(vars, |
| 1079 "static const ::google::protobuf::Descriptor* descriptor();\n"); | 973 "static const ::google::protobuf::Descriptor* descriptor();\n"); |
| 1080 } | 974 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1103 printer->Print( | 997 printer->Print( |
| 1104 "$cap_oneof_name$_NOT_SET = 0,\n", | 998 "$cap_oneof_name$_NOT_SET = 0,\n", |
| 1105 "cap_oneof_name", | 999 "cap_oneof_name", |
| 1106 ToUpper(descriptor_->oneof_decl(i)->name())); | 1000 ToUpper(descriptor_->oneof_decl(i)->name())); |
| 1107 printer->Outdent(); | 1001 printer->Outdent(); |
| 1108 printer->Print( | 1002 printer->Print( |
| 1109 "};\n" | 1003 "};\n" |
| 1110 "\n"); | 1004 "\n"); |
| 1111 } | 1005 } |
| 1112 | 1006 |
| 1113 // TODO(gerbens) make this private, while still granting other protos access. | 1007 if (!StaticInitializersForced(descriptor_->file(), options_)) { |
| 1114 printer->Print( | 1008 printer->Print(vars, |
| 1115 vars, | 1009 "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" |
| 1010 "// Returns the internal default instance pointer. This function can\n" |
| 1011 "// return NULL thus should not be used by the user. This is intended\n" |
| 1012 "// for Protobuf internal code. Please use default_instance() declared\n" |
| 1013 "// above instead.\n" |
| 1116 "static inline const $classname$* internal_default_instance() {\n" | 1014 "static inline const $classname$* internal_default_instance() {\n" |
| 1117 " return reinterpret_cast<const $classname$*>(\n" | 1015 " return default_instance_;\n" |
| 1118 " &_$classname$_default_instance_);\n" | |
| 1119 "}\n" | 1016 "}\n" |
| 1017 "#endif\n" |
| 1120 "\n"); | 1018 "\n"); |
| 1019 } |
| 1121 | 1020 |
| 1122 | 1021 |
| 1123 if (SupportsArenas(descriptor_)) { | 1022 if (SupportsArenas(descriptor_)) { |
| 1124 printer->Print(vars, | 1023 printer->Print(vars, |
| 1125 "void UnsafeArenaSwap($classname$* other);\n"); | 1024 "void UnsafeArenaSwap($classname$* other);\n"); |
| 1126 } | 1025 } |
| 1127 | 1026 |
| 1128 if (IsAnyMessage(descriptor_)) { | 1027 if (IsAnyMessage(descriptor_)) { |
| 1129 printer->Print(vars, | 1028 printer->Print(vars, |
| 1130 "// implements Any -----------------------------------------------\n" | 1029 "// implements Any -----------------------------------------------\n" |
| 1131 "\n" | 1030 "\n" |
| 1132 "void PackFrom(const ::google::protobuf::Message& message);\n" | 1031 "void PackFrom(const ::google::protobuf::Message& message);\n" |
| 1133 "void PackFrom(const ::google::protobuf::Message& message,\n" | 1032 "void PackFrom(const ::google::protobuf::Message& message,\n" |
| 1134 " const ::std::string& type_url_prefix);\n" | 1033 " const ::std::string& type_url_prefix);\n" |
| 1135 "bool UnpackTo(::google::protobuf::Message* message) const;\n" | 1034 "bool UnpackTo(::google::protobuf::Message* message) const;\n" |
| 1136 "template<typename T> bool Is() const {\n" | 1035 "template<typename T> bool Is() const {\n" |
| 1137 " return _any_metadata_.Is<T>();\n" | 1036 " return _any_metadata_.Is<T>();\n" |
| 1138 "}\n" | 1037 "}\n" |
| 1139 "\n"); | 1038 "\n"); |
| 1140 } | 1039 } |
| 1141 | 1040 |
| 1142 vars["new_final"] = " PROTOBUF_FINAL"; | |
| 1143 | |
| 1144 printer->Print(vars, | 1041 printer->Print(vars, |
| 1145 "GOOGLE_ATTRIBUTE_NOINLINE void Swap($classname$* other);\n" | 1042 "GOOGLE_ATTRIBUTE_NOINLINE void Swap($classname$* other);\n" |
| 1146 "\n" | 1043 "\n" |
| 1147 "// implements Message ----------------------------------------------\n" | 1044 "// implements Message ----------------------------------------------\n" |
| 1148 "\n" | 1045 "\n" |
| 1149 "inline $classname$* New() const$new_final$ { return New(NULL); }\n" | 1046 "inline $classname$* New() const { return New(NULL); }\n" |
| 1150 "\n" | 1047 "\n" |
| 1151 "$classname$* New(::google::protobuf::Arena* arena) const$new_final$;\n"); | 1048 "$classname$* New(::google::protobuf::Arena* arena) const;\n"); |
| 1152 | |
| 1153 // For instances that derive from Message (rather than MessageLite), some | |
| 1154 // methods are virtual and should be marked as final. | |
| 1155 string use_final = HasDescriptorMethods(descriptor_->file(), options_) ? | |
| 1156 " PROTOBUF_FINAL" : ""; | |
| 1157 | 1049 |
| 1158 if (HasGeneratedMethods(descriptor_->file(), options_)) { | 1050 if (HasGeneratedMethods(descriptor_->file(), options_)) { |
| 1159 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 1051 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
| 1160 printer->Print(vars, | 1052 printer->Print(vars, |
| 1161 "void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;\
n" | 1053 "void CopyFrom(const ::google::protobuf::Message& from);\n" |
| 1162 "void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
\n"); | 1054 "void MergeFrom(const ::google::protobuf::Message& from);\n"); |
| 1163 } else { | 1055 } else { |
| 1164 printer->Print(vars, | 1056 printer->Print(vars, |
| 1165 "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
\n" | 1057 "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
;\n"); |
| 1166 " PROTOBUF_FINAL;\n"); | |
| 1167 } | 1058 } |
| 1168 | 1059 |
| 1169 vars["clear_final"] = " PROTOBUF_FINAL"; | 1060 printer->Print(vars, |
| 1170 vars["is_initialized_final"] = " PROTOBUF_FINAL"; | 1061 "void CopyFrom(const $classname$& from);\n" |
| 1171 vars["merge_partial_final"] = " PROTOBUF_FINAL"; | 1062 "void MergeFrom(const $classname$& from);\n" |
| 1172 | 1063 "void Clear();\n" |
| 1173 printer->Print( | 1064 "bool IsInitialized() const;\n" |
| 1174 vars, | 1065 "\n" |
| 1175 "void CopyFrom(const $classname$& from);\n" | 1066 "int ByteSize() const;\n" |
| 1176 "void MergeFrom(const $classname$& from);\n" | 1067 "bool MergePartialFromCodedStream(\n" |
| 1177 "void Clear()$clear_final$;\n" | 1068 " ::google::protobuf::io::CodedInputStream* input);\n" |
| 1178 "bool IsInitialized() const$is_initialized_final$;\n" | 1069 "void SerializeWithCachedSizes(\n" |
| 1179 "\n" | 1070 " ::google::protobuf::io::CodedOutputStream* output) const;\n"); |
| 1180 "size_t ByteSizeLong() const PROTOBUF_FINAL;\n" | |
| 1181 "bool MergePartialFromCodedStream(\n" | |
| 1182 " ::google::protobuf::io::CodedInputStream* input)$merge_partial_fina
l$;\n" | |
| 1183 "void SerializeWithCachedSizes(\n" | |
| 1184 " ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_F
INAL;\n"); | |
| 1185 // DiscardUnknownFields() is implemented in message.cc using reflections. We | 1071 // DiscardUnknownFields() is implemented in message.cc using reflections. We |
| 1186 // need to implement this function in generated code for messages. | 1072 // need to implement this function in generated code for messages. |
| 1187 if (!UseUnknownFieldSet(descriptor_->file(), options_)) { | 1073 if (!UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1188 printer->Print( | 1074 printer->Print( |
| 1189 "void DiscardUnknownFields()$final$;\n", | 1075 "void DiscardUnknownFields();\n"); |
| 1190 "final", use_final); | |
| 1191 } | 1076 } |
| 1192 if (HasFastArraySerialization(descriptor_->file(), options_)) { | 1077 if (HasFastArraySerialization(descriptor_->file(), options_)) { |
| 1193 printer->Print( | 1078 printer->Print( |
| 1194 "::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(\n" | 1079 "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::pr
otobuf::uint8* output) const;\n"); |
| 1195 " bool deterministic, ::google::protobuf::uint8* target) const PROTOB
UF_FINAL;\n" | 1080 } |
| 1196 "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::pr
otobuf::uint8* output)\n" | 1081 } |
| 1197 " const PROTOBUF_FINAL {\n" | 1082 |
| 1198 " return InternalSerializeWithCachedSizesToArray(false, output);\n" | 1083 // Check all FieldDescriptors including those in oneofs to estimate |
| 1199 "}\n"); | 1084 // whether ::std::string is likely to be used, and depending on that |
| 1085 // estimate, set uses_string_ to true or false. That contols |
| 1086 // whether to force initialization of empty_string_ in SharedCtor(). |
| 1087 // It's often advantageous to do so to keep "is empty_string_ |
| 1088 // inited?" code from appearing all over the place. |
| 1089 vector<const FieldDescriptor*> descriptors; |
| 1090 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1091 descriptors.push_back(descriptor_->field(i)); |
| 1092 } |
| 1093 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1094 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
| 1095 descriptors.push_back(descriptor_->oneof_decl(i)->field(j)); |
| 1096 } |
| 1097 } |
| 1098 uses_string_ = false; |
| 1099 if (PreserveUnknownFields(descriptor_) && |
| 1100 !UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1101 uses_string_ = true; |
| 1102 } |
| 1103 for (int i = 0; i < descriptors.size(); i++) { |
| 1104 const FieldDescriptor* field = descriptors[i]; |
| 1105 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { |
| 1106 switch (field->options().ctype()) { |
| 1107 default: uses_string_ = true; break; |
| 1108 } |
| 1200 } | 1109 } |
| 1201 } | 1110 } |
| 1202 | 1111 |
| 1203 printer->Print( | 1112 printer->Print( |
| 1204 "int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }\n" | 1113 "int GetCachedSize() const { return _cached_size_; }\n" |
| 1205 "private:\n" | 1114 "private:\n" |
| 1206 "void SharedCtor();\n" | 1115 "void SharedCtor();\n" |
| 1207 "void SharedDtor();\n" | 1116 "void SharedDtor();\n" |
| 1208 "void SetCachedSize(int size) const$final$;\n" | 1117 "void SetCachedSize(int size) const;\n" |
| 1209 "void InternalSwap($classname$* other);\n", | 1118 "void InternalSwap($classname$* other);\n", |
| 1210 "classname", classname_, | 1119 "classname", classname_); |
| 1211 "final", use_final); | |
| 1212 if (SupportsArenas(descriptor_)) { | 1120 if (SupportsArenas(descriptor_)) { |
| 1213 printer->Print( | 1121 printer->Print( |
| 1214 "protected:\n" | 1122 "protected:\n" |
| 1215 "explicit $classname$(::google::protobuf::Arena* arena);\n" | 1123 "explicit $classname$(::google::protobuf::Arena* arena);\n" |
| 1216 "private:\n" | 1124 "private:\n" |
| 1217 "static void ArenaDtor(void* object);\n" | 1125 "static void ArenaDtor(void* object);\n" |
| 1218 "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n", | 1126 "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n", |
| 1219 "classname", classname_); | 1127 "classname", classname_); |
| 1220 } | 1128 } |
| 1221 | 1129 |
| 1222 if (SupportsArenas(descriptor_)) { | 1130 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1223 printer->Print( | 1131 printer->Print( |
| 1224 "private:\n" | 1132 "private:\n" |
| 1225 "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" | 1133 "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" |
| 1226 " return _internal_metadata_.arena();\n" | 1134 " return _internal_metadata_.arena();\n" |
| 1227 "}\n" | 1135 "}\n" |
| 1228 "inline void* MaybeArenaPtr() const {\n" | 1136 "inline void* MaybeArenaPtr() const {\n" |
| 1229 " return _internal_metadata_.raw_arena_ptr();\n" | 1137 " return _internal_metadata_.raw_arena_ptr();\n" |
| 1230 "}\n"); | 1138 "}\n" |
| 1139 "public:\n" |
| 1140 "\n"); |
| 1231 } else { | 1141 } else { |
| 1232 printer->Print( | 1142 printer->Print( |
| 1233 "private:\n" | 1143 "private:\n" |
| 1234 "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" | 1144 "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" |
| 1235 " return NULL;\n" | 1145 " return _arena_ptr_;\n" |
| 1236 "}\n" | 1146 "}\n" |
| 1237 "inline void* MaybeArenaPtr() const {\n" | 1147 "inline ::google::protobuf::Arena* MaybeArenaPtr() const {\n" |
| 1238 " return NULL;\n" | 1148 " return _arena_ptr_;\n" |
| 1239 "}\n"); | 1149 "}\n" |
| 1240 } | |
| 1241 | |
| 1242 printer->Print( | |
| 1243 "public:\n" | 1150 "public:\n" |
| 1244 "\n"); | 1151 "\n"); |
| 1152 } |
| 1245 | 1153 |
| 1246 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 1154 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
| 1247 printer->Print( | 1155 printer->Print( |
| 1248 "::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;\n" | 1156 "::google::protobuf::Metadata GetMetadata() const;\n" |
| 1249 "\n"); | 1157 "\n"); |
| 1250 } else { | 1158 } else { |
| 1251 printer->Print( | 1159 printer->Print( |
| 1252 "::std::string GetTypeName() const PROTOBUF_FINAL;\n" | 1160 "::std::string GetTypeName() const;\n" |
| 1253 "\n"); | 1161 "\n"); |
| 1254 } | 1162 } |
| 1255 | 1163 |
| 1256 printer->Print( | 1164 printer->Print( |
| 1257 "// nested types ----------------------------------------------------\n" | 1165 "// nested types ----------------------------------------------------\n" |
| 1258 "\n"); | 1166 "\n"); |
| 1259 | 1167 |
| 1260 // Import all nested message classes into this class's scope with typedefs. | 1168 // Import all nested message classes into this class's scope with typedefs. |
| 1261 for (int i = 0; i < descriptor_->nested_type_count(); i++) { | 1169 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1262 const Descriptor* nested_type = descriptor_->nested_type(i); | 1170 const Descriptor* nested_type = descriptor_->nested_type(i); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 printer->Print(" private:\n"); | 1208 printer->Print(" private:\n"); |
| 1301 printer->Indent(); | 1209 printer->Indent(); |
| 1302 | 1210 |
| 1303 | 1211 |
| 1304 for (int i = 0; i < descriptor_->field_count(); i++) { | 1212 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1305 if (!descriptor_->field(i)->is_repeated()) { | 1213 if (!descriptor_->field(i)->is_repeated()) { |
| 1306 // set_has_***() generated in all proto1/2 code and in oneofs (only) for | 1214 // set_has_***() generated in all proto1/2 code and in oneofs (only) for |
| 1307 // messages without true field presence. | 1215 // messages without true field presence. |
| 1308 if (HasFieldPresence(descriptor_->file()) || | 1216 if (HasFieldPresence(descriptor_->file()) || |
| 1309 descriptor_->field(i)->containing_oneof()) { | 1217 descriptor_->field(i)->containing_oneof()) { |
| 1310 printer->Print("void set_has_$name$();\n", "name", | 1218 printer->Print( |
| 1311 FieldName(descriptor_->field(i))); | 1219 "inline void set_has_$name$();\n", |
| 1220 "name", FieldName(descriptor_->field(i))); |
| 1312 } | 1221 } |
| 1313 // clear_has_***() generated only for non-oneof fields | 1222 // clear_has_***() generated only for non-oneof fields |
| 1314 // in proto1/2. | 1223 // in proto1/2. |
| 1315 if (!descriptor_->field(i)->containing_oneof() && | 1224 if (!descriptor_->field(i)->containing_oneof() && |
| 1316 HasFieldPresence(descriptor_->file())) { | 1225 HasFieldPresence(descriptor_->file())) { |
| 1317 printer->Print("void clear_has_$name$();\n", "name", | 1226 printer->Print( |
| 1318 FieldName(descriptor_->field(i))); | 1227 "inline void clear_has_$name$();\n", |
| 1228 "name", FieldName(descriptor_->field(i))); |
| 1319 } | 1229 } |
| 1320 } | 1230 } |
| 1321 } | 1231 } |
| 1322 printer->Print("\n"); | 1232 printer->Print("\n"); |
| 1323 | 1233 |
| 1324 // Generate oneof function declarations | 1234 // Generate oneof function declarations |
| 1325 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1235 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1326 printer->Print( | 1236 printer->Print( |
| 1327 "inline bool has_$oneof_name$() const;\n" | 1237 "inline bool has_$oneof_name$() const;\n" |
| 1328 "void clear_$oneof_name$();\n" | 1238 "void clear_$oneof_name$();\n" |
| 1329 "inline void clear_has_$oneof_name$();\n\n", | 1239 "inline void clear_has_$oneof_name$();\n\n", |
| 1330 "oneof_name", descriptor_->oneof_decl(i)->name()); | 1240 "oneof_name", descriptor_->oneof_decl(i)->name()); |
| 1331 } | 1241 } |
| 1332 | 1242 |
| 1333 if (HasGeneratedMethods(descriptor_->file(), options_) && | 1243 if (HasGeneratedMethods(descriptor_->file(), options_) && |
| 1334 !descriptor_->options().message_set_wire_format() && | 1244 !descriptor_->options().message_set_wire_format() && |
| 1335 num_required_fields_ > 1) { | 1245 num_required_fields_ > 1) { |
| 1336 printer->Print( | 1246 printer->Print( |
| 1337 "// helper for ByteSizeLong()\n" | 1247 "// helper for ByteSize()\n" |
| 1338 "size_t RequiredFieldsByteSizeFallback() const;\n\n"); | 1248 "int RequiredFieldsByteSizeFallback() const;\n\n"); |
| 1339 } | 1249 } |
| 1340 | 1250 |
| 1341 // Prepare decls for _cached_size_ and _has_bits_. Their position in the | 1251 // Prepare decls for _cached_size_ and _has_bits_. Their position in the |
| 1342 // output will be determined later. | 1252 // output will be determined later. |
| 1343 | 1253 |
| 1344 bool need_to_emit_cached_size = true; | 1254 bool need_to_emit_cached_size = true; |
| 1345 // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it. | 1255 // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it. |
| 1346 const string cached_size_decl = "mutable int _cached_size_;\n"; | 1256 const string cached_size_decl = "mutable int _cached_size_;\n"; |
| 1347 | 1257 |
| 1348 const size_t sizeof_has_bits = HasBitsSize(); | 1258 // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields. |
| 1259 size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4; |
| 1260 if (descriptor_->field_count() == 0) { |
| 1261 // Zero-size arrays aren't technically allowed, and MSVC in particular |
| 1262 // doesn't like them. We still need to declare these arrays to make |
| 1263 // other code compile. Since this is an uncommon case, we'll just declare |
| 1264 // them with size 1 and waste some space. Oh well. |
| 1265 sizeof_has_bits = 4; |
| 1266 } |
| 1349 const string has_bits_decl = sizeof_has_bits == 0 ? "" : | 1267 const string has_bits_decl = sizeof_has_bits == 0 ? "" : |
| 1350 "::google::protobuf::internal::HasBits<" + SimpleItoa(sizeof_has_bits / 4)
+ | 1268 "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4)
+ "];\n"; |
| 1351 "> _has_bits_;\n"; | 1269 |
| 1352 | 1270 |
| 1353 // To minimize padding, data members are divided into three sections: | 1271 // To minimize padding, data members are divided into three sections: |
| 1354 // (1) members assumed to align to 8 bytes | 1272 // (1) members assumed to align to 8 bytes |
| 1355 // (2) members corresponding to message fields, re-ordered to optimize | 1273 // (2) members corresponding to message fields, re-ordered to optimize |
| 1356 // alignment. | 1274 // alignment. |
| 1357 // (3) members assumed to align to 4 bytes. | 1275 // (3) members assumed to align to 4 bytes. |
| 1358 | 1276 |
| 1359 // Members assumed to align to 8 bytes: | 1277 // Members assumed to align to 8 bytes: |
| 1360 | 1278 |
| 1361 if (descriptor_->extension_range_count() > 0) { | 1279 if (descriptor_->extension_range_count() > 0) { |
| 1362 printer->Print( | 1280 printer->Print( |
| 1363 "::google::protobuf::internal::ExtensionSet _extensions_;\n" | 1281 "::google::protobuf::internal::ExtensionSet _extensions_;\n" |
| 1364 "\n"); | 1282 "\n"); |
| 1365 } | 1283 } |
| 1366 | 1284 |
| 1367 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 1285 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1368 printer->Print( | 1286 printer->Print( |
| 1369 "::google::protobuf::internal::InternalMetadataWithArena _internal_metadat
a_;\n"); | 1287 "::google::protobuf::internal::InternalMetadataWithArena _internal_metadat
a_;\n"); |
| 1370 } else { | 1288 } else { |
| 1371 printer->Print( | 1289 printer->Print( |
| 1372 "::google::protobuf::internal::InternalMetadataWithArenaLite " | 1290 "::google::protobuf::internal::ArenaStringPtr _unknown_fields_;\n" |
| 1373 "_internal_metadata_;\n"); | 1291 "::google::protobuf::Arena* _arena_ptr_;\n" |
| 1292 "\n"); |
| 1374 } | 1293 } |
| 1375 | 1294 |
| 1376 if (SupportsArenas(descriptor_)) { | 1295 if (SupportsArenas(descriptor_)) { |
| 1377 printer->Print( | 1296 printer->Print( |
| 1378 "friend class ::google::protobuf::Arena;\n" | 1297 "friend class ::google::protobuf::Arena;\n" |
| 1379 "typedef void InternalArenaConstructable_;\n" | 1298 "typedef void InternalArenaConstructable_;\n" |
| 1380 "typedef void DestructorSkippable_;\n"); | 1299 "typedef void DestructorSkippable_;\n"); |
| 1381 } | 1300 } |
| 1382 | 1301 |
| 1383 if (HasFieldPresence(descriptor_->file())) { | 1302 if (HasFieldPresence(descriptor_->file())) { |
| 1384 // _has_bits_ is frequently accessed, so to reduce code size and improve | 1303 // _has_bits_ is frequently accessed, so to reduce code size and improve |
| 1385 // speed, it should be close to the start of the object. But, try not to | 1304 // speed, it should be close to the start of the object. But, try not to |
| 1386 // waste space:_has_bits_ by itself always makes sense if its size is a | 1305 // waste space:_has_bits_ by itself always makes sense if its size is a |
| 1387 // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together | 1306 // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together |
| 1388 // will work well. | 1307 // will work well. |
| 1389 printer->Print(has_bits_decl.c_str()); | 1308 printer->Print(has_bits_decl.c_str()); |
| 1390 if ((sizeof_has_bits % 8) != 0) { | 1309 if ((sizeof_has_bits % 8) != 0) { |
| 1391 printer->Print(cached_size_decl.c_str()); | 1310 printer->Print(cached_size_decl.c_str()); |
| 1392 need_to_emit_cached_size = false; | 1311 need_to_emit_cached_size = false; |
| 1393 } | 1312 } |
| 1313 } else { |
| 1314 // Without field presence, we need another way to disambiguate the default |
| 1315 // instance, because the default instance's submessage fields (if any) store |
| 1316 // pointers to the default instances of the submessages even when they |
| 1317 // aren't present. Alternatives to this approach might be to (i) use a |
| 1318 // tagged pointer on all message fields, setting a tag bit for "not really |
| 1319 // present, just default instance"; or (ii) comparing |this| against the |
| 1320 // return value from GeneratedMessageFactory::GetPrototype() in all |
| 1321 // has_$field$() calls. However, both of these options are much more |
| 1322 // expensive (in code size and CPU overhead) than just checking a field in |
| 1323 // the message. Long-term, the best solution would be to rearchitect the |
| 1324 // default instance design not to store pointers to submessage default |
| 1325 // instances, and have reflection get those some other way; but that change |
| 1326 // would have too much impact on proto2. |
| 1327 printer->Print( |
| 1328 "bool _is_default_instance_;\n"); |
| 1394 } | 1329 } |
| 1395 | 1330 |
| 1396 // Field members: | 1331 // Field members: |
| 1397 | 1332 |
| 1333 // List fields which doesn't belong to any oneof |
| 1334 vector<const FieldDescriptor*> fields; |
| 1335 hash_map<string, int> fieldname_to_chunk; |
| 1336 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1337 if (!descriptor_->field(i)->containing_oneof()) { |
| 1338 const FieldDescriptor* field = descriptor_->field(i); |
| 1339 fields.push_back(field); |
| 1340 fieldname_to_chunk[FieldName(field)] = i / 8; |
| 1341 } |
| 1342 } |
| 1343 OptimizePadding(&fields); |
| 1398 // Emit some private and static members | 1344 // Emit some private and static members |
| 1399 for (int i = 0; i < optimized_order_.size(); ++i) { | 1345 runs_of_fields_ = vector< vector<string> >(1); |
| 1400 const FieldDescriptor* field = optimized_order_[i]; | 1346 for (int i = 0; i < fields.size(); ++i) { |
| 1347 const FieldDescriptor* field = fields[i]; |
| 1401 const FieldGenerator& generator = field_generators_.get(field); | 1348 const FieldGenerator& generator = field_generators_.get(field); |
| 1402 generator.GenerateStaticMembers(printer); | 1349 generator.GenerateStaticMembers(printer); |
| 1403 generator.GeneratePrivateMembers(printer); | 1350 generator.GeneratePrivateMembers(printer); |
| 1351 if (CanClearByZeroing(field)) { |
| 1352 const string& fieldname = FieldName(field); |
| 1353 if (!runs_of_fields_.back().empty() && |
| 1354 (fieldname_to_chunk[runs_of_fields_.back().back()] != |
| 1355 fieldname_to_chunk[fieldname])) { |
| 1356 runs_of_fields_.push_back(vector<string>()); |
| 1357 } |
| 1358 runs_of_fields_.back().push_back(fieldname); |
| 1359 } else if (!runs_of_fields_.back().empty()) { |
| 1360 runs_of_fields_.push_back(vector<string>()); |
| 1361 } |
| 1404 } | 1362 } |
| 1405 | 1363 |
| 1406 // For each oneof generate a union | 1364 // For each oneof generate a union |
| 1407 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1365 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1408 printer->Print( | 1366 printer->Print( |
| 1409 "union $camel_oneof_name$Union {\n" | 1367 "union $camel_oneof_name$Union {\n" |
| 1410 // explicit empty constructor is needed when union contains | 1368 // explicit empty constructor is needed when union contains |
| 1411 // ArenaStringPtr members for string fields. | 1369 // ArenaStringPtr members for string fields. |
| 1412 " $camel_oneof_name$Union() {}\n", | 1370 " $camel_oneof_name$Union() {}\n", |
| 1413 "camel_oneof_name", | 1371 "camel_oneof_name", |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1443 | 1401 |
| 1444 // Generate _any_metadata_ for the Any type. | 1402 // Generate _any_metadata_ for the Any type. |
| 1445 if (IsAnyMessage(descriptor_)) { | 1403 if (IsAnyMessage(descriptor_)) { |
| 1446 printer->Print(vars, | 1404 printer->Print(vars, |
| 1447 "::google::protobuf::internal::AnyMetadata _any_metadata_;\n"); | 1405 "::google::protobuf::internal::AnyMetadata _any_metadata_;\n"); |
| 1448 } | 1406 } |
| 1449 | 1407 |
| 1450 // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as | 1408 // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as |
| 1451 // friends so that they can access private static variables like | 1409 // friends so that they can access private static variables like |
| 1452 // default_instance_ and reflection_. | 1410 // default_instance_ and reflection_. |
| 1453 printer->Print("friend void $dllexport_decl$ $initdefaultsname$_impl();\n", | 1411 PrintHandlingOptionalStaticInitializers( |
| 1454 // Vars. | 1412 descriptor_->file(), options_, printer, |
| 1455 "dllexport_decl", options_.dllexport_decl, "initdefaultsname", | 1413 // With static initializers. |
| 1456 GlobalInitDefaultsName(descriptor_->file()->name())); | 1414 "friend void $dllexport_decl$ $adddescriptorsname$();\n", |
| 1457 printer->Print("friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", | 1415 // Without. |
| 1458 // Vars. | 1416 "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", |
| 1459 "dllexport_decl", options_.dllexport_decl, | 1417 // Vars. |
| 1460 "adddescriptorsname", | 1418 "dllexport_decl", options_.dllexport_decl, "adddescriptorsname", |
| 1461 GlobalAddDescriptorsName(descriptor_->file()->name())); | 1419 GlobalAddDescriptorsName(descriptor_->file()->name())); |
| 1462 | 1420 |
| 1463 printer->Print( | 1421 printer->Print( |
| 1464 "friend const ::google::protobuf::uint32* $offsetfunname$();\n" | 1422 "friend void $assigndescriptorsname$();\n" |
| 1465 "friend void $shutdownfilename$();\n" | 1423 "friend void $shutdownfilename$();\n" |
| 1466 "\n", | 1424 "\n", |
| 1467 "offsetfunname", GlobalOffsetTableName(descriptor_->file()->name()), | 1425 "assigndescriptorsname", |
| 1468 "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); | 1426 GlobalAssignDescriptorsName(descriptor_->file()->name()), |
| 1427 "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); |
| 1428 |
| 1429 printer->Print( |
| 1430 "void InitAsDefaultInstance();\n" |
| 1431 "static $classname$* default_instance_;\n", |
| 1432 "classname", classname_); |
| 1469 | 1433 |
| 1470 printer->Outdent(); | 1434 printer->Outdent(); |
| 1471 printer->Print("};"); | 1435 printer->Print(vars, "};"); |
| 1472 GOOGLE_DCHECK(!need_to_emit_cached_size); | 1436 GOOGLE_DCHECK(!need_to_emit_cached_size); |
| 1473 } | 1437 } |
| 1474 | 1438 |
| 1475 void MessageGenerator:: | 1439 void MessageGenerator:: |
| 1476 GenerateDependentInlineMethods(io::Printer* printer) { | 1440 GenerateDependentInlineMethods(io::Printer* printer) { |
| 1477 if (IsMapEntryMessage(descriptor_)) return; | 1441 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1478 for (int i = 0; i < descriptor_->field_count(); i++) { | 1442 // map entry message doesn't need inline methods. Since map entry message |
| 1479 if (descriptor_->field(i)->options().weak()) { | 1443 // cannot be a top level class, we just need to avoid calling |
| 1480 field_generators_.get(descriptor_->field(i)) | 1444 // GenerateInlineMethods here. |
| 1481 .GenerateDependentInlineAccessorDefinitions(printer); | 1445 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; |
| 1482 } | 1446 nested_generators_[i]->GenerateDependentInlineMethods(printer); |
| 1447 printer->Print(kThinSeparator); |
| 1448 printer->Print("\n"); |
| 1483 } | 1449 } |
| 1450 |
| 1484 GenerateDependentFieldAccessorDefinitions(printer); | 1451 GenerateDependentFieldAccessorDefinitions(printer); |
| 1485 } | 1452 } |
| 1486 | 1453 |
| 1487 void MessageGenerator:: | 1454 void MessageGenerator:: |
| 1488 GenerateInlineMethods(io::Printer* printer, bool is_inline) { | 1455 GenerateInlineMethods(io::Printer* printer, bool is_inline) { |
| 1489 if (IsMapEntryMessage(descriptor_)) return; | 1456 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1457 // map entry message doesn't need inline methods. Since map entry message |
| 1458 // cannot be a top level class, we just need to avoid calling |
| 1459 // GenerateInlineMethods here. |
| 1460 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; |
| 1461 nested_generators_[i]->GenerateInlineMethods(printer, is_inline); |
| 1462 printer->Print(kThinSeparator); |
| 1463 printer->Print("\n"); |
| 1464 } |
| 1465 |
| 1490 GenerateFieldAccessorDefinitions(printer, is_inline); | 1466 GenerateFieldAccessorDefinitions(printer, is_inline); |
| 1491 | 1467 |
| 1492 // Generate oneof_case() functions. | 1468 // Generate oneof_case() functions. |
| 1493 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1469 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1494 std::map<string, string> vars; | 1470 map<string, string> vars; |
| 1495 vars["class_name"] = classname_; | 1471 vars["class_name"] = classname_; |
| 1496 vars["camel_oneof_name"] = UnderscoresToCamelCase( | 1472 vars["camel_oneof_name"] = UnderscoresToCamelCase( |
| 1497 descriptor_->oneof_decl(i)->name(), true); | 1473 descriptor_->oneof_decl(i)->name(), true); |
| 1498 vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); | 1474 vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); |
| 1499 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); | 1475 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); |
| 1500 vars["inline"] = is_inline ? "inline " : ""; | 1476 vars["inline"] = is_inline ? "inline " : ""; |
| 1501 printer->Print( | 1477 printer->Print( |
| 1502 vars, | 1478 vars, |
| 1503 "$inline$" | 1479 "$inline$" |
| 1504 "$class_name$::$camel_oneof_name$Case $class_name$::" | 1480 "$class_name$::$camel_oneof_name$Case $class_name$::" |
| 1505 "$oneof_name$_case() const {\n" | 1481 "$oneof_name$_case() const {\n" |
| 1506 " return $class_name$::$camel_oneof_name$Case(" | 1482 " return $class_name$::$camel_oneof_name$Case(" |
| 1507 "_oneof_case_[$oneof_index$]);\n" | 1483 "_oneof_case_[$oneof_index$]);\n" |
| 1508 "}\n"); | 1484 "}\n"); |
| 1509 } | 1485 } |
| 1510 } | 1486 } |
| 1511 | 1487 |
| 1512 void MessageGenerator:: | 1488 void MessageGenerator:: |
| 1513 GenerateDescriptorDeclarations(io::Printer* printer) { | 1489 GenerateDescriptorDeclarations(io::Printer* printer) { |
| 1490 if (!IsMapEntryMessage(descriptor_)) { |
| 1491 printer->Print( |
| 1492 "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n" |
| 1493 "const ::google::protobuf::internal::GeneratedMessageReflection*\n" |
| 1494 " $name$_reflection_ = NULL;\n", |
| 1495 "name", classname_); |
| 1496 } else { |
| 1497 printer->Print( |
| 1498 "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n", |
| 1499 "name", classname_); |
| 1500 } |
| 1501 |
| 1514 // Generate oneof default instance for reflection usage. | 1502 // Generate oneof default instance for reflection usage. |
| 1515 if (descriptor_->oneof_decl_count() > 0) { | 1503 if (descriptor_->oneof_decl_count() > 0) { |
| 1516 printer->Print("struct $name$OneofInstance {\n", | 1504 printer->Print("struct $name$OneofInstance {\n", |
| 1517 "name", classname_); | 1505 "name", classname_); |
| 1518 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1506 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1519 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | 1507 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
| 1520 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); | 1508 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); |
| 1521 printer->Print(" "); | 1509 printer->Print(" "); |
| 1522 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || | 1510 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || |
| 1523 (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && | 1511 (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && |
| 1524 EffectiveStringCType(field) != FieldOptions::STRING)) { | 1512 EffectiveStringCType(field) != FieldOptions::STRING)) { |
| 1525 printer->Print("const "); | 1513 printer->Print("const "); |
| 1526 } | 1514 } |
| 1527 field_generators_.get(field).GeneratePrivateMembers(printer); | 1515 field_generators_.get(field).GeneratePrivateMembers(printer); |
| 1528 } | 1516 } |
| 1529 } | 1517 } |
| 1530 | 1518 |
| 1531 printer->Print("} $name$_default_oneof_instance_;\n", "name", classname_); | 1519 printer->Print("}* $name$_default_oneof_instance_ = NULL;\n", |
| 1520 "name", classname_); |
| 1521 } |
| 1522 |
| 1523 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1524 nested_generators_[i]->GenerateDescriptorDeclarations(printer); |
| 1525 } |
| 1526 |
| 1527 for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
| 1528 printer->Print( |
| 1529 "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", |
| 1530 "name", ClassName(descriptor_->enum_type(i), false)); |
| 1532 } | 1531 } |
| 1533 } | 1532 } |
| 1534 | 1533 |
| 1535 void MessageGenerator::GenerateSchema(io::Printer* printer, int offset, | 1534 void MessageGenerator:: |
| 1536 int has_offset) { | 1535 GenerateDescriptorInitializer(io::Printer* printer, int index) { |
| 1536 // TODO(kenton): Passing the index to this method is redundant; just use |
| 1537 // descriptor_->index() instead. |
| 1538 map<string, string> vars; |
| 1539 vars["classname"] = classname_; |
| 1540 vars["index"] = SimpleItoa(index); |
| 1541 |
| 1542 // Obtain the descriptor from the parent's descriptor. |
| 1543 if (descriptor_->containing_type() == NULL) { |
| 1544 printer->Print(vars, |
| 1545 "$classname$_descriptor_ = file->message_type($index$);\n"); |
| 1546 } else { |
| 1547 vars["parent"] = ClassName(descriptor_->containing_type(), false); |
| 1548 printer->Print(vars, |
| 1549 "$classname$_descriptor_ = " |
| 1550 "$parent$_descriptor_->nested_type($index$);\n"); |
| 1551 } |
| 1552 |
| 1537 if (IsMapEntryMessage(descriptor_)) return; | 1553 if (IsMapEntryMessage(descriptor_)) return; |
| 1538 | 1554 |
| 1539 std::map<string, string> vars; | 1555 // Generate the offsets. |
| 1556 GenerateOffsets(printer); |
| 1540 | 1557 |
| 1541 vars["classname"] = classname_; | 1558 const bool pass_pool_and_factory = false; |
| 1542 vars["offset"] = SimpleItoa(offset); | 1559 vars["fn"] = pass_pool_and_factory ? |
| 1543 vars["has_bits_offsets"] = HasFieldPresence(descriptor_->file()) | 1560 "new ::google::protobuf::internal::GeneratedMessageReflection" : |
| 1544 ? SimpleItoa(offset + has_offset) | 1561 "::google::protobuf::internal::GeneratedMessageReflection" |
| 1545 : "-1"; | 1562 "::NewGeneratedMessageReflection"; |
| 1563 // Construct the reflection object. |
| 1564 printer->Print(vars, |
| 1565 "$classname$_reflection_ =\n" |
| 1566 " $fn$(\n" |
| 1567 " $classname$_descriptor_,\n" |
| 1568 " $classname$::default_instance_,\n" |
| 1569 " $classname$_offsets_,\n"); |
| 1570 if (!HasFieldPresence(descriptor_->file())) { |
| 1571 // If we don't have field presence, then _has_bits_ does not exist. |
| 1572 printer->Print(vars, |
| 1573 " -1,\n"); |
| 1574 } else { |
| 1575 printer->Print(vars, |
| 1576 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[
0]),\n"); |
| 1577 } |
| 1578 |
| 1579 // Unknown field offset: either points to the unknown field set if embedded |
| 1580 // directly, or indicates that the unknown field set is stored as part of the |
| 1581 // internal metadata if not. |
| 1582 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1583 printer->Print(vars, |
| 1584 " -1,\n"); |
| 1585 } else { |
| 1586 printer->Print(vars, |
| 1587 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" |
| 1588 "$classname$, _unknown_fields_),\n"); |
| 1589 } |
| 1590 |
| 1591 if (descriptor_->extension_range_count() > 0) { |
| 1592 printer->Print(vars, |
| 1593 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" |
| 1594 "$classname$, _extensions_),\n"); |
| 1595 } else { |
| 1596 // No extensions. |
| 1597 printer->Print(vars, |
| 1598 " -1,\n"); |
| 1599 } |
| 1600 |
| 1601 if (descriptor_->oneof_decl_count() > 0) { |
| 1602 printer->Print(vars, |
| 1603 " $classname$_default_oneof_instance_,\n" |
| 1604 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" |
| 1605 "$classname$, _oneof_case_[0]),\n"); |
| 1606 } |
| 1607 |
| 1608 if (pass_pool_and_factory) { |
| 1609 printer->Print( |
| 1610 " ::google::protobuf::DescriptorPool::generated_pool(),\n"); |
| 1611 printer->Print(vars, |
| 1612 " ::google::protobuf::MessageFactory::generated_factory(
),\n"); |
| 1613 } |
| 1546 | 1614 |
| 1547 printer->Print(vars, | 1615 printer->Print(vars, |
| 1548 "{ $offset$, $has_bits_offsets$, sizeof($classname$)},\n"); | 1616 " sizeof($classname$),\n"); |
| 1617 |
| 1618 // Arena offset: either an offset to the metadata struct that contains the |
| 1619 // arena pointer and unknown field set (in a space-efficient way) if we use |
| 1620 // that implementation strategy, or an offset directly to the arena pointer if |
| 1621 // not (because e.g. we don't have an unknown field set). |
| 1622 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1623 printer->Print(vars, |
| 1624 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" |
| 1625 "$classname$, _internal_metadata_),\n"); |
| 1626 } else { |
| 1627 printer->Print(vars, |
| 1628 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" |
| 1629 "$classname$, _arena_),\n"); |
| 1630 } |
| 1631 |
| 1632 // is_default_instance_ offset. |
| 1633 if (HasFieldPresence(descriptor_->file())) { |
| 1634 printer->Print(vars, |
| 1635 " -1);\n"); |
| 1636 } else { |
| 1637 printer->Print(vars, |
| 1638 " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" |
| 1639 "$classname$, _is_default_instance_));\n"); |
| 1640 } |
| 1641 |
| 1642 // Handle nested types. |
| 1643 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1644 nested_generators_[i]->GenerateDescriptorInitializer(printer, i); |
| 1645 } |
| 1646 |
| 1647 for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
| 1648 enum_generators_[i]->GenerateDescriptorInitializer(printer, i); |
| 1649 } |
| 1549 } | 1650 } |
| 1550 | 1651 |
| 1551 void MessageGenerator:: | 1652 void MessageGenerator:: |
| 1552 GenerateTypeRegistrations(io::Printer* printer) { | 1653 GenerateTypeRegistrations(io::Printer* printer) { |
| 1553 // Register this message type with the message factory. | 1654 // Register this message type with the message factory. |
| 1554 if (IsMapEntryMessage(descriptor_)) { | 1655 if (!IsMapEntryMessage(descriptor_)) { |
| 1555 std::map<string, string> vars; | 1656 printer->Print( |
| 1657 "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n" |
| 1658 " $classname$_descriptor_, &$classname$::default_instance());\n", |
| 1659 "classname", classname_); |
| 1660 } |
| 1661 else { |
| 1662 map<string, string> vars; |
| 1556 CollectMapInfo(descriptor_, &vars); | 1663 CollectMapInfo(descriptor_, &vars); |
| 1557 vars["classname"] = classname_; | 1664 vars["classname"] = classname_; |
| 1558 | 1665 |
| 1559 const FieldDescriptor* val = descriptor_->FindFieldByName("value"); | 1666 const FieldDescriptor* val = descriptor_->FindFieldByName("value"); |
| 1560 if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 && | 1667 if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 && |
| 1561 val->type() == FieldDescriptor::TYPE_ENUM) { | 1668 val->type() == FieldDescriptor::TYPE_ENUM) { |
| 1562 const EnumValueDescriptor* default_value = val->default_value_enum(); | 1669 const EnumValueDescriptor* default_value = val->default_value_enum(); |
| 1563 vars["default_enum_value"] = Int32ToString(default_value->number()); | 1670 vars["default_enum_value"] = Int32ToString(default_value->number()); |
| 1564 } else { | 1671 } else { |
| 1565 vars["default_enum_value"] = "0"; | 1672 vars["default_enum_value"] = "0"; |
| 1566 } | 1673 } |
| 1567 | 1674 |
| 1568 vars["index_in_metadata"] = SimpleItoa(index_in_metadata_); | 1675 printer->Print(vars, |
| 1676 "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n" |
| 1677 " $classname$_descriptor_,\n" |
| 1678 " ::google::protobuf::internal::MapEntry<\n" |
| 1679 " $key$,\n" |
| 1680 " $val$,\n" |
| 1681 " $key_wire_type$,\n" |
| 1682 " $val_wire_type$,\n" |
| 1683 " $default_enum_value$>::CreateDefaultInstance(\n" |
| 1684 " $classname$_descriptor_));\n"); |
| 1685 } |
| 1569 | 1686 |
| 1570 printer->Print( | 1687 // Handle nested types. |
| 1571 vars, | 1688 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1572 "const ::google::protobuf::Descriptor* $classname$_descriptor = " | 1689 nested_generators_[i]->GenerateTypeRegistrations(printer); |
| 1573 "file_level_metadata[$index_in_metadata$].descriptor;\n" | |
| 1574 "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n
" | |
| 1575 " $classname$_descriptor,\n" | |
| 1576 " ::google::protobuf::internal::MapEntry<\n" | |
| 1577 " $key$,\n" | |
| 1578 " $val$,\n" | |
| 1579 " $key_wire_type$,\n" | |
| 1580 " $val_wire_type$,\n" | |
| 1581 " $default_enum_value$>::CreateDefaultInstance(\n" | |
| 1582 " $classname$_descriptor));\n"); | |
| 1583 } | 1690 } |
| 1584 } | 1691 } |
| 1585 | 1692 |
| 1586 void MessageGenerator:: | 1693 void MessageGenerator:: |
| 1587 GenerateDefaultInstanceAllocator(io::Printer* printer) { | 1694 GenerateDefaultInstanceAllocator(io::Printer* printer) { |
| 1588 if (IsMapEntryMessage(descriptor_)) return; | |
| 1589 | |
| 1590 // Construct the default instances of all fields, as they will be used | 1695 // Construct the default instances of all fields, as they will be used |
| 1591 // when creating the default instance of the entire message. | 1696 // when creating the default instance of the entire message. |
| 1592 for (int i = 0; i < descriptor_->field_count(); i++) { | 1697 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1593 field_generators_.get(descriptor_->field(i)) | 1698 field_generators_.get(descriptor_->field(i)) |
| 1594 .GenerateDefaultInstanceAllocator(printer); | 1699 .GenerateDefaultInstanceAllocator(printer); |
| 1595 } | 1700 } |
| 1596 | 1701 |
| 1702 if (IsMapEntryMessage(descriptor_)) return; |
| 1703 |
| 1597 // Construct the default instance. We can't call InitAsDefaultInstance() yet | 1704 // Construct the default instance. We can't call InitAsDefaultInstance() yet |
| 1598 // because we need to make sure all default instances that this one might | 1705 // because we need to make sure all default instances that this one might |
| 1599 // depend on are constructed first. | 1706 // depend on are constructed first. |
| 1600 printer->Print("_$classname$_default_instance_.DefaultConstruct();\n", | 1707 printer->Print( |
| 1601 "classname", classname_); | 1708 "$classname$::default_instance_ = new $classname$();\n", |
| 1709 "classname", classname_); |
| 1710 |
| 1711 if ((descriptor_->oneof_decl_count() > 0) && |
| 1712 HasDescriptorMethods(descriptor_->file(), options_)) { |
| 1713 printer->Print( |
| 1714 "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n", |
| 1715 "classname", classname_); |
| 1716 } |
| 1717 |
| 1718 // Handle nested types. |
| 1719 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1720 nested_generators_[i]->GenerateDefaultInstanceAllocator(printer); |
| 1721 } |
| 1722 |
| 1602 } | 1723 } |
| 1603 | 1724 |
| 1604 void MessageGenerator:: | 1725 void MessageGenerator:: |
| 1605 GenerateDefaultInstanceInitializer(io::Printer* printer) { | 1726 GenerateDefaultInstanceInitializer(io::Printer* printer) { |
| 1606 if (IsMapEntryMessage(descriptor_)) return; | 1727 printer->Print( |
| 1728 "$classname$::default_instance_->InitAsDefaultInstance();\n", |
| 1729 "classname", classname_); |
| 1607 | 1730 |
| 1608 // The default instance needs all of its embedded message pointers | 1731 // Register extensions. |
| 1609 // cross-linked to other default instances. We can't do this initialization | 1732 for (int i = 0; i < descriptor_->extension_count(); i++) { |
| 1610 // in the constructor because some other default instances may not have been | 1733 extension_generators_[i]->GenerateRegistration(printer); |
| 1611 // constructed yet at that time. | 1734 } |
| 1612 // TODO(kenton): Maybe all message fields (even for non-default messages) | |
| 1613 // should be initialized to point at default instances rather than NULL? | |
| 1614 for (int i = 0; i < descriptor_->field_count(); i++) { | |
| 1615 const FieldDescriptor* field = descriptor_->field(i); | |
| 1616 | 1735 |
| 1617 if (!field->is_repeated() && | 1736 // Handle nested types. |
| 1618 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && | 1737 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1619 (field->containing_oneof() == NULL || | 1738 // map entry message doesn't need to initialize default instance manually. |
| 1620 HasDescriptorMethods(descriptor_->file(), options_))) { | 1739 // Since map entry message cannot be a top level class, we just need to |
| 1621 string name; | 1740 // avoid calling DefaultInstanceInitializer here. |
| 1622 if (field->containing_oneof()) { | 1741 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; |
| 1623 name = classname_ + "_default_oneof_instance_."; | 1742 nested_generators_[i]->GenerateDefaultInstanceInitializer(printer); |
| 1624 } else { | |
| 1625 name = "_" + classname_ + "_default_instance_.get_mutable()->"; | |
| 1626 } | |
| 1627 name += FieldName(field); | |
| 1628 printer->Print( | |
| 1629 "$name$_ = const_cast< $type$*>(\n" | |
| 1630 " $type$::internal_default_instance());\n", | |
| 1631 // Vars. | |
| 1632 "name", name, "type", FieldMessageTypeName(field)); | |
| 1633 } else if (field->containing_oneof() && | |
| 1634 HasDescriptorMethods(descriptor_->file(), options_)) { | |
| 1635 field_generators_.get(descriptor_->field(i)) | |
| 1636 .GenerateConstructorCode(printer); | |
| 1637 } | |
| 1638 } | 1743 } |
| 1639 } | 1744 } |
| 1640 | 1745 |
| 1641 void MessageGenerator:: | 1746 void MessageGenerator:: |
| 1642 GenerateShutdownCode(io::Printer* printer) { | 1747 GenerateShutdownCode(io::Printer* printer) { |
| 1643 if (IsMapEntryMessage(descriptor_)) return; | 1748 printer->Print( |
| 1644 | 1749 "delete $classname$::default_instance_;\n", |
| 1645 printer->Print("_$classname$_default_instance_.Shutdown();\n", "classname", | 1750 "classname", classname_); |
| 1646 classname_); | |
| 1647 | 1751 |
| 1648 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 1752 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
| 1649 printer->Print("delete file_level_metadata[$index$].reflection;\n", "index", | 1753 if (descriptor_->oneof_decl_count() > 0) { |
| 1650 SimpleItoa(index_in_metadata_)); | 1754 printer->Print( |
| 1755 "delete $classname$_default_oneof_instance_;\n", |
| 1756 "classname", classname_); |
| 1757 } |
| 1758 printer->Print( |
| 1759 "delete $classname$_reflection_;\n", |
| 1760 "classname", classname_); |
| 1651 } | 1761 } |
| 1652 | 1762 |
| 1653 // Handle default instances of fields. | 1763 // Handle default instances of fields. |
| 1654 for (int i = 0; i < descriptor_->field_count(); i++) { | 1764 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1655 field_generators_.get(descriptor_->field(i)) | 1765 field_generators_.get(descriptor_->field(i)) |
| 1656 .GenerateShutdownCode(printer); | 1766 .GenerateShutdownCode(printer); |
| 1657 } | 1767 } |
| 1768 |
| 1769 // Handle nested types. |
| 1770 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1771 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; |
| 1772 nested_generators_[i]->GenerateShutdownCode(printer); |
| 1773 } |
| 1658 } | 1774 } |
| 1659 | 1775 |
| 1660 void MessageGenerator:: | 1776 void MessageGenerator:: |
| 1661 GenerateClassMethods(io::Printer* printer) { | 1777 GenerateClassMethods(io::Printer* printer) { |
| 1662 if (IsMapEntryMessage(descriptor_)) return; | |
| 1663 | |
| 1664 // mutable_unknown_fields wrapper function for LazyStringOutputStream | 1778 // mutable_unknown_fields wrapper function for LazyStringOutputStream |
| 1665 // callback. | 1779 // callback. |
| 1666 if (PreserveUnknownFields(descriptor_) && | 1780 if (PreserveUnknownFields(descriptor_) && |
| 1667 !UseUnknownFieldSet(descriptor_->file(), options_)) { | 1781 !UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1668 printer->Print( | 1782 printer->Print( |
| 1669 "static ::std::string* MutableUnknownFieldsFor$classname$(\n" | 1783 "static ::std::string* MutableUnknownFieldsFor$classname$(\n" |
| 1670 " $classname$* ptr) {\n" | 1784 " $classname$* ptr) {\n" |
| 1671 " return ptr->mutable_unknown_fields();\n" | 1785 " return ptr->mutable_unknown_fields();\n" |
| 1672 "}\n" | 1786 "}\n" |
| 1673 "\n", | 1787 "\n", |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1684 " _any_metadata_.PackFrom(message, type_url_prefix);\n" | 1798 " _any_metadata_.PackFrom(message, type_url_prefix);\n" |
| 1685 "}\n" | 1799 "}\n" |
| 1686 "\n" | 1800 "\n" |
| 1687 "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\
n" | 1801 "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\
n" |
| 1688 " return _any_metadata_.UnpackTo(message);\n" | 1802 " return _any_metadata_.UnpackTo(message);\n" |
| 1689 "}\n" | 1803 "}\n" |
| 1690 "\n", | 1804 "\n", |
| 1691 "classname", classname_); | 1805 "classname", classname_); |
| 1692 } | 1806 } |
| 1693 | 1807 |
| 1808 for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
| 1809 enum_generators_[i]->GenerateMethods(printer); |
| 1810 } |
| 1811 |
| 1812 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 1813 // map entry message doesn't need class methods. Since map entry message |
| 1814 // cannot be a top level class, we just need to avoid calling |
| 1815 // GenerateClassMethods here. |
| 1816 if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; |
| 1817 nested_generators_[i]->GenerateClassMethods(printer); |
| 1818 printer->Print("\n"); |
| 1819 printer->Print(kThinSeparator); |
| 1820 printer->Print("\n"); |
| 1821 } |
| 1822 |
| 1694 // Generate non-inline field definitions. | 1823 // Generate non-inline field definitions. |
| 1695 for (int i = 0; i < descriptor_->field_count(); i++) { | 1824 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1696 field_generators_.get(descriptor_->field(i)) | 1825 field_generators_.get(descriptor_->field(i)) |
| 1697 .GenerateNonInlineAccessorDefinitions(printer); | 1826 .GenerateNonInlineAccessorDefinitions(printer); |
| 1698 } | 1827 } |
| 1699 | 1828 |
| 1700 // Generate field number constants. | 1829 // Generate field number constants. |
| 1701 printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); | 1830 printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); |
| 1702 for (int i = 0; i < descriptor_->field_count(); i++) { | 1831 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1703 const FieldDescriptor *field = descriptor_->field(i); | 1832 const FieldDescriptor *field = descriptor_->field(i); |
| 1704 printer->Print( | 1833 printer->Print( |
| 1705 "const int $classname$::$constant_name$;\n", | 1834 "const int $classname$::$constant_name$;\n", |
| 1706 "classname", ClassName(FieldScope(field), false), | 1835 "classname", ClassName(FieldScope(field), false), |
| 1707 "constant_name", FieldConstantName(field)); | 1836 "constant_name", FieldConstantName(field)); |
| 1708 } | 1837 } |
| 1709 printer->Print( | 1838 printer->Print( |
| 1710 "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" | 1839 "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" |
| 1711 "\n"); | 1840 "\n"); |
| 1712 | 1841 |
| 1842 // Define extension identifiers. |
| 1843 for (int i = 0; i < descriptor_->extension_count(); i++) { |
| 1844 extension_generators_[i]->GenerateDefinition(printer); |
| 1845 } |
| 1846 |
| 1713 GenerateStructors(printer); | 1847 GenerateStructors(printer); |
| 1714 printer->Print("\n"); | 1848 printer->Print("\n"); |
| 1715 | 1849 |
| 1716 if (descriptor_->oneof_decl_count() > 0) { | 1850 if (descriptor_->oneof_decl_count() > 0) { |
| 1717 GenerateOneofClear(printer); | 1851 GenerateOneofClear(printer); |
| 1718 printer->Print("\n"); | 1852 printer->Print("\n"); |
| 1719 } | 1853 } |
| 1720 | 1854 |
| 1721 if (HasGeneratedMethods(descriptor_->file(), options_)) { | 1855 if (HasGeneratedMethods(descriptor_->file(), options_)) { |
| 1722 GenerateClear(printer); | 1856 GenerateClear(printer); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1744 | 1878 |
| 1745 GenerateIsInitialized(printer); | 1879 GenerateIsInitialized(printer); |
| 1746 printer->Print("\n"); | 1880 printer->Print("\n"); |
| 1747 } | 1881 } |
| 1748 | 1882 |
| 1749 GenerateSwap(printer); | 1883 GenerateSwap(printer); |
| 1750 printer->Print("\n"); | 1884 printer->Print("\n"); |
| 1751 | 1885 |
| 1752 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 1886 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
| 1753 printer->Print( | 1887 printer->Print( |
| 1754 "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" | 1888 "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" |
| 1755 " protobuf_AssignDescriptorsOnce();\n" | 1889 " protobuf_AssignDescriptorsOnce();\n" |
| 1756 " return file_level_metadata[$index$];\n" | 1890 " ::google::protobuf::Metadata metadata;\n" |
| 1757 "}\n" | 1891 " metadata.descriptor = $classname$_descriptor_;\n" |
| 1758 "\n", | 1892 " metadata.reflection = $classname$_reflection_;\n" |
| 1759 "classname", classname_, "index", SimpleItoa(index_in_metadata_)); | 1893 " return metadata;\n" |
| 1894 "}\n" |
| 1895 "\n", |
| 1896 "classname", classname_); |
| 1760 } else { | 1897 } else { |
| 1761 printer->Print( | 1898 printer->Print( |
| 1762 "::std::string $classname$::GetTypeName() const {\n" | 1899 "::std::string $classname$::GetTypeName() const {\n" |
| 1763 " return \"$type_name$\";\n" | 1900 " return \"$type_name$\";\n" |
| 1764 "}\n" | 1901 "}\n" |
| 1765 "\n", | 1902 "\n", |
| 1766 "classname", classname_, | 1903 "classname", classname_, |
| 1767 "type_name", descriptor_->full_name()); | 1904 "type_name", descriptor_->full_name()); |
| 1768 } | 1905 } |
| 1769 | 1906 |
| 1770 } | 1907 } |
| 1771 | 1908 |
| 1772 std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( | 1909 void MessageGenerator:: |
| 1773 io::Printer* printer) { | 1910 GenerateOffsets(io::Printer* printer) { |
| 1774 if (IsMapEntryMessage(descriptor_)) return std::make_pair(0, 0); | 1911 printer->Print("static const int $classname$_offsets_[$field_count$] = {\n", |
| 1775 std::map<string, string> variables; | 1912 "classname", classname_, "field_count", |
| 1776 variables["classname"] = classname_; | 1913 SimpleItoa(std::max(1, descriptor_->field_count() + |
| 1914 descriptor_->oneof_decl_count()))); |
| 1915 printer->Indent(); |
| 1777 | 1916 |
| 1778 if (HasFieldPresence(descriptor_->file())) { | |
| 1779 printer->Print( | |
| 1780 variables, | |
| 1781 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_)
,\n"); | |
| 1782 } else { | |
| 1783 printer->Print("~0u, // no _has_bits_\n"); | |
| 1784 } | |
| 1785 printer->Print(variables, | |
| 1786 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " | |
| 1787 "_internal_metadata_),\n"); | |
| 1788 if (descriptor_->extension_range_count() > 0) { | |
| 1789 printer->Print( | |
| 1790 variables, | |
| 1791 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _extensions
_),\n"); | |
| 1792 } else { | |
| 1793 printer->Print("~0u, // no _extensions_\n"); | |
| 1794 } | |
| 1795 if (descriptor_->oneof_decl_count() > 0) { | |
| 1796 printer->Print(variables, | |
| 1797 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$,
" | |
| 1798 "_oneof_case_[0]),\n"); | |
| 1799 } else { | |
| 1800 printer->Print("~0u, // no _oneof_case_\n"); | |
| 1801 } | |
| 1802 | |
| 1803 const int kNumGenericOffsets = 4; // the number of fixed offsets above | |
| 1804 const size_t offsets = kNumGenericOffsets + | |
| 1805 descriptor_->field_count() + | |
| 1806 descriptor_->oneof_decl_count(); | |
| 1807 size_t entries = offsets; | |
| 1808 for (int i = 0; i < descriptor_->field_count(); i++) { | 1917 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1809 const FieldDescriptor* field = descriptor_->field(i); | 1918 const FieldDescriptor* field = descriptor_->field(i); |
| 1810 if (field->containing_oneof()) { | 1919 if (field->containing_oneof()) { |
| 1811 printer->Print( | 1920 printer->Print( |
| 1812 "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" | 1921 "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" |
| 1813 "(&$classname$_default_oneof_instance_), $name$_),\n", | 1922 "$classname$_default_oneof_instance_, $name$_),\n", |
| 1814 "classname", classname_, "name", FieldName(field)); | 1923 "classname", classname_, |
| 1924 "name", FieldName(field)); |
| 1815 } else { | 1925 } else { |
| 1816 printer->Print( | 1926 printer->Print( |
| 1817 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " | 1927 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " |
| 1818 "$name$_),\n", | 1928 "$name$_),\n", |
| 1819 "classname", classname_, | 1929 "classname", classname_, |
| 1820 "name", FieldName(field)); | 1930 "name", FieldName(field)); |
| 1821 } | 1931 } |
| 1822 } | 1932 } |
| 1823 | 1933 |
| 1824 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1934 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1825 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); | 1935 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); |
| 1826 printer->Print( | 1936 printer->Print( |
| 1827 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", | 1937 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", |
| 1828 "classname", classname_, | 1938 "classname", classname_, |
| 1829 "name", oneof->name()); | 1939 "name", oneof->name()); |
| 1830 } | 1940 } |
| 1831 | 1941 |
| 1832 if (HasFieldPresence(descriptor_->file())) { | 1942 printer->Outdent(); |
| 1833 entries += has_bit_indices_.size(); | 1943 printer->Print("};\n"); |
| 1834 for (int i = 0; i < has_bit_indices_.size(); i++) { | |
| 1835 printer->Print("$index$,\n", "index", SimpleItoa(has_bit_indices_[i])); | |
| 1836 } | |
| 1837 } | |
| 1838 | |
| 1839 return std::make_pair(entries, offsets); | |
| 1840 } | 1944 } |
| 1841 | 1945 |
| 1842 void MessageGenerator:: | 1946 void MessageGenerator:: |
| 1843 GenerateSharedConstructorCode(io::Printer* printer) { | 1947 GenerateSharedConstructorCode(io::Printer* printer) { |
| 1844 printer->Print( | 1948 printer->Print( |
| 1845 "void $classname$::SharedCtor() {\n", | 1949 "void $classname$::SharedCtor() {\n", |
| 1846 "classname", classname_); | 1950 "classname", classname_); |
| 1847 printer->Indent(); | 1951 printer->Indent(); |
| 1848 | 1952 |
| 1849 bool need_to_clear_cached_size = true; | 1953 if (!HasFieldPresence(descriptor_->file())) { |
| 1850 // We reproduce the logic used for laying out _cached_sized_ in the class | 1954 printer->Print( |
| 1851 // definition, as to initialize it in-order. | 1955 " _is_default_instance_ = false;\n"); |
| 1852 if (HasFieldPresence(descriptor_->file()) && | |
| 1853 (HasBitsSize() % 8) != 0) { | |
| 1854 printer->Print("_cached_size_ = 0;\n"); | |
| 1855 need_to_clear_cached_size = false; | |
| 1856 } | 1956 } |
| 1857 | 1957 |
| 1858 // TODO(gerbens) Clean this hack, and why do i need a reference to a pointer?? | 1958 printer->Print(StrCat( |
| 1859 for (int i = 0; i < descriptor_->nested_type_count(); i++) { | 1959 uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", |
| 1860 if (HasDescriptorMethods(descriptor_->file(), options_) && | 1960 "_cached_size_ = 0;\n").c_str()); |
| 1861 IsMapEntryMessage(descriptor_->nested_type(i))) { | 1961 |
| 1862 printer->Print( | 1962 if (PreserveUnknownFields(descriptor_) && |
| 1863 "const ::google::protobuf::Descriptor*& $type$_descriptor = " | 1963 !UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 1864 "file_level_metadata[$index$].descriptor;\n", | 1964 printer->Print( |
| 1865 "type", ClassName(descriptor_->nested_type(i), false), "index", | 1965 "_unknown_fields_.UnsafeSetDefault(\n" |
| 1866 SimpleItoa(nested_generators_[i]->index_in_metadata_)); | 1966 " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); |
| 1967 } |
| 1968 |
| 1969 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1970 if (!descriptor_->field(i)->containing_oneof()) { |
| 1971 field_generators_.get(descriptor_->field(i)) |
| 1972 .GenerateConstructorCode(printer); |
| 1867 } | 1973 } |
| 1868 } | 1974 } |
| 1869 | 1975 |
| 1870 std::vector<bool> processed(optimized_order_.size(), false); | 1976 if (HasFieldPresence(descriptor_->file())) { |
| 1871 GenerateConstructorBody(printer, processed, false); | 1977 printer->Print( |
| 1978 "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); |
| 1979 } |
| 1872 | 1980 |
| 1873 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1981 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1874 printer->Print( | 1982 printer->Print( |
| 1875 "clear_has_$oneof_name$();\n", | 1983 "clear_has_$oneof_name$();\n", |
| 1876 "oneof_name", descriptor_->oneof_decl(i)->name()); | 1984 "oneof_name", descriptor_->oneof_decl(i)->name()); |
| 1877 } | 1985 } |
| 1878 | 1986 |
| 1879 if (need_to_clear_cached_size) { | |
| 1880 printer->Print("_cached_size_ = 0;\n"); | |
| 1881 } | |
| 1882 | |
| 1883 printer->Outdent(); | 1987 printer->Outdent(); |
| 1884 printer->Print("}\n\n"); | 1988 printer->Print("}\n\n"); |
| 1885 } | 1989 } |
| 1886 | 1990 |
| 1887 void MessageGenerator:: | 1991 void MessageGenerator:: |
| 1888 GenerateSharedDestructorCode(io::Printer* printer) { | 1992 GenerateSharedDestructorCode(io::Printer* printer) { |
| 1889 printer->Print( | 1993 printer->Print( |
| 1890 "void $classname$::SharedDtor() {\n", | 1994 "void $classname$::SharedDtor() {\n", |
| 1891 "classname", classname_); | 1995 "classname", classname_); |
| 1892 printer->Indent(); | 1996 printer->Indent(); |
| 1893 if (SupportsArenas(descriptor_)) { | 1997 if (SupportsArenas(descriptor_)) { |
| 1894 // Do nothing when the message is allocated in an arena. | 1998 // Do nothing when the message is allocated in an arena. |
| 1895 printer->Print( | 1999 printer->Print( |
| 1896 "::google::protobuf::Arena* arena = GetArenaNoVirtual();\n" | 2000 "if (GetArenaNoVirtual() != NULL) {\n" |
| 1897 "if (arena != NULL) {\n" | |
| 1898 " return;\n" | 2001 " return;\n" |
| 1899 "}\n" | 2002 "}\n" |
| 1900 "\n"); | 2003 "\n"); |
| 1901 } | 2004 } |
| 1902 | 2005 |
| 2006 // Write the desctructor for _unknown_fields_ in lite runtime. |
| 2007 if (PreserveUnknownFields(descriptor_) && |
| 2008 !UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2009 if (SupportsArenas(descriptor_)) { |
| 2010 printer->Print( |
| 2011 "_unknown_fields_.Destroy(\n" |
| 2012 " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" |
| 2013 " GetArenaNoVirtual());\n"); |
| 2014 } else { |
| 2015 printer->Print( |
| 2016 "_unknown_fields_.DestroyNoArena(\n" |
| 2017 " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
); |
| 2018 } |
| 2019 } |
| 2020 |
| 1903 // Write the destructors for each field except oneof members. | 2021 // Write the destructors for each field except oneof members. |
| 1904 // optimized_order_ does not contain oneof fields. | 2022 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1905 for (int i = 0; i < optimized_order_.size(); i++) { | 2023 if (!descriptor_->field(i)->containing_oneof()) { |
| 1906 const FieldDescriptor* field = optimized_order_[i]; | 2024 field_generators_.get(descriptor_->field(i)) |
| 1907 field_generators_.get(field).GenerateDestructorCode(printer); | 2025 .GenerateDestructorCode(printer); |
| 2026 } |
| 1908 } | 2027 } |
| 1909 | 2028 |
| 1910 // Generate code to destruct oneofs. Clearing should do the work. | 2029 // Generate code to destruct oneofs. Clearing should do the work. |
| 1911 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 2030 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1912 printer->Print( | 2031 printer->Print( |
| 1913 "if (has_$oneof_name$()) {\n" | 2032 "if (has_$oneof_name$()) {\n" |
| 1914 " clear_$oneof_name$();\n" | 2033 " clear_$oneof_name$();\n" |
| 1915 "}\n", | 2034 "}\n", |
| 1916 "oneof_name", descriptor_->oneof_decl(i)->name()); | 2035 "oneof_name", descriptor_->oneof_decl(i)->name()); |
| 1917 } | 2036 } |
| 1918 | 2037 |
| 2038 PrintHandlingOptionalStaticInitializers( |
| 2039 descriptor_->file(), options_, printer, |
| 2040 // With static initializers. |
| 2041 "if (this != default_instance_) {\n", |
| 2042 // Without. |
| 2043 "if (this != &default_instance()) {\n"); |
| 2044 |
| 2045 // We need to delete all embedded messages. |
| 2046 // TODO(kenton): If we make unset messages point at default instances |
| 2047 // instead of NULL, then it would make sense to move this code into |
| 2048 // MessageFieldGenerator::GenerateDestructorCode(). |
| 2049 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 2050 const FieldDescriptor* field = descriptor_->field(i); |
| 2051 |
| 2052 if (!field->is_repeated() && |
| 2053 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
| 2054 // Skip oneof members |
| 2055 if (!field->containing_oneof()) { |
| 2056 printer->Print( |
| 2057 " delete $name$_;\n", |
| 2058 "name", FieldName(field)); |
| 2059 } |
| 2060 } |
| 2061 } |
| 2062 |
| 1919 printer->Outdent(); | 2063 printer->Outdent(); |
| 1920 printer->Print( | 2064 printer->Print( |
| 2065 " }\n" |
| 1921 "}\n" | 2066 "}\n" |
| 1922 "\n"); | 2067 "\n"); |
| 1923 } | 2068 } |
| 1924 | 2069 |
| 1925 void MessageGenerator:: | 2070 void MessageGenerator:: |
| 1926 GenerateArenaDestructorCode(io::Printer* printer) { | 2071 GenerateArenaDestructorCode(io::Printer* printer) { |
| 1927 // Generate the ArenaDtor() method. Track whether any fields actually produced | 2072 // Generate the ArenaDtor() method. Track whether any fields actually produced |
| 1928 // code that needs to be called. | 2073 // code that needs to be called. |
| 1929 printer->Print( | 2074 printer->Print( |
| 1930 "void $classname$::ArenaDtor(void* object) {\n", | 2075 "void $classname$::ArenaDtor(void* object) {\n", |
| 1931 "classname", classname_); | 2076 "classname", classname_); |
| 1932 printer->Indent(); | 2077 printer->Indent(); |
| 1933 | 2078 |
| 1934 // This code is placed inside a static method, rather than an ordinary one, | 2079 // This code is placed inside a static method, rather than an ordinary one, |
| 1935 // since that simplifies Arena's destructor list (ordinary function pointers | 2080 // since that simplifies Arena's destructor list (ordinary function pointers |
| 1936 // rather than member function pointers). _this is the object being | 2081 // rather than member function pointers). _this is the object being |
| 1937 // destructed. | 2082 // destructed. |
| 1938 printer->Print( | 2083 printer->Print( |
| 1939 "$classname$* _this = reinterpret_cast< $classname$* >(object);\n" | 2084 "$classname$* _this = reinterpret_cast< $classname$* >(object);\n" |
| 1940 // avoid an "unused variable" warning in case no fields have dtor code. | 2085 // avoid an "unused variable" warning in case no fields have dtor code. |
| 1941 "(void)_this;\n", | 2086 "(void)_this;\n", |
| 1942 "classname", classname_); | 2087 "classname", classname_); |
| 1943 | 2088 |
| 1944 bool need_registration = false; | 2089 bool need_registration = false; |
| 1945 // Process non-oneof fields first. | 2090 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1946 for (int i = 0; i < optimized_order_.size(); i++) { | 2091 if (field_generators_.get(descriptor_->field(i)) |
| 1947 const FieldDescriptor* field = optimized_order_[i]; | |
| 1948 if (field_generators_.get(field) | |
| 1949 .GenerateArenaDestructorCode(printer)) { | 2092 .GenerateArenaDestructorCode(printer)) { |
| 1950 need_registration = true; | 2093 need_registration = true; |
| 1951 } | 2094 } |
| 1952 } | 2095 } |
| 1953 | |
| 1954 // Process oneof fields. | |
| 1955 // | |
| 1956 // Note: As of 10/5/2016, GenerateArenaDestructorCode does not emit anything | |
| 1957 // and returns false for oneof fields. | |
| 1958 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | |
| 1959 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); | |
| 1960 | |
| 1961 for (int j = 0; j < oneof->field_count(); j++) { | |
| 1962 const FieldDescriptor* field = oneof->field(j); | |
| 1963 if (field_generators_.get(field) | |
| 1964 .GenerateArenaDestructorCode(printer)) { | |
| 1965 need_registration = true; | |
| 1966 } | |
| 1967 } | |
| 1968 } | |
| 1969 | |
| 1970 printer->Outdent(); | 2096 printer->Outdent(); |
| 1971 printer->Print( | 2097 printer->Print( |
| 1972 "}\n"); | 2098 "}\n"); |
| 1973 | 2099 |
| 1974 if (need_registration) { | 2100 if (need_registration) { |
| 1975 printer->Print( | 2101 printer->Print( |
| 1976 "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* a
rena) {\n" | 2102 "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* a
rena) {\n" |
| 1977 " if (arena != NULL) {\n" | 2103 " if (arena != NULL) {\n" |
| 1978 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" | 2104 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" |
| 1979 " }\n" | 2105 " }\n" |
| 1980 "}\n", | 2106 "}\n", |
| 1981 "classname", classname_); | 2107 "classname", classname_); |
| 1982 } else { | 2108 } else { |
| 1983 printer->Print( | 2109 printer->Print( |
| 1984 "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {
\n" | 2110 "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {
\n" |
| 1985 "}\n", | 2111 "}\n", |
| 1986 "classname", classname_); | 2112 "classname", classname_); |
| 1987 } | 2113 } |
| 1988 } | 2114 } |
| 1989 | 2115 |
| 1990 void MessageGenerator::GenerateConstructorBody(io::Printer* printer, | |
| 1991 std::vector<bool> processed, | |
| 1992 bool copy_constructor) const { | |
| 1993 const FieldDescriptor* last_start = NULL; | |
| 1994 // RunMap maps from fields that start each run to the number of fields in that | |
| 1995 // run. This is optimized for the common case that there are very few runs in | |
| 1996 // a message and that most of the eligible fields appear together. | |
| 1997 typedef hash_map<const FieldDescriptor*, size_t> RunMap; | |
| 1998 RunMap runs; | |
| 1999 | |
| 2000 for (int i = 0; i < optimized_order_.size(); ++i) { | |
| 2001 const FieldDescriptor* field = optimized_order_[i]; | |
| 2002 if ((copy_constructor && IsPOD(field)) || | |
| 2003 (!copy_constructor && CanConstructByZeroing(field, options_))) { | |
| 2004 if (last_start == NULL) { | |
| 2005 last_start = field; | |
| 2006 } | |
| 2007 | |
| 2008 runs[last_start]++; | |
| 2009 } else { | |
| 2010 last_start = NULL; | |
| 2011 } | |
| 2012 } | |
| 2013 | |
| 2014 string pod_template; | |
| 2015 if (copy_constructor) { | |
| 2016 pod_template = | |
| 2017 "::memcpy(&$first$_, &from.$first$_,\n" | |
| 2018 " reinterpret_cast<char*>(&$last$_) -\n" | |
| 2019 " reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n"; | |
| 2020 } else { | |
| 2021 pod_template = | |
| 2022 "::memset(&$first$_, 0, reinterpret_cast<char*>(&$last$_) -\n" | |
| 2023 " reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n"; | |
| 2024 } | |
| 2025 | |
| 2026 for (int i = 0; i < optimized_order_.size(); ++i) { | |
| 2027 if (processed[i]) { | |
| 2028 continue; | |
| 2029 } | |
| 2030 | |
| 2031 const FieldDescriptor* field = optimized_order_[i]; | |
| 2032 RunMap::const_iterator it = runs.find(field); | |
| 2033 | |
| 2034 // We only apply the memset technique to runs of more than one field, as | |
| 2035 // assignment is better than memset for generated code clarity. | |
| 2036 if (it != runs.end() && it->second > 1) { | |
| 2037 // Use a memset, then skip run_length fields. | |
| 2038 const size_t run_length = it->second; | |
| 2039 const string first_field_name = FieldName(field); | |
| 2040 const string last_field_name = | |
| 2041 FieldName(optimized_order_[i + run_length - 1]); | |
| 2042 | |
| 2043 printer->Print(pod_template.c_str(), | |
| 2044 "first", first_field_name, | |
| 2045 "last", last_field_name); | |
| 2046 | |
| 2047 i += run_length - 1; | |
| 2048 // ++i at the top of the loop. | |
| 2049 } else { | |
| 2050 if (copy_constructor) { | |
| 2051 field_generators_.get(field).GenerateCopyConstructorCode(printer); | |
| 2052 } else { | |
| 2053 field_generators_.get(field).GenerateConstructorCode(printer); | |
| 2054 } | |
| 2055 } | |
| 2056 } | |
| 2057 } | |
| 2058 | |
| 2059 void MessageGenerator:: | 2116 void MessageGenerator:: |
| 2060 GenerateStructors(io::Printer* printer) { | 2117 GenerateStructors(io::Printer* printer) { |
| 2061 string superclass; | 2118 string superclass; |
| 2062 if (use_dependent_base_) { | 2119 if (use_dependent_base_) { |
| 2063 superclass = | 2120 superclass = |
| 2064 DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; | 2121 DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; |
| 2065 } else { | 2122 } else { |
| 2066 superclass = SuperClassName(descriptor_, options_); | 2123 superclass = SuperClassName(descriptor_, options_); |
| 2067 } | 2124 } |
| 2068 string initializer_with_arena = superclass + "()"; | 2125 string initializer_with_arena = superclass + "()"; |
| 2069 | 2126 |
| 2070 if (descriptor_->extension_range_count() > 0) { | 2127 if (descriptor_->extension_range_count() > 0) { |
| 2071 initializer_with_arena += ",\n _extensions_(arena)"; | 2128 initializer_with_arena += ",\n _extensions_(arena)"; |
| 2072 } | 2129 } |
| 2073 | 2130 |
| 2074 initializer_with_arena += ",\n _internal_metadata_(arena)"; | 2131 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2132 initializer_with_arena += ",\n _internal_metadata_(arena)"; |
| 2133 } else { |
| 2134 initializer_with_arena += ",\n _arena_ptr_(arena)"; |
| 2135 } |
| 2075 | 2136 |
| 2076 // Initialize member variables with arena constructor. | 2137 // Initialize member variables with arena constructor. |
| 2077 for (int i = 0; i < optimized_order_.size(); i++) { | 2138 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 2078 const FieldDescriptor* field = optimized_order_[i]; | 2139 bool has_arena_constructor = descriptor_->field(i)->is_repeated(); |
| 2079 | |
| 2080 bool has_arena_constructor = field->is_repeated(); | |
| 2081 if (has_arena_constructor) { | 2140 if (has_arena_constructor) { |
| 2082 initializer_with_arena += string(",\n ") + | 2141 initializer_with_arena += string(",\n ") + |
| 2083 FieldName(field) + string("_(arena)"); | 2142 FieldName(descriptor_->field(i)) + string("_(arena)"); |
| 2084 } | 2143 } |
| 2085 } | 2144 } |
| 2086 | 2145 |
| 2087 if (IsAnyMessage(descriptor_)) { | 2146 if (IsAnyMessage(descriptor_)) { |
| 2088 initializer_with_arena += ",\n _any_metadata_(&type_url_, &value_)"; | 2147 initializer_with_arena += ",\n _any_metadata_(&type_url, &value_)"; |
| 2089 } | 2148 } |
| 2090 | 2149 |
| 2091 string initializer_null; | 2150 string initializer_null; |
| 2092 initializer_null = ", _internal_metadata_(NULL)"; | 2151 initializer_null = (UseUnknownFieldSet(descriptor_->file(), options_) ? |
| 2152 ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)"); |
| 2093 if (IsAnyMessage(descriptor_)) { | 2153 if (IsAnyMessage(descriptor_)) { |
| 2094 initializer_null += ", _any_metadata_(&type_url_, &value_)"; | 2154 initializer_null += ", _any_metadata_(&type_url_, &value_)"; |
| 2095 } | 2155 } |
| 2096 | 2156 |
| 2097 printer->Print( | 2157 printer->Print( |
| 2098 "$classname$::$classname$()\n" | 2158 "$classname$::$classname$()\n" |
| 2099 " : $superclass$()$initializer$ {\n" | 2159 " : $superclass$()$initializer$ {\n" |
| 2100 " if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {\n" | |
| 2101 " $initdefaultsname$();\n" | |
| 2102 " }\n" | |
| 2103 " SharedCtor();\n" | 2160 " SharedCtor();\n" |
| 2104 " // @@protoc_insertion_point(constructor:$full_name$)\n" | 2161 " // @@protoc_insertion_point(constructor:$full_name$)\n" |
| 2105 "}\n", | 2162 "}\n", |
| 2106 "classname", classname_, "superclass", superclass, "full_name", | 2163 "classname", classname_, |
| 2107 descriptor_->full_name(), "initializer", initializer_null, | 2164 "superclass", superclass, |
| 2108 "initdefaultsname", GlobalInitDefaultsName(descriptor_->file()->name())); | 2165 "full_name", descriptor_->full_name(), |
| 2166 "initializer", initializer_null); |
| 2109 | 2167 |
| 2110 if (SupportsArenas(descriptor_)) { | 2168 if (SupportsArenas(descriptor_)) { |
| 2111 printer->Print( | 2169 printer->Print( |
| 2170 "\n" |
| 2112 "$classname$::$classname$(::google::protobuf::Arena* arena)\n" | 2171 "$classname$::$classname$(::google::protobuf::Arena* arena)\n" |
| 2113 " : $initializer$ {\n" | 2172 " : $initializer$ {\n" |
| 2114 // When arenas are used it's safe to assume we have finished | |
| 2115 // static init time (protos with arenas are unsafe during static init) | |
| 2116 "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" | |
| 2117 " $initdefaultsname$();\n" | |
| 2118 "#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" | |
| 2119 " SharedCtor();\n" | 2173 " SharedCtor();\n" |
| 2120 " RegisterArenaDtor(arena);\n" | 2174 " RegisterArenaDtor(arena);\n" |
| 2121 " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" | 2175 " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" |
| 2122 "}\n", | 2176 "}\n", |
| 2123 "initializer", initializer_with_arena, "classname", classname_, | 2177 "initializer", initializer_with_arena, |
| 2124 "superclass", superclass, "full_name", descriptor_->full_name(), | 2178 "classname", classname_, |
| 2125 "initdefaultsname", | 2179 "superclass", superclass, |
| 2126 GlobalInitDefaultsName(descriptor_->file()->name())); | 2180 "full_name", descriptor_->full_name()); |
| 2127 } | 2181 } |
| 2128 | 2182 |
| 2183 printer->Print( |
| 2184 "\n" |
| 2185 "void $classname$::InitAsDefaultInstance() {\n", |
| 2186 "classname", classname_); |
| 2187 |
| 2188 if (!HasFieldPresence(descriptor_->file())) { |
| 2189 printer->Print( |
| 2190 " _is_default_instance_ = true;\n"); |
| 2191 } |
| 2192 |
| 2193 // The default instance needs all of its embedded message pointers |
| 2194 // cross-linked to other default instances. We can't do this initialization |
| 2195 // in the constructor because some other default instances may not have been |
| 2196 // constructed yet at that time. |
| 2197 // TODO(kenton): Maybe all message fields (even for non-default messages) |
| 2198 // should be initialized to point at default instances rather than NULL? |
| 2199 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 2200 const FieldDescriptor* field = descriptor_->field(i); |
| 2201 |
| 2202 if (!field->is_repeated() && |
| 2203 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && |
| 2204 (field->containing_oneof() == NULL || |
| 2205 HasDescriptorMethods(descriptor_->file(), options_))) { |
| 2206 string name; |
| 2207 if (field->containing_oneof()) { |
| 2208 name = classname_ + "_default_oneof_instance_->"; |
| 2209 } |
| 2210 name += FieldName(field); |
| 2211 PrintHandlingOptionalStaticInitializers( |
| 2212 descriptor_->file(), options_, printer, |
| 2213 // With static initializers. |
| 2214 " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", |
| 2215 // Without. |
| 2216 " $name$_ = const_cast< $type$*>(\n" |
| 2217 " $type$::internal_default_instance());\n", |
| 2218 // Vars. |
| 2219 "name", name, "type", FieldMessageTypeName(field)); |
| 2220 } else if (field->containing_oneof() && |
| 2221 HasDescriptorMethods(descriptor_->file(), options_)) { |
| 2222 field_generators_.get(descriptor_->field(i)) |
| 2223 .GenerateConstructorCode(printer); |
| 2224 } |
| 2225 } |
| 2226 printer->Print( |
| 2227 "}\n" |
| 2228 "\n"); |
| 2229 |
| 2129 // Generate the copy constructor. | 2230 // Generate the copy constructor. |
| 2130 printer->Print( | 2231 printer->Print( |
| 2131 "$classname$::$classname$(const $classname$& from)\n" | 2232 "$classname$::$classname$(const $classname$& from)\n" |
| 2132 " : $superclass$()", | 2233 " : $superclass$()", |
| 2133 "classname", classname_, | 2234 "classname", classname_, |
| 2134 "superclass", superclass, | 2235 "superclass", superclass, |
| 2135 "full_name", descriptor_->full_name()); | 2236 "full_name", descriptor_->full_name()); |
| 2136 printer->Indent(); | 2237 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2137 printer->Indent(); | 2238 printer->Print( |
| 2138 printer->Indent(); | 2239 ",\n _internal_metadata_(NULL)"); |
| 2139 | 2240 } else if (!UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2241 printer->Print(",\n _arena_ptr_(NULL)"); |
| 2242 } |
| 2243 if (IsAnyMessage(descriptor_)) { |
| 2244 printer->Print(",\n _any_metadata_(&type_url_, &value_)"); |
| 2245 } |
| 2246 printer->Print(" {\n"); |
| 2140 printer->Print( | 2247 printer->Print( |
| 2141 ",\n_internal_metadata_(NULL)"); | 2248 " SharedCtor();\n" |
| 2142 | 2249 " MergeFrom(from);\n" |
| 2143 if (HasFieldPresence(descriptor_->file())) { | |
| 2144 printer->Print(",\n_has_bits_(from._has_bits_)"); | |
| 2145 } | |
| 2146 | |
| 2147 bool need_to_emit_cached_size = true; | |
| 2148 const string cached_size_decl = ",\n_cached_size_(0)"; | |
| 2149 // We reproduce the logic used for laying out _cached_sized_ in the class | |
| 2150 // definition, as to initialize it in-order. | |
| 2151 if (HasFieldPresence(descriptor_->file()) && | |
| 2152 (HasBitsSize() % 8) != 0) { | |
| 2153 printer->Print(cached_size_decl.c_str()); | |
| 2154 need_to_emit_cached_size = false; | |
| 2155 } | |
| 2156 | |
| 2157 std::vector<bool> processed(optimized_order_.size(), false); | |
| 2158 for (int i = 0; i < optimized_order_.size(); ++i) { | |
| 2159 const FieldDescriptor* field = optimized_order_[i]; | |
| 2160 | |
| 2161 if (!(field->is_repeated() && !(field->is_map())) | |
| 2162 ) { | |
| 2163 continue; | |
| 2164 } | |
| 2165 | |
| 2166 processed[i] = true; | |
| 2167 printer->Print(",\n$name$_(from.$name$_)", | |
| 2168 "name", FieldName(field)); | |
| 2169 } | |
| 2170 | |
| 2171 if (need_to_emit_cached_size) { | |
| 2172 printer->Print(cached_size_decl.c_str()); | |
| 2173 need_to_emit_cached_size = false; | |
| 2174 } | |
| 2175 | |
| 2176 if (IsAnyMessage(descriptor_)) { | |
| 2177 printer->Print(",\n_any_metadata_(&type_url_, &value_)"); | |
| 2178 } | |
| 2179 | |
| 2180 printer->Outdent(); | |
| 2181 printer->Outdent(); | |
| 2182 printer->Print(" {\n"); | |
| 2183 | |
| 2184 printer->Print( | |
| 2185 "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); | |
| 2186 | |
| 2187 if (descriptor_->extension_range_count() > 0) { | |
| 2188 printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); | |
| 2189 } | |
| 2190 | |
| 2191 // TODO(gerbens) Clean this hack, and why do i need a reference to a pointer?? | |
| 2192 for (int i = 0; i < descriptor_->nested_type_count(); i++) { | |
| 2193 if (HasDescriptorMethods(descriptor_->file(), options_) && | |
| 2194 IsMapEntryMessage(descriptor_->nested_type(i))) { | |
| 2195 printer->Print( | |
| 2196 "const ::google::protobuf::Descriptor*& $type$_descriptor = " | |
| 2197 "file_level_metadata[$index$].descriptor;\n", | |
| 2198 "type", ClassName(descriptor_->nested_type(i), false), "index", | |
| 2199 SimpleItoa(nested_generators_[i]->index_in_metadata_)); | |
| 2200 } | |
| 2201 } | |
| 2202 | |
| 2203 GenerateConstructorBody(printer, processed, true); | |
| 2204 | |
| 2205 // Copy oneof fields. Oneof field requires oneof case check. | |
| 2206 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { | |
| 2207 printer->Print( | |
| 2208 "clear_has_$oneofname$();\n" | |
| 2209 "switch (from.$oneofname$_case()) {\n", | |
| 2210 "oneofname", descriptor_->oneof_decl(i)->name()); | |
| 2211 printer->Indent(); | |
| 2212 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | |
| 2213 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); | |
| 2214 printer->Print( | |
| 2215 "case k$field_name$: {\n", | |
| 2216 "field_name", UnderscoresToCamelCase(field->name(), true)); | |
| 2217 printer->Indent(); | |
| 2218 field_generators_.get(field).GenerateMergingCode(printer); | |
| 2219 printer->Print( | |
| 2220 "break;\n"); | |
| 2221 printer->Outdent(); | |
| 2222 printer->Print( | |
| 2223 "}\n"); | |
| 2224 } | |
| 2225 printer->Print( | |
| 2226 "case $cap_oneof_name$_NOT_SET: {\n" | |
| 2227 " break;\n" | |
| 2228 "}\n", | |
| 2229 "oneof_index", | |
| 2230 SimpleItoa(descriptor_->oneof_decl(i)->index()), | |
| 2231 "cap_oneof_name", | |
| 2232 ToUpper(descriptor_->oneof_decl(i)->name())); | |
| 2233 printer->Outdent(); | |
| 2234 printer->Print( | |
| 2235 "}\n"); | |
| 2236 } | |
| 2237 | |
| 2238 printer->Outdent(); | |
| 2239 printer->Print( | |
| 2240 " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" | 2250 " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" |
| 2241 "}\n" | 2251 "}\n" |
| 2242 "\n", | 2252 "\n", |
| 2253 "classname", classname_, |
| 2254 "superclass", superclass, |
| 2243 "full_name", descriptor_->full_name()); | 2255 "full_name", descriptor_->full_name()); |
| 2244 | 2256 |
| 2245 // Generate the shared constructor code. | 2257 // Generate the shared constructor code. |
| 2246 GenerateSharedConstructorCode(printer); | 2258 GenerateSharedConstructorCode(printer); |
| 2247 | 2259 |
| 2248 // Generate the destructor. | 2260 // Generate the destructor. |
| 2249 printer->Print( | 2261 printer->Print( |
| 2250 "$classname$::~$classname$() {\n" | 2262 "$classname$::~$classname$() {\n" |
| 2251 " // @@protoc_insertion_point(destructor:$full_name$)\n" | 2263 " // @@protoc_insertion_point(destructor:$full_name$)\n" |
| 2252 " SharedDtor();\n" | 2264 " SharedDtor();\n" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2269 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" | 2281 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" |
| 2270 " _cached_size_ = size;\n" | 2282 " _cached_size_ = size;\n" |
| 2271 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" | 2283 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" |
| 2272 "}\n", | 2284 "}\n", |
| 2273 "classname", classname_); | 2285 "classname", classname_); |
| 2274 | 2286 |
| 2275 // Only generate this member if it's not disabled. | 2287 // Only generate this member if it's not disabled. |
| 2276 if (HasDescriptorMethods(descriptor_->file(), options_) && | 2288 if (HasDescriptorMethods(descriptor_->file(), options_) && |
| 2277 !descriptor_->options().no_standard_descriptor_accessor()) { | 2289 !descriptor_->options().no_standard_descriptor_accessor()) { |
| 2278 printer->Print( | 2290 printer->Print( |
| 2279 "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" | 2291 "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" |
| 2280 " protobuf_AssignDescriptorsOnce();\n" | 2292 " protobuf_AssignDescriptorsOnce();\n" |
| 2281 " return file_level_metadata[$index$].descriptor;\n" | 2293 " return $classname$_descriptor_;\n" |
| 2282 "}\n" | 2294 "}\n" |
| 2283 "\n", | 2295 "\n", |
| 2284 "index", SimpleItoa(index_in_metadata_), "classname", classname_); | 2296 "classname", classname_, |
| 2297 "adddescriptorsname", |
| 2298 GlobalAddDescriptorsName(descriptor_->file()->name())); |
| 2285 } | 2299 } |
| 2286 | 2300 |
| 2287 printer->Print( | 2301 printer->Print( |
| 2288 "const $classname$& $classname$::default_instance() {\n" | 2302 "const $classname$& $classname$::default_instance() {\n", |
| 2289 " $initdefaultsname$();\n" | 2303 "classname", classname_); |
| 2290 " return *internal_default_instance();\n" | 2304 |
| 2291 "}\n\n", | 2305 PrintHandlingOptionalStaticInitializers( |
| 2292 "classname", classname_, "initdefaultsname", | 2306 descriptor_->file(), options_, printer, |
| 2293 GlobalInitDefaultsName(descriptor_->file()->name())); | 2307 // With static initializers. |
| 2308 " if (default_instance_ == NULL) $adddescriptorsname$();\n", |
| 2309 // Without. |
| 2310 " $adddescriptorsname$();\n", |
| 2311 // Vars. |
| 2312 "adddescriptorsname", |
| 2313 GlobalAddDescriptorsName(descriptor_->file()->name())); |
| 2314 |
| 2315 printer->Print( |
| 2316 " return *default_instance_;\n" |
| 2317 "}\n" |
| 2318 "\n" |
| 2319 "$classname$* $classname$::default_instance_ = NULL;\n" |
| 2320 "\n", |
| 2321 "classname", classname_); |
| 2294 | 2322 |
| 2295 if (SupportsArenas(descriptor_)) { | 2323 if (SupportsArenas(descriptor_)) { |
| 2296 printer->Print( | 2324 printer->Print( |
| 2297 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" | 2325 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" |
| 2298 " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n" | 2326 " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n" |
| 2299 "}\n", | 2327 "}\n", |
| 2300 "classname", classname_); | 2328 "classname", classname_); |
| 2301 } else { | 2329 } else { |
| 2302 printer->Print( | 2330 printer->Print( |
| 2303 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" | 2331 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2328 "void $classname$::Clear() {\n" | 2356 "void $classname$::Clear() {\n" |
| 2329 "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", | 2357 "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", |
| 2330 "classname", classname_, "full_name", descriptor_->full_name()); | 2358 "classname", classname_, "full_name", descriptor_->full_name()); |
| 2331 printer->Indent(); | 2359 printer->Indent(); |
| 2332 | 2360 |
| 2333 // Step 1: Extensions | 2361 // Step 1: Extensions |
| 2334 if (descriptor_->extension_range_count() > 0) { | 2362 if (descriptor_->extension_range_count() > 0) { |
| 2335 printer->Print("_extensions_.Clear();\n"); | 2363 printer->Print("_extensions_.Clear();\n"); |
| 2336 } | 2364 } |
| 2337 | 2365 |
| 2338 int last_i = -1; | 2366 // Step 2: Everything but extensions, repeateds, unions. |
| 2339 for (int i = 0; i < optimized_order_.size(); ) { | 2367 // These are handled in chunks of 8. The first chunk is |
| 2340 // Detect infinite loops. | 2368 // the non-extensions-non-repeateds-non-unions in |
| 2341 GOOGLE_CHECK_NE(i, last_i); | 2369 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), |
| 2342 last_i = i; | 2370 // and the second chunk is the same for |
| 2371 // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), |
| 2372 // etc. |
| 2373 set<int> step2_indices; |
| 2374 hash_map<string, int> fieldname_to_chunk; |
| 2375 hash_map<int, string> memsets_for_chunk; |
| 2376 hash_map<int, int> memset_field_count_for_chunk; |
| 2377 hash_set<string> handled; // fields that appear anywhere in memsets_for_chunk |
| 2378 hash_map<int, uint32> fields_mask_for_chunk; |
| 2379 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 2380 const FieldDescriptor* field = descriptor_->field(i); |
| 2381 if (!field->is_repeated() && !field->containing_oneof()) { |
| 2382 step2_indices.insert(i); |
| 2383 int chunk = i / 8; |
| 2384 fieldname_to_chunk[FieldName(field)] = chunk; |
| 2385 fields_mask_for_chunk[chunk] |= static_cast<uint32>(1) << (i % 32); |
| 2386 } |
| 2387 } |
| 2343 | 2388 |
| 2344 // Step 2: Repeated fields don't use _has_bits_; emit code to clear them | 2389 // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. |
| 2345 // here. | 2390 // The generated code uses two macros to help it clear runs of fields: |
| 2346 for (; i < optimized_order_.size(); i++) { | 2391 // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the |
| 2347 const FieldDescriptor* field = optimized_order_[i]; | 2392 // positions of two fields in the Message. |
| 2348 const FieldGenerator& generator = field_generators_.get(field); | 2393 // ZR_ zeroes a non-empty range of fields via memset. |
| 2394 const char* macros = |
| 2395 "#if defined(__clang__)\n" |
| 2396 "#define ZR_HELPER_(f) \\\n" |
| 2397 " _Pragma(\"clang diagnostic push\") \\\n" |
| 2398 " _Pragma(\"clang diagnostic ignored \\\"-Winvalid-offsetof\\\"\") \\\n" |
| 2399 " __builtin_offsetof($classname$, f) \\\n" |
| 2400 " _Pragma(\"clang diagnostic pop\")\n" |
| 2401 "#else\n" |
| 2402 "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n" |
| 2403 " &reinterpret_cast<$classname$*>(16)->f)\n" |
| 2404 "#endif\n\n" |
| 2405 "#define ZR_(first, last) do {\\\n" |
| 2406 " ::memset(&first, 0,\\\n" |
| 2407 " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n" |
| 2408 "} while (0)\n\n"; |
| 2409 for (int i = 0; i < runs_of_fields_.size(); i++) { |
| 2410 const vector<string>& run = runs_of_fields_[i]; |
| 2411 if (run.size() < 2) continue; |
| 2412 const string& first_field_name = run[0]; |
| 2413 const string& last_field_name = run.back(); |
| 2414 int chunk = fieldname_to_chunk[run[0]]; |
| 2415 memsets_for_chunk[chunk].append( |
| 2416 "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n"); |
| 2417 for (int j = 0; j < run.size(); j++) { |
| 2418 GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]); |
| 2419 handled.insert(run[j]); |
| 2420 } |
| 2421 memset_field_count_for_chunk[chunk] += run.size(); |
| 2422 } |
| 2423 const bool macros_are_needed = handled.size() > 0; |
| 2424 if (macros_are_needed) { |
| 2425 printer->Outdent(); |
| 2426 printer->Print(macros, |
| 2427 "classname", classname_); |
| 2428 printer->Indent(); |
| 2429 } |
| 2430 // Step 2b: Finish step 2, ignoring fields handled in step 2a. |
| 2431 int last_index = -1; |
| 2432 bool chunk_block_in_progress = false; |
| 2433 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 2434 if (step2_indices.count(i) == 0) continue; |
| 2435 const FieldDescriptor* field = descriptor_->field(i); |
| 2436 const string fieldname = FieldName(field); |
| 2437 if (i / 8 != last_index / 8 || last_index < 0) { |
| 2438 // End previous chunk, if there was one. |
| 2439 if (chunk_block_in_progress) { |
| 2440 printer->Outdent(); |
| 2441 printer->Print("}\n"); |
| 2442 chunk_block_in_progress = false; |
| 2443 } |
| 2444 // Start chunk. |
| 2445 const string& memsets = memsets_for_chunk[i / 8]; |
| 2446 uint32 mask = fields_mask_for_chunk[i / 8]; |
| 2447 int count = popcnt(mask); |
| 2448 GOOGLE_DCHECK_GE(count, 1); |
| 2449 if (count == 1 || |
| 2450 (count <= 4 && count == memset_field_count_for_chunk[i / 8])) { |
| 2451 // No "if" here because the chunk is trivial. |
| 2452 } else { |
| 2453 if (HasFieldPresence(descriptor_->file())) { |
| 2454 printer->Print( |
| 2455 "if (_has_bits_[$index$ / 32] & $mask$u) {\n", |
| 2456 "index", SimpleItoa(i / 8 * 8), |
| 2457 "mask", SimpleItoa(mask)); |
| 2458 printer->Indent(); |
| 2459 chunk_block_in_progress = true; |
| 2460 } |
| 2461 } |
| 2462 printer->Print(memsets.c_str()); |
| 2463 } |
| 2464 last_index = i; |
| 2465 if (handled.count(fieldname) > 0) continue; |
| 2349 | 2466 |
| 2350 if (!field->is_repeated()) { | 2467 // It's faster to just overwrite primitive types, but we should |
| 2351 break; | 2468 // only clear strings and messages if they were set. |
| 2352 } | 2469 // TODO(kenton): Let the CppFieldGenerator decide this somehow. |
| 2470 bool should_check_bit = |
| 2471 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || |
| 2472 field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; |
| 2353 | 2473 |
| 2474 bool have_enclosing_if = false; |
| 2475 if (should_check_bit && |
| 2476 // If no field presence, then always clear strings/messages as well. |
| 2477 HasFieldPresence(descriptor_->file())) { |
| 2478 printer->Print("if (has_$name$()) {\n", "name", fieldname); |
| 2479 printer->Indent(); |
| 2480 have_enclosing_if = true; |
| 2481 } |
| 2482 |
| 2483 if (use_dependent_base_ && IsFieldDependent(field)) { |
| 2484 printer->Print("clear_$name$();\n", "name", fieldname); |
| 2485 } else { |
| 2486 field_generators_.get(field).GenerateClearingCode(printer); |
| 2487 } |
| 2488 |
| 2489 if (have_enclosing_if) { |
| 2490 printer->Outdent(); |
| 2491 printer->Print("}\n"); |
| 2492 } |
| 2493 } |
| 2494 |
| 2495 if (chunk_block_in_progress) { |
| 2496 printer->Outdent(); |
| 2497 printer->Print("}\n"); |
| 2498 } |
| 2499 if (macros_are_needed) { |
| 2500 printer->Outdent(); |
| 2501 printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n"); |
| 2502 printer->Indent(); |
| 2503 } |
| 2504 |
| 2505 // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here. |
| 2506 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 2507 const FieldDescriptor* field = descriptor_->field(i); |
| 2508 |
| 2509 if (field->is_repeated()) { |
| 2354 if (use_dependent_base_ && IsFieldDependent(field)) { | 2510 if (use_dependent_base_ && IsFieldDependent(field)) { |
| 2355 printer->Print("clear_$name$();\n", "name", FieldName(field)); | 2511 printer->Print("clear_$name$();\n", "name", FieldName(field)); |
| 2356 } else { | 2512 } else { |
| 2357 generator.GenerateMessageClearingCode(printer); | 2513 field_generators_.get(field).GenerateClearingCode(printer); |
| 2358 } | |
| 2359 } | |
| 2360 | |
| 2361 // Step 3: Greedily seek runs of fields that can be cleared by | |
| 2362 // memset-to-0. | |
| 2363 int last_chunk = -1; | |
| 2364 int last_chunk_start = -1; | |
| 2365 int last_chunk_end = -1; | |
| 2366 uint32 last_chunk_mask = 0; | |
| 2367 | |
| 2368 int memset_run_start = -1; | |
| 2369 int memset_run_end = -1; | |
| 2370 for (; i < optimized_order_.size(); i++) { | |
| 2371 const FieldDescriptor* field = optimized_order_[i]; | |
| 2372 | |
| 2373 if (!CanInitializeByZeroing(field)) { | |
| 2374 break; | |
| 2375 } | |
| 2376 | |
| 2377 // "index" defines where in the _has_bits_ the field appears. | |
| 2378 // "i" is our loop counter within optimized_order_. | |
| 2379 int index = HasFieldPresence(descriptor_->file()) ? | |
| 2380 has_bit_indices_[field->index()] : 0; | |
| 2381 int chunk = index / 8; | |
| 2382 | |
| 2383 if (last_chunk == -1) { | |
| 2384 last_chunk = chunk; | |
| 2385 last_chunk_start = i; | |
| 2386 } else if (chunk != last_chunk) { | |
| 2387 // Emit the fields for this chunk so far. | |
| 2388 break; | |
| 2389 } | |
| 2390 | |
| 2391 if (memset_run_start == -1) { | |
| 2392 memset_run_start = i; | |
| 2393 } | |
| 2394 | |
| 2395 memset_run_end = i; | |
| 2396 last_chunk_end = i; | |
| 2397 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); | |
| 2398 } | |
| 2399 | |
| 2400 // Step 4: Non-repeated, non-zero initializable fields. | |
| 2401 for (; i < optimized_order_.size(); i++) { | |
| 2402 const FieldDescriptor* field = optimized_order_[i]; | |
| 2403 if (field->is_repeated() || CanInitializeByZeroing(field)) { | |
| 2404 break; | |
| 2405 } | |
| 2406 | |
| 2407 // "index" defines where in the _has_bits_ the field appears. | |
| 2408 // "i" is our loop counter within optimized_order_. | |
| 2409 int index = HasFieldPresence(descriptor_->file()) ? | |
| 2410 has_bit_indices_[field->index()] : 0; | |
| 2411 int chunk = index / 8; | |
| 2412 | |
| 2413 if (last_chunk == -1) { | |
| 2414 last_chunk = chunk; | |
| 2415 last_chunk_start = i; | |
| 2416 } else if (chunk != last_chunk) { | |
| 2417 // Emit the fields for this chunk so far. | |
| 2418 break; | |
| 2419 } | |
| 2420 | |
| 2421 last_chunk_end = i; | |
| 2422 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); | |
| 2423 } | |
| 2424 | |
| 2425 if (last_chunk != -1) { | |
| 2426 GOOGLE_DCHECK_NE(-1, last_chunk_start); | |
| 2427 GOOGLE_DCHECK_NE(-1, last_chunk_end); | |
| 2428 GOOGLE_DCHECK_NE(0, last_chunk_mask); | |
| 2429 | |
| 2430 const int count = popcnt(last_chunk_mask); | |
| 2431 const bool have_outer_if = HasFieldPresence(descriptor_->file()) && | |
| 2432 (last_chunk_start != last_chunk_end); | |
| 2433 | |
| 2434 if (have_outer_if) { | |
| 2435 // Check (up to) 8 has_bits at a time if we have more than one field in | |
| 2436 // this chunk. Due to field layout ordering, we may check | |
| 2437 // _has_bits_[last_chunk * 8 / 32] multiple times. | |
| 2438 GOOGLE_DCHECK_LE(2, count); | |
| 2439 GOOGLE_DCHECK_GE(8, count); | |
| 2440 | |
| 2441 printer->Print( | |
| 2442 "if (_has_bits_[$index$ / 32] & $mask$u) {\n", | |
| 2443 "index", SimpleItoa(last_chunk * 8), | |
| 2444 "mask", SimpleItoa(last_chunk_mask)); | |
| 2445 printer->Indent(); | |
| 2446 } | |
| 2447 | |
| 2448 if (memset_run_start != -1) { | |
| 2449 if (memset_run_start == memset_run_end) { | |
| 2450 // For clarity, do not memset a single field. | |
| 2451 const FieldGenerator& generator = | |
| 2452 field_generators_.get(optimized_order_[memset_run_start]); | |
| 2453 generator.GenerateMessageClearingCode(printer); | |
| 2454 } else { | |
| 2455 const string first_field_name = | |
| 2456 FieldName(optimized_order_[memset_run_start]); | |
| 2457 const string last_field_name = | |
| 2458 FieldName(optimized_order_[memset_run_end]); | |
| 2459 | |
| 2460 printer->Print( | |
| 2461 "::memset(&$first$_, 0, reinterpret_cast<char*>(&$last$_) -\n" | |
| 2462 " reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n", | |
| 2463 "first", first_field_name, | |
| 2464 "last", last_field_name); | |
| 2465 } | |
| 2466 | |
| 2467 // Advance last_chunk_start to skip over the fields we zeroed/memset. | |
| 2468 last_chunk_start = memset_run_end + 1; | |
| 2469 } | |
| 2470 | |
| 2471 // Go back and emit clears for each of the fields we processed. | |
| 2472 for (int j = last_chunk_start; j <= last_chunk_end; j++) { | |
| 2473 const FieldDescriptor* field = optimized_order_[j]; | |
| 2474 const string fieldname = FieldName(field); | |
| 2475 const FieldGenerator& generator = field_generators_.get(field); | |
| 2476 | |
| 2477 // It's faster to just overwrite primitive types, but we should only | |
| 2478 // clear strings and messages if they were set. | |
| 2479 // | |
| 2480 // TODO(kenton): Let the CppFieldGenerator decide this somehow. | |
| 2481 bool should_check_bit = | |
| 2482 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || | |
| 2483 field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; | |
| 2484 | |
| 2485 bool have_enclosing_if = false; | |
| 2486 if (should_check_bit && | |
| 2487 // If no field presence, then always clear strings/messages as well. | |
| 2488 HasFieldPresence(descriptor_->file())) { | |
| 2489 printer->Print("if (has_$name$()) {\n", "name", fieldname); | |
| 2490 printer->Indent(); | |
| 2491 have_enclosing_if = true; | |
| 2492 } | |
| 2493 | |
| 2494 generator.GenerateMessageClearingCode(printer); | |
| 2495 | |
| 2496 if (have_enclosing_if) { | |
| 2497 printer->Outdent(); | |
| 2498 printer->Print("}\n"); | |
| 2499 } | |
| 2500 } | |
| 2501 | |
| 2502 if (have_outer_if) { | |
| 2503 printer->Outdent(); | |
| 2504 printer->Print("}\n"); | |
| 2505 } | 2514 } |
| 2506 } | 2515 } |
| 2507 } | 2516 } |
| 2508 | 2517 |
| 2509 // Step 4: Unions. | 2518 // Step 4: Unions. |
| 2510 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 2519 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 2511 printer->Print( | 2520 printer->Print( |
| 2512 "clear_$oneof_name$();\n", | 2521 "clear_$oneof_name$();\n", |
| 2513 "oneof_name", descriptor_->oneof_decl(i)->name()); | 2522 "oneof_name", descriptor_->oneof_decl(i)->name()); |
| 2514 } | 2523 } |
| 2515 | 2524 |
| 2516 if (HasFieldPresence(descriptor_->file())) { | 2525 if (HasFieldPresence(descriptor_->file())) { |
| 2517 // Step 5: Everything else. | 2526 // Step 5: Everything else. |
| 2518 printer->Print("_has_bits_.Clear();\n"); | 2527 printer->Print( |
| 2528 "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); |
| 2519 } | 2529 } |
| 2520 | 2530 |
| 2521 if (PreserveUnknownFields(descriptor_)) { | 2531 if (PreserveUnknownFields(descriptor_)) { |
| 2522 printer->Print("_internal_metadata_.Clear();\n"); | 2532 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2533 printer->Print( |
| 2534 "if (_internal_metadata_.have_unknown_fields()) {\n" |
| 2535 " mutable_unknown_fields()->Clear();\n" |
| 2536 "}\n"); |
| 2537 } else { |
| 2538 if (SupportsArenas(descriptor_)) { |
| 2539 printer->Print( |
| 2540 "_unknown_fields_.ClearToEmpty(\n" |
| 2541 " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" |
| 2542 " GetArenaNoVirtual());\n"); |
| 2543 } else { |
| 2544 printer->Print( |
| 2545 "_unknown_fields_.ClearToEmptyNoArena(\n" |
| 2546 " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
); |
| 2547 } |
| 2548 } |
| 2523 } | 2549 } |
| 2524 | 2550 |
| 2525 printer->Outdent(); | 2551 printer->Outdent(); |
| 2526 printer->Print("}\n"); | 2552 printer->Print("}\n"); |
| 2527 } | 2553 } |
| 2528 | 2554 |
| 2529 void MessageGenerator:: | 2555 void MessageGenerator:: |
| 2530 GenerateOneofClear(io::Printer* printer) { | 2556 GenerateOneofClear(io::Printer* printer) { |
| 2531 // Generated function clears the active field and union case (e.g. foo_case_). | 2557 // Generated function clears the active field and union case (e.g. foo_case_). |
| 2532 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 2558 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 2533 std::map<string, string> oneof_vars; | 2559 map<string, string> oneof_vars; |
| 2534 oneof_vars["classname"] = classname_; | 2560 oneof_vars["classname"] = classname_; |
| 2535 oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); | 2561 oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); |
| 2536 oneof_vars["full_name"] = descriptor_->full_name(); | 2562 oneof_vars["full_name"] = descriptor_->full_name(); |
| 2537 string message_class; | 2563 string message_class; |
| 2538 | 2564 |
| 2539 printer->Print(oneof_vars, | 2565 printer->Print(oneof_vars, |
| 2540 "void $classname$::clear_$oneofname$() {\n" | 2566 "void $classname$::clear_$oneofname$() {\n" |
| 2541 "// @@protoc_insertion_point(one_of_clear_start:" | 2567 "// @@protoc_insertion_point(one_of_clear_start:" |
| 2542 "$full_name$)\n"); | 2568 "$full_name$)\n"); |
| 2543 printer->Indent(); | 2569 printer->Indent(); |
| 2544 printer->Print(oneof_vars, | 2570 printer->Print(oneof_vars, |
| 2545 "switch ($oneofname$_case()) {\n"); | 2571 "switch($oneofname$_case()) {\n"); |
| 2546 printer->Indent(); | 2572 printer->Indent(); |
| 2547 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | 2573 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
| 2548 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); | 2574 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); |
| 2549 printer->Print( | 2575 printer->Print( |
| 2550 "case k$field_name$: {\n", | 2576 "case k$field_name$: {\n", |
| 2551 "field_name", UnderscoresToCamelCase(field->name(), true)); | 2577 "field_name", UnderscoresToCamelCase(field->name(), true)); |
| 2552 printer->Indent(); | 2578 printer->Indent(); |
| 2553 // We clear only allocated objects in oneofs | 2579 // We clear only allocated objects in oneofs |
| 2554 if (!IsStringOrMessage(field)) { | 2580 if (!IsStringOrMessage(field)) { |
| 2555 printer->Print( | 2581 printer->Print( |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2589 // Generate the Swap member function. This is a lightweight wrapper around | 2615 // Generate the Swap member function. This is a lightweight wrapper around |
| 2590 // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory | 2616 // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory |
| 2591 // ownership situation: swapping across arenas or between an arena and a | 2617 // ownership situation: swapping across arenas or between an arena and a |
| 2592 // heap requires copying. | 2618 // heap requires copying. |
| 2593 printer->Print( | 2619 printer->Print( |
| 2594 "GOOGLE_ATTRIBUTE_NOINLINE void $classname$::Swap($classname$* other) {\
n" | 2620 "GOOGLE_ATTRIBUTE_NOINLINE void $classname$::Swap($classname$* other) {\
n" |
| 2595 " if (other == this) return;\n" | 2621 " if (other == this) return;\n" |
| 2596 " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n" | 2622 " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n" |
| 2597 " InternalSwap(other);\n" | 2623 " InternalSwap(other);\n" |
| 2598 " } else {\n" | 2624 " } else {\n" |
| 2599 " $classname$* temp = New(GetArenaNoVirtual());\n" | 2625 " $classname$ temp;\n" |
| 2600 " temp->MergeFrom(*other);\n" | 2626 " temp.MergeFrom(*this);\n" |
| 2601 " other->CopyFrom(*this);\n" | 2627 " CopyFrom(*other);\n" |
| 2602 " InternalSwap(temp);\n" | 2628 " other->CopyFrom(temp);\n" |
| 2603 " if (GetArenaNoVirtual() == NULL) {\n" | |
| 2604 " delete temp;\n" | |
| 2605 " }\n" | |
| 2606 " }\n" | 2629 " }\n" |
| 2607 "}\n" | 2630 "}\n" |
| 2608 "void $classname$::UnsafeArenaSwap($classname$* other) {\n" | 2631 "void $classname$::UnsafeArenaSwap($classname$* other) {\n" |
| 2609 " if (other == this) return;\n" | 2632 " if (other == this) return;\n" |
| 2610 " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" | 2633 " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" |
| 2611 " InternalSwap(other);\n" | 2634 " InternalSwap(other);\n" |
| 2612 "}\n", | 2635 "}\n", |
| 2613 "classname", classname_); | 2636 "classname", classname_); |
| 2614 } else { | 2637 } else { |
| 2615 printer->Print( | 2638 printer->Print( |
| 2616 "void $classname$::Swap($classname$* other) {\n" | 2639 "void $classname$::Swap($classname$* other) {\n" |
| 2617 " if (other == this) return;\n" | 2640 " if (other == this) return;\n" |
| 2618 " InternalSwap(other);\n" | 2641 " InternalSwap(other);\n" |
| 2619 "}\n", | 2642 "}\n", |
| 2620 "classname", classname_); | 2643 "classname", classname_); |
| 2621 } | 2644 } |
| 2622 | 2645 |
| 2623 // Generate the UnsafeArenaSwap member function. | 2646 // Generate the UnsafeArenaSwap member function. |
| 2624 printer->Print("void $classname$::InternalSwap($classname$* other) {\n", | 2647 printer->Print("void $classname$::InternalSwap($classname$* other) {\n", |
| 2625 "classname", classname_); | 2648 "classname", classname_); |
| 2626 printer->Indent(); | 2649 printer->Indent(); |
| 2627 | 2650 |
| 2628 if (HasGeneratedMethods(descriptor_->file(), options_)) { | 2651 if (HasGeneratedMethods(descriptor_->file(), options_)) { |
| 2629 for (int i = 0; i < optimized_order_.size(); i++) { | 2652 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 2630 // optimized_order_ does not contain oneof fields, but the field | 2653 const FieldDescriptor* field = descriptor_->field(i); |
| 2631 // generators for these fields do not emit swapping code on their own. | |
| 2632 const FieldDescriptor* field = optimized_order_[i]; | |
| 2633 field_generators_.get(field).GenerateSwappingCode(printer); | 2654 field_generators_.get(field).GenerateSwappingCode(printer); |
| 2634 } | 2655 } |
| 2635 | 2656 |
| 2636 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 2657 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 2637 printer->Print( | 2658 printer->Print( |
| 2638 "std::swap($oneof_name$_, other->$oneof_name$_);\n" | 2659 "std::swap($oneof_name$_, other->$oneof_name$_);\n" |
| 2639 "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", | 2660 "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", |
| 2640 "oneof_name", descriptor_->oneof_decl(i)->name(), | 2661 "oneof_name", descriptor_->oneof_decl(i)->name(), |
| 2641 "i", SimpleItoa(i)); | 2662 "i", SimpleItoa(i)); |
| 2642 } | 2663 } |
| 2643 | 2664 |
| 2644 if (HasFieldPresence(descriptor_->file())) { | 2665 if (HasFieldPresence(descriptor_->file())) { |
| 2645 for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { | 2666 for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { |
| 2646 printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", | 2667 printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", |
| 2647 "i", SimpleItoa(i)); | 2668 "i", SimpleItoa(i)); |
| 2648 } | 2669 } |
| 2649 } | 2670 } |
| 2650 | 2671 |
| 2651 if (PreserveUnknownFields(descriptor_)) { | 2672 // Ignore PreserveUnknownFields here - always swap internal_metadata as it |
| 2652 printer->Print("_internal_metadata_.Swap(&other->_internal_metadata_);\n")
; | 2673 // may contain more than just unknown fields. |
| 2674 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2675 printer->Print( |
| 2676 "_internal_metadata_.Swap(&other->_internal_metadata_);\n"); |
| 2677 } else { |
| 2678 printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); |
| 2653 } | 2679 } |
| 2654 | 2680 |
| 2655 printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); | 2681 printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); |
| 2656 if (descriptor_->extension_range_count() > 0) { | 2682 if (descriptor_->extension_range_count() > 0) { |
| 2657 printer->Print("_extensions_.Swap(&other->_extensions_);\n"); | 2683 printer->Print("_extensions_.Swap(&other->_extensions_);\n"); |
| 2658 } | 2684 } |
| 2659 } else { | 2685 } else { |
| 2660 printer->Print("GetReflection()->Swap(this, other);"); | 2686 printer->Print("GetReflection()->Swap(this, other);"); |
| 2661 } | 2687 } |
| 2662 | 2688 |
| 2663 printer->Outdent(); | 2689 printer->Outdent(); |
| 2664 printer->Print("}\n"); | 2690 printer->Print("}\n"); |
| 2665 } | 2691 } |
| 2666 | 2692 |
| 2667 void MessageGenerator:: | 2693 void MessageGenerator:: |
| 2668 GenerateMergeFrom(io::Printer* printer) { | 2694 GenerateMergeFrom(io::Printer* printer) { |
| 2669 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 2695 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
| 2670 // Generate the generalized MergeFrom (aka that which takes in the Message | 2696 // Generate the generalized MergeFrom (aka that which takes in the Message |
| 2671 // base class as a parameter). | 2697 // base class as a parameter). |
| 2672 printer->Print( | 2698 printer->Print( |
| 2673 "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\
n" | 2699 "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\
n" |
| 2674 "// @@protoc_insertion_point(generalized_merge_from_start:" | 2700 "// @@protoc_insertion_point(generalized_merge_from_start:" |
| 2675 "$full_name$)\n" | 2701 "$full_name$)\n" |
| 2676 " GOOGLE_DCHECK_NE(&from, this);\n", | 2702 " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", |
| 2677 "classname", classname_, "full_name", descriptor_->full_name()); | 2703 "classname", classname_, "full_name", descriptor_->full_name()); |
| 2678 printer->Indent(); | 2704 printer->Indent(); |
| 2679 | 2705 |
| 2680 // Cast the message to the proper type. If we find that the message is | 2706 // Cast the message to the proper type. If we find that the message is |
| 2681 // *not* of the proper type, we can still call Merge via the reflection | 2707 // *not* of the proper type, we can still call Merge via the reflection |
| 2682 // system, as the GOOGLE_CHECK above ensured that we have the same descripto
r | 2708 // system, as the GOOGLE_CHECK above ensured that we have the same descripto
r |
| 2683 // for each message. | 2709 // for each message. |
| 2684 printer->Print( | 2710 printer->Print( |
| 2685 "const $classname$* source =\n" | 2711 "const $classname$* source = \n" |
| 2686 " ::google::protobuf::internal::DynamicCastToGenerated<const $classname
$>(\n" | 2712 " ::google::protobuf::internal::DynamicCastToGenerated<const $classname
$>(\n" |
| 2687 " &from);\n" | 2713 " &from);\n" |
| 2688 "if (source == NULL) {\n" | 2714 "if (source == NULL) {\n" |
| 2689 "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" | 2715 "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" |
| 2690 "$full_name$)\n" | 2716 "$full_name$)\n" |
| 2691 " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" | 2717 " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" |
| 2692 "} else {\n" | 2718 "} else {\n" |
| 2693 "// @@protoc_insertion_point(generalized_merge_from_cast_success:" | 2719 "// @@protoc_insertion_point(generalized_merge_from_cast_success:" |
| 2694 "$full_name$)\n" | 2720 "$full_name$)\n" |
| 2695 " MergeFrom(*source);\n" | 2721 " MergeFrom(*source);\n" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2707 "}\n" | 2733 "}\n" |
| 2708 "\n", | 2734 "\n", |
| 2709 "classname", classname_); | 2735 "classname", classname_); |
| 2710 } | 2736 } |
| 2711 | 2737 |
| 2712 // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and ca
st. | 2738 // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and ca
st. |
| 2713 printer->Print( | 2739 printer->Print( |
| 2714 "void $classname$::MergeFrom(const $classname$& from) {\n" | 2740 "void $classname$::MergeFrom(const $classname$& from) {\n" |
| 2715 "// @@protoc_insertion_point(class_specific_merge_from_start:" | 2741 "// @@protoc_insertion_point(class_specific_merge_from_start:" |
| 2716 "$full_name$)\n" | 2742 "$full_name$)\n" |
| 2717 " GOOGLE_DCHECK_NE(&from, this);\n", | 2743 " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", |
| 2718 "classname", classname_, "full_name", descriptor_->full_name()); | 2744 "classname", classname_, "full_name", descriptor_->full_name()); |
| 2719 printer->Indent(); | 2745 printer->Indent(); |
| 2720 | 2746 |
| 2721 if (descriptor_->extension_range_count() > 0) { | 2747 // Merge Repeated fields. These fields do not require a |
| 2722 printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); | 2748 // check as we can simply iterate over them. |
| 2723 } | 2749 for (int i = 0; i < descriptor_->field_count(); ++i) { |
| 2750 const FieldDescriptor* field = descriptor_->field(i); |
| 2724 | 2751 |
| 2725 printer->Print( | 2752 if (field->is_repeated()) { |
| 2726 "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); | 2753 field_generators_.get(field).GenerateMergingCode(printer); |
| 2727 | |
| 2728 int last_i = -1; | |
| 2729 for (int i = 0; i < optimized_order_.size(); ) { | |
| 2730 // Detect infinite loops. | |
| 2731 GOOGLE_CHECK_NE(i, last_i); | |
| 2732 last_i = i; | |
| 2733 | |
| 2734 // Merge Repeated fields. These fields do not require a | |
| 2735 // check as we can simply iterate over them. | |
| 2736 for (; i < optimized_order_.size(); i++) { | |
| 2737 const FieldDescriptor* field = optimized_order_[i]; | |
| 2738 if (!field->is_repeated()) { | |
| 2739 break; | |
| 2740 } | |
| 2741 | |
| 2742 const FieldGenerator& generator = field_generators_.get(field); | |
| 2743 generator.GenerateMergingCode(printer); | |
| 2744 } | |
| 2745 | |
| 2746 // Merge Optional and Required fields (after a _has_bit check). | |
| 2747 int last_chunk = -1; | |
| 2748 int last_chunk_start = -1; | |
| 2749 int last_chunk_end = -1; | |
| 2750 uint32 last_chunk_mask = 0; | |
| 2751 for (; i < optimized_order_.size(); i++) { | |
| 2752 const FieldDescriptor* field = optimized_order_[i]; | |
| 2753 if (field->is_repeated()) { | |
| 2754 break; | |
| 2755 } | |
| 2756 | |
| 2757 // "index" defines where in the _has_bits_ the field appears. | |
| 2758 // "i" is our loop counter within optimized_order_. | |
| 2759 int index = HasFieldPresence(descriptor_->file()) ? | |
| 2760 has_bit_indices_[field->index()] : 0; | |
| 2761 int chunk = index / 8; | |
| 2762 | |
| 2763 if (last_chunk == -1) { | |
| 2764 last_chunk = chunk; | |
| 2765 last_chunk_start = i; | |
| 2766 } else if (chunk != last_chunk) { | |
| 2767 // Emit the fields for this chunk so far. | |
| 2768 break; | |
| 2769 } | |
| 2770 | |
| 2771 last_chunk_end = i; | |
| 2772 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); | |
| 2773 } | |
| 2774 | |
| 2775 if (last_chunk != -1) { | |
| 2776 GOOGLE_DCHECK_NE(-1, last_chunk_start); | |
| 2777 GOOGLE_DCHECK_NE(-1, last_chunk_end); | |
| 2778 GOOGLE_DCHECK_NE(0, last_chunk_mask); | |
| 2779 | |
| 2780 const int count = popcnt(last_chunk_mask); | |
| 2781 const bool have_outer_if = HasFieldPresence(descriptor_->file()) && | |
| 2782 (last_chunk_start != last_chunk_end); | |
| 2783 | |
| 2784 if (have_outer_if) { | |
| 2785 // Check (up to) 8 has_bits at a time if we have more than one field in | |
| 2786 // this chunk. Due to field layout ordering, we may check | |
| 2787 // _has_bits_[last_chunk * 8 / 32] multiple times. | |
| 2788 GOOGLE_DCHECK_LE(2, count); | |
| 2789 GOOGLE_DCHECK_GE(8, count); | |
| 2790 | |
| 2791 printer->Print( | |
| 2792 "if (from._has_bits_[$index$ / 32] & $mask$u) {\n", | |
| 2793 "index", SimpleItoa(last_chunk * 8), | |
| 2794 "mask", SimpleItoa(last_chunk_mask)); | |
| 2795 printer->Indent(); | |
| 2796 } | |
| 2797 | |
| 2798 // Go back and emit clears for each of the fields we processed. | |
| 2799 for (int j = last_chunk_start; j <= last_chunk_end; j++) { | |
| 2800 const FieldDescriptor* field = optimized_order_[j]; | |
| 2801 const FieldGenerator& generator = field_generators_.get(field); | |
| 2802 | |
| 2803 bool have_enclosing_if = false; | |
| 2804 if (HasFieldPresence(descriptor_->file())) { | |
| 2805 printer->Print( | |
| 2806 "if (from.has_$name$()) {\n", | |
| 2807 "name", FieldName(field)); | |
| 2808 printer->Indent(); | |
| 2809 have_enclosing_if = true; | |
| 2810 } else { | |
| 2811 // Merge semantics without true field presence: primitive fields are | |
| 2812 // merged only if non-zero (numeric) or non-empty (string). | |
| 2813 have_enclosing_if = EmitFieldNonDefaultCondition( | |
| 2814 printer, "from.", field); | |
| 2815 } | |
| 2816 | |
| 2817 generator.GenerateMergingCode(printer); | |
| 2818 | |
| 2819 if (have_enclosing_if) { | |
| 2820 printer->Outdent(); | |
| 2821 printer->Print("}\n"); | |
| 2822 } | |
| 2823 } | |
| 2824 | |
| 2825 if (have_outer_if) { | |
| 2826 printer->Outdent(); | |
| 2827 printer->Print("}\n"); | |
| 2828 } | |
| 2829 } | 2754 } |
| 2830 } | 2755 } |
| 2831 | 2756 |
| 2832 // Merge oneof fields. Oneof field requires oneof case check. | 2757 // Merge oneof fields. Oneof field requires oneof case check. |
| 2833 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { | 2758 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { |
| 2834 printer->Print( | 2759 printer->Print( |
| 2835 "switch (from.$oneofname$_case()) {\n", | 2760 "switch (from.$oneofname$_case()) {\n", |
| 2836 "oneofname", descriptor_->oneof_decl(i)->name()); | 2761 "oneofname", descriptor_->oneof_decl(i)->name()); |
| 2837 printer->Indent(); | 2762 printer->Indent(); |
| 2838 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | 2763 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2852 "case $cap_oneof_name$_NOT_SET: {\n" | 2777 "case $cap_oneof_name$_NOT_SET: {\n" |
| 2853 " break;\n" | 2778 " break;\n" |
| 2854 "}\n", | 2779 "}\n", |
| 2855 "cap_oneof_name", | 2780 "cap_oneof_name", |
| 2856 ToUpper(descriptor_->oneof_decl(i)->name())); | 2781 ToUpper(descriptor_->oneof_decl(i)->name())); |
| 2857 printer->Outdent(); | 2782 printer->Outdent(); |
| 2858 printer->Print( | 2783 printer->Print( |
| 2859 "}\n"); | 2784 "}\n"); |
| 2860 } | 2785 } |
| 2861 | 2786 |
| 2787 // Merge Optional and Required fields (after a _has_bit check). |
| 2788 int last_index = -1; |
| 2789 |
| 2790 for (int i = 0; i < descriptor_->field_count(); ++i) { |
| 2791 const FieldDescriptor* field = descriptor_->field(i); |
| 2792 |
| 2793 if (!field->is_repeated() && !field->containing_oneof()) { |
| 2794 if (HasFieldPresence(descriptor_->file())) { |
| 2795 // See above in GenerateClear for an explanation of this. |
| 2796 if (i / 8 != last_index / 8 || last_index < 0) { |
| 2797 if (last_index >= 0) { |
| 2798 printer->Outdent(); |
| 2799 printer->Print("}\n"); |
| 2800 } |
| 2801 printer->Print( |
| 2802 "if (from._has_bits_[$index$ / 32] & " |
| 2803 "(0xffu << ($index$ % 32))) {\n", |
| 2804 "index", SimpleItoa(field->index())); |
| 2805 printer->Indent(); |
| 2806 } |
| 2807 } |
| 2808 |
| 2809 last_index = i; |
| 2810 |
| 2811 bool have_enclosing_if = false; |
| 2812 if (HasFieldPresence(descriptor_->file())) { |
| 2813 printer->Print( |
| 2814 "if (from.has_$name$()) {\n", |
| 2815 "name", FieldName(field)); |
| 2816 printer->Indent(); |
| 2817 have_enclosing_if = true; |
| 2818 } else { |
| 2819 // Merge semantics without true field presence: primitive fields are |
| 2820 // merged only if non-zero (numeric) or non-empty (string). |
| 2821 have_enclosing_if = EmitFieldNonDefaultCondition( |
| 2822 printer, "from.", field); |
| 2823 } |
| 2824 |
| 2825 field_generators_.get(field).GenerateMergingCode(printer); |
| 2826 |
| 2827 if (have_enclosing_if) { |
| 2828 printer->Outdent(); |
| 2829 printer->Print("}\n"); |
| 2830 } |
| 2831 } |
| 2832 } |
| 2833 |
| 2834 if (HasFieldPresence(descriptor_->file()) && |
| 2835 last_index >= 0) { |
| 2836 printer->Outdent(); |
| 2837 printer->Print("}\n"); |
| 2838 } |
| 2839 |
| 2840 if (descriptor_->extension_range_count() > 0) { |
| 2841 printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); |
| 2842 } |
| 2843 |
| 2844 if (PreserveUnknownFields(descriptor_)) { |
| 2845 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2846 printer->Print( |
| 2847 "if (from._internal_metadata_.have_unknown_fields()) {\n" |
| 2848 " mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n" |
| 2849 "}\n"); |
| 2850 } else { |
| 2851 printer->Print( |
| 2852 "if (!from.unknown_fields().empty()) {\n" |
| 2853 " mutable_unknown_fields()->append(from.unknown_fields());\n" |
| 2854 "}\n"); |
| 2855 } |
| 2856 } |
| 2857 |
| 2862 printer->Outdent(); | 2858 printer->Outdent(); |
| 2863 printer->Print("}\n"); | 2859 printer->Print("}\n"); |
| 2864 } | 2860 } |
| 2865 | 2861 |
| 2866 void MessageGenerator:: | 2862 void MessageGenerator:: |
| 2867 GenerateCopyFrom(io::Printer* printer) { | 2863 GenerateCopyFrom(io::Printer* printer) { |
| 2868 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 2864 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
| 2869 // Generate the generalized CopyFrom (aka that which takes in the Message | 2865 // Generate the generalized CopyFrom (aka that which takes in the Message |
| 2870 // base class as a parameter). | 2866 // base class as a parameter). |
| 2871 printer->Print( | 2867 printer->Print( |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2903 | 2899 |
| 2904 void MessageGenerator:: | 2900 void MessageGenerator:: |
| 2905 GenerateMergeFromCodedStream(io::Printer* printer) { | 2901 GenerateMergeFromCodedStream(io::Printer* printer) { |
| 2906 if (descriptor_->options().message_set_wire_format()) { | 2902 if (descriptor_->options().message_set_wire_format()) { |
| 2907 // Special-case MessageSet. | 2903 // Special-case MessageSet. |
| 2908 printer->Print( | 2904 printer->Print( |
| 2909 "bool $classname$::MergePartialFromCodedStream(\n" | 2905 "bool $classname$::MergePartialFromCodedStream(\n" |
| 2910 " ::google::protobuf::io::CodedInputStream* input) {\n", | 2906 " ::google::protobuf::io::CodedInputStream* input) {\n", |
| 2911 "classname", classname_); | 2907 "classname", classname_); |
| 2912 | 2908 |
| 2913 printer->Print( | 2909 PrintHandlingOptionalStaticInitializers( |
| 2914 " return _extensions_.ParseMessageSet(input, " | 2910 descriptor_->file(), options_, printer, |
| 2915 "internal_default_instance(),\n" | 2911 // With static initializers. |
| 2912 " return _extensions_.ParseMessageSet(input, default_instance_,\n" |
| 2913 " mutable_unknown_fields());\n", |
| 2914 // Without. |
| 2915 " return _extensions_.ParseMessageSet(input, &default_instance(),\n" |
| 2916 " mutable_unknown_fields());\n", | 2916 " mutable_unknown_fields());\n", |
| 2917 // Vars. | 2917 // Vars. |
| 2918 "classname", classname_); | 2918 "classname", classname_); |
| 2919 | 2919 |
| 2920 printer->Print( | 2920 printer->Print( |
| 2921 "}\n"); | 2921 "}\n"); |
| 2922 return; | 2922 return; |
| 2923 } | 2923 } |
| 2924 | 2924 |
| 2925 printer->Print( | 2925 printer->Print( |
| 2926 "bool $classname$::MergePartialFromCodedStream(\n" | 2926 "bool $classname$::MergePartialFromCodedStream(\n" |
| 2927 " ::google::protobuf::io::CodedInputStream* input) {\n" | 2927 " ::google::protobuf::io::CodedInputStream* input) {\n" |
| 2928 "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\
n" | 2928 "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\
n" |
| 2929 " ::google::protobuf::uint32 tag;\n", | 2929 " ::google::protobuf::uint32 tag;\n", |
| 2930 "classname", classname_); | 2930 "classname", classname_); |
| 2931 | 2931 |
| 2932 if (PreserveUnknownFields(descriptor_) && | 2932 if (PreserveUnknownFields(descriptor_) && |
| 2933 !UseUnknownFieldSet(descriptor_->file(), options_)) { | 2933 !UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 2934 // Use LazyStringOutputString to avoid initializing unknown fields string | 2934 // Use LazyStringOutputString to avoid initializing unknown fields string |
| 2935 // unless it is actually needed. For the same reason, disable eager refresh | 2935 // unless it is actually needed. For the same reason, disable eager refresh |
| 2936 // on the CodedOutputStream. | 2936 // on the CodedOutputStream. |
| 2937 printer->Print( | 2937 printer->Print( |
| 2938 " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n
" | 2938 " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n
" |
| 2939 " NewPermanentCallback(\n" | 2939 " ::google::protobuf::internal::NewPermanentCallback(\n" |
| 2940 " &MutableUnknownFieldsFor$classname$, this));\n" | 2940 " &MutableUnknownFieldsFor$classname$, this));\n" |
| 2941 " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" | 2941 " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" |
| 2942 " &unknown_fields_string, false);\n", | 2942 " &unknown_fields_string, false);\n", |
| 2943 "classname", classname_); | 2943 "classname", classname_); |
| 2944 } | 2944 } |
| 2945 | 2945 |
| 2946 printer->Print( | 2946 printer->Print( |
| 2947 " // @@protoc_insertion_point(parse_start:$full_name$)\n", | 2947 " // @@protoc_insertion_point(parse_start:$full_name$)\n", |
| 2948 "full_name", descriptor_->full_name()); | 2948 "full_name", descriptor_->full_name()); |
| 2949 | 2949 |
| 2950 printer->Indent(); | 2950 printer->Indent(); |
| 2951 printer->Print("for (;;) {\n"); | 2951 printer->Print("for (;;) {\n"); |
| 2952 printer->Indent(); | 2952 printer->Indent(); |
| 2953 | 2953 |
| 2954 std::vector<const FieldDescriptor*> ordered_fields = | 2954 google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields( |
| 2955 SortFieldsByNumber(descriptor_); | 2955 SortFieldsByNumber(descriptor_)); |
| 2956 uint32 maxtag = descriptor_->field_count() == 0 ? 0 : | 2956 uint32 maxtag = descriptor_->field_count() == 0 ? 0 : |
| 2957 WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); | 2957 WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); |
| 2958 const int kCutoff0 = 127; // fits in 1-byte varint | 2958 const int kCutoff0 = 127; // fits in 1-byte varint |
| 2959 const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint | 2959 const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint |
| 2960 | |
| 2961 // We need to capture the last tag when parsing if this is a Group type, as | |
| 2962 // our caller will verify (via CodedInputStream::LastTagWas) that the correct | |
| 2963 // closing tag was received. | |
| 2964 bool capture_last_tag = false; | |
| 2965 const Descriptor* parent = descriptor_->containing_type(); | |
| 2966 if (parent) { | |
| 2967 for (int i = 0; i < parent->field_count(); i++) { | |
| 2968 const FieldDescriptor* field = parent->field(i); | |
| 2969 if (field->type() == FieldDescriptor::TYPE_GROUP && | |
| 2970 field->message_type() == descriptor_) { | |
| 2971 capture_last_tag = true; | |
| 2972 break; | |
| 2973 } | |
| 2974 } | |
| 2975 } | |
| 2976 | |
| 2977 for (int i = 0; i < descriptor_->file()->extension_count(); i++) { | |
| 2978 const FieldDescriptor* field = descriptor_->file()->extension(i); | |
| 2979 if (field->type() == FieldDescriptor::TYPE_GROUP && | |
| 2980 field->message_type() == descriptor_) { | |
| 2981 capture_last_tag = true; | |
| 2982 break; | |
| 2983 } | |
| 2984 } | |
| 2985 | |
| 2986 printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " | 2960 printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " |
| 2987 "input->ReadTagWithCutoff$lasttag$($max$u);\n" | 2961 "input->ReadTagWithCutoff($max$);\n" |
| 2988 "tag = p.first;\n" | 2962 "tag = p.first;\n" |
| 2989 "if (!p.second) goto handle_unusual;\n", | 2963 "if (!p.second) goto handle_unusual;\n", |
| 2990 "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : | 2964 "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : |
| 2991 (maxtag <= kCutoff1 ? kCutoff1 : | 2965 (maxtag <= kCutoff1 ? kCutoff1 : |
| 2992 maxtag)), | 2966 maxtag))); |
| 2993 "lasttag", !capture_last_tag ? "NoLastTag" : ""); | |
| 2994 | |
| 2995 if (descriptor_->field_count() > 0) { | 2967 if (descriptor_->field_count() > 0) { |
| 2996 // We don't even want to print the switch() if we have no fields because | 2968 // We don't even want to print the switch() if we have no fields because |
| 2997 // MSVC dislikes switch() statements that contain only a default value. | 2969 // MSVC dislikes switch() statements that contain only a default value. |
| 2998 | 2970 |
| 2999 // Note: If we just switched on the tag rather than the field number, we | 2971 // Note: If we just switched on the tag rather than the field number, we |
| 3000 // could avoid the need for the if() to check the wire type at the beginning | 2972 // could avoid the need for the if() to check the wire type at the beginning |
| 3001 // of each case. However, this is actually a bit slower in practice as it | 2973 // of each case. However, this is actually a bit slower in practice as it |
| 3002 // creates a jump table that is 8x larger and sparser, and meanwhile the | 2974 // creates a jump table that is 8x larger and sparser, and meanwhile the |
| 3003 // if()s are highly predictable. | 2975 // if()s are highly predictable. |
| 3004 // | |
| 3005 // Historically, we inserted checks to peek at the next tag on the wire and | |
| 3006 // jump directly to the next case statement. While this avoids the jump | |
| 3007 // table that the switch uses, it greatly increases code size (20-60%) and | |
| 3008 // inserts branches that may fail (especially for real world protos that | |
| 3009 // interleave--in field number order--hot and cold fields). Loadtests | |
| 3010 // confirmed that removing this optimization is performance neutral. | |
| 3011 printer->Print("switch (::google::protobuf::internal::WireFormatLite::" | 2976 printer->Print("switch (::google::protobuf::internal::WireFormatLite::" |
| 3012 "GetTagFieldNumber(tag)) {\n"); | 2977 "GetTagFieldNumber(tag)) {\n"); |
| 3013 | 2978 |
| 3014 printer->Indent(); | 2979 printer->Indent(); |
| 3015 | 2980 |
| 3016 // Find repeated messages and groups now, to simplify what follows. | 2981 // Find repeated messages and groups now, to simplify what follows. |
| 3017 hash_set<int> fields_with_parse_loop; | 2982 hash_set<int> fields_with_parse_loop; |
| 3018 for (int i = 0; i < ordered_fields.size(); i++) { | 2983 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3019 const FieldDescriptor* field = ordered_fields[i]; | 2984 const FieldDescriptor* field = ordered_fields[i]; |
| 3020 if (field->is_repeated() && | 2985 if (field->is_repeated() && |
| 3021 (field->type() == FieldDescriptor::TYPE_MESSAGE || | 2986 (field->type() == FieldDescriptor::TYPE_MESSAGE || |
| 3022 field->type() == FieldDescriptor::TYPE_GROUP)) { | 2987 field->type() == FieldDescriptor::TYPE_GROUP)) { |
| 3023 fields_with_parse_loop.insert(i); | 2988 fields_with_parse_loop.insert(i); |
| 3024 } | 2989 } |
| 3025 } | 2990 } |
| 3026 | 2991 |
| 3027 for (int i = 0; i < ordered_fields.size(); i++) { | 2992 // need_label is true if we generated "goto parse_$name$" while handling the |
| 2993 // previous field. |
| 2994 bool need_label = false; |
| 2995 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3028 const FieldDescriptor* field = ordered_fields[i]; | 2996 const FieldDescriptor* field = ordered_fields[i]; |
| 3029 const bool loops = fields_with_parse_loop.count(i) > 0; | 2997 const bool loops = fields_with_parse_loop.count(i) > 0; |
| 2998 const bool next_field_loops = fields_with_parse_loop.count(i + 1) > 0; |
| 3030 | 2999 |
| 3031 PrintFieldComment(printer, field); | 3000 PrintFieldComment(printer, field); |
| 3032 | 3001 |
| 3033 printer->Print( | 3002 printer->Print( |
| 3034 "case $number$: {\n", | 3003 "case $number$: {\n", |
| 3035 "number", SimpleItoa(field->number())); | 3004 "number", SimpleItoa(field->number())); |
| 3036 printer->Indent(); | 3005 printer->Indent(); |
| 3037 const FieldGenerator& field_generator = field_generators_.get(field); | 3006 const FieldGenerator& field_generator = field_generators_.get(field); |
| 3038 | 3007 |
| 3039 // Emit code to parse the common, expected case. | 3008 // Emit code to parse the common, expected case. |
| 3040 printer->Print("if (tag == $commontag$u) {\n", | 3009 printer->Print("if (tag == $commontag$) {\n", |
| 3041 "commontag", SimpleItoa(WireFormat::MakeTag(field))); | 3010 "commontag", SimpleItoa(WireFormat::MakeTag(field))); |
| 3042 | 3011 |
| 3012 if (need_label || |
| 3013 (field->is_repeated() && !field->is_packed() && !loops)) { |
| 3014 printer->Print( |
| 3015 " parse_$name$:\n", |
| 3016 "name", field->name()); |
| 3017 } |
| 3043 if (loops) { | 3018 if (loops) { |
| 3044 printer->Print(" DO_(input->IncrementRecursionDepth());\n"); | 3019 printer->Print( |
| 3020 " DO_(input->IncrementRecursionDepth());\n" |
| 3021 " parse_loop_$name$:\n", |
| 3022 "name", field->name()); |
| 3045 } | 3023 } |
| 3046 | 3024 |
| 3047 printer->Indent(); | 3025 printer->Indent(); |
| 3048 if (field->is_packed()) { | 3026 if (field->is_packed()) { |
| 3049 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); | 3027 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); |
| 3050 } else { | 3028 } else { |
| 3051 field_generator.GenerateMergeFromCodedStream(printer); | 3029 field_generator.GenerateMergeFromCodedStream(printer); |
| 3052 } | 3030 } |
| 3053 printer->Outdent(); | 3031 printer->Outdent(); |
| 3054 | 3032 |
| 3055 // Emit code to parse unexpectedly packed or unpacked values. | 3033 // Emit code to parse unexpectedly packed or unpacked values. |
| 3056 if (field->is_packed()) { | 3034 if (field->is_packed()) { |
| 3057 internal::WireFormatLite::WireType wiretype = | 3035 internal::WireFormatLite::WireType wiretype = |
| 3058 WireFormat::WireTypeForFieldType(field->type()); | 3036 WireFormat::WireTypeForFieldType(field->type()); |
| 3059 printer->Print("} else if (tag == $uncommontag$u) {\n", | 3037 printer->Print("} else if (tag == $uncommontag$) {\n", |
| 3060 "uncommontag", SimpleItoa( | 3038 "uncommontag", SimpleItoa( |
| 3061 internal::WireFormatLite::MakeTag( | 3039 internal::WireFormatLite::MakeTag( |
| 3062 field->number(), wiretype))); | 3040 field->number(), wiretype))); |
| 3063 printer->Indent(); | 3041 printer->Indent(); |
| 3064 field_generator.GenerateMergeFromCodedStream(printer); | 3042 field_generator.GenerateMergeFromCodedStream(printer); |
| 3065 printer->Outdent(); | 3043 printer->Outdent(); |
| 3066 } else if (field->is_packable() && !field->is_packed()) { | 3044 } else if (field->is_packable() && !field->is_packed()) { |
| 3067 internal::WireFormatLite::WireType wiretype = | 3045 internal::WireFormatLite::WireType wiretype = |
| 3068 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; | 3046 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; |
| 3069 printer->Print("} else if (tag == $uncommontag$u) {\n", | 3047 printer->Print("} else if (tag == $uncommontag$) {\n", |
| 3070 "uncommontag", SimpleItoa( | 3048 "uncommontag", SimpleItoa( |
| 3071 internal::WireFormatLite::MakeTag( | 3049 internal::WireFormatLite::MakeTag( |
| 3072 field->number(), wiretype))); | 3050 field->number(), wiretype))); |
| 3073 printer->Indent(); | 3051 printer->Indent(); |
| 3074 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); | 3052 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); |
| 3075 printer->Outdent(); | 3053 printer->Outdent(); |
| 3076 } | 3054 } |
| 3077 | 3055 |
| 3078 printer->Print( | 3056 printer->Print( |
| 3079 "} else {\n" | 3057 "} else {\n" |
| 3080 " goto handle_unusual;\n" | 3058 " goto handle_unusual;\n" |
| 3081 "}\n"); | 3059 "}\n"); |
| 3082 | 3060 |
| 3083 // For repeated messages/groups, we need to decrement recursion depth. | 3061 // switch() is slow since it can't be predicted well. Insert some if()s |
| 3062 // here that attempt to predict the next tag. |
| 3063 // For non-packed repeated fields, expect the same tag again. |
| 3084 if (loops) { | 3064 if (loops) { |
| 3085 printer->Print( | 3065 printer->Print( |
| 3086 "input->UnsafeDecrementRecursionDepth();\n"); | 3066 "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n", |
| 3067 "tag", SimpleItoa(WireFormat::MakeTag(field)), |
| 3068 "name", field->name()); |
| 3069 } else if (field->is_repeated() && !field->is_packed()) { |
| 3070 printer->Print( |
| 3071 "if (input->ExpectTag($tag$)) goto parse_$name$;\n", |
| 3072 "tag", SimpleItoa(WireFormat::MakeTag(field)), |
| 3073 "name", field->name()); |
| 3074 } |
| 3075 |
| 3076 // Have we emitted "if (input->ExpectTag($next_tag$)) ..." yet? |
| 3077 bool emitted_goto_next_tag = false; |
| 3078 |
| 3079 // For repeated messages/groups, we need to decrement recursion depth, |
| 3080 // unless the next tag is also for a repeated message/group. |
| 3081 if (loops) { |
| 3082 if (next_field_loops) { |
| 3083 const FieldDescriptor* next_field = ordered_fields[i + 1]; |
| 3084 printer->Print( |
| 3085 "if (input->ExpectTag($next_tag$)) goto parse_loop_$next_name$;\n", |
| 3086 "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), |
| 3087 "next_name", next_field->name()); |
| 3088 emitted_goto_next_tag = true; |
| 3089 } |
| 3090 printer->Print( |
| 3091 "input->UnsafeDecrementRecursionDepth();\n"); |
| 3092 } |
| 3093 |
| 3094 // If there are more fields, expect the next one. |
| 3095 need_label = false; |
| 3096 if (!emitted_goto_next_tag) { |
| 3097 if (i + 1 == descriptor_->field_count()) { |
| 3098 // Expect EOF. |
| 3099 // TODO(kenton): Expect group end-tag? |
| 3100 printer->Print( |
| 3101 "if (input->ExpectAtEnd()) goto success;\n"); |
| 3102 } else { |
| 3103 const FieldDescriptor* next_field = ordered_fields[i + 1]; |
| 3104 printer->Print( |
| 3105 "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n", |
| 3106 "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), |
| 3107 "next_name", next_field->name()); |
| 3108 need_label = true; |
| 3109 } |
| 3087 } | 3110 } |
| 3088 | 3111 |
| 3089 printer->Print( | 3112 printer->Print( |
| 3090 "break;\n"); | 3113 "break;\n"); |
| 3091 | 3114 |
| 3092 printer->Outdent(); | 3115 printer->Outdent(); |
| 3093 printer->Print("}\n\n"); | 3116 printer->Print("}\n\n"); |
| 3094 } | 3117 } |
| 3095 | 3118 |
| 3096 printer->Print("default: {\n"); | 3119 printer->Print("default: {\n"); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3129 } else { | 3152 } else { |
| 3130 printer->Print( | 3153 printer->Print( |
| 3131 "($start$u <= tag && tag < $end$u)", | 3154 "($start$u <= tag && tag < $end$u)", |
| 3132 "start", SimpleItoa(start_tag), | 3155 "start", SimpleItoa(start_tag), |
| 3133 "end", SimpleItoa(end_tag)); | 3156 "end", SimpleItoa(end_tag)); |
| 3134 } | 3157 } |
| 3135 } | 3158 } |
| 3136 printer->Print(") {\n"); | 3159 printer->Print(") {\n"); |
| 3137 if (PreserveUnknownFields(descriptor_)) { | 3160 if (PreserveUnknownFields(descriptor_)) { |
| 3138 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 3161 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 3139 printer->Print( | 3162 PrintHandlingOptionalStaticInitializers( |
| 3140 " DO_(_extensions_.ParseField(tag, input, " | 3163 descriptor_->file(), options_, printer, |
| 3141 "internal_default_instance(),\n" | 3164 // With static initializers. |
| 3165 " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" |
| 3166 " mutable_unknown_fields()));\n", |
| 3167 // Without. |
| 3168 " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" |
| 3142 " mutable_unknown_fields()));\n"); | 3169 " mutable_unknown_fields()));\n"); |
| 3143 } else { | 3170 } else { |
| 3144 printer->Print( | 3171 PrintHandlingOptionalStaticInitializers( |
| 3145 " DO_(_extensions_.ParseField(tag, input, " | 3172 descriptor_->file(), options_, printer, |
| 3146 "internal_default_instance(),\n" | 3173 // With static initializers. |
| 3174 " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" |
| 3175 " &unknown_fields_stream));\n", |
| 3176 // Without. |
| 3177 " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" |
| 3147 " &unknown_fields_stream));\n"); | 3178 " &unknown_fields_stream));\n"); |
| 3148 } | 3179 } |
| 3149 } else { | 3180 } else { |
| 3150 printer->Print( | 3181 PrintHandlingOptionalStaticInitializers( |
| 3182 descriptor_->file(), options_, printer, |
| 3151 // With static initializers. | 3183 // With static initializers. |
| 3152 " DO_(_extensions_.ParseField(tag, input, " | 3184 " DO_(_extensions_.ParseField(tag, input, default_instance_);\n", |
| 3153 "internal_default_instance());\n"); | 3185 // Without. |
| 3186 " DO_(_extensions_.ParseField(tag, input, &default_instance());\n"); |
| 3154 } | 3187 } |
| 3155 printer->Print( | 3188 printer->Print( |
| 3156 " continue;\n" | 3189 " continue;\n" |
| 3157 "}\n"); | 3190 "}\n"); |
| 3158 } | 3191 } |
| 3159 | 3192 |
| 3160 // We really don't recognize this tag. Skip it. | 3193 // We really don't recognize this tag. Skip it. |
| 3161 if (PreserveUnknownFields(descriptor_)) { | 3194 if (PreserveUnknownFields(descriptor_)) { |
| 3162 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 3195 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 3163 printer->Print( | 3196 printer->Print( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3188 "success:\n" | 3221 "success:\n" |
| 3189 " // @@protoc_insertion_point(parse_success:$full_name$)\n" | 3222 " // @@protoc_insertion_point(parse_success:$full_name$)\n" |
| 3190 " return true;\n" | 3223 " return true;\n" |
| 3191 "failure:\n" | 3224 "failure:\n" |
| 3192 " // @@protoc_insertion_point(parse_failure:$full_name$)\n" | 3225 " // @@protoc_insertion_point(parse_failure:$full_name$)\n" |
| 3193 " return false;\n" | 3226 " return false;\n" |
| 3194 "#undef DO_\n" | 3227 "#undef DO_\n" |
| 3195 "}\n", "full_name", descriptor_->full_name()); | 3228 "}\n", "full_name", descriptor_->full_name()); |
| 3196 } | 3229 } |
| 3197 | 3230 |
| 3198 void MessageGenerator::GenerateSerializeOneofFields( | |
| 3199 io::Printer* printer, const std::vector<const FieldDescriptor*>& fields, | |
| 3200 bool to_array) { | |
| 3201 GOOGLE_CHECK(!fields.empty()); | |
| 3202 if (fields.size() == 1) { | |
| 3203 GenerateSerializeOneField(printer, fields[0], to_array); | |
| 3204 return; | |
| 3205 } | |
| 3206 // We have multiple mutually exclusive choices. Emit a switch statement. | |
| 3207 const OneofDescriptor* oneof = fields[0]->containing_oneof(); | |
| 3208 printer->Print( | |
| 3209 "switch ($oneofname$_case()) {\n", | |
| 3210 "oneofname", oneof->name()); | |
| 3211 printer->Indent(); | |
| 3212 for (int i = 0; i < fields.size(); i++) { | |
| 3213 const FieldDescriptor* field = fields[i]; | |
| 3214 printer->Print( | |
| 3215 "case k$field_name$:\n", | |
| 3216 "field_name", UnderscoresToCamelCase(field->name(), true)); | |
| 3217 printer->Indent(); | |
| 3218 if (to_array) { | |
| 3219 field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( | |
| 3220 printer); | |
| 3221 } else { | |
| 3222 field_generators_.get(field).GenerateSerializeWithCachedSizes(printer); | |
| 3223 } | |
| 3224 printer->Print( | |
| 3225 "break;\n"); | |
| 3226 printer->Outdent(); | |
| 3227 } | |
| 3228 printer->Outdent(); | |
| 3229 // Doing nothing is an option. | |
| 3230 printer->Print( | |
| 3231 " default: ;\n" | |
| 3232 "}\n"); | |
| 3233 } | |
| 3234 | |
| 3235 void MessageGenerator::GenerateSerializeOneField( | 3231 void MessageGenerator::GenerateSerializeOneField( |
| 3236 io::Printer* printer, const FieldDescriptor* field, bool to_array) { | 3232 io::Printer* printer, const FieldDescriptor* field, bool to_array) { |
| 3237 PrintFieldComment(printer, field); | 3233 PrintFieldComment(printer, field); |
| 3238 | 3234 |
| 3239 bool have_enclosing_if = false; | 3235 bool have_enclosing_if = false; |
| 3240 if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) { | 3236 if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) { |
| 3241 printer->Print( | 3237 printer->Print( |
| 3242 "if (has_$name$()) {\n", | 3238 "if (has_$name$()) {\n", |
| 3243 "name", FieldName(field)); | 3239 "name", FieldName(field)); |
| 3244 printer->Indent(); | 3240 printer->Indent(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3257 if (have_enclosing_if) { | 3253 if (have_enclosing_if) { |
| 3258 printer->Outdent(); | 3254 printer->Outdent(); |
| 3259 printer->Print("}\n"); | 3255 printer->Print("}\n"); |
| 3260 } | 3256 } |
| 3261 printer->Print("\n"); | 3257 printer->Print("\n"); |
| 3262 } | 3258 } |
| 3263 | 3259 |
| 3264 void MessageGenerator::GenerateSerializeOneExtensionRange( | 3260 void MessageGenerator::GenerateSerializeOneExtensionRange( |
| 3265 io::Printer* printer, const Descriptor::ExtensionRange* range, | 3261 io::Printer* printer, const Descriptor::ExtensionRange* range, |
| 3266 bool to_array) { | 3262 bool to_array) { |
| 3267 std::map<string, string> vars; | 3263 map<string, string> vars; |
| 3268 vars["start"] = SimpleItoa(range->start); | 3264 vars["start"] = SimpleItoa(range->start); |
| 3269 vars["end"] = SimpleItoa(range->end); | 3265 vars["end"] = SimpleItoa(range->end); |
| 3270 printer->Print(vars, | 3266 printer->Print(vars, |
| 3271 "// Extension range [$start$, $end$)\n"); | 3267 "// Extension range [$start$, $end$)\n"); |
| 3272 if (to_array) { | 3268 if (to_array) { |
| 3273 printer->Print(vars, | 3269 printer->Print(vars, |
| 3274 "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n" | 3270 "target = _extensions_.SerializeWithCachedSizesToArray(\n" |
| 3275 " $start$, $end$, false, target);\n\n"); | 3271 " $start$, $end$, target);\n\n"); |
| 3276 } else { | 3272 } else { |
| 3277 printer->Print(vars, | 3273 printer->Print(vars, |
| 3278 "_extensions_.SerializeWithCachedSizes(\n" | 3274 "_extensions_.SerializeWithCachedSizes(\n" |
| 3279 " $start$, $end$, output);\n\n"); | 3275 " $start$, $end$, output);\n\n"); |
| 3280 } | 3276 } |
| 3281 } | 3277 } |
| 3282 | 3278 |
| 3283 void MessageGenerator:: | 3279 void MessageGenerator:: |
| 3284 GenerateSerializeWithCachedSizes(io::Printer* printer) { | 3280 GenerateSerializeWithCachedSizes(io::Printer* printer) { |
| 3285 if (descriptor_->options().message_set_wire_format()) { | 3281 if (descriptor_->options().message_set_wire_format()) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3317 printer->Outdent(); | 3313 printer->Outdent(); |
| 3318 printer->Print( | 3314 printer->Print( |
| 3319 "}\n"); | 3315 "}\n"); |
| 3320 } | 3316 } |
| 3321 | 3317 |
| 3322 void MessageGenerator:: | 3318 void MessageGenerator:: |
| 3323 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { | 3319 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { |
| 3324 if (descriptor_->options().message_set_wire_format()) { | 3320 if (descriptor_->options().message_set_wire_format()) { |
| 3325 // Special-case MessageSet. | 3321 // Special-case MessageSet. |
| 3326 printer->Print( | 3322 printer->Print( |
| 3327 "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesT
oArray(\n" | 3323 "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\
n" |
| 3328 " bool deterministic, ::google::protobuf::uint8* target) const {\n" | 3324 " ::google::protobuf::uint8* target) const {\n" |
| 3329 " target = _extensions_." | 3325 " target =\n" |
| 3330 "InternalSerializeMessageSetWithCachedSizesToArray(\n" | 3326 " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", |
| 3331 " deterministic, target);\n", | |
| 3332 "classname", classname_); | 3327 "classname", classname_); |
| 3333 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); | 3328 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); |
| 3334 printer->Print( | 3329 printer->Print( |
| 3335 " target = ::google::protobuf::internal::WireFormat::\n" | 3330 " target = ::google::protobuf::internal::WireFormat::\n" |
| 3336 " SerializeUnknownMessageSetItemsToArray(\n" | 3331 " SerializeUnknownMessageSetItemsToArray(\n" |
| 3337 " unknown_fields(), target);\n"); | 3332 " unknown_fields(), target);\n"); |
| 3338 printer->Print( | 3333 printer->Print( |
| 3339 " return target;\n" | 3334 " return target;\n" |
| 3340 "}\n"); | 3335 "}\n"); |
| 3341 return; | 3336 return; |
| 3342 } | 3337 } |
| 3343 | 3338 |
| 3344 printer->Print( | 3339 printer->Print( |
| 3345 "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToA
rray(\n" | 3340 "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" |
| 3346 " bool deterministic, ::google::protobuf::uint8* target) const {\n", | 3341 " ::google::protobuf::uint8* target) const {\n", |
| 3347 "classname", classname_); | 3342 "classname", classname_); |
| 3348 printer->Indent(); | 3343 printer->Indent(); |
| 3349 | 3344 |
| 3350 printer->Print("(void)deterministic; // Unused\n"); | |
| 3351 printer->Print( | 3345 printer->Print( |
| 3352 "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", | 3346 "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", |
| 3353 "full_name", descriptor_->full_name()); | 3347 "full_name", descriptor_->full_name()); |
| 3354 | 3348 |
| 3355 GenerateSerializeWithCachedSizesBody(printer, true); | 3349 GenerateSerializeWithCachedSizesBody(printer, true); |
| 3356 | 3350 |
| 3357 printer->Print( | 3351 printer->Print( |
| 3358 "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", | 3352 "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", |
| 3359 "full_name", descriptor_->full_name()); | 3353 "full_name", descriptor_->full_name()); |
| 3360 | 3354 |
| 3361 printer->Outdent(); | 3355 printer->Outdent(); |
| 3362 printer->Print( | 3356 printer->Print( |
| 3363 " return target;\n" | 3357 " return target;\n" |
| 3364 "}\n"); | 3358 "}\n"); |
| 3365 } | 3359 } |
| 3366 | 3360 |
| 3367 void MessageGenerator:: | 3361 void MessageGenerator:: |
| 3368 GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { | 3362 GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { |
| 3369 // If there are multiple fields in a row from the same oneof then we | 3363 google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields( |
| 3370 // coalesce them and emit a switch statement. This is more efficient | 3364 SortFieldsByNumber(descriptor_)); |
| 3371 // because it lets the C++ compiler know this is a "at most one can happen" | |
| 3372 // situation. If we emitted "if (has_x()) ...; if (has_y()) ..." the C++ | |
| 3373 // compiler's emitted code might check has_y() even when has_x() is true. | |
| 3374 class LazySerializerEmitter { | |
| 3375 public: | |
| 3376 LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer, | |
| 3377 bool to_array) | |
| 3378 : mg_(mg), | |
| 3379 printer_(printer), | |
| 3380 to_array_(to_array), | |
| 3381 eager_(!HasFieldPresence(mg->descriptor_->file())) {} | |
| 3382 | 3365 |
| 3383 ~LazySerializerEmitter() { Flush(); } | 3366 vector<const Descriptor::ExtensionRange*> sorted_extensions; |
| 3384 | |
| 3385 // If conditions allow, try to accumulate a run of fields from the same | |
| 3386 // oneof, and handle them at the next Flush(). | |
| 3387 void Emit(const FieldDescriptor* field) { | |
| 3388 if (eager_ || MustFlush(field)) { | |
| 3389 Flush(); | |
| 3390 } | |
| 3391 if (field->containing_oneof() == NULL) { | |
| 3392 mg_->GenerateSerializeOneField(printer_, field, to_array_); | |
| 3393 } else { | |
| 3394 v_.push_back(field); | |
| 3395 } | |
| 3396 } | |
| 3397 | |
| 3398 void Flush() { | |
| 3399 if (!v_.empty()) { | |
| 3400 mg_->GenerateSerializeOneofFields(printer_, v_, to_array_); | |
| 3401 v_.clear(); | |
| 3402 } | |
| 3403 } | |
| 3404 | |
| 3405 private: | |
| 3406 // If we have multiple fields in v_ then they all must be from the same | |
| 3407 // oneof. Would adding field to v_ break that invariant? | |
| 3408 bool MustFlush(const FieldDescriptor* field) { | |
| 3409 return !v_.empty() && | |
| 3410 v_[0]->containing_oneof() != field->containing_oneof(); | |
| 3411 } | |
| 3412 | |
| 3413 MessageGenerator* mg_; | |
| 3414 io::Printer* printer_; | |
| 3415 const bool to_array_; | |
| 3416 const bool eager_; | |
| 3417 std::vector<const FieldDescriptor*> v_; | |
| 3418 }; | |
| 3419 | |
| 3420 std::vector<const FieldDescriptor*> ordered_fields = | |
| 3421 SortFieldsByNumber(descriptor_); | |
| 3422 | |
| 3423 std::vector<const Descriptor::ExtensionRange*> sorted_extensions; | |
| 3424 for (int i = 0; i < descriptor_->extension_range_count(); ++i) { | 3367 for (int i = 0; i < descriptor_->extension_range_count(); ++i) { |
| 3425 sorted_extensions.push_back(descriptor_->extension_range(i)); | 3368 sorted_extensions.push_back(descriptor_->extension_range(i)); |
| 3426 } | 3369 } |
| 3427 std::sort(sorted_extensions.begin(), sorted_extensions.end(), | 3370 std::sort(sorted_extensions.begin(), sorted_extensions.end(), |
| 3428 ExtensionRangeSorter()); | 3371 ExtensionRangeSorter()); |
| 3429 | 3372 |
| 3430 // Merge the fields and the extension ranges, both sorted by field number. | 3373 // Merge the fields and the extension ranges, both sorted by field number. |
| 3431 { | 3374 int i, j; |
| 3432 LazySerializerEmitter e(this, printer, to_array); | 3375 for (i = 0, j = 0; |
| 3433 int i, j; | 3376 i < descriptor_->field_count() || j < sorted_extensions.size(); |
| 3434 for (i = 0, j = 0; | 3377 ) { |
| 3435 i < ordered_fields.size() || j < sorted_extensions.size();) { | 3378 if (i == descriptor_->field_count()) { |
| 3436 if (i == descriptor_->field_count()) { | 3379 GenerateSerializeOneExtensionRange(printer, |
| 3437 e.Flush(); | 3380 sorted_extensions[j++], |
| 3438 GenerateSerializeOneExtensionRange(printer, | 3381 to_array); |
| 3439 sorted_extensions[j++], | 3382 } else if (j == sorted_extensions.size()) { |
| 3440 to_array); | 3383 GenerateSerializeOneField(printer, ordered_fields[i++], to_array); |
| 3441 } else if (j == sorted_extensions.size()) { | 3384 } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) { |
| 3442 e.Emit(ordered_fields[i++]); | 3385 GenerateSerializeOneField(printer, ordered_fields[i++], to_array); |
| 3443 } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) { | 3386 } else { |
| 3444 e.Emit(ordered_fields[i++]); | 3387 GenerateSerializeOneExtensionRange(printer, |
| 3445 } else { | 3388 sorted_extensions[j++], |
| 3446 e.Flush(); | 3389 to_array); |
| 3447 GenerateSerializeOneExtensionRange(printer, | |
| 3448 sorted_extensions[j++], | |
| 3449 to_array); | |
| 3450 } | |
| 3451 } | 3390 } |
| 3452 } | 3391 } |
| 3453 | 3392 |
| 3454 if (PreserveUnknownFields(descriptor_)) { | 3393 if (PreserveUnknownFields(descriptor_)) { |
| 3455 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 3394 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 3456 printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n"); | 3395 printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n"); |
| 3457 printer->Indent(); | 3396 printer->Indent(); |
| 3458 if (to_array) { | 3397 if (to_array) { |
| 3459 printer->Print( | 3398 printer->Print( |
| 3460 "target = " | 3399 "target = " |
| 3461 "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsT
oArray(\n" | 3400 "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsT
oArray(\n" |
| 3462 " unknown_fields(), target);\n"); | 3401 " unknown_fields(), target);\n"); |
| 3463 } else { | 3402 } else { |
| 3464 printer->Print( | 3403 printer->Print( |
| 3465 "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" | 3404 "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" |
| 3466 " unknown_fields(), output);\n"); | 3405 " unknown_fields(), output);\n"); |
| 3467 } | 3406 } |
| 3468 printer->Outdent(); | 3407 printer->Outdent(); |
| 3469 | 3408 |
| 3470 printer->Print( | 3409 printer->Print( |
| 3471 "}\n"); | 3410 "}\n"); |
| 3472 } else { | 3411 } else { |
| 3473 printer->Print( | 3412 printer->Print( |
| 3474 "output->WriteRaw(unknown_fields().data(),\n" | 3413 "output->WriteRaw(unknown_fields().data(),\n" |
| 3475 " static_cast<int>(unknown_fields().size()));\n"); | 3414 " static_cast<int>(unknown_fields().size()));\n"); |
| 3476 } | 3415 } |
| 3477 } | 3416 } |
| 3478 } | 3417 } |
| 3479 | 3418 |
| 3480 std::vector<uint32> MessageGenerator::RequiredFieldsBitMask() const { | 3419 static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) { |
| 3481 const int array_size = HasBitsSize(); | 3420 vector<uint32> result; |
| 3482 std::vector<uint32> masks(array_size, 0); | 3421 uint32 mask = 0; |
| 3483 | 3422 for (int i = 0; i < desc->field_count(); i++) { |
| 3484 for (int i = 0; i < descriptor_->field_count(); i++) { | 3423 if (i > 0 && i % 32 == 0) { |
| 3485 const FieldDescriptor* field = descriptor_->field(i); | 3424 result.push_back(mask); |
| 3486 if (!field->is_required()) { | 3425 mask = 0; |
| 3487 continue; | |
| 3488 } | 3426 } |
| 3489 | 3427 if (desc->field(i)->is_required()) { |
| 3490 const int has_bit_index = has_bit_indices_[field->index()]; | 3428 mask |= (1 << (i & 31)); |
| 3491 masks[has_bit_index / 32] |= | 3429 } |
| 3492 static_cast<uint32>(1) << (has_bit_index % 32); | |
| 3493 } | 3430 } |
| 3494 return masks; | 3431 if (mask != 0) { |
| 3432 result.push_back(mask); |
| 3433 } |
| 3434 return result; |
| 3495 } | 3435 } |
| 3496 | 3436 |
| 3497 // Create an expression that evaluates to | 3437 // Create an expression that evaluates to |
| 3498 // "for all i, (_has_bits_[i] & masks[i]) == masks[i]" | 3438 // "for all i, (_has_bits_[i] & masks[i]) == masks[i]" |
| 3499 // masks is allowed to be shorter than _has_bits_, but at least one element of | 3439 // masks is allowed to be shorter than _has_bits_, but at least one element of |
| 3500 // masks must be non-zero. | 3440 // masks must be non-zero. |
| 3501 static string ConditionalToCheckBitmasks(const std::vector<uint32>& masks) { | 3441 static string ConditionalToCheckBitmasks(const vector<uint32>& masks) { |
| 3502 std::vector<string> parts; | 3442 vector<string> parts; |
| 3503 for (int i = 0; i < masks.size(); i++) { | 3443 for (int i = 0; i < masks.size(); i++) { |
| 3504 if (masks[i] == 0) continue; | 3444 if (masks[i] == 0) continue; |
| 3505 string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); | 3445 string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); |
| 3506 // Each xor evaluates to 0 if the expected bits are present. | 3446 // Each xor evaluates to 0 if the expected bits are present. |
| 3507 parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); | 3447 parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); |
| 3508 } | 3448 } |
| 3509 GOOGLE_CHECK(!parts.empty()); | 3449 GOOGLE_CHECK(!parts.empty()); |
| 3510 // If we have multiple parts, each expected to be 0, then bitwise-or them. | 3450 // If we have multiple parts, each expected to be 0, then bitwise-or them. |
| 3511 string result = parts.size() == 1 ? parts[0] : | 3451 string result = parts.size() == 1 ? parts[0] : |
| 3512 StrCat("(", Join(parts, "\n | "), ")"); | 3452 StrCat("(", Join(parts, "\n | "), ")"); |
| 3513 return result + " == 0"; | 3453 return result + " == 0"; |
| 3514 } | 3454 } |
| 3515 | 3455 |
| 3516 void MessageGenerator:: | 3456 void MessageGenerator:: |
| 3517 GenerateByteSize(io::Printer* printer) { | 3457 GenerateByteSize(io::Printer* printer) { |
| 3518 if (descriptor_->options().message_set_wire_format()) { | 3458 if (descriptor_->options().message_set_wire_format()) { |
| 3519 // Special-case MessageSet. | 3459 // Special-case MessageSet. |
| 3520 printer->Print( | 3460 printer->Print( |
| 3521 "size_t $classname$::ByteSizeLong() const {\n" | 3461 "int $classname$::ByteSize() const {\n" |
| 3522 "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" | 3462 "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" |
| 3523 " size_t total_size = _extensions_.MessageSetByteSize();\n", | 3463 " int total_size = _extensions_.MessageSetByteSize();\n", |
| 3524 "classname", classname_, "full_name", descriptor_->full_name()); | 3464 "classname", classname_, "full_name", descriptor_->full_name()); |
| 3525 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); | 3465 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); |
| 3526 printer->Print( | 3466 printer->Print( |
| 3527 "if (_internal_metadata_.have_unknown_fields()) {\n" | 3467 "if (_internal_metadata_.have_unknown_fields()) {\n" |
| 3528 " total_size += ::google::protobuf::internal::WireFormat::\n" | 3468 " total_size += ::google::protobuf::internal::WireFormat::\n" |
| 3529 " ComputeUnknownMessageSetItemsSize(unknown_fields());\n" | 3469 " ComputeUnknownMessageSetItemsSize(unknown_fields());\n" |
| 3530 "}\n"); | 3470 "}\n"); |
| 3531 printer->Print( | 3471 printer->Print( |
| 3532 " int cached_size = ::google::protobuf::internal::ToCachedSize(total_size
);\n" | |
| 3533 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" | 3472 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" |
| 3534 " _cached_size_ = cached_size;\n" | 3473 " _cached_size_ = total_size;\n" |
| 3535 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" | 3474 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" |
| 3536 " return total_size;\n" | 3475 " return total_size;\n" |
| 3537 "}\n"); | 3476 "}\n"); |
| 3538 return; | 3477 return; |
| 3539 } | 3478 } |
| 3540 | 3479 |
| 3541 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { | 3480 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { |
| 3542 // Emit a function (rarely used, we hope) that handles the required fields | 3481 // Emit a function (rarely used, we hope) that handles the required fields |
| 3543 // by checking for each one individually. | 3482 // by checking for each one individually. |
| 3544 printer->Print( | 3483 printer->Print( |
| 3545 "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n" | 3484 "int $classname$::RequiredFieldsByteSizeFallback() const {\n" |
| 3546 "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" | 3485 "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" |
| 3547 "$full_name$)\n", | 3486 "$full_name$)\n", |
| 3548 "classname", classname_, "full_name", descriptor_->full_name()); | 3487 "classname", classname_, "full_name", descriptor_->full_name()); |
| 3549 printer->Indent(); | 3488 printer->Indent(); |
| 3550 printer->Print("size_t total_size = 0;\n"); | 3489 printer->Print("int total_size = 0;\n"); |
| 3551 for (int i = 0; i < optimized_order_.size(); i++) { | 3490 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3552 const FieldDescriptor* field = optimized_order_[i]; | 3491 const FieldDescriptor* field = descriptor_->field(i); |
| 3553 if (field->is_required()) { | 3492 if (field->is_required()) { |
| 3554 printer->Print("\n" | 3493 printer->Print("\n" |
| 3555 "if (has_$name$()) {\n", | 3494 "if (has_$name$()) {\n", |
| 3556 "name", FieldName(field)); | 3495 "name", FieldName(field)); |
| 3557 printer->Indent(); | 3496 printer->Indent(); |
| 3558 PrintFieldComment(printer, field); | 3497 PrintFieldComment(printer, field); |
| 3559 field_generators_.get(field).GenerateByteSize(printer); | 3498 field_generators_.get(field).GenerateByteSize(printer); |
| 3560 printer->Outdent(); | 3499 printer->Outdent(); |
| 3561 printer->Print("}\n"); | 3500 printer->Print("}\n"); |
| 3562 } | 3501 } |
| 3563 } | 3502 } |
| 3564 printer->Print("\n" | 3503 printer->Print("\n" |
| 3565 "return total_size;\n"); | 3504 "return total_size;\n"); |
| 3566 printer->Outdent(); | 3505 printer->Outdent(); |
| 3567 printer->Print("}\n"); | 3506 printer->Print("}\n"); |
| 3568 } | 3507 } |
| 3569 | 3508 |
| 3570 printer->Print( | 3509 printer->Print( |
| 3571 "size_t $classname$::ByteSizeLong() const {\n" | 3510 "int $classname$::ByteSize() const {\n" |
| 3572 "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", | 3511 "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", |
| 3573 "classname", classname_, "full_name", descriptor_->full_name()); | 3512 "classname", classname_, "full_name", descriptor_->full_name()); |
| 3574 printer->Indent(); | 3513 printer->Indent(); |
| 3575 printer->Print( | 3514 printer->Print( |
| 3576 "size_t total_size = 0;\n" | 3515 "int total_size = 0;\n" |
| 3577 "\n"); | 3516 "\n"); |
| 3578 | 3517 |
| 3579 if (descriptor_->extension_range_count() > 0) { | |
| 3580 printer->Print( | |
| 3581 "total_size += _extensions_.ByteSize();\n" | |
| 3582 "\n"); | |
| 3583 } | |
| 3584 | |
| 3585 if (PreserveUnknownFields(descriptor_)) { | |
| 3586 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | |
| 3587 printer->Print( | |
| 3588 "if (_internal_metadata_.have_unknown_fields()) {\n" | |
| 3589 " total_size +=\n" | |
| 3590 " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
\n" | |
| 3591 " unknown_fields());\n" | |
| 3592 "}\n"); | |
| 3593 } else { | |
| 3594 printer->Print( | |
| 3595 "total_size += unknown_fields().size();\n" | |
| 3596 "\n"); | |
| 3597 } | |
| 3598 } | |
| 3599 | |
| 3600 // Handle required fields (if any). We expect all of them to be | 3518 // Handle required fields (if any). We expect all of them to be |
| 3601 // present, so emit one conditional that checks for that. If they are all | 3519 // present, so emit one conditional that checks for that. If they are all |
| 3602 // present then the fast path executes; otherwise the slow path executes. | 3520 // present then the fast path executes; otherwise the slow path executes. |
| 3603 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { | 3521 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { |
| 3604 // The fast path works if all required fields are present. | 3522 // The fast path works if all required fields are present. |
| 3605 const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(); | 3523 vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_); |
| 3606 printer->Print((string("if (") + | 3524 printer->Print((string("if (") + |
| 3607 ConditionalToCheckBitmasks(masks_for_has_bits) + | 3525 ConditionalToCheckBitmasks(masks_for_has_bits) + |
| 3608 ") { // All required fields are present.\n").c_str()); | 3526 ") { // All required fields are present.\n").c_str()); |
| 3609 printer->Indent(); | 3527 printer->Indent(); |
| 3610 // Oneof fields cannot be required, so optimized_order_ contains all of the | 3528 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3611 // fields that we need to potentially emit. | 3529 const FieldDescriptor* field = descriptor_->field(i); |
| 3612 for (int i = 0; i < optimized_order_.size(); i++) { | |
| 3613 const FieldDescriptor* field = optimized_order_[i]; | |
| 3614 if (!field->is_required()) continue; | 3530 if (!field->is_required()) continue; |
| 3615 PrintFieldComment(printer, field); | 3531 PrintFieldComment(printer, field); |
| 3616 field_generators_.get(field).GenerateByteSize(printer); | 3532 field_generators_.get(field).GenerateByteSize(printer); |
| 3617 printer->Print("\n"); | 3533 printer->Print("\n"); |
| 3618 } | 3534 } |
| 3619 printer->Outdent(); | 3535 printer->Outdent(); |
| 3620 printer->Print("} else {\n" // the slow path | 3536 printer->Print("} else {\n" // the slow path |
| 3621 " total_size += RequiredFieldsByteSizeFallback();\n" | 3537 " total_size += RequiredFieldsByteSizeFallback();\n" |
| 3622 "}\n"); | 3538 "}\n"); |
| 3623 } else { | 3539 } else { |
| 3624 // num_required_fields_ <= 1: no need to be tricky | 3540 // num_required_fields_ <= 1: no need to be tricky |
| 3625 for (int i = 0; i < optimized_order_.size(); i++) { | 3541 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3626 const FieldDescriptor* field = optimized_order_[i]; | 3542 const FieldDescriptor* field = descriptor_->field(i); |
| 3627 if (!field->is_required()) continue; | 3543 if (!field->is_required()) continue; |
| 3628 PrintFieldComment(printer, field); | 3544 PrintFieldComment(printer, field); |
| 3629 printer->Print("if (has_$name$()) {\n", | 3545 printer->Print("if (has_$name$()) {\n", |
| 3630 "name", FieldName(field)); | 3546 "name", FieldName(field)); |
| 3631 printer->Indent(); | 3547 printer->Indent(); |
| 3632 field_generators_.get(field).GenerateByteSize(printer); | 3548 field_generators_.get(field).GenerateByteSize(printer); |
| 3633 printer->Outdent(); | 3549 printer->Outdent(); |
| 3634 printer->Print("}\n"); | 3550 printer->Print("}\n"); |
| 3635 } | 3551 } |
| 3636 } | 3552 } |
| 3637 | 3553 |
| 3638 int last_i = -1; | 3554 // Handle optional fields (worry below about repeateds, oneofs, etc.). |
| 3639 for (int i = 0; i < optimized_order_.size(); ) { | 3555 // These are handled in chunks of 8. The first chunk is |
| 3640 // Detect infinite loops. | 3556 // the non-requireds-non-repeateds-non-unions-non-extensions in |
| 3641 GOOGLE_CHECK_NE(i, last_i); | 3557 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), |
| 3642 last_i = i; | 3558 // and the second chunk is the same for |
| 3559 // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), |
| 3560 // etc. |
| 3561 hash_map<int, uint32> fields_mask_for_chunk; |
| 3562 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3563 const FieldDescriptor* field = descriptor_->field(i); |
| 3564 if (!field->is_required() && !field->is_repeated() && |
| 3565 !field->containing_oneof()) { |
| 3566 fields_mask_for_chunk[i / 8] |= static_cast<uint32>(1) << (i % 32); |
| 3567 } |
| 3568 } |
| 3643 | 3569 |
| 3644 // Skip required fields. | 3570 int last_index = -1; |
| 3645 for (; i < optimized_order_.size() && | 3571 bool chunk_block_in_progress = false; |
| 3646 optimized_order_[i]->is_required(); i++) { | 3572 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3647 } | 3573 const FieldDescriptor* field = descriptor_->field(i); |
| 3574 if (!field->is_required() && !field->is_repeated() && |
| 3575 !field->containing_oneof()) { |
| 3576 // See above in GenerateClear for an explanation of this. |
| 3577 // TODO(kenton): Share code? Unclear how to do so without |
| 3578 // over-engineering. |
| 3579 if (i / 8 != last_index / 8 || last_index < 0) { |
| 3580 // End previous chunk, if there was one. |
| 3581 if (chunk_block_in_progress) { |
| 3582 printer->Outdent(); |
| 3583 printer->Print("}\n"); |
| 3584 chunk_block_in_progress = false; |
| 3585 } |
| 3586 // Start chunk. |
| 3587 uint32 mask = fields_mask_for_chunk[i / 8]; |
| 3588 int count = popcnt(mask); |
| 3589 GOOGLE_DCHECK_GE(count, 1); |
| 3590 if (count == 1) { |
| 3591 // No "if" here because the chunk is trivial. |
| 3592 } else { |
| 3593 if (HasFieldPresence(descriptor_->file())) { |
| 3594 printer->Print( |
| 3595 "if (_has_bits_[$index$ / 32] & $mask$u) {\n", |
| 3596 "index", SimpleItoa(i), |
| 3597 "mask", SimpleItoa(mask)); |
| 3598 printer->Indent(); |
| 3599 chunk_block_in_progress = true; |
| 3600 } |
| 3601 } |
| 3602 } |
| 3603 last_index = i; |
| 3648 | 3604 |
| 3649 // Handle repeated fields. | 3605 PrintFieldComment(printer, field); |
| 3650 for (; i < optimized_order_.size(); i++) { | 3606 |
| 3651 const FieldDescriptor* field = optimized_order_[i]; | 3607 bool have_enclosing_if = false; |
| 3652 if (!field->is_repeated()) { | 3608 if (HasFieldPresence(descriptor_->file())) { |
| 3653 break; | 3609 printer->Print( |
| 3610 "if (has_$name$()) {\n", |
| 3611 "name", FieldName(field)); |
| 3612 printer->Indent(); |
| 3613 have_enclosing_if = true; |
| 3614 } else { |
| 3615 // Without field presence: field is serialized only if it has a |
| 3616 // non-default value. |
| 3617 have_enclosing_if = EmitFieldNonDefaultCondition( |
| 3618 printer, "this->", field); |
| 3654 } | 3619 } |
| 3655 | 3620 |
| 3656 PrintFieldComment(printer, field); | 3621 field_generators_.get(field).GenerateByteSize(printer); |
| 3657 const FieldGenerator& generator = field_generators_.get(field); | |
| 3658 generator.GenerateByteSize(printer); | |
| 3659 printer->Print("\n"); | |
| 3660 } | |
| 3661 | 3622 |
| 3662 // Handle optional (non-repeated/oneof) fields. | 3623 if (have_enclosing_if) { |
| 3663 // | 3624 printer->Outdent(); |
| 3664 // These are handled in chunks of 8. The first chunk is | |
| 3665 // the non-requireds-non-repeateds-non-unions-non-extensions in | |
| 3666 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), | |
| 3667 // and the second chunk is the same for | |
| 3668 // descriptor_->field(8), descriptor_->field(9), ... | |
| 3669 // descriptor_->field(15), | |
| 3670 // etc. | |
| 3671 int last_chunk = -1; | |
| 3672 int last_chunk_start = -1; | |
| 3673 int last_chunk_end = -1; | |
| 3674 uint32 last_chunk_mask = 0; | |
| 3675 for (; i < optimized_order_.size(); i++) { | |
| 3676 const FieldDescriptor* field = optimized_order_[i]; | |
| 3677 if (field->is_repeated() || field->is_required()) { | |
| 3678 break; | |
| 3679 } | |
| 3680 | |
| 3681 // "index" defines where in the _has_bits_ the field appears. | |
| 3682 // "i" is our loop counter within optimized_order_. | |
| 3683 int index = HasFieldPresence(descriptor_->file()) ? | |
| 3684 has_bit_indices_[field->index()] : 0; | |
| 3685 int chunk = index / 8; | |
| 3686 | |
| 3687 if (last_chunk == -1) { | |
| 3688 last_chunk = chunk; | |
| 3689 last_chunk_start = i; | |
| 3690 } else if (chunk != last_chunk) { | |
| 3691 // Emit the fields for this chunk so far. | |
| 3692 break; | |
| 3693 } | |
| 3694 | |
| 3695 last_chunk_end = i; | |
| 3696 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); | |
| 3697 } | |
| 3698 | |
| 3699 if (last_chunk != -1) { | |
| 3700 GOOGLE_DCHECK_NE(-1, last_chunk_start); | |
| 3701 GOOGLE_DCHECK_NE(-1, last_chunk_end); | |
| 3702 GOOGLE_DCHECK_NE(0, last_chunk_mask); | |
| 3703 | |
| 3704 const int count = popcnt(last_chunk_mask); | |
| 3705 const bool have_outer_if = HasFieldPresence(descriptor_->file()) && | |
| 3706 (last_chunk_start != last_chunk_end); | |
| 3707 | |
| 3708 if (have_outer_if) { | |
| 3709 // Check (up to) 8 has_bits at a time if we have more than one field in | |
| 3710 // this chunk. Due to field layout ordering, we may check | |
| 3711 // _has_bits_[last_chunk * 8 / 32] multiple times. | |
| 3712 GOOGLE_DCHECK_LE(2, count); | |
| 3713 GOOGLE_DCHECK_GE(8, count); | |
| 3714 | |
| 3715 printer->Print( | 3625 printer->Print( |
| 3716 "if (_has_bits_[$index$ / 32] & $mask$u) {\n", | 3626 "}\n" |
| 3717 "index", SimpleItoa(last_chunk * 8), | 3627 "\n"); |
| 3718 "mask", SimpleItoa(last_chunk_mask)); | |
| 3719 printer->Indent(); | |
| 3720 } | |
| 3721 | |
| 3722 // Go back and emit checks for each of the fields we processed. | |
| 3723 for (int j = last_chunk_start; j <= last_chunk_end; j++) { | |
| 3724 const FieldDescriptor* field = optimized_order_[j]; | |
| 3725 const FieldGenerator& generator = field_generators_.get(field); | |
| 3726 | |
| 3727 PrintFieldComment(printer, field); | |
| 3728 | |
| 3729 bool have_enclosing_if = false; | |
| 3730 if (HasFieldPresence(descriptor_->file())) { | |
| 3731 printer->Print( | |
| 3732 "if (has_$name$()) {\n", | |
| 3733 "name", FieldName(field)); | |
| 3734 printer->Indent(); | |
| 3735 have_enclosing_if = true; | |
| 3736 } else { | |
| 3737 // Without field presence: field is serialized only if it has a | |
| 3738 // non-default value. | |
| 3739 have_enclosing_if = EmitFieldNonDefaultCondition( | |
| 3740 printer, "this->", field); | |
| 3741 } | |
| 3742 | |
| 3743 generator.GenerateByteSize(printer); | |
| 3744 | |
| 3745 if (have_enclosing_if) { | |
| 3746 printer->Outdent(); | |
| 3747 printer->Print( | |
| 3748 "}\n" | |
| 3749 "\n"); | |
| 3750 } | |
| 3751 } | |
| 3752 | |
| 3753 if (have_outer_if) { | |
| 3754 printer->Outdent(); | |
| 3755 printer->Print("}\n"); | |
| 3756 } | 3628 } |
| 3757 } | 3629 } |
| 3758 } | 3630 } |
| 3759 | 3631 |
| 3632 if (chunk_block_in_progress) { |
| 3633 printer->Outdent(); |
| 3634 printer->Print("}\n"); |
| 3635 } |
| 3636 |
| 3637 // Repeated fields don't use _has_bits_ so we count them in a separate |
| 3638 // pass. |
| 3639 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3640 const FieldDescriptor* field = descriptor_->field(i); |
| 3641 |
| 3642 if (field->is_repeated()) { |
| 3643 PrintFieldComment(printer, field); |
| 3644 field_generators_.get(field).GenerateByteSize(printer); |
| 3645 printer->Print("\n"); |
| 3646 } |
| 3647 } |
| 3648 |
| 3760 // Fields inside a oneof don't use _has_bits_ so we count them in a separate | 3649 // Fields inside a oneof don't use _has_bits_ so we count them in a separate |
| 3761 // pass. | 3650 // pass. |
| 3762 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 3651 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 3763 printer->Print( | 3652 printer->Print( |
| 3764 "switch ($oneofname$_case()) {\n", | 3653 "switch ($oneofname$_case()) {\n", |
| 3765 "oneofname", descriptor_->oneof_decl(i)->name()); | 3654 "oneofname", descriptor_->oneof_decl(i)->name()); |
| 3766 printer->Indent(); | 3655 printer->Indent(); |
| 3767 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | 3656 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
| 3768 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); | 3657 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); |
| 3769 PrintFieldComment(printer, field); | 3658 PrintFieldComment(printer, field); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3782 "case $cap_oneof_name$_NOT_SET: {\n" | 3671 "case $cap_oneof_name$_NOT_SET: {\n" |
| 3783 " break;\n" | 3672 " break;\n" |
| 3784 "}\n", | 3673 "}\n", |
| 3785 "cap_oneof_name", | 3674 "cap_oneof_name", |
| 3786 ToUpper(descriptor_->oneof_decl(i)->name())); | 3675 ToUpper(descriptor_->oneof_decl(i)->name())); |
| 3787 printer->Outdent(); | 3676 printer->Outdent(); |
| 3788 printer->Print( | 3677 printer->Print( |
| 3789 "}\n"); | 3678 "}\n"); |
| 3790 } | 3679 } |
| 3791 | 3680 |
| 3681 if (descriptor_->extension_range_count() > 0) { |
| 3682 printer->Print( |
| 3683 "total_size += _extensions_.ByteSize();\n" |
| 3684 "\n"); |
| 3685 } |
| 3686 |
| 3687 if (PreserveUnknownFields(descriptor_)) { |
| 3688 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 3689 printer->Print( |
| 3690 "if (_internal_metadata_.have_unknown_fields()) {\n" |
| 3691 " total_size +=\n" |
| 3692 " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
\n" |
| 3693 " unknown_fields());\n" |
| 3694 "}\n"); |
| 3695 } else { |
| 3696 printer->Print( |
| 3697 "total_size += unknown_fields().size();\n" |
| 3698 "\n"); |
| 3699 } |
| 3700 } |
| 3701 |
| 3792 // We update _cached_size_ even though this is a const method. In theory, | 3702 // We update _cached_size_ even though this is a const method. In theory, |
| 3793 // this is not thread-compatible, because concurrent writes have undefined | 3703 // this is not thread-compatible, because concurrent writes have undefined |
| 3794 // results. In practice, since any concurrent writes will be writing the | 3704 // results. In practice, since any concurrent writes will be writing the |
| 3795 // exact same value, it works on all common processors. In a future version | 3705 // exact same value, it works on all common processors. In a future version |
| 3796 // of C++, _cached_size_ should be made into an atomic<int>. | 3706 // of C++, _cached_size_ should be made into an atomic<int>. |
| 3797 printer->Print( | 3707 printer->Print( |
| 3798 "int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n
" | |
| 3799 "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" | 3708 "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" |
| 3800 "_cached_size_ = cached_size;\n" | 3709 "_cached_size_ = total_size;\n" |
| 3801 "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" | 3710 "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" |
| 3802 "return total_size;\n"); | 3711 "return total_size;\n"); |
| 3803 | 3712 |
| 3804 printer->Outdent(); | 3713 printer->Outdent(); |
| 3805 printer->Print("}\n"); | 3714 printer->Print("}\n"); |
| 3806 } | 3715 } |
| 3807 | 3716 |
| 3808 void MessageGenerator:: | 3717 void MessageGenerator:: |
| 3809 GenerateIsInitialized(io::Printer* printer) { | 3718 GenerateIsInitialized(io::Printer* printer) { |
| 3810 printer->Print( | 3719 printer->Print( |
| 3811 "bool $classname$::IsInitialized() const {\n", | 3720 "bool $classname$::IsInitialized() const {\n", |
| 3812 "classname", classname_); | 3721 "classname", classname_); |
| 3813 printer->Indent(); | 3722 printer->Indent(); |
| 3814 | 3723 |
| 3815 if (descriptor_->extension_range_count() > 0) { | |
| 3816 printer->Print( | |
| 3817 "if (!_extensions_.IsInitialized()) {\n" | |
| 3818 " return false;\n" | |
| 3819 "}\n\n"); | |
| 3820 } | |
| 3821 | |
| 3822 if (HasFieldPresence(descriptor_->file())) { | 3724 if (HasFieldPresence(descriptor_->file())) { |
| 3823 // Check that all required fields in this message are set. We can do this | 3725 // Check that all required fields in this message are set. We can do this |
| 3824 // most efficiently by checking 32 "has bits" at a time. | 3726 // most efficiently by checking 32 "has bits" at a time. |
| 3825 const std::vector<uint32> masks = RequiredFieldsBitMask(); | 3727 int has_bits_array_size = (descriptor_->field_count() + 31) / 32; |
| 3728 for (int i = 0; i < has_bits_array_size; i++) { |
| 3729 uint32 mask = 0; |
| 3730 for (int bit = 0; bit < 32; bit++) { |
| 3731 int index = i * 32 + bit; |
| 3732 if (index >= descriptor_->field_count()) break; |
| 3733 const FieldDescriptor* field = descriptor_->field(index); |
| 3826 | 3734 |
| 3827 for (int i = 0; i < masks.size(); i++) { | 3735 if (field->is_required()) { |
| 3828 uint32 mask = masks[i]; | 3736 mask |= 1 << bit; |
| 3829 if (mask == 0) { | 3737 } |
| 3830 continue; | |
| 3831 } | 3738 } |
| 3832 | 3739 |
| 3833 // TODO(ckennelly): Consider doing something similar to ByteSizeLong(), | 3740 if (mask != 0) { |
| 3834 // where we check all of the required fields in a single branch (assuming | 3741 printer->Print( |
| 3835 // that we aren't going to benefit from early termination). | 3742 "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", |
| 3836 printer->Print( | 3743 "i", SimpleItoa(i), |
| 3837 "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", | 3744 "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); |
| 3838 "i", SimpleItoa(i), | 3745 } |
| 3839 "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); | |
| 3840 } | 3746 } |
| 3841 } | 3747 } |
| 3842 | 3748 |
| 3843 // Now check that all non-oneof embedded messages are initialized. | 3749 // Now check that all embedded messages are initialized. |
| 3844 for (int i = 0; i < optimized_order_.size(); i++) { | 3750 printer->Print("\n"); |
| 3845 const FieldDescriptor* field = optimized_order_[i]; | 3751 for (int i = 0; i < descriptor_->field_count(); i++) { |
| 3846 // TODO(ckennelly): Push this down into a generator? | 3752 const FieldDescriptor* field = descriptor_->field(i); |
| 3847 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && | 3753 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && |
| 3848 !ShouldIgnoreRequiredFieldCheck(field, options_) && | 3754 !ShouldIgnoreRequiredFieldCheck(field, options_) && |
| 3849 HasRequiredFields(field->message_type(), options_)) { | 3755 HasRequiredFields(field->message_type(), options_)) { |
| 3850 if (field->is_repeated()) { | 3756 if (field->is_repeated()) { |
| 3851 printer->Print( | 3757 printer->Print( |
| 3852 "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))
" | 3758 "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))
" |
| 3853 " return false;\n", | 3759 " return false;\n", |
| 3854 "name", FieldName(field)); | 3760 "name", FieldName(field)); |
| 3855 } else { | 3761 } else { |
| 3856 GOOGLE_CHECK(field->options().weak() || !field->containing_oneof()); | 3762 if (field->options().weak() || !field->containing_oneof()) { |
| 3857 // For weak fields, use the data member (::google::protobuf::Message*) i
nstead | |
| 3858 // of the getter to avoid a link dependency on the weak message type | |
| 3859 // which is only forward declared. | |
| 3860 printer->Print( | |
| 3861 "if (has_$name$()) {\n" | |
| 3862 " if (!this->$name$_->IsInitialized()) return false;\n" | |
| 3863 "}\n", | |
| 3864 "name", FieldName(field)); | |
| 3865 } | |
| 3866 } | |
| 3867 } | |
| 3868 | |
| 3869 // Go through the oneof fields, emitting a switch if any might have required | |
| 3870 // fields. | |
| 3871 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | |
| 3872 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); | |
| 3873 | |
| 3874 bool has_required_fields = false; | |
| 3875 for (int j = 0; j < oneof->field_count(); j++) { | |
| 3876 const FieldDescriptor* field = oneof->field(j); | |
| 3877 | |
| 3878 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && | |
| 3879 !ShouldIgnoreRequiredFieldCheck(field, options_) && | |
| 3880 HasRequiredFields(field->message_type(), options_)) { | |
| 3881 has_required_fields = true; | |
| 3882 break; | |
| 3883 } | |
| 3884 } | |
| 3885 | |
| 3886 if (!has_required_fields) { | |
| 3887 continue; | |
| 3888 } | |
| 3889 | |
| 3890 printer->Print( | |
| 3891 "switch ($oneofname$_case()) {\n", | |
| 3892 "oneofname", oneof->name()); | |
| 3893 printer->Indent(); | |
| 3894 for (int j = 0; j < oneof->field_count(); j++) { | |
| 3895 const FieldDescriptor* field = oneof->field(j); | |
| 3896 printer->Print( | |
| 3897 "case k$field_name$: {\n", | |
| 3898 "field_name", UnderscoresToCamelCase(field->name(), true)); | |
| 3899 printer->Indent(); | |
| 3900 | |
| 3901 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && | |
| 3902 !ShouldIgnoreRequiredFieldCheck(field, options_) && | |
| 3903 HasRequiredFields(field->message_type(), options_)) { | |
| 3904 GOOGLE_CHECK(!(field->options().weak() || !field->containing_oneof())); | |
| 3905 if (field->options().weak()) { | |
| 3906 // For weak fields, use the data member (::google::protobuf::Message*)
instead | 3763 // For weak fields, use the data member (::google::protobuf::Message*)
instead |
| 3907 // of the getter to avoid a link dependency on the weak message type | 3764 // of the getter to avoid a link dependency on the weak message type |
| 3908 // which is only forward declared. | 3765 // which is only forward declared. |
| 3909 printer->Print( | 3766 printer->Print( |
| 3910 "if (has_$name$()) {\n" | 3767 "if (has_$name$()) {\n" |
| 3911 " if (!this->$name$_->IsInitialized()) return false;\n" | 3768 " if (!this->$name$_->IsInitialized()) return false;\n" |
| 3912 "}\n", | 3769 "}\n", |
| 3913 "name", FieldName(field)); | 3770 "name", FieldName(field)); |
| 3914 } else { | 3771 } else { |
| 3915 printer->Print( | 3772 printer->Print( |
| 3916 "if (has_$name$()) {\n" | 3773 "if (has_$name$()) {\n" |
| 3917 " if (!this->$name$().IsInitialized()) return false;\n" | 3774 " if (!this->$name$().IsInitialized()) return false;\n" |
| 3918 "}\n", | 3775 "}\n", |
| 3919 "name", FieldName(field)); | 3776 "name", FieldName(field)); |
| 3920 } | 3777 } |
| 3921 } | 3778 } |
| 3779 } |
| 3780 } |
| 3922 | 3781 |
| 3923 printer->Print( | 3782 if (descriptor_->extension_range_count() > 0) { |
| 3924 "break;\n"); | |
| 3925 printer->Outdent(); | |
| 3926 printer->Print( | |
| 3927 "}\n"); | |
| 3928 } | |
| 3929 printer->Print( | 3783 printer->Print( |
| 3930 "case $cap_oneof_name$_NOT_SET: {\n" | 3784 "\n" |
| 3931 " break;\n" | 3785 "if (!_extensions_.IsInitialized()) return false;"); |
| 3932 "}\n", | |
| 3933 "cap_oneof_name", | |
| 3934 ToUpper(oneof->name())); | |
| 3935 printer->Outdent(); | |
| 3936 printer->Print( | |
| 3937 "}\n"); | |
| 3938 } | 3786 } |
| 3939 | 3787 |
| 3940 printer->Outdent(); | 3788 printer->Outdent(); |
| 3941 printer->Print( | 3789 printer->Print( |
| 3942 " return true;\n" | 3790 " return true;\n" |
| 3943 "}\n"); | 3791 "}\n"); |
| 3944 } | 3792 } |
| 3945 | 3793 |
| 3946 | 3794 |
| 3947 } // namespace cpp | 3795 } // namespace cpp |
| 3948 } // namespace compiler | 3796 } // namespace compiler |
| 3949 } // namespace protobuf | 3797 } // namespace protobuf |
| 3950 } // namespace google | 3798 } // namespace google |
| OLD | NEW |