• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/c_custom_types_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12 #include "util/options.h"
13 
14 namespace OHOS {
15 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)16 bool CCustomTypesCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
17 {
18     if (ast_->GetASTFileType() != ASTFileType::AST_TYPES) {
19         return false;
20     }
21 
22     directory_ = GetFileParentPath(targetDirectory);
23     if (!File::CreateParentDir(directory_)) {
24         Logger::E("CCustomTypesCodeEmitter", "Create '%s' failed!", directory_.c_str());
25         return false;
26     }
27 
28     return true;
29 }
30 
EmitCode()31 void CCustomTypesCodeEmitter::EmitCode()
32 {
33     if (Options::GetInstance().DoPassthrough()) {
34         EmitPassthroughCustomTypesHeaderFile();
35     } else {
36         EmitCustomTypesHeaderFile();
37         EmitCustomTypesSourceFile();
38     }
39 }
40 
EmitPassthroughCustomTypesHeaderFile()41 void CCustomTypesCodeEmitter::EmitPassthroughCustomTypesHeaderFile()
42 {
43     std::string filePath =
44         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
45     File file(filePath, File::WRITE);
46     StringBuilder sb;
47 
48     EmitLicense(sb);
49     EmitHeadMacro(sb, baseName_);
50     sb.Append("\n");
51     EmitPassthroughHeaderInclusions(sb);
52     sb.Append("\n");
53     EmitHeadExternC(sb);
54     sb.Append("\n");
55     EmitCustomTypeDecls(sb);
56     EmitTailExternC(sb);
57     sb.Append("\n");
58     EmitTailMacro(sb, baseName_);
59 
60     std::string data = sb.ToString();
61     file.WriteData(data.c_str(), data.size());
62     file.Flush();
63     file.Close();
64 }
65 
EmitPassthroughHeaderInclusions(StringBuilder & sb)66 void CCustomTypesCodeEmitter::EmitPassthroughHeaderInclusions(StringBuilder &sb)
67 {
68     HeaderFile::HeaderFileSet headerFiles;
69     headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
70     headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdbool");
71 
72     for (const auto &file : headerFiles) {
73         sb.AppendFormat("%s\n", file.ToString().c_str());
74     }
75 }
76 
EmitCustomTypesHeaderFile()77 void CCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
78 {
79     std::string filePath =
80         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
81     File file(filePath, File::WRITE);
82     StringBuilder sb;
83 
84     EmitLicense(sb);
85     EmitHeadMacro(sb, baseName_);
86     sb.Append("\n");
87     EmitHeaderInclusions(sb);
88     sb.Append("\n");
89     EmitInterfaceBuffSizeMacro(sb);
90     sb.Append("\n");
91     EmitHeadExternC(sb);
92     sb.Append("\n");
93     EmitCustomTypeDecls(sb);
94     sb.Append("\n");
95     EmitCustomTypeFuncDecl(sb);
96     sb.Append("\n");
97     EmitTailExternC(sb);
98     sb.Append("\n");
99     EmitTailMacro(sb, baseName_);
100 
101     std::string data = sb.ToString();
102     file.WriteData(data.c_str(), data.size());
103     file.Flush();
104     file.Close();
105 }
106 
EmitHeaderInclusions(StringBuilder & sb)107 void CCustomTypesCodeEmitter::EmitHeaderInclusions(StringBuilder &sb)
108 {
109     HeaderFile::HeaderFileSet headerFiles;
110     GetHeaderOtherLibInclusions(headerFiles);
111 
112     for (const auto &file : headerFiles) {
113         sb.AppendFormat("%s\n", file.ToString().c_str());
114     }
115 }
116 
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)117 void CCustomTypesCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
118 {
119     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
120         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
121         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
122             headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf");
123             break;
124         }
125     }
126 }
127 
EmitCustomTypeDecls(StringBuilder & sb)128 void CCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder &sb)
129 {
130     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
131         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
132         EmitCustomTypeDecl(sb, type);
133         if (i + 1 < ast_->GetTypeDefinitionNumber()) {
134             sb.Append("\n");
135         }
136     }
137 }
138 
EmitCustomTypeDecl(StringBuilder & sb,const AutoPtr<ASTType> & type)139 void CCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder &sb, const AutoPtr<ASTType> &type)
140 {
141     switch (type->GetTypeKind()) {
142         case TypeKind::TYPE_ENUM: {
143             AutoPtr<ASTEnumType> enumType = dynamic_cast<ASTEnumType *>(type.Get());
144             sb.Append(enumType->EmitCTypeDecl()).Append("\n");
145             break;
146         }
147         case TypeKind::TYPE_STRUCT: {
148             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
149             sb.Append(structType->EmitCTypeDecl()).Append("\n");
150             break;
151         }
152         case TypeKind::TYPE_UNION: {
153             AutoPtr<ASTUnionType> unionType = dynamic_cast<ASTUnionType *>(type.Get());
154             sb.Append(unionType->EmitCTypeDecl()).Append("\n");
155             break;
156         }
157         default:
158             break;
159     }
160 }
161 
EmitCustomTypeFuncDecl(StringBuilder & sb)162 void CCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder &sb)
163 {
164     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
165         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
166         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
167             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
168             EmitCustomTypeMarshallingDecl(sb, structType);
169             sb.Append("\n");
170             EmitCustomTypeUnmarshallingDecl(sb, structType);
171             sb.Append("\n");
172             EmitCustomTypeFreeDecl(sb, structType);
173             if (i + 1 < ast_->GetTypeDefinitionNumber()) {
174                 sb.Append("\n");
175             }
176         }
177     }
178 }
179 
EmitCustomTypeMarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)180 void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
181 {
182     std::string objName("dataBlock");
183     sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s);\n", type->GetName().c_str(),
184         type->EmitCType().c_str(), objName.c_str());
185 }
186 
EmitCustomTypeUnmarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)187 void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
188 {
189     std::string objName("dataBlock");
190     sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s);\n", type->GetName().c_str(),
191         type->EmitCType().c_str(), objName.c_str());
192 }
193 
EmitCustomTypeFreeDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)194 void CCustomTypesCodeEmitter::EmitCustomTypeFreeDecl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
195 {
196     std::string objName("dataBlock");
197     sb.AppendFormat(
198         "void %sFree(%s *%s, bool freeSelf);\n", type->GetName().c_str(), type->EmitCType().c_str(), objName.c_str());
199 }
200 
EmitCustomTypesSourceFile()201 void CCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
202 {
203     std::string filePath =
204         File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(baseName_).c_str()));
205     File file(filePath, File::WRITE);
206     StringBuilder sb;
207 
208     EmitLicense(sb);
209     EmitSoucreInclusions(sb);
210     sb.Append("\n");
211     UtilMethodMap utilMethods;
212     GetUtilMethods(utilMethods);
213     EmitUtilMethods(sb, "", utilMethods, true);
214     sb.Append("\n");
215     EmitUtilMethods(sb, "", utilMethods, false);
216     sb.Append("\n");
217     EmitCustomTypeDataProcess(sb);
218 
219     std::string data = sb.ToString();
220     file.WriteData(data.c_str(), data.size());
221     file.Flush();
222     file.Close();
223 }
224 
EmitSoucreInclusions(StringBuilder & sb)225 void CCustomTypesCodeEmitter::EmitSoucreInclusions(StringBuilder &sb)
226 {
227     HeaderFile::HeaderFileSet headerFiles;
228     headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_));
229     GetSourceOtherLibInclusions(headerFiles);
230 
231     for (const auto &file : headerFiles) {
232         sb.AppendFormat("%s\n", file.ToString().c_str());
233     }
234 }
235 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)236 void CCustomTypesCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
237 {
238     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
239     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
240 
241     const AST::TypeStringMap &types = ast_->GetTypes();
242     for (const auto &pair : types) {
243         AutoPtr<ASTType> type = pair.second;
244         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT || type->GetTypeKind() == TypeKind::TYPE_UNION) {
245             headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
246             break;
247         }
248     }
249 }
250 
EmitCustomTypeDataProcess(StringBuilder & sb)251 void CCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder &sb)
252 {
253     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
254         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
255         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
256             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
257             EmitCustomTypeMarshallingImpl(sb, structType);
258             sb.Append("\n");
259             EmitCustomTypeUnmarshallingImpl(sb, structType);
260             sb.Append("\n");
261             EmitCustomTypeFreeImpl(sb, structType);
262             if (i + 1 < ast_->GetTypeDefinitionNumber()) {
263                 sb.Append("\n");
264             }
265         }
266     }
267 }
268 
EmitCustomTypeMarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)269 void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
270 {
271     std::string objName("dataBlock");
272     sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s)\n", type->GetName().c_str(),
273         type->EmitCType().c_str(), objName.c_str());
274     sb.Append("{\n");
275     EmitMarshallingVarDecl(type, objName, sb, TAB);
276     EmitParamCheck(objName, sb, TAB);
277     sb.Append("\n");
278     if (type->IsPod()) {
279         if (Options::GetInstance().DoGenerateKernelCode()) {
280             sb.Append(TAB).AppendFormat("if (!HdfSbufWriteBuffer(data, (const void *)%s, sizeof(%s))) {\n",
281                 objName.c_str(), type->EmitCType().c_str());
282         } else {
283             sb.Append(TAB).AppendFormat("if (!HdfSbufWriteUnpadBuffer(data, (const uint8_t *)%s, sizeof(%s))) {\n",
284                 objName.c_str(), type->EmitCType().c_str());
285         }
286         sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to write buffer data\", __func__);\n");
287         sb.Append(TAB).Append(TAB).Append("return false;\n");
288         sb.Append(TAB).Append("}\n");
289     } else {
290         for (size_t i = 0; i < type->GetMemberNumber(); i++) {
291             std::string memberName = type->GetMemberName(i);
292             AutoPtr<ASTType> memberType = type->GetMemberType(i);
293             std::string name = StringHelper::Format("%s->%s", objName.c_str(), memberName.c_str());
294             memberType->EmitCMarshalling(name, sb, TAB);
295             sb.Append("\n");
296         }
297     }
298 
299     sb.Append(TAB).Append("return true;\n");
300     sb.Append("}\n");
301 }
302 
EmitCustomTypeUnmarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)303 void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
304 {
305     std::string objName("dataBlock");
306     freeObjStatements_.clear();
307     sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s)\n", type->GetName().c_str(),
308         type->EmitCType().c_str(), objName.c_str());
309     sb.Append("{\n");
310     EmitUnmarshallingVarDecl(type, objName, sb, TAB);
311     EmitParamCheck(objName, sb, TAB);
312     sb.Append("\n");
313     if (type->IsPod()) {
314         EmitPodTypeUnmarshalling(type, objName, sb, TAB);
315     } else {
316         for (size_t i = 0; i < type->GetMemberNumber(); i++) {
317             AutoPtr<ASTType> memberType = type->GetMemberType(i);
318             EmitMemberUnmarshalling(memberType, objName, type->GetMemberName(i), sb, TAB);
319         }
320     }
321     sb.Append(TAB).Append("return true;\n");
322     sb.AppendFormat("%s:\n", errorsLabelName_);
323     EmitCustomTypeMemoryRecycle(type, objName, sb, TAB);
324     sb.Append(TAB).Append("return false;\n");
325     sb.Append("}\n");
326 }
327 
EmitMarshallingVarDecl(const AutoPtr<ASTStructType> & type,const std::string & name,StringBuilder & sb,const std::string & prefix)328 void CCustomTypesCodeEmitter::EmitMarshallingVarDecl(
329     const AutoPtr<ASTStructType> &type, const std::string &name, StringBuilder &sb, const std::string &prefix)
330 {
331     if (!Options::GetInstance().DoGenerateKernelCode()) {
332         return;
333     }
334 
335     for (size_t i = 0; i < type->GetMemberNumber(); i++) {
336         if (EmitNeedLoopVar(type->GetMemberType(i), true, false)) {
337             sb.Append(prefix).Append("uint32_t i = 0;\n");
338             break;
339         }
340     }
341 }
342 
EmitUnmarshallingVarDecl(const AutoPtr<ASTStructType> & type,const std::string & name,StringBuilder & sb,const std::string & prefix)343 void CCustomTypesCodeEmitter::EmitUnmarshallingVarDecl(
344     const AutoPtr<ASTStructType> &type, const std::string &name, StringBuilder &sb, const std::string &prefix)
345 {
346     if (!Options::GetInstance().DoGenerateKernelCode()) {
347         return;
348     }
349 
350     if (type->IsPod()) {
351         sb.Append(prefix).AppendFormat("%s *%sPtr = NULL;\n", type->EmitCType().c_str(), name.c_str());
352         sb.Append(prefix).AppendFormat("uint32_t %sLen = 0;\n\n", name.c_str());
353         return;
354     }
355 
356     for (size_t i = 0; i < type->GetMemberNumber(); i++) {
357         if (EmitNeedLoopVar(type->GetMemberType(i), true, true)) {
358             sb.Append(prefix).Append("uint32_t i = 0;\n");
359             break;
360         }
361     }
362 }
363 
EmitParamCheck(const std::string & name,StringBuilder & sb,const std::string & prefix)364 void CCustomTypesCodeEmitter::EmitParamCheck(const std::string &name, StringBuilder &sb, const std::string &prefix)
365 {
366     sb.Append(prefix).Append("if (data == NULL) {\n");
367     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid sbuf\", __func__);\n");
368     sb.Append(prefix + TAB).Append("return false;\n");
369     sb.Append(prefix).Append("}\n\n");
370     sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.c_str());
371     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid data block\", __func__);\n");
372     sb.Append(prefix + TAB).Append("return false;\n");
373     sb.Append(prefix).Append("}\n");
374 }
375 
EmitPodTypeUnmarshalling(const AutoPtr<ASTStructType> & type,const std::string & name,StringBuilder & sb,const std::string & prefix)376 void CCustomTypesCodeEmitter::EmitPodTypeUnmarshalling(
377     const AutoPtr<ASTStructType> &type, const std::string &name, StringBuilder &sb, const std::string &prefix)
378 {
379     std::string objPtrName = StringHelper::Format("%sPtr", name.c_str());
380     if (Options::GetInstance().DoGenerateKernelCode()) {
381         std::string lenName = StringHelper::Format("%sLen", name.c_str());
382         sb.Append(prefix).AppendFormat(
383             "if (!HdfSbufReadBuffer(data, (const void**)&%s, &%s)) {\n", objPtrName.c_str(), lenName.c_str());
384         sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to read buffer data\", __func__);\n");
385         sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
386         sb.Append(prefix).Append("}\n\n");
387         sb.Append(prefix).AppendFormat(
388             "if (%s == NULL || %s != sizeof(%s)) {\n", objPtrName.c_str(), lenName.c_str(), type->EmitCType().c_str());
389         sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid data from reading buffer\", __func__);\n");
390         sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
391         sb.Append(prefix).Append("}\n");
392     } else {
393         sb.Append(prefix).AppendFormat("const %s *%s = (const %s *)HdfSbufReadUnpadBuffer(data, sizeof(%s));\n",
394             type->EmitCType().c_str(), objPtrName.c_str(), type->EmitCType().c_str(), type->EmitCType().c_str());
395         sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", objPtrName.c_str());
396         sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to read buffer data\", __func__);\n");
397         sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
398         sb.Append(prefix).Append("}\n\n");
399     }
400 
401     sb.Append(prefix).AppendFormat("if (memcpy_s(%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", name.c_str(),
402         type->EmitCType().c_str(), objPtrName.c_str(), type->EmitCType().c_str());
403     sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to memcpy data\", __func__);\n");
404     sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
405     sb.Append(prefix).Append("}\n\n");
406 }
407 
EmitMemberUnmarshalling(const AutoPtr<ASTType> & type,const std::string & name,const std::string & memberName,StringBuilder & sb,const std::string & prefix)408 void CCustomTypesCodeEmitter::EmitMemberUnmarshalling(const AutoPtr<ASTType> &type, const std::string &name,
409     const std::string &memberName, StringBuilder &sb, const std::string &prefix)
410 {
411     std::string varName = StringHelper::Format("%s->%s", name.c_str(), memberName.c_str());
412     switch (type->GetTypeKind()) {
413         case TypeKind::TYPE_STRING: {
414             EmitStringMemberUnmarshalling(type, memberName, varName, sb, prefix);
415             break;
416         }
417         case TypeKind::TYPE_STRUCT: {
418             std::string paramName = StringHelper::Format("&%s", varName.c_str());
419             type->EmitCUnMarshalling(paramName, errorsLabelName_, sb, prefix, freeObjStatements_);
420             sb.Append("\n");
421             break;
422         }
423         case TypeKind::TYPE_UNION: {
424             std::string tmpName = StringHelper::Format("%sCp", memberName.c_str());
425             type->EmitCUnMarshalling(tmpName, errorsLabelName_, sb, prefix, freeObjStatements_);
426             sb.Append(prefix).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", varName.c_str(),
427                 type->EmitCType().c_str(), tmpName.c_str(), type->EmitCType().c_str());
428             sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to memcpy data\", __func__);\n");
429             sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
430             sb.Append(prefix).Append("}\n");
431             break;
432         }
433         case TypeKind::TYPE_ARRAY:
434         case TypeKind::TYPE_LIST: {
435             EmitArrayMemberUnmarshalling(type, memberName, varName, sb, prefix);
436             sb.Append("\n");
437             break;
438         }
439         default: {
440             type->EmitCUnMarshalling(varName, errorsLabelName_, sb, prefix, freeObjStatements_);
441             sb.Append("\n");
442         }
443     }
444 }
445 
EmitStringMemberUnmarshalling(const AutoPtr<ASTType> & type,const std::string & memberName,const std::string & varName,StringBuilder & sb,const std::string & prefix)446 void CCustomTypesCodeEmitter::EmitStringMemberUnmarshalling(const AutoPtr<ASTType> &type, const std::string &memberName,
447     const std::string &varName, StringBuilder &sb, const std::string &prefix)
448 {
449     std::string tmpName = StringHelper::Format("%sCp", memberName.c_str());
450     sb.Append(prefix).Append("{\n");
451     type->EmitCUnMarshalling(tmpName, errorsLabelName_, sb, prefix + TAB, freeObjStatements_);
452     if (Options::GetInstance().DoGenerateKernelCode()) {
453         sb.Append(prefix + TAB)
454             .AppendFormat("%s = (char*)OsalMemCalloc(strlen(%s) + 1);\n", varName.c_str(), tmpName.c_str());
455         sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", varName.c_str());
456         sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
457         sb.Append(prefix + TAB).Append("}\n");
458         sb.Append(prefix + TAB).AppendFormat("if (strcpy_s(%s, (strlen(%s) + 1), %s) != EOK) {\n",
459             varName.c_str(), tmpName.c_str(), tmpName.c_str());
460         sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
461         sb.Append(prefix + TAB).Append("}\n");
462     } else {
463         sb.Append(prefix + TAB).AppendFormat("%s = strdup(%s);\n", varName.c_str(), tmpName.c_str());
464     }
465 
466     sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", varName.c_str());
467     sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", errorsLabelName_);
468     sb.Append(prefix + TAB).Append("}\n");
469     sb.Append(prefix).Append("}\n");
470     sb.Append("\n");
471 }
472 
EmitArrayMemberUnmarshalling(const AutoPtr<ASTType> & type,const std::string & memberName,const std::string & varName,StringBuilder & sb,const std::string & prefix)473 void CCustomTypesCodeEmitter::EmitArrayMemberUnmarshalling(const AutoPtr<ASTType> &type, const std::string &memberName,
474     const std::string &varName, StringBuilder &sb, const std::string &prefix)
475 {
476     std::string tmpName = StringHelper::Format("%sCp", memberName.c_str());
477     AutoPtr<ASTType> elementType = nullptr;
478     if (type->GetTypeKind() == TypeKind::TYPE_ARRAY) {
479         AutoPtr<ASTArrayType> arrayType = dynamic_cast<ASTArrayType *>(type.Get());
480         elementType = arrayType->GetElementType();
481     } else {
482         AutoPtr<ASTListType> listType = dynamic_cast<ASTListType *>(type.Get());
483         elementType = listType->GetElementType();
484     }
485 
486     if (elementType->IsStringType()) {
487         type->EmitCUnMarshalling(varName, errorsLabelName_, sb, prefix, freeObjStatements_);
488         return;
489     }
490 
491     sb.Append(prefix).Append("{\n");
492     sb.Append(prefix + TAB).AppendFormat("%s* %s = NULL;\n", elementType->EmitCType().c_str(), tmpName.c_str());
493     sb.Append(prefix + TAB).AppendFormat("uint32_t %sLen = 0;\n", tmpName.c_str());
494     type->EmitCUnMarshalling(tmpName, errorsLabelName_, sb, prefix + TAB, freeObjStatements_);
495     sb.Append(prefix + TAB).AppendFormat("%s = %s;\n", varName.c_str(), tmpName.c_str());
496     sb.Append(prefix + TAB).AppendFormat("%sLen = %sLen;\n", varName.c_str(), tmpName.c_str());
497     sb.Append(prefix).Append("}\n");
498 }
499 
EmitCustomTypeFreeImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)500 void CCustomTypesCodeEmitter::EmitCustomTypeFreeImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
501 {
502     std::string objName("dataBlock");
503     sb.AppendFormat(
504         "void %sFree(%s *%s, bool freeSelf)\n", type->GetName().c_str(), type->EmitCType().c_str(), objName.c_str());
505     sb.Append("{\n");
506 
507     if (isKernelCode_) {
508         for (size_t i = 0; i < type->GetMemberNumber(); i++) {
509             AutoPtr<ASTType> memberType = type->GetMemberType(i);
510             if (EmitNeedLoopVar(memberType, false, true)) {
511                 sb.Append(TAB).Append("uint32_t i = 0;\n");
512                 break;
513             }
514         }
515     }
516 
517     sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
518     sb.Append(TAB).Append(TAB).Append("return;\n");
519     sb.Append(TAB).Append("}\n");
520     sb.Append("\n");
521 
522     EmitCustomTypeMemoryRecycle(type, objName, sb, TAB);
523 
524     sb.Append(TAB).Append("if (freeSelf) {\n");
525     sb.Append(TAB).Append(TAB).Append("OsalMemFree(dataBlock);\n");
526     sb.Append(TAB).Append("}\n");
527     sb.Append("}\n");
528 }
529 
EmitCustomTypeMemoryRecycle(const AutoPtr<ASTStructType> & type,const std::string & name,StringBuilder & sb,const std::string & prefix)530 void CCustomTypesCodeEmitter::EmitCustomTypeMemoryRecycle(
531     const AutoPtr<ASTStructType> &type, const std::string &name, StringBuilder &sb, const std::string &prefix)
532 {
533     for (size_t i = 0; i < type->GetMemberNumber(); i++) {
534         AutoPtr<ASTType> memberType = type->GetMemberType(i);
535         std::string memberName = type->GetMemberName(i);
536         std::string varName = StringHelper::Format("%s->%s", name.c_str(), memberName.c_str());
537         switch (memberType->GetTypeKind()) {
538             case TypeKind::TYPE_STRING:
539             case TypeKind::TYPE_STRUCT:
540             case TypeKind::TYPE_ARRAY:
541             case TypeKind::TYPE_LIST:
542                 memberType->EmitMemoryRecycle(varName, false, false, sb, prefix);
543                 sb.Append("\n");
544                 break;
545             default:
546                 break;
547         }
548     }
549 }
550 
GetUtilMethods(UtilMethodMap & methods)551 void CCustomTypesCodeEmitter::GetUtilMethods(UtilMethodMap &methods)
552 {
553     for (const auto &typePair : ast_->GetTypes()) {
554         typePair.second->RegisterWriteMethod(Options::GetInstance().GetTargetLanguage(), SerMode::CUSTOM_SER, methods);
555         typePair.second->RegisterReadMethod(Options::GetInstance().GetTargetLanguage(), SerMode::CUSTOM_SER, methods);
556     }
557 }
558 } // namespace HDI
559 } // namespace OHOS