• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "cpp_service_stub_code_emitter.h"
17 #include "util/file.h"
18 #include "util/logger.h"
19 
20 namespace OHOS {
21 namespace Idl {
ResolveDirectory(const std::string & targetDirectory)22 bool CppServiceStubCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
23 {
24     if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
25         directory_ = GetFileParentPath(targetDirectory);
26     } else {
27         return false;
28     }
29 
30     if (!File::CreateParentDir(directory_)) {
31         Logger::E("CppServiceStubCodeEmitter", "Create '%s' failed!", directory_.c_str());
32         return false;
33     }
34 
35     return true;
36 }
37 
EmitCode()38 void CppServiceStubCodeEmitter::EmitCode()
39 {
40     if (mode_ == GenMode::IPC) {
41         EmitStubHeaderFile();
42         EmitStubSourceFile();
43     }
44 }
45 
EmitStubHeaderFile()46 void CppServiceStubCodeEmitter::EmitStubHeaderFile()
47 {
48     std::string filePath =
49         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(stubName_).c_str()));
50     File file(filePath, File::WRITE);
51     StringBuilder sb;
52 
53     EmitLicense(sb);
54     EmitHeadMacro(sb, stubFullName_);
55     sb.Append("\n");
56     EmitStubHeaderInclusions(sb);
57     sb.Append("\n");
58     EmitStubDecl(sb);
59     sb.Append("\n");
60     EmitTailMacro(sb, stubFullName_);
61 
62     std::string data = sb.ToString();
63     file.WriteData(data.c_str(), data.size());
64     file.Flush();
65     file.Close();
66 }
67 
EmitStubHeaderInclusions(StringBuilder & sb)68 void CppServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder &sb)
69 {
70     HeaderFile::HeaderFileSet headerFiles;
71 
72     headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
73     if (interface_->GetExtendsInterface() != nullptr) {
74         headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE,
75             EmitHeaderNameByInterface(interface_->GetExtendsInterface(), stubName_));
76     }
77     GetHeaderOtherLibInclusions(headerFiles);
78 
79     for (const auto &file : headerFiles) {
80         sb.AppendFormat("%s\n", file.ToString().c_str());
81     }
82 }
83 
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const84 void CppServiceStubCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
85 {
86     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
87     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option");
88     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "ipc_object_stub");
89     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
90     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "refbase");
91 }
92 
EmitStubDecl(StringBuilder & sb)93 void CppServiceStubCodeEmitter::EmitStubDecl(StringBuilder &sb)
94 {
95     EmitBeginNamespace(sb);
96     sb.Append("\n");
97     EmitStubUsingNamespace(sb);
98     sb.AppendFormat("class %s : public IPCObjectStub {\n", stubName_.c_str());
99     EmitStubBody(sb, TAB);
100     sb.Append("};\n");
101     EmitEndNamespace(sb);
102 }
103 
EmitStubUsingNamespace(StringBuilder & sb) const104 void CppServiceStubCodeEmitter::EmitStubUsingNamespace(StringBuilder &sb) const
105 {
106     sb.Append("using namespace OHOS;\n");
107 }
108 
EmitStubBody(StringBuilder & sb,const std::string & prefix) const109 void CppServiceStubCodeEmitter::EmitStubBody(StringBuilder &sb, const std::string &prefix) const
110 {
111     sb.Append("public:\n");
112     EmitStubConstructorDecl(sb, prefix);
113     sb.Append("\n");
114     EmitStubOnRequestDecl(sb, prefix);
115     sb.Append("\n");
116     EmitStubMethodDecls(sb, prefix);
117     sb.Append("\n");
118     EmitStubPrivateData(sb, prefix);
119 }
120 
EmitStubConstructorDecl(StringBuilder & sb,const std::string & prefix) const121 void CppServiceStubCodeEmitter::EmitStubConstructorDecl(StringBuilder &sb, const std::string &prefix) const
122 {
123     sb.Append(prefix).AppendFormat("explicit %s(const sptr<%s> &impl);\n", stubName_.c_str(), interfaceName_.c_str());
124     sb.Append(prefix).AppendFormat("virtual ~%s();\n", stubName_.c_str());
125 }
126 
EmitStubOnRequestDecl(StringBuilder & sb,const std::string & prefix) const127 void CppServiceStubCodeEmitter::EmitStubOnRequestDecl(StringBuilder &sb, const std::string &prefix) const
128 {
129     sb.Append(prefix).Append("int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, ");
130     sb.Append("MessageOption &option) override;\n");
131 }
132 
EmitStubMethodDecls(StringBuilder & sb,const std::string & prefix) const133 void CppServiceStubCodeEmitter::EmitStubMethodDecls(StringBuilder &sb, const std::string &prefix) const
134 {
135     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
136         EmitStubStaticMethodDecl(method, sb, prefix);
137         sb.Append("\n");
138     }
139     if (interface_->GetExtendsInterface() == nullptr) {
140         EmitStubStaticMethodDecl(interface_->GetVersionMethod(), sb, prefix);
141         sb.Append("\n");
142     }
143 
144     sb.Append("private:\n");
145     AutoPtr<ASTInterfaceType> interface = interface_;
146     while (interface != nullptr) {
147         for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
148             EmitStubMethodDecl(method, sb, prefix);
149             sb.Append("\n");
150         }
151         interface = interface->GetExtendsInterface();
152     }
153     EmitStubMethodDecl(interface_->GetVersionMethod(), sb, prefix);
154     sb.Append("\n");
155 }
156 
EmitStubMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const157 void CppServiceStubCodeEmitter::EmitStubMethodDecl(
158     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
159 {
160     sb.Append(prefix).AppendFormat("int32_t %s%s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s);\n",
161         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
162         HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(), optionName_.c_str());
163 }
164 
EmitStubStaticMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const165 void CppServiceStubCodeEmitter::EmitStubStaticMethodDecl(
166     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
167 {
168     sb.Append(prefix).AppendFormat(
169         "static int32_t %s%s%s_(MessageParcel& %s, MessageParcel& %s, MessageOption& %s, sptr<%s> impl);\n",
170         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
171         HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(),
172         optionName_.c_str(), EmitDefinitionByInterface(interface_, interfaceName_).c_str());
173 }
174 
EmitStubPrivateData(StringBuilder & sb,const std::string & prefix) const175 void CppServiceStubCodeEmitter::EmitStubPrivateData(StringBuilder &sb, const std::string &prefix) const
176 {
177     sb.Append(prefix).AppendFormat("static inline ObjectDelegator<%s, %s> objDelegator_;\n",
178         EmitDefinitionByInterface(interface_, stubName_).c_str(),
179         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
180     sb.Append(prefix).AppendFormat("sptr<%s> impl_;\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
181 }
182 
EmitStubSourceFile()183 void CppServiceStubCodeEmitter::EmitStubSourceFile()
184 {
185     std::string filePath =
186         File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(stubName_).c_str()));
187     File file(filePath, File::WRITE);
188     StringBuilder sb;
189 
190     EmitLicense(sb);
191     EmitStubSourceInclusions(sb);
192     sb.Append("\n");
193     EmitLogTagMacro(sb, FileName(stubName_));
194     sb.Append("\n");
195     EmitBeginNamespace(sb);
196     EmitUtilMethods(sb, true);
197     sb.Append("\n");
198     EmitUtilMethods(sb, false);
199     sb.Append("\n");
200     EmitInterfaceGetMethodImpl(sb, "");
201     sb.Append("\n");
202     EmitStubConstructorImpl(sb, "");
203     sb.Append("\n");
204     EmitStubOnRequestMethodImpl(sb, "");
205     sb.Append("\n");
206     EmitStubMethodImpls(sb, "");
207     EmitEndNamespace(sb);
208 
209     std::string data = sb.ToString();
210     file.WriteData(data.c_str(), data.size());
211     file.Flush();
212     file.Close();
213 }
214 
EmitStubSourceInclusions(StringBuilder & sb)215 void CppServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder &sb)
216 {
217     HeaderFile::HeaderFileSet headerFiles;
218     headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(stubName_));
219     GetSourceOtherLibInclusions(headerFiles);
220     GetSourceOtherFileInclusions(headerFiles);
221 
222     for (const auto &file : headerFiles) {
223         sb.AppendFormat("%s\n", file.ToString().c_str());
224     }
225 }
226 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const227 void CppServiceStubCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
228 {
229     if (!interface_->IsSerializable()) {
230         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
231         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
232         headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
233     } else {
234         const AST::TypeStringMap &types = ast_->GetTypes();
235         for (const auto &pair : types) {
236             AutoPtr<ASTType> type = pair.second;
237             if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
238                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
239                 break;
240             }
241         }
242     }
243 
244     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
245         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
246             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
247             AutoPtr<ASTType> paramType = param->GetType();
248             if ((param->GetAttribute() == ASTParamAttr::PARAM_IN) &&
249                 (param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
250                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iproxy_broker");
251             }
252 
253             if ((param->GetAttribute() == ASTParamAttr::PARAM_OUT) &&
254                 (param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
255                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
256             }
257         }
258     }
259 
260     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
261     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
262 }
263 
GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet & headerFiles) const264 void CppServiceStubCodeEmitter::GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet &headerFiles) const
265 {
266     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
267         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
268             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
269             AutoPtr<ASTType> paramType = param->GetType();
270             if ((param->GetAttribute() == ASTParamAttr::PARAM_IN) &&
271                 (param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
272                 AutoPtr<ASTInterfaceType> type = static_cast<ASTInterfaceType *>(paramType.Get());
273                 std::string FileName = InterfaceToFilePath(paramType->ToString());
274                 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, FileName);
275             }
276         }
277     }
278 }
279 
EmitInterfaceGetMethodImpl(StringBuilder & sb,const std::string & prefix) const280 void CppServiceStubCodeEmitter::EmitInterfaceGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
281 {
282     if (!interface_->IsSerializable()) {
283         EmitGetMethodImpl(sb, prefix);
284         sb.Append(prefix).Append("\n");
285         EmitGetInstanceMethodImpl(sb, prefix);
286         sb.Append(prefix).Append("\n");
287     }
288 }
289 
EmitGetMethodImpl(StringBuilder & sb,const std::string & prefix) const290 void CppServiceStubCodeEmitter::EmitGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
291 {
292     sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(bool isStub)\n",
293         EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
294         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
295     sb.Append(prefix).Append("{\n");
296     sb.Append(prefix + TAB).AppendFormat("return %s::Get(\"%s\", isStub);\n",
297         EmitDefinitionByInterface(interface_, interfaceName_).c_str(), FileName(implName_).c_str());
298     sb.Append(prefix).Append("}\n");
299 }
300 
EmitGetInstanceMethodImpl(StringBuilder & sb,const std::string & prefix) const301 void CppServiceStubCodeEmitter::EmitGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix) const
302 {
303     sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(const std::string& serviceName, bool isStub)\n",
304         EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
305         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
306     sb.Append(prefix).Append("{\n");
307 
308     sb.Append(prefix + TAB).Append("if (!isStub) {\n");
309     sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
310     sb.Append(prefix + TAB).Append("}\n");
311 
312     sb.Append(prefix + TAB).AppendFormat("std::string desc = Str16ToStr8(%s::GetDescriptor());\n",
313         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
314     sb.Append(prefix + TAB).Append("void *impl = LoadHdiImpl(desc.c_str(), ");
315     sb.AppendFormat("serviceName == \"%s\" ? \"service\" : serviceName.c_str());\n", FileName(implName_).c_str());
316     sb.Append(prefix + TAB).Append("if (impl == nullptr) {\n");
317     sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"failed to load hdi impl %{public}s\", desc.c_str());\n");
318     sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
319     sb.Append(prefix + TAB).Append("}\n");
320     sb.Append(prefix + TAB).AppendFormat("return reinterpret_cast<%s *>(impl);\n",
321         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
322     sb.Append(prefix).Append("}\n");
323 }
324 
EmitStubConstructorImpl(StringBuilder & sb,const std::string & prefix) const325 void CppServiceStubCodeEmitter::EmitStubConstructorImpl(StringBuilder &sb, const std::string &prefix) const
326 {
327     sb.Append(prefix).AppendFormat("%s::%s(const sptr<%s> &impl)\n",
328         EmitDefinitionByInterface(interface_, stubName_).c_str(), stubName_.c_str(),
329         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
330     sb.Append(prefix + TAB).AppendFormat(": IPCObjectStub(%s::GetDescriptor()), impl_(impl)\n",
331         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
332     sb.Append(prefix).Append("{\n");
333     sb.Append(prefix).Append("}\n\n");
334 
335     sb.Append(prefix).AppendFormat(
336         "%s::~%s()\n", EmitDefinitionByInterface(interface_, stubName_).c_str(), stubName_.c_str());
337     sb.Append(prefix).Append("{\n");
338     sb.Append(prefix + TAB).Append("HDF_LOGI(\"%{public}s enter\", __func__);\n");
339     sb.Append(prefix + TAB).Append("ObjectCollector::GetInstance().RemoveObject(impl_);\n");
340     sb.Append(prefix).Append("}\n");
341 }
342 
EmitStubOnRequestMethodImpl(StringBuilder & sb,const std::string & prefix)343 void CppServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix)
344 {
345     sb.Append(prefix).AppendFormat(
346         "int32_t %s::OnRemoteRequest(uint32_t code, ", EmitDefinitionByInterface(interface_, stubName_).c_str());
347     sb.Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n");
348     sb.Append(prefix).Append("{\n");
349 
350     sb.Append(prefix + TAB).Append("switch (code) {\n");
351     AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
352     sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).c_str());
353     sb.Append(prefix + TAB + TAB + TAB)
354         .AppendFormat("return %sStub%s%s(data, reply, option);\n",
355         baseName_.c_str(), getVerMethod->GetName().c_str(), getVerMethod->GetMethodIdentifier().c_str());
356     AutoPtr<ASTInterfaceType> interface = interface_;
357     while (interface != nullptr) {
358         for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
359             sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(method).c_str());
360             sb.Append(prefix + TAB + TAB + TAB)
361                 .AppendFormat("return %sStub%s%s(data, reply, option);\n",
362                 baseName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str());
363         }
364         interface = interface->GetExtendsInterface();
365     }
366 
367     sb.Append(prefix + TAB + TAB).Append("default: {\n");
368     sb.Append(prefix + TAB + TAB + TAB)
369         .Append("HDF_LOGE(\"%{public}s: cmd %{public}d is not supported\", __func__, code);\n");
370     sb.Append(prefix + TAB + TAB + TAB).Append("return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n");
371     sb.Append(prefix + TAB + TAB).Append("}\n");
372     sb.Append(prefix + TAB).Append("}\n");
373     sb.Append("}\n");
374 }
375 
EmitStubMethodImpls(StringBuilder & sb,const std::string & prefix) const376 void CppServiceStubCodeEmitter::EmitStubMethodImpls(StringBuilder &sb, const std::string &prefix) const
377 {
378     AutoPtr<ASTInterfaceType> interface = interface_;
379     AutoPtr<ASTInterfaceType> mataInterface = interface_;
380     while (interface != nullptr) {
381         for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
382             EmitStubMethodImpl(interface, method, sb, prefix);
383             sb.Append("\n");
384         }
385         interface = interface->GetExtendsInterface();
386         if (interface != nullptr) {
387             mataInterface = interface;
388         }
389     }
390     AutoPtr<ASTMethod> verMethod = interface_->GetVersionMethod();
391     EmitStubMethodImpl(mataInterface, verMethod, sb, prefix);
392     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
393         sb.Append("\n");
394         EmitStubStaticMethodImpl(method, sb, prefix);
395     }
396     if (interface_->GetExtendsInterface() == nullptr) {
397         sb.Append("\n");
398         EmitStubStaticMethodImpl(verMethod, sb, prefix);
399     }
400     return;
401 }
402 
EmitStubMethodImpl(AutoPtr<ASTInterfaceType> interface,const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const403 void CppServiceStubCodeEmitter::EmitStubMethodImpl(AutoPtr<ASTInterfaceType> interface,
404     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
405 {
406     sb.Append(prefix).AppendFormat("int32_t %s::%s%s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s)\n",
407         EmitDefinitionByInterface(interface_, stubName_).c_str(),
408         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
409         HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(), optionName_.c_str());
410     sb.Append(prefix).Append("{\n");
411     sb.Append(prefix + TAB).AppendFormat("return %s::%s%s%s_(%s, %s, %s, impl_);\n",
412         EmitDefinitionByInterface(interface, stubName_).c_str(),
413         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
414         HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(),
415         optionName_.c_str());
416     sb.Append("}\n");
417 }
418 
EmitStubStaticMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const419 void CppServiceStubCodeEmitter::EmitStubStaticMethodImpl(
420     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
421 {
422     sb.Append(prefix).AppendFormat(
423         "int32_t %s::%s%s%s_(MessageParcel& %s, MessageParcel& %s, MessageOption& %s, sptr<%s> impl)\n",
424         EmitDefinitionByInterface(interface_, stubName_).c_str(),
425         stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
426         HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(), optionName_.c_str(),
427         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
428     sb.Append(prefix).Append("{\n");
429 
430     // read interface token and check it
431     EmitStubReadInterfaceToken(HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
432     sb.Append("\n");
433 
434     EmitStubReadMemFlag(method, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
435 
436     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
437         AutoPtr<ASTParameter> param = method->GetParameter(i);
438         if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
439             EmitReadMethodParameter(param, TypeMode::PARAM_IN, sb, prefix + TAB);
440             sb.Append("\n");
441         } else {
442             EmitLocalVariable(param, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
443             sb.Append("\n");
444         }
445     }
446 
447     EmitStubCallMethod(method, sb, prefix + TAB);
448     sb.Append("\n");
449 
450     if (!method->IsOneWay()) {
451         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
452             AutoPtr<ASTParameter> param = method->GetParameter(i);
453             if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
454                 EmitWriteMethodParameter(param, HdiTypeEmitter::replyParcelName_, sb, prefix + TAB);
455                 sb.Append("\n");
456             }
457         }
458     }
459 
460     sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
461     sb.Append("}\n");
462 }
463 
EmitStubCallMethod(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const464 void CppServiceStubCodeEmitter::EmitStubCallMethod(
465     const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
466 {
467     sb.Append(prefix).Append("if (impl == nullptr) {\n");
468     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: impl is nullptr!\", __func__);\n");
469     sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
470     sb.Append(prefix).Append("}\n\n");
471 
472     sb.Append(prefix).AppendFormat("int32_t %s = impl->%s(", HdiTypeEmitter::errorCodeName_.c_str(),
473         method->GetName().c_str());
474     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
475         AutoPtr<ASTParameter> param = method->GetParameter(i);
476         sb.Append(param->GetName());
477         if (i + 1 < method->GetParameterNumber()) {
478             sb.Append(", ");
479         }
480     }
481     sb.Append(");\n");
482 
483     sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
484     sb.Append(prefix + TAB)
485         .AppendFormat("HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n",
486         HdiTypeEmitter::errorCodeName_.c_str());
487     sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
488     sb.Append(prefix).Append("}\n");
489 }
490 
EmitStubReadInterfaceToken(const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const491 void CppServiceStubCodeEmitter::EmitStubReadInterfaceToken(
492     const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
493 {
494     sb.Append(prefix).AppendFormat("if (%s.ReadInterfaceToken() != %s::GetDescriptor()) {\n", parcelName.c_str(),
495         EmitDefinitionByInterface(interface_, interfaceName_).c_str());
496     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: interface token check failed!\", __func__);\n");
497     sb.Append(prefix + TAB).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
498     sb.Append(prefix).Append("}\n");
499 }
500 
EmitStubReadMemFlag(const AutoPtr<ASTMethod> & method,const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const501 void CppServiceStubCodeEmitter::EmitStubReadMemFlag(const AutoPtr<ASTMethod> &method,
502     const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
503 {
504     if (NeedFlag(method)) {
505         sb.Append(prefix).AppendFormat("bool %s = false;\n", flagOfSetMemName_.c_str());
506         sb.Append(prefix).AppendFormat("if (!%s.ReadBool(%s)) {\n", parcelName.c_str(), flagOfSetMemName_.c_str());
507         sb.Append(prefix + TAB)
508             .AppendFormat("HDF_LOGE(\"%%{public}s: failed to read %s\", __func__);\n", flagOfSetMemName_.c_str());
509         sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
510         sb.Append(prefix).Append("}\n");
511     }
512 }
513 
EmitLocalVariable(const AutoPtr<ASTParameter> & param,const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const514 void CppServiceStubCodeEmitter::EmitLocalVariable(const AutoPtr<ASTParameter> &param,
515     const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
516 {
517     EmitCppLocalVar(param, sb, prefix);
518     AutoPtr<ASTType> type = param->GetType();
519     if (!type->IsStringType() && !type->IsArrayType() && !type->IsListType()) {
520         return;
521     }
522 
523     sb.Append(prefix).AppendFormat("if (%s) {\n", flagOfSetMemName_.c_str());
524     std::string capacityName = "capacity";
525     sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", capacityName.c_str());
526     sb.Append(prefix + TAB).AppendFormat("if (!%s.ReadUint32(%s)) {\n", parcelName.c_str(), capacityName.c_str());
527     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to read %s\", __func__);\n",
528         capacityName.c_str());
529     sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
530     sb.Append(prefix + TAB).Append("}\n");
531 
532     if (type->IsStringType()) {
533         sb.Append(prefix + TAB).AppendFormat("%s(%s, >, %s / sizeof(char), HDF_ERR_INVALID_PARAM);\n",
534             CHECK_VALUE_RETURN_MACRO, capacityName.c_str(), MAX_BUFF_SIZE_MACRO);
535     } else {
536         AutoPtr<ASTArrayType> arrayType = static_cast<ASTArrayType *>(type.Get());
537         sb.Append(prefix + TAB).AppendFormat("%s(%s, >, %s / sizeof(%s), HDF_ERR_INVALID_PARAM);\n",
538             CHECK_VALUE_RETURN_MACRO, capacityName.c_str(), MAX_BUFF_SIZE_MACRO,
539             GetTypeEmitter(arrayType->GetElementType())->EmitCppType().c_str());
540     }
541     sb.Append(prefix + TAB).AppendFormat("%s.reserve(%s);\n", param->GetName().c_str(), capacityName.c_str());
542     sb.Append(prefix).Append("}\n");
543 }
544 
EmitCppLocalVar(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix) const545 void CppServiceStubCodeEmitter::EmitCppLocalVar(const AutoPtr<ASTParameter> &param,
546     StringBuilder &sb, const std::string &prefix) const
547 {
548     AutoPtr<ASTType> type = param->GetType();
549     AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
550     if (typeEmitter == nullptr) {
551         return;
552     }
553     sb.Append(prefix).AppendFormat("%s %s", typeEmitter->EmitCppType(TypeMode::LOCAL_VAR).c_str(),
554         param->GetName().c_str());
555     switch (type->GetTypeKind()) {
556         case TypeKind::TYPE_BOOLEAN:
557             sb.Append(" = false");
558             break;
559         case TypeKind::TYPE_BYTE:
560         case TypeKind::TYPE_SHORT:
561         case TypeKind::TYPE_INT:
562         case TypeKind::TYPE_LONG:
563         case TypeKind::TYPE_UCHAR:
564         case TypeKind::TYPE_USHORT:
565         case TypeKind::TYPE_UINT:
566         case TypeKind::TYPE_ULONG:
567         case TypeKind::TYPE_FLOAT:
568         case TypeKind::TYPE_DOUBLE:
569             sb.Append(" = 0");
570             break;
571         case TypeKind::TYPE_FILEDESCRIPTOR:
572             sb.Append(" = -1");
573             break;
574         case TypeKind::TYPE_SEQUENCEABLE:
575             sb.Append(" = nullptr");
576             break;
577         default:
578             break;
579     }
580     sb.Append(";\n");
581 }
582 
EmitUtilMethods(StringBuilder & sb,bool isDecl)583 void CppServiceStubCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
584 {
585     UtilMethodMap methods;
586     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
587         for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
588             AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
589             AutoPtr<ASTType> paramType = param->GetType();
590             AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
591             if (typeEmitter == nullptr) {
592                 continue;
593             }
594             if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
595                 typeEmitter->EmitCppReadMethods(methods, "", "", isDecl);
596             } else {
597                 typeEmitter->EmitCppWriteMethods(methods, "", "", isDecl);
598             }
599         }
600     }
601     EmitUtilMethodMap(sb, methods);
602 }
603 } // namespace Idl
604 } // namespace OHOS
605