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/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 String & targetDirectory)15 bool CppCustomTypesCodeEmitter::ResolveDirectory(const String& targetDirectory)
16 {
17 if (ast_->GetASTFileType() != ASTFileType::AST_TYPES) {
18 return false;
19 }
20
21 directory_ = GetFilePath(targetDirectory);
22 if (!File::CreateParentDir(directory_)) {
23 Logger::E("CppCustomTypesCodeEmitter", "Create '%s' failed!", directory_.string());
24 return false;
25 }
26
27 return true;
28 }
29
EmitCode()30 void CppCustomTypesCodeEmitter::EmitCode()
31 {
32 EmitCustomTypesHeaderFile();
33 EmitCustomTypesSourceFile();
34 }
35
EmitCustomTypesHeaderFile()36 void CppCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
37 {
38 String filePath = String::Format("%s/%s.h", directory_.string(), FileName(baseName_).string());
39 File file(filePath, File::WRITE);
40 String marcoName = String::Format("%s.%s", ast_->GetPackageName().string(), baseName_.string());
41 StringBuilder sb;
42
43 EmitLicense(sb);
44 EmitHeadMacro(sb, marcoName);
45 sb.Append("\n");
46 EmitHeaderFileInclusions(sb);
47 sb.Append("\n");
48 EmitInterfaceBuffSizeMacro(sb);
49 sb.Append("\n");
50 EmitBeginNamespace(sb);
51 sb.Append("\n");
52 EmitUsingNamespace(sb);
53 sb.Append("\n");
54 EmitCustomTypeDecls(sb);
55 sb.Append("\n");
56 EmitCustomTypeFuncDecl(sb);
57 sb.Append("\n");
58 EmitEndNamespace(sb);
59 sb.Append("\n");
60 EmitTailMacro(sb, marcoName);
61
62 String data = sb.ToString();
63 file.WriteData(data.string(), data.GetLength());
64 file.Flush();
65 file.Close();
66 }
67
EmitHeaderFileInclusions(StringBuilder & sb)68 void CppCustomTypesCodeEmitter::EmitHeaderFileInclusions(StringBuilder& sb)
69 {
70 HeaderFile::HeaderFileSet headerFiles;
71
72 GetStdlibInclusions(headerFiles);
73 GetImportInclusions(headerFiles);
74 GetHeaderOtherLibInclusions(headerFiles);
75
76 for (const auto& file : headerFiles) {
77 sb.AppendFormat("%s\n", file.ToString().string());
78 }
79 }
80
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)81 void CppCustomTypesCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
82 {
83 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel"));
84 }
85
EmitCustomTypeDecls(StringBuilder & sb)86 void CppCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder& sb)
87 {
88 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
89 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
90 EmitCustomTypeDecl(sb, type);
91 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
92 sb.Append("\n");
93 }
94 }
95 }
96
EmitCustomTypeDecl(StringBuilder & sb,const AutoPtr<ASTType> & type)97 void CppCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr<ASTType>& type)
98 {
99 switch (type->GetTypeKind()) {
100 case TypeKind::TYPE_ENUM: {
101 AutoPtr<ASTEnumType> enumType = dynamic_cast<ASTEnumType*>(type.Get());
102 sb.Append(enumType->EmitCppTypeDecl()).Append("\n");
103 break;
104 }
105 case TypeKind::TYPE_STRUCT: {
106 AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType*>(type.Get());
107 sb.Append(structType->EmitCppTypeDecl()).Append("\n");
108 break;
109 }
110 case TypeKind::TYPE_UNION: {
111 AutoPtr<ASTUnionType> unionType = dynamic_cast<ASTUnionType*>(type.Get());
112 sb.Append(unionType->EmitCppTypeDecl()).Append("\n");
113 break;
114 }
115 default:
116 break;
117 }
118 }
119
EmitCustomTypeFuncDecl(StringBuilder & sb)120 void CppCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder& sb)
121 {
122 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
123 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
124 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
125 AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType*>(type.Get());
126 EmitCustomTypeMarshallingDecl(sb, structType);
127 sb.Append("\n");
128 EmitCustomTypeUnmarshallingDecl(sb, structType);
129 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
130 sb.Append("\n");
131 }
132 }
133 }
134 }
135
EmitCustomTypeMarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)136 void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder& sb, const AutoPtr<ASTStructType>& type)
137 {
138 String objName("dataBlock");
139 sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel &data, const %s& %s);\n",
140 type->GetName().string(), type->EmitCppType().string(), objName.string());
141 }
142
EmitCustomTypeUnmarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)143 void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, const AutoPtr<ASTStructType>& type)
144 {
145 String objName("dataBlock");
146 sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel &data, %s& %s);\n",
147 type->GetName().string(), type->EmitCppType().string(), objName.string());
148 }
149
EmitCustomTypesSourceFile()150 void CppCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
151 {
152 String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(baseName_).string());
153 File file(filePath, File::WRITE);
154 StringBuilder sb;
155
156 EmitLicense(sb);
157 EmitSourceFileInclusions(sb);
158 sb.Append("\n");
159 EmitBeginNamespace(sb);
160 sb.Append("\n");
161 EmitCustomTypeDataProcess(sb);
162 sb.Append("\n");
163 EmitEndNamespace(sb);
164
165 String data = sb.ToString();
166 file.WriteData(data.string(), data.GetLength());
167 file.Flush();
168 file.Close();
169 }
170
EmitSourceFileInclusions(StringBuilder & sb)171 void CppCustomTypesCodeEmitter::EmitSourceFileInclusions(StringBuilder& sb)
172 {
173 HeaderFile::HeaderFileSet headerFiles;
174
175 headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_)));
176 GetSourceOtherLibInclusions(headerFiles);
177
178 for (const auto& file : headerFiles) {
179 sb.AppendFormat("%s\n", file.ToString().string());
180 }
181 }
182
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)183 void CppCustomTypesCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
184 {
185 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log"));
186 const AST::TypeStringMap& types = ast_->GetTypes();
187 for (const auto& pair : types) {
188 AutoPtr<ASTType> type = pair.second;
189 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT || type->GetTypeKind() == TypeKind::TYPE_UNION) {
190 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
191 break;
192 }
193 }
194 }
195
EmitCustomTypeDataProcess(StringBuilder & sb)196 void CppCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder& sb)
197 {
198 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
199 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
200 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
201 AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType*>(type.Get());
202 EmitCustomTypeMarshallingImpl(sb, structType);
203 sb.Append("\n");
204 EmitCustomTypeUnmarshallingImpl(sb, structType);
205 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
206 sb.Append("\n");
207 }
208 }
209 }
210 }
211
EmitCustomTypeMarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)212 void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr<ASTStructType>& type)
213 {
214 String objName("dataBlock");
215
216 sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel& data, const %s& %s)\n",
217 type->EmitCppType().string(), type->EmitCppType().string(), objName.string());
218 sb.Append("{\n");
219 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
220 AutoPtr<ASTType> memberType = type->GetMemberType(i);
221 String memberName = type->GetMemberName(i);
222
223 String name = String::Format("%s.%s", objName.string(), memberName.string());
224 memberType->EmitCppMarshalling("data", name, sb, g_tab);
225 if (i + 1 < type->GetMemberNumber()) {
226 sb.Append("\n");
227 }
228 }
229
230 sb.Append(g_tab).Append("return true;\n");
231 sb.Append("}\n");
232 }
233
EmitCustomTypeUnmarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)234 void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr<ASTStructType>& type)
235 {
236 String objName("dataBlock");
237
238 sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel& data, %s& %s)\n",
239 type->GetName().string(), type->EmitCppType().string(), objName.string());
240 sb.Append("{\n");
241
242 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
243 AutoPtr<ASTType> memberType = type->GetMemberType(i);
244 String memberName = type->GetMemberName(i);
245 String name = String::Format("%s.%s", objName.string(), memberName.string());
246 if (i > 0) {
247 sb.Append("\n");
248 }
249
250 if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) {
251 String cpName = String::Format("%sCp", memberName.string());
252 memberType->EmitCppUnMarshalling("data", cpName, sb, g_tab, false);
253 sb.Append(g_tab).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", name.string(),
254 memberType->EmitCppType().string(), cpName.string(), memberType->EmitCppType().string());
255 } else {
256 memberType->EmitCppUnMarshalling("data", name, sb, g_tab, false);
257 }
258 }
259
260 sb.Append(g_tab).AppendFormat("return true;\n", objName.string());
261 sb.Append("}\n");
262 }
263
EmitBeginNamespace(StringBuilder & sb)264 void CppCustomTypesCodeEmitter::EmitBeginNamespace(StringBuilder& sb)
265 {
266 std::vector<String> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
267 for (const auto& nspace : cppNamespaceVec) {
268 sb.AppendFormat("namespace %s {\n", nspace.string());
269 }
270 }
271
EmitEndNamespace(StringBuilder & sb)272 void CppCustomTypesCodeEmitter::EmitEndNamespace(StringBuilder& sb)
273 {
274 std::vector<String> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
275 for (auto nspaceIter = cppNamespaceVec.rbegin(); nspaceIter != cppNamespaceVec.rend(); nspaceIter++) {
276 sb.AppendFormat("} // %s\n", nspaceIter->string());
277 }
278 }
279 } // namespace HDI
280 } // namespace OHOS
281