1 /*
2 * Copyright (c) 2021-2023 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 #include "util/string_helper.h"
13
14 namespace OHOS {
15 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)16 bool CppClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
17 {
18 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
19 directory_ = GetFileParentPath(targetDirectory);
20 } else {
21 return false;
22 }
23
24 if (!File::CreateParentDir(directory_)) {
25 Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", directory_.c_str());
26 return false;
27 }
28
29 return true;
30 }
31
EmitCode()32 void CppClientProxyCodeEmitter::EmitCode()
33 {
34 switch (mode_) {
35 case GenMode::PASSTHROUGH: {
36 if (!interface_->IsSerializable()) {
37 EmitPassthroughProxySourceFile();
38 }
39 break;
40 }
41 case GenMode::IPC: {
42 EmitProxyHeaderFile();
43 EmitProxySourceFile();
44 }
45 default:
46 break;
47 }
48 }
49
EmitProxyHeaderFile()50 void CppClientProxyCodeEmitter::EmitProxyHeaderFile()
51 {
52 std::string filePath =
53 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_ + "Proxy").c_str()));
54 File file(filePath, File::WRITE);
55 StringBuilder sb;
56
57 EmitLicense(sb);
58 EmitHeadMacro(sb, proxyFullName_);
59 sb.Append("\n");
60 EmitProxyHeaderInclusions(sb);
61 sb.Append("\n");
62 EmitBeginNamespace(sb);
63 sb.Append("\n");
64 EmitProxyDecl(sb, "");
65 sb.Append("\n");
66 EmitEndNamespace(sb);
67 sb.Append("\n");
68 EmitTailMacro(sb, proxyFullName_);
69
70 std::string data = sb.ToString();
71 file.WriteData(data.c_str(), data.size());
72 file.Flush();
73 file.Close();
74 }
75
EmitProxyHeaderInclusions(StringBuilder & sb)76 void CppClientProxyCodeEmitter::EmitProxyHeaderInclusions(StringBuilder &sb)
77 {
78 HeaderFile::HeaderFileSet headerFiles;
79
80 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
81 if (interface_->GetExtendsInterface() != nullptr) {
82 headerFiles.emplace(
83 HeaderFileType::OWN_HEADER_FILE, EmitHeaderNameByInterface(interface_->GetExtendsInterface(), proxyName_));
84 }
85 GetHeaderOtherLibInclusions(headerFiles);
86
87 for (const auto &file : headerFiles) {
88 sb.AppendFormat("%s\n", file.ToString().c_str());
89 }
90 }
91
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const92 void CppClientProxyCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
93 {
94 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iproxy_broker");
95 }
96
EmitProxyDecl(StringBuilder & sb,const std::string & prefix)97 void CppClientProxyCodeEmitter::EmitProxyDecl(StringBuilder &sb, const std::string &prefix)
98 {
99 (void)prefix;
100 sb.AppendFormat("class %s : public IProxyBroker<%s> {\n", proxyName_.c_str(),
101 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
102 sb.Append("public:\n");
103 EmitProxyConstructor(sb, TAB);
104 sb.Append("\n");
105 EmitProxyMethodDecls(sb, TAB);
106 sb.Append("\n");
107 sb.Append("private:\n");
108 EmitProxyConstants(sb, TAB);
109 sb.Append("};\n");
110 }
111
EmitProxyConstructor(StringBuilder & sb,const std::string & prefix) const112 void CppClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder &sb, const std::string &prefix) const
113 {
114 sb.Append(prefix).AppendFormat("explicit %s(const sptr<IRemoteObject>& remote)", proxyName_.c_str());
115 sb.AppendFormat(
116 " : IProxyBroker<%s>(remote) {}\n\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
117 sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", proxyName_.c_str());
118 }
119
EmitProxyMethodDecls(StringBuilder & sb,const std::string & prefix) const120 void CppClientProxyCodeEmitter::EmitProxyMethodDecls(StringBuilder &sb, const std::string &prefix) const
121 {
122 EmitProxyIsProxyMethodImpl(sb, prefix);
123 AutoPtr<ASTInterfaceType> interface = interface_;
124 while (interface != nullptr) {
125 for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
126 EmitProxyMethodDecl(method, sb, prefix);
127 sb.Append("\n");
128 }
129 interface = interface->GetExtendsInterface();
130 }
131 EmitProxyMethodDecl(interface_->GetVersionMethod(), sb, prefix);
132 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
133 sb.Append("\n");
134 EmitProxyStaticMethodDecl(method, sb, prefix);
135 }
136 if (interface_->GetExtendsInterface() == nullptr) {
137 sb.Append("\n");
138 EmitProxyStaticMethodDecl(interface_->GetVersionMethod(), sb, prefix);
139 }
140 }
141
EmitProxyMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const142 void CppClientProxyCodeEmitter::EmitProxyMethodDecl(
143 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
144 {
145 if (method->GetParameterNumber() == 0) {
146 sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().c_str());
147 } else {
148 StringBuilder paramStr;
149 paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
150
151 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
152 AutoPtr<ASTParameter> param = method->GetParameter(i);
153 EmitProxyMethodParameter(param, paramStr, "");
154 if (i + 1 < method->GetParameterNumber()) {
155 paramStr.Append(", ");
156 }
157 }
158
159 paramStr.Append(") override;");
160
161 sb.Append(SpecificationParam(paramStr, prefix + TAB));
162 sb.Append("\n");
163 }
164 }
165
EmitProxyStaticMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const166 void CppClientProxyCodeEmitter::EmitProxyStaticMethodDecl(
167 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
168 {
169 if (method->GetParameterNumber() == 0) {
170 sb.Append(prefix).AppendFormat(
171 "static int32_t %s_(const sptr<IRemoteObject> remote);\n", method->GetName().c_str());
172 } else {
173 StringBuilder paramStr;
174 paramStr.Append(prefix).AppendFormat("static int32_t %s_(", method->GetName().c_str());
175
176 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
177 AutoPtr<ASTParameter> param = method->GetParameter(i);
178 EmitProxyMethodParameter(param, paramStr, "");
179 paramStr.Append(", ");
180 }
181 paramStr.Append("const sptr<IRemoteObject> remote");
182
183 paramStr.Append(");");
184
185 sb.Append(SpecificationParam(paramStr, prefix + TAB));
186 sb.Append("\n");
187 }
188 }
189
EmitProxyConstants(StringBuilder & sb,const std::string & prefix) const190 void CppClientProxyCodeEmitter::EmitProxyConstants(StringBuilder &sb, const std::string &prefix) const
191 {
192 sb.Append(prefix).AppendFormat(
193 "static inline BrokerDelegator<%s> delegator_;\n", EmitDefinitionByInterface(interface_, proxyName_).c_str());
194 }
195
EmitProxyMethodParameter(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix) const196 void CppClientProxyCodeEmitter::EmitProxyMethodParameter(
197 const AutoPtr<ASTParameter> ¶m, StringBuilder &sb, const std::string &prefix) const
198 {
199 sb.Append(prefix).Append(param->EmitCppParameter());
200 }
201
EmitPassthroughProxySourceFile()202 void CppClientProxyCodeEmitter::EmitPassthroughProxySourceFile()
203 {
204 std::string filePath =
205 File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(proxyName_).c_str()));
206 File file(filePath, File::WRITE);
207 StringBuilder sb;
208
209 EmitLicense(sb);
210 EmitPassthroughProxySourceInclusions(sb);
211 sb.Append("\n");
212 EmitLogTagMacro(sb, FileName(proxyName_));
213 sb.Append("\n");
214 EmitBeginNamespace(sb);
215 EmitGetMethodImpl(sb, "");
216 sb.Append("\n");
217 EmitPassthroughGetInstanceMethodImpl(sb, "");
218 EmitEndNamespace(sb);
219
220 std::string data = sb.ToString();
221 file.WriteData(data.c_str(), data.size());
222 file.Flush();
223 file.Close();
224 }
225
EmitPassthroughProxySourceInclusions(StringBuilder & sb)226 void CppClientProxyCodeEmitter::EmitPassthroughProxySourceInclusions(StringBuilder &sb)
227 {
228 HeaderFile::HeaderFileSet headerFiles;
229
230 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
231 if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
232 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "codecvt");
233 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "locale");
234 } else {
235 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
236 }
237 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
238 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
239
240 for (const auto &file : headerFiles) {
241 sb.AppendFormat("%s\n", file.ToString().c_str());
242 }
243 }
244
EmitPassthroughGetInstanceMethodImpl(StringBuilder & sb,const std::string & prefix) const245 void CppClientProxyCodeEmitter::EmitPassthroughGetInstanceMethodImpl(StringBuilder &sb,
246 const std::string &prefix) const
247 {
248 sb.Append(prefix).AppendFormat("%s %s::Get(const std::string &serviceName, bool isStub)\n",
249 interface_->EmitCppType().c_str(), interface_->GetName().c_str());
250 sb.Append(prefix).Append("{\n");
251 EmitProxyPassthroughtLoadImpl(sb, prefix + TAB);
252 sb.Append(prefix + TAB).Append("return nullptr;\n");
253 sb.Append(prefix).Append("}\n");
254 }
255
EmitProxySourceFile()256 void CppClientProxyCodeEmitter::EmitProxySourceFile()
257 {
258 std::string filePath =
259 File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(proxyName_).c_str()));
260 File file(filePath, File::WRITE);
261 StringBuilder sb;
262
263 EmitLicense(sb);
264 EmitProxySourceInclusions(sb);
265 sb.Append("\n");
266 EmitLogTagMacro(sb, FileName(proxyName_));
267 sb.Append("\n");
268 EmitBeginNamespace(sb);
269 sb.Append("\n");
270 UtilMethodMap utilMethods;
271 GetUtilMethods(utilMethods);
272 EmitUtilMethods(sb, "", utilMethods, true);
273 sb.Append("\n");
274 if (interface_->GetExtendsInterface() != nullptr) {
275 EmitProxyCastFromMethodImplTemplate(sb, "");
276 sb.Append("\n");
277 }
278 if (!interface_->IsSerializable()) {
279 EmitGetMethodImpl(sb, "");
280 sb.Append("\n");
281 EmitGetInstanceMethodImpl(sb, "");
282 sb.Append("\n");
283 }
284 EmitProxyCastFromMethodImpls(sb, "");
285 EmitUtilMethods(sb, "", utilMethods, false);
286 EmitProxyMethodImpls(sb, "");
287 sb.Append("\n");
288 EmitEndNamespace(sb);
289
290 std::string data = sb.ToString();
291 file.WriteData(data.c_str(), data.size());
292 file.Flush();
293 file.Close();
294 }
295
EmitProxySourceInclusions(StringBuilder & sb)296 void CppClientProxyCodeEmitter::EmitProxySourceInclusions(StringBuilder &sb)
297 {
298 HeaderFile::HeaderFileSet headerFiles;
299 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(proxyName_));
300 GetSourceOtherLibInclusions(headerFiles);
301 GetSourceOtherFileInclusions(headerFiles);
302
303 for (const auto &file : headerFiles) {
304 sb.AppendFormat("%s\n", file.ToString().c_str());
305 }
306 }
307
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const308 void CppClientProxyCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
309 {
310 if (!interface_->IsSerializable()) {
311 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iservmgr_hdi");
312 }
313 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
314 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
315 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option");
316 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
317 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
318 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
319
320 const AST::TypeStringMap &types = ast_->GetTypes();
321 for (const auto &pair : types) {
322 AutoPtr<ASTType> type = pair.second;
323 if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
324 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
325 break;
326 }
327 }
328
329 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
330 for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
331 AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
332 AutoPtr<ASTType> paramType = param->GetType();
333 if (param->GetAttribute() == ParamAttr::PARAM_IN &&
334 (paramType->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
335 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
336 }
337
338 if (param->GetAttribute() == ParamAttr::PARAM_OUT &&
339 (paramType->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
340 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iproxy_broker");
341 }
342 }
343 }
344 }
345
GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet & headerFiles) const346 void CppClientProxyCodeEmitter::GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet &headerFiles) const
347 {
348 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
349 for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
350 AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
351 AutoPtr<ASTType> paramType = param->GetType();
352 if (param->GetAttribute() == ParamAttr::PARAM_OUT &&
353 (param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
354 AutoPtr<ASTInterfaceType> type = dynamic_cast<ASTInterfaceType *>(paramType.Get());
355 std::string FileName = InterfaceToFilePath(paramType->ToString());
356 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, FileName);
357 }
358 }
359 }
360 }
361
EmitGetMethodImpl(StringBuilder & sb,const std::string & prefix) const362 void CppClientProxyCodeEmitter::EmitGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
363 {
364 sb.Append(prefix).AppendFormat("%s %s::Get(bool isStub)\n", interface_->EmitCppType().c_str(),
365 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
366 sb.Append(prefix).Append("{\n");
367 sb.Append(prefix + TAB)
368 .AppendFormat("return %s::Get(\"%s\", isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
369 sb.Append(prefix).Append("}\n");
370 }
371
EmitGetInstanceMethodImpl(StringBuilder & sb,const std::string & prefix)372 void CppClientProxyCodeEmitter::EmitGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix)
373 {
374 std::string objName = "proxy";
375 std::string serMajorName = "serMajorVer";
376 std::string serMinorName = "serMinorVer";
377 sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(const std::string& serviceName, bool isStub)\n",
378 EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
379 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
380 sb.Append(prefix).Append("{\n");
381 EmitProxyPassthroughtLoadImpl(sb, prefix + TAB);
382 sb.Append(prefix + TAB).Append("using namespace OHOS::HDI::ServiceManager::V1_0;\n");
383 sb.Append(prefix + TAB).Append("auto servMgr = IServiceManager::Get();\n");
384 sb.Append(prefix + TAB).Append("if (servMgr == nullptr) {\n");
385 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get IServiceManager failed!\", __func__);\n");
386 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
387 sb.Append(prefix + TAB).Append("}\n\n");
388 sb.Append(prefix + TAB).Append("sptr<IRemoteObject> remote = ");
389 sb.Append("servMgr->GetService(serviceName.c_str());\n");
390 sb.Append(prefix + TAB).Append("if (remote == nullptr) {\n");
391 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get remote object failed!\", __func__);\n");
392 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
393 sb.Append(prefix + TAB).Append("}\n\n");
394 sb.Append(prefix + TAB).AppendFormat("sptr<%s> %s = new %s(remote);\n",
395 EmitDefinitionByInterface(interface_, interfaceName_).c_str(), objName.c_str(),
396 ((StringHelper::StartWith(interfaceName_, "I") ? interfaceName_.substr(1) : interfaceName_) +
397 "Proxy").c_str());
398 sb.Append(prefix + TAB).AppendFormat("if (%s == nullptr) {\n", objName.c_str());
399 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:iface_cast failed!\", __func__);\n");
400 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
401 sb.Append(prefix + TAB).Append("}\n\n");
402
403 sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMajorName.c_str());
404 sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMinorName.c_str());
405 sb.Append(prefix + TAB).AppendFormat("int32_t %s = %s->GetVersion(%s, %s);\n",
406 errorCodeName_.c_str(), objName.c_str(), serMajorName.c_str(), serMinorName.c_str());
407 sb.Append(prefix + TAB).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.c_str());
408 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get version failed!\", __func__);\n");
409 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
410 sb.Append(prefix + TAB).Append("}\n\n");
411
412 sb.Append(prefix + TAB).AppendFormat("if (%s != %d) {\n", serMajorName.c_str(), ast_->GetMajorVer());
413 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:check version failed! ");
414 sb.Append("version of service:%u.%u");
415 sb.AppendFormat(", version of client:%d.%d\", __func__, ", ast_->GetMajorVer(), ast_->GetMinorVer());
416 sb.AppendFormat("%s, %s);\n", serMajorName.c_str(), serMinorName.c_str());
417 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
418 sb.Append(prefix + TAB).Append("}\n\n");
419 sb.Append(prefix + TAB).AppendFormat("return %s;\n", objName.c_str());
420 sb.Append(prefix).Append("}\n");
421 }
422
EmitProxyPassthroughtLoadImpl(StringBuilder & sb,const std::string & prefix) const423 void CppClientProxyCodeEmitter::EmitProxyPassthroughtLoadImpl(StringBuilder &sb, const std::string &prefix) const
424 {
425 sb.Append(prefix).AppendFormat("if (isStub) {\n");
426
427 if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
428 sb.Append(prefix + TAB).Append("std::string desc = ");
429 sb.Append("std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(");
430 sb.AppendFormat("%s::GetDescriptor());\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
431 } else {
432 sb.Append(prefix + TAB).AppendFormat("std::string desc = Str16ToStr8(%s::GetDescriptor());\n",
433 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
434 }
435 sb.Append(prefix + TAB).Append("void *impl = LoadHdiImpl(desc.c_str(), ");
436 sb.AppendFormat("serviceName == \"%s\" ? \"service\" : serviceName.c_str());\n", FileName(implName_).c_str());
437 sb.Append(prefix + TAB).Append("if (impl == nullptr) {\n");
438 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"failed to load hdi impl %{public}s\", desc.data());\n");
439 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
440 sb.Append(prefix + TAB).Append("}\n");
441
442 if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
443 sb.Append(prefix + TAB).AppendFormat("return std::shared_ptr<%s>(reinterpret_cast<%s *>(impl));\n",
444 EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
445 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
446 } else {
447 sb.Append(prefix + TAB).AppendFormat("return reinterpret_cast<%s *>(impl);\n",
448 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
449 }
450 sb.Append(prefix).Append("}\n\n");
451 }
452
EmitProxyMethodImpls(StringBuilder & sb,const std::string & prefix)453 void CppClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder &sb, const std::string &prefix)
454 {
455 AutoPtr<ASTInterfaceType> interface = interface_;
456 AutoPtr<ASTInterfaceType> metaInterface = interface_;
457 while (interface != nullptr) {
458 for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
459 EmitProxyMethodImpl(interface, method, sb, prefix);
460 sb.Append("\n");
461 }
462 interface = interface->GetExtendsInterface();
463 if (interface != nullptr) {
464 metaInterface = interface;
465 }
466 }
467 AutoPtr<ASTMethod> verMethod = interface_->GetVersionMethod();
468 EmitProxyMethodImpl(metaInterface, verMethod, sb, prefix);
469 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
470 sb.Append("\n");
471 EmitProxyStaticMethodImpl(method, sb, prefix);
472 }
473 if (interface_->GetExtendsInterface() == nullptr) {
474 sb.Append("\n");
475 EmitProxyStaticMethodImpl(interface_->GetVersionMethod(), sb, prefix);
476 }
477 }
478
EmitProxyIsProxyMethodImpl(StringBuilder & sb,const std::string & prefix) const479 void CppClientProxyCodeEmitter::EmitProxyIsProxyMethodImpl(StringBuilder &sb, const std::string &prefix) const
480 {
481 sb.Append(prefix).Append("inline bool IsProxy() override\n");
482 sb.Append(prefix).Append("{\n");
483 sb.Append(prefix + TAB).Append("return true;\n");
484 sb.Append(prefix).Append("}\n\n");
485 }
486
EmitProxyCastFromMethodImpls(StringBuilder & sb,const std::string & prefix) const487 void CppClientProxyCodeEmitter::EmitProxyCastFromMethodImpls(StringBuilder &sb, const std::string &prefix) const
488 {
489 AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
490 while (interface != nullptr) {
491 EmitProxyCastFromMethodImpl(interface, sb, prefix);
492 sb.Append(prefix).Append("\n");
493 interface = interface->GetExtendsInterface();
494 }
495 }
496
EmitProxyCastFromMethodImpl(const AutoPtr<ASTInterfaceType> interface,StringBuilder & sb,const std::string & prefix) const497 void CppClientProxyCodeEmitter::EmitProxyCastFromMethodImpl(const AutoPtr<ASTInterfaceType> interface,
498 StringBuilder &sb, const std::string &prefix) const
499 {
500 std::string currentInterface = EmitDefinitionByInterface(interface_, interfaceName_);
501 std::string parentInterface = EmitDefinitionByInterface(interface, interfaceName_);
502
503 sb.Append(prefix).AppendFormat("sptr<%s> %s::CastFrom(const sptr<%s> &parent)\n",
504 currentInterface.c_str(), currentInterface.c_str(), parentInterface.c_str());
505 sb.Append(prefix).Append("{\n");
506 sb.Append(prefix + TAB).AppendFormat("return CastFromTemplate<%s, %s>(parent);\n",
507 currentInterface.c_str(), parentInterface.c_str());
508 sb.Append(prefix).Append("}\n");
509 }
510
EmitProxyCastFromMethodImplTemplate(StringBuilder & sb,const std::string & prefix) const511 void CppClientProxyCodeEmitter::EmitProxyCastFromMethodImplTemplate(StringBuilder &sb, const std::string &prefix) const
512 {
513 std::string serMajorName = "serMajorVer";
514 std::string serMinorName = "serMinorVer";
515
516 sb.Append(prefix).Append("template<typename ChildType, typename ParentType>\n");
517 sb.Append(prefix).Append("static sptr<ChildType> CastFromTemplate(const sptr<ParentType> &parent)\n");
518 sb.Append(prefix).Append("{\n");
519 sb.Append(prefix + TAB).Append("if (parent == nullptr) {\n");
520 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:parent is nullptr!\", __func__);\n");
521 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
522 sb.Append(prefix + TAB).Append("}\n\n");
523
524 sb.Append(prefix + TAB).Append("if (!parent->IsProxy()) {\n");
525 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:not proxy, not support castfrom!\", __func__);\n");
526 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
527 sb.Append(prefix + TAB).Append("}\n\n");
528
529 sb.Append(prefix + TAB).AppendFormat("sptr<IRemoteObject> remote = OHOS::HDI::hdi_objcast<ParentType>(parent);\n");
530 sb.Append(prefix + TAB).Append("if (remote == nullptr) {\n");
531 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:hdi_objcast failed!\", __func__);\n");
532 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
533 sb.Append(prefix + TAB).Append("}\n\n");
534
535 sb.Append(prefix + TAB).AppendFormat("sptr<ChildType> proxy = OHOS::HDI::hdi_facecast<ChildType>(remote);\n");
536 sb.Append(prefix + TAB).Append("if (proxy == nullptr) {\n");
537 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:hdi_facecast failed!\", __func__);\n");
538 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
539 sb.Append(prefix + TAB).Append("}\n\n");
540
541 sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMajorName.c_str());
542 sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMinorName.c_str());
543 sb.Append(prefix + TAB).AppendFormat("int32_t %s = proxy->GetVersion(%s, %s);\n",
544 errorCodeName_.c_str(), serMajorName.c_str(), serMinorName.c_str());
545 sb.Append(prefix + TAB).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.c_str());
546 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get version failed!\", __func__);\n");
547 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
548 sb.Append(prefix + TAB).Append("}\n\n");
549
550 sb.Append(prefix + TAB).AppendFormat("if (%s != %d) {\n", serMajorName.c_str(), ast_->GetMajorVer());
551 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:check version failed! ");
552 sb.Append("version of service:%u.%u");
553 sb.AppendFormat(", version of client:%d.%d\", __func__, ", ast_->GetMajorVer(), ast_->GetMinorVer());
554 sb.AppendFormat("%s, %s);\n", serMajorName.c_str(), serMinorName.c_str());
555 sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
556 sb.Append(prefix + TAB).Append("}\n\n");
557
558 sb.Append(prefix + TAB).Append("return proxy;\n");
559 sb.Append(prefix).Append("}\n");
560 }
561
EmitProxyMethodImpl(const AutoPtr<ASTInterfaceType> interface,const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)562 void CppClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr<ASTInterfaceType> interface,
563 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
564 {
565 if (method->GetParameterNumber() == 0) {
566 sb.Append(prefix).AppendFormat(
567 "int32_t %s::%s()\n", EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
568 } else {
569 StringBuilder paramStr;
570 paramStr.Append(prefix).AppendFormat(
571 "int32_t %s::%s(", EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
572 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
573 AutoPtr<ASTParameter> param = method->GetParameter(i);
574 EmitProxyMethodParameter(param, paramStr, "");
575 if (i + 1 < method->GetParameterNumber()) {
576 paramStr.Append(", ");
577 }
578 }
579
580 paramStr.Append(")");
581
582 sb.Append(SpecificationParam(paramStr, prefix + TAB));
583 sb.Append("\n");
584 }
585 EmitProxyMethodBody(interface, method, sb, prefix);
586 }
587
EmitProxyStaticMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)588 void CppClientProxyCodeEmitter::EmitProxyStaticMethodImpl(
589 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
590 {
591 if (method->GetParameterNumber() == 0) {
592 sb.Append(prefix).AppendFormat("int32_t %s::%s_(const sptr<IRemoteObject> remote)\n",
593 EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
594 } else {
595 StringBuilder paramStr;
596 paramStr.Append(prefix).AppendFormat(
597 "int32_t %s::%s_(", EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
598 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
599 AutoPtr<ASTParameter> param = method->GetParameter(i);
600 EmitProxyMethodParameter(param, paramStr, "");
601 paramStr.Append(", ");
602 }
603
604 paramStr.Append("const sptr<IRemoteObject> remote)");
605 sb.Append(SpecificationParam(paramStr, prefix + TAB));
606 sb.Append("\n");
607 }
608 EmitProxyStaticMethodBody(method, sb, prefix);
609 }
610
EmitProxyMethodBody(const AutoPtr<ASTInterfaceType> interface,const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)611 void CppClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr<ASTInterfaceType> interface,
612 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
613 {
614 sb.Append(prefix).Append("{\n");
615 sb.Append(prefix + TAB).AppendFormat("return %s::%s_(",
616 EmitDefinitionByInterface(interface, proxyName_).c_str(), method->GetName().c_str());
617 if (method->GetParameterNumber() > 0) {
618 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
619 AutoPtr<ASTParameter> param = method->GetParameter(i);
620 sb.Append(param->GetName().c_str());
621 sb.Append(", ");
622 }
623 }
624 sb.Append("Remote());\n");
625 sb.Append(prefix).Append("}\n");
626 }
627
EmitProxyStaticMethodBody(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)628 void CppClientProxyCodeEmitter::EmitProxyStaticMethodBody(
629 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
630 {
631 std::string option = method->IsOneWay() ? "MessageOption::TF_ASYNC" : "MessageOption::TF_SYNC";
632 sb.Append(prefix).Append("{\n");
633 sb.Append(prefix + TAB).AppendFormat("MessageParcel %s;\n", dataParcelName_.c_str());
634 sb.Append(prefix + TAB).AppendFormat("MessageParcel %s;\n", replyParcelName_.c_str());
635 sb.Append(prefix + TAB).AppendFormat("MessageOption %s(%s);\n", optionName_.c_str(), option.c_str());
636 sb.Append("\n");
637
638 // write interface token
639 EmitWriteInterfaceToken(dataParcelName_, sb, prefix + TAB);
640 sb.Append("\n");
641
642 EmitWriteFlagOfNeedSetMem(method, dataParcelName_, sb, prefix + TAB);
643
644 if (method->GetParameterNumber() > 0) {
645 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
646 AutoPtr<ASTParameter> param = method->GetParameter(i);
647 if (param->GetAttribute() == ParamAttr::PARAM_IN) {
648 EmitWriteMethodParameter(param, dataParcelName_, sb, prefix + TAB);
649 sb.Append("\n");
650 }
651 }
652 }
653 sb.Append(prefix + TAB).AppendFormat("if (remote == nullptr) {\n");
654 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: invalid remote object!\", __func__);\n");
655 sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
656 sb.Append(prefix + TAB).Append("}\n\n");
657 sb.Append(prefix + TAB).AppendFormat("int32_t %s = remote->SendRequest(%s, %s, %s, %s);\n", errorCodeName_.c_str(),
658 EmitMethodCmdID(method).c_str(), dataParcelName_.c_str(), replyParcelName_.c_str(), optionName_.c_str());
659 sb.Append(prefix + TAB).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.c_str());
660 sb.Append(prefix + TAB + TAB).AppendFormat(
661 "HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n", errorCodeName_.c_str());
662 sb.Append(prefix + TAB + TAB).AppendFormat("return %s;\n", errorCodeName_.c_str());
663 sb.Append(prefix + TAB).Append("}\n");
664
665 if (!method->IsOneWay()) {
666 sb.Append("\n");
667 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
668 AutoPtr<ASTParameter> param = method->GetParameter(i);
669 if (param->GetAttribute() == ParamAttr::PARAM_OUT) {
670 EmitReadMethodParameter(param, replyParcelName_, false, sb, prefix + TAB);
671 sb.Append("\n");
672 }
673 }
674 }
675
676 sb.Append(prefix + TAB).AppendFormat("return %s;\n", errorCodeName_.c_str());
677 sb.Append(prefix).Append("}\n");
678 }
679
EmitWriteInterfaceToken(const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const680 void CppClientProxyCodeEmitter::EmitWriteInterfaceToken(
681 const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
682 {
683 sb.Append(prefix).AppendFormat("if (!%s.WriteInterfaceToken(%s::GetDescriptor())) {\n", parcelName.c_str(),
684 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
685 sb.Append(prefix + TAB)
686 .AppendFormat("HDF_LOGE(\"%%{public}s: failed to write interface descriptor!\", __func__);\n");
687 sb.Append(prefix + TAB).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
688 sb.Append(prefix).Append("}\n");
689 }
690
EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> & method,const std::string & dataBufName,StringBuilder & sb,const std::string & prefix) const691 void CppClientProxyCodeEmitter::EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> &method,
692 const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const
693 {
694 if (NeedFlag(method)) {
695 sb.Append(prefix).AppendFormat("if (!%s.WriteBool(false)) {\n", dataBufName.c_str());
696 sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s:failed to write flag of memory setting!\", __func__);\n");
697 sb.Append(prefix + TAB).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
698 sb.Append(prefix).Append("}\n\n");
699 }
700 }
701
GetUtilMethods(UtilMethodMap & methods)702 void CppClientProxyCodeEmitter::GetUtilMethods(UtilMethodMap &methods)
703 {
704 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
705 for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
706 AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
707 AutoPtr<ASTType> paramType = param->GetType();
708 if (param->GetAttribute() == ParamAttr::PARAM_IN) {
709 paramType->RegisterWriteMethod(Options::GetInstance().GetLanguage(), SerMode::PROXY_SER, methods);
710 } else {
711 paramType->RegisterReadMethod(Options::GetInstance().GetLanguage(), SerMode::PROXY_SER, methods);
712 }
713 }
714 }
715 }
716 } // namespace HDI
717 } // namespace OHOS