• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "codegen/cpp_custom_types_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12 
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)15 bool CppCustomTypesCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
16 {
17     if (ast_->GetASTFileType() != ASTFileType::AST_TYPES) {
18         return false;
19     }
20 
21     directory_ = GetFileParentPath(targetDirectory);
22     if (!File::CreateParentDir(directory_)) {
23         Logger::E("CppCustomTypesCodeEmitter", "Create '%s' failed!", directory_.c_str());
24         return false;
25     }
26 
27     return true;
28 }
29 
EmitCode()30 void CppCustomTypesCodeEmitter::EmitCode()
31 {
32     if (Options::GetInstance().DoPassthrough()) {
33         EmitPassthroughCustomTypesHeaderFile();
34     } else {
35         EmitCustomTypesHeaderFile();
36         EmitCustomTypesSourceFile();
37     }
38 }
39 
EmitPassthroughCustomTypesHeaderFile()40 void CppCustomTypesCodeEmitter::EmitPassthroughCustomTypesHeaderFile()
41 {
42     std::string filePath =
43         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
44     File file(filePath, File::WRITE);
45     std::string marcoName = StringHelper::Format("%s.%s", ast_->GetPackageName().c_str(), baseName_.c_str());
46     StringBuilder sb;
47 
48     EmitLicense(sb);
49     EmitHeadMacro(sb, marcoName);
50     sb.Append("\n");
51     EmitPassthroughHeaderFileInclusions(sb);
52     sb.Append("\n");
53     EmitBeginNamespace(sb);
54     sb.Append("\n");
55     EmitUsingNamespace(sb);
56     sb.Append("\n");
57     EmitCustomTypeDecls(sb);
58     EmitEndNamespace(sb);
59     sb.Append("\n");
60     EmitTailMacro(sb, marcoName);
61 
62     std::string data = sb.ToString();
63     file.WriteData(data.c_str(), data.size());
64     file.Flush();
65     file.Close();
66 }
67 
EmitPassthroughHeaderFileInclusions(StringBuilder & sb)68 void CppCustomTypesCodeEmitter::EmitPassthroughHeaderFileInclusions(StringBuilder &sb)
69 {
70     HeaderFile::HeaderFileSet headerFiles;
71 
72     GetStdlibInclusions(headerFiles);
73     GetImportInclusions(headerFiles);
74 
75     for (const auto &file : headerFiles) {
76         sb.AppendFormat("%s\n", file.ToString().c_str());
77     }
78 }
79 
EmitCustomTypesHeaderFile()80 void CppCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
81 {
82     std::string filePath =
83         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
84     File file(filePath, File::WRITE);
85     std::string marcoName = StringHelper::Format("%s.%s", ast_->GetPackageName().c_str(), baseName_.c_str());
86     StringBuilder sb;
87 
88     EmitLicense(sb);
89     EmitHeadMacro(sb, marcoName);
90     sb.Append("\n");
91     EmitHeaderFileInclusions(sb);
92     sb.Append("\n");
93     EmitInterfaceBuffSizeMacro(sb);
94     sb.Append("\n");
95     EmitBeginNamespace(sb);
96     sb.Append("\n");
97     EmitUsingNamespace(sb);
98     sb.Append("\n");
99     EmitCustomTypeDecls(sb);
100     sb.Append("\n");
101     EmitCustomTypeFuncDecl(sb);
102     sb.Append("\n");
103     EmitEndNamespace(sb);
104     sb.Append("\n");
105     EmitTailMacro(sb, marcoName);
106 
107     std::string data = sb.ToString();
108     file.WriteData(data.c_str(), data.size());
109     file.Flush();
110     file.Close();
111 }
112 
EmitHeaderFileInclusions(StringBuilder & sb)113 void CppCustomTypesCodeEmitter::EmitHeaderFileInclusions(StringBuilder &sb)
114 {
115     HeaderFile::HeaderFileSet headerFiles;
116 
117     GetStdlibInclusions(headerFiles);
118     GetImportInclusions(headerFiles);
119     GetHeaderOtherLibInclusions(headerFiles);
120 
121     for (const auto &file : headerFiles) {
122         sb.AppendFormat("%s\n", file.ToString().c_str());
123     }
124 }
125 
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)126 void CppCustomTypesCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
127 {
128     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
129 }
130 
EmitUsingNamespace(StringBuilder & sb)131 void CppCustomTypesCodeEmitter::EmitUsingNamespace(StringBuilder &sb)
132 {
133     sb.Append("using namespace OHOS;\n");
134     EmitImportUsingNamespace(sb);
135 }
136 
EmitCustomTypeDecls(StringBuilder & sb)137 void CppCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder &sb)
138 {
139     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
140         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
141         EmitCustomTypeDecl(sb, type);
142         if (i + 1 < ast_->GetTypeDefinitionNumber()) {
143             sb.Append("\n");
144         }
145     }
146 }
147 
EmitCustomTypeDecl(StringBuilder & sb,const AutoPtr<ASTType> & type)148 void CppCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder &sb, const AutoPtr<ASTType> &type)
149 {
150     switch (type->GetTypeKind()) {
151         case TypeKind::TYPE_ENUM: {
152             AutoPtr<ASTEnumType> enumType = dynamic_cast<ASTEnumType *>(type.Get());
153             sb.Append(enumType->EmitCppTypeDecl()).Append("\n");
154             break;
155         }
156         case TypeKind::TYPE_STRUCT: {
157             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
158             sb.Append(structType->EmitCppTypeDecl()).Append("\n");
159             break;
160         }
161         case TypeKind::TYPE_UNION: {
162             AutoPtr<ASTUnionType> unionType = dynamic_cast<ASTUnionType *>(type.Get());
163             sb.Append(unionType->EmitCppTypeDecl()).Append("\n");
164             break;
165         }
166         default:
167             break;
168     }
169 }
170 
EmitCustomTypeFuncDecl(StringBuilder & sb)171 void CppCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder &sb)
172 {
173     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
174         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
175         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
176             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
177             EmitCustomTypeMarshallingDecl(sb, structType);
178             sb.Append("\n");
179             EmitCustomTypeUnmarshallingDecl(sb, structType);
180             if (i + 1 < ast_->GetTypeDefinitionNumber()) {
181                 sb.Append("\n");
182             }
183         }
184     }
185 }
186 
EmitCustomTypeMarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)187 void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
188 {
189     std::string objName("dataBlock");
190     sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel &data, const %s& %s);\n", type->GetName().c_str(),
191         type->EmitCppType().c_str(), objName.c_str());
192 }
193 
EmitCustomTypeUnmarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)194 void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
195 {
196     std::string objName("dataBlock");
197     sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel &data, %s& %s);\n", type->GetName().c_str(),
198         type->EmitCppType().c_str(), objName.c_str());
199 }
200 
EmitCustomTypesSourceFile()201 void CppCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
202 {
203     std::string filePath =
204         File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(baseName_).c_str()));
205     File file(filePath, File::WRITE);
206     StringBuilder sb;
207 
208     EmitLicense(sb);
209     EmitSourceFileInclusions(sb);
210     sb.Append("\n");
211     EmitBeginNamespace(sb);
212     sb.Append("\n");
213     UtilMethodMap utilMethods;
214     GetUtilMethods(utilMethods);
215     EmitUtilMethods(sb, "", utilMethods, true);
216     sb.Append("\n");
217     EmitUtilMethods(sb, "", utilMethods, false);
218     sb.Append("\n");
219     EmitCustomTypeDataProcess(sb);
220     sb.Append("\n");
221     EmitEndNamespace(sb);
222 
223     std::string data = sb.ToString();
224     file.WriteData(data.c_str(), data.size());
225     file.Flush();
226     file.Close();
227 }
228 
EmitSourceFileInclusions(StringBuilder & sb)229 void CppCustomTypesCodeEmitter::EmitSourceFileInclusions(StringBuilder &sb)
230 {
231     HeaderFile::HeaderFileSet headerFiles;
232 
233     headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_));
234     GetSourceOtherLibInclusions(headerFiles);
235 
236     for (const auto &file : headerFiles) {
237         sb.AppendFormat("%s\n", file.ToString().c_str());
238     }
239 }
240 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)241 void CppCustomTypesCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
242 {
243     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
244     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
245 }
246 
EmitCustomTypeDataProcess(StringBuilder & sb)247 void CppCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder &sb)
248 {
249     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
250         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
251         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
252             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
253             EmitCustomTypeMarshallingImpl(sb, structType);
254             sb.Append("\n");
255             EmitCustomTypeUnmarshallingImpl(sb, structType);
256             if (i + 1 < ast_->GetTypeDefinitionNumber()) {
257                 sb.Append("\n");
258             }
259         }
260     }
261 }
262 
EmitCustomTypeMarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)263 void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
264 {
265     std::string objName("dataBlock");
266 
267     sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel& data, const %s& %s)\n", type->EmitCppType().c_str(),
268         type->EmitCppType().c_str(), objName.c_str());
269     sb.Append("{\n");
270 
271     if (type->IsPod()) {
272         sb.Append(TAB).AppendFormat("if (!data.WriteUnpadBuffer((const void*)&%s, sizeof(%s))) {\n", objName.c_str(),
273             type->EmitCppType().c_str());
274         sb.Append(TAB).Append(TAB).Append("return false;\n");
275         sb.Append(TAB).Append("}\n");
276     } else {
277         for (size_t i = 0; i < type->GetMemberNumber(); i++) {
278             AutoPtr<ASTType> memberType = type->GetMemberType(i);
279             std::string memberName = type->GetMemberName(i);
280 
281             std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
282             memberType->EmitCppMarshalling("data", name, sb, TAB);
283             if (i + 1 < type->GetMemberNumber()) {
284                 sb.Append("\n");
285             }
286         }
287     }
288 
289     sb.Append(TAB).Append("return true;\n");
290     sb.Append("}\n");
291 }
292 
EmitCustomTypeUnmarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)293 void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
294 {
295     std::string objName("dataBlock");
296 
297     sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel& data, %s& %s)\n", type->GetName().c_str(),
298         type->EmitCppType().c_str(), objName.c_str());
299     sb.Append("{\n");
300 
301     if (type->IsPod()) {
302         std::string objPtrName = StringHelper::Format("%sPtr", objName.c_str());
303         sb.Append(TAB).AppendFormat("const %s *%s = reinterpret_cast<const %s*>(data.ReadUnpadBuffer(sizeof(%s)));\n",
304             type->EmitCppType().c_str(), objPtrName.c_str(), type->EmitCppType().c_str(), type->EmitCppType().c_str());
305         sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objPtrName.c_str());
306         sb.Append(TAB).Append(TAB).Append("return false;\n");
307         sb.Append(TAB).Append("}\n\n");
308         sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", objName.c_str(),
309             type->EmitCppType().c_str(), objPtrName.c_str(), type->EmitCppType().c_str());
310         sb.Append(TAB).Append(TAB).Append("return false;\n");
311         sb.Append(TAB).Append("}\n");
312     } else {
313         for (size_t i = 0; i < type->GetMemberNumber(); i++) {
314             AutoPtr<ASTType> memberType = type->GetMemberType(i);
315             std::string memberName = type->GetMemberName(i);
316             std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
317             if (i > 0) {
318                 sb.Append("\n");
319             }
320 
321             if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) {
322                 std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
323                 memberType->EmitCppUnMarshalling("data", cpName, sb, TAB, false);
324                 sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
325                     name.c_str(), memberType->EmitCppType().c_str(), cpName.c_str(),
326                     memberType->EmitCppType().c_str());
327                 sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to memcpy %s\", __func__);\n",
328                     name.c_str());
329                 sb.Append(TAB).Append(TAB).Append("return false;\n");
330                 sb.Append(TAB).Append("}\n");
331             } else if (memberType->GetTypeKind() == TypeKind::TYPE_STRING) {
332                 std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
333                 memberType->EmitCppUnMarshalling("data", cpName, sb, TAB, false);
334                 sb.Append(TAB).AppendFormat("%s = %s;\n", name.c_str(), cpName.c_str());
335             } else {
336                 memberType->EmitCppUnMarshalling("data", name, sb, TAB, false);
337             }
338         }
339     }
340     sb.Append(TAB).AppendFormat("return true;\n", objName.c_str());
341     sb.Append("}\n");
342 }
343 
EmitBeginNamespace(StringBuilder & sb)344 void CppCustomTypesCodeEmitter::EmitBeginNamespace(StringBuilder &sb)
345 {
346     std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
347     for (const auto &nspace : cppNamespaceVec) {
348         sb.AppendFormat("namespace %s {\n", nspace.c_str());
349     }
350 }
351 
EmitEndNamespace(StringBuilder & sb)352 void CppCustomTypesCodeEmitter::EmitEndNamespace(StringBuilder &sb)
353 {
354     std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
355     for (auto nspaceIter = cppNamespaceVec.rbegin(); nspaceIter != cppNamespaceVec.rend(); nspaceIter++) {
356         sb.AppendFormat("} // %s\n", nspaceIter->c_str());
357     }
358 }
359 
GetUtilMethods(UtilMethodMap & methods)360 void CppCustomTypesCodeEmitter::GetUtilMethods(UtilMethodMap &methods)
361 {
362     for (const auto &typePair : ast_->GetTypes()) {
363         typePair.second->RegisterWriteMethod(Options::GetInstance().GetTargetLanguage(), SerMode::CUSTOM_SER, methods);
364         typePair.second->RegisterReadMethod(Options::GetInstance().GetTargetLanguage(), SerMode::CUSTOM_SER, methods);
365     }
366 }
367 } // namespace HDI
368 } // namespace OHOS
369