• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &param, 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