1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cpp_service_impl_code_emitter.h"
17 #include "util/file.h"
18 #include "util/logger.h"
19
20 namespace OHOS {
21 namespace Idl {
ResolveDirectory(const std::string & targetDirectory)22 bool CppServiceImplCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
23 {
24 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
25 directory_ = GetFileParentPath(targetDirectory);
26 } else {
27 return false;
28 }
29
30 if (!File::CreateParentDir(directory_)) {
31 Logger::E("CppServiceImplCodeEmitter", "Create '%s' failed!", directory_.c_str());
32 return false;
33 }
34
35 return true;
36 }
37
EmitCode()38 void CppServiceImplCodeEmitter::EmitCode()
39 {
40 switch (mode_) {
41 case GenMode::PASSTHROUGH:
42 case GenMode::IPC: {
43 EmitImplHeaderFile();
44 EmitImplSourceFile();
45 break;
46 }
47 default:
48 break;
49 }
50 }
51
EmitImplHeaderFile()52 void CppServiceImplCodeEmitter::EmitImplHeaderFile()
53 {
54 std::string filePath =
55 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
56 File file(filePath, File::WRITE);
57 StringBuilder sb;
58
59 EmitLicense(sb);
60 EmitHeadMacro(sb, implFullName_);
61 sb.Append("\n");
62 EmitServiceImplInclusions(sb);
63 sb.Append("\n");
64 EmitServiceImplDecl(sb);
65 sb.Append("\n");
66 EmitTailMacro(sb, implFullName_);
67
68 std::string data = sb.ToString();
69 file.WriteData(data.c_str(), data.size());
70 file.Flush();
71 file.Close();
72 }
73
EmitServiceImplInclusions(StringBuilder & sb)74 void CppServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder &sb)
75 {
76 HeaderFile::HeaderFileSet headerFiles;
77 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
78
79 for (const auto &file : headerFiles) {
80 sb.AppendFormat("%s\n", file.ToString().c_str());
81 }
82 }
83
EmitServiceImplDecl(StringBuilder & sb)84 void CppServiceImplCodeEmitter::EmitServiceImplDecl(StringBuilder &sb)
85 {
86 EmitBeginNamespace(sb);
87 sb.AppendFormat("class %sService : public %s {\n", baseName_.c_str(),
88 EmitDefinitionByInterface(interface_, interfaceName_).c_str());
89 sb.Append("public:\n");
90 EmitServiceImplBody(sb, TAB);
91 sb.Append("};\n");
92 EmitEndNamespace(sb);
93 }
94
EmitServiceImplBody(StringBuilder & sb,const std::string & prefix)95 void CppServiceImplCodeEmitter::EmitServiceImplBody(StringBuilder &sb, const std::string &prefix)
96 {
97 (void)prefix;
98 EmitServiceImplConstructor(sb, TAB);
99 sb.Append("\n");
100 EmitServiceImplMethodDecls(sb, TAB);
101 }
102
EmitServiceImplConstructor(StringBuilder & sb,const std::string & prefix) const103 void CppServiceImplCodeEmitter::EmitServiceImplConstructor(StringBuilder &sb, const std::string &prefix) const
104 {
105 sb.Append(prefix).AppendFormat("%s() = default;\n", implName_.c_str());
106 sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", implName_.c_str());
107 }
108
EmitServiceImplMethodDecls(StringBuilder & sb,const std::string & prefix) const109 void CppServiceImplCodeEmitter::EmitServiceImplMethodDecls(StringBuilder &sb, const std::string &prefix) const
110 {
111 AutoPtr<ASTInterfaceType> interface = interface_;
112 while (interface != nullptr) {
113 for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
114 EmitServiceImplMethodDecl(method, sb, prefix);
115 sb.Append("\n");
116 }
117 interface = interface->GetExtendsInterface();
118 }
119 }
120
EmitServiceImplMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const121 void CppServiceImplCodeEmitter::EmitServiceImplMethodDecl(
122 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
123 {
124 if (method->GetParameterNumber() == 0) {
125 sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().c_str());
126 } else {
127 StringBuilder paramStr;
128 paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
129 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
130 AutoPtr<ASTParameter> param = method->GetParameter(i);
131 EmitInterfaceMethodParameter(param, paramStr, "");
132 if (i + 1 < method->GetParameterNumber()) {
133 paramStr.Append(", ");
134 }
135 }
136
137 paramStr.Append(") override;");
138
139 sb.Append(SpecificationParam(paramStr, prefix + TAB));
140 sb.Append("\n");
141 }
142 }
143
EmitImplSourceFile()144 void CppServiceImplCodeEmitter::EmitImplSourceFile()
145 {
146 std::string filePath = File::AdapterPath(
147 StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(implName_).c_str()));
148 File file(filePath, File::WRITE);
149 StringBuilder sb;
150
151 EmitLicense(sb);
152 EmitImplSourceInclusions(sb);
153 sb.Append("\n");
154 EmitLogTagMacro(sb, FileName(implName_));
155 sb.Append("\n");
156 EmitBeginNamespace(sb);
157 EmitServiceImplGetMethodImpl(sb, "");
158 EmitServiceImplMethodImpls(sb, "");
159 EmitEndNamespace(sb);
160
161 std::string data = sb.ToString();
162 file.WriteData(data.c_str(), data.size());
163 file.Flush();
164 file.Close();
165 }
166
EmitImplSourceInclusions(StringBuilder & sb)167 void CppServiceImplCodeEmitter::EmitImplSourceInclusions(StringBuilder &sb)
168 {
169 HeaderFile::HeaderFileSet headerFiles;
170 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
171 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
172
173 for (const auto &file : headerFiles) {
174 sb.AppendFormat("%s\n", file.ToString().c_str());
175 }
176 }
177
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const178 void CppServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
179 {
180 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
181 }
182
EmitServiceImplMethodImpls(StringBuilder & sb,const std::string & prefix) const183 void CppServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const
184 {
185 AutoPtr<ASTInterfaceType> interface = interface_;
186 while (interface != nullptr) {
187 for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
188 EmitServiceImplMethodImpl(method, sb, prefix);
189 sb.Append("\n");
190 }
191 interface = interface->GetExtendsInterface();
192 }
193 }
194
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const195 void CppServiceImplCodeEmitter::EmitServiceImplMethodImpl(
196 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
197 {
198 if (method->GetParameterNumber() == 0) {
199 sb.Append(prefix).AppendFormat("int32_t %sService::%s()\n", baseName_.c_str(), method->GetName().c_str());
200 } else {
201 StringBuilder paramStr;
202 paramStr.Append(prefix).AppendFormat("int32_t %sService::%s(", baseName_.c_str(), method->GetName().c_str());
203 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
204 AutoPtr<ASTParameter> param = method->GetParameter(i);
205 EmitInterfaceMethodParameter(param, paramStr, "");
206 if (i + 1 < method->GetParameterNumber()) {
207 paramStr.Append(", ");
208 }
209 }
210
211 paramStr.AppendFormat(")");
212
213 sb.Append(SpecificationParam(paramStr, prefix + TAB));
214 sb.Append("\n");
215 }
216
217 sb.Append(prefix).Append("{\n");
218 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
219 sb.Append(prefix).Append("}\n");
220 }
221
EmitServiceImplGetMethodImpl(StringBuilder & sb,const std::string & prefix) const222 void CppServiceImplCodeEmitter::EmitServiceImplGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
223 {
224 if (!interface_->IsSerializable()) {
225 sb.Append(prefix).AppendFormat(
226 "extern \"C\" %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
227 sb.Append(prefix).Append("{\n");
228 sb.Append(prefix + TAB).AppendFormat("return new (std::nothrow) %s();\n", implName_.c_str());
229 sb.Append(prefix).Append("}\n\n");
230 }
231 }
232 } // namespace Idl
233 } // namespace OHOS