1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "sa_cpp_code_emitter.h"
17
18 #include <regex>
19 #include <unordered_set>
20
21 #include "util/options.h"
22 #include "util/logger.h"
23
24 namespace OHOS {
25 namespace Idl {
GetImportInclusions(HeaderFile::HeaderFileSet & headerFiles)26 void SACppCodeEmitter::GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles)
27 {
28 for (const auto &importName : ast_->GetImportNames()) {
29 size_t index = importName.rfind(SEPARATOR);
30 if (index == std::string::npos) {
31 index = -1;
32 }
33 std::string fileName = importName.substr(index + 1);
34 std::string relativePath = importName.substr(0, index + 1) + FileName(fileName).c_str();
35 std::replace(relativePath.begin(), relativePath.end(), '\\', '/');
36 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, relativePath);
37 }
38 }
39
EmitImportUsingNamespace(StringBuilder & sb) const40 void SACppCodeEmitter::EmitImportUsingNamespace(StringBuilder &sb) const
41 {
42 std::unordered_map<std::string, int> usedNamespace;
43 for (const auto &importPair : ast_->GetImports()) {
44 AutoPtr<AST> importAst = importPair.second;
45 if (importAst->GetASTFileType() == ASTFileType::AST_SEQUENCEABLE ||
46 importAst->GetASTFileType() == ASTFileType::AST_RAWDATA) {
47 continue;
48 }
49 size_t index = importPair.first.rfind(".");
50 std::string usingName = importPair.first.substr(0, index);
51 if (usingName.empty()) {
52 continue;
53 }
54 std::regex dotToColons("\\.");
55 usingName = std::regex_replace(usingName, dotToColons, "::");
56 if (usedNamespace[usingName] == 0) {
57 usedNamespace[usingName] = 1;
58 sb.Append("using namespace ").AppendFormat("%s;\n", usingName.c_str());
59 }
60 }
61 sb.Append("\n");
62 }
63
GetStdlibInclusions(HeaderFile::HeaderFileSet & headerFiles)64 void SACppCodeEmitter::GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles)
65 {
66 const AST::TypeStringMap &types = ast_->GetTypes();
67
68 // Add header files dependency by default to avoid compatibility problems
69 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
70 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdint");
71 for (const auto &pair : types) {
72 AutoPtr<ASTType> type = pair.second;
73 switch (type->GetTypeKind()) {
74 case TypeKind::TYPE_ARRAY:
75 case TypeKind::TYPE_LIST: {
76 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "vector");
77 break;
78 }
79 case TypeKind::TYPE_MAP: {
80 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "unordered_map");
81 break;
82 }
83 case TypeKind::TYPE_ORDEREDMAP: {
84 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "map");
85 break;
86 }
87 default:
88 break;
89 }
90 }
91 }
92
EmitBeginNamespace(StringBuilder & sb) const93 void SACppCodeEmitter::EmitBeginNamespace(StringBuilder &sb) const
94 {
95 std::string fullnamespace = GetNamespace(interface_->GetNamespace()->ToString());
96 std::vector<std::string> namespaceVec = StringHelper::Split(fullnamespace, ".");
97
98 for (const auto &nspace : namespaceVec) {
99 sb.AppendFormat("namespace %s {\n", nspace.c_str());
100 }
101 }
102
EmitEndNamespace(StringBuilder & sb) const103 void SACppCodeEmitter::EmitEndNamespace(StringBuilder &sb) const
104 {
105 std::string fullnamespace = GetNamespace(interface_->GetNamespace()->ToString());
106 std::vector<std::string> namespaceVec = StringHelper::Split(fullnamespace, ".");
107
108 for (std::vector<std::string>::const_reverse_iterator nspaceIter = namespaceVec.rbegin();
109 nspaceIter != namespaceVec.rend(); ++nspaceIter) {
110 sb.AppendFormat("} // namespace %s\n", nspaceIter->c_str());
111 }
112 }
113
EmitWriteMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const114 void SACppCodeEmitter::EmitWriteMethodParameter(const AutoPtr<ASTParameter> ¶m, const std::string &parcelName,
115 StringBuilder &sb, const std::string &prefix) const
116 {
117 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
118 if (typeEmitter != nullptr) {
119 typeEmitter->isParamInout = param->GetAttribute() == ASTParamAttr::PARAM_INOUT;
120 typeEmitter->isProxy = isProxy;
121 typeEmitter->EmitCppWriteVar(parcelName, param->GetName(), sb, prefix);
122 }
123 }
124
EmitReadMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,bool emitType,StringBuilder & sb,const std::string & prefix) const125 void SACppCodeEmitter::EmitReadMethodParameter(const AutoPtr<ASTParameter> ¶m, const std::string &parcelName,
126 bool emitType, StringBuilder &sb, const std::string &prefix) const
127 {
128 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
129 if (typeEmitter != nullptr) {
130 typeEmitter->EmitCppReadVar(parcelName, param->GetName(), sb, prefix, emitType);
131 }
132 }
133
EmitInterfaceMethodParams(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const134 void SACppCodeEmitter::EmitInterfaceMethodParams(AutoPtr<ASTMethod> &method, StringBuilder &sb,
135 const std::string &prefix) const
136 {
137 EmitParamsWithReturnType(method, sb, prefix, true);
138 }
139
EmitInterfaceClientMethodParams(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix,bool includeValue) const140 void SACppCodeEmitter::EmitInterfaceClientMethodParams(AutoPtr<ASTMethod> &method, StringBuilder &sb,
141 const std::string &prefix, bool includeValue) const
142 {
143 EmitParamsWithReturnType(method, sb, prefix, true);
144 if (!method->IsOneWay()) {
145 int paramNumber = static_cast<int>(method->GetParameterNumber());
146 if (paramNumber == 0) {
147 sb.Append("int32_t timeout");
148 } else {
149 sb.Append(",\n").Append(prefix).Append("int32_t timeout");
150 }
151 if (includeValue) {
152 sb.Append(" = LOAD_SA_TIMEOUT");
153 }
154 }
155 }
156
EmitInterfaceClientMethodParamsWithoutType(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const157 void SACppCodeEmitter::EmitInterfaceClientMethodParamsWithoutType(AutoPtr<ASTMethod> &method, StringBuilder &sb,
158 const std::string &prefix) const
159 {
160 EmitParamsWithReturnType(method, sb, prefix, false);
161 }
162
EmitParamsWithReturnType(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix,bool includeType) const163 void SACppCodeEmitter::EmitParamsWithReturnType(AutoPtr<ASTMethod> &method, StringBuilder &sb,
164 const std::string &prefix, bool includeType) const
165 {
166 AutoPtr<ASTType> returnType = method->GetReturnType();
167 TypeKind retTypeKind = returnType->GetTypeKind();
168 int paramNumber = static_cast<int>(method->GetParameterNumber());
169
170 for (int i = 0; i < paramNumber; i++) {
171 AutoPtr<ASTParameter> param = method->GetParameter(i);
172 if (param == nullptr) {
173 return;
174 }
175 sb.Append("\n").Append(prefix);
176 if (includeType) {
177 sb.AppendFormat(EmitCppParameter(param).c_str());
178 } else {
179 sb.AppendFormat(param->GetName().c_str());
180 }
181 if ((i != paramNumber - 1) || (retTypeKind != TypeKind::TYPE_VOID)) {
182 sb.Append(",");
183 }
184 }
185 if (retTypeKind != TypeKind::TYPE_VOID) {
186 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(returnType);
187 if (typeEmitter != nullptr) {
188 sb.Append("\n").Append(prefix).AppendFormat(includeType ? "%s funcResult" : "funcResult",
189 typeEmitter->EmitCppType(TypeMode::PARAM_OUT).c_str());
190 }
191 }
192 }
193
EmitCppParameter(AutoPtr<ASTParameter> & param) const194 std::string SACppCodeEmitter::EmitCppParameter(AutoPtr<ASTParameter> ¶m) const
195 {
196 std::string name = param->GetName();
197 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
198 if (typeEmitter == nullptr) {
199 return StringHelper::Format("unknow param attr %s", name.c_str());
200 }
201 ASTParamAttr::ParamAttr attrAttr = param->GetAttribute();
202 if (attrAttr == ASTParamAttr::PARAM_INOUT) {
203 return StringHelper::Format("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_INOUT).c_str(), name.c_str());
204 } else if (attrAttr == ASTParamAttr::PARAM_IN) {
205 return StringHelper::Format("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_IN).c_str(), name.c_str());
206 } else if (attrAttr == ASTParamAttr::PARAM_OUT) {
207 return StringHelper::Format("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_OUT).c_str(), name.c_str());
208 }
209 return StringHelper::Format("unknow param attr %s", name.c_str());
210 }
211
EmitSecurecInclusion(StringBuilder & sb) const212 void SACppCodeEmitter::EmitSecurecInclusion(StringBuilder &sb) const
213 {
214 size_t methodNumber = interface_->GetMethodNumber();
215 for (size_t i = 0; i < methodNumber; i++) {
216 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
217 size_t paramNumber = method->GetParameterNumber();
218 for (size_t j = 0; j < paramNumber; j++) {
219 AutoPtr<ASTParameter> param = method->GetParameter(j);
220 TypeKind paramTypeKind = param->GetType()->GetTypeKind();
221 if (paramTypeKind == TypeKind::TYPE_UNION || paramTypeKind == TypeKind::TYPE_STRUCT) {
222 sb.Append("#include <securec.h>\n");
223 return;
224 }
225 }
226
227 AutoPtr<ASTType> returnType = method->GetReturnType();
228 TypeKind retTypeKind = returnType->GetTypeKind();
229 if (retTypeKind == TypeKind::TYPE_UNION || retTypeKind == TypeKind::TYPE_STRUCT) {
230 sb.Append("#include <securec.h>\n");
231 return;
232 }
233 }
234 }
235
GetOverloadName(AutoPtr<ASTMethod> & method,std::string & overloadname) const236 void SACppCodeEmitter::GetOverloadName(AutoPtr<ASTMethod> &method, std::string &overloadname) const
237 {
238 size_t paramNumber = method->GetParameterNumber();
239
240 for (size_t i = 0; i < paramNumber; i++) {
241 AutoPtr<ASTParameter> param = method->GetParameter(i);
242 ASTParamAttr::ParamAttr attrAttr = param->GetAttribute();
243 if (attrAttr == ASTParamAttr::PARAM_INOUT) {
244 overloadname += "_inout_";
245 } else if (attrAttr == ASTParamAttr::PARAM_IN) {
246 overloadname += "_in_";
247 } else if (attrAttr == ASTParamAttr::PARAM_OUT) {
248 overloadname += "_out_";
249 }
250 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
251 if (typeEmitter == nullptr) {
252 return;
253 }
254 overloadname += typeEmitter->GetTypeName();
255 }
256
257 AutoPtr<ASTType> returnType = method->GetReturnType();
258 TypeKind retTypeKind = returnType->GetTypeKind();
259 if (retTypeKind != TypeKind::TYPE_VOID) {
260 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(returnType);
261 if (typeEmitter == nullptr) {
262 return;
263 }
264 overloadname += "_out_" + typeEmitter->GetTypeName();
265 }
266
267 std::transform(overloadname.begin(), overloadname.end(), overloadname.begin(), ::tolower);
268 overloadname = std::regex_replace(overloadname, std::regex("\\b[a-zA-Z]+\\."), "");
269 overloadname = std::regex_replace(overloadname, std::regex("[ <]"), "_");
270 overloadname = std::regex_replace(overloadname, std::regex("\\[]"), "_vector");
271 overloadname = std::regex_replace(overloadname, std::regex("[,>]"), "");
272 }
273
CheckMethodOverload(AutoPtr<ASTMethod> & method,size_t & index,std::string & overloadname) const274 void SACppCodeEmitter::CheckMethodOverload(AutoPtr<ASTMethod> &method, size_t &index, std::string &overloadname) const
275 {
276 for (size_t i = 0; i < index; i++) {
277 if (interface_->GetMethod(i)->GetName() == method->GetName()) {
278 GetOverloadName(method, overloadname);
279 break;
280 }
281 }
282 }
283
EmitInterfaceMethodCommands(StringBuilder & sb,const std::string & prefix)284 void SACppCodeEmitter::EmitInterfaceMethodCommands(StringBuilder &sb, const std::string &prefix)
285 {
286 size_t methodNumber = interface_->GetMethodNumber();
287 sb.AppendFormat("enum class %sIpcCode {\n", interface_->GetName().c_str());
288 for (size_t i = 0; i < methodNumber; i++) {
289 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
290 std::string overloadname = "";
291 CheckMethodOverload(method, i, overloadname);
292 std::string commandCode = "COMMAND_" + ConstantName(method->GetName() + overloadname);
293 bool hasIpcCode = method->HasIpcCode();
294 if (i == 0 && !hasIpcCode) {
295 commandCode += " = MIN_TRANSACTION_ID";
296 } else if (hasIpcCode) {
297 commandCode += " = " + method->GetIpcCodeStr();
298 }
299 commandCode += ",\n";
300 sb.Append(prefix).AppendFormat(commandCode.c_str());
301 }
302 sb.Append("};\n\n");
303 }
304
305 } // namespace Idl
306 } // namespace OHOS