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