Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc

Issue 2293073002: Tracing V2: Proto fields reflection. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698