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