1 /*
2 * Copyright (c) 2021-2023 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 "ast/ast_interface_type.h"
10 #include "util/string_builder.h"
11
12 namespace OHOS {
13 namespace HDI {
SetNamespace(const AutoPtr<ASTNamespace> & nspace)14 void ASTInterfaceType::SetNamespace(const AutoPtr<ASTNamespace> &nspace)
15 {
16 ASTType::SetNamespace(nspace);
17 if (namespace_ != nullptr) {
18 namespace_->AddInterface(this);
19 }
20 }
21
AddMethod(const AutoPtr<ASTMethod> & method)22 void ASTInterfaceType::AddMethod(const AutoPtr<ASTMethod> &method)
23 {
24 if (method == nullptr) {
25 return;
26 }
27 methods_.push_back(method);
28 }
29
GetMethod(size_t index)30 AutoPtr<ASTMethod> ASTInterfaceType::GetMethod(size_t index)
31 {
32 if (index >= methods_.size()) {
33 return nullptr;
34 }
35
36 return methods_[index];
37 }
38
AddExtendsInterface(AutoPtr<ASTInterfaceType> interface)39 bool ASTInterfaceType::AddExtendsInterface(AutoPtr<ASTInterfaceType> interface)
40 {
41 if (extendsInterface_ != nullptr) {
42 return false;
43 }
44 extendsInterface_ = interface;
45 return true;
46 }
47
SetVersion(size_t & majorVer,size_t & minorVer)48 void ASTInterfaceType::SetVersion(size_t &majorVer, size_t &minorVer)
49 {
50 majorVersion_ = majorVer;
51 minorVersion_ = minorVer;
52 }
53
GetMethodsBySystem(SystemLevel system) const54 std::vector<AutoPtr<ASTMethod>> ASTInterfaceType::GetMethodsBySystem(SystemLevel system) const
55 {
56 std::vector<AutoPtr<ASTMethod>> methods;
57 for (const auto &method : methods_) {
58 if (method->GetAttribute()->Match(system)) {
59 methods.push_back(method);
60 }
61 }
62 return methods;
63 }
64
IsInterfaceType()65 bool ASTInterfaceType::IsInterfaceType()
66 {
67 return true;
68 }
69
Dump(const std::string & prefix)70 std::string ASTInterfaceType::Dump(const std::string &prefix)
71 {
72 StringBuilder sb;
73
74 sb.Append(prefix);
75 sb.Append(prefix).Append(attr_->Dump(prefix)).Append(" ");
76 sb.AppendFormat("interface %s {\n", name_.c_str());
77 for (auto method : methods_) {
78 std::string info = method->Dump(prefix + " ");
79 sb.Append(info);
80 if (method != methods_[methods_.size() - 1]) {
81 sb.Append('\n');
82 }
83 }
84 sb.Append(prefix).Append("}\n");
85
86 return sb.ToString();
87 }
88
GetTypeKind()89 TypeKind ASTInterfaceType::GetTypeKind()
90 {
91 return TypeKind::TYPE_INTERFACE;
92 }
93
GetFullName() const94 std::string ASTInterfaceType::GetFullName() const
95 {
96 return namespace_->ToString() + name_;
97 }
98
EmitDescMacroName() const99 std::string ASTInterfaceType::EmitDescMacroName() const
100 {
101 return StringHelper::Format("%s_INTERFACE_DESC", StringHelper::StrToUpper(name_).c_str());
102 }
103
EmitCType(TypeMode mode) const104 std::string ASTInterfaceType::EmitCType(TypeMode mode) const
105 {
106 switch (mode) {
107 case TypeMode::NO_MODE:
108 return StringHelper::Format("struct %s", name_.c_str());
109 case TypeMode::PARAM_IN:
110 return StringHelper::Format("struct %s*", name_.c_str());
111 case TypeMode::PARAM_OUT:
112 return StringHelper::Format("struct %s**", name_.c_str());
113 case TypeMode::LOCAL_VAR:
114 return StringHelper::Format("struct %s*", name_.c_str());
115 default:
116 return "unknow type";
117 }
118 }
119
EmitCppType(TypeMode mode) const120 std::string ASTInterfaceType::EmitCppType(TypeMode mode) const
121 {
122 std::string pointerName = "sptr";
123 if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
124 pointerName = "std::shared_ptr";
125 }
126 switch (mode) {
127 case TypeMode::NO_MODE:
128 return StringHelper::Format("%s<%s>", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
129 case TypeMode::PARAM_IN:
130 return StringHelper::Format(
131 "const %s<%s>&", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
132 case TypeMode::PARAM_OUT:
133 return StringHelper::Format(
134 "%s<%s>&", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
135 case TypeMode::LOCAL_VAR:
136 return StringHelper::Format("%s<%s>", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
137 default:
138 return "unknow type";
139 }
140 }
141
EmitJavaType(TypeMode mode,bool isInnerType) const142 std::string ASTInterfaceType::EmitJavaType(TypeMode mode, bool isInnerType) const
143 {
144 return name_;
145 }
146
EmitCWriteVar(const std::string & parcelName,const std::string & name,const std::string & ecName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const147 void ASTInterfaceType::EmitCWriteVar(const std::string &parcelName, const std::string &name, const std::string &ecName,
148 const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
149 {
150 sb.Append(prefix).AppendFormat("if (!WriteInterface(%s, %s, %s)) {\n", parcelName.c_str(),
151 EmitDescMacroName().c_str(), name.c_str());
152 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
153 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
154 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
155 sb.Append(prefix).Append("}\n");
156 }
157
EmitCProxyReadVar(const std::string & parcelName,const std::string & name,bool isInnerType,const std::string & ecName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const158 void ASTInterfaceType::EmitCProxyReadVar(const std::string &parcelName, const std::string &name, bool isInnerType,
159 const std::string &ecName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
160 {
161 sb.Append(prefix).AppendFormat("*%s = Read%s(%s);\n", name.c_str(), name_.c_str(), parcelName.c_str());
162 sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.c_str());
163 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
164 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
165 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
166 sb.Append(prefix).Append("}\n");
167 }
168
EmitCStubReadVar(const std::string & parcelName,const std::string & name,const std::string & ecName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const169 void ASTInterfaceType::EmitCStubReadVar(const std::string &parcelName, const std::string &name,
170 const std::string &ecName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
171 {
172 sb.Append(prefix).AppendFormat("%s = Read%s(%s);\n", name.c_str(), name_.c_str(), parcelName.c_str());
173 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.c_str());
174 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
175 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
176 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
177 sb.Append(prefix).Append("}\n");
178 }
179
EmitCppWriteVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,unsigned int innerLevel) const180 void ASTInterfaceType::EmitCppWriteVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
181 const std::string &prefix, unsigned int innerLevel) const
182 {
183 sb.Append(prefix).AppendFormat("if (%s == nullptr) {\n", name.c_str());
184 sb.Append(prefix + TAB)
185 .AppendFormat("HDF_LOGE(\"%%{public}s: parameter %s is nullptr!\", __func__);\n", name.c_str());
186 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
187 sb.Append(prefix).Append("}\n");
188 sb.Append("\n");
189 sb.Append(prefix).AppendFormat("if (!%s.WriteRemoteObject(", parcelName.c_str());
190 sb.AppendFormat("OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(%s, %s::GetDescriptor()))) {\n",
191 name.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
192 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
193 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
194 sb.Append(prefix).Append("}\n");
195 }
196
EmitCppReadVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,bool initVariable,unsigned int innerLevel) const197 void ASTInterfaceType::EmitCppReadVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
198 const std::string &prefix, bool initVariable, unsigned int innerLevel) const
199 {
200 if (initVariable) {
201 sb.Append(prefix).AppendFormat("sptr<%s> %s;\n", GetNameWithNamespace(namespace_, name_).c_str(), name.c_str());
202 }
203 sb.Append(prefix).AppendFormat("if (!ReadInterface<%s>(%s, %s)) {\n",
204 GetNameWithNamespace(namespace_, name_).c_str(), parcelName.c_str(), name.c_str());
205 sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to read interface object\", __func__);\n");
206 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
207 sb.Append(prefix).Append("}\n");
208 }
209
EmitJavaWriteVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix) const210 void ASTInterfaceType::EmitJavaWriteVar(
211 const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
212 {
213 sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s.asObject());\n", parcelName.c_str(), name.c_str());
214 }
215
EmitJavaReadVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix) const216 void ASTInterfaceType::EmitJavaReadVar(
217 const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
218 {
219 std::string stubName = StringHelper::StartWith(name_, "I") ? (name_.substr(1) + "Stub") : (name_ + "Stub");
220 sb.Append(prefix).AppendFormat(
221 "%s = %s.asInterface(%s.readRemoteObject());\n", name.c_str(), stubName.c_str(), parcelName.c_str());
222 }
223
EmitJavaReadInnerVar(const std::string & parcelName,const std::string & name,bool isInner,StringBuilder & sb,const std::string & prefix) const224 void ASTInterfaceType::EmitJavaReadInnerVar(const std::string &parcelName, const std::string &name, bool isInner,
225 StringBuilder &sb, const std::string &prefix) const
226 {
227 std::string stubName = StringHelper::StartWith(name_, "I") ? (name_.substr(1) + "Stub") : (name_ + "Stub");
228 sb.Append(prefix).AppendFormat("%s %s = %s.asInterface(%s.readRemoteObject());\n",
229 EmitJavaType(TypeMode::NO_MODE).c_str(), name.c_str(), stubName.c_str(), parcelName.c_str());
230 }
231
RegisterWriteMethod(Language language,SerMode mode,UtilMethodMap & methods) const232 void ASTInterfaceType::RegisterWriteMethod(Language language, SerMode mode, UtilMethodMap &methods) const
233 {
234 using namespace std::placeholders;
235 if (language == Language::C) {
236 methods.emplace("WriteInterface", std::bind(&ASTInterfaceType::EmitCWriteMethods, this, _1, _2, _3, _4));
237 }
238 }
239
RegisterReadMethod(Language language,SerMode mode,UtilMethodMap & methods) const240 void ASTInterfaceType::RegisterReadMethod(Language language, SerMode mode, UtilMethodMap &methods) const
241 {
242 using namespace std::placeholders;
243
244 switch (language) {
245 case Language::C: {
246 std::string methodName = StringHelper::Format("Read%s", name_.c_str());
247 methods.emplace(methodName, std::bind(&ASTInterfaceType::EmitCReadMethods, this, _1, _2, _3, _4));
248 break;
249 }
250 case Language::CPP: {
251 methods.emplace("ReadInterface", std::bind(&ASTInterfaceType::EmitCppReadMethods, this, _1, _2, _3, _4));
252 break;
253 }
254 default:
255 break;
256 }
257 }
258
EmitCWriteMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const259 void ASTInterfaceType::EmitCWriteMethods(StringBuilder &sb, const std::string &prefix,
260 const std::string &methodPrefix, bool isDecl) const
261 {
262 std::string methodName = StringHelper::Format("%sWriteInterface", methodPrefix.c_str());
263 if (isDecl) {
264 sb.Append(prefix).AppendFormat("static bool %s(struct HdfSBuf *parcel, const char *desc, void *interface);\n",
265 methodName.c_str());
266 return;
267 }
268 sb.Append(prefix).AppendFormat("static bool %s(struct HdfSBuf *parcel, const char *desc, void *interface)\n",
269 methodName.c_str());
270 sb.Append(prefix).Append("{\n");
271 sb.Append(prefix + TAB).Append("if (interface == NULL) {\n");
272 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: invalid interface object\", __func__);\n");
273 sb.Append(prefix + TAB + TAB).Append("return false;\n");
274 sb.Append(prefix + TAB).Append("}\n\n");
275 sb.Append(prefix + TAB).Append("struct HdfRemoteService **stub = StubCollectorGetOrNewObject(desc, interface);\n");
276 sb.Append(prefix + TAB).Append("if (stub == NULL) {\n");
277 sb.Append(prefix + TAB + TAB).Append(
278 "HDF_LOGE(\"%{public}s: failed to get stub of '%{public}s'\", __func__, desc);\n");
279 sb.Append(prefix + TAB + TAB).Append("return false;\n");
280 sb.Append(prefix + TAB).Append("}\n\n");
281 sb.Append(prefix + TAB).Append("if (HdfSbufWriteRemoteService(parcel, *stub) != HDF_SUCCESS) {\n");
282 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: failed to write remote service\", __func__);\n");
283 sb.Append(prefix + TAB + TAB).Append("return false;\n");
284 sb.Append(prefix + TAB).Append("}\n\n");
285 sb.Append(prefix + TAB).Append("return true;\n");
286 sb.Append(prefix).Append("}\n");
287 }
288
EmitCReadMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const289 void ASTInterfaceType::EmitCReadMethods(StringBuilder &sb, const std::string &prefix,
290 const std::string &methodPrefix, bool isDecl) const
291 {
292 std::string methodName = StringHelper::Format("%sRead%s", methodPrefix.c_str(), name_.c_str());
293 if (isDecl) {
294 sb.Append(prefix).AppendFormat("static struct %s *%s(struct HdfSBuf *parcel);\n", name_.c_str(),
295 methodName.c_str());
296 return;
297 }
298 sb.Append(prefix).AppendFormat("static struct %s *%s(struct HdfSBuf *parcel)\n", name_.c_str(),
299 methodName.c_str());
300 sb.Append(prefix).Append("{\n");
301 sb.Append(prefix + TAB).Append("struct HdfRemoteService *remote = HdfSbufReadRemoteService(parcel);\n");
302 sb.Append(prefix + TAB).Append("if (remote == NULL) {\n");
303 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: ");
304 sb.AppendFormat(" failed to read remote service of '%s'\", __func__);\n", name_.c_str());
305 sb.Append(prefix + TAB + TAB).Append("return NULL;\n");
306 sb.Append(prefix + TAB).Append("}\n\n");
307 sb.Append(prefix + TAB).AppendFormat("return %sGet(remote);\n", name_.c_str());
308 sb.Append(prefix).Append("}\n");
309 }
310
EmitCppReadMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const311 void ASTInterfaceType::EmitCppReadMethods(StringBuilder &sb, const std::string &prefix,
312 const std::string &methodPrefix, bool isDecl) const
313 {
314 std::string methodName = StringHelper::Format("%sReadInterface", methodPrefix.c_str(), name_.c_str());
315 sb.Append(prefix).AppendFormat("template<typename InterfaceType>\n");
316 sb.Append(prefix).AppendFormat("static bool %s(MessageParcel &parcel, sptr<InterfaceType>& object)",
317 methodName.c_str());
318 if (isDecl) {
319 sb.Append(";\n");
320 return;
321 } else {
322 sb.Append("\n");
323 }
324
325 sb.Append(prefix).Append("{\n");
326 sb.Append(prefix + TAB).Append("sptr<IRemoteObject> remote = parcel.ReadRemoteObject();\n");
327 sb.Append(prefix + TAB).Append("if (remote == nullptr) {\n");
328 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: read an invalid remote object\", __func__);\n");
329 sb.Append(prefix + TAB + TAB).Append("return false;\n");
330 sb.Append(prefix + TAB).Append("}\n\n");
331 sb.Append(prefix + TAB).Append("object = hdi_facecast<InterfaceType>(remote);\n");
332 sb.Append(prefix + TAB).Append("if (object == nullptr) {\n");
333 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: failed to cast interface object\", __func__);\n");
334 sb.Append(prefix + TAB + TAB).Append("return false;\n");
335 sb.Append(prefix + TAB).Append("}\n");
336 sb.Append(prefix + TAB).Append("return true;\n");
337 sb.Append(prefix).Append("}\n");
338 }
339 } // namespace HDI
340 } // namespace OHOS
341