• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "codegen/cpp_code_emitter.h"
17 
18 #include "securec.h"
19 #include "util/file.h"
20 
21 namespace OHOS {
22 namespace Idl {
EmitInterface()23 void CppCodeEmitter::EmitInterface()
24 {
25     EmitInterfaceHeaderFile();
26 }
27 
EmitInterfaceHeaderFile()28 void CppCodeEmitter::EmitInterfaceHeaderFile()
29 {
30     String filePath = String::Format("%s/%s.h", directory_.string(), FileName(interfaceName_).string());
31     File file(filePath, File::WRITE);
32 
33     StringBuilder sb;
34 
35     EmitLicense(sb);
36     sb.Append("\n");
37     EmitHeadMacro(sb, interfaceFullName_);
38     sb.Append("\n");
39     EmitInterfaceInclusions(sb);
40     sb.Append("\n");
41     if (EmitInterfaceUsings(sb)) {
42         sb.Append("\n");
43     }
44     EmitInterfaceDefinition(sb);
45     EmitTailMacro(sb, interfaceFullName_);
46 
47     String data = sb.ToString();
48     file.WriteData(data.string(), data.GetLength());
49     file.Flush();
50     file.Close();
51 }
52 
EmitInterfaceInclusions(StringBuilder & sb)53 void CppCodeEmitter::EmitInterfaceInclusions(StringBuilder& sb)
54 {
55     EmitInterfaceStdlibInclusions(sb);
56     EmitInterfaceDBinderInclusions(sb);
57     EmitInterfaceSelfDefinedTypeInclusions(sb);
58 }
59 
EmitInterfaceStdlibInclusions(StringBuilder & sb)60 void CppCodeEmitter::EmitInterfaceStdlibInclusions(StringBuilder& sb)
61 {
62     bool includeString = false;
63     bool includeList = false;
64     bool includeMap = false;
65     bool includeNum = false;
66     for (int i = 0; i < metaComponent_->typeNumber_; i++) {
67         MetaType* mt = metaComponent_->types_[i];
68         switch (mt->kind_) {
69             case TypeKind::Byte: {
70                 if (!includeNum) {
71                     sb.Append("#include <cstdint>\n");
72                     includeNum = true;
73                 }
74                 break;
75             }
76             case TypeKind::String: {
77                 if (!includeString) {
78                     sb.Append("#include <string_ex.h>\n");
79                     includeString = true;
80                 }
81                 break;
82             }
83             case TypeKind::Array:
84             case TypeKind::List: {
85                 if (!includeList) {
86                     sb.Append("#include <vector>\n");
87                     includeList = true;
88                 }
89                 break;
90             }
91             case TypeKind::Map: {
92                 if (!includeMap) {
93                     sb.Append("#include <unordered_map>\n");
94                     includeMap = true;
95                 }
96                 break;
97             }
98             default:
99                 break;
100         }
101     }
102 }
103 
EmitInterfaceDBinderInclusions(StringBuilder & sb)104 void CppCodeEmitter::EmitInterfaceDBinderInclusions(StringBuilder& sb)
105 {
106     sb.Append("#include <iremote_broker.h>\n");
107     if (logOn_) {
108         sb.Append("#include \"hilog/log.h\"\n");
109     }
110 }
111 
GetFilePath(const String & fpnp)112 String CppCodeEmitter::GetFilePath(const String& fpnp)
113 {
114     int pos = fpnp.IndexOf("..");
115     if (pos == -1) {
116         return String();
117     }
118     String res = fpnp.Substring(0, pos + 1);
119     return res;
120 }
121 
GetFilePathNoPoint(const String & fpnp)122 String CppCodeEmitter::GetFilePathNoPoint(const String& fpnp)
123 {
124     int pos = fpnp.IndexOf("..");
125     if (pos == -1) {
126         return String();
127     }
128     String res = fpnp.Substring(0, pos);
129     return res;
130 }
131 
GetNamespace(const String & fpnp)132 String CppCodeEmitter::GetNamespace(const String& fpnp)
133 {
134     int pos = fpnp.IndexOf("..");
135     if (pos == -1) {
136         return fpnp;
137     }
138     String res = fpnp.Substring(pos + 2);
139     return res;
140 }
141 
EmitInterfaceSelfDefinedTypeInclusions(StringBuilder & sb)142 void CppCodeEmitter::EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb)
143 {
144     for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) {
145         MetaSequenceable* mp = metaComponent_->sequenceables_[i];
146         if (mp == nullptr) {
147             continue;
148         }
149         String filePath = GetFilePathNoPoint(String(mp->namespace_));
150         String fileName;
151         String sequenceName = mp->name_;
152         filePath.IsEmpty() ? fileName = FileName(sequenceName) : fileName = FileName(filePath);
153         sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string());
154     }
155 
156     for (int i = 0; i < metaComponent_->interfaceNumber_; i++) {
157         MetaInterface* mi = metaComponent_->interfaces_[i];
158         if (mi->external_) {
159             String filePath = GetFilePath(String(mi->namespace_));
160             String fileName = FileName(filePath + mi->name_);
161             sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string());
162         }
163     }
164 }
165 
EmitInterfaceUsings(StringBuilder & sb)166 bool CppCodeEmitter::EmitInterfaceUsings(StringBuilder& sb)
167 {
168     bool ret = false;
169     for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) {
170         MetaSequenceable* mp = metaComponent_->sequenceables_[i];
171         String np = GetNamespace(String(mp->namespace_));
172         if (np.IsEmpty()) {
173             continue;
174         }
175         String fullName = CppFullName(np + mp->name_);
176         sb.Append("using ").AppendFormat("%s;\n", fullName.string());
177         ret = true;
178     }
179 
180     for (int i = 0; i < metaComponent_->interfaceNumber_; i++) {
181         MetaInterface* mi = metaComponent_->interfaces_[i];
182         if (mi->external_) {
183             String np = GetNamespace(String(mi->namespace_));
184             if (np.IsEmpty()) {
185                 continue;
186             }
187             String fullName = CppFullName(np + mi->name_);
188             sb.Append("using ").AppendFormat("%s;\n", fullName.string());
189             ret = true;
190         }
191     }
192     return ret;
193 }
194 
EmitInterfaceDefinition(StringBuilder & sb)195 void CppCodeEmitter::EmitInterfaceDefinition(StringBuilder& sb)
196 {
197     EmitBeginNamespace(sb);
198     sb.AppendFormat("class %s : public IRemoteBroker {\n", metaInterface_->name_);
199     sb.Append("public:\n");
200     EmitInterfaceBody(sb, TAB);
201     EmitInterfaceMemberVariables(sb, TAB);
202     sb.Append("};\n");
203     EmitEndNamespace(sb);
204 }
205 
EmitInterfaceBody(StringBuilder & sb,const String & prefix)206 void CppCodeEmitter::EmitInterfaceBody(StringBuilder& sb, const String& prefix)
207 {
208     String nameWithoutPath = GetNamespace(interfaceFullName_);
209     sb.Append(TAB).AppendFormat("DECLARE_INTERFACE_DESCRIPTOR(u\"%s\");\n", nameWithoutPath.string());
210     sb.Append("\n");
211     EmitInterfaceMethods(sb, TAB);
212 }
213 
EmitInterfaceMethods(StringBuilder & sb,const String & prefix)214 void CppCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix)
215 {
216     if (metaInterface_->methodNumber_ > 0) {
217         for (int i = 0; i < metaInterface_->methodNumber_; i++) {
218             MetaMethod* mm = metaInterface_->methods_[i];
219             EmitInterfaceMethod(mm, sb, prefix);
220             if (i != metaInterface_->methodNumber_ - 1) {
221                 sb.Append("\n");
222             }
223         }
224     }
225 }
226 
EmitInterfaceMethod(MetaMethod * mm,StringBuilder & sb,const String & prefix)227 void CppCodeEmitter::EmitInterfaceMethod(MetaMethod* mm, StringBuilder& sb, const String& prefix)
228 {
229     MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
230     if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
231         sb.Append(prefix).AppendFormat("virtual ErrCode %s() = 0;\n", mm->name_);
232     } else {
233         sb.Append(prefix).AppendFormat("virtual ErrCode %s(\n", mm->name_);
234         for (int i = 0; i < mm->parameterNumber_; i++) {
235             MetaParameter* mp = mm->parameters_[i];
236             EmitInterfaceMethodParameter(mp, sb, prefix + TAB);
237             if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
238                 sb.Append(",\n");
239             }
240         }
241         if (returnType->kind_ != TypeKind::Void) {
242             EmitInterfaceMethodReturn(returnType, sb, prefix + TAB);
243         }
244         sb.Append(") = 0;\n");
245     }
246 }
247 
EmitInterfaceMethodParameter(MetaParameter * mp,StringBuilder & sb,const String & prefix)248 void CppCodeEmitter::EmitInterfaceMethodParameter(MetaParameter* mp, StringBuilder& sb, const String& prefix)
249 {
250     sb.Append(prefix);
251 
252     MetaType* mt = metaComponent_->types_[mp->typeIndex_];
253     const std::string name = mp->name_;
254     sb.AppendFormat("%s %s", EmitType(mt, mp->attributes_, false).string(), name.c_str());
255 }
256 
EmitInterfaceMethodReturn(MetaType * mt,StringBuilder & sb,const String & prefix)257 void CppCodeEmitter::EmitInterfaceMethodReturn(MetaType* mt, StringBuilder& sb, const String& prefix)
258 {
259     sb.Append(prefix).AppendFormat("%s result", EmitType(mt, ATTR_OUT, false).string());
260 }
261 
EmitInterfaceMemberVariables(StringBuilder & sb,const String & prefix)262 void CppCodeEmitter::EmitInterfaceMemberVariables(StringBuilder& sb, const String& prefix)
263 {
264     sb.Append("protected:\n");
265     if (!domainId_.IsNull() && !logTag_.IsNull()) {
266         sb.Append(prefix).AppendFormat(
267             "static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, %s, \"%s\"};\n",
268             domainId_.string(), logTag_.string());
269     }
270     sb.Append(prefix).Append("const int VECTOR_MAX_SIZE = 102400;\n");
271     sb.Append(prefix).Append("const int LIST_MAX_SIZE = 102400;\n");
272     sb.Append(prefix).Append("const int MAP_MAX_SIZE = 102400;\n");
273 }
274 
EmitInterfaceProxy()275 void CppCodeEmitter::EmitInterfaceProxy()
276 {
277     EmitInterfaceProxyHeaderFile();
278     EmitInterfaceProxyCppFile();
279 }
280 
EmitInterfaceProxyHeaderFile()281 void CppCodeEmitter::EmitInterfaceProxyHeaderFile()
282 {
283     String filePath = String::Format("%s/%s.h", directory_.string(), FileName(proxyName_).string());
284     File file(filePath, File::WRITE);
285 
286     StringBuilder sb;
287 
288     EmitLicense(sb);
289     sb.Append("\n");
290     EmitHeadMacro(sb, proxyFullName_);
291     sb.Append("\n");
292     sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string());
293     sb.Append("#include <iremote_proxy.h>\n");
294     sb.Append("\n");
295     EmitInterfaceProxyInHeaderFile(sb);
296     EmitTailMacro(sb, proxyFullName_);
297 
298     String data = sb.ToString();
299     file.WriteData(data.string(), data.GetLength());
300     file.Flush();
301     file.Close();
302 }
303 
EmitInterfaceProxyInHeaderFile(StringBuilder & sb)304 void CppCodeEmitter::EmitInterfaceProxyInHeaderFile(StringBuilder& sb)
305 {
306     EmitBeginNamespace(sb);
307     sb.AppendFormat("class %s : public IRemoteProxy<%s> {\n", proxyName_.string(), interfaceName_.string());
308     sb.Append("public:\n");
309     EmitInterfaceProxyConstructor(sb, TAB);
310     sb.Append("\n");
311     EmitInterfaceProxyMethodDecls(sb, TAB);
312     sb.Append("\n");
313     sb.Append("private:\n");
314     EmitInterfaceProxyConstants(sb, TAB);
315     sb.Append("};\n");
316     EmitEndNamespace(sb);
317 }
318 
EmitInterfaceProxyConstructor(StringBuilder & sb,const String & prefix)319 void CppCodeEmitter::EmitInterfaceProxyConstructor(StringBuilder& sb, const String& prefix)
320 {
321     sb.Append(prefix).AppendFormat("explicit %s(\n", proxyName_.string());
322     sb.Append(prefix + TAB).Append("const sptr<IRemoteObject>& remote)\n");
323     sb.Append(prefix + TAB).AppendFormat(": IRemoteProxy<%s>(remote)\n", interfaceName_.string());
324     sb.Append(prefix).Append("{}\n");
325     sb.Append("\n");
326     sb.Append(prefix).AppendFormat("virtual ~%s()\n", proxyName_.string());
327     sb.Append(prefix).Append("{}\n");
328 }
329 
EmitInterfaceProxyMethodDecls(StringBuilder & sb,const String & prefix)330 void CppCodeEmitter::EmitInterfaceProxyMethodDecls(StringBuilder& sb, const String& prefix)
331 {
332     if (metaInterface_->methodNumber_ > 0) {
333         for (int i = 0; i < metaInterface_->methodNumber_; i++) {
334             MetaMethod* mm = metaInterface_->methods_[i];
335             EmitInterfaceProxyMethodDecl(mm, sb, prefix);
336             if (i != metaInterface_->methodNumber_ - 1) {
337                 sb.Append("\n");
338             }
339         }
340     }
341 }
342 
EmitInterfaceProxyMethodDecl(MetaMethod * mm,StringBuilder & sb,const String & prefix)343 void CppCodeEmitter::EmitInterfaceProxyMethodDecl(MetaMethod* mm, StringBuilder& sb, const String& prefix)
344 {
345     MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
346     if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
347         sb.Append(prefix).AppendFormat("ErrCode %s() override;\n", mm->name_);
348     } else {
349         sb.Append(prefix).AppendFormat("ErrCode %s(\n", mm->name_);
350         for (int i = 0; i < mm->parameterNumber_; i++) {
351             MetaParameter* mp = mm->parameters_[i];
352             EmitInterfaceMethodParameter(mp, sb, prefix + TAB);
353             if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
354                 sb.Append(",\n");
355             }
356         }
357         if (returnType->kind_ != TypeKind::Void) {
358             EmitInterfaceMethodReturn(returnType, sb, prefix + TAB);
359         }
360         sb.Append(") override;\n");
361     }
362 }
363 
EmitInterfaceProxyConstants(StringBuilder & sb,const String & prefix)364 void CppCodeEmitter::EmitInterfaceProxyConstants(StringBuilder& sb, const String& prefix)
365 {
366     EmitInterfaceMethodCommands(sb, prefix);
367     sb.Append("\n");
368     sb.Append(prefix).AppendFormat("static inline BrokerDelegator<%s> delegator_;\n", proxyName_.string());
369 }
370 
EmitInterfaceProxyCppFile()371 void CppCodeEmitter::EmitInterfaceProxyCppFile()
372 {
373     String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(proxyName_).string());
374     File file(filePath, File::WRITE);
375 
376     StringBuilder sb;
377 
378     EmitLicense(sb);
379     sb.Append("\n");
380     sb.AppendFormat("#include \"%s.h\"\n", FileName(proxyName_).string());
381     if (logOn_) {
382         sb.Append("#include \"hilog/log.h\"\n");
383     }
384     if (hitraceOn_) {
385         sb.Append("#include \"hitrace_meter.h\"\n");
386     }
387     sb.Append("\n");
388     if (logOn_) {
389         sb.Append("using OHOS::HiviewDFX::HiLog;\n\n");
390     }
391     EmitBeginNamespace(sb);
392     EmitInterfaceProxyMethodImpls(sb, "");
393     EmitEndNamespace(sb);
394 
395     String data = sb.ToString();
396     file.WriteData(data.string(), data.GetLength());
397     file.Flush();
398     file.Close();
399 }
400 
EmitInterfaceProxyMethodImpls(StringBuilder & sb,const String & prefix)401 void CppCodeEmitter::EmitInterfaceProxyMethodImpls(StringBuilder& sb, const String& prefix)
402 {
403     if (metaInterface_->methodNumber_ > 0) {
404         for (int i = 0; i < metaInterface_->methodNumber_; i++) {
405             MetaMethod* mm = metaInterface_->methods_[i];
406             EmitInterfaceProxyMethodImpl(mm, sb, prefix);
407             if (i != metaInterface_->methodNumber_ - 1) {
408                 sb.Append("\n");
409             }
410         }
411     }
412 }
413 
EmitInterfaceProxyMethodImpl(MetaMethod * mm,StringBuilder & sb,const String & prefix)414 void CppCodeEmitter::EmitInterfaceProxyMethodImpl(MetaMethod* mm, StringBuilder& sb, const String& prefix)
415 {
416     MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
417     if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
418         sb.Append(prefix).AppendFormat("ErrCode %s::%s()\n", proxyName_.string(), mm->name_);
419     } else {
420         sb.Append(prefix).AppendFormat("ErrCode %s::%s(\n", proxyName_.string(), mm->name_);
421         for (int i = 0; i < mm->parameterNumber_; i++) {
422             MetaParameter* mp = mm->parameters_[i];
423             EmitInterfaceMethodParameter(mp, sb, prefix + TAB);
424             if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
425                 sb.Append(",\n");
426             }
427         }
428         if (returnType->kind_ != TypeKind::Void) {
429             EmitInterfaceMethodReturn(returnType, sb, prefix + TAB);
430         }
431         sb.Append(")\n");
432     }
433     EmitInterfaceProxyMethodBody(mm, sb, prefix);
434 }
435 
EmitInterfaceProxyMethodBody(MetaMethod * mm,StringBuilder & sb,const String & prefix)436 void CppCodeEmitter::EmitInterfaceProxyMethodBody(MetaMethod* mm, StringBuilder& sb, const String& prefix)
437 {
438     sb.Append(prefix).Append("{\n");
439     if (hitraceOn_) {
440         sb.Append(prefix + TAB).AppendFormat("HITRACE_METER_NAME(%s, __PRETTY_FUNCTION__);\n",
441             hitraceTag_.string());
442     }
443     sb.Append(prefix + TAB).Append("MessageParcel data;\n");
444     sb.Append(prefix + TAB).Append("MessageParcel reply;\n");
445     sb.Append(prefix + TAB).AppendFormat("MessageOption option(%s);\n",
446         (mm->properties_ & METHOD_PROPERTY_ONEWAY) != 0 ? "MessageOption::TF_ASYNC" : "MessageOption::TF_SYNC");
447     sb.Append("\n");
448     sb.Append(prefix + TAB).Append("if (!data.WriteInterfaceToken(GetDescriptor())) {\n");
449     if (logOn_) {
450         sb.Append(prefix + TAB).Append(TAB).Append("HiLog::Error(LABEL, \"Write interface token failed!\");\n");
451     }
452     sb.Append(prefix + TAB).Append(TAB).Append("return ERR_INVALID_VALUE;\n");
453     sb.Append(prefix + TAB).Append("}\n");
454     sb.Append("\n");
455 
456     for (int i = 0; i < mm->parameterNumber_; i++) {
457         MetaParameter* mp = mm->parameters_[i];
458         if ((mp->attributes_ & ATTR_IN) != 0) {
459             EmitWriteMethodParameter(mp, "data.", sb, prefix + TAB);
460         }
461     }
462     sb.Append("\n");
463     sb.Append(prefix + TAB).Append("sptr<IRemoteObject> remote = Remote();\n");
464     sb.Append(prefix + TAB).Append("if (remote == nullptr) {\n");
465     if (logOn_) {
466         sb.Append(prefix + TAB).Append(TAB).Append("HiLog::Error(LABEL, \"Remote is nullptr!\");\n");
467     }
468     sb.Append(prefix + TAB).Append(TAB).Append("return ERR_INVALID_DATA;\n");
469     sb.Append(prefix + TAB).Append("}\n");
470     sb.Append(prefix + TAB).AppendFormat("int32_t result = remote->SendRequest(COMMAND_%s, data, reply, option);\n",
471         ConstantName(mm->name_).string());
472     sb.Append(prefix + TAB).Append("if (FAILED(result)) {\n");
473     if (logOn_) {
474         sb.Append(prefix + TAB).Append(TAB).Append("HiLog::Error(LABEL, \"Send request failed!\");\n");
475     }
476     sb.Append(prefix + TAB).Append("    return result;\n");
477     sb.Append(prefix + TAB).Append("}\n");
478     EmitInterfaceProxyMethodRetValue(mm, sb, prefix);
479 }
480 
EmitInterfaceProxyMethodRetValue(MetaMethod * mm,StringBuilder & sb,const String & prefix)481 void CppCodeEmitter::EmitInterfaceProxyMethodRetValue(MetaMethod* mm, StringBuilder& sb, const String& prefix)
482 {
483     if ((mm->properties_ & METHOD_PROPERTY_ONEWAY) == 0) {
484         sb.Append("\n");
485         sb.Append(prefix + TAB).Append("ErrCode errCode = reply.ReadInt32();\n");
486         sb.Append(prefix + TAB).Append("if (FAILED(errCode)) {\n");
487         if (logOn_) {
488             sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"Read Int32 failed!\");\n");
489         }
490         sb.Append(prefix + TAB).Append("    return errCode;\n");
491         sb.Append(prefix + TAB).Append("}\n");
492         sb.Append("\n");
493         for (int i = 0; i < mm->parameterNumber_; i++) {
494             MetaParameter* mp = mm->parameters_[i];
495             if ((mp->attributes_ & ATTR_OUT) != 0) {
496                 EmitReadMethodParameter(mp, "reply.", sb, prefix + TAB);
497             }
498         }
499         MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
500         if (returnType->kind_ != TypeKind::Void) {
501             EmitReadVariable("reply.", "result", returnType, sb, prefix + TAB, false);
502         }
503     }
504     sb.Append(prefix + TAB).Append("return ERR_OK;\n");
505     sb.Append(prefix).Append("}\n");
506 }
507 
EmitWriteMethodParameter(MetaParameter * mp,const String & parcelName,StringBuilder & sb,const String & prefix)508 void CppCodeEmitter::EmitWriteMethodParameter(MetaParameter* mp, const String& parcelName, StringBuilder& sb,
509     const String& prefix)
510 {
511     MetaType* mt = metaComponent_->types_[mp->typeIndex_];
512     const std::string name = mp->name_;
513     EmitWriteVariable(parcelName, name, mt, sb, prefix);
514 }
515 
EmitReadMethodParameter(MetaParameter * mp,const String & parcelName,StringBuilder & sb,const String & prefix)516 void CppCodeEmitter::EmitReadMethodParameter(MetaParameter* mp, const String& parcelName, StringBuilder& sb,
517     const String& prefix)
518 {
519     MetaType* mt = metaComponent_->types_[mp->typeIndex_];
520     const std::string name = mp->name_;
521     EmitReadVariable(parcelName, name, mt, sb, prefix, false);
522 }
523 
EmitInterfaceStub()524 void CppCodeEmitter::EmitInterfaceStub()
525 {
526     EmitInterfaceStubHeaderFile();
527     EmitInterfaceStubCppFile();
528 }
529 
EmitInterfaceStubHeaderFile()530 void CppCodeEmitter::EmitInterfaceStubHeaderFile()
531 {
532     String filePath = String::Format("%s/%s.h", directory_.string(), FileName(stubName_).string());
533     File file(filePath, File::WRITE);
534 
535     StringBuilder sb;
536 
537     EmitLicense(sb);
538     sb.Append("\n");
539     EmitHeadMacro(sb, stubFullName_);
540     sb.Append("\n");
541     sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string());
542     sb.Append("#include <iremote_stub.h>\n");
543     sb.Append("\n");
544     EmitInterfaceStubInHeaderFile(sb);
545     EmitTailMacro(sb, stubFullName_);
546 
547     String data = sb.ToString();
548     file.WriteData(data.string(), data.GetLength());
549     file.Flush();
550     file.Close();
551 }
552 
EmitInterfaceStubInHeaderFile(StringBuilder & sb)553 void CppCodeEmitter::EmitInterfaceStubInHeaderFile(StringBuilder& sb)
554 {
555     EmitBeginNamespace(sb);
556     sb.AppendFormat("class %s : public IRemoteStub<%s> {\n", stubName_.string(), interfaceName_.string());
557     sb.Append("public:\n");
558     EmitInterfaceStubMethodDecls(sb, TAB);
559     sb.Append("\n");
560     sb.Append("private:\n");
561     EmitInterfaceStubConstants(sb, TAB);
562     sb.Append("};\n");
563     EmitEndNamespace(sb);
564 }
565 
EmitInterfaceStubMethodDecls(StringBuilder & sb,const String & prefix)566 void CppCodeEmitter::EmitInterfaceStubMethodDecls(StringBuilder& sb, const String& prefix)
567 {
568     sb.Append(prefix).Append("int32_t OnRemoteRequest(\n");
569     sb.Append(prefix + TAB).Append("uint32_t code,\n");
570     sb.Append(prefix + TAB).Append("MessageParcel& data,\n");
571     sb.Append(prefix + TAB).Append("MessageParcel& reply,\n");
572     sb.Append(prefix + TAB).Append("MessageOption& option) override;\n");
573 }
574 
EmitInterfaceStubConstants(StringBuilder & sb,const String & prefix)575 void CppCodeEmitter::EmitInterfaceStubConstants(StringBuilder& sb, const String& prefix)
576 {
577     EmitInterfaceMethodCommands(sb, prefix);
578 }
579 
EmitInterfaceStubCppFile()580 void CppCodeEmitter::EmitInterfaceStubCppFile()
581 {
582     String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(stubName_).string());
583     File file(filePath, File::WRITE);
584 
585     StringBuilder sb;
586 
587     EmitLicense(sb);
588     sb.Append("\n");
589     sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string());
590     if (logOn_) {
591         sb.Append("#include \"hilog/log.h\"\n");
592     }
593     if (hitraceOn_) {
594         sb.Append("#include \"hitrace_meter.h\"\n");
595     }
596     sb.Append("\n");
597     if (logOn_) {
598         sb.Append("using OHOS::HiviewDFX::HiLog;\n\n");
599     }
600     EmitBeginNamespace(sb);
601     EmitInterfaceStubMethodImpls(sb, "");
602     EmitEndNamespace(sb);
603 
604     String data = sb.ToString();
605     file.WriteData(data.string(), data.GetLength());
606     file.Flush();
607     file.Close();
608 }
609 
EmitInterfaceStubMethodImpls(StringBuilder & sb,const String & prefix)610 void CppCodeEmitter::EmitInterfaceStubMethodImpls(StringBuilder& sb, const String& prefix)
611 {
612     sb.Append(prefix).AppendFormat("int32_t %s::OnRemoteRequest(\n", stubName_.string());
613     sb.Append(prefix + TAB).Append("uint32_t code,\n");
614     sb.Append(prefix + TAB).Append("MessageParcel& data,\n");
615     sb.Append(prefix + TAB).Append("MessageParcel& reply,\n");
616     sb.Append(prefix + TAB).Append("MessageOption& option)\n");
617     sb.Append(prefix).Append("{\n");
618     if (hitraceOn_) {
619     sb.Append(prefix + TAB).AppendFormat("HITRACE_METER_NAME(%s, __PRETTY_FUNCTION__);\n",
620         hitraceTag_.string());
621     }
622     sb.Append(prefix + TAB).Append("std::u16string localDescriptor = GetDescriptor();\n");
623     sb.Append(prefix + TAB).Append("std::u16string remoteDescriptor = data.ReadInterfaceToken();\n");
624     sb.Append(prefix + TAB).Append("if (localDescriptor != remoteDescriptor) {\n");
625     sb.Append(prefix + TAB).Append(TAB).Append("return ERR_TRANSACTION_FAILED;\n");
626     sb.Append(prefix + TAB).Append("}\n");
627     sb.Append(prefix + TAB).Append("switch (code) {\n");
628     for (int i = 0; i < metaInterface_->methodNumber_; i++) {
629         MetaMethod* mm = metaInterface_->methods_[i];
630         EmitInterfaceStubMethodImpl(mm, sb, prefix + TAB + TAB);
631     }
632     sb.Append(prefix + TAB).Append(TAB).Append("default:\n");
633     sb.Append(prefix + TAB).Append(TAB).Append(TAB).Append(
634         "return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n");
635     sb.Append(prefix + TAB).Append("}\n\n");
636     sb.Append(prefix + TAB).Append("return ERR_TRANSACTION_FAILED;\n");
637     sb.Append(prefix).Append("}\n");
638 }
639 
EmitInterfaceStubMethodImpl(MetaMethod * mm,StringBuilder & sb,const String & prefix)640 void CppCodeEmitter::EmitInterfaceStubMethodImpl(MetaMethod* mm, StringBuilder& sb, const String& prefix)
641 {
642     sb.Append(prefix).AppendFormat("case COMMAND_%s: {\n", ConstantName(mm->name_).string());
643     for (int i = 0; i < mm->parameterNumber_; i++) {
644         MetaParameter* mp = mm->parameters_[i];
645         if ((mp->attributes_ & ATTR_IN) != 0) {
646             MetaType* mt = metaComponent_->types_[mp->typeIndex_];
647             const std::string name = mp->name_;
648             EmitReadVariable("data.", name, mt, sb, prefix + TAB);
649         } else if ((mp->attributes_ & ATTR_OUT) != 0) {
650             EmitLocalVariable(mp, sb, prefix + TAB);
651         }
652     }
653     MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
654     if (returnType->kind_ != TypeKind::Void) {
655         if ((returnType->kind_ == TypeKind::Sequenceable) || (returnType->kind_ == TypeKind::Interface)) {
656             sb.Append(prefix + TAB).AppendFormat("%s result = nullptr;\n",
657                 EmitType(returnType, ATTR_IN, true).string());
658         } else {
659             sb.Append(prefix + TAB).AppendFormat("%s result;\n", EmitType(returnType, ATTR_IN, true).string());
660         }
661     }
662     if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
663         sb.Append(prefix + TAB).AppendFormat("ErrCode errCode = %s();\n", mm->name_);
664     } else {
665         sb.Append(prefix + TAB).AppendFormat("ErrCode errCode = %s(", mm->name_);
666         for (int i = 0; i < mm->parameterNumber_; i++) {
667             MetaParameter* mp = mm->parameters_[i];
668             if (mp == nullptr) {
669                 continue;
670             }
671             const std::string name = mp->name_;
672             MetaType* mGetType = metaComponent_->types_[mp->typeIndex_];
673             if (mGetType != nullptr && mGetType->kind_ == TypeKind::Sequenceable && !mp->isSequenceableForOut_) {
674                 const std::string parameterName = "*" + name;
675                 sb.Append(parameterName.c_str());
676             } else {
677                 sb.Append(name.c_str());
678             }
679 
680             if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
681                 sb.Append(", ");
682             }
683         }
684         if (returnType->kind_ != TypeKind::Void) {
685             EmitReturnParameter("result", returnType, sb);
686         }
687         sb.AppendFormat(");\n", mm->name_);
688     }
689     sb.Append(prefix + TAB).Append("if (!reply.WriteInt32(errCode)) {\n");
690     if (logOn_) {
691         sb.Append(prefix + TAB).Append(TAB).Append("HiLog::Error(LABEL, \"Write Int32 failed!\");\n");
692     }
693     sb.Append(prefix + TAB).Append(TAB).Append("return ERR_INVALID_VALUE;\n");
694     sb.Append(prefix + TAB).Append("}\n");
695     bool hasOutParameter = false;
696     for (int i = 0; i < mm->parameterNumber_; i++) {
697         MetaParameter* mp = mm->parameters_[i];
698         if ((mp->attributes_ & ATTR_OUT) != 0) {
699             hasOutParameter = true;
700         }
701     }
702     if (hasOutParameter || returnType->kind_ != TypeKind::Void) {
703         sb.Append(prefix + TAB).Append("if (SUCCEEDED(errCode)) {\n");
704         for (int i = 0; i < mm->parameterNumber_; i++) {
705             MetaParameter* mp = mm->parameters_[i];
706             if ((mp->attributes_ & ATTR_OUT) != 0) {
707                 EmitWriteMethodParameter(mp, "reply.", sb, prefix + TAB + TAB);
708             }
709         }
710         if (returnType->kind_ != TypeKind::Void) {
711             EmitWriteVariable("reply.", "result", returnType, sb, prefix + TAB + TAB);
712         }
713         sb.Append(prefix + TAB).Append("}\n");
714     }
715     sb.Append(prefix + TAB).Append("return ERR_NONE;\n");
716     sb.Append(prefix).Append("}\n");
717 }
718 
EmitInterfaceMethodCommands(StringBuilder & sb,const String & prefix)719 void CppCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix)
720 {
721     for (int i = 0; i < metaInterface_->methodNumber_; i++) {
722         MetaMethod* mm = metaInterface_->methods_[i];
723         sb.Append(prefix).AppendFormat("static constexpr int32_t COMMAND_%s = MIN_TRANSACTION_ID + %d;\n",
724             ConstantName(mm->name_).string(), i);
725     }
726 }
727 
EmitLicense(StringBuilder & sb)728 void CppCodeEmitter::EmitLicense(StringBuilder& sb)
729 {
730     sb.Append(metaInterface_->license_).Append("\n");
731 }
732 
EmitHeadMacro(StringBuilder & sb,const String & fullName)733 void CppCodeEmitter::EmitHeadMacro(StringBuilder& sb, const String& fullName)
734 {
735     String macroName = MacroName(fullName);
736     sb.Append("#ifndef ").Append(macroName).Append("\n");
737     sb.Append("#define ").Append(macroName).Append("\n");
738 }
739 
EmitTailMacro(StringBuilder & sb,const String & fullName)740 void CppCodeEmitter::EmitTailMacro(StringBuilder& sb, const String& fullName)
741 {
742     String macroName = MacroName(fullName);
743     sb.Append("#endif // ").Append(macroName).Append("\n\n");
744 }
745 
EmitBeginNamespace(StringBuilder & sb)746 void CppCodeEmitter::EmitBeginNamespace(StringBuilder& sb)
747 {
748     String nspace = GetNamespace(metaInterface_->namespace_);
749     int index = nspace.IndexOf('.');
750     while (index != -1) {
751         sb.AppendFormat("namespace %s {\n", nspace.Substring(0, index).string());
752         nspace = nspace.Substring(index + 1);
753         index = nspace.IndexOf('.');
754     }
755 }
756 
EmitEndNamespace(StringBuilder & sb)757 void CppCodeEmitter::EmitEndNamespace(StringBuilder& sb)
758 {
759     String nspace = GetNamespace(metaInterface_->namespace_);
760     nspace = nspace.Substring(0, nspace.GetLength() - 1);
761     while (!nspace.IsEmpty()) {
762         int index = nspace.LastIndexOf('.');
763         sb.AppendFormat("} // namespace %s\n", index != -1 ?
764             nspace.Substring(index + 1, nspace.GetLength()).string() : nspace.string());
765         nspace = nspace.Substring(0, index);
766     }
767 }
768 
EmitWriteVariable(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & sb,const String & prefix)769 void CppCodeEmitter::EmitWriteVariable(const String& parcelName, const std::string& name, MetaType* mt,
770     StringBuilder& sb, const String& prefix)
771 {
772     switch (mt->kind_) {
773         case TypeKind::Boolean:
774             sb.Append(prefix).AppendFormat("if (!%sWriteInt32(%s ? 1 : 0)) {\n", parcelName.string(), name.c_str());
775             if (logOn_) {
776                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
777                     name.c_str());
778             }
779             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
780             sb.Append(prefix).Append("}\n");
781             break;
782         case TypeKind::Char:
783         case TypeKind::Byte:
784         case TypeKind::Short:
785         case TypeKind::Integer:
786             sb.Append(prefix).AppendFormat("if (!%sWriteInt32(%s)) {\n", parcelName.string(), name.c_str());
787             if (logOn_) {
788                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
789                     name.c_str());
790             }
791             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
792             sb.Append(prefix).Append("}\n");
793             break;
794         case TypeKind::Long:
795             sb.Append(prefix).AppendFormat("if (!%sWriteInt64(%s)) {\n", parcelName.string(), name.c_str());
796             if (logOn_) {
797                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
798                     name.c_str());
799             }
800             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
801             sb.Append(prefix).Append("}\n");
802             break;
803         case TypeKind::Float:
804             sb.Append(prefix).AppendFormat("if (!%sWriteFloat(%s)) {\n", parcelName.string(), name.c_str());
805             if (logOn_) {
806                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
807                     name.c_str());
808             }
809             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
810             sb.Append(prefix).Append("}\n");
811             break;
812         case TypeKind::Double:
813             sb.Append(prefix).AppendFormat("if (!%sWriteDouble(%s)) {\n", parcelName.string(), name.c_str());
814             if (logOn_) {
815                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
816                     name.c_str());
817             }
818             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
819             sb.Append(prefix).Append("}\n");
820             break;
821         default:
822             EmitWriteVariableComplex(parcelName, name, mt, sb, prefix);
823             break;
824     }
825 }
826 
EmitWriteVariableComplex(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & sb,const String & prefix)827 void CppCodeEmitter::EmitWriteVariableComplex(
828     const String& parcelName, const std::string& name, MetaType* mt, StringBuilder& sb, const String& prefix)
829 {
830     switch (mt->kind_) {
831         case TypeKind::Array:
832         case TypeKind::List: {
833             sb.Append(prefix).AppendFormat("if (%s.size() > VECTOR_MAX_SIZE) {\n", name.c_str());
834             if (logOn_) {
835                 if (mt != nullptr && mt->kind_ == TypeKind::Array) {
836                     sb.Append(prefix).Append(TAB).Append(
837                         "HiLog::Error(LABEL, \"The vector/array size exceeds the security limit!\");\n");
838                 } else {
839                     sb.Append(prefix).Append(TAB).AppendFormat(
840                         "HiLog::Error(LABEL, \"The list size exceeds the security limit!\");\n");
841                 }
842             }
843             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
844             sb.Append(prefix).Append("}\n");
845             sb.Append(prefix).AppendFormat("%sWriteInt32(%s.size());\n", parcelName.string(), name.c_str());
846             sb.Append(prefix).AppendFormat("for (auto it = %s.begin(); it != %s.end(); ++it) {\n",
847                 name.c_str(), name.c_str());
848             MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
849             EmitWriteVariable(parcelName, "(*it)", innerType, sb, prefix + TAB);
850             sb.Append(prefix).Append("}\n");
851             break;
852         }
853         case TypeKind::Map: {
854             sb.Append(prefix).AppendFormat("if (%s.size() > MAP_MAX_SIZE) {\n", name.c_str());
855             if (logOn_) {
856                 sb.Append(prefix).Append(TAB).AppendFormat(
857                     "HiLog::Error(LABEL, \"The map size exceeds the security limit!\");\n");
858             }
859             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
860             sb.Append(prefix).Append("}\n");
861             sb.Append("\n");
862             sb.Append(prefix).AppendFormat("%sWriteInt32(%s.size());\n", parcelName.string(), name.c_str());
863             sb.Append(prefix).AppendFormat("for (auto it = %s.begin(); it != %s.end(); ++it) {\n",
864                 name.c_str(), name.c_str());
865             MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
866             MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
867             EmitWriteVariable(parcelName, "(it->first)", keyType, sb, prefix + TAB);
868             EmitWriteVariable(parcelName, "(it->second)", valueType, sb, prefix + TAB);
869             sb.Append(prefix).Append("}\n");
870             break;
871         }
872         default:
873             EmitWriteVariableObject(parcelName, name, mt, sb, prefix);
874             break;
875     }
876 }
877 
EmitWriteVariableObject(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & sb,const String & prefix)878 void CppCodeEmitter::EmitWriteVariableObject(
879     const String& parcelName, const std::string& name, MetaType* mt, StringBuilder& sb, const String& prefix)
880 {
881     switch (mt->kind_) {
882         case TypeKind::String:
883             sb.Append(prefix).AppendFormat("if (!%sWriteString16(Str8ToStr16(%s))) {\n", parcelName.string(),
884                 name.c_str());
885             if (logOn_) {
886                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
887                     name.c_str());
888             }
889             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
890             sb.Append(prefix).Append("}\n");
891             break;
892         case TypeKind::Sequenceable:
893             sb.Append(prefix).AppendFormat("if (!%sWriteParcelable(&%s)) {\n", parcelName.string(), name.c_str());
894             if (logOn_) {
895                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
896                     name.c_str());
897             }
898             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
899             sb.Append(prefix).Append("}\n");
900             break;
901         case TypeKind::Interface:
902             sb.Append(prefix).AppendFormat("if (!%sWriteRemoteObject(%s)) {\n", parcelName.string(), name.c_str());
903             if (logOn_) {
904                 sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Write [%s] failed!\");\n",
905                     name.c_str());
906             }
907             sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
908             sb.Append(prefix).Append("}\n");
909             break;
910         default:
911             break;
912     }
913 }
914 
EmitReadVariable(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & sb,const String & prefix,bool emitType)915 void CppCodeEmitter::EmitReadVariable(const String& parcelName, const std::string& name, MetaType* mt,
916     StringBuilder& sb, const String& prefix, bool emitType)
917 {
918     switch (mt->kind_) {
919         case TypeKind::Boolean:
920             if (emitType) {
921                 sb.Append(prefix).AppendFormat("%s %s = %sReadInt32() == 1 ? true : false;\n",
922                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
923             } else {
924                 sb.Append(prefix).AppendFormat("%s = %sReadInt32() == 1 ? true : false;\n",
925                     name.c_str(), parcelName.string());
926             }
927             break;
928         case TypeKind::Char:
929         case TypeKind::Byte:
930         case TypeKind::Short:
931             if (emitType) {
932                 sb.Append(prefix).AppendFormat("%s %s = (%s)%sReadInt32();\n", EmitType(mt, ATTR_IN, true).string(),
933                     name.c_str(), EmitType(mt, ATTR_IN, true).string(), parcelName.string());
934             } else {
935                 sb.Append(prefix).AppendFormat("%s = (%s)%sReadInt32();\n", name.c_str(),
936                     EmitType(mt, ATTR_IN, true).string(), parcelName.string());
937             }
938             break;
939         case TypeKind::Integer:
940             if (emitType) {
941                 sb.Append(prefix).AppendFormat("%s %s = %sReadInt32();\n",
942                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
943             } else {
944                 sb.Append(prefix).AppendFormat("%s = %sReadInt32();\n", name.c_str(), parcelName.string());
945             }
946             break;
947         case TypeKind::Long:
948             if (emitType) {
949                 sb.Append(prefix).AppendFormat("%s %s = %sReadInt64();\n",
950                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
951             } else {
952                 sb.Append(prefix).AppendFormat("%s = %sReadInt64();\n", name.c_str(), parcelName.string());
953             }
954             break;
955         case TypeKind::Float:
956             if (emitType) {
957                 sb.Append(prefix).AppendFormat("%s %s = %sReadFloat();\n",
958                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
959             } else {
960                 sb.Append(prefix).AppendFormat("%s = %sReadFloat();\n", name.c_str(), parcelName.string());
961             }
962             break;
963         case TypeKind::Double:
964             if (emitType) {
965                 sb.Append(prefix).AppendFormat("%s %s = %sReadDouble();\n",
966                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
967             } else {
968                 sb.Append(prefix).AppendFormat("%s = %sReadDouble();\n", name.c_str(), parcelName.string());
969             }
970             break;
971         default:
972             EmitReadVariableComplex(parcelName, name, mt, sb, prefix, emitType);
973             break;
974     }
975 }
976 
EmitReadVariableComplex(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & sb,const String & prefix,bool emitType)977 void CppCodeEmitter::EmitReadVariableComplex(const String& parcelName, const std::string& name, MetaType* mt,
978     StringBuilder& sb, const String& prefix, bool emitType)
979 {
980     switch (mt->kind_) {
981         case TypeKind::String:
982             if (emitType) {
983                 sb.Append(prefix).AppendFormat("%s %s = Str16ToStr8(%sReadString16());\n",
984                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
985             } else {
986                 sb.Append(prefix).AppendFormat("%s = Str16ToStr8(%sReadString16());\n",
987                     name.c_str(), parcelName.string());
988             }
989             break;
990         case TypeKind::Map: {
991             if (emitType) {
992                 sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
993             }
994             sb.Append(prefix).AppendFormat("int32_t %sSize = %sReadInt32();\n", name.c_str(), parcelName.string());
995             sb.Append(prefix).AppendFormat("for (int32_t i = 0; i < %sSize; ++i) {\n", name.c_str());
996             MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
997             MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
998             EmitReadVariable(parcelName, "key", keyType, sb, prefix + TAB);
999             EmitReadVariable(parcelName, "value", valueType, sb, prefix + TAB);
1000             sb.Append(prefix + TAB).AppendFormat("%s[key] = value;\n", name.c_str());
1001             sb.Append(prefix).Append("}\n");
1002             break;
1003         }
1004         default:
1005             EmitReadVariableList(parcelName, name, mt, sb, prefix, emitType);
1006             break;
1007     }
1008 }
1009 
EmitReadVariableList(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & sb,const String & prefix,bool emitType)1010 void CppCodeEmitter::EmitReadVariableList(const String& parcelName, const std::string& name, MetaType* mt,
1011     StringBuilder& sb, const String& prefix, bool emitType)
1012 {
1013     switch (mt->kind_) {
1014         case TypeKind::Array:
1015         case TypeKind::List: {
1016             if (emitType) {
1017                 sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
1018             }
1019             sb.Append(prefix).AppendFormat("int32_t %sSize = %sReadInt32();\n", name.c_str(), parcelName.string());
1020             sb.Append(prefix).AppendFormat("if (%sSize > VECTOR_MAX_SIZE) {\n", name.c_str());
1021             sb.Append(prefix + TAB).Append(
1022                 "HiLog::Error(LABEL, \"The vector/array size exceeds the security limit!\");\n");
1023             sb.Append(prefix + TAB).Append("return ERR_INVALID_DATA;\n");
1024             sb.Append(prefix).Append("}\n");
1025             sb.Append(prefix).AppendFormat("for (int32_t i = 0; i < %sSize; ++i) {\n", name.c_str());
1026             MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
1027             EmitReadVariable(parcelName, "value", innerType, sb, prefix + TAB);
1028             if (innerType->kind_ == TypeKind::Sequenceable) {
1029                 sb.Append(prefix + TAB).AppendFormat("%s.push_back(*value);\n", name.c_str());
1030             } else {
1031                 sb.Append(prefix + TAB).AppendFormat("%s.push_back(value);\n", name.c_str());
1032             }
1033             sb.Append(prefix).Append("}\n");
1034             break;
1035         }
1036         default:
1037             EmitReadVariableObject(parcelName, name, mt, sb, prefix, emitType);
1038             break;
1039     }
1040 }
1041 
EmitReadVariableObject(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & sb,const String & prefix,bool emitType)1042 void CppCodeEmitter::EmitReadVariableObject(const String& parcelName, const std::string& name, MetaType* mt,
1043     StringBuilder& sb, const String& prefix, bool emitType)
1044 {
1045     switch (mt->kind_) {
1046         case TypeKind::Sequenceable: {
1047             MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_];
1048             if (mp == nullptr) {
1049                 break;
1050             }
1051             if (emitType) {
1052                 readSequenceable_ = true;
1053                 sb.Append(prefix).AppendFormat("if ((!%sReadParcelable<%s>())) {\n",
1054                     parcelName.string(), mp->name_);
1055                 if (logOn_) {
1056                     sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Read [%s] failed!\");\n",
1057                         mp->name_);
1058                 }
1059                 sb.Append(prefix).Append(TAB).Append("return ERR_INVALID_DATA;\n");
1060                 sb.Append(prefix).Append("}\n");
1061                 sb.Append(prefix).AppendFormat("std::unique_ptr<%s> %s(%sReadParcelable<%s>());\n\n",
1062                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string(), mp->name_);
1063             } else {
1064                 sb.Append(prefix).AppendFormat("std::unique_ptr<%s> info(%sReadParcelable<%s>());\n",
1065                     mp->name_, parcelName.string(), mp->name_);
1066                 sb.Append(prefix).Append("if (info != nullptr) {\n");
1067                 sb.Append(prefix).Append(TAB).AppendFormat("%s = *info;\n", name.c_str());
1068                 sb.Append(prefix).Append("}\n\n");
1069             }
1070             break;
1071         }
1072         case TypeKind::Interface: {
1073             MetaInterface* mi = metaComponent_->interfaces_[mt->index_];
1074             if (emitType) {
1075                 sb.Append(prefix).AppendFormat("%s %s = %sReadRemoteObject();\n",
1076                     EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
1077                 sb.Append(prefix).AppendFormat("if (%s == nullptr) {\n", name.c_str());
1078                 if (logOn_) {
1079                     sb.Append(prefix).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"Read [%s] failed!\");\n",
1080                         name.c_str());
1081                 }
1082                 sb.Append(prefix).Append(TAB).AppendFormat("return ERR_INVALID_DATA;\n");
1083                 sb.Append(prefix).Append("}\n\n");
1084             } else {
1085                 sb.Append(prefix).AppendFormat("%s = iface_cast<%s>(%sReadRemoteObject());\n",
1086                     name.c_str(),  mi->name_, parcelName.string());
1087             }
1088             break;
1089         }
1090         default:
1091             break;
1092     }
1093 }
1094 
EmitLocalVariable(MetaParameter * mp,StringBuilder & sb,const String & prefix)1095 void CppCodeEmitter::EmitLocalVariable(MetaParameter* mp, StringBuilder& sb, const String& prefix)
1096 {
1097     MetaType* mt = metaComponent_->types_[mp->typeIndex_];
1098     const std::string name = mp->name_;
1099     if ((mt->kind_ == TypeKind::Sequenceable) || (mt->kind_ == TypeKind::Interface)) {
1100         createSequenceableForOut_ = true;
1101         mp->isSequenceableForOut_ = true;
1102         sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
1103     } else {
1104         sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
1105     }
1106 }
1107 
EmitReturnParameter(const String & name,MetaType * mt,StringBuilder & sb)1108 void CppCodeEmitter::EmitReturnParameter(const String& name, MetaType* mt, StringBuilder& sb)
1109 {
1110     switch (mt->kind_) {
1111         case TypeKind::Char:
1112         case TypeKind::Boolean:
1113         case TypeKind::Byte:
1114         case TypeKind::Short:
1115         case TypeKind::Integer:
1116         case TypeKind::Long:
1117         case TypeKind::Float:
1118         case TypeKind::Double:
1119         case TypeKind::String:
1120         case TypeKind::Sequenceable:
1121         case TypeKind::Interface:
1122         case TypeKind::List:
1123         case TypeKind::Map:
1124         case TypeKind::Array:
1125             sb.Append(name);
1126             break;
1127         default:
1128             break;
1129     }
1130 }
1131 
EmitType(MetaType * mt,unsigned int attributes,bool isInnerType)1132 String CppCodeEmitter::EmitType(MetaType* mt, unsigned int attributes, bool isInnerType)
1133 {
1134     switch (mt->kind_) {
1135         case TypeKind::Char:
1136             enteredVector_ = false;
1137             if (attributes & ATTR_IN) {
1138                 return "zchar";
1139             } else {
1140                 return "zchar&";
1141             }
1142         case TypeKind::Boolean:
1143             enteredVector_ = false;
1144             if (attributes & ATTR_IN) {
1145                 return "bool";
1146             } else {
1147                 return "bool&";
1148             }
1149         case TypeKind::Byte:
1150             enteredVector_ = false;
1151             if (attributes & ATTR_IN) {
1152                 return "int8_t";
1153             } else {
1154                 return "int8_t&";
1155             }
1156         case TypeKind::Short:
1157             enteredVector_ = false;
1158             if (attributes & ATTR_IN) {
1159                 return "short";
1160             } else {
1161                 return "short&";
1162             }
1163         case TypeKind::Integer:
1164             enteredVector_ = false;
1165             if (attributes & ATTR_IN) {
1166                 return "int32_t";
1167             } else {
1168                 return "int32_t&";
1169             }
1170         case TypeKind::Long:
1171             enteredVector_ = false;
1172             if (attributes & ATTR_IN) {
1173                 return "long";
1174             } else {
1175                 return "long&";
1176             }
1177         case TypeKind::Float:
1178             enteredVector_ = false;
1179             if (attributes & ATTR_IN) {
1180                 return "float";
1181             } else {
1182                 return "float&";
1183             }
1184         case TypeKind::Double:
1185             enteredVector_ = false;
1186             if (attributes & ATTR_IN) {
1187                 return "double";
1188             } else {
1189                 return "double&";
1190             }
1191         case TypeKind::Void:
1192             enteredVector_ = false;
1193             return "void";
1194         default:
1195             return EmitComplexType(mt, attributes, isInnerType);
1196     }
1197 }
1198 
EmitComplexType(MetaType * mt,unsigned int attributes,bool isInnerType)1199 String CppCodeEmitter::EmitComplexType(MetaType* mt, unsigned int attributes, bool isInnerType)
1200 {
1201     switch (mt->kind_) {
1202         case TypeKind::String:
1203             enteredVector_ = false;
1204             if (attributes & ATTR_IN) {
1205                 if (!isInnerType) {
1206                     return "const std::string&";
1207                 } else {
1208                     return "std::string";
1209                 }
1210             } else {
1211                 return "std::string&";
1212             }
1213         case TypeKind::Map: {
1214             MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
1215             MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
1216             if (attributes & ATTR_OUT) {
1217                 return String::Format("std::unordered_map<%s, %s>&",
1218                     EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string());
1219             } else {
1220                 if (!isInnerType) {
1221                     return String::Format("const std::unordered_map<%s, %s>&",
1222                         EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string());
1223                 } else {
1224                     return String::Format("std::unordered_map<%s, %s>",
1225                         EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string());
1226                 }
1227             }
1228             break;
1229         }
1230         default:
1231             return EmitListType(mt, attributes, isInnerType);
1232     }
1233 }
1234 
EmitListType(MetaType * mt,unsigned int attributes,bool isInnerType)1235 String CppCodeEmitter::EmitListType(MetaType* mt, unsigned int attributes, bool isInnerType)
1236 {
1237     switch (mt->kind_) {
1238         case TypeKind::Array:
1239         case TypeKind::List: {
1240             enteredVector_ = true;
1241             MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
1242             if (attributes & ATTR_OUT) {
1243                 return String::Format("std::vector<%s>&",
1244                                       EmitType(elementType, ATTR_IN, true).string());
1245             } else {
1246                 if (!isInnerType) {
1247                     return String::Format("const std::vector<%s>&",
1248                                           EmitType(elementType, ATTR_IN, true).string());
1249                 } else {
1250                     return String::Format("std::vector<%s>",
1251                                           EmitType(elementType, ATTR_IN, true).string());
1252                 }
1253             }
1254         }
1255         default:
1256             return EmitObjectType(mt, attributes, isInnerType);
1257     }
1258 }
1259 
EmitObjectType(MetaType * mt,unsigned int attributes,bool isInnerType)1260 String CppCodeEmitter::EmitObjectType(MetaType* mt, unsigned int attributes, bool isInnerType)
1261 {
1262     switch (mt->kind_) {
1263         case TypeKind::Sequenceable: {
1264             MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_];
1265             if (mp == nullptr) {
1266                 return "unknown type";
1267             }
1268             if (enteredVector_) {
1269                 enteredVector_ = false;
1270                 return String::Format("%s", mp->name_);
1271             }
1272             if (readSequenceable_) {
1273                 readSequenceable_ = false;
1274                 return String::Format("%s", mp->name_);
1275             }
1276             if (createSequenceableForOut_) {
1277                 createSequenceableForOut_ = false;
1278                 return String::Format("%s", mp->name_);
1279             }
1280             if ((attributes & ATTR_MASK) == (ATTR_IN | ATTR_OUT)) {
1281                 return String::Format("%s*", mp->name_);
1282             } else if (attributes & ATTR_IN) {
1283                 return String::Format("const %s&", mp->name_);
1284             } else {
1285                 return String::Format("%s&", mp->name_);
1286             }
1287         }
1288         case TypeKind::Interface: {
1289             MetaInterface* mi = metaComponent_->interfaces_[mt->index_];
1290             if (mi == nullptr) {
1291                 return "unknown type";
1292             }
1293             if (attributes & ATTR_IN) {
1294                 if (!isInnerType) {
1295                     return String::Format("const sptr<%s>&", mi->name_);
1296                 } else {
1297                     return String::Format("sptr<%s>", mi->name_);
1298                 }
1299             } else {
1300                 return String::Format("sptr<%s>&", mi->name_);
1301             }
1302         }
1303         default:
1304             return "unknown type";
1305     }
1306 }
1307 
CppFullName(const String & name)1308 String CppCodeEmitter::CppFullName(const String& name)
1309 {
1310     if (name.IsEmpty()) {
1311         return name;
1312     }
1313 
1314     return name.Replace(".", "::");
1315 }
1316 
FileName(const String & name)1317 String CppCodeEmitter::FileName(const String& name)
1318 {
1319     if (name.IsEmpty()) {
1320         return name;
1321     }
1322 
1323     StringBuilder sb;
1324 
1325     for (int i = 0; i < name.GetLength(); i++) {
1326         char c = name[i];
1327         if (isupper(c) != 0) {
1328             // 2->Index of the last char array.
1329             if (i > 1 && name[i - 1] != '.' && name[i - 2] != '.') {
1330                 sb.Append('_');
1331             }
1332             sb.Append(tolower(c));
1333         } else {
1334             sb.Append(c);
1335         }
1336     }
1337 
1338     return sb.ToString().Replace('.', '/');
1339 }
1340 
MacroName(const String & name)1341 String CppCodeEmitter::MacroName(const String& name)
1342 {
1343     if (name.IsEmpty()) {
1344         return name;
1345     }
1346 
1347     String macro = name.Replace('.', '_').ToUpperCase() + "_H";
1348     return macro;
1349 }
1350 
ConstantName(const String & name)1351 String CppCodeEmitter::ConstantName(const String& name)
1352 {
1353     if (name.IsEmpty()) {
1354         return name;
1355     }
1356 
1357     StringBuilder sb;
1358 
1359     for (int i = 0; i < name.GetLength(); i++) {
1360         char c = name[i];
1361         if (isupper(c) != 0) {
1362             if (i > 1) {
1363                 sb.Append('_');
1364             }
1365             sb.Append(c);
1366         } else {
1367             sb.Append(toupper(c));
1368         }
1369     }
1370 
1371     return sb.ToString();
1372 }
1373 
UnderlineAdded(const String & originName)1374 const std::string CppCodeEmitter::UnderlineAdded(const String& originName)
1375 {
1376     std::string underline("_");
1377     return underline + std::string(originName.string());
1378 }
1379 } // namespace Idl
1380 } // namespace OHOS