• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "proto_encoder_plugin_generator.h"
17 
18 using google::protobuf::FileDescriptor;
19 using google::protobuf::EnumDescriptor;
20 using google::protobuf::Descriptor;
21 using google::protobuf::io::Printer;
22 using google::protobuf::EnumValueDescriptor;
23 using google::protobuf::FieldDescriptor;
24 
25 class OptGeneratorImpl {
26 public:
OptGeneratorImpl(const FileDescriptor * file)27     explicit OptGeneratorImpl(const FileDescriptor* file) : fileContent_(file), printer_(nullptr) {}
28 
GetPrefix(const std::string & fileName)29     static std::string GetPrefix(const std::string& fileName)
30     {
31         std::string prefix = "";
32         for (size_t i = 0; i < fileName.length(); i++) {
33             if (fileName.c_str()[i] == '.') {
34                 break;
35             }
36             prefix += fileName.c_str()[i];
37         }
38         return prefix;
39     }
40 
SetNames(const std::string & fileName,const std::string & packageName)41     std::string SetNames(const std::string& fileName, const std::string& packageName)
42     {
43         fileName_ = fileName;
44         packageName_ = packageName + "::";
45         headFileName_ = "";
46 
47         for (size_t i = 0; i < fileName.length(); i++) {
48             if (fileName.c_str()[i] == '.') {
49                 break;
50             }
51             headFileName_ += fileName.c_str()[i];
52         }
53         baseName_ = SwapName(headFileName_);
54         return headFileName_;
55     }
56 
57     // Swap variable style. e.g: cpu_plugin_config to cpuPluginConfig
SwapName(const std::string & s)58     static std::string SwapName(const std::string& s)
59     {
60         std::string ret = "";
61         bool b = true;
62         for (size_t i = 0; i < s.length(); i++) {
63             char c = s[i];
64             if (c == '_') {
65                 b = true;
66             } else if (b && islower(c)) {
67                 ret += (c + 'A' - 'a');
68                 b = false;
69             } else {
70                 ret += c;
71             }
72         }
73         return ret;
74     }
75 
Tolowercase(const std::string & s)76     static std::string Tolowercase(const std::string& s)
77     {
78         std::string str = s;
79         std::transform(str.begin(), str.end(), str.begin(), [](const char& c) {
80             return std::tolower(c);
81         });
82         return str;
83     }
84 
GenHeader()85     void GenHeader()
86     {
87         GenPrefix();
88         GenerateEnum();
89         GenerateClass();
90         GenSurfix();
91     }
92 
GenPrefix()93     void GenPrefix()
94     {
95         printer_->Print("// Generated by protoencoder plugin.\n");
96         printer_->Print("#pragma once\n");
97         printer_->Print("#include \"base_message.h\"\n");
98 
99         for (int i = 0; i < fileContent_->dependency_count(); ++i) {
100             printer_->Print("#include \"@name@.pbencoder.h\"\n", "name",
101                             GetPrefix(fileContent_->dependency(i)->name()));
102         }
103 
104         printer_->Print("namespace OHOS {\n");
105         printer_->Print("namespace Developtools {\n");
106         printer_->Print("namespace Profiler {\n");
107         printer_->Print("namespace ProtoEncoder {\n");
108     }
109 
GenerateEnum()110     void GenerateEnum()
111     {
112         for (int i = 0; i < fileContent_->enum_type_count(); ++i) {
113             printer_->Print("enum @class@ : uint32_t {\n", "class", fileContent_->enum_type(i)->name());
114             printer_->Indent();
115 
116             for (int j = 0; j < fileContent_->enum_type(i)->value_count(); ++j) {
117                 const EnumValueDescriptor* value = fileContent_->enum_type(i)->value(j);
118                 const std::string value_name = value->name();
119                 printer_->Print("@name@ = @number@,\n", "name", value_name, "number",
120                                 std::to_string(value->number()));
121             }
122             printer_->Outdent();
123             printer_->Print("};\n");
124         }
125     }
126 
GenerateNestClass(const Descriptor * message)127     void GenerateNestClass(const Descriptor* message)
128     {
129         for (int i = 0; i < message->nested_type_count(); ++i) {
130             const Descriptor* nestmessage = message->nested_type(i);
131             GenerateNestClass(nestmessage);
132             printer_->Print(
133                 "class @name@ : public BaseMessage {\n"
134                 " public:\n",
135                 "name", nestmessage->name());
136             printer_->Indent();
137             printer_->Print("@name@() = default;\n", "name", nestmessage->name());
138             printer_->Print(
139                 "explicit @name@(RandomWriteCtx* writeCtx, MessagePool* messagePool = nullptr) : BaseMessage(writeCtx, messagePool) {}\n",
140                 "name", nestmessage->name());
141             GenerateFieldsID(nestmessage);
142             GenerateFunction(nestmessage);
143             printer_->Outdent();
144             printer_->Print("};\n\n");
145         }
146     }
147 
GenerateClass()148     void GenerateClass()
149     {
150         // forward declaration
151         for (int i = 0; i < fileContent_->message_type_count(); ++i) {
152             const Descriptor* message = fileContent_->message_type(i);
153             printer_->Print("class @name@;\n", "name", message->name());
154         }
155 
156         for (int i = 0; i < fileContent_->message_type_count(); ++i) {
157             const Descriptor* message = fileContent_->message_type(i);
158             GenerateNestClass(message);
159 
160             printer_->Print(
161                 "class @name@ : public BaseMessage {\n"
162                 " public:\n",
163                 "name", message->name());
164             printer_->Indent();
165             printer_->Print("@name@() = default;\n", "name", message->name());
166             printer_->Print(
167                 "explicit @name@(RandomWriteCtx* writeCtx, MessagePool* messagePool = nullptr) : BaseMessage(writeCtx, messagePool) {}\n",
168                 "name", message->name());
169             GenerateFieldsID(message);
170             GenerateFunction(message);
171             printer_->Outdent();
172             printer_->Print("};\n\n");
173         }
174     }
175 
GenerateFieldsID(const Descriptor * message)176     void GenerateFieldsID(const Descriptor* message)
177     {
178         for (int i = 0; i < message->field_count(); ++i) {
179             const FieldDescriptor* field = message->field(i);
180             printer_->Print("static const uint32_t FIELDID_@name@ = @id@;\n",
181                 "name", field->name(), "id", std::to_string(field->number()));
182         }
183     }
184 
GenerateFunction(const Descriptor * message)185     void GenerateFunction(const Descriptor* message)
186     {
187         // field->is_repeated()
188         for (int i = 0; i < message->field_count(); ++i) {
189             const FieldDescriptor* field = message->field(i);
190             if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
191                 printer_->Print("inline @typename@* @mora@_@name@()\n",
192                     "mora", field->is_repeated()?"add":"mutable",
193                     "typename", field->message_type()->name(),
194                     "name", Tolowercase(field->name()));
195                 printer_->Print("{\n");
196                 printer_->Indent();
197                 printer_->Print("return AddSubMessage<@typename@>(FIELDID_@name@);\n",
198                     "typename", field->message_type()->name(),
199                     "name", field->name());
200                 printer_->Outdent();
201                 printer_->Print("}\n");
202             } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
203                 printer_->Print("inline void set_@name@(const void* bytes, uint32_t size)\n",
204                     "name", Tolowercase(field->name()));
205                 printer_->Print("{\n");
206                 printer_->Indent();
207                 printer_->Print("AddBytes(FIELDID_@name@, bytes, size);\n", "name", field->name());
208                 printer_->Outdent();
209                 printer_->Print("}\n");
210                 printer_->Print("void set_@name@(GetDataCallback getData)\n", "name", Tolowercase(field->name()));
211                 printer_->Print("{\n");
212                 printer_->Indent();
213                 printer_->Print("return AddBytesByCallBack(FIELDID_@name@, getData);\n", "name", field->name());
214                 printer_->Outdent();
215                 printer_->Print("}\n");
216                 printer_->Print("inline RandomWriteCtx* startAdd_@name@()\n", "name", Tolowercase(field->name()));
217                 printer_->Print("{\n");
218                 printer_->Indent();
219                 printer_->Print("return StartAddBytes(FIELDID_@name@);\n", "name", field->name());
220                 printer_->Outdent();
221                 printer_->Print("}\n");
222                 printer_->Print("inline void finishAdd_@name@(int32_t size)\n", "name", Tolowercase(field->name()));
223                 printer_->Print("{\n");
224                 printer_->Indent();
225                 printer_->Print("return FinishAddBytes(size);\n", "name", field->name());
226                 printer_->Outdent();
227                 printer_->Print("}\n");
228             } else if (field->type() == FieldDescriptor::TYPE_STRING) {
229                 printer_->Print("inline void @sora@_@name@(const std::string& str)\n",
230                     "sora", field->is_repeated()?"add":"set",
231                     "name", Tolowercase(field->name()));
232                 printer_->Print("{\n");
233                 printer_->Indent();
234                 printer_->Print("AddBytes(FIELDID_@name@, str.data(), str.size());\n", "name", field->name());
235                 printer_->Outdent();
236                 printer_->Print("}\n");
237                 printer_->Print("inline void @sora@_@name@(std::string&& str)\n",
238                     "sora", field->is_repeated()?"add":"set",
239                     "name", Tolowercase(field->name()));
240                 printer_->Print("{\n");
241                 printer_->Indent();
242                 printer_->Print("AddBytes(FIELDID_@name@, str.data(), str.size());\n", "name", field->name());
243                 printer_->Outdent();
244                 printer_->Print("}\n");
245                 printer_->Print("inline void @sora@_@name@(const char* str)\n",
246                     "sora", field->is_repeated()?"add":"set",
247                     "name", Tolowercase(field->name()));
248                 printer_->Print("{\n");
249                 printer_->Indent();
250                 printer_->Print("AddBytes(FIELDID_@name@, str, strlen(str));\n", "name", field->name());
251                 printer_->Outdent();
252                 printer_->Print("}\n");
253                 printer_->Print("inline void @sora@_@name@(const char* str, uint32_t len)\n",
254                     "sora", field->is_repeated()?"add":"set",
255                     "name", Tolowercase(field->name()));
256                 printer_->Print("{\n");
257                 printer_->Indent();
258                 printer_->Print("AddBytes(FIELDID_@name@, str, len);\n", "name", field->name());
259                 printer_->Outdent();
260                 printer_->Print("}\n");
261             } else {
262                 // varint, fix32, fix64
263                 printer_->Print("inline void @sora@_@name@(@paramtype@ v)\n",
264                     "sora", field->is_repeated()?"add":"set", "name", Tolowercase(field->name()),
265                     "paramtype", GetParamType(field));
266                 printer_->Print("{\n");
267                 printer_->Indent();
268                 printer_->Print("@type@(FIELDID_@name@, v);\n", "type",
269                     GetInnerType(field), "name", field->name());
270                 printer_->Outdent();
271                 printer_->Print("}\n");
272                 // packed
273                 if (!field->is_repeated()) {
274                     continue;
275                 }
276                 if (field->type() == FieldDescriptor::TYPE_SINT32 ||
277                     field->type() == FieldDescriptor::TYPE_SINT64) {
278                     perror("repeated signed(zigzag) fields are not supported in libprotobuf\n");
279                     continue;
280                 }
281                 if (!field->is_packed()) {
282                     continue;
283                 }
284                 printer_->Print("inline void add_@name@(const @paramtype@* array, uint32_t size)\n",
285                     "name", Tolowercase(field->name()),
286                     "paramtype", GetParamType(field));
287                 printer_->Print("{\n");
288                 printer_->Indent();
289                 printer_->Print("@type@(FIELDID_@name@, array, size);\n",
290                     "type", GetInnerType(field, true), "name", field->name());
291                 printer_->Outdent();
292                 printer_->Print("}\n");
293 
294                 printer_->Print("inline void add_@name@(const std::vector<@paramtype@>& array)\n",
295                     "name", Tolowercase(field->name()),
296                     "paramtype", GetParamType(field));
297                 printer_->Print("{\n");
298                 printer_->Indent();
299                 printer_->Print("@type@(FIELDID_@name@, array.data(), array.size());\n",
300                     "type", GetInnerType(field, true), "name", field->name());
301                 printer_->Outdent();
302                 printer_->Print("}\n");
303             }
304         }
305     }
306 
GetParamType(const FieldDescriptor * field)307     static std::string GetParamType(const FieldDescriptor* field)
308     {
309         switch (field->type()) {
310             case FieldDescriptor::TYPE_BOOL:
311                 return "bool";
312             case FieldDescriptor::TYPE_ENUM:
313             case FieldDescriptor::TYPE_UINT32:
314             case FieldDescriptor::TYPE_FIXED32:
315                 return "uint32_t";
316             case FieldDescriptor::TYPE_INT32:
317             case FieldDescriptor::TYPE_SINT32:
318             case FieldDescriptor::TYPE_SFIXED32:
319                 return "int32_t";
320             case FieldDescriptor::TYPE_INT64:
321             case FieldDescriptor::TYPE_SINT64:
322             case FieldDescriptor::TYPE_SFIXED64:
323                 return "int64_t";
324             case FieldDescriptor::TYPE_UINT64:
325             case FieldDescriptor::TYPE_FIXED64:
326                 return "uint64_t";
327             case FieldDescriptor::TYPE_DOUBLE:
328                 return "double";
329             case FieldDescriptor::TYPE_FLOAT:
330                 return "float";
331             case FieldDescriptor::TYPE_STRING:
332             case FieldDescriptor::TYPE_GROUP:
333             case FieldDescriptor::TYPE_MESSAGE:
334             case FieldDescriptor::TYPE_BYTES:
335                 return "";
336             default:
337                 return "";
338         }
339         return "";
340     }
341 
GetInnerType(const FieldDescriptor * field,bool packed=false)342     static std::string GetInnerType(const FieldDescriptor* field, bool packed = false)
343     {
344         switch (field->type()) {
345             case FieldDescriptor::TYPE_BOOL:
346             case FieldDescriptor::TYPE_ENUM:
347             case FieldDescriptor::TYPE_INT32:
348             case FieldDescriptor::TYPE_INT64:
349             case FieldDescriptor::TYPE_UINT32:
350             case FieldDescriptor::TYPE_UINT64:
351                 return packed ? "AddPackedVarint" : "AddVarint";
352             case FieldDescriptor::TYPE_SINT32:
353             case FieldDescriptor::TYPE_SINT64:
354                 return "AddZigZagVarint";
355             case FieldDescriptor::TYPE_FIXED64:
356             case FieldDescriptor::TYPE_SFIXED64:
357             case FieldDescriptor::TYPE_DOUBLE:
358                 return packed ? "AddPackedFixed" : "AddFixed64";
359             case FieldDescriptor::TYPE_FIXED32:
360             case FieldDescriptor::TYPE_SFIXED32:
361             case FieldDescriptor::TYPE_FLOAT:
362                 return packed ? "AddPackedFixed" : "AddFixed32";
363             case FieldDescriptor::TYPE_STRING:
364             case FieldDescriptor::TYPE_GROUP:
365             case FieldDescriptor::TYPE_MESSAGE:
366             case FieldDescriptor::TYPE_BYTES:
367                 return "";
368             default:
369                 return "";
370         }
371         return "";
372     }
373 
GenSurfix()374     void GenSurfix()
375     {
376         printer_->Print("} // namespace ProtoEncoder\n");
377         printer_->Print("} // namespace Profiler\n");
378         printer_->Print("} // namespace Developtools\n");
379         printer_->Print("} // namespace OHOS\n");
380     }
381 
SetPrinter(Printer * stub_h_printer)382     void SetPrinter(Printer* stub_h_printer)
383     {
384         printer_ = stub_h_printer;
385     }
386 private:
387     std::string fileName_ = "";
388     std::string baseName_ = "";
389     std::string packageName_ = "";
390     std::string headFileName_ = "";
391     std::vector<std::string> namespaces_;
392     const FileDescriptor* const fileContent_;
393     std::vector<const Descriptor*> stack_;
394     std::vector<const EnumDescriptor*> enums_;
395     Printer* printer_;
396 };
397 
ProtoEncoderGenerator()398 ProtoEncoderGenerator::ProtoEncoderGenerator() {}
399 
~ProtoEncoderGenerator()400 ProtoEncoderGenerator::~ProtoEncoderGenerator() {}
401 
Generate(const google::protobuf::FileDescriptor * file,const std::string & parameter,google::protobuf::compiler::GeneratorContext * context,std::string * error) const402 bool ProtoEncoderGenerator::Generate(const google::protobuf::FileDescriptor* file,
403                                      const std::string& parameter,
404                                      google::protobuf::compiler::GeneratorContext* context,
405                                      std::string* error) const
406 {
407     auto pcsp = std::make_shared<OptGeneratorImpl>(file);
408     std::string baseName = pcsp->SetNames(file->name(), file->package());
409     std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> headerOutput(context->Open(baseName +
410                                                                                               ".pbencoder.h"));
411     std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> sourceOutput(context->Open(baseName +
412                                                                                               ".pbencoder.cc"));
413     Printer hPrinter(headerOutput.get(), '@');
414     pcsp->SetPrinter(&hPrinter);
415     pcsp->GenHeader();
416 
417     Printer ccPrinter(sourceOutput.get(), '@');
418     ccPrinter.Print("// empty\n");
419     return true;
420 }
421