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 if (methods_.size() > 0 && methods_.size() < SIZE_MAX) {
78 for (auto method : methods_) {
79 std::string info = method->Dump(prefix + " ");
80 sb.Append(info);
81 if (method != methods_[methods_.size() - 1]) {
82 sb.Append('\n');
83 }
84 }
85 }
86 sb.Append(prefix).Append("}\n");
87
88 return sb.ToString();
89 }
90
GetTypeKind()91 TypeKind ASTInterfaceType::GetTypeKind()
92 {
93 return TypeKind::TYPE_INTERFACE;
94 }
95
GetFullName() const96 std::string ASTInterfaceType::GetFullName() const
97 {
98 return namespace_->ToString() + name_;
99 }
100
EmitDescMacroName() const101 std::string ASTInterfaceType::EmitDescMacroName() const
102 {
103 return StringHelper::Format("%s_INTERFACE_DESC", StringHelper::StrToUpper(name_).c_str());
104 }
105
EmitCType(TypeMode mode) const106 std::string ASTInterfaceType::EmitCType(TypeMode mode) const
107 {
108 switch (mode) {
109 case TypeMode::NO_MODE:
110 return StringHelper::Format("struct %s", name_.c_str());
111 case TypeMode::PARAM_IN:
112 return StringHelper::Format("struct %s*", name_.c_str());
113 case TypeMode::PARAM_OUT:
114 return StringHelper::Format("struct %s**", name_.c_str());
115 case TypeMode::LOCAL_VAR:
116 return StringHelper::Format("struct %s*", name_.c_str());
117 default:
118 return "unknow type";
119 }
120 }
121
EmitCppType(TypeMode mode) const122 std::string ASTInterfaceType::EmitCppType(TypeMode mode) const
123 {
124 std::string pointerName = "sptr";
125 if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
126 pointerName = "std::shared_ptr";
127 }
128 switch (mode) {
129 case TypeMode::NO_MODE:
130 return StringHelper::Format("%s<%s>", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
131 case TypeMode::PARAM_IN:
132 return StringHelper::Format(
133 "const %s<%s>&", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
134 case TypeMode::PARAM_OUT:
135 return StringHelper::Format(
136 "%s<%s>&", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
137 case TypeMode::LOCAL_VAR:
138 return StringHelper::Format("%s<%s>", pointerName.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
139 default:
140 return "unknow type";
141 }
142 }
143
EmitJavaType(TypeMode mode,bool isInnerType) const144 std::string ASTInterfaceType::EmitJavaType(TypeMode mode, bool isInnerType) const
145 {
146 return name_;
147 }
148
EmitCWriteVar(const std::string & parcelName,const std::string & name,const std::string & ecName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const149 void ASTInterfaceType::EmitCWriteVar(const std::string &parcelName, const std::string &name, const std::string &ecName,
150 const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
151 {
152 sb.Append(prefix).AppendFormat("if (!WriteInterface(%s, %s, %s)) {\n", parcelName.c_str(),
153 EmitDescMacroName().c_str(), name.c_str());
154 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
155 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
156 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
157 sb.Append(prefix).Append("}\n");
158 }
159
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) const160 void ASTInterfaceType::EmitCProxyReadVar(const std::string &parcelName, const std::string &name, bool isInnerType,
161 const std::string &ecName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
162 {
163 sb.Append(prefix).AppendFormat("*%s = Read%s(%s);\n", name.c_str(), name_.c_str(), parcelName.c_str());
164 sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.c_str());
165 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
166 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
167 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
168 sb.Append(prefix).Append("}\n");
169 }
170
EmitCStubReadVar(const std::string & parcelName,const std::string & name,const std::string & ecName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const171 void ASTInterfaceType::EmitCStubReadVar(const std::string &parcelName, const std::string &name,
172 const std::string &ecName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
173 {
174 sb.Append(prefix).AppendFormat("%s = Read%s(%s);\n", name.c_str(), name_.c_str(), parcelName.c_str());
175 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.c_str());
176 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
177 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
178 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
179 sb.Append(prefix).Append("}\n");
180 }
181
EmitCppWriteVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,unsigned int innerLevel) const182 void ASTInterfaceType::EmitCppWriteVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
183 const std::string &prefix, unsigned int innerLevel) const
184 {
185 sb.Append(prefix).AppendFormat("if (%s == nullptr) {\n", name.c_str());
186 sb.Append(prefix + TAB)
187 .AppendFormat("HDF_LOGE(\"%%{public}s: parameter %s is nullptr!\", __func__);\n", name.c_str());
188 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
189 sb.Append(prefix).Append("}\n");
190 sb.Append("\n");
191 sb.Append(prefix).AppendFormat("if (!%s.WriteRemoteObject(", parcelName.c_str());
192 sb.AppendFormat("OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(%s, %s::GetDescriptor()))) {\n",
193 name.c_str(), GetNameWithNamespace(namespace_, name_).c_str());
194 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
195 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
196 sb.Append(prefix).Append("}\n");
197 }
198
EmitCppReadVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,bool initVariable,unsigned int innerLevel) const199 void ASTInterfaceType::EmitCppReadVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
200 const std::string &prefix, bool initVariable, unsigned int innerLevel) const
201 {
202 std::string interfaceNamespace = GetNamespaceWithColon(namespace_, name_);
203 if (initVariable) {
204 sb.Append(prefix).AppendFormat("sptr<%s> %s;\n", GetNameWithNamespace(namespace_, name_).c_str(), name.c_str());
205 }
206 sb.Append(prefix).AppendFormat("sptr<IRemoteObject> %sRemote = %s.ReadRemoteObject();\n", name.c_str(),
207 parcelName.c_str());
208 sb.Append(prefix).AppendFormat("if (%sRemote == nullptr) {\n", name.c_str());
209 sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: read an invalid remote object\", __func__);\n");
210 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
211 sb.Append(prefix).Append("}\n\n");
212 sb.Append(prefix).AppendFormat("%s = new %s(%sRemote);\n", name.c_str(),
213 (interfaceNamespace +
214 (StringHelper::StartWith(name_, "I") ? name_.substr(1) : name_) + "Proxy").c_str(), name.c_str());
215 sb.Append(prefix).AppendFormat("if (%s == nullptr) {\n", name.c_str());
216 sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to create interface object\", __func__);\n");
217 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
218 sb.Append(prefix).Append("}\n");
219 }
220
EmitJavaWriteVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix) const221 void ASTInterfaceType::EmitJavaWriteVar(
222 const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
223 {
224 sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s.asObject());\n", parcelName.c_str(), name.c_str());
225 }
226
EmitJavaReadVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix) const227 void ASTInterfaceType::EmitJavaReadVar(
228 const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
229 {
230 std::string stubName = StringHelper::StartWith(name_, "I") ? (name_.substr(1) + "Stub") : (name_ + "Stub");
231 sb.Append(prefix).AppendFormat(
232 "%s = %s.asInterface(%s.readRemoteObject());\n", name.c_str(), stubName.c_str(), parcelName.c_str());
233 }
234
EmitJavaReadInnerVar(const std::string & parcelName,const std::string & name,bool isInner,StringBuilder & sb,const std::string & prefix) const235 void ASTInterfaceType::EmitJavaReadInnerVar(const std::string &parcelName, const std::string &name, bool isInner,
236 StringBuilder &sb, const std::string &prefix) const
237 {
238 std::string stubName = StringHelper::StartWith(name_, "I") ? (name_.substr(1) + "Stub") : (name_ + "Stub");
239 sb.Append(prefix).AppendFormat("%s %s = %s.asInterface(%s.readRemoteObject());\n",
240 EmitJavaType(TypeMode::NO_MODE).c_str(), name.c_str(), stubName.c_str(), parcelName.c_str());
241 }
242
RegisterWriteMethod(Language language,SerMode mode,UtilMethodMap & methods) const243 void ASTInterfaceType::RegisterWriteMethod(Language language, SerMode mode, UtilMethodMap &methods) const
244 {
245 using namespace std::placeholders;
246 if (language == Language::C) {
247 methods.emplace("WriteInterface", std::bind(&ASTInterfaceType::EmitCWriteMethods, this, _1, _2, _3, _4));
248 }
249 }
250
RegisterReadMethod(Language language,SerMode mode,UtilMethodMap & methods) const251 void ASTInterfaceType::RegisterReadMethod(Language language, SerMode mode, UtilMethodMap &methods) const
252 {
253 using namespace std::placeholders;
254
255 switch (language) {
256 case Language::C: {
257 std::string methodName = StringHelper::Format("Read%s", name_.c_str());
258 methods.emplace(methodName, std::bind(&ASTInterfaceType::EmitCReadMethods, this, _1, _2, _3, _4));
259 break;
260 }
261 default:
262 break;
263 }
264 }
265
EmitCWriteMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const266 void ASTInterfaceType::EmitCWriteMethods(StringBuilder &sb, const std::string &prefix,
267 const std::string &methodPrefix, bool isDecl) const
268 {
269 std::string methodName = StringHelper::Format("%sWriteInterface", methodPrefix.c_str());
270 if (isDecl) {
271 sb.Append(prefix).AppendFormat("static bool %s(struct HdfSBuf *parcel, const char *desc, void *interface);\n",
272 methodName.c_str());
273 return;
274 }
275 sb.Append(prefix).AppendFormat("static bool %s(struct HdfSBuf *parcel, const char *desc, void *interface)\n",
276 methodName.c_str());
277 sb.Append(prefix).Append("{\n");
278 sb.Append(prefix + TAB).Append("if (interface == NULL) {\n");
279 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: invalid interface object\", __func__);\n");
280 sb.Append(prefix + TAB + TAB).Append("return false;\n");
281 sb.Append(prefix + TAB).Append("}\n\n");
282 sb.Append(prefix + TAB).Append("struct HdfRemoteService **stub = StubCollectorGetOrNewObject(desc, interface);\n");
283 sb.Append(prefix + TAB).Append("if (stub == NULL) {\n");
284 sb.Append(prefix + TAB + TAB).Append(
285 "HDF_LOGE(\"%{public}s: failed to get stub of '%{public}s'\", __func__, desc);\n");
286 sb.Append(prefix + TAB + TAB).Append("return false;\n");
287 sb.Append(prefix + TAB).Append("}\n\n");
288 sb.Append(prefix + TAB).Append("if (HdfSbufWriteRemoteService(parcel, *stub) != HDF_SUCCESS) {\n");
289 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: failed to write remote service\", __func__);\n");
290 sb.Append(prefix + TAB + TAB).Append("return false;\n");
291 sb.Append(prefix + TAB).Append("}\n\n");
292 sb.Append(prefix + TAB).Append("return true;\n");
293 sb.Append(prefix).Append("}\n");
294 }
295
EmitCReadMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const296 void ASTInterfaceType::EmitCReadMethods(StringBuilder &sb, const std::string &prefix,
297 const std::string &methodPrefix, bool isDecl) const
298 {
299 std::string methodName = StringHelper::Format("%sRead%s", methodPrefix.c_str(), name_.c_str());
300 if (isDecl) {
301 sb.Append(prefix).AppendFormat("static struct %s *%s(struct HdfSBuf *parcel);\n", name_.c_str(),
302 methodName.c_str());
303 return;
304 }
305 sb.Append(prefix).AppendFormat("static struct %s *%s(struct HdfSBuf *parcel)\n", name_.c_str(),
306 methodName.c_str());
307 sb.Append(prefix).Append("{\n");
308 sb.Append(prefix + TAB).Append("struct HdfRemoteService *remote = HdfSbufReadRemoteService(parcel);\n");
309 sb.Append(prefix + TAB).Append("if (remote == NULL) {\n");
310 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: ");
311 sb.AppendFormat(" failed to read remote service of '%s'\", __func__);\n", name_.c_str());
312 sb.Append(prefix + TAB + TAB).Append("return NULL;\n");
313 sb.Append(prefix + TAB).Append("}\n\n");
314 sb.Append(prefix + TAB).AppendFormat("return %sGet(remote);\n", name_.c_str());
315 sb.Append(prefix).Append("}\n");
316 }
317 } // namespace HDI
318 } // namespace OHOS
319