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) { |
| 1662 if (IsMapEntryMessage(descriptor_)) return; |
| 1663 |
1778 // mutable_unknown_fields wrapper function for LazyStringOutputStream | 1664 // mutable_unknown_fields wrapper function for LazyStringOutputStream |
1779 // callback. | 1665 // callback. |
1780 if (PreserveUnknownFields(descriptor_) && | 1666 if (PreserveUnknownFields(descriptor_) && |
1781 !UseUnknownFieldSet(descriptor_->file(), options_)) { | 1667 !UseUnknownFieldSet(descriptor_->file(), options_)) { |
1782 printer->Print( | 1668 printer->Print( |
1783 "static ::std::string* MutableUnknownFieldsFor$classname$(\n" | 1669 "static ::std::string* MutableUnknownFieldsFor$classname$(\n" |
1784 " $classname$* ptr) {\n" | 1670 " $classname$* ptr) {\n" |
1785 " return ptr->mutable_unknown_fields();\n" | 1671 " return ptr->mutable_unknown_fields();\n" |
1786 "}\n" | 1672 "}\n" |
1787 "\n", | 1673 "\n", |
(...skipping 10 matching lines...) Expand all Loading... |
1798 " _any_metadata_.PackFrom(message, type_url_prefix);\n" | 1684 " _any_metadata_.PackFrom(message, type_url_prefix);\n" |
1799 "}\n" | 1685 "}\n" |
1800 "\n" | 1686 "\n" |
1801 "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\
n" | 1687 "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\
n" |
1802 " return _any_metadata_.UnpackTo(message);\n" | 1688 " return _any_metadata_.UnpackTo(message);\n" |
1803 "}\n" | 1689 "}\n" |
1804 "\n", | 1690 "\n", |
1805 "classname", classname_); | 1691 "classname", classname_); |
1806 } | 1692 } |
1807 | 1693 |
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. | 1694 // Generate non-inline field definitions. |
1824 for (int i = 0; i < descriptor_->field_count(); i++) { | 1695 for (int i = 0; i < descriptor_->field_count(); i++) { |
1825 field_generators_.get(descriptor_->field(i)) | 1696 field_generators_.get(descriptor_->field(i)) |
1826 .GenerateNonInlineAccessorDefinitions(printer); | 1697 .GenerateNonInlineAccessorDefinitions(printer); |
1827 } | 1698 } |
1828 | 1699 |
1829 // Generate field number constants. | 1700 // Generate field number constants. |
1830 printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); | 1701 printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); |
1831 for (int i = 0; i < descriptor_->field_count(); i++) { | 1702 for (int i = 0; i < descriptor_->field_count(); i++) { |
1832 const FieldDescriptor *field = descriptor_->field(i); | 1703 const FieldDescriptor *field = descriptor_->field(i); |
1833 printer->Print( | 1704 printer->Print( |
1834 "const int $classname$::$constant_name$;\n", | 1705 "const int $classname$::$constant_name$;\n", |
1835 "classname", ClassName(FieldScope(field), false), | 1706 "classname", ClassName(FieldScope(field), false), |
1836 "constant_name", FieldConstantName(field)); | 1707 "constant_name", FieldConstantName(field)); |
1837 } | 1708 } |
1838 printer->Print( | 1709 printer->Print( |
1839 "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" | 1710 "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" |
1840 "\n"); | 1711 "\n"); |
1841 | 1712 |
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); | 1713 GenerateStructors(printer); |
1848 printer->Print("\n"); | 1714 printer->Print("\n"); |
1849 | 1715 |
1850 if (descriptor_->oneof_decl_count() > 0) { | 1716 if (descriptor_->oneof_decl_count() > 0) { |
1851 GenerateOneofClear(printer); | 1717 GenerateOneofClear(printer); |
1852 printer->Print("\n"); | 1718 printer->Print("\n"); |
1853 } | 1719 } |
1854 | 1720 |
1855 if (HasGeneratedMethods(descriptor_->file(), options_)) { | 1721 if (HasGeneratedMethods(descriptor_->file(), options_)) { |
1856 GenerateClear(printer); | 1722 GenerateClear(printer); |
(...skipping 21 matching lines...) Expand all Loading... |
1878 | 1744 |
1879 GenerateIsInitialized(printer); | 1745 GenerateIsInitialized(printer); |
1880 printer->Print("\n"); | 1746 printer->Print("\n"); |
1881 } | 1747 } |
1882 | 1748 |
1883 GenerateSwap(printer); | 1749 GenerateSwap(printer); |
1884 printer->Print("\n"); | 1750 printer->Print("\n"); |
1885 | 1751 |
1886 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 1752 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
1887 printer->Print( | 1753 printer->Print( |
1888 "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" | 1754 "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" |
1889 " protobuf_AssignDescriptorsOnce();\n" | 1755 " protobuf_AssignDescriptorsOnce();\n" |
1890 " ::google::protobuf::Metadata metadata;\n" | 1756 " return file_level_metadata[$index$];\n" |
1891 " metadata.descriptor = $classname$_descriptor_;\n" | 1757 "}\n" |
1892 " metadata.reflection = $classname$_reflection_;\n" | 1758 "\n", |
1893 " return metadata;\n" | 1759 "classname", classname_, "index", SimpleItoa(index_in_metadata_)); |
1894 "}\n" | |
1895 "\n", | |
1896 "classname", classname_); | |
1897 } else { | 1760 } else { |
1898 printer->Print( | 1761 printer->Print( |
1899 "::std::string $classname$::GetTypeName() const {\n" | 1762 "::std::string $classname$::GetTypeName() const {\n" |
1900 " return \"$type_name$\";\n" | 1763 " return \"$type_name$\";\n" |
1901 "}\n" | 1764 "}\n" |
1902 "\n", | 1765 "\n", |
1903 "classname", classname_, | 1766 "classname", classname_, |
1904 "type_name", descriptor_->full_name()); | 1767 "type_name", descriptor_->full_name()); |
1905 } | 1768 } |
1906 | 1769 |
1907 } | 1770 } |
1908 | 1771 |
1909 void MessageGenerator:: | 1772 std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( |
1910 GenerateOffsets(io::Printer* printer) { | 1773 io::Printer* printer) { |
1911 printer->Print("static const int $classname$_offsets_[$field_count$] = {\n", | 1774 if (IsMapEntryMessage(descriptor_)) return std::make_pair(0, 0); |
1912 "classname", classname_, "field_count", | 1775 std::map<string, string> variables; |
1913 SimpleItoa(std::max(1, descriptor_->field_count() + | 1776 variables["classname"] = classname_; |
1914 descriptor_->oneof_decl_count()))); | |
1915 printer->Indent(); | |
1916 | 1777 |
| 1778 if (HasFieldPresence(descriptor_->file())) { |
| 1779 printer->Print( |
| 1780 variables, |
| 1781 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_)
,\n"); |
| 1782 } else { |
| 1783 printer->Print("~0u, // no _has_bits_\n"); |
| 1784 } |
| 1785 printer->Print(variables, |
| 1786 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " |
| 1787 "_internal_metadata_),\n"); |
| 1788 if (descriptor_->extension_range_count() > 0) { |
| 1789 printer->Print( |
| 1790 variables, |
| 1791 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _extensions
_),\n"); |
| 1792 } else { |
| 1793 printer->Print("~0u, // no _extensions_\n"); |
| 1794 } |
| 1795 if (descriptor_->oneof_decl_count() > 0) { |
| 1796 printer->Print(variables, |
| 1797 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$,
" |
| 1798 "_oneof_case_[0]),\n"); |
| 1799 } else { |
| 1800 printer->Print("~0u, // no _oneof_case_\n"); |
| 1801 } |
| 1802 |
| 1803 const int kNumGenericOffsets = 4; // the number of fixed offsets above |
| 1804 const size_t offsets = kNumGenericOffsets + |
| 1805 descriptor_->field_count() + |
| 1806 descriptor_->oneof_decl_count(); |
| 1807 size_t entries = offsets; |
1917 for (int i = 0; i < descriptor_->field_count(); i++) { | 1808 for (int i = 0; i < descriptor_->field_count(); i++) { |
1918 const FieldDescriptor* field = descriptor_->field(i); | 1809 const FieldDescriptor* field = descriptor_->field(i); |
1919 if (field->containing_oneof()) { | 1810 if (field->containing_oneof()) { |
1920 printer->Print( | 1811 printer->Print( |
1921 "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" | 1812 "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" |
1922 "$classname$_default_oneof_instance_, $name$_),\n", | 1813 "(&$classname$_default_oneof_instance_), $name$_),\n", |
1923 "classname", classname_, | 1814 "classname", classname_, "name", FieldName(field)); |
1924 "name", FieldName(field)); | |
1925 } else { | 1815 } else { |
1926 printer->Print( | 1816 printer->Print( |
1927 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " | 1817 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " |
1928 "$name$_),\n", | 1818 "$name$_),\n", |
1929 "classname", classname_, | 1819 "classname", classname_, |
1930 "name", FieldName(field)); | 1820 "name", FieldName(field)); |
1931 } | 1821 } |
1932 } | 1822 } |
1933 | 1823 |
1934 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1824 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
1935 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); | 1825 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); |
1936 printer->Print( | 1826 printer->Print( |
1937 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", | 1827 "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", |
1938 "classname", classname_, | 1828 "classname", classname_, |
1939 "name", oneof->name()); | 1829 "name", oneof->name()); |
1940 } | 1830 } |
1941 | 1831 |
1942 printer->Outdent(); | 1832 if (HasFieldPresence(descriptor_->file())) { |
1943 printer->Print("};\n"); | 1833 entries += has_bit_indices_.size(); |
| 1834 for (int i = 0; i < has_bit_indices_.size(); i++) { |
| 1835 printer->Print("$index$,\n", "index", SimpleItoa(has_bit_indices_[i])); |
| 1836 } |
| 1837 } |
| 1838 |
| 1839 return std::make_pair(entries, offsets); |
1944 } | 1840 } |
1945 | 1841 |
1946 void MessageGenerator:: | 1842 void MessageGenerator:: |
1947 GenerateSharedConstructorCode(io::Printer* printer) { | 1843 GenerateSharedConstructorCode(io::Printer* printer) { |
1948 printer->Print( | 1844 printer->Print( |
1949 "void $classname$::SharedCtor() {\n", | 1845 "void $classname$::SharedCtor() {\n", |
1950 "classname", classname_); | 1846 "classname", classname_); |
1951 printer->Indent(); | 1847 printer->Indent(); |
1952 | 1848 |
1953 if (!HasFieldPresence(descriptor_->file())) { | 1849 bool need_to_clear_cached_size = true; |
1954 printer->Print( | 1850 // We reproduce the logic used for laying out _cached_sized_ in the class |
1955 " _is_default_instance_ = false;\n"); | 1851 // definition, as to initialize it in-order. |
| 1852 if (HasFieldPresence(descriptor_->file()) && |
| 1853 (HasBitsSize() % 8) != 0) { |
| 1854 printer->Print("_cached_size_ = 0;\n"); |
| 1855 need_to_clear_cached_size = false; |
1956 } | 1856 } |
1957 | 1857 |
1958 printer->Print(StrCat( | 1858 // TODO(gerbens) Clean this hack, and why do i need a reference to a pointer?? |
1959 uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", | 1859 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
1960 "_cached_size_ = 0;\n").c_str()); | 1860 if (HasDescriptorMethods(descriptor_->file(), options_) && |
1961 | 1861 IsMapEntryMessage(descriptor_->nested_type(i))) { |
1962 if (PreserveUnknownFields(descriptor_) && | 1862 printer->Print( |
1963 !UseUnknownFieldSet(descriptor_->file(), options_)) { | 1863 "const ::google::protobuf::Descriptor*& $type$_descriptor = " |
1964 printer->Print( | 1864 "file_level_metadata[$index$].descriptor;\n", |
1965 "_unknown_fields_.UnsafeSetDefault(\n" | 1865 "type", ClassName(descriptor_->nested_type(i), false), "index", |
1966 " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); | 1866 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 } | 1867 } |
1974 } | 1868 } |
1975 | 1869 |
1976 if (HasFieldPresence(descriptor_->file())) { | 1870 std::vector<bool> processed(optimized_order_.size(), false); |
1977 printer->Print( | 1871 GenerateConstructorBody(printer, processed, false); |
1978 "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); | |
1979 } | |
1980 | 1872 |
1981 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1873 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
1982 printer->Print( | 1874 printer->Print( |
1983 "clear_has_$oneof_name$();\n", | 1875 "clear_has_$oneof_name$();\n", |
1984 "oneof_name", descriptor_->oneof_decl(i)->name()); | 1876 "oneof_name", descriptor_->oneof_decl(i)->name()); |
1985 } | 1877 } |
1986 | 1878 |
| 1879 if (need_to_clear_cached_size) { |
| 1880 printer->Print("_cached_size_ = 0;\n"); |
| 1881 } |
| 1882 |
1987 printer->Outdent(); | 1883 printer->Outdent(); |
1988 printer->Print("}\n\n"); | 1884 printer->Print("}\n\n"); |
1989 } | 1885 } |
1990 | 1886 |
1991 void MessageGenerator:: | 1887 void MessageGenerator:: |
1992 GenerateSharedDestructorCode(io::Printer* printer) { | 1888 GenerateSharedDestructorCode(io::Printer* printer) { |
1993 printer->Print( | 1889 printer->Print( |
1994 "void $classname$::SharedDtor() {\n", | 1890 "void $classname$::SharedDtor() {\n", |
1995 "classname", classname_); | 1891 "classname", classname_); |
1996 printer->Indent(); | 1892 printer->Indent(); |
1997 if (SupportsArenas(descriptor_)) { | 1893 if (SupportsArenas(descriptor_)) { |
1998 // Do nothing when the message is allocated in an arena. | 1894 // Do nothing when the message is allocated in an arena. |
1999 printer->Print( | 1895 printer->Print( |
2000 "if (GetArenaNoVirtual() != NULL) {\n" | 1896 "::google::protobuf::Arena* arena = GetArenaNoVirtual();\n" |
| 1897 "if (arena != NULL) {\n" |
2001 " return;\n" | 1898 " return;\n" |
2002 "}\n" | 1899 "}\n" |
2003 "\n"); | 1900 "\n"); |
2004 } | 1901 } |
2005 | 1902 |
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. | 1903 // Write the destructors for each field except oneof members. |
2022 for (int i = 0; i < descriptor_->field_count(); i++) { | 1904 // optimized_order_ does not contain oneof fields. |
2023 if (!descriptor_->field(i)->containing_oneof()) { | 1905 for (int i = 0; i < optimized_order_.size(); i++) { |
2024 field_generators_.get(descriptor_->field(i)) | 1906 const FieldDescriptor* field = optimized_order_[i]; |
2025 .GenerateDestructorCode(printer); | 1907 field_generators_.get(field).GenerateDestructorCode(printer); |
2026 } | |
2027 } | 1908 } |
2028 | 1909 |
2029 // Generate code to destruct oneofs. Clearing should do the work. | 1910 // Generate code to destruct oneofs. Clearing should do the work. |
2030 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 1911 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
2031 printer->Print( | 1912 printer->Print( |
2032 "if (has_$oneof_name$()) {\n" | 1913 "if (has_$oneof_name$()) {\n" |
2033 " clear_$oneof_name$();\n" | 1914 " clear_$oneof_name$();\n" |
2034 "}\n", | 1915 "}\n", |
2035 "oneof_name", descriptor_->oneof_decl(i)->name()); | 1916 "oneof_name", descriptor_->oneof_decl(i)->name()); |
2036 } | 1917 } |
2037 | 1918 |
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(); | 1919 printer->Outdent(); |
2064 printer->Print( | 1920 printer->Print( |
2065 " }\n" | |
2066 "}\n" | 1921 "}\n" |
2067 "\n"); | 1922 "\n"); |
2068 } | 1923 } |
2069 | 1924 |
2070 void MessageGenerator:: | 1925 void MessageGenerator:: |
2071 GenerateArenaDestructorCode(io::Printer* printer) { | 1926 GenerateArenaDestructorCode(io::Printer* printer) { |
2072 // Generate the ArenaDtor() method. Track whether any fields actually produced | 1927 // Generate the ArenaDtor() method. Track whether any fields actually produced |
2073 // code that needs to be called. | 1928 // code that needs to be called. |
2074 printer->Print( | 1929 printer->Print( |
2075 "void $classname$::ArenaDtor(void* object) {\n", | 1930 "void $classname$::ArenaDtor(void* object) {\n", |
2076 "classname", classname_); | 1931 "classname", classname_); |
2077 printer->Indent(); | 1932 printer->Indent(); |
2078 | 1933 |
2079 // This code is placed inside a static method, rather than an ordinary one, | 1934 // This code is placed inside a static method, rather than an ordinary one, |
2080 // since that simplifies Arena's destructor list (ordinary function pointers | 1935 // since that simplifies Arena's destructor list (ordinary function pointers |
2081 // rather than member function pointers). _this is the object being | 1936 // rather than member function pointers). _this is the object being |
2082 // destructed. | 1937 // destructed. |
2083 printer->Print( | 1938 printer->Print( |
2084 "$classname$* _this = reinterpret_cast< $classname$* >(object);\n" | 1939 "$classname$* _this = reinterpret_cast< $classname$* >(object);\n" |
2085 // avoid an "unused variable" warning in case no fields have dtor code. | 1940 // avoid an "unused variable" warning in case no fields have dtor code. |
2086 "(void)_this;\n", | 1941 "(void)_this;\n", |
2087 "classname", classname_); | 1942 "classname", classname_); |
2088 | 1943 |
2089 bool need_registration = false; | 1944 bool need_registration = false; |
2090 for (int i = 0; i < descriptor_->field_count(); i++) { | 1945 // Process non-oneof fields first. |
2091 if (field_generators_.get(descriptor_->field(i)) | 1946 for (int i = 0; i < optimized_order_.size(); i++) { |
| 1947 const FieldDescriptor* field = optimized_order_[i]; |
| 1948 if (field_generators_.get(field) |
2092 .GenerateArenaDestructorCode(printer)) { | 1949 .GenerateArenaDestructorCode(printer)) { |
2093 need_registration = true; | 1950 need_registration = true; |
2094 } | 1951 } |
2095 } | 1952 } |
| 1953 |
| 1954 // Process oneof fields. |
| 1955 // |
| 1956 // Note: As of 10/5/2016, GenerateArenaDestructorCode does not emit anything |
| 1957 // and returns false for oneof fields. |
| 1958 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 1959 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); |
| 1960 |
| 1961 for (int j = 0; j < oneof->field_count(); j++) { |
| 1962 const FieldDescriptor* field = oneof->field(j); |
| 1963 if (field_generators_.get(field) |
| 1964 .GenerateArenaDestructorCode(printer)) { |
| 1965 need_registration = true; |
| 1966 } |
| 1967 } |
| 1968 } |
| 1969 |
2096 printer->Outdent(); | 1970 printer->Outdent(); |
2097 printer->Print( | 1971 printer->Print( |
2098 "}\n"); | 1972 "}\n"); |
2099 | 1973 |
2100 if (need_registration) { | 1974 if (need_registration) { |
2101 printer->Print( | 1975 printer->Print( |
2102 "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* a
rena) {\n" | 1976 "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* a
rena) {\n" |
2103 " if (arena != NULL) {\n" | 1977 " if (arena != NULL) {\n" |
2104 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" | 1978 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" |
2105 " }\n" | 1979 " }\n" |
2106 "}\n", | 1980 "}\n", |
2107 "classname", classname_); | 1981 "classname", classname_); |
2108 } else { | 1982 } else { |
2109 printer->Print( | 1983 printer->Print( |
2110 "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {
\n" | 1984 "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {
\n" |
2111 "}\n", | 1985 "}\n", |
2112 "classname", classname_); | 1986 "classname", classname_); |
2113 } | 1987 } |
2114 } | 1988 } |
2115 | 1989 |
| 1990 void MessageGenerator::GenerateConstructorBody(io::Printer* printer, |
| 1991 std::vector<bool> processed, |
| 1992 bool copy_constructor) const { |
| 1993 const FieldDescriptor* last_start = NULL; |
| 1994 // RunMap maps from fields that start each run to the number of fields in that |
| 1995 // run. This is optimized for the common case that there are very few runs in |
| 1996 // a message and that most of the eligible fields appear together. |
| 1997 typedef hash_map<const FieldDescriptor*, size_t> RunMap; |
| 1998 RunMap runs; |
| 1999 |
| 2000 for (int i = 0; i < optimized_order_.size(); ++i) { |
| 2001 const FieldDescriptor* field = optimized_order_[i]; |
| 2002 if ((copy_constructor && IsPOD(field)) || |
| 2003 (!copy_constructor && CanConstructByZeroing(field, options_))) { |
| 2004 if (last_start == NULL) { |
| 2005 last_start = field; |
| 2006 } |
| 2007 |
| 2008 runs[last_start]++; |
| 2009 } else { |
| 2010 last_start = NULL; |
| 2011 } |
| 2012 } |
| 2013 |
| 2014 string pod_template; |
| 2015 if (copy_constructor) { |
| 2016 pod_template = |
| 2017 "::memcpy(&$first$_, &from.$first$_,\n" |
| 2018 " reinterpret_cast<char*>(&$last$_) -\n" |
| 2019 " reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n"; |
| 2020 } else { |
| 2021 pod_template = |
| 2022 "::memset(&$first$_, 0, reinterpret_cast<char*>(&$last$_) -\n" |
| 2023 " reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n"; |
| 2024 } |
| 2025 |
| 2026 for (int i = 0; i < optimized_order_.size(); ++i) { |
| 2027 if (processed[i]) { |
| 2028 continue; |
| 2029 } |
| 2030 |
| 2031 const FieldDescriptor* field = optimized_order_[i]; |
| 2032 RunMap::const_iterator it = runs.find(field); |
| 2033 |
| 2034 // We only apply the memset technique to runs of more than one field, as |
| 2035 // assignment is better than memset for generated code clarity. |
| 2036 if (it != runs.end() && it->second > 1) { |
| 2037 // Use a memset, then skip run_length fields. |
| 2038 const size_t run_length = it->second; |
| 2039 const string first_field_name = FieldName(field); |
| 2040 const string last_field_name = |
| 2041 FieldName(optimized_order_[i + run_length - 1]); |
| 2042 |
| 2043 printer->Print(pod_template.c_str(), |
| 2044 "first", first_field_name, |
| 2045 "last", last_field_name); |
| 2046 |
| 2047 i += run_length - 1; |
| 2048 // ++i at the top of the loop. |
| 2049 } else { |
| 2050 if (copy_constructor) { |
| 2051 field_generators_.get(field).GenerateCopyConstructorCode(printer); |
| 2052 } else { |
| 2053 field_generators_.get(field).GenerateConstructorCode(printer); |
| 2054 } |
| 2055 } |
| 2056 } |
| 2057 } |
| 2058 |
2116 void MessageGenerator:: | 2059 void MessageGenerator:: |
2117 GenerateStructors(io::Printer* printer) { | 2060 GenerateStructors(io::Printer* printer) { |
2118 string superclass; | 2061 string superclass; |
2119 if (use_dependent_base_) { | 2062 if (use_dependent_base_) { |
2120 superclass = | 2063 superclass = |
2121 DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; | 2064 DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; |
2122 } else { | 2065 } else { |
2123 superclass = SuperClassName(descriptor_, options_); | 2066 superclass = SuperClassName(descriptor_, options_); |
2124 } | 2067 } |
2125 string initializer_with_arena = superclass + "()"; | 2068 string initializer_with_arena = superclass + "()"; |
2126 | 2069 |
2127 if (descriptor_->extension_range_count() > 0) { | 2070 if (descriptor_->extension_range_count() > 0) { |
2128 initializer_with_arena += ",\n _extensions_(arena)"; | 2071 initializer_with_arena += ",\n _extensions_(arena)"; |
2129 } | 2072 } |
2130 | 2073 |
2131 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 2074 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 | 2075 |
2137 // Initialize member variables with arena constructor. | 2076 // Initialize member variables with arena constructor. |
2138 for (int i = 0; i < descriptor_->field_count(); i++) { | 2077 for (int i = 0; i < optimized_order_.size(); i++) { |
2139 bool has_arena_constructor = descriptor_->field(i)->is_repeated(); | 2078 const FieldDescriptor* field = optimized_order_[i]; |
| 2079 |
| 2080 bool has_arena_constructor = field->is_repeated(); |
2140 if (has_arena_constructor) { | 2081 if (has_arena_constructor) { |
2141 initializer_with_arena += string(",\n ") + | 2082 initializer_with_arena += string(",\n ") + |
2142 FieldName(descriptor_->field(i)) + string("_(arena)"); | 2083 FieldName(field) + string("_(arena)"); |
2143 } | 2084 } |
2144 } | 2085 } |
2145 | 2086 |
2146 if (IsAnyMessage(descriptor_)) { | 2087 if (IsAnyMessage(descriptor_)) { |
2147 initializer_with_arena += ",\n _any_metadata_(&type_url, &value_)"; | 2088 initializer_with_arena += ",\n _any_metadata_(&type_url_, &value_)"; |
2148 } | 2089 } |
2149 | 2090 |
2150 string initializer_null; | 2091 string initializer_null; |
2151 initializer_null = (UseUnknownFieldSet(descriptor_->file(), options_) ? | 2092 initializer_null = ", _internal_metadata_(NULL)"; |
2152 ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)"); | |
2153 if (IsAnyMessage(descriptor_)) { | 2093 if (IsAnyMessage(descriptor_)) { |
2154 initializer_null += ", _any_metadata_(&type_url_, &value_)"; | 2094 initializer_null += ", _any_metadata_(&type_url_, &value_)"; |
2155 } | 2095 } |
2156 | 2096 |
2157 printer->Print( | 2097 printer->Print( |
2158 "$classname$::$classname$()\n" | 2098 "$classname$::$classname$()\n" |
2159 " : $superclass$()$initializer$ {\n" | 2099 " : $superclass$()$initializer$ {\n" |
| 2100 " if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {\n" |
| 2101 " $initdefaultsname$();\n" |
| 2102 " }\n" |
2160 " SharedCtor();\n" | 2103 " SharedCtor();\n" |
2161 " // @@protoc_insertion_point(constructor:$full_name$)\n" | 2104 " // @@protoc_insertion_point(constructor:$full_name$)\n" |
2162 "}\n", | 2105 "}\n", |
2163 "classname", classname_, | 2106 "classname", classname_, "superclass", superclass, "full_name", |
2164 "superclass", superclass, | 2107 descriptor_->full_name(), "initializer", initializer_null, |
2165 "full_name", descriptor_->full_name(), | 2108 "initdefaultsname", GlobalInitDefaultsName(descriptor_->file()->name())); |
2166 "initializer", initializer_null); | |
2167 | 2109 |
2168 if (SupportsArenas(descriptor_)) { | 2110 if (SupportsArenas(descriptor_)) { |
2169 printer->Print( | 2111 printer->Print( |
2170 "\n" | |
2171 "$classname$::$classname$(::google::protobuf::Arena* arena)\n" | 2112 "$classname$::$classname$(::google::protobuf::Arena* arena)\n" |
2172 " : $initializer$ {\n" | 2113 " : $initializer$ {\n" |
| 2114 // When arenas are used it's safe to assume we have finished |
| 2115 // static init time (protos with arenas are unsafe during static init) |
| 2116 "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" |
| 2117 " $initdefaultsname$();\n" |
| 2118 "#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" |
2173 " SharedCtor();\n" | 2119 " SharedCtor();\n" |
2174 " RegisterArenaDtor(arena);\n" | 2120 " RegisterArenaDtor(arena);\n" |
2175 " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" | 2121 " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" |
2176 "}\n", | 2122 "}\n", |
2177 "initializer", initializer_with_arena, | 2123 "initializer", initializer_with_arena, "classname", classname_, |
2178 "classname", classname_, | 2124 "superclass", superclass, "full_name", descriptor_->full_name(), |
2179 "superclass", superclass, | 2125 "initdefaultsname", |
2180 "full_name", descriptor_->full_name()); | 2126 GlobalInitDefaultsName(descriptor_->file()->name())); |
2181 } | 2127 } |
2182 | 2128 |
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. | 2129 // Generate the copy constructor. |
2231 printer->Print( | 2130 printer->Print( |
2232 "$classname$::$classname$(const $classname$& from)\n" | 2131 "$classname$::$classname$(const $classname$& from)\n" |
2233 " : $superclass$()", | 2132 " : $superclass$()", |
2234 "classname", classname_, | 2133 "classname", classname_, |
2235 "superclass", superclass, | 2134 "superclass", superclass, |
2236 "full_name", descriptor_->full_name()); | 2135 "full_name", descriptor_->full_name()); |
2237 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 2136 printer->Indent(); |
| 2137 printer->Indent(); |
| 2138 printer->Indent(); |
| 2139 |
| 2140 printer->Print( |
| 2141 ",\n_internal_metadata_(NULL)"); |
| 2142 |
| 2143 if (HasFieldPresence(descriptor_->file())) { |
| 2144 printer->Print(",\n_has_bits_(from._has_bits_)"); |
| 2145 } |
| 2146 |
| 2147 bool need_to_emit_cached_size = true; |
| 2148 const string cached_size_decl = ",\n_cached_size_(0)"; |
| 2149 // We reproduce the logic used for laying out _cached_sized_ in the class |
| 2150 // definition, as to initialize it in-order. |
| 2151 if (HasFieldPresence(descriptor_->file()) && |
| 2152 (HasBitsSize() % 8) != 0) { |
| 2153 printer->Print(cached_size_decl.c_str()); |
| 2154 need_to_emit_cached_size = false; |
| 2155 } |
| 2156 |
| 2157 std::vector<bool> processed(optimized_order_.size(), false); |
| 2158 for (int i = 0; i < optimized_order_.size(); ++i) { |
| 2159 const FieldDescriptor* field = optimized_order_[i]; |
| 2160 |
| 2161 if (!(field->is_repeated() && !(field->is_map())) |
| 2162 ) { |
| 2163 continue; |
| 2164 } |
| 2165 |
| 2166 processed[i] = true; |
| 2167 printer->Print(",\n$name$_(from.$name$_)", |
| 2168 "name", FieldName(field)); |
| 2169 } |
| 2170 |
| 2171 if (need_to_emit_cached_size) { |
| 2172 printer->Print(cached_size_decl.c_str()); |
| 2173 need_to_emit_cached_size = false; |
| 2174 } |
| 2175 |
| 2176 if (IsAnyMessage(descriptor_)) { |
| 2177 printer->Print(",\n_any_metadata_(&type_url_, &value_)"); |
| 2178 } |
| 2179 |
| 2180 printer->Outdent(); |
| 2181 printer->Outdent(); |
| 2182 printer->Print(" {\n"); |
| 2183 |
| 2184 printer->Print( |
| 2185 "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); |
| 2186 |
| 2187 if (descriptor_->extension_range_count() > 0) { |
| 2188 printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); |
| 2189 } |
| 2190 |
| 2191 // TODO(gerbens) Clean this hack, and why do i need a reference to a pointer?? |
| 2192 for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 2193 if (HasDescriptorMethods(descriptor_->file(), options_) && |
| 2194 IsMapEntryMessage(descriptor_->nested_type(i))) { |
| 2195 printer->Print( |
| 2196 "const ::google::protobuf::Descriptor*& $type$_descriptor = " |
| 2197 "file_level_metadata[$index$].descriptor;\n", |
| 2198 "type", ClassName(descriptor_->nested_type(i), false), "index", |
| 2199 SimpleItoa(nested_generators_[i]->index_in_metadata_)); |
| 2200 } |
| 2201 } |
| 2202 |
| 2203 GenerateConstructorBody(printer, processed, true); |
| 2204 |
| 2205 // Copy oneof fields. Oneof field requires oneof case check. |
| 2206 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { |
2238 printer->Print( | 2207 printer->Print( |
2239 ",\n _internal_metadata_(NULL)"); | 2208 "clear_has_$oneofname$();\n" |
2240 } else if (!UseUnknownFieldSet(descriptor_->file(), options_)) { | 2209 "switch (from.$oneofname$_case()) {\n", |
2241 printer->Print(",\n _arena_ptr_(NULL)"); | 2210 "oneofname", descriptor_->oneof_decl(i)->name()); |
| 2211 printer->Indent(); |
| 2212 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
| 2213 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); |
| 2214 printer->Print( |
| 2215 "case k$field_name$: {\n", |
| 2216 "field_name", UnderscoresToCamelCase(field->name(), true)); |
| 2217 printer->Indent(); |
| 2218 field_generators_.get(field).GenerateMergingCode(printer); |
| 2219 printer->Print( |
| 2220 "break;\n"); |
| 2221 printer->Outdent(); |
| 2222 printer->Print( |
| 2223 "}\n"); |
| 2224 } |
| 2225 printer->Print( |
| 2226 "case $cap_oneof_name$_NOT_SET: {\n" |
| 2227 " break;\n" |
| 2228 "}\n", |
| 2229 "oneof_index", |
| 2230 SimpleItoa(descriptor_->oneof_decl(i)->index()), |
| 2231 "cap_oneof_name", |
| 2232 ToUpper(descriptor_->oneof_decl(i)->name())); |
| 2233 printer->Outdent(); |
| 2234 printer->Print( |
| 2235 "}\n"); |
2242 } | 2236 } |
2243 if (IsAnyMessage(descriptor_)) { | 2237 |
2244 printer->Print(",\n _any_metadata_(&type_url_, &value_)"); | 2238 printer->Outdent(); |
2245 } | |
2246 printer->Print(" {\n"); | |
2247 printer->Print( | 2239 printer->Print( |
2248 " SharedCtor();\n" | |
2249 " MergeFrom(from);\n" | |
2250 " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" | 2240 " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" |
2251 "}\n" | 2241 "}\n" |
2252 "\n", | 2242 "\n", |
2253 "classname", classname_, | |
2254 "superclass", superclass, | |
2255 "full_name", descriptor_->full_name()); | 2243 "full_name", descriptor_->full_name()); |
2256 | 2244 |
2257 // Generate the shared constructor code. | 2245 // Generate the shared constructor code. |
2258 GenerateSharedConstructorCode(printer); | 2246 GenerateSharedConstructorCode(printer); |
2259 | 2247 |
2260 // Generate the destructor. | 2248 // Generate the destructor. |
2261 printer->Print( | 2249 printer->Print( |
2262 "$classname$::~$classname$() {\n" | 2250 "$classname$::~$classname$() {\n" |
2263 " // @@protoc_insertion_point(destructor:$full_name$)\n" | 2251 " // @@protoc_insertion_point(destructor:$full_name$)\n" |
2264 " SharedDtor();\n" | 2252 " SharedDtor();\n" |
(...skipping 16 matching lines...) Expand all Loading... |
2281 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" | 2269 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" |
2282 " _cached_size_ = size;\n" | 2270 " _cached_size_ = size;\n" |
2283 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" | 2271 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" |
2284 "}\n", | 2272 "}\n", |
2285 "classname", classname_); | 2273 "classname", classname_); |
2286 | 2274 |
2287 // Only generate this member if it's not disabled. | 2275 // Only generate this member if it's not disabled. |
2288 if (HasDescriptorMethods(descriptor_->file(), options_) && | 2276 if (HasDescriptorMethods(descriptor_->file(), options_) && |
2289 !descriptor_->options().no_standard_descriptor_accessor()) { | 2277 !descriptor_->options().no_standard_descriptor_accessor()) { |
2290 printer->Print( | 2278 printer->Print( |
2291 "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" | 2279 "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" |
2292 " protobuf_AssignDescriptorsOnce();\n" | 2280 " protobuf_AssignDescriptorsOnce();\n" |
2293 " return $classname$_descriptor_;\n" | 2281 " return file_level_metadata[$index$].descriptor;\n" |
2294 "}\n" | 2282 "}\n" |
2295 "\n", | 2283 "\n", |
2296 "classname", classname_, | 2284 "index", SimpleItoa(index_in_metadata_), "classname", classname_); |
2297 "adddescriptorsname", | |
2298 GlobalAddDescriptorsName(descriptor_->file()->name())); | |
2299 } | 2285 } |
2300 | 2286 |
2301 printer->Print( | 2287 printer->Print( |
2302 "const $classname$& $classname$::default_instance() {\n", | 2288 "const $classname$& $classname$::default_instance() {\n" |
2303 "classname", classname_); | 2289 " $initdefaultsname$();\n" |
2304 | 2290 " return *internal_default_instance();\n" |
2305 PrintHandlingOptionalStaticInitializers( | 2291 "}\n\n", |
2306 descriptor_->file(), options_, printer, | 2292 "classname", classname_, "initdefaultsname", |
2307 // With static initializers. | 2293 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 | 2294 |
2323 if (SupportsArenas(descriptor_)) { | 2295 if (SupportsArenas(descriptor_)) { |
2324 printer->Print( | 2296 printer->Print( |
2325 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" | 2297 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" |
2326 " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n" | 2298 " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n" |
2327 "}\n", | 2299 "}\n", |
2328 "classname", classname_); | 2300 "classname", classname_); |
2329 } else { | 2301 } else { |
2330 printer->Print( | 2302 printer->Print( |
2331 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" | 2303 "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n
" |
(...skipping 24 matching lines...) Expand all Loading... |
2356 "void $classname$::Clear() {\n" | 2328 "void $classname$::Clear() {\n" |
2357 "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", | 2329 "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", |
2358 "classname", classname_, "full_name", descriptor_->full_name()); | 2330 "classname", classname_, "full_name", descriptor_->full_name()); |
2359 printer->Indent(); | 2331 printer->Indent(); |
2360 | 2332 |
2361 // Step 1: Extensions | 2333 // Step 1: Extensions |
2362 if (descriptor_->extension_range_count() > 0) { | 2334 if (descriptor_->extension_range_count() > 0) { |
2363 printer->Print("_extensions_.Clear();\n"); | 2335 printer->Print("_extensions_.Clear();\n"); |
2364 } | 2336 } |
2365 | 2337 |
2366 // Step 2: Everything but extensions, repeateds, unions. | 2338 int last_i = -1; |
2367 // These are handled in chunks of 8. The first chunk is | 2339 for (int i = 0; i < optimized_order_.size(); ) { |
2368 // the non-extensions-non-repeateds-non-unions in | 2340 // Detect infinite loops. |
2369 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), | 2341 GOOGLE_CHECK_NE(i, last_i); |
2370 // and the second chunk is the same for | 2342 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 | 2343 |
2389 // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. | 2344 // 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: | 2345 // here. |
2391 // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the | 2346 for (; i < optimized_order_.size(); i++) { |
2392 // positions of two fields in the Message. | 2347 const FieldDescriptor* field = optimized_order_[i]; |
2393 // ZR_ zeroes a non-empty range of fields via memset. | 2348 const FieldGenerator& generator = field_generators_.get(field); |
2394 const char* macros = | 2349 |
2395 "#if defined(__clang__)\n" | 2350 if (!field->is_repeated()) { |
2396 "#define ZR_HELPER_(f) \\\n" | 2351 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 } | 2352 } |
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 | 2353 |
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)) { | 2354 if (use_dependent_base_ && IsFieldDependent(field)) { |
2511 printer->Print("clear_$name$();\n", "name", FieldName(field)); | 2355 printer->Print("clear_$name$();\n", "name", FieldName(field)); |
2512 } else { | 2356 } else { |
2513 field_generators_.get(field).GenerateClearingCode(printer); | 2357 generator.GenerateMessageClearingCode(printer); |
| 2358 } |
| 2359 } |
| 2360 |
| 2361 // Step 3: Greedily seek runs of fields that can be cleared by |
| 2362 // memset-to-0. |
| 2363 int last_chunk = -1; |
| 2364 int last_chunk_start = -1; |
| 2365 int last_chunk_end = -1; |
| 2366 uint32 last_chunk_mask = 0; |
| 2367 |
| 2368 int memset_run_start = -1; |
| 2369 int memset_run_end = -1; |
| 2370 for (; i < optimized_order_.size(); i++) { |
| 2371 const FieldDescriptor* field = optimized_order_[i]; |
| 2372 |
| 2373 if (!CanInitializeByZeroing(field)) { |
| 2374 break; |
| 2375 } |
| 2376 |
| 2377 // "index" defines where in the _has_bits_ the field appears. |
| 2378 // "i" is our loop counter within optimized_order_. |
| 2379 int index = HasFieldPresence(descriptor_->file()) ? |
| 2380 has_bit_indices_[field->index()] : 0; |
| 2381 int chunk = index / 8; |
| 2382 |
| 2383 if (last_chunk == -1) { |
| 2384 last_chunk = chunk; |
| 2385 last_chunk_start = i; |
| 2386 } else if (chunk != last_chunk) { |
| 2387 // Emit the fields for this chunk so far. |
| 2388 break; |
| 2389 } |
| 2390 |
| 2391 if (memset_run_start == -1) { |
| 2392 memset_run_start = i; |
| 2393 } |
| 2394 |
| 2395 memset_run_end = i; |
| 2396 last_chunk_end = i; |
| 2397 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); |
| 2398 } |
| 2399 |
| 2400 // Step 4: Non-repeated, non-zero initializable fields. |
| 2401 for (; i < optimized_order_.size(); i++) { |
| 2402 const FieldDescriptor* field = optimized_order_[i]; |
| 2403 if (field->is_repeated() || CanInitializeByZeroing(field)) { |
| 2404 break; |
| 2405 } |
| 2406 |
| 2407 // "index" defines where in the _has_bits_ the field appears. |
| 2408 // "i" is our loop counter within optimized_order_. |
| 2409 int index = HasFieldPresence(descriptor_->file()) ? |
| 2410 has_bit_indices_[field->index()] : 0; |
| 2411 int chunk = index / 8; |
| 2412 |
| 2413 if (last_chunk == -1) { |
| 2414 last_chunk = chunk; |
| 2415 last_chunk_start = i; |
| 2416 } else if (chunk != last_chunk) { |
| 2417 // Emit the fields for this chunk so far. |
| 2418 break; |
| 2419 } |
| 2420 |
| 2421 last_chunk_end = i; |
| 2422 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); |
| 2423 } |
| 2424 |
| 2425 if (last_chunk != -1) { |
| 2426 GOOGLE_DCHECK_NE(-1, last_chunk_start); |
| 2427 GOOGLE_DCHECK_NE(-1, last_chunk_end); |
| 2428 GOOGLE_DCHECK_NE(0, last_chunk_mask); |
| 2429 |
| 2430 const int count = popcnt(last_chunk_mask); |
| 2431 const bool have_outer_if = HasFieldPresence(descriptor_->file()) && |
| 2432 (last_chunk_start != last_chunk_end); |
| 2433 |
| 2434 if (have_outer_if) { |
| 2435 // Check (up to) 8 has_bits at a time if we have more than one field in |
| 2436 // this chunk. Due to field layout ordering, we may check |
| 2437 // _has_bits_[last_chunk * 8 / 32] multiple times. |
| 2438 GOOGLE_DCHECK_LE(2, count); |
| 2439 GOOGLE_DCHECK_GE(8, count); |
| 2440 |
| 2441 printer->Print( |
| 2442 "if (_has_bits_[$index$ / 32] & $mask$u) {\n", |
| 2443 "index", SimpleItoa(last_chunk * 8), |
| 2444 "mask", SimpleItoa(last_chunk_mask)); |
| 2445 printer->Indent(); |
| 2446 } |
| 2447 |
| 2448 if (memset_run_start != -1) { |
| 2449 if (memset_run_start == memset_run_end) { |
| 2450 // For clarity, do not memset a single field. |
| 2451 const FieldGenerator& generator = |
| 2452 field_generators_.get(optimized_order_[memset_run_start]); |
| 2453 generator.GenerateMessageClearingCode(printer); |
| 2454 } else { |
| 2455 const string first_field_name = |
| 2456 FieldName(optimized_order_[memset_run_start]); |
| 2457 const string last_field_name = |
| 2458 FieldName(optimized_order_[memset_run_end]); |
| 2459 |
| 2460 printer->Print( |
| 2461 "::memset(&$first$_, 0, reinterpret_cast<char*>(&$last$_) -\n" |
| 2462 " reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n", |
| 2463 "first", first_field_name, |
| 2464 "last", last_field_name); |
| 2465 } |
| 2466 |
| 2467 // Advance last_chunk_start to skip over the fields we zeroed/memset. |
| 2468 last_chunk_start = memset_run_end + 1; |
| 2469 } |
| 2470 |
| 2471 // Go back and emit clears for each of the fields we processed. |
| 2472 for (int j = last_chunk_start; j <= last_chunk_end; j++) { |
| 2473 const FieldDescriptor* field = optimized_order_[j]; |
| 2474 const string fieldname = FieldName(field); |
| 2475 const FieldGenerator& generator = field_generators_.get(field); |
| 2476 |
| 2477 // It's faster to just overwrite primitive types, but we should only |
| 2478 // clear strings and messages if they were set. |
| 2479 // |
| 2480 // TODO(kenton): Let the CppFieldGenerator decide this somehow. |
| 2481 bool should_check_bit = |
| 2482 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || |
| 2483 field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; |
| 2484 |
| 2485 bool have_enclosing_if = false; |
| 2486 if (should_check_bit && |
| 2487 // If no field presence, then always clear strings/messages as well. |
| 2488 HasFieldPresence(descriptor_->file())) { |
| 2489 printer->Print("if (has_$name$()) {\n", "name", fieldname); |
| 2490 printer->Indent(); |
| 2491 have_enclosing_if = true; |
| 2492 } |
| 2493 |
| 2494 generator.GenerateMessageClearingCode(printer); |
| 2495 |
| 2496 if (have_enclosing_if) { |
| 2497 printer->Outdent(); |
| 2498 printer->Print("}\n"); |
| 2499 } |
| 2500 } |
| 2501 |
| 2502 if (have_outer_if) { |
| 2503 printer->Outdent(); |
| 2504 printer->Print("}\n"); |
2514 } | 2505 } |
2515 } | 2506 } |
2516 } | 2507 } |
2517 | 2508 |
2518 // Step 4: Unions. | 2509 // Step 4: Unions. |
2519 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 2510 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
2520 printer->Print( | 2511 printer->Print( |
2521 "clear_$oneof_name$();\n", | 2512 "clear_$oneof_name$();\n", |
2522 "oneof_name", descriptor_->oneof_decl(i)->name()); | 2513 "oneof_name", descriptor_->oneof_decl(i)->name()); |
2523 } | 2514 } |
2524 | 2515 |
2525 if (HasFieldPresence(descriptor_->file())) { | 2516 if (HasFieldPresence(descriptor_->file())) { |
2526 // Step 5: Everything else. | 2517 // Step 5: Everything else. |
2527 printer->Print( | 2518 printer->Print("_has_bits_.Clear();\n"); |
2528 "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); | |
2529 } | 2519 } |
2530 | 2520 |
2531 if (PreserveUnknownFields(descriptor_)) { | 2521 if (PreserveUnknownFields(descriptor_)) { |
2532 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 2522 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 } | 2523 } |
2550 | 2524 |
2551 printer->Outdent(); | 2525 printer->Outdent(); |
2552 printer->Print("}\n"); | 2526 printer->Print("}\n"); |
2553 } | 2527 } |
2554 | 2528 |
2555 void MessageGenerator:: | 2529 void MessageGenerator:: |
2556 GenerateOneofClear(io::Printer* printer) { | 2530 GenerateOneofClear(io::Printer* printer) { |
2557 // Generated function clears the active field and union case (e.g. foo_case_). | 2531 // Generated function clears the active field and union case (e.g. foo_case_). |
2558 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 2532 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
2559 map<string, string> oneof_vars; | 2533 std::map<string, string> oneof_vars; |
2560 oneof_vars["classname"] = classname_; | 2534 oneof_vars["classname"] = classname_; |
2561 oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); | 2535 oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); |
2562 oneof_vars["full_name"] = descriptor_->full_name(); | 2536 oneof_vars["full_name"] = descriptor_->full_name(); |
2563 string message_class; | 2537 string message_class; |
2564 | 2538 |
2565 printer->Print(oneof_vars, | 2539 printer->Print(oneof_vars, |
2566 "void $classname$::clear_$oneofname$() {\n" | 2540 "void $classname$::clear_$oneofname$() {\n" |
2567 "// @@protoc_insertion_point(one_of_clear_start:" | 2541 "// @@protoc_insertion_point(one_of_clear_start:" |
2568 "$full_name$)\n"); | 2542 "$full_name$)\n"); |
2569 printer->Indent(); | 2543 printer->Indent(); |
2570 printer->Print(oneof_vars, | 2544 printer->Print(oneof_vars, |
2571 "switch($oneofname$_case()) {\n"); | 2545 "switch ($oneofname$_case()) {\n"); |
2572 printer->Indent(); | 2546 printer->Indent(); |
2573 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | 2547 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
2574 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); | 2548 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); |
2575 printer->Print( | 2549 printer->Print( |
2576 "case k$field_name$: {\n", | 2550 "case k$field_name$: {\n", |
2577 "field_name", UnderscoresToCamelCase(field->name(), true)); | 2551 "field_name", UnderscoresToCamelCase(field->name(), true)); |
2578 printer->Indent(); | 2552 printer->Indent(); |
2579 // We clear only allocated objects in oneofs | 2553 // We clear only allocated objects in oneofs |
2580 if (!IsStringOrMessage(field)) { | 2554 if (!IsStringOrMessage(field)) { |
2581 printer->Print( | 2555 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 | 2589 // Generate the Swap member function. This is a lightweight wrapper around |
2616 // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory | 2590 // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory |
2617 // ownership situation: swapping across arenas or between an arena and a | 2591 // ownership situation: swapping across arenas or between an arena and a |
2618 // heap requires copying. | 2592 // heap requires copying. |
2619 printer->Print( | 2593 printer->Print( |
2620 "GOOGLE_ATTRIBUTE_NOINLINE void $classname$::Swap($classname$* other) {\
n" | 2594 "GOOGLE_ATTRIBUTE_NOINLINE void $classname$::Swap($classname$* other) {\
n" |
2621 " if (other == this) return;\n" | 2595 " if (other == this) return;\n" |
2622 " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n" | 2596 " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n" |
2623 " InternalSwap(other);\n" | 2597 " InternalSwap(other);\n" |
2624 " } else {\n" | 2598 " } else {\n" |
2625 " $classname$ temp;\n" | 2599 " $classname$* temp = New(GetArenaNoVirtual());\n" |
2626 " temp.MergeFrom(*this);\n" | 2600 " temp->MergeFrom(*other);\n" |
2627 " CopyFrom(*other);\n" | 2601 " other->CopyFrom(*this);\n" |
2628 " other->CopyFrom(temp);\n" | 2602 " InternalSwap(temp);\n" |
| 2603 " if (GetArenaNoVirtual() == NULL) {\n" |
| 2604 " delete temp;\n" |
| 2605 " }\n" |
2629 " }\n" | 2606 " }\n" |
2630 "}\n" | 2607 "}\n" |
2631 "void $classname$::UnsafeArenaSwap($classname$* other) {\n" | 2608 "void $classname$::UnsafeArenaSwap($classname$* other) {\n" |
2632 " if (other == this) return;\n" | 2609 " if (other == this) return;\n" |
2633 " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" | 2610 " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" |
2634 " InternalSwap(other);\n" | 2611 " InternalSwap(other);\n" |
2635 "}\n", | 2612 "}\n", |
2636 "classname", classname_); | 2613 "classname", classname_); |
2637 } else { | 2614 } else { |
2638 printer->Print( | 2615 printer->Print( |
2639 "void $classname$::Swap($classname$* other) {\n" | 2616 "void $classname$::Swap($classname$* other) {\n" |
2640 " if (other == this) return;\n" | 2617 " if (other == this) return;\n" |
2641 " InternalSwap(other);\n" | 2618 " InternalSwap(other);\n" |
2642 "}\n", | 2619 "}\n", |
2643 "classname", classname_); | 2620 "classname", classname_); |
2644 } | 2621 } |
2645 | 2622 |
2646 // Generate the UnsafeArenaSwap member function. | 2623 // Generate the UnsafeArenaSwap member function. |
2647 printer->Print("void $classname$::InternalSwap($classname$* other) {\n", | 2624 printer->Print("void $classname$::InternalSwap($classname$* other) {\n", |
2648 "classname", classname_); | 2625 "classname", classname_); |
2649 printer->Indent(); | 2626 printer->Indent(); |
2650 | 2627 |
2651 if (HasGeneratedMethods(descriptor_->file(), options_)) { | 2628 if (HasGeneratedMethods(descriptor_->file(), options_)) { |
2652 for (int i = 0; i < descriptor_->field_count(); i++) { | 2629 for (int i = 0; i < optimized_order_.size(); i++) { |
2653 const FieldDescriptor* field = descriptor_->field(i); | 2630 // optimized_order_ does not contain oneof fields, but the field |
| 2631 // generators for these fields do not emit swapping code on their own. |
| 2632 const FieldDescriptor* field = optimized_order_[i]; |
2654 field_generators_.get(field).GenerateSwappingCode(printer); | 2633 field_generators_.get(field).GenerateSwappingCode(printer); |
2655 } | 2634 } |
2656 | 2635 |
2657 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 2636 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
2658 printer->Print( | 2637 printer->Print( |
2659 "std::swap($oneof_name$_, other->$oneof_name$_);\n" | 2638 "std::swap($oneof_name$_, other->$oneof_name$_);\n" |
2660 "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", | 2639 "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", |
2661 "oneof_name", descriptor_->oneof_decl(i)->name(), | 2640 "oneof_name", descriptor_->oneof_decl(i)->name(), |
2662 "i", SimpleItoa(i)); | 2641 "i", SimpleItoa(i)); |
2663 } | 2642 } |
2664 | 2643 |
2665 if (HasFieldPresence(descriptor_->file())) { | 2644 if (HasFieldPresence(descriptor_->file())) { |
2666 for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { | 2645 for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { |
2667 printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", | 2646 printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", |
2668 "i", SimpleItoa(i)); | 2647 "i", SimpleItoa(i)); |
2669 } | 2648 } |
2670 } | 2649 } |
2671 | 2650 |
2672 // Ignore PreserveUnknownFields here - always swap internal_metadata as it | 2651 if (PreserveUnknownFields(descriptor_)) { |
2673 // may contain more than just unknown fields. | 2652 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 } | 2653 } |
2680 | 2654 |
2681 printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); | 2655 printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); |
2682 if (descriptor_->extension_range_count() > 0) { | 2656 if (descriptor_->extension_range_count() > 0) { |
2683 printer->Print("_extensions_.Swap(&other->_extensions_);\n"); | 2657 printer->Print("_extensions_.Swap(&other->_extensions_);\n"); |
2684 } | 2658 } |
2685 } else { | 2659 } else { |
2686 printer->Print("GetReflection()->Swap(this, other);"); | 2660 printer->Print("GetReflection()->Swap(this, other);"); |
2687 } | 2661 } |
2688 | 2662 |
2689 printer->Outdent(); | 2663 printer->Outdent(); |
2690 printer->Print("}\n"); | 2664 printer->Print("}\n"); |
2691 } | 2665 } |
2692 | 2666 |
2693 void MessageGenerator:: | 2667 void MessageGenerator:: |
2694 GenerateMergeFrom(io::Printer* printer) { | 2668 GenerateMergeFrom(io::Printer* printer) { |
2695 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 2669 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
2696 // Generate the generalized MergeFrom (aka that which takes in the Message | 2670 // Generate the generalized MergeFrom (aka that which takes in the Message |
2697 // base class as a parameter). | 2671 // base class as a parameter). |
2698 printer->Print( | 2672 printer->Print( |
2699 "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\
n" | 2673 "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\
n" |
2700 "// @@protoc_insertion_point(generalized_merge_from_start:" | 2674 "// @@protoc_insertion_point(generalized_merge_from_start:" |
2701 "$full_name$)\n" | 2675 "$full_name$)\n" |
2702 " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", | 2676 " GOOGLE_DCHECK_NE(&from, this);\n", |
2703 "classname", classname_, "full_name", descriptor_->full_name()); | 2677 "classname", classname_, "full_name", descriptor_->full_name()); |
2704 printer->Indent(); | 2678 printer->Indent(); |
2705 | 2679 |
2706 // Cast the message to the proper type. If we find that the message is | 2680 // 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 | 2681 // *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 | 2682 // system, as the GOOGLE_CHECK above ensured that we have the same descripto
r |
2709 // for each message. | 2683 // for each message. |
2710 printer->Print( | 2684 printer->Print( |
2711 "const $classname$* source = \n" | 2685 "const $classname$* source =\n" |
2712 " ::google::protobuf::internal::DynamicCastToGenerated<const $classname
$>(\n" | 2686 " ::google::protobuf::internal::DynamicCastToGenerated<const $classname
$>(\n" |
2713 " &from);\n" | 2687 " &from);\n" |
2714 "if (source == NULL) {\n" | 2688 "if (source == NULL) {\n" |
2715 "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" | 2689 "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" |
2716 "$full_name$)\n" | 2690 "$full_name$)\n" |
2717 " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" | 2691 " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" |
2718 "} else {\n" | 2692 "} else {\n" |
2719 "// @@protoc_insertion_point(generalized_merge_from_cast_success:" | 2693 "// @@protoc_insertion_point(generalized_merge_from_cast_success:" |
2720 "$full_name$)\n" | 2694 "$full_name$)\n" |
2721 " MergeFrom(*source);\n" | 2695 " MergeFrom(*source);\n" |
(...skipping 11 matching lines...) Expand all Loading... |
2733 "}\n" | 2707 "}\n" |
2734 "\n", | 2708 "\n", |
2735 "classname", classname_); | 2709 "classname", classname_); |
2736 } | 2710 } |
2737 | 2711 |
2738 // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and ca
st. | 2712 // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and ca
st. |
2739 printer->Print( | 2713 printer->Print( |
2740 "void $classname$::MergeFrom(const $classname$& from) {\n" | 2714 "void $classname$::MergeFrom(const $classname$& from) {\n" |
2741 "// @@protoc_insertion_point(class_specific_merge_from_start:" | 2715 "// @@protoc_insertion_point(class_specific_merge_from_start:" |
2742 "$full_name$)\n" | 2716 "$full_name$)\n" |
2743 " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", | 2717 " GOOGLE_DCHECK_NE(&from, this);\n", |
2744 "classname", classname_, "full_name", descriptor_->full_name()); | 2718 "classname", classname_, "full_name", descriptor_->full_name()); |
2745 printer->Indent(); | 2719 printer->Indent(); |
2746 | 2720 |
2747 // Merge Repeated fields. These fields do not require a | 2721 if (descriptor_->extension_range_count() > 0) { |
2748 // check as we can simply iterate over them. | 2722 printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); |
2749 for (int i = 0; i < descriptor_->field_count(); ++i) { | 2723 } |
2750 const FieldDescriptor* field = descriptor_->field(i); | |
2751 | 2724 |
2752 if (field->is_repeated()) { | 2725 printer->Print( |
2753 field_generators_.get(field).GenerateMergingCode(printer); | 2726 "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); |
| 2727 |
| 2728 int last_i = -1; |
| 2729 for (int i = 0; i < optimized_order_.size(); ) { |
| 2730 // Detect infinite loops. |
| 2731 GOOGLE_CHECK_NE(i, last_i); |
| 2732 last_i = i; |
| 2733 |
| 2734 // Merge Repeated fields. These fields do not require a |
| 2735 // check as we can simply iterate over them. |
| 2736 for (; i < optimized_order_.size(); i++) { |
| 2737 const FieldDescriptor* field = optimized_order_[i]; |
| 2738 if (!field->is_repeated()) { |
| 2739 break; |
| 2740 } |
| 2741 |
| 2742 const FieldGenerator& generator = field_generators_.get(field); |
| 2743 generator.GenerateMergingCode(printer); |
| 2744 } |
| 2745 |
| 2746 // Merge Optional and Required fields (after a _has_bit check). |
| 2747 int last_chunk = -1; |
| 2748 int last_chunk_start = -1; |
| 2749 int last_chunk_end = -1; |
| 2750 uint32 last_chunk_mask = 0; |
| 2751 for (; i < optimized_order_.size(); i++) { |
| 2752 const FieldDescriptor* field = optimized_order_[i]; |
| 2753 if (field->is_repeated()) { |
| 2754 break; |
| 2755 } |
| 2756 |
| 2757 // "index" defines where in the _has_bits_ the field appears. |
| 2758 // "i" is our loop counter within optimized_order_. |
| 2759 int index = HasFieldPresence(descriptor_->file()) ? |
| 2760 has_bit_indices_[field->index()] : 0; |
| 2761 int chunk = index / 8; |
| 2762 |
| 2763 if (last_chunk == -1) { |
| 2764 last_chunk = chunk; |
| 2765 last_chunk_start = i; |
| 2766 } else if (chunk != last_chunk) { |
| 2767 // Emit the fields for this chunk so far. |
| 2768 break; |
| 2769 } |
| 2770 |
| 2771 last_chunk_end = i; |
| 2772 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); |
| 2773 } |
| 2774 |
| 2775 if (last_chunk != -1) { |
| 2776 GOOGLE_DCHECK_NE(-1, last_chunk_start); |
| 2777 GOOGLE_DCHECK_NE(-1, last_chunk_end); |
| 2778 GOOGLE_DCHECK_NE(0, last_chunk_mask); |
| 2779 |
| 2780 const int count = popcnt(last_chunk_mask); |
| 2781 const bool have_outer_if = HasFieldPresence(descriptor_->file()) && |
| 2782 (last_chunk_start != last_chunk_end); |
| 2783 |
| 2784 if (have_outer_if) { |
| 2785 // Check (up to) 8 has_bits at a time if we have more than one field in |
| 2786 // this chunk. Due to field layout ordering, we may check |
| 2787 // _has_bits_[last_chunk * 8 / 32] multiple times. |
| 2788 GOOGLE_DCHECK_LE(2, count); |
| 2789 GOOGLE_DCHECK_GE(8, count); |
| 2790 |
| 2791 printer->Print( |
| 2792 "if (from._has_bits_[$index$ / 32] & $mask$u) {\n", |
| 2793 "index", SimpleItoa(last_chunk * 8), |
| 2794 "mask", SimpleItoa(last_chunk_mask)); |
| 2795 printer->Indent(); |
| 2796 } |
| 2797 |
| 2798 // Go back and emit clears for each of the fields we processed. |
| 2799 for (int j = last_chunk_start; j <= last_chunk_end; j++) { |
| 2800 const FieldDescriptor* field = optimized_order_[j]; |
| 2801 const FieldGenerator& generator = field_generators_.get(field); |
| 2802 |
| 2803 bool have_enclosing_if = false; |
| 2804 if (HasFieldPresence(descriptor_->file())) { |
| 2805 printer->Print( |
| 2806 "if (from.has_$name$()) {\n", |
| 2807 "name", FieldName(field)); |
| 2808 printer->Indent(); |
| 2809 have_enclosing_if = true; |
| 2810 } else { |
| 2811 // Merge semantics without true field presence: primitive fields are |
| 2812 // merged only if non-zero (numeric) or non-empty (string). |
| 2813 have_enclosing_if = EmitFieldNonDefaultCondition( |
| 2814 printer, "from.", field); |
| 2815 } |
| 2816 |
| 2817 generator.GenerateMergingCode(printer); |
| 2818 |
| 2819 if (have_enclosing_if) { |
| 2820 printer->Outdent(); |
| 2821 printer->Print("}\n"); |
| 2822 } |
| 2823 } |
| 2824 |
| 2825 if (have_outer_if) { |
| 2826 printer->Outdent(); |
| 2827 printer->Print("}\n"); |
| 2828 } |
2754 } | 2829 } |
2755 } | 2830 } |
2756 | 2831 |
2757 // Merge oneof fields. Oneof field requires oneof case check. | 2832 // Merge oneof fields. Oneof field requires oneof case check. |
2758 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { | 2833 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { |
2759 printer->Print( | 2834 printer->Print( |
2760 "switch (from.$oneofname$_case()) {\n", | 2835 "switch (from.$oneofname$_case()) {\n", |
2761 "oneofname", descriptor_->oneof_decl(i)->name()); | 2836 "oneofname", descriptor_->oneof_decl(i)->name()); |
2762 printer->Indent(); | 2837 printer->Indent(); |
2763 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | 2838 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" | 2852 "case $cap_oneof_name$_NOT_SET: {\n" |
2778 " break;\n" | 2853 " break;\n" |
2779 "}\n", | 2854 "}\n", |
2780 "cap_oneof_name", | 2855 "cap_oneof_name", |
2781 ToUpper(descriptor_->oneof_decl(i)->name())); | 2856 ToUpper(descriptor_->oneof_decl(i)->name())); |
2782 printer->Outdent(); | 2857 printer->Outdent(); |
2783 printer->Print( | 2858 printer->Print( |
2784 "}\n"); | 2859 "}\n"); |
2785 } | 2860 } |
2786 | 2861 |
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(); | 2862 printer->Outdent(); |
2859 printer->Print("}\n"); | 2863 printer->Print("}\n"); |
2860 } | 2864 } |
2861 | 2865 |
2862 void MessageGenerator:: | 2866 void MessageGenerator:: |
2863 GenerateCopyFrom(io::Printer* printer) { | 2867 GenerateCopyFrom(io::Printer* printer) { |
2864 if (HasDescriptorMethods(descriptor_->file(), options_)) { | 2868 if (HasDescriptorMethods(descriptor_->file(), options_)) { |
2865 // Generate the generalized CopyFrom (aka that which takes in the Message | 2869 // Generate the generalized CopyFrom (aka that which takes in the Message |
2866 // base class as a parameter). | 2870 // base class as a parameter). |
2867 printer->Print( | 2871 printer->Print( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2899 | 2903 |
2900 void MessageGenerator:: | 2904 void MessageGenerator:: |
2901 GenerateMergeFromCodedStream(io::Printer* printer) { | 2905 GenerateMergeFromCodedStream(io::Printer* printer) { |
2902 if (descriptor_->options().message_set_wire_format()) { | 2906 if (descriptor_->options().message_set_wire_format()) { |
2903 // Special-case MessageSet. | 2907 // Special-case MessageSet. |
2904 printer->Print( | 2908 printer->Print( |
2905 "bool $classname$::MergePartialFromCodedStream(\n" | 2909 "bool $classname$::MergePartialFromCodedStream(\n" |
2906 " ::google::protobuf::io::CodedInputStream* input) {\n", | 2910 " ::google::protobuf::io::CodedInputStream* input) {\n", |
2907 "classname", classname_); | 2911 "classname", classname_); |
2908 | 2912 |
2909 PrintHandlingOptionalStaticInitializers( | 2913 printer->Print( |
2910 descriptor_->file(), options_, printer, | 2914 " return _extensions_.ParseMessageSet(input, " |
2911 // With static initializers. | 2915 "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", | 2916 " mutable_unknown_fields());\n", |
2917 // Vars. | 2917 // Vars. |
2918 "classname", classname_); | 2918 "classname", classname_); |
2919 | 2919 |
2920 printer->Print( | 2920 printer->Print( |
2921 "}\n"); | 2921 "}\n"); |
2922 return; | 2922 return; |
2923 } | 2923 } |
2924 | 2924 |
2925 printer->Print( | 2925 printer->Print( |
2926 "bool $classname$::MergePartialFromCodedStream(\n" | 2926 "bool $classname$::MergePartialFromCodedStream(\n" |
2927 " ::google::protobuf::io::CodedInputStream* input) {\n" | 2927 " ::google::protobuf::io::CodedInputStream* input) {\n" |
2928 "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\
n" | 2928 "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\
n" |
2929 " ::google::protobuf::uint32 tag;\n", | 2929 " ::google::protobuf::uint32 tag;\n", |
2930 "classname", classname_); | 2930 "classname", classname_); |
2931 | 2931 |
2932 if (PreserveUnknownFields(descriptor_) && | 2932 if (PreserveUnknownFields(descriptor_) && |
2933 !UseUnknownFieldSet(descriptor_->file(), options_)) { | 2933 !UseUnknownFieldSet(descriptor_->file(), options_)) { |
2934 // Use LazyStringOutputString to avoid initializing unknown fields string | 2934 // Use LazyStringOutputString to avoid initializing unknown fields string |
2935 // unless it is actually needed. For the same reason, disable eager refresh | 2935 // unless it is actually needed. For the same reason, disable eager refresh |
2936 // on the CodedOutputStream. | 2936 // on the CodedOutputStream. |
2937 printer->Print( | 2937 printer->Print( |
2938 " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n
" | 2938 " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n
" |
2939 " ::google::protobuf::internal::NewPermanentCallback(\n" | 2939 " NewPermanentCallback(\n" |
2940 " &MutableUnknownFieldsFor$classname$, this));\n" | 2940 " &MutableUnknownFieldsFor$classname$, this));\n" |
2941 " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" | 2941 " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" |
2942 " &unknown_fields_string, false);\n", | 2942 " &unknown_fields_string, false);\n", |
2943 "classname", classname_); | 2943 "classname", classname_); |
2944 } | 2944 } |
2945 | 2945 |
2946 printer->Print( | 2946 printer->Print( |
2947 " // @@protoc_insertion_point(parse_start:$full_name$)\n", | 2947 " // @@protoc_insertion_point(parse_start:$full_name$)\n", |
2948 "full_name", descriptor_->full_name()); | 2948 "full_name", descriptor_->full_name()); |
2949 | 2949 |
2950 printer->Indent(); | 2950 printer->Indent(); |
2951 printer->Print("for (;;) {\n"); | 2951 printer->Print("for (;;) {\n"); |
2952 printer->Indent(); | 2952 printer->Indent(); |
2953 | 2953 |
2954 google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields( | 2954 std::vector<const FieldDescriptor*> ordered_fields = |
2955 SortFieldsByNumber(descriptor_)); | 2955 SortFieldsByNumber(descriptor_); |
2956 uint32 maxtag = descriptor_->field_count() == 0 ? 0 : | 2956 uint32 maxtag = descriptor_->field_count() == 0 ? 0 : |
2957 WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); | 2957 WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); |
2958 const int kCutoff0 = 127; // fits in 1-byte varint | 2958 const int kCutoff0 = 127; // fits in 1-byte varint |
2959 const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint | 2959 const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint |
| 2960 |
| 2961 // We need to capture the last tag when parsing if this is a Group type, as |
| 2962 // our caller will verify (via CodedInputStream::LastTagWas) that the correct |
| 2963 // closing tag was received. |
| 2964 bool capture_last_tag = false; |
| 2965 const Descriptor* parent = descriptor_->containing_type(); |
| 2966 if (parent) { |
| 2967 for (int i = 0; i < parent->field_count(); i++) { |
| 2968 const FieldDescriptor* field = parent->field(i); |
| 2969 if (field->type() == FieldDescriptor::TYPE_GROUP && |
| 2970 field->message_type() == descriptor_) { |
| 2971 capture_last_tag = true; |
| 2972 break; |
| 2973 } |
| 2974 } |
| 2975 } |
| 2976 |
| 2977 for (int i = 0; i < descriptor_->file()->extension_count(); i++) { |
| 2978 const FieldDescriptor* field = descriptor_->file()->extension(i); |
| 2979 if (field->type() == FieldDescriptor::TYPE_GROUP && |
| 2980 field->message_type() == descriptor_) { |
| 2981 capture_last_tag = true; |
| 2982 break; |
| 2983 } |
| 2984 } |
| 2985 |
2960 printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " | 2986 printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " |
2961 "input->ReadTagWithCutoff($max$);\n" | 2987 "input->ReadTagWithCutoff$lasttag$($max$u);\n" |
2962 "tag = p.first;\n" | 2988 "tag = p.first;\n" |
2963 "if (!p.second) goto handle_unusual;\n", | 2989 "if (!p.second) goto handle_unusual;\n", |
2964 "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : | 2990 "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : |
2965 (maxtag <= kCutoff1 ? kCutoff1 : | 2991 (maxtag <= kCutoff1 ? kCutoff1 : |
2966 maxtag))); | 2992 maxtag)), |
| 2993 "lasttag", !capture_last_tag ? "NoLastTag" : ""); |
| 2994 |
2967 if (descriptor_->field_count() > 0) { | 2995 if (descriptor_->field_count() > 0) { |
2968 // We don't even want to print the switch() if we have no fields because | 2996 // 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. | 2997 // MSVC dislikes switch() statements that contain only a default value. |
2970 | 2998 |
2971 // Note: If we just switched on the tag rather than the field number, we | 2999 // 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 | 3000 // 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 | 3001 // 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 | 3002 // creates a jump table that is 8x larger and sparser, and meanwhile the |
2975 // if()s are highly predictable. | 3003 // if()s are highly predictable. |
| 3004 // |
| 3005 // Historically, we inserted checks to peek at the next tag on the wire and |
| 3006 // jump directly to the next case statement. While this avoids the jump |
| 3007 // table that the switch uses, it greatly increases code size (20-60%) and |
| 3008 // inserts branches that may fail (especially for real world protos that |
| 3009 // interleave--in field number order--hot and cold fields). Loadtests |
| 3010 // confirmed that removing this optimization is performance neutral. |
2976 printer->Print("switch (::google::protobuf::internal::WireFormatLite::" | 3011 printer->Print("switch (::google::protobuf::internal::WireFormatLite::" |
2977 "GetTagFieldNumber(tag)) {\n"); | 3012 "GetTagFieldNumber(tag)) {\n"); |
2978 | 3013 |
2979 printer->Indent(); | 3014 printer->Indent(); |
2980 | 3015 |
2981 // Find repeated messages and groups now, to simplify what follows. | 3016 // Find repeated messages and groups now, to simplify what follows. |
2982 hash_set<int> fields_with_parse_loop; | 3017 hash_set<int> fields_with_parse_loop; |
2983 for (int i = 0; i < descriptor_->field_count(); i++) { | 3018 for (int i = 0; i < ordered_fields.size(); i++) { |
2984 const FieldDescriptor* field = ordered_fields[i]; | 3019 const FieldDescriptor* field = ordered_fields[i]; |
2985 if (field->is_repeated() && | 3020 if (field->is_repeated() && |
2986 (field->type() == FieldDescriptor::TYPE_MESSAGE || | 3021 (field->type() == FieldDescriptor::TYPE_MESSAGE || |
2987 field->type() == FieldDescriptor::TYPE_GROUP)) { | 3022 field->type() == FieldDescriptor::TYPE_GROUP)) { |
2988 fields_with_parse_loop.insert(i); | 3023 fields_with_parse_loop.insert(i); |
2989 } | 3024 } |
2990 } | 3025 } |
2991 | 3026 |
2992 // need_label is true if we generated "goto parse_$name$" while handling the | 3027 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]; | 3028 const FieldDescriptor* field = ordered_fields[i]; |
2997 const bool loops = fields_with_parse_loop.count(i) > 0; | 3029 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 | 3030 |
3000 PrintFieldComment(printer, field); | 3031 PrintFieldComment(printer, field); |
3001 | 3032 |
3002 printer->Print( | 3033 printer->Print( |
3003 "case $number$: {\n", | 3034 "case $number$: {\n", |
3004 "number", SimpleItoa(field->number())); | 3035 "number", SimpleItoa(field->number())); |
3005 printer->Indent(); | 3036 printer->Indent(); |
3006 const FieldGenerator& field_generator = field_generators_.get(field); | 3037 const FieldGenerator& field_generator = field_generators_.get(field); |
3007 | 3038 |
3008 // Emit code to parse the common, expected case. | 3039 // Emit code to parse the common, expected case. |
3009 printer->Print("if (tag == $commontag$) {\n", | 3040 printer->Print("if (tag == $commontag$u) {\n", |
3010 "commontag", SimpleItoa(WireFormat::MakeTag(field))); | 3041 "commontag", SimpleItoa(WireFormat::MakeTag(field))); |
3011 | 3042 |
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) { | 3043 if (loops) { |
3019 printer->Print( | 3044 printer->Print(" DO_(input->IncrementRecursionDepth());\n"); |
3020 " DO_(input->IncrementRecursionDepth());\n" | |
3021 " parse_loop_$name$:\n", | |
3022 "name", field->name()); | |
3023 } | 3045 } |
3024 | 3046 |
3025 printer->Indent(); | 3047 printer->Indent(); |
3026 if (field->is_packed()) { | 3048 if (field->is_packed()) { |
3027 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); | 3049 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); |
3028 } else { | 3050 } else { |
3029 field_generator.GenerateMergeFromCodedStream(printer); | 3051 field_generator.GenerateMergeFromCodedStream(printer); |
3030 } | 3052 } |
3031 printer->Outdent(); | 3053 printer->Outdent(); |
3032 | 3054 |
3033 // Emit code to parse unexpectedly packed or unpacked values. | 3055 // Emit code to parse unexpectedly packed or unpacked values. |
3034 if (field->is_packed()) { | 3056 if (field->is_packed()) { |
3035 internal::WireFormatLite::WireType wiretype = | 3057 internal::WireFormatLite::WireType wiretype = |
3036 WireFormat::WireTypeForFieldType(field->type()); | 3058 WireFormat::WireTypeForFieldType(field->type()); |
3037 printer->Print("} else if (tag == $uncommontag$) {\n", | 3059 printer->Print("} else if (tag == $uncommontag$u) {\n", |
3038 "uncommontag", SimpleItoa( | 3060 "uncommontag", SimpleItoa( |
3039 internal::WireFormatLite::MakeTag( | 3061 internal::WireFormatLite::MakeTag( |
3040 field->number(), wiretype))); | 3062 field->number(), wiretype))); |
3041 printer->Indent(); | 3063 printer->Indent(); |
3042 field_generator.GenerateMergeFromCodedStream(printer); | 3064 field_generator.GenerateMergeFromCodedStream(printer); |
3043 printer->Outdent(); | 3065 printer->Outdent(); |
3044 } else if (field->is_packable() && !field->is_packed()) { | 3066 } else if (field->is_packable() && !field->is_packed()) { |
3045 internal::WireFormatLite::WireType wiretype = | 3067 internal::WireFormatLite::WireType wiretype = |
3046 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; | 3068 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; |
3047 printer->Print("} else if (tag == $uncommontag$) {\n", | 3069 printer->Print("} else if (tag == $uncommontag$u) {\n", |
3048 "uncommontag", SimpleItoa( | 3070 "uncommontag", SimpleItoa( |
3049 internal::WireFormatLite::MakeTag( | 3071 internal::WireFormatLite::MakeTag( |
3050 field->number(), wiretype))); | 3072 field->number(), wiretype))); |
3051 printer->Indent(); | 3073 printer->Indent(); |
3052 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); | 3074 field_generator.GenerateMergeFromCodedStreamWithPacking(printer); |
3053 printer->Outdent(); | 3075 printer->Outdent(); |
3054 } | 3076 } |
3055 | 3077 |
3056 printer->Print( | 3078 printer->Print( |
3057 "} else {\n" | 3079 "} else {\n" |
3058 " goto handle_unusual;\n" | 3080 " goto handle_unusual;\n" |
3059 "}\n"); | 3081 "}\n"); |
3060 | 3082 |
3061 // switch() is slow since it can't be predicted well. Insert some if()s | 3083 // 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) { | 3084 if (loops) { |
3065 printer->Print( | 3085 printer->Print( |
3066 "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n", | 3086 "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 } | 3087 } |
3111 | 3088 |
3112 printer->Print( | 3089 printer->Print( |
3113 "break;\n"); | 3090 "break;\n"); |
3114 | 3091 |
3115 printer->Outdent(); | 3092 printer->Outdent(); |
3116 printer->Print("}\n\n"); | 3093 printer->Print("}\n\n"); |
3117 } | 3094 } |
3118 | 3095 |
3119 printer->Print("default: {\n"); | 3096 printer->Print("default: {\n"); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3152 } else { | 3129 } else { |
3153 printer->Print( | 3130 printer->Print( |
3154 "($start$u <= tag && tag < $end$u)", | 3131 "($start$u <= tag && tag < $end$u)", |
3155 "start", SimpleItoa(start_tag), | 3132 "start", SimpleItoa(start_tag), |
3156 "end", SimpleItoa(end_tag)); | 3133 "end", SimpleItoa(end_tag)); |
3157 } | 3134 } |
3158 } | 3135 } |
3159 printer->Print(") {\n"); | 3136 printer->Print(") {\n"); |
3160 if (PreserveUnknownFields(descriptor_)) { | 3137 if (PreserveUnknownFields(descriptor_)) { |
3161 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 3138 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
3162 PrintHandlingOptionalStaticInitializers( | 3139 printer->Print( |
3163 descriptor_->file(), options_, printer, | 3140 " DO_(_extensions_.ParseField(tag, input, " |
3164 // With static initializers. | 3141 "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"); | 3142 " mutable_unknown_fields()));\n"); |
3170 } else { | 3143 } else { |
3171 PrintHandlingOptionalStaticInitializers( | 3144 printer->Print( |
3172 descriptor_->file(), options_, printer, | 3145 " DO_(_extensions_.ParseField(tag, input, " |
3173 // With static initializers. | 3146 "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"); | 3147 " &unknown_fields_stream));\n"); |
3179 } | 3148 } |
3180 } else { | 3149 } else { |
3181 PrintHandlingOptionalStaticInitializers( | 3150 printer->Print( |
3182 descriptor_->file(), options_, printer, | |
3183 // With static initializers. | 3151 // With static initializers. |
3184 " DO_(_extensions_.ParseField(tag, input, default_instance_);\n", | 3152 " DO_(_extensions_.ParseField(tag, input, " |
3185 // Without. | 3153 "internal_default_instance());\n"); |
3186 " DO_(_extensions_.ParseField(tag, input, &default_instance());\n"); | |
3187 } | 3154 } |
3188 printer->Print( | 3155 printer->Print( |
3189 " continue;\n" | 3156 " continue;\n" |
3190 "}\n"); | 3157 "}\n"); |
3191 } | 3158 } |
3192 | 3159 |
3193 // We really don't recognize this tag. Skip it. | 3160 // We really don't recognize this tag. Skip it. |
3194 if (PreserveUnknownFields(descriptor_)) { | 3161 if (PreserveUnknownFields(descriptor_)) { |
3195 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 3162 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
3196 printer->Print( | 3163 printer->Print( |
(...skipping 24 matching lines...) Expand all Loading... |
3221 "success:\n" | 3188 "success:\n" |
3222 " // @@protoc_insertion_point(parse_success:$full_name$)\n" | 3189 " // @@protoc_insertion_point(parse_success:$full_name$)\n" |
3223 " return true;\n" | 3190 " return true;\n" |
3224 "failure:\n" | 3191 "failure:\n" |
3225 " // @@protoc_insertion_point(parse_failure:$full_name$)\n" | 3192 " // @@protoc_insertion_point(parse_failure:$full_name$)\n" |
3226 " return false;\n" | 3193 " return false;\n" |
3227 "#undef DO_\n" | 3194 "#undef DO_\n" |
3228 "}\n", "full_name", descriptor_->full_name()); | 3195 "}\n", "full_name", descriptor_->full_name()); |
3229 } | 3196 } |
3230 | 3197 |
| 3198 void MessageGenerator::GenerateSerializeOneofFields( |
| 3199 io::Printer* printer, const std::vector<const FieldDescriptor*>& fields, |
| 3200 bool to_array) { |
| 3201 GOOGLE_CHECK(!fields.empty()); |
| 3202 if (fields.size() == 1) { |
| 3203 GenerateSerializeOneField(printer, fields[0], to_array); |
| 3204 return; |
| 3205 } |
| 3206 // We have multiple mutually exclusive choices. Emit a switch statement. |
| 3207 const OneofDescriptor* oneof = fields[0]->containing_oneof(); |
| 3208 printer->Print( |
| 3209 "switch ($oneofname$_case()) {\n", |
| 3210 "oneofname", oneof->name()); |
| 3211 printer->Indent(); |
| 3212 for (int i = 0; i < fields.size(); i++) { |
| 3213 const FieldDescriptor* field = fields[i]; |
| 3214 printer->Print( |
| 3215 "case k$field_name$:\n", |
| 3216 "field_name", UnderscoresToCamelCase(field->name(), true)); |
| 3217 printer->Indent(); |
| 3218 if (to_array) { |
| 3219 field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( |
| 3220 printer); |
| 3221 } else { |
| 3222 field_generators_.get(field).GenerateSerializeWithCachedSizes(printer); |
| 3223 } |
| 3224 printer->Print( |
| 3225 "break;\n"); |
| 3226 printer->Outdent(); |
| 3227 } |
| 3228 printer->Outdent(); |
| 3229 // Doing nothing is an option. |
| 3230 printer->Print( |
| 3231 " default: ;\n" |
| 3232 "}\n"); |
| 3233 } |
| 3234 |
3231 void MessageGenerator::GenerateSerializeOneField( | 3235 void MessageGenerator::GenerateSerializeOneField( |
3232 io::Printer* printer, const FieldDescriptor* field, bool to_array) { | 3236 io::Printer* printer, const FieldDescriptor* field, bool to_array) { |
3233 PrintFieldComment(printer, field); | 3237 PrintFieldComment(printer, field); |
3234 | 3238 |
3235 bool have_enclosing_if = false; | 3239 bool have_enclosing_if = false; |
3236 if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) { | 3240 if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) { |
3237 printer->Print( | 3241 printer->Print( |
3238 "if (has_$name$()) {\n", | 3242 "if (has_$name$()) {\n", |
3239 "name", FieldName(field)); | 3243 "name", FieldName(field)); |
3240 printer->Indent(); | 3244 printer->Indent(); |
(...skipping 12 matching lines...) Expand all Loading... |
3253 if (have_enclosing_if) { | 3257 if (have_enclosing_if) { |
3254 printer->Outdent(); | 3258 printer->Outdent(); |
3255 printer->Print("}\n"); | 3259 printer->Print("}\n"); |
3256 } | 3260 } |
3257 printer->Print("\n"); | 3261 printer->Print("\n"); |
3258 } | 3262 } |
3259 | 3263 |
3260 void MessageGenerator::GenerateSerializeOneExtensionRange( | 3264 void MessageGenerator::GenerateSerializeOneExtensionRange( |
3261 io::Printer* printer, const Descriptor::ExtensionRange* range, | 3265 io::Printer* printer, const Descriptor::ExtensionRange* range, |
3262 bool to_array) { | 3266 bool to_array) { |
3263 map<string, string> vars; | 3267 std::map<string, string> vars; |
3264 vars["start"] = SimpleItoa(range->start); | 3268 vars["start"] = SimpleItoa(range->start); |
3265 vars["end"] = SimpleItoa(range->end); | 3269 vars["end"] = SimpleItoa(range->end); |
3266 printer->Print(vars, | 3270 printer->Print(vars, |
3267 "// Extension range [$start$, $end$)\n"); | 3271 "// Extension range [$start$, $end$)\n"); |
3268 if (to_array) { | 3272 if (to_array) { |
3269 printer->Print(vars, | 3273 printer->Print(vars, |
3270 "target = _extensions_.SerializeWithCachedSizesToArray(\n" | 3274 "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n" |
3271 " $start$, $end$, target);\n\n"); | 3275 " $start$, $end$, false, target);\n\n"); |
3272 } else { | 3276 } else { |
3273 printer->Print(vars, | 3277 printer->Print(vars, |
3274 "_extensions_.SerializeWithCachedSizes(\n" | 3278 "_extensions_.SerializeWithCachedSizes(\n" |
3275 " $start$, $end$, output);\n\n"); | 3279 " $start$, $end$, output);\n\n"); |
3276 } | 3280 } |
3277 } | 3281 } |
3278 | 3282 |
3279 void MessageGenerator:: | 3283 void MessageGenerator:: |
3280 GenerateSerializeWithCachedSizes(io::Printer* printer) { | 3284 GenerateSerializeWithCachedSizes(io::Printer* printer) { |
3281 if (descriptor_->options().message_set_wire_format()) { | 3285 if (descriptor_->options().message_set_wire_format()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3313 printer->Outdent(); | 3317 printer->Outdent(); |
3314 printer->Print( | 3318 printer->Print( |
3315 "}\n"); | 3319 "}\n"); |
3316 } | 3320 } |
3317 | 3321 |
3318 void MessageGenerator:: | 3322 void MessageGenerator:: |
3319 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { | 3323 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { |
3320 if (descriptor_->options().message_set_wire_format()) { | 3324 if (descriptor_->options().message_set_wire_format()) { |
3321 // Special-case MessageSet. | 3325 // Special-case MessageSet. |
3322 printer->Print( | 3326 printer->Print( |
3323 "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\
n" | 3327 "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesT
oArray(\n" |
3324 " ::google::protobuf::uint8* target) const {\n" | 3328 " bool deterministic, ::google::protobuf::uint8* target) const {\n" |
3325 " target =\n" | 3329 " target = _extensions_." |
3326 " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", | 3330 "InternalSerializeMessageSetWithCachedSizesToArray(\n" |
| 3331 " deterministic, target);\n", |
3327 "classname", classname_); | 3332 "classname", classname_); |
3328 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); | 3333 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); |
3329 printer->Print( | 3334 printer->Print( |
3330 " target = ::google::protobuf::internal::WireFormat::\n" | 3335 " target = ::google::protobuf::internal::WireFormat::\n" |
3331 " SerializeUnknownMessageSetItemsToArray(\n" | 3336 " SerializeUnknownMessageSetItemsToArray(\n" |
3332 " unknown_fields(), target);\n"); | 3337 " unknown_fields(), target);\n"); |
3333 printer->Print( | 3338 printer->Print( |
3334 " return target;\n" | 3339 " return target;\n" |
3335 "}\n"); | 3340 "}\n"); |
3336 return; | 3341 return; |
3337 } | 3342 } |
3338 | 3343 |
3339 printer->Print( | 3344 printer->Print( |
3340 "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" | 3345 "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToA
rray(\n" |
3341 " ::google::protobuf::uint8* target) const {\n", | 3346 " bool deterministic, ::google::protobuf::uint8* target) const {\n", |
3342 "classname", classname_); | 3347 "classname", classname_); |
3343 printer->Indent(); | 3348 printer->Indent(); |
3344 | 3349 |
| 3350 printer->Print("(void)deterministic; // Unused\n"); |
3345 printer->Print( | 3351 printer->Print( |
3346 "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", | 3352 "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", |
3347 "full_name", descriptor_->full_name()); | 3353 "full_name", descriptor_->full_name()); |
3348 | 3354 |
3349 GenerateSerializeWithCachedSizesBody(printer, true); | 3355 GenerateSerializeWithCachedSizesBody(printer, true); |
3350 | 3356 |
3351 printer->Print( | 3357 printer->Print( |
3352 "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", | 3358 "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", |
3353 "full_name", descriptor_->full_name()); | 3359 "full_name", descriptor_->full_name()); |
3354 | 3360 |
3355 printer->Outdent(); | 3361 printer->Outdent(); |
3356 printer->Print( | 3362 printer->Print( |
3357 " return target;\n" | 3363 " return target;\n" |
3358 "}\n"); | 3364 "}\n"); |
3359 } | 3365 } |
3360 | 3366 |
3361 void MessageGenerator:: | 3367 void MessageGenerator:: |
3362 GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { | 3368 GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { |
3363 google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields( | 3369 // If there are multiple fields in a row from the same oneof then we |
3364 SortFieldsByNumber(descriptor_)); | 3370 // coalesce them and emit a switch statement. This is more efficient |
| 3371 // because it lets the C++ compiler know this is a "at most one can happen" |
| 3372 // situation. If we emitted "if (has_x()) ...; if (has_y()) ..." the C++ |
| 3373 // compiler's emitted code might check has_y() even when has_x() is true. |
| 3374 class LazySerializerEmitter { |
| 3375 public: |
| 3376 LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer, |
| 3377 bool to_array) |
| 3378 : mg_(mg), |
| 3379 printer_(printer), |
| 3380 to_array_(to_array), |
| 3381 eager_(!HasFieldPresence(mg->descriptor_->file())) {} |
3365 | 3382 |
3366 vector<const Descriptor::ExtensionRange*> sorted_extensions; | 3383 ~LazySerializerEmitter() { Flush(); } |
| 3384 |
| 3385 // If conditions allow, try to accumulate a run of fields from the same |
| 3386 // oneof, and handle them at the next Flush(). |
| 3387 void Emit(const FieldDescriptor* field) { |
| 3388 if (eager_ || MustFlush(field)) { |
| 3389 Flush(); |
| 3390 } |
| 3391 if (field->containing_oneof() == NULL) { |
| 3392 mg_->GenerateSerializeOneField(printer_, field, to_array_); |
| 3393 } else { |
| 3394 v_.push_back(field); |
| 3395 } |
| 3396 } |
| 3397 |
| 3398 void Flush() { |
| 3399 if (!v_.empty()) { |
| 3400 mg_->GenerateSerializeOneofFields(printer_, v_, to_array_); |
| 3401 v_.clear(); |
| 3402 } |
| 3403 } |
| 3404 |
| 3405 private: |
| 3406 // If we have multiple fields in v_ then they all must be from the same |
| 3407 // oneof. Would adding field to v_ break that invariant? |
| 3408 bool MustFlush(const FieldDescriptor* field) { |
| 3409 return !v_.empty() && |
| 3410 v_[0]->containing_oneof() != field->containing_oneof(); |
| 3411 } |
| 3412 |
| 3413 MessageGenerator* mg_; |
| 3414 io::Printer* printer_; |
| 3415 const bool to_array_; |
| 3416 const bool eager_; |
| 3417 std::vector<const FieldDescriptor*> v_; |
| 3418 }; |
| 3419 |
| 3420 std::vector<const FieldDescriptor*> ordered_fields = |
| 3421 SortFieldsByNumber(descriptor_); |
| 3422 |
| 3423 std::vector<const Descriptor::ExtensionRange*> sorted_extensions; |
3367 for (int i = 0; i < descriptor_->extension_range_count(); ++i) { | 3424 for (int i = 0; i < descriptor_->extension_range_count(); ++i) { |
3368 sorted_extensions.push_back(descriptor_->extension_range(i)); | 3425 sorted_extensions.push_back(descriptor_->extension_range(i)); |
3369 } | 3426 } |
3370 std::sort(sorted_extensions.begin(), sorted_extensions.end(), | 3427 std::sort(sorted_extensions.begin(), sorted_extensions.end(), |
3371 ExtensionRangeSorter()); | 3428 ExtensionRangeSorter()); |
3372 | 3429 |
3373 // Merge the fields and the extension ranges, both sorted by field number. | 3430 // Merge the fields and the extension ranges, both sorted by field number. |
3374 int i, j; | 3431 { |
3375 for (i = 0, j = 0; | 3432 LazySerializerEmitter e(this, printer, to_array); |
3376 i < descriptor_->field_count() || j < sorted_extensions.size(); | 3433 int i, j; |
3377 ) { | 3434 for (i = 0, j = 0; |
3378 if (i == descriptor_->field_count()) { | 3435 i < ordered_fields.size() || j < sorted_extensions.size();) { |
3379 GenerateSerializeOneExtensionRange(printer, | 3436 if (i == descriptor_->field_count()) { |
3380 sorted_extensions[j++], | 3437 e.Flush(); |
3381 to_array); | 3438 GenerateSerializeOneExtensionRange(printer, |
3382 } else if (j == sorted_extensions.size()) { | 3439 sorted_extensions[j++], |
3383 GenerateSerializeOneField(printer, ordered_fields[i++], to_array); | 3440 to_array); |
3384 } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) { | 3441 } else if (j == sorted_extensions.size()) { |
3385 GenerateSerializeOneField(printer, ordered_fields[i++], to_array); | 3442 e.Emit(ordered_fields[i++]); |
3386 } else { | 3443 } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) { |
3387 GenerateSerializeOneExtensionRange(printer, | 3444 e.Emit(ordered_fields[i++]); |
3388 sorted_extensions[j++], | 3445 } else { |
3389 to_array); | 3446 e.Flush(); |
| 3447 GenerateSerializeOneExtensionRange(printer, |
| 3448 sorted_extensions[j++], |
| 3449 to_array); |
| 3450 } |
3390 } | 3451 } |
3391 } | 3452 } |
3392 | 3453 |
3393 if (PreserveUnknownFields(descriptor_)) { | 3454 if (PreserveUnknownFields(descriptor_)) { |
3394 if (UseUnknownFieldSet(descriptor_->file(), options_)) { | 3455 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
3395 printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n"); | 3456 printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n"); |
3396 printer->Indent(); | 3457 printer->Indent(); |
3397 if (to_array) { | 3458 if (to_array) { |
3398 printer->Print( | 3459 printer->Print( |
3399 "target = " | 3460 "target = " |
3400 "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsT
oArray(\n" | 3461 "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsT
oArray(\n" |
3401 " unknown_fields(), target);\n"); | 3462 " unknown_fields(), target);\n"); |
3402 } else { | 3463 } else { |
3403 printer->Print( | 3464 printer->Print( |
3404 "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" | 3465 "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" |
3405 " unknown_fields(), output);\n"); | 3466 " unknown_fields(), output);\n"); |
3406 } | 3467 } |
3407 printer->Outdent(); | 3468 printer->Outdent(); |
3408 | 3469 |
3409 printer->Print( | 3470 printer->Print( |
3410 "}\n"); | 3471 "}\n"); |
3411 } else { | 3472 } else { |
3412 printer->Print( | 3473 printer->Print( |
3413 "output->WriteRaw(unknown_fields().data(),\n" | 3474 "output->WriteRaw(unknown_fields().data(),\n" |
3414 " static_cast<int>(unknown_fields().size()));\n"); | 3475 " static_cast<int>(unknown_fields().size()));\n"); |
3415 } | 3476 } |
3416 } | 3477 } |
3417 } | 3478 } |
3418 | 3479 |
3419 static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) { | 3480 std::vector<uint32> MessageGenerator::RequiredFieldsBitMask() const { |
3420 vector<uint32> result; | 3481 const int array_size = HasBitsSize(); |
3421 uint32 mask = 0; | 3482 std::vector<uint32> masks(array_size, 0); |
3422 for (int i = 0; i < desc->field_count(); i++) { | 3483 |
3423 if (i > 0 && i % 32 == 0) { | 3484 for (int i = 0; i < descriptor_->field_count(); i++) { |
3424 result.push_back(mask); | 3485 const FieldDescriptor* field = descriptor_->field(i); |
3425 mask = 0; | 3486 if (!field->is_required()) { |
| 3487 continue; |
3426 } | 3488 } |
3427 if (desc->field(i)->is_required()) { | 3489 |
3428 mask |= (1 << (i & 31)); | 3490 const int has_bit_index = has_bit_indices_[field->index()]; |
3429 } | 3491 masks[has_bit_index / 32] |= |
| 3492 static_cast<uint32>(1) << (has_bit_index % 32); |
3430 } | 3493 } |
3431 if (mask != 0) { | 3494 return masks; |
3432 result.push_back(mask); | |
3433 } | |
3434 return result; | |
3435 } | 3495 } |
3436 | 3496 |
3437 // Create an expression that evaluates to | 3497 // Create an expression that evaluates to |
3438 // "for all i, (_has_bits_[i] & masks[i]) == masks[i]" | 3498 // "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 | 3499 // masks is allowed to be shorter than _has_bits_, but at least one element of |
3440 // masks must be non-zero. | 3500 // masks must be non-zero. |
3441 static string ConditionalToCheckBitmasks(const vector<uint32>& masks) { | 3501 static string ConditionalToCheckBitmasks(const std::vector<uint32>& masks) { |
3442 vector<string> parts; | 3502 std::vector<string> parts; |
3443 for (int i = 0; i < masks.size(); i++) { | 3503 for (int i = 0; i < masks.size(); i++) { |
3444 if (masks[i] == 0) continue; | 3504 if (masks[i] == 0) continue; |
3445 string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); | 3505 string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); |
3446 // Each xor evaluates to 0 if the expected bits are present. | 3506 // Each xor evaluates to 0 if the expected bits are present. |
3447 parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); | 3507 parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); |
3448 } | 3508 } |
3449 GOOGLE_CHECK(!parts.empty()); | 3509 GOOGLE_CHECK(!parts.empty()); |
3450 // If we have multiple parts, each expected to be 0, then bitwise-or them. | 3510 // If we have multiple parts, each expected to be 0, then bitwise-or them. |
3451 string result = parts.size() == 1 ? parts[0] : | 3511 string result = parts.size() == 1 ? parts[0] : |
3452 StrCat("(", Join(parts, "\n | "), ")"); | 3512 StrCat("(", Join(parts, "\n | "), ")"); |
3453 return result + " == 0"; | 3513 return result + " == 0"; |
3454 } | 3514 } |
3455 | 3515 |
3456 void MessageGenerator:: | 3516 void MessageGenerator:: |
3457 GenerateByteSize(io::Printer* printer) { | 3517 GenerateByteSize(io::Printer* printer) { |
3458 if (descriptor_->options().message_set_wire_format()) { | 3518 if (descriptor_->options().message_set_wire_format()) { |
3459 // Special-case MessageSet. | 3519 // Special-case MessageSet. |
3460 printer->Print( | 3520 printer->Print( |
3461 "int $classname$::ByteSize() const {\n" | 3521 "size_t $classname$::ByteSizeLong() const {\n" |
3462 "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" | 3522 "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" |
3463 " int total_size = _extensions_.MessageSetByteSize();\n", | 3523 " size_t total_size = _extensions_.MessageSetByteSize();\n", |
3464 "classname", classname_, "full_name", descriptor_->full_name()); | 3524 "classname", classname_, "full_name", descriptor_->full_name()); |
3465 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); | 3525 GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); |
3466 printer->Print( | 3526 printer->Print( |
3467 "if (_internal_metadata_.have_unknown_fields()) {\n" | 3527 "if (_internal_metadata_.have_unknown_fields()) {\n" |
3468 " total_size += ::google::protobuf::internal::WireFormat::\n" | 3528 " total_size += ::google::protobuf::internal::WireFormat::\n" |
3469 " ComputeUnknownMessageSetItemsSize(unknown_fields());\n" | 3529 " ComputeUnknownMessageSetItemsSize(unknown_fields());\n" |
3470 "}\n"); | 3530 "}\n"); |
3471 printer->Print( | 3531 printer->Print( |
| 3532 " int cached_size = ::google::protobuf::internal::ToCachedSize(total_size
);\n" |
3472 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" | 3533 " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" |
3473 " _cached_size_ = total_size;\n" | 3534 " _cached_size_ = cached_size;\n" |
3474 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" | 3535 " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" |
3475 " return total_size;\n" | 3536 " return total_size;\n" |
3476 "}\n"); | 3537 "}\n"); |
3477 return; | 3538 return; |
3478 } | 3539 } |
3479 | 3540 |
3480 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { | 3541 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { |
3481 // Emit a function (rarely used, we hope) that handles the required fields | 3542 // Emit a function (rarely used, we hope) that handles the required fields |
3482 // by checking for each one individually. | 3543 // by checking for each one individually. |
3483 printer->Print( | 3544 printer->Print( |
3484 "int $classname$::RequiredFieldsByteSizeFallback() const {\n" | 3545 "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n" |
3485 "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" | 3546 "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" |
3486 "$full_name$)\n", | 3547 "$full_name$)\n", |
3487 "classname", classname_, "full_name", descriptor_->full_name()); | 3548 "classname", classname_, "full_name", descriptor_->full_name()); |
3488 printer->Indent(); | 3549 printer->Indent(); |
3489 printer->Print("int total_size = 0;\n"); | 3550 printer->Print("size_t total_size = 0;\n"); |
3490 for (int i = 0; i < descriptor_->field_count(); i++) { | 3551 for (int i = 0; i < optimized_order_.size(); i++) { |
3491 const FieldDescriptor* field = descriptor_->field(i); | 3552 const FieldDescriptor* field = optimized_order_[i]; |
3492 if (field->is_required()) { | 3553 if (field->is_required()) { |
3493 printer->Print("\n" | 3554 printer->Print("\n" |
3494 "if (has_$name$()) {\n", | 3555 "if (has_$name$()) {\n", |
3495 "name", FieldName(field)); | 3556 "name", FieldName(field)); |
3496 printer->Indent(); | 3557 printer->Indent(); |
3497 PrintFieldComment(printer, field); | 3558 PrintFieldComment(printer, field); |
3498 field_generators_.get(field).GenerateByteSize(printer); | 3559 field_generators_.get(field).GenerateByteSize(printer); |
3499 printer->Outdent(); | 3560 printer->Outdent(); |
3500 printer->Print("}\n"); | 3561 printer->Print("}\n"); |
3501 } | 3562 } |
3502 } | 3563 } |
3503 printer->Print("\n" | 3564 printer->Print("\n" |
3504 "return total_size;\n"); | 3565 "return total_size;\n"); |
3505 printer->Outdent(); | 3566 printer->Outdent(); |
3506 printer->Print("}\n"); | 3567 printer->Print("}\n"); |
3507 } | 3568 } |
3508 | 3569 |
3509 printer->Print( | 3570 printer->Print( |
3510 "int $classname$::ByteSize() const {\n" | 3571 "size_t $classname$::ByteSizeLong() const {\n" |
3511 "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", | 3572 "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", |
3512 "classname", classname_, "full_name", descriptor_->full_name()); | 3573 "classname", classname_, "full_name", descriptor_->full_name()); |
3513 printer->Indent(); | 3574 printer->Indent(); |
3514 printer->Print( | 3575 printer->Print( |
3515 "int total_size = 0;\n" | 3576 "size_t total_size = 0;\n" |
3516 "\n"); | 3577 "\n"); |
3517 | 3578 |
| 3579 if (descriptor_->extension_range_count() > 0) { |
| 3580 printer->Print( |
| 3581 "total_size += _extensions_.ByteSize();\n" |
| 3582 "\n"); |
| 3583 } |
| 3584 |
| 3585 if (PreserveUnknownFields(descriptor_)) { |
| 3586 if (UseUnknownFieldSet(descriptor_->file(), options_)) { |
| 3587 printer->Print( |
| 3588 "if (_internal_metadata_.have_unknown_fields()) {\n" |
| 3589 " total_size +=\n" |
| 3590 " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
\n" |
| 3591 " unknown_fields());\n" |
| 3592 "}\n"); |
| 3593 } else { |
| 3594 printer->Print( |
| 3595 "total_size += unknown_fields().size();\n" |
| 3596 "\n"); |
| 3597 } |
| 3598 } |
| 3599 |
3518 // Handle required fields (if any). We expect all of them to be | 3600 // 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 | 3601 // 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. | 3602 // present then the fast path executes; otherwise the slow path executes. |
3521 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { | 3603 if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { |
3522 // The fast path works if all required fields are present. | 3604 // The fast path works if all required fields are present. |
3523 vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_); | 3605 const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(); |
3524 printer->Print((string("if (") + | 3606 printer->Print((string("if (") + |
3525 ConditionalToCheckBitmasks(masks_for_has_bits) + | 3607 ConditionalToCheckBitmasks(masks_for_has_bits) + |
3526 ") { // All required fields are present.\n").c_str()); | 3608 ") { // All required fields are present.\n").c_str()); |
3527 printer->Indent(); | 3609 printer->Indent(); |
3528 for (int i = 0; i < descriptor_->field_count(); i++) { | 3610 // Oneof fields cannot be required, so optimized_order_ contains all of the |
3529 const FieldDescriptor* field = descriptor_->field(i); | 3611 // fields that we need to potentially emit. |
| 3612 for (int i = 0; i < optimized_order_.size(); i++) { |
| 3613 const FieldDescriptor* field = optimized_order_[i]; |
3530 if (!field->is_required()) continue; | 3614 if (!field->is_required()) continue; |
3531 PrintFieldComment(printer, field); | 3615 PrintFieldComment(printer, field); |
3532 field_generators_.get(field).GenerateByteSize(printer); | 3616 field_generators_.get(field).GenerateByteSize(printer); |
3533 printer->Print("\n"); | 3617 printer->Print("\n"); |
3534 } | 3618 } |
3535 printer->Outdent(); | 3619 printer->Outdent(); |
3536 printer->Print("} else {\n" // the slow path | 3620 printer->Print("} else {\n" // the slow path |
3537 " total_size += RequiredFieldsByteSizeFallback();\n" | 3621 " total_size += RequiredFieldsByteSizeFallback();\n" |
3538 "}\n"); | 3622 "}\n"); |
3539 } else { | 3623 } else { |
3540 // num_required_fields_ <= 1: no need to be tricky | 3624 // num_required_fields_ <= 1: no need to be tricky |
3541 for (int i = 0; i < descriptor_->field_count(); i++) { | 3625 for (int i = 0; i < optimized_order_.size(); i++) { |
3542 const FieldDescriptor* field = descriptor_->field(i); | 3626 const FieldDescriptor* field = optimized_order_[i]; |
3543 if (!field->is_required()) continue; | 3627 if (!field->is_required()) continue; |
3544 PrintFieldComment(printer, field); | 3628 PrintFieldComment(printer, field); |
3545 printer->Print("if (has_$name$()) {\n", | 3629 printer->Print("if (has_$name$()) {\n", |
3546 "name", FieldName(field)); | 3630 "name", FieldName(field)); |
3547 printer->Indent(); | 3631 printer->Indent(); |
3548 field_generators_.get(field).GenerateByteSize(printer); | 3632 field_generators_.get(field).GenerateByteSize(printer); |
3549 printer->Outdent(); | 3633 printer->Outdent(); |
3550 printer->Print("}\n"); | 3634 printer->Print("}\n"); |
3551 } | 3635 } |
3552 } | 3636 } |
3553 | 3637 |
3554 // Handle optional fields (worry below about repeateds, oneofs, etc.). | 3638 int last_i = -1; |
3555 // These are handled in chunks of 8. The first chunk is | 3639 for (int i = 0; i < optimized_order_.size(); ) { |
3556 // the non-requireds-non-repeateds-non-unions-non-extensions in | 3640 // Detect infinite loops. |
3557 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), | 3641 GOOGLE_CHECK_NE(i, last_i); |
3558 // and the second chunk is the same for | 3642 last_i = i; |
3559 // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), | 3643 |
3560 // etc. | 3644 // Skip required fields. |
3561 hash_map<int, uint32> fields_mask_for_chunk; | 3645 for (; i < optimized_order_.size() && |
3562 for (int i = 0; i < descriptor_->field_count(); i++) { | 3646 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 } | 3647 } |
3568 } | |
3569 | 3648 |
3570 int last_index = -1; | 3649 // Handle repeated fields. |
3571 bool chunk_block_in_progress = false; | 3650 for (; i < optimized_order_.size(); i++) { |
3572 for (int i = 0; i < descriptor_->field_count(); i++) { | 3651 const FieldDescriptor* field = optimized_order_[i]; |
3573 const FieldDescriptor* field = descriptor_->field(i); | 3652 if (!field->is_repeated()) { |
3574 if (!field->is_required() && !field->is_repeated() && | 3653 break; |
3575 !field->containing_oneof()) { | 3654 } |
3576 // See above in GenerateClear for an explanation of this. | 3655 |
3577 // TODO(kenton): Share code? Unclear how to do so without | 3656 PrintFieldComment(printer, field); |
3578 // over-engineering. | 3657 const FieldGenerator& generator = field_generators_.get(field); |
3579 if (i / 8 != last_index / 8 || last_index < 0) { | 3658 generator.GenerateByteSize(printer); |
3580 // End previous chunk, if there was one. | 3659 printer->Print("\n"); |
3581 if (chunk_block_in_progress) { | 3660 } |
| 3661 |
| 3662 // Handle optional (non-repeated/oneof) fields. |
| 3663 // |
| 3664 // These are handled in chunks of 8. The first chunk is |
| 3665 // the non-requireds-non-repeateds-non-unions-non-extensions in |
| 3666 // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), |
| 3667 // and the second chunk is the same for |
| 3668 // descriptor_->field(8), descriptor_->field(9), ... |
| 3669 // descriptor_->field(15), |
| 3670 // etc. |
| 3671 int last_chunk = -1; |
| 3672 int last_chunk_start = -1; |
| 3673 int last_chunk_end = -1; |
| 3674 uint32 last_chunk_mask = 0; |
| 3675 for (; i < optimized_order_.size(); i++) { |
| 3676 const FieldDescriptor* field = optimized_order_[i]; |
| 3677 if (field->is_repeated() || field->is_required()) { |
| 3678 break; |
| 3679 } |
| 3680 |
| 3681 // "index" defines where in the _has_bits_ the field appears. |
| 3682 // "i" is our loop counter within optimized_order_. |
| 3683 int index = HasFieldPresence(descriptor_->file()) ? |
| 3684 has_bit_indices_[field->index()] : 0; |
| 3685 int chunk = index / 8; |
| 3686 |
| 3687 if (last_chunk == -1) { |
| 3688 last_chunk = chunk; |
| 3689 last_chunk_start = i; |
| 3690 } else if (chunk != last_chunk) { |
| 3691 // Emit the fields for this chunk so far. |
| 3692 break; |
| 3693 } |
| 3694 |
| 3695 last_chunk_end = i; |
| 3696 last_chunk_mask |= static_cast<uint32>(1) << (index % 32); |
| 3697 } |
| 3698 |
| 3699 if (last_chunk != -1) { |
| 3700 GOOGLE_DCHECK_NE(-1, last_chunk_start); |
| 3701 GOOGLE_DCHECK_NE(-1, last_chunk_end); |
| 3702 GOOGLE_DCHECK_NE(0, last_chunk_mask); |
| 3703 |
| 3704 const int count = popcnt(last_chunk_mask); |
| 3705 const bool have_outer_if = HasFieldPresence(descriptor_->file()) && |
| 3706 (last_chunk_start != last_chunk_end); |
| 3707 |
| 3708 if (have_outer_if) { |
| 3709 // Check (up to) 8 has_bits at a time if we have more than one field in |
| 3710 // this chunk. Due to field layout ordering, we may check |
| 3711 // _has_bits_[last_chunk * 8 / 32] multiple times. |
| 3712 GOOGLE_DCHECK_LE(2, count); |
| 3713 GOOGLE_DCHECK_GE(8, count); |
| 3714 |
| 3715 printer->Print( |
| 3716 "if (_has_bits_[$index$ / 32] & $mask$u) {\n", |
| 3717 "index", SimpleItoa(last_chunk * 8), |
| 3718 "mask", SimpleItoa(last_chunk_mask)); |
| 3719 printer->Indent(); |
| 3720 } |
| 3721 |
| 3722 // Go back and emit checks for each of the fields we processed. |
| 3723 for (int j = last_chunk_start; j <= last_chunk_end; j++) { |
| 3724 const FieldDescriptor* field = optimized_order_[j]; |
| 3725 const FieldGenerator& generator = field_generators_.get(field); |
| 3726 |
| 3727 PrintFieldComment(printer, field); |
| 3728 |
| 3729 bool have_enclosing_if = false; |
| 3730 if (HasFieldPresence(descriptor_->file())) { |
| 3731 printer->Print( |
| 3732 "if (has_$name$()) {\n", |
| 3733 "name", FieldName(field)); |
| 3734 printer->Indent(); |
| 3735 have_enclosing_if = true; |
| 3736 } else { |
| 3737 // Without field presence: field is serialized only if it has a |
| 3738 // non-default value. |
| 3739 have_enclosing_if = EmitFieldNonDefaultCondition( |
| 3740 printer, "this->", field); |
| 3741 } |
| 3742 |
| 3743 generator.GenerateByteSize(printer); |
| 3744 |
| 3745 if (have_enclosing_if) { |
3582 printer->Outdent(); | 3746 printer->Outdent(); |
3583 printer->Print("}\n"); | 3747 printer->Print( |
3584 chunk_block_in_progress = false; | 3748 "}\n" |
3585 } | 3749 "\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 } | 3750 } |
3602 } | 3751 } |
3603 last_index = i; | |
3604 | 3752 |
3605 PrintFieldComment(printer, field); | 3753 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(); | 3754 printer->Outdent(); |
3625 printer->Print( | 3755 printer->Print("}\n"); |
3626 "}\n" | |
3627 "\n"); | |
3628 } | 3756 } |
3629 } | 3757 } |
3630 } | 3758 } |
3631 | 3759 |
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 | 3760 // Fields inside a oneof don't use _has_bits_ so we count them in a separate |
3650 // pass. | 3761 // pass. |
3651 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | 3762 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
3652 printer->Print( | 3763 printer->Print( |
3653 "switch ($oneofname$_case()) {\n", | 3764 "switch ($oneofname$_case()) {\n", |
3654 "oneofname", descriptor_->oneof_decl(i)->name()); | 3765 "oneofname", descriptor_->oneof_decl(i)->name()); |
3655 printer->Indent(); | 3766 printer->Indent(); |
3656 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { | 3767 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { |
3657 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); | 3768 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); |
3658 PrintFieldComment(printer, field); | 3769 PrintFieldComment(printer, field); |
(...skipping 12 matching lines...) Expand all Loading... |
3671 "case $cap_oneof_name$_NOT_SET: {\n" | 3782 "case $cap_oneof_name$_NOT_SET: {\n" |
3672 " break;\n" | 3783 " break;\n" |
3673 "}\n", | 3784 "}\n", |
3674 "cap_oneof_name", | 3785 "cap_oneof_name", |
3675 ToUpper(descriptor_->oneof_decl(i)->name())); | 3786 ToUpper(descriptor_->oneof_decl(i)->name())); |
3676 printer->Outdent(); | 3787 printer->Outdent(); |
3677 printer->Print( | 3788 printer->Print( |
3678 "}\n"); | 3789 "}\n"); |
3679 } | 3790 } |
3680 | 3791 |
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, | 3792 // We update _cached_size_ even though this is a const method. In theory, |
3703 // this is not thread-compatible, because concurrent writes have undefined | 3793 // this is not thread-compatible, because concurrent writes have undefined |
3704 // results. In practice, since any concurrent writes will be writing the | 3794 // 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 | 3795 // 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>. | 3796 // of C++, _cached_size_ should be made into an atomic<int>. |
3707 printer->Print( | 3797 printer->Print( |
| 3798 "int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n
" |
3708 "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" | 3799 "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" |
3709 "_cached_size_ = total_size;\n" | 3800 "_cached_size_ = cached_size;\n" |
3710 "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" | 3801 "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" |
3711 "return total_size;\n"); | 3802 "return total_size;\n"); |
3712 | 3803 |
3713 printer->Outdent(); | 3804 printer->Outdent(); |
3714 printer->Print("}\n"); | 3805 printer->Print("}\n"); |
3715 } | 3806 } |
3716 | 3807 |
3717 void MessageGenerator:: | 3808 void MessageGenerator:: |
3718 GenerateIsInitialized(io::Printer* printer) { | 3809 GenerateIsInitialized(io::Printer* printer) { |
3719 printer->Print( | 3810 printer->Print( |
3720 "bool $classname$::IsInitialized() const {\n", | 3811 "bool $classname$::IsInitialized() const {\n", |
3721 "classname", classname_); | 3812 "classname", classname_); |
3722 printer->Indent(); | 3813 printer->Indent(); |
3723 | 3814 |
| 3815 if (descriptor_->extension_range_count() > 0) { |
| 3816 printer->Print( |
| 3817 "if (!_extensions_.IsInitialized()) {\n" |
| 3818 " return false;\n" |
| 3819 "}\n\n"); |
| 3820 } |
| 3821 |
3724 if (HasFieldPresence(descriptor_->file())) { | 3822 if (HasFieldPresence(descriptor_->file())) { |
3725 // Check that all required fields in this message are set. We can do this | 3823 // 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. | 3824 // most efficiently by checking 32 "has bits" at a time. |
3727 int has_bits_array_size = (descriptor_->field_count() + 31) / 32; | 3825 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 | 3826 |
3735 if (field->is_required()) { | 3827 for (int i = 0; i < masks.size(); i++) { |
3736 mask |= 1 << bit; | 3828 uint32 mask = masks[i]; |
3737 } | 3829 if (mask == 0) { |
| 3830 continue; |
3738 } | 3831 } |
3739 | 3832 |
3740 if (mask != 0) { | 3833 // TODO(ckennelly): Consider doing something similar to ByteSizeLong(), |
3741 printer->Print( | 3834 // 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", | 3835 // that we aren't going to benefit from early termination). |
3743 "i", SimpleItoa(i), | 3836 printer->Print( |
3744 "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); | 3837 "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", |
3745 } | 3838 "i", SimpleItoa(i), |
| 3839 "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); |
3746 } | 3840 } |
3747 } | 3841 } |
3748 | 3842 |
3749 // Now check that all embedded messages are initialized. | 3843 // Now check that all non-oneof embedded messages are initialized. |
3750 printer->Print("\n"); | 3844 for (int i = 0; i < optimized_order_.size(); i++) { |
3751 for (int i = 0; i < descriptor_->field_count(); i++) { | 3845 const FieldDescriptor* field = optimized_order_[i]; |
3752 const FieldDescriptor* field = descriptor_->field(i); | 3846 // TODO(ckennelly): Push this down into a generator? |
3753 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && | 3847 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && |
3754 !ShouldIgnoreRequiredFieldCheck(field, options_) && | 3848 !ShouldIgnoreRequiredFieldCheck(field, options_) && |
3755 HasRequiredFields(field->message_type(), options_)) { | 3849 HasRequiredFields(field->message_type(), options_)) { |
3756 if (field->is_repeated()) { | 3850 if (field->is_repeated()) { |
3757 printer->Print( | 3851 printer->Print( |
3758 "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))
" | 3852 "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))
" |
3759 " return false;\n", | 3853 " return false;\n", |
3760 "name", FieldName(field)); | 3854 "name", FieldName(field)); |
3761 } else { | 3855 } else { |
3762 if (field->options().weak() || !field->containing_oneof()) { | 3856 GOOGLE_CHECK(field->options().weak() || !field->containing_oneof()); |
| 3857 // For weak fields, use the data member (::google::protobuf::Message*) i
nstead |
| 3858 // of the getter to avoid a link dependency on the weak message type |
| 3859 // which is only forward declared. |
| 3860 printer->Print( |
| 3861 "if (has_$name$()) {\n" |
| 3862 " if (!this->$name$_->IsInitialized()) return false;\n" |
| 3863 "}\n", |
| 3864 "name", FieldName(field)); |
| 3865 } |
| 3866 } |
| 3867 } |
| 3868 |
| 3869 // Go through the oneof fields, emitting a switch if any might have required |
| 3870 // fields. |
| 3871 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
| 3872 const OneofDescriptor* oneof = descriptor_->oneof_decl(i); |
| 3873 |
| 3874 bool has_required_fields = false; |
| 3875 for (int j = 0; j < oneof->field_count(); j++) { |
| 3876 const FieldDescriptor* field = oneof->field(j); |
| 3877 |
| 3878 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && |
| 3879 !ShouldIgnoreRequiredFieldCheck(field, options_) && |
| 3880 HasRequiredFields(field->message_type(), options_)) { |
| 3881 has_required_fields = true; |
| 3882 break; |
| 3883 } |
| 3884 } |
| 3885 |
| 3886 if (!has_required_fields) { |
| 3887 continue; |
| 3888 } |
| 3889 |
| 3890 printer->Print( |
| 3891 "switch ($oneofname$_case()) {\n", |
| 3892 "oneofname", oneof->name()); |
| 3893 printer->Indent(); |
| 3894 for (int j = 0; j < oneof->field_count(); j++) { |
| 3895 const FieldDescriptor* field = oneof->field(j); |
| 3896 printer->Print( |
| 3897 "case k$field_name$: {\n", |
| 3898 "field_name", UnderscoresToCamelCase(field->name(), true)); |
| 3899 printer->Indent(); |
| 3900 |
| 3901 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && |
| 3902 !ShouldIgnoreRequiredFieldCheck(field, options_) && |
| 3903 HasRequiredFields(field->message_type(), options_)) { |
| 3904 GOOGLE_CHECK(!(field->options().weak() || !field->containing_oneof())); |
| 3905 if (field->options().weak()) { |
3763 // For weak fields, use the data member (::google::protobuf::Message*)
instead | 3906 // 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 | 3907 // of the getter to avoid a link dependency on the weak message type |
3765 // which is only forward declared. | 3908 // which is only forward declared. |
3766 printer->Print( | 3909 printer->Print( |
3767 "if (has_$name$()) {\n" | 3910 "if (has_$name$()) {\n" |
3768 " if (!this->$name$_->IsInitialized()) return false;\n" | 3911 " if (!this->$name$_->IsInitialized()) return false;\n" |
3769 "}\n", | 3912 "}\n", |
3770 "name", FieldName(field)); | 3913 "name", FieldName(field)); |
3771 } else { | 3914 } else { |
3772 printer->Print( | 3915 printer->Print( |
3773 "if (has_$name$()) {\n" | 3916 "if (has_$name$()) {\n" |
3774 " if (!this->$name$().IsInitialized()) return false;\n" | 3917 " if (!this->$name$().IsInitialized()) return false;\n" |
3775 "}\n", | 3918 "}\n", |
3776 "name", FieldName(field)); | 3919 "name", FieldName(field)); |
3777 } | 3920 } |
3778 } | 3921 } |
| 3922 |
| 3923 printer->Print( |
| 3924 "break;\n"); |
| 3925 printer->Outdent(); |
| 3926 printer->Print( |
| 3927 "}\n"); |
3779 } | 3928 } |
3780 } | |
3781 | |
3782 if (descriptor_->extension_range_count() > 0) { | |
3783 printer->Print( | 3929 printer->Print( |
3784 "\n" | 3930 "case $cap_oneof_name$_NOT_SET: {\n" |
3785 "if (!_extensions_.IsInitialized()) return false;"); | 3931 " break;\n" |
| 3932 "}\n", |
| 3933 "cap_oneof_name", |
| 3934 ToUpper(oneof->name())); |
| 3935 printer->Outdent(); |
| 3936 printer->Print( |
| 3937 "}\n"); |
3786 } | 3938 } |
3787 | 3939 |
3788 printer->Outdent(); | 3940 printer->Outdent(); |
3789 printer->Print( | 3941 printer->Print( |
3790 " return true;\n" | 3942 " return true;\n" |
3791 "}\n"); | 3943 "}\n"); |
3792 } | 3944 } |
3793 | 3945 |
3794 | 3946 |
3795 } // namespace cpp | 3947 } // namespace cpp |
3796 } // namespace compiler | 3948 } // namespace compiler |
3797 } // namespace protobuf | 3949 } // namespace protobuf |
3798 } // namespace google | 3950 } // namespace google |
OLD | NEW |