Chromium Code Reviews| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 // prohibited but not recommended in order to avoid name collisions. | 94 // prohibited but not recommended in order to avoid name collisions. |
| 95 template <class T> | 95 template <class T> |
| 96 inline std::string GetCppClassName(const T* descriptor, bool full = false) { | 96 inline std::string GetCppClassName(const T* descriptor, bool full = false) { |
| 97 std::string name = GetDescriptorName(descriptor); | 97 std::string name = GetDescriptorName(descriptor); |
| 98 StripString(&name, ".", '_'); | 98 StripString(&name, ".", '_'); |
| 99 if (full) | 99 if (full) |
| 100 name = full_namespace_prefix_ + name; | 100 name = full_namespace_prefix_ + name; |
| 101 return name; | 101 return name; |
| 102 } | 102 } |
| 103 | 103 |
| 104 inline std::string Capitalize(const std::string& str) { | |
|
Primiano Tucci (use gerrit)
2016/08/31 09:04:07
honestly I feel this is just overkill as you use o
| |
| 105 std::string copy(str); | |
| 106 copy.at(0) = toupper(copy.at(0)); | |
| 107 return copy; | |
| 108 } | |
| 109 | |
| 110 inline std::string GetFieldNumberConstant(const FieldDescriptor* field) { | |
| 111 std::string name = field->camelcase_name(); | |
| 112 if (!name.empty()) { | |
| 113 name = std::string("k") + Capitalize(name) + "FieldNumber"; | |
| 114 } else { | |
| 115 // Protoc allows fields like 'bool _ = 1'. | |
| 116 Abort("Empty field name in camel case notation."); | |
| 117 } | |
| 118 return name; | |
| 119 } | |
| 120 | |
| 104 // Small enums can be written faster without involving VarInt encoder. | 121 // Small enums can be written faster without involving VarInt encoder. |
| 105 inline bool IsTinyEnumField(const FieldDescriptor* field) { | 122 inline bool IsTinyEnumField(const FieldDescriptor* field) { |
| 106 if (field->type() != FieldDescriptor::TYPE_ENUM) | 123 if (field->type() != FieldDescriptor::TYPE_ENUM) |
| 107 return false; | 124 return false; |
| 108 const EnumDescriptor* enumeration = field->enum_type(); | 125 const EnumDescriptor* enumeration = field->enum_type(); |
| 109 | 126 |
| 110 for (int i = 0; i < enumeration->value_count(); ++i) { | 127 for (int i = 0; i < enumeration->value_count(); ++i) { |
| 111 int32_t value = enumeration->value(i)->number(); | 128 int32_t value = enumeration->value(i)->number(); |
| 112 if (value < 0 || value > 0x7F) | 129 if (value < 0 || value > 0x7F) |
| 113 return false; | 130 return false; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 "// //components/tracing/tools/proto_zero_plugin.\n"; | 238 "// //components/tracing/tools/proto_zero_plugin.\n"; |
| 222 std::string guard = package_ + "_" + source_->name() + "_H_"; | 239 std::string guard = package_ + "_" + source_->name() + "_H_"; |
| 223 UpperString(&guard); | 240 UpperString(&guard); |
| 224 StripString(&guard, ".-/\\", '_'); | 241 StripString(&guard, ".-/\\", '_'); |
| 225 | 242 |
| 226 stub_h_->Print( | 243 stub_h_->Print( |
| 227 "$greeting$\n" | 244 "$greeting$\n" |
| 228 "#ifndef $guard$\n" | 245 "#ifndef $guard$\n" |
| 229 "#define $guard$\n\n" | 246 "#define $guard$\n\n" |
| 230 "#include <stddef.h>\n" | 247 "#include <stddef.h>\n" |
| 231 "#include <stdint.h>\n\n" | 248 "#include <stdint.h>\n\n" |
|
Primiano Tucci (use gerrit)
2016/08/31 09:04:07
I think you need also cctype for std::toupper
| |
| 249 "#include <string>\n\n" | |
| 232 "#include \"components/tracing/core/proto_zero_message.h\"\n", | 250 "#include \"components/tracing/core/proto_zero_message.h\"\n", |
| 233 "greeting", greeting, | 251 "greeting", greeting, |
| 234 "guard", guard); | 252 "guard", guard); |
| 235 stub_cc_->Print( | 253 stub_cc_->Print( |
| 236 "$greeting$\n" | 254 "$greeting$\n" |
| 237 "#include \"$name$.h\"\n", | 255 "#include \"$name$.h\"\n", |
| 238 "greeting", greeting, | 256 "greeting", greeting, |
| 239 "name", ProtoStubName(source_)); | 257 "name", ProtoStubName(source_)); |
| 240 | 258 |
| 241 // Print includes for public imports. | 259 // Print includes for public imports. |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 "$inner_class$* $outer_class$::$action$_$name$() {\n" | 446 "$inner_class$* $outer_class$::$action$_$name$() {\n" |
| 429 " return BeginNestedMessage<$inner_class$>($id$);\n" | 447 " return BeginNestedMessage<$inner_class$>($id$);\n" |
| 430 "}\n\n", | 448 "}\n\n", |
| 431 "id", std::to_string(field->number()), | 449 "id", std::to_string(field->number()), |
| 432 "name", field->name(), | 450 "name", field->name(), |
| 433 "action", action, | 451 "action", action, |
| 434 "inner_class", inner_class, | 452 "inner_class", inner_class, |
| 435 "outer_class", outer_class); | 453 "outer_class", outer_class); |
| 436 } | 454 } |
| 437 | 455 |
| 456 void GenerateReflectionHelpers(const Descriptor* message) { | |
| 457 // Field numbers. | |
|
Primiano Tucci (use gerrit)
2016/08/31 09:04:07
I'd make this more clear:
// Field Numbers (e.g.,
kraynov
2016/08/31 17:43:33
Acknowledged.
| |
| 458 if (message->field_count() > 0) { | |
| 459 stub_h_->Print("enum : int32_t {\n"); | |
|
Primiano Tucci (use gerrit)
2016/08/31 09:04:07
just realized this, so far we used uint32_t for fi
kraynov
2016/08/31 17:43:33
Acknowledged.
| |
| 460 stub_h_->Indent(); | |
| 461 | |
| 462 for (int i = 0; i < message->field_count(); ++i) { | |
| 463 const FieldDescriptor* field = message->field(i); | |
| 464 stub_h_->Print( | |
| 465 "$name$ = $id$,\n", | |
| 466 "name", GetFieldNumberConstant(field), | |
| 467 "id", std::to_string(field->number())); | |
| 468 } | |
| 469 stub_h_->Outdent(); | |
| 470 stub_h_->Print("};\n"); | |
| 471 } | |
| 472 | |
| 473 // Fields reflection. | |
| 474 stub_h_->Print( | |
| 475 "static ::tracing::v2::proto::FieldReflection " | |
| 476 "GetFieldReflection(uint32_t field_id);"); | |
| 477 stub_cc_->Print( | |
| 478 "::tracing::v2::proto::FieldReflection " | |
| 479 "$class$::GetFieldReflection(uint32_t field_id) {\n", | |
| 480 "class", GetCppClassName(message)); | |
| 481 stub_cc_->Indent(); | |
| 482 stub_cc_->Print("switch (field_id) {\n"); | |
| 483 stub_cc_->Indent(); | |
| 484 | |
| 485 for (int i = 0; i < message->field_count(); ++i) { | |
| 486 const FieldDescriptor* field = message->field(i); | |
| 487 stub_cc_->Print( | |
| 488 "case $id$:\n" | |
| 489 " return ::tracing::v2::proto::FieldReflection(\"$name$\", " | |
|
Primiano Tucci (use gerrit)
2016/08/31 09:04:07
Hmm this is going to be slow.
Can we make this jus
kraynov
2016/08/31 17:43:33
Done.
| |
| 490 "::tracing::v2::proto::ProtoType::kProtoType$type$," | |
| 491 "$id$, $repeated$);\n", | |
| 492 "name", field->name(), | |
| 493 "type", Capitalize(FieldDescriptor::TypeName(field->type())), | |
| 494 "id", GetFieldNumberConstant(field), | |
| 495 "repeated", std::to_string(field->is_repeated())); | |
| 496 } | |
| 497 stub_cc_->Print( | |
| 498 "default:\n" | |
| 499 " return ::tracing::v2::proto::FieldReflection::CreateInvalid();\n"); | |
| 500 | |
| 501 stub_cc_->Outdent(); | |
| 502 stub_cc_->Print("}\n"); | |
| 503 stub_cc_->Outdent(); | |
| 504 stub_cc_->Print("}\n\n"); | |
| 505 } | |
| 506 | |
| 438 void GenerateMessageDescriptor(const Descriptor* message) { | 507 void GenerateMessageDescriptor(const Descriptor* message) { |
| 439 stub_h_->Print( | 508 stub_h_->Print( |
| 440 "class $name$ : public ::tracing::v2::ProtoZeroMessage {\n" | 509 "class $name$ : public ::tracing::v2::ProtoZeroMessage {\n" |
| 441 " public:\n", | 510 " public:\n", |
| 442 "name", GetCppClassName(message)); | 511 "name", GetCppClassName(message)); |
| 443 stub_h_->Indent(); | 512 stub_h_->Indent(); |
| 444 | 513 |
| 514 GenerateReflectionHelpers(message); | |
| 515 | |
| 445 // Using statements for nested messages. | 516 // Using statements for nested messages. |
| 446 for (int i = 0; i < message->nested_type_count(); ++i) { | 517 for (int i = 0; i < message->nested_type_count(); ++i) { |
| 447 const Descriptor* nested_message = message->nested_type(i); | 518 const Descriptor* nested_message = message->nested_type(i); |
| 448 stub_h_->Print( | 519 stub_h_->Print( |
| 449 "using $local_name$ = $global_name$;\n", | 520 "using $local_name$ = $global_name$;\n", |
| 450 "local_name", nested_message->name(), | 521 "local_name", nested_message->name(), |
| 451 "global_name", GetCppClassName(nested_message, true)); | 522 "global_name", GetCppClassName(nested_message, true)); |
| 452 } | 523 } |
| 453 | 524 |
| 454 // Using statements for nested enums. | 525 // Using statements for nested enums. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 468 for (int j = 0; j < nested_enum->value_count(); ++j) { | 539 for (int j = 0; j < nested_enum->value_count(); ++j) { |
| 469 const EnumValueDescriptor* value = nested_enum->value(j); | 540 const EnumValueDescriptor* value = nested_enum->value(j); |
| 470 stub_h_->Print( | 541 stub_h_->Print( |
| 471 "static const $class$ $name$ = $full_name$;\n", | 542 "static const $class$ $name$ = $full_name$;\n", |
| 472 "class", nested_enum->name(), | 543 "class", nested_enum->name(), |
| 473 "name", value->name(), | 544 "name", value->name(), |
| 474 "full_name", value_name_prefix + value->name()); | 545 "full_name", value_name_prefix + value->name()); |
| 475 } | 546 } |
| 476 } | 547 } |
| 477 | 548 |
| 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. | 549 // Field descriptors. |
| 503 for (int i = 0; i < message->field_count(); ++i) { | 550 for (int i = 0; i < message->field_count(); ++i) { |
| 504 const FieldDescriptor* field = message->field(i); | 551 const FieldDescriptor* field = message->field(i); |
| 505 if (field->is_packed()) { | 552 if (field->is_packed()) { |
| 506 Abort("Packed repeated fields are not supported."); | 553 Abort("Packed repeated fields are not supported."); |
| 507 return; | 554 return; |
| 508 } | 555 } |
| 509 if (field->type() != FieldDescriptor::TYPE_MESSAGE) { | 556 if (field->type() != FieldDescriptor::TYPE_MESSAGE) { |
| 510 GenerateSimpleFieldDescriptor(field); | 557 GenerateSimpleFieldDescriptor(field); |
| 511 } else { | 558 } else { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 | 621 |
| 575 if (!job.GenerateStubs()) { | 622 if (!job.GenerateStubs()) { |
| 576 *error = job.GetFirstError(); | 623 *error = job.GetFirstError(); |
| 577 return false; | 624 return false; |
| 578 } | 625 } |
| 579 return true; | 626 return true; |
| 580 } | 627 } |
| 581 | 628 |
| 582 } // namespace proto | 629 } // namespace proto |
| 583 } // namespace tracing | 630 } // namespace tracing |
| OLD | NEW |