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 #ifndef PROTO_READER_PLUGIN_H
16 #define PROTO_READER_PLUGIN_H
17 #include <string>
18 #include <google/protobuf/compiler/code_generator.h>
19 #include <google/protobuf/compiler/plugin.h>
20 #include <google/protobuf/descriptor.h>
21 #include <google/protobuf/descriptor.pb.h>
22 #include <google/protobuf/io/printer.h>
23 #include <google/protobuf/io/zero_copy_stream.h>
24
25 namespace SysTuning {
26 namespace ProtoReader {
27 using google::protobuf::Descriptor;
28 using google::protobuf::EnumDescriptor;
29 using google::protobuf::FieldDescriptor;
30 using google::protobuf::FileDescriptor;
31 using google::protobuf::compiler::GeneratorContext;
32 using google::protobuf::io::Printer;
33 using google::protobuf::io::ZeroCopyOutputStream;
34
Uppercase(char c)35 inline char Uppercase(char c)
36 {
37 return ('a' <= c && c <= 'z') ? static_cast<char>(c + ('A' - 'a')) : c;
38 }
39
ToUppercase(const std::string & str)40 inline std::string ToUppercase(const std::string &str)
41 {
42 std::string string(str);
43 auto end = string.end();
44 for (auto c = string.begin(); c != end; ++c) {
45 *c = Uppercase(*c);
46 }
47 return string;
48 }
49
50 class ProtoReaderGenerator {
51 public:
ProtoReaderGenerator(const FileDescriptor * file,Printer * printer)52 ProtoReaderGenerator(const FileDescriptor *file, Printer *printer) : fileDescriptor_(file), codePrinter_(printer) {}
53 bool WriteProtoReader();
54 void ParserNamespace();
55 void ParserDescriptors();
56 void ParserDependencies();
57 void GetPBReaderInfo();
58 void WriteBegin();
59 void WriteEnumDescriptor(const EnumDescriptor *enumeration);
60 void WriteDecoder(const Descriptor *descriptor);
61 void WriteEnum(const Descriptor *descriptor);
62 void WriteFunc(const Descriptor *descriptor, const int32_t maxFieldID);
63 void WriteEnd();
GetError()64 const std::string &GetError() const
65 {
66 return error_;
67 }
68
69 public:
70 std::string wrapperNamespace_;
71
72 private:
73 template <class T>
GetDescriptorName(const T * descriptor)74 inline std::string GetDescriptorName(const T *descriptor) const
75 {
76 if (!package_.empty()) {
77 auto strTmp = package_ + ".";
78 return descriptor->full_name().substr(descriptor->full_name().find(strTmp) + sizeof(strTmp));
79 } else {
80 return descriptor->full_name();
81 }
82 }
83 template <class T>
GetDescriptorClass(const T * descriptor)84 const std::string GetDescriptorClass(const T *descriptor)
85 {
86 std::string name = GetDescriptorName(descriptor);
87 size_t pos = name.find(".");
88 if (pos != std::string::npos) {
89 name = name.replace(name.find("."), 1, "_");
90 }
91 return name;
92 }
93 std::string GetFieldNumberConstant(const FieldDescriptor *field);
94
95 private:
96 struct TypeDesc {
97 std::string toFunc;
98 std::string type;
99 std::string packedBufferType;
100 };
101 std::map<FieldDescriptor::Type, TypeDesc> fieldTypeDesc_ = {
102 {FieldDescriptor::TYPE_BOOL, {"ToBool", "bool", "kVarInt"}},
103 {FieldDescriptor::TYPE_SFIXED32, {"ToInt32", "int32_t", "kFixed32"}},
104 {FieldDescriptor::TYPE_SINT32, {"ToInt32", "int32_t", "kVarInt"}},
105 {FieldDescriptor::TYPE_INT32, {"ToInt32", "int32_t", "kVarInt"}},
106 {FieldDescriptor::TYPE_SFIXED64, {"ToInt64", "int64_t", "kFixed64"}},
107 {FieldDescriptor::TYPE_SINT64, {"ToInt64", "int64_t", "kVarInt"}},
108 {FieldDescriptor::TYPE_INT64, {"ToInt64", "int64_t", "kVarInt"}},
109 {FieldDescriptor::TYPE_FIXED32, {"ToUint32", "uint32_t", "kFixed32"}},
110 {FieldDescriptor::TYPE_UINT32, {"ToUint32", "uint32_t", "kVarInt"}},
111 {FieldDescriptor::TYPE_FIXED64, {"ToUint64", "uint64_t", "kFixed64"}},
112 {FieldDescriptor::TYPE_UINT64, {"ToUint64", "uint64_t", "kVarInt"}},
113 {FieldDescriptor::TYPE_FLOAT, {"ToFloat", "float", "kFixed32"}},
114 {FieldDescriptor::TYPE_DOUBLE, {"ToDouble", "double", "kFixed64"}},
115 {FieldDescriptor::TYPE_ENUM, {"ToInt32", "int32_t", "kVarInt"}},
116 {FieldDescriptor::TYPE_STRING, {"ToString", "CharsView", ""}},
117 {FieldDescriptor::TYPE_MESSAGE, {"ToBytes", "BytesView", ""}},
118 {FieldDescriptor::TYPE_BYTES, {"ToBytes", "BytesView", ""}},
119 };
120 const FileDescriptor *const fileDescriptor_;
121 Printer *const codePrinter_;
122 std::string error_;
123 std::string fileDefinded_;
124 std::string package_;
125 std::vector<std::string> vNamespaces_;
126 std::string fullNamespacePrefix_;
127 std::vector<const Descriptor *> vDescriptor_;
128 std::vector<const EnumDescriptor *> vEnumDescriptor_;
129 std::set<const FileDescriptor *> publicImports_;
130 std::set<const Descriptor *> referencedMessages_;
131 std::set<const EnumDescriptor *> referencedEnums_;
132 };
133 class ProtoReaderPlugin : public ::google::protobuf::compiler::CodeGenerator {
134 public:
ProtoReaderPlugin()135 explicit ProtoReaderPlugin(){};
~ProtoReaderPlugin()136 ~ProtoReaderPlugin() override{};
137 bool Generate(const FileDescriptor *file,
138 const std::string &options,
139 GeneratorContext *context,
140 std::string *error) const override;
141 };
142 } // namespace ProtoReader
143 } // namespace SysTuning
144 #endif // PROTO_READER_PLUGIN_H
145