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