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