• 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     switch (mode_) {
33         case GenMode::PASSTHROUGH: {
34             EmitPassthroughCustomTypesHeaderFile();
35             break;
36         }
37         case GenMode::IPC: {
38             EmitCustomTypesHeaderFile();
39             EmitCustomTypesSourceFile();
40         }
41         default:
42             break;
43     }
44 }
45 
EmitPassthroughCustomTypesHeaderFile()46 void CppCustomTypesCodeEmitter::EmitPassthroughCustomTypesHeaderFile()
47 {
48     std::string filePath =
49         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
50     File file(filePath, File::WRITE);
51     std::string marcoName = StringHelper::Format("%s.%s", ast_->GetPackageName().c_str(), baseName_.c_str());
52     StringBuilder sb;
53 
54     EmitLicense(sb);
55     EmitHeadMacro(sb, marcoName);
56     sb.Append("\n");
57     EmitPassthroughHeaderFileInclusions(sb);
58     sb.Append("\n");
59     EmitBeginNamespace(sb);
60     sb.Append("\n");
61     EmitUsingNamespace(sb);
62     sb.Append("\n");
63     EmitCustomTypeDecls(sb);
64     EmitEndNamespace(sb);
65     sb.Append("\n");
66     EmitTailMacro(sb, marcoName);
67 
68     std::string data = sb.ToString();
69     file.WriteData(data.c_str(), data.size());
70     file.Flush();
71     file.Close();
72 }
73 
EmitPassthroughHeaderFileInclusions(StringBuilder & sb)74 void CppCustomTypesCodeEmitter::EmitPassthroughHeaderFileInclusions(StringBuilder &sb)
75 {
76     HeaderFile::HeaderFileSet headerFiles;
77     headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdbool");
78     headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdint");
79     GetStdlibInclusions(headerFiles);
80     GetImportInclusions(headerFiles);
81 
82     for (const auto &file : headerFiles) {
83         sb.AppendFormat("%s\n", file.ToString().c_str());
84     }
85 }
86 
EmitCustomTypesHeaderFile()87 void CppCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
88 {
89     std::string filePath =
90         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
91     File file(filePath, File::WRITE);
92     std::string marcoName = StringHelper::Format("%s.%s", ast_->GetPackageName().c_str(), baseName_.c_str());
93     StringBuilder sb;
94 
95     EmitLicense(sb);
96     EmitHeadMacro(sb, marcoName);
97     sb.Append("\n");
98     EmitHeaderFileInclusions(sb);
99     sb.Append("\n");
100     EmitInterfaceBuffSizeMacro(sb);
101     sb.Append("\n");
102     EmitForwardDeclaration(sb);
103     sb.Append("\n");
104     EmitBeginNamespace(sb);
105     sb.Append("\n");
106     EmitUsingNamespace(sb);
107     sb.Append("\n");
108     EmitCustomTypeDecls(sb);
109     sb.Append("\n");
110     EmitCustomTypeFuncDecl(sb);
111     sb.Append("\n");
112     EmitEndNamespace(sb);
113     sb.Append("\n");
114     EmitTailMacro(sb, marcoName);
115 
116     std::string data = sb.ToString();
117     file.WriteData(data.c_str(), data.size());
118     file.Flush();
119     file.Close();
120 }
121 
EmitHeaderFileInclusions(StringBuilder & sb)122 void CppCustomTypesCodeEmitter::EmitHeaderFileInclusions(StringBuilder &sb)
123 {
124     HeaderFile::HeaderFileSet headerFiles;
125     headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdbool");
126     headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdint");
127     GetStdlibInclusions(headerFiles);
128     GetImportInclusions(headerFiles);
129 
130     for (const auto &file : headerFiles) {
131         sb.AppendFormat("%s\n", file.ToString().c_str());
132     }
133 }
134 
EmitForwardDeclaration(StringBuilder & sb) const135 void CppCustomTypesCodeEmitter::EmitForwardDeclaration(StringBuilder &sb) const
136 {
137     sb.Append("namespace OHOS {\n");
138     sb.Append("class MessageParcel;\n");
139     sb.Append("}\n");
140 }
141 
EmitUsingNamespace(StringBuilder & sb)142 void CppCustomTypesCodeEmitter::EmitUsingNamespace(StringBuilder &sb)
143 {
144     sb.Append("using namespace OHOS;\n");
145     EmitImportUsingNamespace(sb);
146 }
147 
EmitCustomTypeDecls(StringBuilder & sb) const148 void CppCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder &sb) const
149 {
150     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
151         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
152         EmitCustomTypeDecl(sb, type);
153         if (i + 1 < ast_->GetTypeDefinitionNumber()) {
154             sb.Append("\n");
155         }
156     }
157 }
158 
EmitCustomTypeDecl(StringBuilder & sb,const AutoPtr<ASTType> & type) const159 void CppCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder &sb, const AutoPtr<ASTType> &type) const
160 {
161     switch (type->GetTypeKind()) {
162         case TypeKind::TYPE_ENUM: {
163             AutoPtr<ASTEnumType> enumType = dynamic_cast<ASTEnumType *>(type.Get());
164             sb.Append(enumType->EmitCppTypeDecl()).Append("\n");
165             break;
166         }
167         case TypeKind::TYPE_STRUCT: {
168             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
169             sb.Append(structType->EmitCppTypeDecl()).Append("\n");
170             break;
171         }
172         case TypeKind::TYPE_UNION: {
173             AutoPtr<ASTUnionType> unionType = dynamic_cast<ASTUnionType *>(type.Get());
174             sb.Append(unionType->EmitCppTypeDecl()).Append("\n");
175             break;
176         }
177         default:
178             break;
179     }
180 }
181 
EmitCustomTypeFuncDecl(StringBuilder & sb) const182 void CppCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder &sb) const
183 {
184     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
185         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
186         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
187             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
188             EmitCustomTypeMarshallingDecl(sb, structType);
189             sb.Append("\n");
190             EmitCustomTypeUnmarshallingDecl(sb, structType);
191             if (i + 1 < ast_->GetTypeDefinitionNumber()) {
192                 sb.Append("\n");
193             }
194         }
195     }
196 }
197 
EmitCustomTypeMarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type) const198 void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(
199     StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
200 {
201     std::string objName("dataBlock");
202     sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel &data, const %s& %s);\n", type->GetName().c_str(),
203         type->EmitCppType().c_str(), objName.c_str());
204 }
205 
EmitCustomTypeUnmarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type) const206 void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder &sb,
207     const AutoPtr<ASTStructType> &type) const
208 {
209     std::string objName("dataBlock");
210     sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel &data, %s& %s);\n", type->GetName().c_str(),
211         type->EmitCppType().c_str(), objName.c_str());
212 }
213 
EmitCustomTypesSourceFile()214 void CppCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
215 {
216     std::string filePath =
217         File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(baseName_).c_str()));
218     File file(filePath, File::WRITE);
219     StringBuilder sb;
220 
221     EmitLicense(sb);
222     EmitSourceFileInclusions(sb);
223     sb.Append("\n");
224     EmitBeginNamespace(sb);
225     sb.Append("\n");
226     UtilMethodMap utilMethods;
227     GetUtilMethods(utilMethods);
228     EmitUtilMethods(sb, "", utilMethods, true);
229     sb.Append("\n");
230     EmitUtilMethods(sb, "", utilMethods, false);
231     sb.Append("\n");
232     EmitCustomTypeDataProcess(sb);
233     sb.Append("\n");
234     EmitEndNamespace(sb);
235 
236     std::string data = sb.ToString();
237     file.WriteData(data.c_str(), data.size());
238     file.Flush();
239     file.Close();
240 }
241 
EmitSourceFileInclusions(StringBuilder & sb)242 void CppCustomTypesCodeEmitter::EmitSourceFileInclusions(StringBuilder &sb)
243 {
244     HeaderFile::HeaderFileSet headerFiles;
245 
246     headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_));
247     GetSourceOtherLibInclusions(headerFiles);
248 
249     for (const auto &file : headerFiles) {
250         sb.AppendFormat("%s\n", file.ToString().c_str());
251     }
252 }
253 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const254 void CppCustomTypesCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
255 {
256     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
257     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
258     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
259 }
260 
EmitCustomTypeDataProcess(StringBuilder & sb) const261 void CppCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder &sb) const
262 {
263     for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
264         AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
265         if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
266             AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
267             EmitCustomTypeMarshallingImpl(sb, structType);
268             sb.Append("\n");
269             EmitCustomTypeUnmarshallingImpl(sb, structType);
270             if (i + 1 < ast_->GetTypeDefinitionNumber()) {
271                 sb.Append("\n");
272             }
273         }
274     }
275 }
276 
EmitCustomTypeMarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type) const277 void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(
278     StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
279 {
280     std::string objName("dataBlock");
281 
282     sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel& data, const %s& %s)\n", type->GetName().c_str(),
283         type->EmitCppType().c_str(), objName.c_str());
284     sb.Append("{\n");
285 
286     if (type->IsPod()) {
287         sb.Append(TAB).AppendFormat("if (!data.WriteUnpadBuffer((const void*)&%s, sizeof(%s))) {\n", objName.c_str(),
288             type->EmitCppType().c_str());
289         sb.Append(TAB).Append(TAB).Append("return false;\n");
290         sb.Append(TAB).Append("}\n");
291     } else {
292         for (size_t i = 0; i < type->GetMemberNumber(); i++) {
293             AutoPtr<ASTType> memberType = type->GetMemberType(i);
294             std::string memberName = type->GetMemberName(i);
295 
296             std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
297             memberType->EmitCppMarshalling("data", name, sb, TAB);
298             if (i + 1 < type->GetMemberNumber()) {
299                 sb.Append("\n");
300             }
301         }
302     }
303 
304     sb.Append(TAB).Append("return true;\n");
305     sb.Append("}\n");
306 }
307 
EmitCustomTypeUnmarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type) const308 void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(
309     StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
310 {
311     std::string objName("dataBlock");
312 
313     sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel& data, %s& %s)\n", type->GetName().c_str(),
314         type->EmitCppType().c_str(), objName.c_str());
315     sb.Append("{\n");
316 
317     if (type->IsPod()) {
318         std::string objPtrName = StringHelper::Format("%sPtr", objName.c_str());
319         sb.Append(TAB).AppendFormat("const %s *%s = reinterpret_cast<const %s*>(data.ReadUnpadBuffer(sizeof(%s)));\n",
320             type->EmitCppType().c_str(), objPtrName.c_str(), type->EmitCppType().c_str(), type->EmitCppType().c_str());
321         sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objPtrName.c_str());
322         sb.Append(TAB).Append(TAB).Append("return false;\n");
323         sb.Append(TAB).Append("}\n\n");
324         sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", objName.c_str(),
325             type->EmitCppType().c_str(), objPtrName.c_str(), type->EmitCppType().c_str());
326         sb.Append(TAB).Append(TAB).Append("return false;\n");
327         sb.Append(TAB).Append("}\n");
328     } else {
329         for (size_t i = 0; i < type->GetMemberNumber(); i++) {
330             AutoPtr<ASTType> memberType = type->GetMemberType(i);
331             std::string memberName = type->GetMemberName(i);
332             std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
333             if (i > 0) {
334                 sb.Append("\n");
335             }
336 
337             if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) {
338                 std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
339                 memberType->EmitCppUnMarshalling("data", cpName, sb, TAB, false);
340                 sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
341                     name.c_str(), memberType->EmitCppType().c_str(), cpName.c_str(),
342                     memberType->EmitCppType().c_str());
343                 sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to memcpy %s\", __func__);\n",
344                     name.c_str());
345                 sb.Append(TAB).Append(TAB).Append("return false;\n");
346                 sb.Append(TAB).Append("}\n");
347             } else if (memberType->GetTypeKind() == TypeKind::TYPE_STRING) {
348                 std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
349                 memberType->EmitCppUnMarshalling("data", cpName, sb, TAB, false);
350                 sb.Append(TAB).AppendFormat("%s = %s;\n", name.c_str(), cpName.c_str());
351             } else {
352                 memberType->EmitCppUnMarshalling("data", name, sb, TAB, false);
353             }
354         }
355     }
356     sb.Append(TAB).AppendFormat("return true;\n", objName.c_str());
357     sb.Append("}\n");
358 }
359 
EmitBeginNamespace(StringBuilder & sb)360 void CppCustomTypesCodeEmitter::EmitBeginNamespace(StringBuilder &sb)
361 {
362     std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
363     for (const auto &nspace : cppNamespaceVec) {
364         sb.AppendFormat("namespace %s {\n", nspace.c_str());
365     }
366 }
367 
EmitEndNamespace(StringBuilder & sb)368 void CppCustomTypesCodeEmitter::EmitEndNamespace(StringBuilder &sb)
369 {
370     std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
371     for (std::vector<std::string>::const_reverse_iterator nspaceIter = cppNamespaceVec.rbegin();
372         nspaceIter != cppNamespaceVec.rend(); ++nspaceIter) {
373         sb.AppendFormat("} // %s\n", nspaceIter->c_str());
374     }
375 }
376 
GetUtilMethods(UtilMethodMap & methods)377 void CppCustomTypesCodeEmitter::GetUtilMethods(UtilMethodMap &methods)
378 {
379     for (const auto &typePair : ast_->GetTypes()) {
380         typePair.second->RegisterWriteMethod(Options::GetInstance().GetLanguage(), SerMode::CUSTOM_SER, methods);
381         typePair.second->RegisterReadMethod(Options::GetInstance().GetLanguage(), SerMode::CUSTOM_SER, methods);
382     }
383 }
384 } // namespace HDI
385 } // namespace OHOS
386