• 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_code_emitter.h"
10 
11 #include <regex>
12 #include <unordered_set>
13 
14 #include "util/options.h"
15 
16 #include "util/logger.h"
17 
18 namespace OHOS {
19 namespace HDI {
GetStdlibInclusions(HeaderFile::HeaderFileSet & headerFiles)20 void CppCodeEmitter::GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles)
21 {
22     const AST::TypeStringMap &types = ast_->GetTypes();
23     for (const auto &pair : types) {
24         AutoPtr<ASTType> type = pair.second;
25         switch (type->GetTypeKind()) {
26             case TypeKind::TYPE_STRING: {
27                 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "string");
28                 break;
29             }
30             case TypeKind::TYPE_ARRAY:
31             case TypeKind::TYPE_LIST: {
32                 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "vector");
33                 break;
34             }
35             case TypeKind::TYPE_MAP: {
36                 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "map");
37                 break;
38             }
39             case TypeKind::TYPE_SMQ: {
40                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_smq");
41                 break;
42             }
43             case TypeKind::TYPE_ASHMEM: {
44                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "ashmem");
45                 break;
46             }
47             case TypeKind::TYPE_BUFFER_HANDLE: {
48                 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_buffer_handle");
49                 break;
50             }
51             default:
52                 break;
53         }
54     }
55 }
56 
GetImportInclusions(HeaderFile::HeaderFileSet & headerFiles)57 void CppCodeEmitter::GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles)
58 {
59     for (const auto &importPair : ast_->GetImports()) {
60         AutoPtr<AST> importAst = importPair.second;
61         std::string fileName = (importAst->GetASTFileType() == ASTFileType::AST_SEQUENCEABLE) ?
62             PackageToFilePath(importAst->GetName()) :
63             PackageToFilePath(importAst->GetFullName());
64         headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, fileName);
65     }
66 }
67 
EmitInterfaceMethodParameter(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix)68 void CppCodeEmitter::EmitInterfaceMethodParameter(
69     const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix)
70 {
71     sb.Append(prefix).Append(param->EmitCppParameter());
72 }
73 
EmitLicense(StringBuilder & sb)74 void CppCodeEmitter::EmitLicense(StringBuilder &sb)
75 {
76     if (ast_->GetLicense().empty()) {
77         return;
78     }
79     sb.Append(ast_->GetLicense()).Append("\n\n");
80 }
81 
EmitHeadMacro(StringBuilder & sb,const std::string & fullName)82 void CppCodeEmitter::EmitHeadMacro(StringBuilder &sb, const std::string &fullName)
83 {
84     std::string macroName = MacroName(fullName);
85     sb.Append("#ifndef ").Append(macroName).Append("\n");
86     sb.Append("#define ").Append(macroName).Append("\n");
87 }
88 
EmitTailMacro(StringBuilder & sb,const std::string & fullName)89 void CppCodeEmitter::EmitTailMacro(StringBuilder &sb, const std::string &fullName)
90 {
91     std::string macroName = MacroName(fullName);
92     sb.Append("#endif // ").Append(macroName);
93 }
94 
EmitHeadExternC(StringBuilder & sb)95 void CppCodeEmitter::EmitHeadExternC(StringBuilder &sb)
96 {
97     sb.Append("#ifdef __cplusplus\n");
98     sb.Append("extern \"C\" {\n");
99     sb.Append("#endif /* __cplusplus */\n");
100 }
101 
EmitTailExternC(StringBuilder & sb)102 void CppCodeEmitter::EmitTailExternC(StringBuilder &sb)
103 {
104     sb.Append("#ifdef __cplusplus\n");
105     sb.Append("}\n");
106     sb.Append("#endif /* __cplusplus */\n");
107 }
108 
isVersion(const std::string & name)109 bool CppCodeEmitter::isVersion(const std::string &name)
110 {
111     std::regex rVer("[V|v][0-9]+_[0-9]+");
112     return std::regex_match(name.c_str(), rVer);
113 }
114 
EmitCppNameSpaceVec(const std::string & namespaceStr)115 std::vector<std::string> CppCodeEmitter::EmitCppNameSpaceVec(const std::string &namespaceStr)
116 {
117     std::vector<std::string> result;
118     std::vector<std::string> namespaceVec = StringHelper::Split(namespaceStr, ".");
119     bool findVersion = false;
120 
121     std::string rootPackage = Options::GetInstance().GetRootPackage(namespaceStr);
122     size_t rootPackageNum = StringHelper::Split(rootPackage, ".").size();
123 
124     for (size_t i = 0; i < namespaceVec.size(); i++) {
125         std::string name;
126         if (i < rootPackageNum) {
127             name = StringHelper::StrToUpper(namespaceVec[i]);
128         } else if (!findVersion && isVersion(namespaceVec[i])) {
129             name = StringHelper::Replace(namespaceVec[i], 'v', 'V');
130             findVersion = true;
131         } else {
132             if (findVersion) {
133                 name = namespaceVec[i];
134             } else {
135                 name = PascalName(namespaceVec[i]);
136             }
137         }
138 
139         result.emplace_back(name);
140     }
141     return result;
142 }
143 
EmitPackageToNameSpace(const std::string & packageName)144 std::string CppCodeEmitter::EmitPackageToNameSpace(const std::string &packageName)
145 {
146     if (packageName.empty()) {
147         return packageName;
148     }
149 
150     StringBuilder nameSpaceStr;
151     std::vector<std::string> namespaceVec = EmitCppNameSpaceVec(packageName);
152     for (auto nameIter = namespaceVec.begin(); nameIter != namespaceVec.end(); nameIter++) {
153         nameSpaceStr.Append(*nameIter);
154         if (nameIter != namespaceVec.end() - 1) {
155             nameSpaceStr.Append("::");
156         }
157     }
158 
159     return nameSpaceStr.ToString();
160 }
161 
EmitBeginNamespace(StringBuilder & sb)162 void CppCodeEmitter::EmitBeginNamespace(StringBuilder &sb)
163 {
164     std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(interface_->GetNamespace()->ToString());
165     for (const auto &nspace : cppNamespaceVec) {
166         sb.AppendFormat("namespace %s {\n", nspace.c_str());
167     }
168 }
169 
EmitEndNamespace(StringBuilder & sb)170 void CppCodeEmitter::EmitEndNamespace(StringBuilder &sb)
171 {
172     std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(interface_->GetNamespace()->ToString());
173 
174     for (auto nspaceIter = cppNamespaceVec.rbegin(); nspaceIter != cppNamespaceVec.rend(); nspaceIter++) {
175         sb.AppendFormat("} // %s\n", nspaceIter->c_str());
176     }
177 }
178 
EmitUsingNamespace(StringBuilder & sb)179 void CppCodeEmitter::EmitUsingNamespace(StringBuilder &sb)
180 {
181     sb.Append("using namespace OHOS;\n");
182     sb.Append("using namespace OHOS::HDI;\n");
183     EmitImportUsingNamespace(sb);
184 }
185 
EmitNamespace(const std::string & packageName)186 std::string CppCodeEmitter::EmitNamespace(const std::string &packageName)
187 {
188     if (packageName.empty()) {
189         return packageName;
190     }
191 
192     size_t index = packageName.rfind('.');
193     return index != std::string::npos ? StringHelper::SubStr(packageName, 0, index) : packageName;
194 }
195 
EmitImportUsingNamespace(StringBuilder & sb)196 void CppCodeEmitter::EmitImportUsingNamespace(StringBuilder &sb)
197 {
198     using StringSet = std::unordered_set<std::string>;
199     StringSet namespaceSet;
200     std::string selfNameSpace = EmitPackageToNameSpace(EmitNamespace(ast_->GetFullName()));
201 
202     for (const auto &importPair : ast_->GetImports()) {
203         AutoPtr<AST> import = importPair.second;
204         std::string nameSpace = EmitPackageToNameSpace(EmitNamespace(import->GetFullName()));
205         if (nameSpace == selfNameSpace) {
206             continue;
207         }
208         namespaceSet.emplace(nameSpace);
209     }
210 
211     const AST::TypeStringMap &types = ast_->GetTypes();
212     for (const auto &pair : types) {
213         AutoPtr<ASTType> type = pair.second;
214         if (type->GetTypeKind() == TypeKind::TYPE_SMQ ||
215             type->GetTypeKind() == TypeKind::TYPE_BUFFER_HANDLE) {
216             namespaceSet.emplace("OHOS::HDI::Base");
217             break;
218         }
219     }
220 
221     for (const auto &nspace : namespaceSet) {
222         sb.Append("using namespace ").AppendFormat("%s;\n", nspace.c_str());
223     }
224 }
225 
EmitWriteMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,StringBuilder & sb,const std::string & prefix)226 void CppCodeEmitter::EmitWriteMethodParameter(
227     const AutoPtr<ASTParameter> &param, const std::string &parcelName, StringBuilder &sb, const std::string &prefix)
228 {
229     AutoPtr<ASTType> type = param->GetType();
230     type->EmitCppWriteVar(parcelName, param->GetName(), sb, prefix);
231 }
232 
EmitReadMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,bool initVariable,StringBuilder & sb,const std::string & prefix)233 void CppCodeEmitter::EmitReadMethodParameter(const AutoPtr<ASTParameter> &param, const std::string &parcelName,
234     bool initVariable, StringBuilder &sb, const std::string &prefix)
235 {
236     AutoPtr<ASTType> type = param->GetType();
237     type->EmitCppReadVar(parcelName, param->GetName(), sb, prefix, initVariable);
238 }
239 
MacroName(const std::string & name)240 std::string CppCodeEmitter::MacroName(const std::string &name)
241 {
242     if (name.empty()) {
243         return name;
244     }
245 
246     std::string macro = StringHelper::StrToUpper(StringHelper::Replace(name, '.', '_')) + "_H";
247     return macro;
248 }
249 
SpecificationParam(StringBuilder & paramSb,const std::string & prefix)250 std::string CppCodeEmitter::SpecificationParam(StringBuilder &paramSb, const std::string &prefix)
251 {
252     size_t maxLineLen = 120;
253     size_t replaceLen = 2;
254     std::string paramStr = paramSb.ToString();
255     size_t preIndex = 0;
256     size_t curIndex = 0;
257 
258     std::string insertStr = StringHelper::Format("\n%s", prefix.c_str());
259     for (; curIndex < paramStr.size(); curIndex++) {
260         if (curIndex == maxLineLen && preIndex > 0) {
261             StringHelper::Replace(paramStr, preIndex, replaceLen, ",");
262             paramStr.insert(preIndex + 1, insertStr);
263         } else {
264             if (paramStr[curIndex] == ',') {
265                 preIndex = curIndex;
266             }
267         }
268     }
269     return paramStr;
270 }
271 } // namespace HDI
272 } // namespace OHOS