1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "codegen/cpp_interface_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)15 bool CppInterfaceCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
16 {
17 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
18 directory_ = GetFileParentPath(targetDirectory);
19 } else {
20 return false;
21 }
22
23 if (!File::CreateParentDir(directory_)) {
24 Logger::E("CppInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
25 return false;
26 }
27
28 return true;
29 }
30
EmitCode()31 void CppInterfaceCodeEmitter::EmitCode()
32 {
33 switch (mode_) {
34 case GenMode::PASSTHROUGH:
35 case GenMode::IPC: {
36 EmitInterfaceHeaderFile();
37 break;
38 }
39 default:
40 break;
41 }
42 }
43
EmitInterfaceHeaderFile()44 void CppInterfaceCodeEmitter::EmitInterfaceHeaderFile()
45 {
46 std::string filePath =
47 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
48 File file(filePath, File::WRITE);
49 StringBuilder sb;
50
51 EmitLicense(sb);
52 EmitHeadMacro(sb, interfaceFullName_);
53 sb.Append("\n");
54 EmitInterfaceInclusions(sb);
55 if (!Options::GetInstance().DoPassthrough()) {
56 sb.Append("\n");
57 EmitInterfaceBuffSizeMacro(sb);
58 }
59 sb.Append("\n");
60 EmitBeginNamespace(sb);
61 EmitUsingNamespace(sb);
62 if (!Options::GetInstance().DoPassthrough()) {
63 sb.Append("\n");
64 if (interface_->GetExtendsInterface() == nullptr) {
65 EmitInterfaceMethodCommands(sb, "");
66 } else {
67 EmitInterfaceMethodCommandsWithExtends(sb, "");
68 }
69 }
70 sb.Append("\n");
71 EmitInterfaceDefinition(sb);
72 EmitEndNamespace(sb);
73 sb.Append("\n");
74 EmitTailMacro(sb, interfaceFullName_);
75
76 std::string data = sb.ToString();
77 file.WriteData(data.c_str(), data.size());
78 file.Flush();
79 file.Close();
80 }
81
EmitInterfaceInclusions(StringBuilder & sb)82 void CppInterfaceCodeEmitter::EmitInterfaceInclusions(StringBuilder &sb)
83 {
84 HeaderFile::HeaderFileSet headerFiles;
85
86 GetStdlibInclusions(headerFiles);
87 GetImportInclusions(headerFiles);
88 GetHeaderOtherLibInclusions(headerFiles);
89
90 for (const auto &file : headerFiles) {
91 sb.AppendFormat("%s\n", file.ToString().c_str());
92 }
93 }
94
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const95 void CppInterfaceCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
96 {
97 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
98 headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
99 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_base");
100 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
101 }
102
EmitInterfaceVersionMacro(StringBuilder & sb) const103 void CppInterfaceCodeEmitter::EmitInterfaceVersionMacro(StringBuilder &sb) const
104 {
105 sb.AppendFormat("#define %s %u\n", majorVerName_.c_str(), ast_->GetMajorVer());
106 sb.AppendFormat("#define %s %u\n", minorVerName_.c_str(), ast_->GetMinorVer());
107 }
108
EmitInterfaceDefinition(StringBuilder & sb)109 void CppInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder &sb)
110 {
111 AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
112 if (interface != nullptr) {
113 sb.AppendFormat("class %s : public %s {\n", interfaceName_.c_str(),
114 EmitDefinitionByInterface(interface, interfaceName_).c_str());
115 } else {
116 sb.AppendFormat("class %s : public HdiBase {\n", interfaceName_.c_str());
117 }
118 sb.Append("public:\n");
119 EmitInterfaceDescriptor(sb, TAB);
120 sb.Append("\n");
121 EmitInterfaceDestruction(sb, TAB);
122 sb.Append("\n");
123 if (!interface_->IsSerializable()) {
124 EmitGetMethodDecl(sb, TAB);
125 sb.Append("\n");
126 }
127 if (interface_->GetExtendsInterface() != nullptr) {
128 EmitCastFromDecl(sb, TAB);
129 sb.Append("\n");
130 }
131 EmitInterfaceMethodsDecl(sb, TAB);
132 sb.Append("\n");
133 EmitGetDescMethod(sb, TAB);
134 sb.Append("};\n");
135 }
136
EmitGetDescMethod(StringBuilder & sb,const std::string & prefix) const137 void CppInterfaceCodeEmitter::EmitGetDescMethod(StringBuilder &sb, const std::string &prefix) const
138 {
139 AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
140 if (interface == nullptr) {
141 sb.Append(prefix).Append("virtual const std::u16string GetDesc()");
142 } else {
143 sb.Append(prefix).Append("const std::u16string GetDesc() override");
144 }
145 sb.Append("\n");
146 sb.Append(prefix).Append("{").Append("\n");
147 sb.Append(prefix + TAB).Append("return metaDescriptor_;\n");
148 sb.Append(prefix).Append("}\n");
149 }
150
EmitInterfaceDescriptor(StringBuilder & sb,const std::string & prefix) const151 void CppInterfaceCodeEmitter::EmitInterfaceDescriptor(StringBuilder &sb, const std::string &prefix) const
152 {
153 (void)prefix;
154 sb.Append(TAB).AppendFormat("DECLARE_HDI_DESCRIPTOR(u\"%s\");\n", interfaceFullName_.c_str());
155 }
156
EmitCastFromDecl(StringBuilder & sb,const std::string & prefix) const157 void CppInterfaceCodeEmitter::EmitCastFromDecl(StringBuilder &sb, const std::string &prefix) const
158 {
159 std::string currentInterface = EmitDefinitionByInterface(interface_, interfaceName_);
160
161 AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
162 while (interface != nullptr) {
163 std::string parentInterface = EmitDefinitionByInterface(interface, interfaceName_);
164 sb.Append(prefix).AppendFormat("static sptr<%s> CastFrom(const sptr<%s> &parent);\n",
165 currentInterface.c_str(), parentInterface.c_str());
166 interface = interface->GetExtendsInterface();
167 }
168 }
169
EmitGetMethodDecl(StringBuilder & sb,const std::string & prefix) const170 void CppInterfaceCodeEmitter::EmitGetMethodDecl(StringBuilder &sb, const std::string &prefix) const
171 {
172 sb.Append(prefix).AppendFormat("static %s Get(bool isStub = false);\n", interface_->EmitCppType().c_str());
173 sb.Append(prefix).AppendFormat(
174 "static %s Get(const std::string &serviceName, bool isStub = false);\n", interface_->EmitCppType().c_str());
175 }
176
EmitInterfaceDestruction(StringBuilder & sb,const std::string & prefix) const177 void CppInterfaceCodeEmitter::EmitInterfaceDestruction(StringBuilder &sb, const std::string &prefix) const
178 {
179 sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", interface_->GetName().c_str());
180 }
181
EmitInterfaceMethodsDecl(StringBuilder & sb,const std::string & prefix)182 void CppInterfaceCodeEmitter::EmitInterfaceMethodsDecl(StringBuilder &sb, const std::string &prefix)
183 {
184 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
185 EmitInterfaceMethodDecl(method, sb, prefix);
186 sb.Append("\n");
187 }
188
189 EmitInterfaceGetVersionMethod(sb, prefix);
190 if (interface_->GetExtendsInterface() == nullptr) {
191 sb.Append("\n");
192 EmitInterfaceIsProxyMethod(sb, prefix);
193 }
194 }
195
EmitInterfaceMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const196 void CppInterfaceCodeEmitter::EmitInterfaceMethodDecl(
197 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
198 {
199 if (interface_->GetExtendsInterface() != nullptr && method->IsOverload()) {
200 sb.Append(prefix).AppendFormat("using %s::%s;\n",
201 EmitDefinitionByInterface(interface_->GetExtendsInterface(), interfaceName_).c_str(),
202 method->GetName().c_str());
203 }
204
205 if (method->GetParameterNumber() == 0) {
206 sb.Append(prefix).AppendFormat("virtual int32_t %s() = 0;\n", method->GetName().c_str());
207 } else {
208 StringBuilder paramStr;
209 paramStr.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().c_str());
210 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
211 AutoPtr<ASTParameter> param = method->GetParameter(i);
212 EmitInterfaceMethodParameter(param, paramStr, "");
213 if (i + 1 < method->GetParameterNumber()) {
214 paramStr.Append(", ");
215 }
216 }
217
218 paramStr.Append(") = 0;");
219 sb.Append(SpecificationParam(paramStr, prefix + TAB));
220 sb.Append("\n");
221 }
222 }
223
EmitInterfaceGetVersionMethod(StringBuilder & sb,const std::string & prefix) const224 void CppInterfaceCodeEmitter::EmitInterfaceGetVersionMethod(StringBuilder &sb, const std::string &prefix) const
225 {
226 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
227 if (interface_->GetExtendsInterface() == nullptr) {
228 sb.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().c_str());
229 } else {
230 sb.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
231 }
232 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
233 AutoPtr<ASTParameter> param = method->GetParameter(i);
234 EmitInterfaceMethodParameter(param, sb, "");
235 if (i + 1 < method->GetParameterNumber()) {
236 sb.Append(", ");
237 }
238 }
239 sb.Append(")");
240 if (interface_->GetExtendsInterface() != nullptr) {
241 sb.Append(" override");
242 }
243 sb.Append("\n");
244 sb.Append(prefix).Append("{\n");
245
246 AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
247 sb.Append(prefix + TAB).AppendFormat("%s = %d;\n", majorParam->GetName().c_str(), ast_->GetMajorVer());
248 AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
249 sb.Append(prefix + TAB).AppendFormat("%s = %d;\n", minorParam->GetName().c_str(), ast_->GetMinorVer());
250
251 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
252 sb.Append(prefix).Append("}\n");
253 }
254
EmitInterfaceIsProxyMethod(StringBuilder & sb,const std::string & prefix) const255 void CppInterfaceCodeEmitter::EmitInterfaceIsProxyMethod(StringBuilder &sb, const std::string &prefix) const
256 {
257 sb.Append(prefix).AppendFormat("virtual bool %s(", "IsProxy");
258 sb.Append(")\n");
259 sb.Append(prefix).Append("{\n");
260 sb.Append(prefix + TAB).Append("return false;\n");
261 sb.Append(prefix).Append("}\n");
262 }
263
EmitInterfaceMethodParameter(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix) const264 void CppInterfaceCodeEmitter::EmitInterfaceMethodParameter(
265 const AutoPtr<ASTParameter> ¶m, StringBuilder &sb, const std::string &prefix) const
266 {
267 sb.Append(prefix).Append(param->EmitCppParameter());
268 }
269
EmitInterfaceMethodCommandsWithExtends(StringBuilder & sb,const std::string & prefix)270 void CppInterfaceCodeEmitter::EmitInterfaceMethodCommandsWithExtends(StringBuilder &sb, const std::string &prefix)
271 {
272 size_t extendMethods = 0;
273 AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
274 while (interface != nullptr) {
275 extendMethods += interface->GetMethodNumber();
276 interface = interface->GetExtendsInterface();
277 }
278
279 sb.Append(prefix).AppendFormat("enum {\n");
280 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
281 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
282 sb.Append(prefix + TAB)
283 .Append(EmitMethodCmdID(method))
284 .AppendFormat(" = %d", extendMethods + i + 1)
285 .Append(",\n");
286 }
287 sb.Append(prefix).Append("};\n");
288 }
289 } // namespace HDI
290 } // namespace OHOS