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_client_proxy_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const String & targetDirectory)15 bool CppClientProxyCodeEmitter::ResolveDirectory(const String& targetDirectory)
16 {
17 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE ||
18 ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
19 directory_ = GetFilePath(targetDirectory);
20 } else {
21 return false;
22 }
23
24 if (!File::CreateParentDir(directory_)) {
25 Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", directory_.string());
26 return false;
27 }
28
29 return true;
30 }
31
EmitCode()32 void CppClientProxyCodeEmitter::EmitCode()
33 {
34 EmitProxyHeaderFile();
35 EmitProxySourceFile();
36 }
37
EmitProxyHeaderFile()38 void CppClientProxyCodeEmitter::EmitProxyHeaderFile()
39 {
40 String filePath = String::Format("%s/%s.h", directory_.string(), FileName(baseName_ + "Proxy").string());
41 File file(filePath, File::WRITE);
42 StringBuilder sb;
43
44 EmitLicense(sb);
45 EmitHeadMacro(sb, proxyFullName_);
46 sb.Append("\n");
47 EmitProxyHeaderInclusions(sb);
48 sb.Append("\n");
49 EmitBeginNamespace(sb);
50 sb.Append("\n");
51 EmitProxyDecl(sb, "");
52 sb.Append("\n");
53 EmitEndNamespace(sb);
54 sb.Append("\n");
55 EmitTailMacro(sb, proxyFullName_);
56
57 String data = sb.ToString();
58 file.WriteData(data.string(), data.GetLength());
59 file.Flush();
60 file.Close();
61 }
62
EmitProxyHeaderInclusions(StringBuilder & sb)63 void CppClientProxyCodeEmitter::EmitProxyHeaderInclusions(StringBuilder& sb)
64 {
65 HeaderFile::HeaderFileSet headerFiles;
66
67 headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_)));
68 GetHeaderOtherLibInclusions(headerFiles);
69
70 for (const auto& file : headerFiles) {
71 sb.AppendFormat("%s\n", file.ToString().string());
72 }
73 }
74
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)75 void CppClientProxyCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
76 {
77 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iremote_proxy"));
78 }
79
EmitProxyDecl(StringBuilder & sb,const String & prefix)80 void CppClientProxyCodeEmitter::EmitProxyDecl(StringBuilder& sb, const String& prefix)
81 {
82 sb.AppendFormat("class %s : public IRemoteProxy<%s> {\n",
83 proxyName_.string(), interfaceName_.string());
84 sb.Append("public:\n");
85 EmitProxyConstructor(sb, g_tab);
86 sb.Append("\n");
87 EmitProxyMethodDecls(sb, g_tab);
88 sb.Append("\n");
89 sb.Append("private:\n");
90 EmitProxyConstants(sb, g_tab);
91 sb.Append("};\n");
92 }
93
EmitProxyConstructor(StringBuilder & sb,const String & prefix)94 void CppClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder& sb, const String& prefix)
95 {
96 sb.Append(prefix).AppendFormat("explicit %s(const sptr<IRemoteObject>& remote)", proxyName_.string());
97 sb.AppendFormat(" : IRemoteProxy<%s>(remote) {}\n\n", interfaceName_.string());
98 sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", proxyName_.string());
99 }
100
EmitProxyMethodDecls(StringBuilder & sb,const String & prefix)101 void CppClientProxyCodeEmitter::EmitProxyMethodDecls(StringBuilder& sb, const String& prefix)
102 {
103 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
104 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
105 EmitProxyMethodDecl(method, sb, prefix);
106 sb.Append("\n");
107 }
108
109 EmitProxyMethodDecl(interface_->GetVersionMethod(), sb, prefix);
110 }
111
EmitProxyMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)112 void CppClientProxyCodeEmitter::EmitProxyMethodDecl(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
113 const String& prefix)
114 {
115 if (method->GetParameterNumber() == 0) {
116 sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().string());
117 } else {
118 StringBuilder paramStr;
119 paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().string());
120
121 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
122 AutoPtr<ASTParameter> param = method->GetParameter(i);
123 EmitProxyMethodParameter(param, paramStr, "");
124 if (i + 1 < method->GetParameterNumber()) {
125 paramStr.Append(", ");
126 }
127 }
128
129 paramStr.Append(") override;");
130
131 sb.Append(SpecificationParam(paramStr, prefix + g_tab));
132 sb.Append("\n");
133 }
134 }
135
EmitProxyConstants(StringBuilder & sb,const String & prefix)136 void CppClientProxyCodeEmitter::EmitProxyConstants(StringBuilder& sb, const String& prefix)
137 {
138 sb.Append(prefix).AppendFormat("static inline BrokerDelegator<%s> delegator_;\n", proxyName_.string());
139 }
140
EmitProxyMethodParameter(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const String & prefix)141 void CppClientProxyCodeEmitter::EmitProxyMethodParameter(const AutoPtr<ASTParameter>& param, StringBuilder& sb,
142 const String& prefix)
143 {
144 sb.Append(prefix).Append(param->EmitCppParameter());
145 }
146
EmitProxySourceFile()147 void CppClientProxyCodeEmitter::EmitProxySourceFile()
148 {
149 String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(baseName_ + "Proxy").string());
150 File file(filePath, File::WRITE);
151 StringBuilder sb;
152
153 EmitLicense(sb);
154 EmitProxySourceInclusions(sb);
155 sb.Append("\n");
156 EmitBeginNamespace(sb);
157 sb.Append("\n");
158 if (!interface_->IsSerializable()) {
159 EmitGetMethodImpl(sb, "");
160 sb.Append("\n");
161 EmitGetInstanceMethodImpl(sb, "");
162 sb.Append("\n");
163 }
164 EmitProxyMethodImpls(sb, "");
165 sb.Append("\n");
166 EmitEndNamespace(sb);
167
168 String data = sb.ToString();
169 file.WriteData(data.string(), data.GetLength());
170 file.Flush();
171 file.Close();
172 }
173
EmitProxySourceInclusions(StringBuilder & sb)174 void CppClientProxyCodeEmitter::EmitProxySourceInclusions(StringBuilder& sb)
175 {
176 HeaderFile::HeaderFileSet headerFiles;
177 headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(proxyName_)));
178 GetSourceOtherLibInclusions(headerFiles);
179
180 for (const auto& file : headerFiles) {
181 sb.AppendFormat("%s\n", file.ToString().string());
182 }
183 }
184
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)185 void CppClientProxyCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
186 {
187 if (!interface_->IsSerializable()) {
188 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iservmgr_hdi"));
189 }
190 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base"));
191 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log"));
192 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option"));
193 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel"));
194
195 const AST::TypeStringMap& types = ast_->GetTypes();
196 for (const auto& pair : types) {
197 AutoPtr<ASTType> type = pair.second;
198 if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
199 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
200 break;
201 }
202 }
203 }
204
EmitGetMethodImpl(StringBuilder & sb,const String & prefix)205 void CppClientProxyCodeEmitter::EmitGetMethodImpl(StringBuilder& sb, const String& prefix)
206 {
207 sb.Append(prefix).AppendFormat("sptr<%s> %s::Get()\n",
208 interface_->GetName().string(), interface_->GetName().string());
209 sb.Append(prefix).Append("{\n");
210 sb.Append(prefix + g_tab).AppendFormat("return %s::GetInstance(\"%s\");\n",
211 interfaceName_.string(), FileName(implName_).string());
212 sb.Append(prefix).Append("}\n");
213 }
214
EmitGetInstanceMethodImpl(StringBuilder & sb,const String & prefix)215 void CppClientProxyCodeEmitter::EmitGetInstanceMethodImpl(StringBuilder& sb, const String& prefix)
216 {
217 String objName = "proxy";
218 String SerMajorName = "serMajorVer";
219 String SerMinorName = "serMinorVer";
220 sb.Append(prefix).AppendFormat("sptr<%s> %s::GetInstance(const std::string& serviceName)\n",
221 interface_->GetName().string(), interface_->GetName().string());
222 sb.Append(prefix).Append("{\n");
223 sb.Append(prefix + g_tab).Append("using namespace OHOS::HDI::ServiceManager::V1_0;\n");
224 sb.Append(prefix + g_tab).Append("auto servMgr = IServiceManager::Get();\n");
225 sb.Append(prefix + g_tab).Append("if (servMgr == nullptr) {\n");
226 sb.Append(prefix + g_tab + g_tab).Append(
227 "HDF_LOGE(\"%{public}s:get IServiceManager failed!\", __func__);\n");
228 sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
229 sb.Append(prefix + g_tab).Append("}\n\n");
230
231 sb.Append(prefix + g_tab).Append("sptr<IRemoteObject> remote = ");
232 sb.Append("servMgr->GetService(serviceName.c_str());\n");
233 sb.Append(prefix + g_tab).Append("if (remote == nullptr) {\n");
234 sb.Append(prefix + g_tab + g_tab).Append(
235 "HDF_LOGE(\"%{public}s:get remote object failed!\", __func__);\n");
236 sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
237 sb.Append(prefix + g_tab).Append("}\n\n");
238
239 sb.Append(prefix + g_tab).AppendFormat("sptr<%s> %s = iface_cast<%s>(remote);\n",
240 interfaceName_.string(), objName.string(), interfaceName_.string());
241 sb.Append(prefix + g_tab).AppendFormat("if (%s == nullptr) {\n", objName.string());
242 sb.Append(prefix + g_tab + g_tab).Append("HDF_LOGE(\"%{public}s:iface_cast failed!\", __func__);\n");
243 sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
244 sb.Append(prefix + g_tab).Append("}\n\n");
245
246 sb.Append(prefix + g_tab).AppendFormat("uint32_t %s = 0;\n", SerMajorName.string());
247 sb.Append(prefix + g_tab).AppendFormat("uint32_t %s = 0;\n", SerMinorName.string());
248 sb.Append(prefix + g_tab).AppendFormat("int32_t %s = %s->GetVersion(%s, %s);\n", errorCodeName_.string(),
249 objName.string(), SerMajorName.string(), SerMinorName.string());
250 sb.Append(prefix + g_tab).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.string());
251 sb.Append(prefix + g_tab + g_tab).Append("HDF_LOGE(\"%{public}s:get version failed!\", __func__);\n");
252 sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
253 sb.Append(prefix + g_tab).Append("}\n\n");
254
255 sb.Append(prefix + g_tab).AppendFormat("if (%s != %s) {\n", SerMajorName.string(), majorVerName_.string());
256 sb.Append(prefix + g_tab + g_tab).Append("HDF_LOGE(\"%{public}s:check version failed! ");
257 sb.Append("version of service:%u.%u, version of client:%u.%u\", __func__,\n");
258 sb.Append(prefix + g_tab + g_tab + g_tab).AppendFormat("%s, %s, %s, %s);\n",
259 SerMajorName.string(), SerMinorName.string(), majorVerName_.string(), minorVerName_.string());
260 sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
261 sb.Append(prefix + g_tab).Append("}\n\n");
262 sb.Append(prefix + g_tab).AppendFormat("return %s;\n", objName.string());
263 sb.Append(prefix).Append("}\n");
264 }
265
EmitProxyMethodImpls(StringBuilder & sb,const String & prefix)266 void CppClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb, const String& prefix)
267 {
268 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
269 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
270 EmitProxyMethodImpl(method, sb, prefix);
271 sb.Append("\n");
272 }
273
274 EmitProxyMethodImpl(interface_->GetVersionMethod(), sb, prefix);
275 }
276
EmitProxyMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)277 void CppClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
278 const String& prefix)
279 {
280 if (method->GetParameterNumber() == 0) {
281 sb.Append(prefix).AppendFormat("int32_t %s::%s()\n", proxyName_.string(), method->GetName().string());
282 } else {
283 StringBuilder paramStr;
284 paramStr.Append(prefix).AppendFormat("int32_t %s::%s(", proxyName_.string(), method->GetName().string());
285 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
286 AutoPtr<ASTParameter> param = method->GetParameter(i);
287 EmitProxyMethodParameter(param, paramStr, "");
288 if (i + 1 < method->GetParameterNumber()) {
289 paramStr.Append(", ");
290 }
291 }
292
293 paramStr.Append(")");
294
295 sb.Append(SpecificationParam(paramStr, prefix + g_tab));
296 sb.Append("\n");
297 }
298 EmitProxyMethodBody(method, sb, prefix);
299 }
300
EmitProxyMethodBody(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)301 void CppClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
302 const String& prefix)
303 {
304 String option = method->IsOneWay() ? "MessageOption::TF_ASYNC" : "MessageOption::TF_SYNC";
305 sb.Append(prefix).Append("{\n");
306 sb.Append(prefix + g_tab).AppendFormat("MessageParcel %s;\n", dataParcelName_.string());
307 sb.Append(prefix + g_tab).AppendFormat("MessageParcel %s;\n", replyParcelName_.string());
308 sb.Append(prefix + g_tab).AppendFormat("MessageOption %s(%s);\n", optionName_.string(), option.string());
309 sb.Append("\n");
310
311 // write interface token
312 EmitWriteInterfaceToken(dataParcelName_, sb, prefix + g_tab);
313 sb.Append("\n");
314
315 if (method->GetParameterNumber() > 0) {
316 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
317 AutoPtr<ASTParameter> param = method->GetParameter(i);
318 if (param->GetAttribute() == ParamAttr::PARAM_IN) {
319 EmitWriteMethodParameter(param, dataParcelName_, sb, prefix + g_tab);
320 sb.Append("\n");
321 }
322 }
323 }
324
325 sb.Append(prefix + g_tab).AppendFormat("int32_t %s = Remote()->SendRequest(%s, %s, %s, %s);\n",
326 errorCodeName_.string(), EmitMethodCmdID(method).string(), dataParcelName_.string(),
327 replyParcelName_.string(), optionName_.string());
328 sb.Append(prefix + g_tab).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.string());
329 sb.Append(prefix + g_tab + g_tab).AppendFormat(
330 "HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n", errorCodeName_.string());
331 sb.Append(prefix + g_tab + g_tab).AppendFormat("return %s;\n", errorCodeName_.string());
332 sb.Append(prefix + g_tab).Append("}\n");
333
334 if (!method->IsOneWay()) {
335 sb.Append("\n");
336 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
337 AutoPtr<ASTParameter> param = method->GetParameter(i);
338 if (param->GetAttribute() == ParamAttr::PARAM_OUT) {
339 EmitReadMethodParameter(param, replyParcelName_, false, sb, prefix + g_tab);
340 sb.Append("\n");
341 }
342 }
343 }
344
345 sb.Append(prefix + g_tab).Append("return HDF_SUCCESS;\n");
346 sb.Append(prefix).Append("}\n");
347 }
348
EmitWriteInterfaceToken(const String & parcelName,StringBuilder & sb,const String & prefix)349 void CppClientProxyCodeEmitter::EmitWriteInterfaceToken(const String& parcelName, StringBuilder& sb,
350 const String& prefix)
351 {
352 sb.Append(prefix).AppendFormat("if (!%s.WriteInterfaceToken(GetDescriptor())) {\n", parcelName.string());
353 sb.Append(prefix + g_tab).AppendFormat(
354 "HDF_LOGE(\"%%{public}s: write interface descriptor failed!\", __func__);\n");
355 sb.Append(prefix + g_tab).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
356 sb.Append(prefix).Append("}\n");
357 }
358 } // namespace HDI
359 } // namespace OHOS