1 /*
2 * Copyright (c) 2021-2022 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
IsInterfaceType()39 bool ASTInterfaceType::IsInterfaceType()
40 {
41 return true;
42 }
43
ToString() const44 std::string ASTInterfaceType::ToString() const
45 {
46 return name_;
47 }
48
Dump(const std::string & prefix)49 std::string ASTInterfaceType::Dump(const std::string &prefix)
50 {
51 StringBuilder sb;
52
53 sb.Append(prefix);
54 sb.Append(prefix).Append(attr_->Dump(prefix)).Append(" ");
55 sb.AppendFormat("interface %s {\n", name_.c_str());
56 for (auto method : methods_) {
57 std::string info = method->Dump(prefix + " ");
58 sb.Append(info);
59 if (method != methods_[methods_.size() - 1]) {
60 sb.Append('\n');
61 }
62 }
63 sb.Append(prefix).Append("}\n");
64
65 return sb.ToString();
66 }
67
GetTypeKind()68 TypeKind ASTInterfaceType::GetTypeKind()
69 {
70 return TypeKind::TYPE_INTERFACE;
71 }
72
GetFullName() const73 std::string ASTInterfaceType::GetFullName() const
74 {
75 return namespace_->ToString() + name_;
76 }
77
EmitDescMacroName() const78 std::string ASTInterfaceType::EmitDescMacroName() const
79 {
80 return StringHelper::Format("%s_INTERFACE_DESC", StringHelper::StrToUpper(name_).c_str());
81 }
82
EmitCType(TypeMode mode) const83 std::string ASTInterfaceType::EmitCType(TypeMode mode) const
84 {
85 switch (mode) {
86 case TypeMode::NO_MODE:
87 return StringHelper::Format("struct %s", name_.c_str());
88 case TypeMode::PARAM_IN:
89 return StringHelper::Format("struct %s*", name_.c_str());
90 case TypeMode::PARAM_OUT:
91 return StringHelper::Format("struct %s**", name_.c_str());
92 case TypeMode::LOCAL_VAR:
93 return StringHelper::Format("struct %s*", name_.c_str());
94 default:
95 return "unknow type";
96 }
97 }
98
EmitCppType(TypeMode mode) const99 std::string ASTInterfaceType::EmitCppType(TypeMode mode) const
100 {
101 switch (mode) {
102 case TypeMode::NO_MODE:
103 return StringHelper::Format("sptr<%s>", name_.c_str());
104 case TypeMode::PARAM_IN:
105 return StringHelper::Format("const sptr<%s>&", name_.c_str());
106 case TypeMode::PARAM_OUT:
107 return StringHelper::Format("sptr<%s>&", name_.c_str());
108 case TypeMode::LOCAL_VAR:
109 return StringHelper::Format("sptr<%s>", name_.c_str());
110 default:
111 return "unknow type";
112 }
113 }
114
EmitJavaType(TypeMode mode,bool isInnerType) const115 std::string ASTInterfaceType::EmitJavaType(TypeMode mode, bool isInnerType) const
116 {
117 return name_;
118 }
119
EmitCWriteVar(const std::string & parcelName,const std::string & name,const std::string & ecName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const120 void ASTInterfaceType::EmitCWriteVar(const std::string &parcelName, const std::string &name, const std::string &ecName,
121 const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
122 {
123 sb.Append(prefix).AppendFormat("if (!WriteInterface(%s, %s, %s)) {\n", parcelName.c_str(),
124 EmitDescMacroName().c_str(), name.c_str());
125 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
126 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
127 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
128 sb.Append(prefix).Append("}\n");
129 }
130
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) const131 void ASTInterfaceType::EmitCProxyReadVar(const std::string &parcelName, const std::string &name, bool isInnerType,
132 const std::string &ecName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
133 {
134 sb.Append(prefix).AppendFormat("*%s = Read%s(%s);\n", name.c_str(), name_.c_str(), parcelName.c_str());
135 sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.c_str());
136 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
137 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
138 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
139 sb.Append(prefix).Append("}\n");
140 }
141
EmitCStubReadVar(const std::string & parcelName,const std::string & name,const std::string & ecName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const142 void ASTInterfaceType::EmitCStubReadVar(const std::string &parcelName, const std::string &name,
143 const std::string &ecName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
144 {
145 sb.Append(prefix).AppendFormat("%s = Read%s(%s);\n", name.c_str(), name_.c_str(), parcelName.c_str());
146 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.c_str());
147 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
148 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", ecName.c_str());
149 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
150 sb.Append(prefix).Append("}\n");
151 }
152
EmitCppWriteVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,unsigned int innerLevel) const153 void ASTInterfaceType::EmitCppWriteVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
154 const std::string &prefix, unsigned int innerLevel) const
155 {
156 sb.Append(prefix).AppendFormat("if (!%s.WriteRemoteObject(", parcelName.c_str());
157 sb.AppendFormat("OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(%s, %s::GetDescriptor()))) {\n",
158 name.c_str(), name_.c_str());
159 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
160 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
161 sb.Append(prefix).Append("}\n");
162 }
163
EmitCppReadVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,bool initVariable,unsigned int innerLevel) const164 void ASTInterfaceType::EmitCppReadVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
165 const std::string &prefix, bool initVariable, unsigned int innerLevel) const
166 {
167 if (initVariable) {
168 sb.Append(prefix).AppendFormat("sptr<%s> %s;\n", name_.c_str(), name.c_str());
169 }
170 sb.Append(prefix).AppendFormat(
171 "if (!ReadInterface<%s>(%s, %s)) {\n", name_.c_str(), parcelName.c_str(), name.c_str());
172 sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to read interface object\", __func__);\n");
173 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
174 sb.Append(prefix).Append("}\n");
175 }
176
EmitJavaWriteVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix) const177 void ASTInterfaceType::EmitJavaWriteVar(
178 const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
179 {
180 sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s.asObject());\n", parcelName.c_str(), name.c_str());
181 }
182
EmitJavaReadVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix) const183 void ASTInterfaceType::EmitJavaReadVar(
184 const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
185 {
186 std::string stubName = StringHelper::StartWith(name_, "I") ? (name_.substr(1) + "Stub") : (name_ + "Stub");
187 sb.Append(prefix).AppendFormat(
188 "%s = %s.asInterface(%s.readRemoteObject());\n", name.c_str(), stubName.c_str(), parcelName.c_str());
189 }
190
EmitJavaReadInnerVar(const std::string & parcelName,const std::string & name,bool isInner,StringBuilder & sb,const std::string & prefix) const191 void ASTInterfaceType::EmitJavaReadInnerVar(const std::string &parcelName, const std::string &name, bool isInner,
192 StringBuilder &sb, const std::string &prefix) const
193 {
194 std::string stubName = StringHelper::StartWith(name_, "I") ? (name_.substr(1) + "Stub") : (name_ + "Stub");
195 sb.Append(prefix).AppendFormat("%s %s = %s.asInterface(%s.readRemoteObject());\n",
196 EmitJavaType(TypeMode::NO_MODE).c_str(), name.c_str(), stubName.c_str(), parcelName.c_str());
197 }
198
RegisterWriteMethod(Options::Language language,SerMode mode,UtilMethodMap & methods) const199 void ASTInterfaceType::RegisterWriteMethod(Options::Language language, SerMode mode, UtilMethodMap &methods) const
200 {
201 using namespace std::placeholders;
202 std::string methodName = "WriteInterface";
203 switch (language) {
204 case Options::Language::C:
205 methods.emplace(methodName, std::bind(&ASTInterfaceType::EmitCWriteMethods, this, _1, _2, _3, _4));
206 break;
207 default:
208 break;
209 }
210 }
211
RegisterReadMethod(Options::Language language,SerMode mode,UtilMethodMap & methods) const212 void ASTInterfaceType::RegisterReadMethod(Options::Language language, SerMode mode, UtilMethodMap &methods) const
213 {
214 using namespace std::placeholders;
215
216 switch (language) {
217 case Options::Language::C: {
218 std::string methodName = StringHelper::Format("Read%s", name_.c_str());
219 methods.emplace(methodName, std::bind(&ASTInterfaceType::EmitCReadMethods, this, _1, _2, _3, _4));
220 break;
221 }
222 case Options::Language::CPP: {
223 methods.emplace("ReadInterface", std::bind(&ASTInterfaceType::EmitCppReadMethods, this, _1, _2, _3, _4));
224 break;
225 }
226 default:
227 break;
228 }
229 }
230
EmitCWriteMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const231 void ASTInterfaceType::EmitCWriteMethods(StringBuilder &sb, const std::string &prefix,
232 const std::string &methodPrefix, bool isDecl) const
233 {
234 std::string methodName = StringHelper::Format("%sWriteInterface", methodPrefix.c_str());
235 if (isDecl) {
236 sb.Append(prefix).AppendFormat("static bool %s(struct HdfSBuf *parcel, const char *desc, void *interface);\n",
237 methodName.c_str());
238 return;
239 }
240 sb.Append(prefix).AppendFormat("static bool %s(struct HdfSBuf *parcel, const char *desc, void *interface)\n",
241 methodName.c_str());
242 sb.Append(prefix).Append("{\n");
243 sb.Append(prefix + TAB).Append("if (interface == NULL) {\n");
244 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: invalid interface object\", __func__);\n");
245 sb.Append(prefix + TAB + TAB).Append("return false;\n");
246 sb.Append(prefix + TAB).Append("}\n\n");
247 sb.Append(prefix + TAB).Append("struct HdfRemoteService **stub = StubCollectorGetOrNewObject(desc, interface);\n");
248 sb.Append(prefix + TAB).Append("if (stub == NULL) {\n");
249 sb.Append(prefix + TAB + TAB).Append(
250 "HDF_LOGE(\"%{public}s: failed to get stub of '%{public}s'\", __func__, desc);\n");
251 sb.Append(prefix + TAB + TAB).Append("return false;\n");
252 sb.Append(prefix + TAB).Append("}\n\n");
253 sb.Append(prefix + TAB).Append("if (HdfSbufWriteRemoteService(parcel, *stub) != HDF_SUCCESS) {\n");
254 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: failed to write remote service\", __func__);\n");
255 sb.Append(prefix + TAB + TAB).Append("return false;\n");
256 sb.Append(prefix + TAB).Append("}\n\n");
257 sb.Append(prefix + TAB).Append("return true;\n");
258 sb.Append(prefix).Append("}\n");
259 }
260
EmitCReadMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const261 void ASTInterfaceType::EmitCReadMethods(StringBuilder &sb, const std::string &prefix,
262 const std::string &methodPrefix, bool isDecl) const
263 {
264 std::string methodName = StringHelper::Format("%sRead%s", methodPrefix.c_str(), name_.c_str());
265 if (isDecl) {
266 sb.Append(prefix).AppendFormat("static struct %s *%s(struct HdfSBuf *parcel);\n", name_.c_str(),
267 methodName.c_str());
268 return;
269 }
270 sb.Append(prefix).AppendFormat("static struct %s *%s(struct HdfSBuf *parcel)\n", name_.c_str(),
271 methodName.c_str());
272 sb.Append(prefix).Append("{\n");
273 sb.Append(prefix + TAB).Append("struct HdfRemoteService *remote = HdfSbufReadRemoteService(parcel);\n");
274 sb.Append(prefix + TAB).Append("if (remote == NULL) {\n");
275 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: ");
276 sb.AppendFormat(" failed to read remote service of '%s'\", __func__);\n", name_.c_str());
277 sb.Append(prefix + TAB + TAB).Append("return NULL;\n");
278 sb.Append(prefix + TAB).Append("}\n\n");
279 sb.Append(prefix + TAB).AppendFormat("return %sGet(remote);\n", name_.c_str());
280 sb.Append(prefix).Append("}\n");
281 }
282
EmitCppReadMethods(StringBuilder & sb,const std::string & prefix,const std::string & methodPrefix,bool isDecl) const283 void ASTInterfaceType::EmitCppReadMethods(StringBuilder &sb, const std::string &prefix,
284 const std::string &methodPrefix, bool isDecl) const
285 {
286 std::string methodName = StringHelper::Format("%sReadInterface", methodPrefix.c_str(), name_.c_str());
287 sb.Append(prefix).AppendFormat("template<typename InterfaceType>\n");
288 sb.Append(prefix).AppendFormat("static bool %s(MessageParcel &parcel, sptr<InterfaceType>& object)",
289 methodName.c_str());
290 if (isDecl) {
291 sb.Append(";\n");
292 return;
293 } else {
294 sb.Append("\n");
295 }
296
297 sb.Append(prefix).Append("{\n");
298 sb.Append(prefix + TAB).Append("sptr<IRemoteObject> remote = parcel.ReadRemoteObject();\n");
299 sb.Append(prefix + TAB).Append("if (remote == nullptr) {\n");
300 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: read an invalid remote object\", __func__);\n");
301 sb.Append(prefix + TAB + TAB).Append("return false;\n");
302 sb.Append(prefix + TAB).Append("}\n\n");
303 sb.Append(prefix + TAB).Append("object = hdi_facecast<InterfaceType>(remote);\n");
304 sb.Append(prefix + TAB).Append("if (object == nullptr) {\n");
305 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: failed to cast interface object\", __func__);\n");
306 sb.Append(prefix + TAB + TAB).Append("return false;\n");
307 sb.Append(prefix + TAB).Append("}\n");
308 sb.Append(prefix + TAB).Append("return true;\n");
309 sb.Append(prefix).Append("}\n");
310 }
311 } // namespace HDI
312 } // namespace OHOS