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> ¶m,
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