• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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