Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "proto_zero_generator.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <algorithm> | |
| 9 | |
| 10 #include <google/protobuf/descriptor.h> | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
make these absolute includes
https://google.githu
| |
| 11 #include <google/protobuf/io/printer.h> | |
| 12 #include <google/protobuf/io/zero_copy_stream.h> | |
| 13 #include <google/protobuf/stubs/strutil.h> | |
| 14 | |
| 15 namespace google { | |
| 16 namespace protobuf { | |
| 17 namespace compiler { | |
| 18 namespace fastcpp { | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 // 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.
| |
| 23 const string OUT_INCLUDES = | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:16
This generates a static initializer (Bad thing).
A
| |
| 24 "#include \"base/trace_event/append_only_proto_message.h\"\n"; | |
| 25 const string OUT_MESSAGE_CLASS = | |
| 26 "::base::trace_event::AppendOnlyProtoMessage"; | |
| 27 | |
| 28 | |
| 29 class GeneratorJob { | |
| 30 public: | |
| 31 GeneratorJob(const FileDescriptor* file, io::Printer* printer) | |
| 32 : file_(file), printer_(printer) {} | |
| 33 | |
| 34 void Run() { | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
Hmm Run makes it feel this is like part of some th
| |
| 35 PrepareNamespace(); | |
| 36 PrepareIncludeGuard(); | |
| 37 PrepareMessages(); | |
| 38 | |
| 39 PrintBoilerplate(); | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
I'd s/Print/Generate/ in these functions.
| |
| 40 for (const Descriptor* message : messages_) { | |
| 41 PrintMessage(message); | |
| 42 } | |
| 43 PrintEpilog(); | |
| 44 } | |
| 45 | |
| 46 private: | |
| 47 // Split string by dots. | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
Looks like this is reinventing base/strings/string
| |
| 48 vector<string> StringTokens(const string& str) { | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
std::string. I think we disallow "using namespace
| |
| 49 vector<string> tokens; | |
| 50 size_t left = 0; | |
| 51 while (left < str.size()) { | |
| 52 size_t right = std::min(str.find('.', left), str.size()); | |
| 53 tokens.push_back(str.substr(left, right)); | |
| 54 left = right + 1; | |
| 55 } | |
| 56 return tokens; | |
| 57 } | |
| 58 | |
| 59 // Seal generated classes into namespace corresponding to package name. | |
| 60 void PrepareNamespace() { | |
| 61 package_ = file_->package(); | |
| 62 namespaces_ = StringTokens(package_); | |
| 63 absolute_namespace_ = "::"; | |
| 64 for (const string ns : namespaces_) { | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:18
missing & (const string&), this one is unnecessari
| |
| 65 absolute_namespace_ += ns + "::"; | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
this will make the abs_namespace end with "::". Do
| |
| 66 } | |
| 67 } | |
| 68 | |
| 69 // Unique define to guard a header. | |
| 70 void PrepareIncludeGuard() { | |
| 71 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
| |
| 72 UpperString(&include_guard_); | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
Use ToUpperASCII from base/strings
| |
| 73 StripString(&include_guard_, ".-", '_'); | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
ditto
| |
| 74 } | |
| 75 | |
| 76 // Collect all messages in DFS order. | |
| 77 // TODO(kraynov) Try topological sort to eliminate forward declarations. | |
| 78 void PrepareMessages() { | |
| 79 vector<const Descriptor*> stack; | |
| 80 for (int i = 0; i < file_->message_type_count(); ++i) { | |
| 81 stack.push_back(file_->message_type(i)); | |
| 82 } | |
| 83 while (stack.size() > 0) { | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:16
s/.size() > 0/! ... .empty())
| |
| 84 const Descriptor* message = stack.back(); | |
| 85 stack.pop_back(); | |
| 86 messages_.push_back(message); | |
| 87 for (int i = 0; i < message->nested_type_count(); ++i) { | |
| 88 stack.push_back(message->nested_type(i)); | |
| 89 } | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 // Get C++ class name corresponding to message descriptor. | |
| 94 // Nested names are splitted by underscores. | |
| 95 string GetCppClassName(const Descriptor* message) { | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
this seems to be a static function
| |
| 96 string class_name = StripPrefixString(message->full_name(), package_ + "."); | |
| 97 StripString(&class_name, ".-", '_'); | |
| 98 return class_name; | |
| 99 } | |
| 100 | |
| 101 void PrintBoilerplate() { | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:16
I think this should be called:
GeneratePrologue()
| |
| 102 printer_->Print( | |
| 103 "// Autogenerated. DO NOT EDIT.\n" | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
maybe say: autogenerated by //components/tracing/t
| |
| 104 "#ifndef $guard$\n" | |
| 105 "#define $guard$\n\n" | |
| 106 "$includes$\n", | |
| 107 | |
| 108 "includes", OUT_INCLUDES, | |
| 109 "guard", include_guard_); | |
| 110 | |
| 111 // Print namespaces | |
| 112 for (string ns : namespaces_) { | |
| 113 printer_->Print("namespace $ns$ {\n", "ns", ns); | |
| 114 } | |
| 115 printer_->Print("\n"); | |
| 116 // Print forward declarations | |
| 117 for (const Descriptor* message : messages_) { | |
| 118 printer_->Print( | |
| 119 "class $class$;\n", | |
| 120 "class", GetCppClassName(message)); | |
| 121 } | |
| 122 printer_->Print("\n"); | |
| 123 } | |
| 124 | |
| 125 void PrintSimpleField(const FieldDescriptor* field) { | |
| 126 string type; | |
| 127 string appender; | |
| 128 | |
| 129 switch (field->type()) { | |
| 130 case FieldDescriptor::TYPE_DOUBLE: | |
| 131 type = "double"; | |
| 132 appender = "AppendDouble"; | |
| 133 break; | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
also TYPE_FLOAT
| |
| 134 case FieldDescriptor::TYPE_INT64: | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
I think this is SINT64.
It seems proto supports in
| |
| 135 type = "int64_t"; | |
| 136 appender = "AppendVarIntSigned"; | |
| 137 break; | |
| 138 case FieldDescriptor::TYPE_BOOL: | |
| 139 type = "bool"; | |
| 140 appender = "AppendVarIntUnsigned"; | |
| 141 break; | |
| 142 case FieldDescriptor::TYPE_STRING: | |
| 143 type = "const char*"; | |
| 144 appender = "AppendString"; | |
| 145 break; | |
| 146 default: | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
Add TYPE_UINT32
| |
| 147 // TODO(kraynov) Fail if not supported. | |
| 148 break; | |
| 149 } | |
| 150 printer_->Print( | |
| 151 "void set_$name$($type$ value) {\n" | |
| 152 " $appender$($number$, value);\n" | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
s/number/field_number
| |
| 153 "}\n", | |
| 154 | |
| 155 "type", type, | |
| 156 "name", field->name(), | |
| 157 "appender", appender, | |
| 158 "number", std::to_string(field->number())); | |
| 159 } | |
| 160 | |
| 161 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
| |
| 162 printer_->Print( | |
| 163 "$class$* add_$name$() {\n" | |
| 164 " $class$* inst = new $class$(buffer(), this);\n" | |
| 165 " BeginNestedMessage($number$, std::unique_ptr<$base$>(inst));\n" | |
| 166 " return inst;\n" | |
| 167 "}\n", | |
| 168 | |
| 169 "class", absolute_namespace_ + GetCppClassName(field->message_type()), | |
| 170 "name", field->name(), | |
| 171 "number", std::to_string(field->number()), | |
| 172 "base", OUT_MESSAGE_CLASS); | |
| 173 } | |
| 174 | |
| 175 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
| |
| 176 for (int i = 0; i < message->field_count(); ++i) { | |
| 177 if (message->field(i)->type() != FieldDescriptor::TYPE_MESSAGE) { | |
| 178 PrintSimpleField(message->field(i)); | |
| 179 } else { | |
| 180 PrintNestedMessageField(message->field(i)); | |
| 181 } | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 void PrintMessage(const Descriptor* message) { | |
| 186 printer_->Print( | |
| 187 "class $class$ : public $base$ {\n", | |
| 188 | |
| 189 "class", GetCppClassName(message), | |
| 190 "base", OUT_MESSAGE_CLASS); | |
| 191 | |
| 192 printer_->Indent(); | |
| 193 PrintFields(message); | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
Legibility: hmm maybe PrintFields should just be i
| |
| 194 printer_->Outdent(); | |
| 195 printer_->Print("};\n\n"); | |
| 196 } | |
| 197 | |
| 198 void PrintEpilog() { | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:18
s/Epilog/Epilogue/
| |
| 199 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_)
| |
| 200 printer_->Print("} // namespace $ns$\n", "ns", *it); | |
| 201 } | |
| 202 printer_->Print("" | |
| 203 "#endif // $guard$\n", | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
yeah don't worry about this (the guard name in the
| |
| 204 "guard", include_guard_); | |
| 205 } | |
| 206 | |
| 207 const FileDescriptor* file_; | |
|
Primiano Tucci (use gerrit)
2016/07/05 11:30:17
I'd s/file_/descriptor_/.
file_. suggests it's a u
| |
| 208 io::Printer* printer_; | |
| 209 | |
| 210 string package_; | |
| 211 string include_guard_; | |
| 212 vector<string> namespaces_; | |
| 213 string absolute_namespace_; | |
| 214 vector<const Descriptor*> messages_; | |
| 215 }; | |
| 216 | |
| 217 } // namespace | |
| 218 | |
| 219 bool Generator::Generate(const FileDescriptor* file, | |
| 220 const string& parameter, | |
| 221 GeneratorContext* context, | |
| 222 string* error) const { | |
| 223 | |
| 224 using google::protobuf::scoped_ptr; | |
| 225 | |
| 226 string stub_name = StripSuffixString(file->name(), ".proto") + ".zeropb"; | |
| 227 | |
| 228 scoped_ptr<io::ZeroCopyOutputStream> pb_h(context->Open(stub_name + ".h")); | |
| 229 io::Printer pb_h_printer(pb_h.get(), '$'); // $ used as variable delimiter. | |
| 230 GeneratorJob job(file, &pb_h_printer); | |
| 231 job.Run(); | |
| 232 | |
| 233 scoped_ptr<io::ZeroCopyOutputStream> pb_cc(context->Open(stub_name + ".cc")); | |
| 234 io::Printer pb_cc_printer(pb_cc.get(), '$'); | |
| 235 pb_cc_printer.Print("// This file intentionally left blank.\n"); | |
| 236 | |
| 237 return true; | |
| 238 } | |
| 239 | |
| 240 } // namespace fastcpp | |
| 241 } // namespace compiler | |
| 242 } // namespace protobuf | |
| 243 } // namespace google | |
| OLD | NEW |