• 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_client_proxy_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 CppClientProxyCodeEmitter::ResolveDirectory(const String& targetDirectory)
16 {
17     if (ast_->GetASTFileType() == ASTFileType::AST_IFACE ||
18         ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
19         directory_ = GetFilePath(targetDirectory);
20     } else {
21         return false;
22     }
23 
24     if (!File::CreateParentDir(directory_)) {
25         Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", directory_.string());
26         return false;
27     }
28 
29     return true;
30 }
31 
EmitCode()32 void CppClientProxyCodeEmitter::EmitCode()
33 {
34     EmitProxyHeaderFile();
35     EmitProxySourceFile();
36 }
37 
EmitProxyHeaderFile()38 void CppClientProxyCodeEmitter::EmitProxyHeaderFile()
39 {
40     String filePath = String::Format("%s/%s.h", directory_.string(), FileName(baseName_ + "Proxy").string());
41     File file(filePath, File::WRITE);
42     StringBuilder sb;
43 
44     EmitLicense(sb);
45     EmitHeadMacro(sb, proxyFullName_);
46     sb.Append("\n");
47     EmitProxyHeaderInclusions(sb);
48     sb.Append("\n");
49     EmitBeginNamespace(sb);
50     sb.Append("\n");
51     EmitProxyDecl(sb, "");
52     sb.Append("\n");
53     EmitEndNamespace(sb);
54     sb.Append("\n");
55     EmitTailMacro(sb, proxyFullName_);
56 
57     String data = sb.ToString();
58     file.WriteData(data.string(), data.GetLength());
59     file.Flush();
60     file.Close();
61 }
62 
EmitProxyHeaderInclusions(StringBuilder & sb)63 void CppClientProxyCodeEmitter::EmitProxyHeaderInclusions(StringBuilder& sb)
64 {
65     HeaderFile::HeaderFileSet headerFiles;
66 
67     headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_)));
68     GetHeaderOtherLibInclusions(headerFiles);
69 
70     for (const auto& file : headerFiles) {
71         sb.AppendFormat("%s\n", file.ToString().string());
72     }
73 }
74 
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)75 void CppClientProxyCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
76 {
77     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iremote_proxy"));
78 }
79 
EmitProxyDecl(StringBuilder & sb,const String & prefix)80 void CppClientProxyCodeEmitter::EmitProxyDecl(StringBuilder& sb, const String& prefix)
81 {
82     sb.AppendFormat("class %s : public IRemoteProxy<%s> {\n",
83         proxyName_.string(), interfaceName_.string());
84     sb.Append("public:\n");
85     EmitProxyConstructor(sb, g_tab);
86     sb.Append("\n");
87     EmitProxyMethodDecls(sb, g_tab);
88     sb.Append("\n");
89     sb.Append("private:\n");
90     EmitProxyConstants(sb, g_tab);
91     sb.Append("};\n");
92 }
93 
EmitProxyConstructor(StringBuilder & sb,const String & prefix)94 void CppClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder& sb, const String& prefix)
95 {
96     sb.Append(prefix).AppendFormat("explicit %s(const sptr<IRemoteObject>& remote)", proxyName_.string());
97     sb.AppendFormat(" : IRemoteProxy<%s>(remote) {}\n\n", interfaceName_.string());
98     sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", proxyName_.string());
99 }
100 
EmitProxyMethodDecls(StringBuilder & sb,const String & prefix)101 void CppClientProxyCodeEmitter::EmitProxyMethodDecls(StringBuilder& sb, const String& prefix)
102 {
103     for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
104         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
105         EmitProxyMethodDecl(method, sb, prefix);
106         sb.Append("\n");
107     }
108 
109     EmitProxyMethodDecl(interface_->GetVersionMethod(), sb, prefix);
110 }
111 
EmitProxyMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)112 void CppClientProxyCodeEmitter::EmitProxyMethodDecl(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
113     const String& prefix)
114 {
115     if (method->GetParameterNumber() == 0) {
116         sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().string());
117     } else {
118         StringBuilder paramStr;
119         paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().string());
120 
121         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
122             AutoPtr<ASTParameter> param = method->GetParameter(i);
123             EmitProxyMethodParameter(param, paramStr, "");
124             if (i + 1 < method->GetParameterNumber()) {
125                 paramStr.Append(", ");
126             }
127         }
128 
129         paramStr.Append(") override;");
130 
131         sb.Append(SpecificationParam(paramStr, prefix + g_tab));
132         sb.Append("\n");
133     }
134 }
135 
EmitProxyConstants(StringBuilder & sb,const String & prefix)136 void CppClientProxyCodeEmitter::EmitProxyConstants(StringBuilder& sb, const String& prefix)
137 {
138     sb.Append(prefix).AppendFormat("static inline BrokerDelegator<%s> delegator_;\n", proxyName_.string());
139 }
140 
EmitProxyMethodParameter(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const String & prefix)141 void CppClientProxyCodeEmitter::EmitProxyMethodParameter(const AutoPtr<ASTParameter>& param, StringBuilder& sb,
142     const String& prefix)
143 {
144     sb.Append(prefix).Append(param->EmitCppParameter());
145 }
146 
EmitProxySourceFile()147 void CppClientProxyCodeEmitter::EmitProxySourceFile()
148 {
149     String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(baseName_ + "Proxy").string());
150     File file(filePath, File::WRITE);
151     StringBuilder sb;
152 
153     EmitLicense(sb);
154     EmitProxySourceInclusions(sb);
155     sb.Append("\n");
156     EmitBeginNamespace(sb);
157     sb.Append("\n");
158     if (!interface_->IsSerializable()) {
159         EmitGetMethodImpl(sb, "");
160         sb.Append("\n");
161         EmitGetInstanceMethodImpl(sb, "");
162         sb.Append("\n");
163     }
164     EmitProxyMethodImpls(sb, "");
165     sb.Append("\n");
166     EmitEndNamespace(sb);
167 
168     String data = sb.ToString();
169     file.WriteData(data.string(), data.GetLength());
170     file.Flush();
171     file.Close();
172 }
173 
EmitProxySourceInclusions(StringBuilder & sb)174 void CppClientProxyCodeEmitter::EmitProxySourceInclusions(StringBuilder& sb)
175 {
176     HeaderFile::HeaderFileSet headerFiles;
177     headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(proxyName_)));
178     GetSourceOtherLibInclusions(headerFiles);
179 
180     for (const auto& file : headerFiles) {
181         sb.AppendFormat("%s\n", file.ToString().string());
182     }
183 }
184 
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)185 void CppClientProxyCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
186 {
187     if (!interface_->IsSerializable()) {
188         headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iservmgr_hdi"));
189     }
190     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base"));
191     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log"));
192     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option"));
193     headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel"));
194 
195     const AST::TypeStringMap& types = ast_->GetTypes();
196     for (const auto& pair : types) {
197         AutoPtr<ASTType> type = pair.second;
198         if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
199             headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
200             break;
201         }
202     }
203 }
204 
EmitGetMethodImpl(StringBuilder & sb,const String & prefix)205 void CppClientProxyCodeEmitter::EmitGetMethodImpl(StringBuilder& sb, const String& prefix)
206 {
207     sb.Append(prefix).AppendFormat("sptr<%s> %s::Get()\n",
208         interface_->GetName().string(), interface_->GetName().string());
209     sb.Append(prefix).Append("{\n");
210     sb.Append(prefix + g_tab).AppendFormat("return %s::GetInstance(\"%s\");\n",
211         interfaceName_.string(), FileName(implName_).string());
212     sb.Append(prefix).Append("}\n");
213 }
214 
EmitGetInstanceMethodImpl(StringBuilder & sb,const String & prefix)215 void CppClientProxyCodeEmitter::EmitGetInstanceMethodImpl(StringBuilder& sb, const String& prefix)
216 {
217     String objName = "proxy";
218     String SerMajorName = "serMajorVer";
219     String SerMinorName = "serMinorVer";
220     sb.Append(prefix).AppendFormat("sptr<%s> %s::GetInstance(const std::string& serviceName)\n",
221         interface_->GetName().string(), interface_->GetName().string());
222     sb.Append(prefix).Append("{\n");
223     sb.Append(prefix + g_tab).Append("using namespace OHOS::HDI::ServiceManager::V1_0;\n");
224     sb.Append(prefix + g_tab).Append("auto servMgr = IServiceManager::Get();\n");
225     sb.Append(prefix + g_tab).Append("if (servMgr == nullptr) {\n");
226     sb.Append(prefix + g_tab + g_tab).Append(
227         "HDF_LOGE(\"%{public}s:get IServiceManager failed!\", __func__);\n");
228     sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
229     sb.Append(prefix + g_tab).Append("}\n\n");
230 
231     sb.Append(prefix + g_tab).Append("sptr<IRemoteObject> remote = ");
232     sb.Append("servMgr->GetService(serviceName.c_str());\n");
233     sb.Append(prefix + g_tab).Append("if (remote == nullptr) {\n");
234     sb.Append(prefix + g_tab + g_tab).Append(
235         "HDF_LOGE(\"%{public}s:get remote object failed!\", __func__);\n");
236     sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
237     sb.Append(prefix + g_tab).Append("}\n\n");
238 
239     sb.Append(prefix + g_tab).AppendFormat("sptr<%s> %s = iface_cast<%s>(remote);\n",
240         interfaceName_.string(), objName.string(), interfaceName_.string());
241     sb.Append(prefix + g_tab).AppendFormat("if (%s == nullptr) {\n", objName.string());
242     sb.Append(prefix + g_tab + g_tab).Append("HDF_LOGE(\"%{public}s:iface_cast failed!\", __func__);\n");
243     sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
244     sb.Append(prefix + g_tab).Append("}\n\n");
245 
246     sb.Append(prefix + g_tab).AppendFormat("uint32_t %s = 0;\n", SerMajorName.string());
247     sb.Append(prefix + g_tab).AppendFormat("uint32_t %s = 0;\n", SerMinorName.string());
248     sb.Append(prefix + g_tab).AppendFormat("int32_t %s = %s->GetVersion(%s, %s);\n", errorCodeName_.string(),
249         objName.string(), SerMajorName.string(), SerMinorName.string());
250     sb.Append(prefix + g_tab).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.string());
251     sb.Append(prefix + g_tab + g_tab).Append("HDF_LOGE(\"%{public}s:get version failed!\", __func__);\n");
252     sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
253     sb.Append(prefix + g_tab).Append("}\n\n");
254 
255     sb.Append(prefix + g_tab).AppendFormat("if (%s != %s) {\n", SerMajorName.string(), majorVerName_.string());
256     sb.Append(prefix + g_tab + g_tab).Append("HDF_LOGE(\"%{public}s:check version failed! ");
257     sb.Append("version of service:%u.%u, version of client:%u.%u\", __func__,\n");
258     sb.Append(prefix + g_tab + g_tab + g_tab).AppendFormat("%s, %s, %s, %s);\n",
259         SerMajorName.string(), SerMinorName.string(), majorVerName_.string(), minorVerName_.string());
260     sb.Append(prefix + g_tab + g_tab).Append("return nullptr;\n");
261     sb.Append(prefix + g_tab).Append("}\n\n");
262     sb.Append(prefix + g_tab).AppendFormat("return %s;\n", objName.string());
263     sb.Append(prefix).Append("}\n");
264 }
265 
EmitProxyMethodImpls(StringBuilder & sb,const String & prefix)266 void CppClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb, const String& prefix)
267 {
268     for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
269         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
270         EmitProxyMethodImpl(method, sb, prefix);
271         sb.Append("\n");
272     }
273 
274     EmitProxyMethodImpl(interface_->GetVersionMethod(), sb, prefix);
275 }
276 
EmitProxyMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)277 void CppClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
278     const String& prefix)
279 {
280     if (method->GetParameterNumber() == 0) {
281         sb.Append(prefix).AppendFormat("int32_t %s::%s()\n", proxyName_.string(), method->GetName().string());
282     } else {
283         StringBuilder paramStr;
284         paramStr.Append(prefix).AppendFormat("int32_t %s::%s(", proxyName_.string(), method->GetName().string());
285         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
286             AutoPtr<ASTParameter> param = method->GetParameter(i);
287             EmitProxyMethodParameter(param, paramStr, "");
288             if (i + 1 < method->GetParameterNumber()) {
289                 paramStr.Append(", ");
290             }
291         }
292 
293         paramStr.Append(")");
294 
295         sb.Append(SpecificationParam(paramStr, prefix + g_tab));
296         sb.Append("\n");
297     }
298     EmitProxyMethodBody(method, sb, prefix);
299 }
300 
EmitProxyMethodBody(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)301 void CppClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
302     const String& prefix)
303 {
304     String option = method->IsOneWay() ? "MessageOption::TF_ASYNC" : "MessageOption::TF_SYNC";
305     sb.Append(prefix).Append("{\n");
306     sb.Append(prefix + g_tab).AppendFormat("MessageParcel %s;\n", dataParcelName_.string());
307     sb.Append(prefix + g_tab).AppendFormat("MessageParcel %s;\n", replyParcelName_.string());
308     sb.Append(prefix + g_tab).AppendFormat("MessageOption %s(%s);\n", optionName_.string(), option.string());
309     sb.Append("\n");
310 
311     // write interface token
312     EmitWriteInterfaceToken(dataParcelName_, sb, prefix + g_tab);
313     sb.Append("\n");
314 
315     if (method->GetParameterNumber() > 0) {
316         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
317             AutoPtr<ASTParameter> param = method->GetParameter(i);
318             if (param->GetAttribute() == ParamAttr::PARAM_IN) {
319                 EmitWriteMethodParameter(param, dataParcelName_, sb, prefix + g_tab);
320                 sb.Append("\n");
321             }
322         }
323     }
324 
325     sb.Append(prefix + g_tab).AppendFormat("int32_t %s = Remote()->SendRequest(%s, %s, %s, %s);\n",
326         errorCodeName_.string(), EmitMethodCmdID(method).string(), dataParcelName_.string(),
327         replyParcelName_.string(), optionName_.string());
328     sb.Append(prefix + g_tab).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.string());
329     sb.Append(prefix + g_tab + g_tab).AppendFormat(
330         "HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n", errorCodeName_.string());
331     sb.Append(prefix + g_tab + g_tab).AppendFormat("return %s;\n", errorCodeName_.string());
332     sb.Append(prefix + g_tab).Append("}\n");
333 
334     if (!method->IsOneWay()) {
335         sb.Append("\n");
336         for (size_t i = 0; i < method->GetParameterNumber(); i++) {
337             AutoPtr<ASTParameter> param = method->GetParameter(i);
338             if (param->GetAttribute() == ParamAttr::PARAM_OUT) {
339                 EmitReadMethodParameter(param, replyParcelName_, false, sb, prefix + g_tab);
340                 sb.Append("\n");
341             }
342         }
343     }
344 
345     sb.Append(prefix + g_tab).Append("return HDF_SUCCESS;\n");
346     sb.Append(prefix).Append("}\n");
347 }
348 
EmitWriteInterfaceToken(const String & parcelName,StringBuilder & sb,const String & prefix)349 void CppClientProxyCodeEmitter::EmitWriteInterfaceToken(const String& parcelName, StringBuilder& sb,
350     const String& prefix)
351 {
352     sb.Append(prefix).AppendFormat("if (!%s.WriteInterfaceToken(GetDescriptor())) {\n", parcelName.string());
353     sb.Append(prefix + g_tab).AppendFormat(
354         "HDF_LOGE(\"%%{public}s: write interface descriptor failed!\", __func__);\n");
355     sb.Append(prefix + g_tab).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
356     sb.Append(prefix).Append("}\n");
357 }
358 } // namespace HDI
359 } // namespace OHOS