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 "codegen/cpp_service_impl_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)15 bool CppServiceImplCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
16 {
17 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
18 directory_ = GetFileParentPath(targetDirectory);
19 } else {
20 return false;
21 }
22
23 if (!File::CreateParentDir(directory_)) {
24 Logger::E("CppServiceImplCodeEmitter", "Create '%s' failed!", directory_.c_str());
25 return false;
26 }
27
28 return true;
29 }
30
EmitCode()31 void CppServiceImplCodeEmitter::EmitCode()
32 {
33 switch (mode_) {
34 case GenMode::PASSTHROUGH:
35 case GenMode::IPC: {
36 EmitImplHeaderFile();
37 EmitImplSourceFile();
38 break;
39 }
40 default:
41 break;
42 }
43 }
44
EmitImplHeaderFile()45 void CppServiceImplCodeEmitter::EmitImplHeaderFile()
46 {
47 std::string filePath =
48 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
49 File file(filePath, File::WRITE);
50 StringBuilder sb;
51
52 EmitLicense(sb);
53 EmitHeadMacro(sb, implFullName_);
54 sb.Append("\n");
55 EmitServiceImplInclusions(sb);
56 sb.Append("\n");
57 EmitServiceImplDecl(sb);
58 sb.Append("\n");
59 EmitTailMacro(sb, implFullName_);
60
61 std::string data = sb.ToString();
62 file.WriteData(data.c_str(), data.size());
63 file.Flush();
64 file.Close();
65 }
66
EmitServiceImplInclusions(StringBuilder & sb)67 void CppServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder &sb)
68 {
69 HeaderFile::HeaderFileSet headerFiles;
70 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
71
72 for (const auto &file : headerFiles) {
73 sb.AppendFormat("%s\n", file.ToString().c_str());
74 }
75 }
76
EmitServiceImplDecl(StringBuilder & sb)77 void CppServiceImplCodeEmitter::EmitServiceImplDecl(StringBuilder &sb)
78 {
79 EmitBeginNamespace(sb);
80 sb.AppendFormat("class %sService : public %s {\n", baseName_.c_str(),
81 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
82 sb.Append("public:\n");
83 EmitServiceImplBody(sb, TAB);
84 sb.Append("};\n");
85 EmitEndNamespace(sb);
86 }
87
EmitServiceImplBody(StringBuilder & sb,const std::string & prefix)88 void CppServiceImplCodeEmitter::EmitServiceImplBody(StringBuilder &sb, const std::string &prefix)
89 {
90 (void)prefix;
91 EmitServiceImplConstructor(sb, TAB);
92 sb.Append("\n");
93 EmitServiceImplMethodDecls(sb, TAB);
94 }
95
EmitServiceImplConstructor(StringBuilder & sb,const std::string & prefix) const96 void CppServiceImplCodeEmitter::EmitServiceImplConstructor(StringBuilder &sb, const std::string &prefix) const
97 {
98 sb.Append(prefix).AppendFormat("%s() = default;\n", implName_.c_str());
99 sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", implName_.c_str());
100 }
101
EmitServiceImplMethodDecls(StringBuilder & sb,const std::string & prefix) const102 void CppServiceImplCodeEmitter::EmitServiceImplMethodDecls(StringBuilder &sb, const std::string &prefix) const
103 {
104 AutoPtr<ASTInterfaceType> interface = interface_;
105 while (interface != nullptr) {
106 for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
107 EmitServiceImplMethodDecl(method, sb, prefix);
108 sb.Append("\n");
109 }
110 interface = interface->GetExtendsInterface();
111 }
112 }
113
EmitServiceImplMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const114 void CppServiceImplCodeEmitter::EmitServiceImplMethodDecl(
115 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
116 {
117 if (method->GetParameterNumber() == 0) {
118 sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().c_str());
119 } else {
120 StringBuilder paramStr;
121 paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
122 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
123 AutoPtr<ASTParameter> param = method->GetParameter(i);
124 EmitInterfaceMethodParameter(param, paramStr, "");
125 if (i + 1 < method->GetParameterNumber()) {
126 paramStr.Append(", ");
127 }
128 }
129
130 paramStr.Append(") override;");
131
132 sb.Append(SpecificationParam(paramStr, prefix + TAB));
133 sb.Append("\n");
134 }
135 }
136
EmitImplSourceFile()137 void CppServiceImplCodeEmitter::EmitImplSourceFile()
138 {
139 std::string filePath = File::AdapterPath(
140 StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(implName_).c_str()));
141 File file(filePath, File::WRITE);
142 StringBuilder sb;
143
144 EmitLicense(sb);
145 EmitImplSourceInclusions(sb);
146 sb.Append("\n");
147 EmitLogTagMacro(sb, FileName(implName_));
148 sb.Append("\n");
149 EmitBeginNamespace(sb);
150 EmitServiceImplGetMethodImpl(sb, "");
151 EmitServiceImplMethodImpls(sb, "");
152 EmitEndNamespace(sb);
153
154 std::string data = sb.ToString();
155 file.WriteData(data.c_str(), data.size());
156 file.Flush();
157 file.Close();
158 }
159
EmitImplSourceInclusions(StringBuilder & sb)160 void CppServiceImplCodeEmitter::EmitImplSourceInclusions(StringBuilder &sb)
161 {
162 HeaderFile::HeaderFileSet headerFiles;
163 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
164 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
165
166 for (const auto &file : headerFiles) {
167 sb.AppendFormat("%s\n", file.ToString().c_str());
168 }
169 }
170
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const171 void CppServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
172 {
173 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
174 }
175
EmitServiceImplMethodImpls(StringBuilder & sb,const std::string & prefix) const176 void CppServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const
177 {
178 AutoPtr<ASTInterfaceType> interface = interface_;
179 while (interface != nullptr) {
180 for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
181 EmitServiceImplMethodImpl(method, sb, prefix);
182 sb.Append("\n");
183 }
184 interface = interface->GetExtendsInterface();
185 }
186 }
187
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const188 void CppServiceImplCodeEmitter::EmitServiceImplMethodImpl(
189 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
190 {
191 if (method->GetParameterNumber() == 0) {
192 sb.Append(prefix).AppendFormat("int32_t %sService::%s()\n", baseName_.c_str(), method->GetName().c_str());
193 } else {
194 StringBuilder paramStr;
195 paramStr.Append(prefix).AppendFormat("int32_t %sService::%s(", baseName_.c_str(), method->GetName().c_str());
196 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
197 AutoPtr<ASTParameter> param = method->GetParameter(i);
198 EmitInterfaceMethodParameter(param, paramStr, "");
199 if (i + 1 < method->GetParameterNumber()) {
200 paramStr.Append(", ");
201 }
202 }
203
204 paramStr.AppendFormat(")");
205
206 sb.Append(SpecificationParam(paramStr, prefix + TAB));
207 sb.Append("\n");
208 }
209
210 sb.Append(prefix).Append("{\n");
211 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
212 sb.Append(prefix).Append("}\n");
213 }
214
EmitServiceImplGetMethodImpl(StringBuilder & sb,const std::string & prefix) const215 void CppServiceImplCodeEmitter::EmitServiceImplGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
216 {
217 if (!interface_->IsSerializable()) {
218 sb.Append(prefix).AppendFormat(
219 "extern \"C\" %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
220 sb.Append(prefix).Append("{\n");
221 sb.Append(prefix + TAB).AppendFormat("return new (std::nothrow) %s();\n", implName_.c_str());
222 sb.Append(prefix).Append("}\n\n");
223 }
224 }
225 } // namespace HDI
226 } // namespace OHOS