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