• 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_service_stub_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 CppServiceStubCodeEmitter::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("CppServiceStubCodeEmitter", "Create '%s' failed!", directory_.c_str());
25         return false;
26     }
27 
28     return true;
29 }
30 
EmitCode()31 void CppServiceStubCodeEmitter::EmitCode()
32 {
33     if (mode_ == GenMode::IPC) {
34         EmitStubHeaderFile();
35         EmitStubSourceFile();
36     }
37 }
38 
EmitStubHeaderFile()39 void CppServiceStubCodeEmitter::EmitStubHeaderFile()
40 {
41     std::string filePath =
42         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(stubName_).c_str()));
43     File file(filePath, File::WRITE);
44     StringBuilder sb;
45 
46     EmitLicense(sb);
47     EmitHeadMacro(sb, stubFullName_);
48     sb.Append("\n");
49     EmitStubHeaderInclusions(sb);
50     sb.Append("\n");
51     EmitStubDecl(sb);
52     sb.Append("\n");
53     EmitTailMacro(sb, stubFullName_);
54 
55     std::string data = sb.ToString();
56     file.WriteData(data.c_str(), data.size());
57     file.Flush();
58     file.Close();
59 }
60 
EmitStubHeaderInclusions(StringBuilder & sb)61 void CppServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder &sb)
62 {
63     HeaderFile::HeaderFileSet headerFiles;
64 
65     headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
66     if (interface_->GetExtendsInterface() != nullptr) {
67         headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE,
68             EmitHeaderNameByInterface(interface_->GetExtendsInterface(), stubName_));
69     }
70     GetHeaderOtherLibInclusions(headerFiles);
71 
72     for (const auto &file : headerFiles) {
73         sb.AppendFormat("%s\n", file.ToString().c_str());
74     }
75 }
76 
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const77 void CppServiceStubCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
78 {
79     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
80     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option");
81     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "ipc_object_stub");
82     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
83     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "refbase");
84 }
85 
EmitStubDecl(StringBuilder & sb)86 void CppServiceStubCodeEmitter::EmitStubDecl(StringBuilder &sb)
87 {
88     EmitBeginNamespace(sb);
89     sb.Append("\n");
90     EmitStubUsingNamespace(sb);
91     sb.AppendFormat("class %s : public IPCObjectStub {\n", stubName_.c_str());
92     EmitStubBody(sb, TAB);
93     sb.Append("};\n");
94     EmitEndNamespace(sb);
95 }
96 
EmitStubUsingNamespace(StringBuilder & sb) const97 void CppServiceStubCodeEmitter::EmitStubUsingNamespace(StringBuilder &sb) const
98 {
99     sb.Append("using namespace OHOS;\n");
100 }
101 
EmitStubBody(StringBuilder & sb,const std::string & prefix) const102 void CppServiceStubCodeEmitter::EmitStubBody(StringBuilder &sb, const std::string &prefix) const
103 {
104     sb.Append("public:\n");
105     EmitStubConstructorDecl(sb, prefix);
106     sb.Append("\n");
107     EmitStubOnRequestDecl(sb, prefix);
108     sb.Append("\n");
109     EmitStubMethodDecls(sb, prefix);
110     sb.Append("\n");
111     EmitStubPrivateData(sb, prefix);
112 }
113 
EmitStubConstructorDecl(StringBuilder & sb,const std::string & prefix) const114 void CppServiceStubCodeEmitter::EmitStubConstructorDecl(StringBuilder &sb, const std::string &prefix) const
115 {
116     sb.Append(prefix).AppendFormat("explicit %s(const sptr<%s> &impl);\n", stubName_.c_str(), interfaceName_.c_str());
117     sb.Append(prefix).AppendFormat("virtual ~%s();\n", stubName_.c_str());
118 }
119 
EmitStubOnRequestDecl(StringBuilder & sb,const std::string & prefix) const120 void CppServiceStubCodeEmitter::EmitStubOnRequestDecl(StringBuilder &sb, const std::string &prefix) const
121 {
122     sb.Append(prefix).Append("int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, ");
123     sb.Append("MessageOption &option) override;\n");
124 }
125 
EmitStubMethodDecls(StringBuilder & sb,const std::string & prefix) const126 void CppServiceStubCodeEmitter::EmitStubMethodDecls(StringBuilder &sb, const std::string &prefix) const
127 {
128     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
129         EmitStubStaticMethodDecl(method, sb, prefix);
130         sb.Append("\n");
131     }
132     if (interface_->GetExtendsInterface() == nullptr) {
133         EmitStubStaticMethodDecl(interface_->GetVersionMethod(), sb, prefix);
134         sb.Append("\n");
135     }
136 
137     sb.Append("private:\n");
138     AutoPtr<ASTInterfaceType> interface = interface_;
139     while (interface != nullptr) {
140         for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
141             EmitStubMethodDecl(method, sb, prefix);
142             sb.Append("\n");
143         }
144         interface = interface->GetExtendsInterface();
145     }
146     EmitStubMethodDecl(interface_->GetVersionMethod(), sb, prefix);
147     sb.Append("\n");
148 }
149 
EmitStubMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const150 void CppServiceStubCodeEmitter::EmitStubMethodDecl(
151     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
152 {
153     sb.Append(prefix).AppendFormat("int32_t %s%s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s);\n",
154         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
155         dataParcelName_.c_str(), replyParcelName_.c_str(), optionName_.c_str());
156 }
157 
EmitStubStaticMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const158 void CppServiceStubCodeEmitter::EmitStubStaticMethodDecl(
159     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
160 {
161     sb.Append(prefix).AppendFormat(
162         "static int32_t %s%s%s_(MessageParcel& %s, MessageParcel& %s, MessageOption& %s, sptr<%s> impl);\n",
163         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
164         dataParcelName_.c_str(), replyParcelName_.c_str(),
165         optionName_.c_str(), EmitDefinitionByInterface(interface_, interfaceName_).c_str());
166 }
167 
EmitStubPrivateData(StringBuilder & sb,const std::string & prefix) const168 void CppServiceStubCodeEmitter::EmitStubPrivateData(StringBuilder &sb, const std::string &prefix) const
169 {
170     sb.Append(prefix).AppendFormat("static inline ObjectDelegator<%s, %s> objDelegator_;\n",
171         EmitDefinitionByInterface(interface_, stubName_).c_str(),
172         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
173     sb.Append(prefix).AppendFormat("sptr<%s> impl_;\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
174 }
175 
EmitStubSourceFile()176 void CppServiceStubCodeEmitter::EmitStubSourceFile()
177 {
178     std::string filePath =
179         File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(stubName_).c_str()));
180     File file(filePath, File::WRITE);
181     StringBuilder sb;
182 
183     EmitLicense(sb);
184     EmitStubSourceInclusions(sb);
185     sb.Append("\n");
186     EmitLogTagMacro(sb, FileName(stubName_));
187     sb.Append("\n");
188     EmitBeginNamespace(sb);
189     UtilMethodMap utilMethods;
190     GetUtilMethods(utilMethods);
191     EmitUtilMethods(sb, "", utilMethods, true);
192     sb.Append("\n");
193     EmitUtilMethods(sb, "", utilMethods, false);
194     sb.Append("\n");
195     EmitInterfaceGetMethodImpl(sb, "");
196     sb.Append("\n");
197     EmitStubConstructorImpl(sb, "");
198     sb.Append("\n");
199     EmitStubOnRequestMethodImpl(sb, "");
200     sb.Append("\n");
201     EmitStubMethodImpls(sb, "");
202     EmitEndNamespace(sb);
203 
204     std::string data = sb.ToString();
205     file.WriteData(data.c_str(), data.size());
206     file.Flush();
207     file.Close();
208 }
209 
EmitStubSourceInclusions(StringBuilder & sb)210 void CppServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder &sb)
211 {
212     HeaderFile::HeaderFileSet headerFiles;
213     headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(stubName_));
214     GetSourceOtherLibInclusions(headerFiles);
215     GetSourceOtherFileInclusions(headerFiles);
216 
217     for (const auto &file : headerFiles) {
218         sb.AppendFormat("%s\n", file.ToString().c_str());
219     }
220 }
221 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const222 void CppServiceStubCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
223 {
224     if (!interface_->IsSerializable()) {
225         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
226         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
227         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
228     } else {
229         const AST::TypeStringMap &types = ast_->GetTypes();
230         for (const auto &pair : types) {
231             AutoPtr<ASTType> type = pair.second;
232             if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
233                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
234                 break;
235             }
236         }
237     }
238 
239     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
240         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
241             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
242             AutoPtr<ASTType> paramType = param->GetType();
243             if (param->GetAttribute() == ParamAttr::PARAM_IN &&
244                 (param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
245                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iproxy_broker");
246             }
247 
248             if (param->GetAttribute() == ParamAttr::PARAM_OUT &&
249                 (param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
250                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
251             }
252         }
253     }
254 
255     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
256     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
257 }
258 
GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet & headerFiles) const259 void CppServiceStubCodeEmitter::GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet &headerFiles) const
260 {
261     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
262         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
263             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
264             AutoPtr<ASTType> paramType = param->GetType();
265             if (param->GetAttribute() == ParamAttr::PARAM_IN &&
266                 (param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
267                 AutoPtr<ASTInterfaceType> type = dynamic_cast<ASTInterfaceType *>(paramType.Get());
268                 std::string FileName = InterfaceToFilePath(paramType->ToString());
269                 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, FileName);
270             }
271         }
272     }
273 }
274 
EmitInterfaceGetMethodImpl(StringBuilder & sb,const std::string & prefix) const275 void CppServiceStubCodeEmitter::EmitInterfaceGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
276 {
277     if (!interface_->IsSerializable()) {
278         EmitGetMethodImpl(sb, prefix);
279         sb.Append(prefix).Append("\n");
280         EmitGetInstanceMethodImpl(sb, prefix);
281         sb.Append(prefix).Append("\n");
282     }
283 }
284 
EmitGetMethodImpl(StringBuilder & sb,const std::string & prefix) const285 void CppServiceStubCodeEmitter::EmitGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
286 {
287     sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(bool isStub)\n",
288         EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
289         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
290     sb.Append(prefix).Append("{\n");
291     sb.Append(prefix + TAB).AppendFormat("return %s::Get(\"%s\", isStub);\n",
292         EmitDefinitionByInterface(interface_, interfaceName_).c_str(), FileName(implName_).c_str());
293     sb.Append(prefix).Append("}\n");
294 }
295 
EmitGetInstanceMethodImpl(StringBuilder & sb,const std::string & prefix) const296 void CppServiceStubCodeEmitter::EmitGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix) const
297 {
298     sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(const std::string& serviceName, bool isStub)\n",
299         EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
300         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
301     sb.Append(prefix).Append("{\n");
302 
303     sb.Append(prefix + TAB).Append("if (!isStub) {\n");
304     sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
305     sb.Append(prefix + TAB).Append("}\n");
306 
307     sb.Append(prefix + TAB).AppendFormat("std::string desc = Str16ToStr8(%s::GetDescriptor());\n",
308         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
309     sb.Append(prefix + TAB).Append("void *impl = LoadHdiImpl(desc.c_str(), ");
310     sb.AppendFormat("serviceName == \"%s\" ? \"service\" : serviceName.c_str());\n", FileName(implName_).c_str());
311     sb.Append(prefix + TAB).Append("if (impl == nullptr) {\n");
312     sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"failed to load hdi impl %{public}s\", desc.c_str());\n");
313     sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
314     sb.Append(prefix + TAB).Append("}\n");
315     sb.Append(prefix + TAB).AppendFormat("return reinterpret_cast<%s *>(impl);\n",
316         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
317     sb.Append(prefix).Append("}\n");
318 }
319 
EmitStubConstructorImpl(StringBuilder & sb,const std::string & prefix) const320 void CppServiceStubCodeEmitter::EmitStubConstructorImpl(StringBuilder &sb, const std::string &prefix) const
321 {
322     sb.Append(prefix).AppendFormat("%s::%s(const sptr<%s> &impl)\n",
323         EmitDefinitionByInterface(interface_, stubName_).c_str(), stubName_.c_str(),
324         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
325     sb.Append(prefix + TAB).AppendFormat(": IPCObjectStub(%s::GetDescriptor()), impl_(impl)\n",
326         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
327     sb.Append(prefix).Append("{\n");
328     sb.Append(prefix).Append("}\n\n");
329 
330     sb.Append(prefix).AppendFormat(
331         "%s::~%s()\n", EmitDefinitionByInterface(interface_, stubName_).c_str(), stubName_.c_str());
332     sb.Append(prefix).Append("{\n");
333     sb.Append(prefix + TAB).Append("HDF_LOGI(\"%{public}s enter\", __func__);\n");
334     sb.Append(prefix + TAB).Append("ObjectCollector::GetInstance().RemoveObject(impl_);\n");
335     sb.Append(prefix).Append("}\n");
336 }
337 
EmitStubOnRequestMethodImpl(StringBuilder & sb,const std::string & prefix)338 void CppServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix)
339 {
340     sb.Append(prefix).AppendFormat(
341         "int32_t %s::OnRemoteRequest(uint32_t code, ", EmitDefinitionByInterface(interface_, stubName_).c_str());
342     sb.Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n");
343     sb.Append(prefix).Append("{\n");
344 
345     sb.Append(prefix + TAB).Append("switch (code) {\n");
346     AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
347     sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).c_str());
348     sb.Append(prefix + TAB + TAB + TAB)
349         .AppendFormat("return %sStub%s%s(data, reply, option);\n",
350         baseName_.c_str(), getVerMethod->GetName().c_str(), getVerMethod->GetMethodIdentifier().c_str());
351     AutoPtr<ASTInterfaceType> interface = interface_;
352     while (interface != nullptr) {
353         for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
354             sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(method).c_str());
355             sb.Append(prefix + TAB + TAB + TAB)
356                 .AppendFormat("return %sStub%s%s(data, reply, option);\n",
357                 baseName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str());
358         }
359         interface = interface->GetExtendsInterface();
360     }
361 
362     sb.Append(prefix + TAB + TAB).Append("default: {\n");
363     sb.Append(prefix + TAB + TAB + TAB)
364         .Append("HDF_LOGE(\"%{public}s: cmd %{public}d is not supported\", __func__, code);\n");
365     sb.Append(prefix + TAB + TAB + TAB).Append("return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n");
366     sb.Append(prefix + TAB + TAB).Append("}\n");
367     sb.Append(prefix + TAB).Append("}\n");
368     sb.Append("}\n");
369 }
370 
EmitStubMethodImpls(StringBuilder & sb,const std::string & prefix) const371 void CppServiceStubCodeEmitter::EmitStubMethodImpls(StringBuilder &sb, const std::string &prefix) const
372 {
373     AutoPtr<ASTInterfaceType> interface = interface_;
374     AutoPtr<ASTInterfaceType> mataInterface = interface_;
375     while (interface != nullptr) {
376         for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
377             EmitStubMethodImpl(interface, method, sb, prefix);
378             sb.Append("\n");
379         }
380         interface = interface->GetExtendsInterface();
381         if (interface != nullptr) {
382             mataInterface = interface;
383         }
384     }
385     AutoPtr<ASTMethod> verMethod = interface_->GetVersionMethod();
386     EmitStubMethodImpl(mataInterface, verMethod, sb, prefix);
387     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
388         sb.Append("\n");
389         EmitStubStaticMethodImpl(method, sb, prefix);
390     }
391     if (interface_->GetExtendsInterface() == nullptr) {
392         sb.Append("\n");
393         EmitStubStaticMethodImpl(verMethod, sb, prefix);
394     }
395 }
396 
EmitStubMethodImpl(AutoPtr<ASTInterfaceType> interface,const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const397 void CppServiceStubCodeEmitter::EmitStubMethodImpl(AutoPtr<ASTInterfaceType> interface,
398     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
399 {
400     sb.Append(prefix).AppendFormat("int32_t %s::%s%s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s)\n",
401         EmitDefinitionByInterface(interface_, stubName_).c_str(),
402         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
403         dataParcelName_.c_str(), replyParcelName_.c_str(), optionName_.c_str());
404     sb.Append(prefix).Append("{\n");
405     sb.Append(prefix + TAB).AppendFormat("return %s::%s%s%s_(%s, %s, %s, impl_);\n",
406         EmitDefinitionByInterface(interface, stubName_).c_str(),
407         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
408         dataParcelName_.c_str(), replyParcelName_.c_str(),
409         optionName_.c_str());
410     sb.Append("}\n");
411 }
412 
EmitStubStaticMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const413 void CppServiceStubCodeEmitter::EmitStubStaticMethodImpl(
414     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
415 {
416     sb.Append(prefix).AppendFormat(
417         "int32_t %s::%s%s%s_(MessageParcel& %s, MessageParcel& %s, MessageOption& %s, sptr<%s> impl)\n",
418         EmitDefinitionByInterface(interface_, stubName_).c_str(),
419         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
420         dataParcelName_.c_str(), replyParcelName_.c_str(), optionName_.c_str(),
421         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
422     sb.Append(prefix).Append("{\n");
423 
424     // read interface token and check it
425     EmitStubReadInterfaceToken(dataParcelName_, sb, prefix + TAB);
426     sb.Append("\n");
427 
428     EmitStubReadMemFlag(method, dataParcelName_, sb, prefix + TAB);
429 
430     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
431         AutoPtr<ASTParameter> param = method->GetParameter(i);
432         if (param->GetAttribute() == ParamAttr::PARAM_IN) {
433             EmitReadMethodParameter(param, dataParcelName_, true, sb, prefix + TAB);
434             sb.Append("\n");
435         } else {
436             EmitLocalVariable(param, dataParcelName_, sb, prefix + TAB);
437             sb.Append("\n");
438         }
439     }
440 
441     EmitStubCallMethod(method, sb, prefix + TAB);
442     sb.Append("\n");
443 
444     if (!method->IsOneWay()) {
445         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
446             AutoPtr<ASTParameter> param = method->GetParameter(i);
447             if (param->GetAttribute() == ParamAttr::PARAM_OUT) {
448                 EmitWriteMethodParameter(param, replyParcelName_, sb, prefix + TAB);
449                 sb.Append("\n");
450             }
451         }
452     }
453 
454     sb.Append(prefix + TAB).AppendFormat("return %s;\n", errorCodeName_.c_str());
455     sb.Append("}\n");
456 }
457 
EmitStubCallMethod(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const458 void CppServiceStubCodeEmitter::EmitStubCallMethod(
459     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
460 {
461     sb.Append(prefix).Append("if (impl == nullptr) {\n");
462     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: impl is nullptr!\", __func__);\n");
463     sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
464     sb.Append(prefix).Append("}\n\n");
465 
466     sb.Append(prefix).AppendFormat("int32_t %s = impl->%s(", errorCodeName_.c_str(), method->GetName().c_str());
467     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
468         AutoPtr<ASTParameter> param = method->GetParameter(i);
469         sb.Append(param->GetName());
470         if (i + 1 < method->GetParameterNumber()) {
471             sb.Append(", ");
472         }
473     }
474     sb.Append(");\n");
475 
476     sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.c_str());
477     sb.Append(prefix + TAB)
478         .AppendFormat("HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n",
479         errorCodeName_.c_str());
480     sb.Append(prefix + TAB).AppendFormat("return %s;\n", errorCodeName_.c_str());
481     sb.Append(prefix).Append("}\n");
482 }
483 
EmitStubReadInterfaceToken(const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const484 void CppServiceStubCodeEmitter::EmitStubReadInterfaceToken(
485     const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
486 {
487     sb.Append(prefix).AppendFormat("if (%s.ReadInterfaceToken() != %s::GetDescriptor()) {\n", parcelName.c_str(),
488         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
489     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: interface token check failed!\", __func__);\n");
490     sb.Append(prefix + TAB).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
491     sb.Append(prefix).Append("}\n");
492 }
493 
EmitStubReadMemFlag(const AutoPtr<ASTMethod> & method,const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const494 void CppServiceStubCodeEmitter::EmitStubReadMemFlag(const AutoPtr<ASTMethod> &method,
495     const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
496 {
497     if (NeedFlag(method)) {
498         sb.Append(prefix).AppendFormat("bool %s = false;\n", flagOfSetMemName_.c_str());
499         sb.Append(prefix).AppendFormat("if (!%s.ReadBool(%s)) {\n", parcelName.c_str(), flagOfSetMemName_.c_str());
500         sb.Append(prefix + TAB)
501             .AppendFormat("HDF_LOGE(\"%%{public}s: failed to read %s\", __func__);\n", flagOfSetMemName_.c_str());
502         sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
503         sb.Append(prefix).Append("}\n");
504     }
505 }
506 
EmitLocalVariable(const AutoPtr<ASTParameter> & param,const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const507 void CppServiceStubCodeEmitter::EmitLocalVariable(const AutoPtr<ASTParameter> &param,
508     const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
509 {
510     sb.Append(prefix).Append(param->EmitCppLocalVar()).Append("\n");
511     AutoPtr<ASTType> type = param->GetType();
512     if (!type->IsStringType() && !type->IsArrayType() && !type->IsListType()) {
513         return;
514     }
515 
516     sb.Append(prefix).AppendFormat("if (%s) {\n", flagOfSetMemName_.c_str());
517     std::string capacityName = "capacity";
518     sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", capacityName.c_str());
519     sb.Append(prefix + TAB).AppendFormat("if (!%s.ReadUint32(%s)) {\n", parcelName.c_str(), capacityName.c_str());
520     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to read %s\", __func__);\n",
521         capacityName.c_str());
522     sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
523     sb.Append(prefix + TAB).Append("}\n");
524 
525     if (type->IsStringType()) {
526         sb.Append(prefix + TAB).AppendFormat("%s(%s, >, %s / sizeof(char), HDF_ERR_INVALID_PARAM);\n",
527             CHECK_VALUE_RETURN_MACRO, capacityName.c_str(), MAX_BUFF_SIZE_MACRO);
528     } else {
529         AutoPtr<ASTArrayType> arrayType = dynamic_cast<ASTArrayType *>(type.Get());
530         sb.Append(prefix + TAB).AppendFormat("%s(%s, >, %s / sizeof(%s), HDF_ERR_INVALID_PARAM);\n",
531             CHECK_VALUE_RETURN_MACRO, capacityName.c_str(), MAX_BUFF_SIZE_MACRO,
532             arrayType->GetElementType()->EmitCppType().c_str());
533     }
534     sb.Append(prefix + TAB).AppendFormat("%s.reserve(%s);\n", param->GetName().c_str(), capacityName.c_str());
535     sb.Append(prefix).Append("}\n");
536 }
537 
GetUtilMethods(UtilMethodMap & methods)538 void CppServiceStubCodeEmitter::GetUtilMethods(UtilMethodMap &methods)
539 {
540     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
541         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
542             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
543             AutoPtr<ASTType> paramType = param->GetType();
544             if (param->GetAttribute() == ParamAttr::PARAM_IN) {
545                 paramType->RegisterReadMethod(Options::GetInstance().GetLanguage(), SerMode::STUB_SER, methods);
546             } else {
547                 paramType->RegisterWriteMethod(Options::GetInstance().GetLanguage(), SerMode::STUB_SER, methods);
548             }
549         }
550     }
551 }
552 } // namespace HDI
553 } // namespace OHOS
554