• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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