| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "proto_zero_generator.h" | 5 #include "proto_zero_generator.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 inline std::string ProtoStubName(const FileDescriptor* proto) { | 37 inline std::string ProtoStubName(const FileDescriptor* proto) { |
| 38 return StripSuffixString(proto->name(), ".proto") + ".pbzero"; | 38 return StripSuffixString(proto->name(), ".proto") + ".pbzero"; |
| 39 } | 39 } |
| 40 | 40 |
| 41 class GeneratorJob { | 41 class GeneratorJob { |
| 42 public: | 42 public: |
| 43 GeneratorJob(const FileDescriptor *file, | 43 GeneratorJob(const FileDescriptor *file, |
| 44 Printer* stub_h_printer, | 44 Printer* stub_h_printer, |
| 45 Printer* stub_cc_printer) | 45 Printer* stub_cc_printer) |
| 46 : source_(file), | 46 : source_(file), stub_h_(stub_h_printer), stub_cc_(stub_cc_printer) { |
| 47 stub_h_(stub_h_printer), | 47 } |
| 48 stub_cc_(stub_cc_printer) {} | |
| 49 | 48 |
| 50 bool GenerateStubs() { | 49 bool GenerateStubs() { |
| 51 Preprocess(); | 50 Preprocess(); |
| 52 GeneratePrologue(); | 51 GeneratePrologue(); |
| 53 for (const EnumDescriptor* enumeration: enums_) | 52 for (const EnumDescriptor* enumeration: enums_) |
| 54 GenerateEnumDescriptor(enumeration); | 53 GenerateEnumDescriptor(enumeration); |
| 55 for (const Descriptor* message : messages_) | 54 for (const Descriptor* message : messages_) |
| 56 GenerateMessageDescriptor(message); | 55 GenerateMessageDescriptor(message); |
| 57 GenerateEpilogue(); | 56 GenerateEpilogue(); |
| 58 return error_.empty(); | 57 return error_.empty(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 // prohibited but not recommended in order to avoid name collisions. | 93 // prohibited but not recommended in order to avoid name collisions. |
| 95 template <class T> | 94 template <class T> |
| 96 inline std::string GetCppClassName(const T* descriptor, bool full = false) { | 95 inline std::string GetCppClassName(const T* descriptor, bool full = false) { |
| 97 std::string name = GetDescriptorName(descriptor); | 96 std::string name = GetDescriptorName(descriptor); |
| 98 StripString(&name, ".", '_'); | 97 StripString(&name, ".", '_'); |
| 99 if (full) | 98 if (full) |
| 100 name = full_namespace_prefix_ + name; | 99 name = full_namespace_prefix_ + name; |
| 101 return name; | 100 return name; |
| 102 } | 101 } |
| 103 | 102 |
| 103 inline std::string GetFieldNumberConstant(const FieldDescriptor* field) { |
| 104 std::string name = field->camelcase_name(); |
| 105 if (!name.empty()) { |
| 106 name.at(0) = toupper(name.at(0)); |
| 107 name = "k" + name + "FieldNumber"; |
| 108 } else { |
| 109 // Protoc allows fields like 'bool _ = 1'. |
| 110 Abort("Empty field name in camel case notation."); |
| 111 } |
| 112 return name; |
| 113 } |
| 114 |
| 104 // Small enums can be written faster without involving VarInt encoder. | 115 // Small enums can be written faster without involving VarInt encoder. |
| 105 inline bool IsTinyEnumField(const FieldDescriptor* field) { | 116 inline bool IsTinyEnumField(const FieldDescriptor* field) { |
| 106 if (field->type() != FieldDescriptor::TYPE_ENUM) | 117 if (field->type() != FieldDescriptor::TYPE_ENUM) |
| 107 return false; | 118 return false; |
| 108 const EnumDescriptor* enumeration = field->enum_type(); | 119 const EnumDescriptor* enumeration = field->enum_type(); |
| 109 | 120 |
| 110 for (int i = 0; i < enumeration->value_count(); ++i) { | 121 for (int i = 0; i < enumeration->value_count(); ++i) { |
| 111 int32_t value = enumeration->value(i)->number(); | 122 int32_t value = enumeration->value(i)->number(); |
| 112 if (value < 0 || value > 0x7F) | 123 if (value < 0 || value > 0x7F) |
| 113 return false; | 124 return false; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 stub_h_->Print("\n"); | 267 stub_h_->Print("\n"); |
| 257 | 268 |
| 258 // Print includes for private imports to .cc file. | 269 // Print includes for private imports to .cc file. |
| 259 for (const FileDescriptor* dependency : private_imports_) { | 270 for (const FileDescriptor* dependency : private_imports_) { |
| 260 stub_cc_->Print( | 271 stub_cc_->Print( |
| 261 "#include \"$name$.h\"\n", | 272 "#include \"$name$.h\"\n", |
| 262 "name", ProtoStubName(dependency)); | 273 "name", ProtoStubName(dependency)); |
| 263 } | 274 } |
| 264 stub_cc_->Print("\n"); | 275 stub_cc_->Print("\n"); |
| 265 | 276 |
| 277 if (messages_.size() > 0) { |
| 278 stub_cc_->Print( |
| 279 "namespace {\n" |
| 280 " static const ::tracing::v2::proto::ProtoFieldDescriptor " |
| 281 "kInvalidField = {\"\", " |
| 282 "::tracing::v2::proto::ProtoFieldDescriptor::Type::TYPE_INVALID, " |
| 283 "0, false};\n" |
| 284 "}\n\n"); |
| 285 } |
| 286 |
| 266 // Print namespaces. | 287 // Print namespaces. |
| 267 for (const std::string& ns : namespaces_) { | 288 for (const std::string& ns : namespaces_) { |
| 268 stub_h_->Print("namespace $ns$ {\n", "ns", ns); | 289 stub_h_->Print("namespace $ns$ {\n", "ns", ns); |
| 269 stub_cc_->Print("namespace $ns$ {\n", "ns", ns); | 290 stub_cc_->Print("namespace $ns$ {\n", "ns", ns); |
| 270 } | 291 } |
| 271 stub_h_->Print("\n"); | 292 stub_h_->Print("\n"); |
| 272 stub_cc_->Print("\n"); | 293 stub_cc_->Print("\n"); |
| 273 | 294 |
| 274 // Print forward declarations. | 295 // Print forward declarations. |
| 275 for (const Descriptor* message : referenced_messages_) { | 296 for (const Descriptor* message : referenced_messages_) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 "$inner_class$* $outer_class$::$action$_$name$() {\n" | 449 "$inner_class$* $outer_class$::$action$_$name$() {\n" |
| 429 " return BeginNestedMessage<$inner_class$>($id$);\n" | 450 " return BeginNestedMessage<$inner_class$>($id$);\n" |
| 430 "}\n\n", | 451 "}\n\n", |
| 431 "id", std::to_string(field->number()), | 452 "id", std::to_string(field->number()), |
| 432 "name", field->name(), | 453 "name", field->name(), |
| 433 "action", action, | 454 "action", action, |
| 434 "inner_class", inner_class, | 455 "inner_class", inner_class, |
| 435 "outer_class", outer_class); | 456 "outer_class", outer_class); |
| 436 } | 457 } |
| 437 | 458 |
| 459 void GenerateReflectionForMessageFields(const Descriptor* message) { |
| 460 const bool has_fields = (message->field_count() > 0); |
| 461 |
| 462 // Field number constants. |
| 463 if (has_fields) { |
| 464 stub_h_->Print("enum : int32_t {\n"); |
| 465 stub_h_->Indent(); |
| 466 |
| 467 for (int i = 0; i < message->field_count(); ++i) { |
| 468 const FieldDescriptor* field = message->field(i); |
| 469 stub_h_->Print( |
| 470 "$name$ = $id$,\n", |
| 471 "name", GetFieldNumberConstant(field), |
| 472 "id", std::to_string(field->number())); |
| 473 } |
| 474 stub_h_->Outdent(); |
| 475 stub_h_->Print("};\n"); |
| 476 } |
| 477 |
| 478 // Fields reflection table. |
| 479 stub_h_->Print( |
| 480 "static const ::tracing::v2::proto::ProtoFieldDescriptor* " |
| 481 "GetFieldDescriptor(uint32_t field_id);\n"); |
| 482 |
| 483 std::string class_name = GetCppClassName(message); |
| 484 if (has_fields) { |
| 485 stub_cc_->Print( |
| 486 "static const ::tracing::v2::proto::ProtoFieldDescriptor " |
| 487 "kFields_$class$[] = {\n", |
| 488 "class", class_name); |
| 489 stub_cc_->Indent(); |
| 490 for (int i = 0; i < message->field_count(); ++i) { |
| 491 const FieldDescriptor* field = message->field(i); |
| 492 std::string type_const = |
| 493 std::string("TYPE_") + FieldDescriptor::TypeName(field->type()); |
| 494 UpperString(&type_const); |
| 495 stub_cc_->Print( |
| 496 "{\"$name$\", " |
| 497 "::tracing::v2::proto::ProtoFieldDescriptor::Type::$type$, " |
| 498 "$number$, $is_repeated$},\n", |
| 499 "name", field->name(), |
| 500 "type", type_const, |
| 501 "number", std::to_string(field->number()), |
| 502 "is_repeated", std::to_string(field->is_repeated())); |
| 503 } |
| 504 stub_cc_->Outdent(); |
| 505 stub_cc_->Print("};\n\n"); |
| 506 } |
| 507 |
| 508 // Fields reflection getter. |
| 509 stub_cc_->Print( |
| 510 "const ::tracing::v2::proto::ProtoFieldDescriptor* " |
| 511 "$class$::GetFieldDescriptor(uint32_t field_id) {\n", |
| 512 "class", class_name); |
| 513 stub_cc_->Indent(); |
| 514 if (has_fields) { |
| 515 stub_cc_->Print("switch (field_id) {\n"); |
| 516 stub_cc_->Indent(); |
| 517 for (int i = 0; i < message->field_count(); ++i) { |
| 518 stub_cc_->Print( |
| 519 "case $field$:\n" |
| 520 " return &kFields_$class$[$id$];\n", |
| 521 "class", class_name, |
| 522 "field", GetFieldNumberConstant(message->field(i)), |
| 523 "id", std::to_string(i)); |
| 524 } |
| 525 stub_cc_->Print( |
| 526 "default:\n" |
| 527 " return &kInvalidField;\n"); |
| 528 stub_cc_->Outdent(); |
| 529 stub_cc_->Print("}\n"); |
| 530 } else { |
| 531 stub_cc_->Print("return &kInvalidField;\n"); |
| 532 } |
| 533 stub_cc_->Outdent(); |
| 534 stub_cc_->Print("}\n\n"); |
| 535 } |
| 536 |
| 438 void GenerateMessageDescriptor(const Descriptor* message) { | 537 void GenerateMessageDescriptor(const Descriptor* message) { |
| 439 stub_h_->Print( | 538 stub_h_->Print( |
| 440 "class $name$ : public ::tracing::v2::ProtoZeroMessage {\n" | 539 "class $name$ : public ::tracing::v2::ProtoZeroMessage {\n" |
| 441 " public:\n", | 540 " public:\n", |
| 442 "name", GetCppClassName(message)); | 541 "name", GetCppClassName(message)); |
| 443 stub_h_->Indent(); | 542 stub_h_->Indent(); |
| 444 | 543 |
| 544 GenerateReflectionForMessageFields(message); |
| 545 |
| 445 // Using statements for nested messages. | 546 // Using statements for nested messages. |
| 446 for (int i = 0; i < message->nested_type_count(); ++i) { | 547 for (int i = 0; i < message->nested_type_count(); ++i) { |
| 447 const Descriptor* nested_message = message->nested_type(i); | 548 const Descriptor* nested_message = message->nested_type(i); |
| 448 stub_h_->Print( | 549 stub_h_->Print( |
| 449 "using $local_name$ = $global_name$;\n", | 550 "using $local_name$ = $global_name$;\n", |
| 450 "local_name", nested_message->name(), | 551 "local_name", nested_message->name(), |
| 451 "global_name", GetCppClassName(nested_message, true)); | 552 "global_name", GetCppClassName(nested_message, true)); |
| 452 } | 553 } |
| 453 | 554 |
| 454 // Using statements for nested enums. | 555 // Using statements for nested enums. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 468 for (int j = 0; j < nested_enum->value_count(); ++j) { | 569 for (int j = 0; j < nested_enum->value_count(); ++j) { |
| 469 const EnumValueDescriptor* value = nested_enum->value(j); | 570 const EnumValueDescriptor* value = nested_enum->value(j); |
| 470 stub_h_->Print( | 571 stub_h_->Print( |
| 471 "static const $class$ $name$ = $full_name$;\n", | 572 "static const $class$ $name$ = $full_name$;\n", |
| 472 "class", nested_enum->name(), | 573 "class", nested_enum->name(), |
| 473 "name", value->name(), | 574 "name", value->name(), |
| 474 "full_name", value_name_prefix + value->name()); | 575 "full_name", value_name_prefix + value->name()); |
| 475 } | 576 } |
| 476 } | 577 } |
| 477 | 578 |
| 478 // Field numbers. | |
| 479 if (message->field_count() > 0) { | |
| 480 stub_h_->Print("enum : int32_t {\n"); | |
| 481 stub_h_->Indent(); | |
| 482 | |
| 483 for (int i = 0; i < message->field_count(); ++i) { | |
| 484 const FieldDescriptor* field = message->field(i); | |
| 485 std::string name = field->camelcase_name(); | |
| 486 if (!name.empty()) { | |
| 487 name.at(0) = toupper(name.at(0)); | |
| 488 } else { | |
| 489 // Protoc allows fields like 'bool _ = 1'. | |
| 490 Abort("Empty field name in camel case notation."); | |
| 491 } | |
| 492 | |
| 493 stub_h_->Print( | |
| 494 "k$name$FieldNumber = $id$,\n", | |
| 495 "name", name, | |
| 496 "id", std::to_string(field->number())); | |
| 497 } | |
| 498 stub_h_->Outdent(); | |
| 499 stub_h_->Print("};\n"); | |
| 500 } | |
| 501 | |
| 502 // Field descriptors. | 579 // Field descriptors. |
| 503 for (int i = 0; i < message->field_count(); ++i) { | 580 for (int i = 0; i < message->field_count(); ++i) { |
| 504 const FieldDescriptor* field = message->field(i); | 581 const FieldDescriptor* field = message->field(i); |
| 505 if (field->is_packed()) { | 582 if (field->is_packed()) { |
| 506 Abort("Packed repeated fields are not supported."); | 583 Abort("Packed repeated fields are not supported."); |
| 507 return; | 584 return; |
| 508 } | 585 } |
| 509 if (field->type() != FieldDescriptor::TYPE_MESSAGE) { | 586 if (field->type() != FieldDescriptor::TYPE_MESSAGE) { |
| 510 GenerateSimpleFieldDescriptor(field); | 587 GenerateSimpleFieldDescriptor(field); |
| 511 } else { | 588 } else { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 | 651 |
| 575 if (!job.GenerateStubs()) { | 652 if (!job.GenerateStubs()) { |
| 576 *error = job.GetFirstError(); | 653 *error = job.GetFirstError(); |
| 577 return false; | 654 return false; |
| 578 } | 655 } |
| 579 return true; | 656 return true; |
| 580 } | 657 } |
| 581 | 658 |
| 582 } // namespace proto | 659 } // namespace proto |
| 583 } // namespace tracing | 660 } // namespace tracing |
| OLD | NEW |