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