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 EmitInterfaceHeaderFile();
34 }
35
EmitInterfaceHeaderFile()36 void CppInterfaceCodeEmitter::EmitInterfaceHeaderFile()
37 {
38 std::string filePath =
39 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
40 File file(filePath, File::WRITE);
41 StringBuilder sb;
42
43 EmitLicense(sb);
44 EmitHeadMacro(sb, interfaceFullName_);
45 sb.Append("\n");
46 EmitInterfaceInclusions(sb);
47 sb.Append("\n");
48 EmitInterfaceVersionMacro(sb);
49 if (!Options::GetInstance().DoPassthrough()) {
50 sb.Append("\n");
51 EmitInterfaceBuffSizeMacro(sb);
52 }
53 sb.Append("\n");
54 EmitBeginNamespace(sb);
55 EmitUsingNamespace(sb);
56 if (!Options::GetInstance().DoPassthrough()) {
57 sb.Append("\n");
58 EmitInterfaceMethodCommands(sb, "");
59 }
60 sb.Append("\n");
61 EmitInterfaceDefinition(sb);
62 EmitEndNamespace(sb);
63 sb.Append("\n");
64 EmitTailMacro(sb, interfaceFullName_);
65
66 std::string data = sb.ToString();
67 file.WriteData(data.c_str(), data.size());
68 file.Flush();
69 file.Close();
70 }
71
EmitInterfaceInclusions(StringBuilder & sb)72 void CppInterfaceCodeEmitter::EmitInterfaceInclusions(StringBuilder &sb)
73 {
74 HeaderFile::HeaderFileSet headerFiles;
75
76 GetStdlibInclusions(headerFiles);
77 GetImportInclusions(headerFiles);
78 GetHeaderOtherLibInclusions(headerFiles);
79
80 for (const auto &file : headerFiles) {
81 sb.AppendFormat("%s\n", file.ToString().c_str());
82 }
83 }
84
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)85 void CppInterfaceCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
86 {
87 headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
88 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_base");
89 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
90 }
91
EmitInterfaceVersionMacro(StringBuilder & sb)92 void CppInterfaceCodeEmitter::EmitInterfaceVersionMacro(StringBuilder &sb)
93 {
94 sb.AppendFormat("#define %s %u\n", majorVerName_.c_str(), ast_->GetMajorVer());
95 sb.AppendFormat("#define %s %u\n", minorVerName_.c_str(), ast_->GetMinorVer());
96 }
97
EmitInterfaceDefinition(StringBuilder & sb)98 void CppInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder &sb)
99 {
100 if (!interface_->IsSerializable()) {
101 sb.AppendFormat("class %s : public HdiBase {\n", interfaceName_.c_str());
102 sb.Append("public:\n");
103 EmitInterfaceDescriptor(sb, TAB);
104 sb.Append("\n");
105 EmitInterfaceDestruction(sb, TAB);
106 sb.Append("\n");
107 EmitGetMethodDecl(sb, TAB);
108 sb.Append("\n");
109 EmitInterfaceMethodsDecl(sb, TAB);
110 sb.Append("};\n");
111 } else {
112 sb.AppendFormat("class %s : public HdiBase {\n", interfaceName_.c_str());
113 sb.Append("public:\n");
114 EmitInterfaceDescriptor(sb, TAB);
115 sb.Append("\n");
116 EmitInterfaceDestruction(sb, TAB);
117 sb.Append("\n");
118 EmitInterfaceMethodsDecl(sb, TAB);
119 sb.Append("};\n");
120 }
121 }
122
EmitInterfaceDescriptor(StringBuilder & sb,const std::string & prefix)123 void CppInterfaceCodeEmitter::EmitInterfaceDescriptor(StringBuilder &sb, const std::string &prefix)
124 {
125 sb.Append(TAB).AppendFormat("DECLARE_HDI_DESCRIPTOR(u\"%s\");\n", interfaceFullName_.c_str());
126 }
127
EmitGetMethodDecl(StringBuilder & sb,const std::string & prefix)128 void CppInterfaceCodeEmitter::EmitGetMethodDecl(StringBuilder &sb, const std::string &prefix)
129 {
130 sb.Append(prefix).AppendFormat("static sptr<%s> Get(bool isStub = false);\n", interface_->GetName().c_str());
131 sb.Append(prefix).AppendFormat(
132 "static sptr<%s> Get(const std::string &serviceName, bool isStub = false);\n", interface_->GetName().c_str());
133 }
134
EmitInterfaceDestruction(StringBuilder & sb,const std::string & prefix)135 void CppInterfaceCodeEmitter::EmitInterfaceDestruction(StringBuilder &sb, const std::string &prefix)
136 {
137 sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", interface_->GetName().c_str());
138 }
139
EmitInterfaceMethodsDecl(StringBuilder & sb,const std::string & prefix)140 void CppInterfaceCodeEmitter::EmitInterfaceMethodsDecl(StringBuilder &sb, const std::string &prefix)
141 {
142 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
143 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
144 EmitInterfaceMethodDecl(method, sb, prefix);
145 sb.Append("\n");
146 }
147
148 EmitInterfaceGetVersionMethod(sb, prefix);
149 }
150
EmitInterfaceMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)151 void CppInterfaceCodeEmitter::EmitInterfaceMethodDecl(
152 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
153 {
154 if (method->GetParameterNumber() == 0) {
155 sb.Append(prefix).AppendFormat("virtual int32_t %s() = 0;\n", method->GetName().c_str());
156 } else {
157 StringBuilder paramStr;
158 paramStr.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().c_str());
159 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
160 AutoPtr<ASTParameter> param = method->GetParameter(i);
161 EmitInterfaceMethodParameter(param, paramStr, "");
162 if (i + 1 < method->GetParameterNumber()) {
163 paramStr.Append(", ");
164 }
165 }
166
167 paramStr.Append(") = 0;");
168 sb.Append(SpecificationParam(paramStr, prefix + TAB));
169 sb.Append("\n");
170 }
171 }
172
EmitInterfaceGetVersionMethod(StringBuilder & sb,const std::string & prefix)173 void CppInterfaceCodeEmitter::EmitInterfaceGetVersionMethod(StringBuilder &sb, const std::string &prefix)
174 {
175 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
176 sb.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().c_str());
177 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
178 AutoPtr<ASTParameter> param = method->GetParameter(i);
179 EmitInterfaceMethodParameter(param, sb, "");
180 if (i + 1 < method->GetParameterNumber()) {
181 sb.Append(", ");
182 }
183 }
184
185 sb.AppendFormat(")\n");
186 sb.Append(prefix).Append("{\n");
187
188 AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
189 sb.Append(prefix + TAB).AppendFormat("%s = %s;\n", majorParam->GetName().c_str(), majorVerName_.c_str());
190 AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
191 sb.Append(prefix + TAB).AppendFormat("%s = %s;\n", minorParam->GetName().c_str(), minorVerName_.c_str());
192
193 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
194 sb.Append(prefix).Append("}\n");
195 }
196
EmitInterfaceMethodParameter(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix)197 void CppInterfaceCodeEmitter::EmitInterfaceMethodParameter(
198 const AutoPtr<ASTParameter> ¶m, StringBuilder &sb, const std::string &prefix)
199 {
200 sb.Append(prefix).Append(param->EmitCppParameter());
201 }
202 } // namespace HDI
203 } // namespace OHOS