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

Unified Diff: components/tracing/proto_zero_plugin/proto_zero_generator.cc

Issue 2083373002: proto_zero_plugin [NOT FOR REVIEW]. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: refactoring Created 4 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: components/tracing/proto_zero_plugin/proto_zero_generator.cc
diff --git a/components/tracing/proto_zero_plugin/proto_zero_generator.cc b/components/tracing/proto_zero_plugin/proto_zero_generator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d7bd85eb066ea16cbe016cb58f44f548844d3d32
--- /dev/null
+++ b/components/tracing/proto_zero_plugin/proto_zero_generator.cc
@@ -0,0 +1,243 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "proto_zero_generator.h"
+
+#include <string>
+#include <algorithm>
+
+#include <google/protobuf/descriptor.h>
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 make these absolute includes https://google.githu
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace fastcpp {
+
+namespace {
+
+// TODO(kraynov) Ship "lite" runtime in order to use outside of tracing.
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 Not sure what this TODO means.
+const string OUT_INCLUDES =
Primiano Tucci (use gerrit) 2016/07/05 11:30:16 This generates a static initializer (Bad thing). A
+ "#include \"base/trace_event/append_only_proto_message.h\"\n";
+const string OUT_MESSAGE_CLASS =
+ "::base::trace_event::AppendOnlyProtoMessage";
+
+
+class GeneratorJob {
+ public:
+ GeneratorJob(const FileDescriptor* file, io::Printer* printer)
+ : file_(file), printer_(printer) {}
+
+ void Run() {
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 Hmm Run makes it feel this is like part of some th
+ PrepareNamespace();
+ PrepareIncludeGuard();
+ PrepareMessages();
+
+ PrintBoilerplate();
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 I'd s/Print/Generate/ in these functions.
+ for (const Descriptor* message : messages_) {
+ PrintMessage(message);
+ }
+ PrintEpilog();
+ }
+
+ private:
+ // Split string by dots.
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 Looks like this is reinventing base/strings/string
+ vector<string> StringTokens(const string& str) {
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 std::string. I think we disallow "using namespace
+ vector<string> tokens;
+ size_t left = 0;
+ while (left < str.size()) {
+ size_t right = std::min(str.find('.', left), str.size());
+ tokens.push_back(str.substr(left, right));
+ left = right + 1;
+ }
+ return tokens;
+ }
+
+ // Seal generated classes into namespace corresponding to package name.
+ void PrepareNamespace() {
+ package_ = file_->package();
+ namespaces_ = StringTokens(package_);
+ absolute_namespace_ = "::";
+ for (const string ns : namespaces_) {
Primiano Tucci (use gerrit) 2016/07/05 11:30:18 missing & (const string&), this one is unnecessari
+ absolute_namespace_ += ns + "::";
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 this will make the abs_namespace end with "::". Do
+ }
+ }
+
+ // Unique define to guard a header.
+ void PrepareIncludeGuard() {
+ include_guard_ = package_ + "_" + file_->name() + "_H_";
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 Why this method pre-computing the include guard? L
+ UpperString(&include_guard_);
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 Use ToUpperASCII from base/strings
+ StripString(&include_guard_, ".-", '_');
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 ditto
+ }
+
+ // Collect all messages in DFS order.
+ // TODO(kraynov) Try topological sort to eliminate forward declarations.
+ void PrepareMessages() {
+ vector<const Descriptor*> stack;
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ stack.push_back(file_->message_type(i));
+ }
+ while (stack.size() > 0) {
Primiano Tucci (use gerrit) 2016/07/05 11:30:16 s/.size() > 0/! ... .empty())
+ const Descriptor* message = stack.back();
+ stack.pop_back();
+ messages_.push_back(message);
+ for (int i = 0; i < message->nested_type_count(); ++i) {
+ stack.push_back(message->nested_type(i));
+ }
+ }
+ }
+
+ // Get C++ class name corresponding to message descriptor.
+ // Nested names are splitted by underscores.
+ string GetCppClassName(const Descriptor* message) {
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 this seems to be a static function
+ string class_name = StripPrefixString(message->full_name(), package_ + ".");
+ StripString(&class_name, ".-", '_');
+ return class_name;
+ }
+
+ void PrintBoilerplate() {
Primiano Tucci (use gerrit) 2016/07/05 11:30:16 I think this should be called: GeneratePrologue()
+ printer_->Print(
+ "// Autogenerated. DO NOT EDIT.\n"
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 maybe say: autogenerated by //components/tracing/t
+ "#ifndef $guard$\n"
+ "#define $guard$\n\n"
+ "$includes$\n",
+
+ "includes", OUT_INCLUDES,
+ "guard", include_guard_);
+
+ // Print namespaces
+ for (string ns : namespaces_) {
+ printer_->Print("namespace $ns$ {\n", "ns", ns);
+ }
+ printer_->Print("\n");
+ // Print forward declarations
+ for (const Descriptor* message : messages_) {
+ printer_->Print(
+ "class $class$;\n",
+ "class", GetCppClassName(message));
+ }
+ printer_->Print("\n");
+ }
+
+ void PrintSimpleField(const FieldDescriptor* field) {
+ string type;
+ string appender;
+
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_DOUBLE:
+ type = "double";
+ appender = "AppendDouble";
+ break;
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 also TYPE_FLOAT
+ case FieldDescriptor::TYPE_INT64:
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 I think this is SINT64. It seems proto supports in
+ type = "int64_t";
+ appender = "AppendVarIntSigned";
+ break;
+ case FieldDescriptor::TYPE_BOOL:
+ type = "bool";
+ appender = "AppendVarIntUnsigned";
+ break;
+ case FieldDescriptor::TYPE_STRING:
+ type = "const char*";
+ appender = "AppendString";
+ break;
+ default:
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 Add TYPE_UINT32
+ // TODO(kraynov) Fail if not supported.
+ break;
+ }
+ printer_->Print(
+ "void set_$name$($type$ value) {\n"
+ " $appender$($number$, value);\n"
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 s/number/field_number
+ "}\n",
+
+ "type", type,
+ "name", field->name(),
+ "appender", appender,
+ "number", std::to_string(field->number()));
+ }
+
+ void PrintNestedMessageField(const FieldDescriptor* field) {
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 For the moment let's leave this out and re-add onc
+ printer_->Print(
+ "$class$* add_$name$() {\n"
+ " $class$* inst = new $class$(buffer(), this);\n"
+ " BeginNestedMessage($number$, std::unique_ptr<$base$>(inst));\n"
+ " return inst;\n"
+ "}\n",
+
+ "class", absolute_namespace_ + GetCppClassName(field->message_type()),
+ "name", field->name(),
+ "number", std::to_string(field->number()),
+ "base", OUT_MESSAGE_CLASS);
+ }
+
+ void PrintFields(const Descriptor* message) {
Primiano Tucci (use gerrit) 2016/07/05 11:30:18 I'd s/message/descriptor/ here and elsewhere. In g
+ for (int i = 0; i < message->field_count(); ++i) {
+ if (message->field(i)->type() != FieldDescriptor::TYPE_MESSAGE) {
+ PrintSimpleField(message->field(i));
+ } else {
+ PrintNestedMessageField(message->field(i));
+ }
+ }
+ }
+
+ void PrintMessage(const Descriptor* message) {
+ printer_->Print(
+ "class $class$ : public $base$ {\n",
+
+ "class", GetCppClassName(message),
+ "base", OUT_MESSAGE_CLASS);
+
+ printer_->Indent();
+ PrintFields(message);
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 Legibility: hmm maybe PrintFields should just be i
+ printer_->Outdent();
+ printer_->Print("};\n\n");
+ }
+
+ void PrintEpilog() {
Primiano Tucci (use gerrit) 2016/07/05 11:30:18 s/Epilog/Epilogue/
+ for (auto it = namespaces_.rbegin(); it != namespaces_.rend(); ++it) {
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 for (const std::string& ns : namespaces_)
+ printer_->Print("} // namespace $ns$\n", "ns", *it);
+ }
+ printer_->Print(""
+ "#endif // $guard$\n",
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 yeah don't worry about this (the guard name in the
+ "guard", include_guard_);
+ }
+
+ const FileDescriptor* file_;
Primiano Tucci (use gerrit) 2016/07/05 11:30:17 I'd s/file_/descriptor_/. file_. suggests it's a u
+ io::Printer* printer_;
+
+ string package_;
+ string include_guard_;
+ vector<string> namespaces_;
+ string absolute_namespace_;
+ vector<const Descriptor*> messages_;
+};
+
+} // namespace
+
+bool Generator::Generate(const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* context,
+ string* error) const {
+
+ using google::protobuf::scoped_ptr;
+
+ string stub_name = StripSuffixString(file->name(), ".proto") + ".zeropb";
+
+ scoped_ptr<io::ZeroCopyOutputStream> pb_h(context->Open(stub_name + ".h"));
+ io::Printer pb_h_printer(pb_h.get(), '$'); // $ used as variable delimiter.
+ GeneratorJob job(file, &pb_h_printer);
+ job.Run();
+
+ scoped_ptr<io::ZeroCopyOutputStream> pb_cc(context->Open(stub_name + ".cc"));
+ io::Printer pb_cc_printer(pb_cc.get(), '$');
+ pb_cc_printer.Print("// This file intentionally left blank.\n");
+
+ return true;
+}
+
+} // namespace fastcpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google

Powered by Google App Engine
This is Rietveld 408576698