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