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 "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 EmitImplHeaderFile();
34 EmitImplSourceFile();
35 }
36
EmitImplHeaderFile()37 void CppServiceImplCodeEmitter::EmitImplHeaderFile()
38 {
39 std::string filePath =
40 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
41 File file(filePath, File::WRITE);
42 StringBuilder sb;
43
44 EmitLicense(sb);
45 EmitHeadMacro(sb, implFullName_);
46 sb.Append("\n");
47 EmitServiceImplInclusions(sb);
48 sb.Append("\n");
49 EmitServiceImplDecl(sb);
50 sb.Append("\n");
51 EmitTailMacro(sb, implFullName_);
52
53 std::string data = sb.ToString();
54 file.WriteData(data.c_str(), data.size());
55 file.Flush();
56 file.Close();
57 }
58
EmitServiceImplInclusions(StringBuilder & sb)59 void CppServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder &sb)
60 {
61 HeaderFile::HeaderFileSet headerFiles;
62 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
63
64 for (const auto &file : headerFiles) {
65 sb.AppendFormat("%s\n", file.ToString().c_str());
66 }
67 }
68
EmitServiceImplDecl(StringBuilder & sb)69 void CppServiceImplCodeEmitter::EmitServiceImplDecl(StringBuilder &sb)
70 {
71 EmitBeginNamespace(sb);
72 sb.AppendFormat("class %sService : public %s {\n", baseName_.c_str(), interfaceName_.c_str());
73 sb.Append("public:\n");
74 EmitServiceImplBody(sb, TAB);
75 sb.Append("};\n");
76 EmitEndNamespace(sb);
77 }
78
EmitServiceImplBody(StringBuilder & sb,const std::string & prefix)79 void CppServiceImplCodeEmitter::EmitServiceImplBody(StringBuilder &sb, const std::string &prefix)
80 {
81 EmitServiceImplConstructor(sb, TAB);
82 sb.Append("\n");
83 EmitServiceImplMethodDecls(sb, TAB);
84 }
85
EmitServiceImplConstructor(StringBuilder & sb,const std::string & prefix)86 void CppServiceImplCodeEmitter::EmitServiceImplConstructor(StringBuilder &sb, const std::string &prefix)
87 {
88 sb.Append(prefix).AppendFormat("%s() = default;\n", implName_.c_str());
89 sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", implName_.c_str());
90 }
91
EmitServiceImplMethodDecls(StringBuilder & sb,const std::string & prefix)92 void CppServiceImplCodeEmitter::EmitServiceImplMethodDecls(StringBuilder &sb, const std::string &prefix)
93 {
94 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
95 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
96 EmitServiceImplMethodDecl(method, sb, prefix);
97 if (i + 1 < interface_->GetMethodNumber()) {
98 sb.Append("\n");
99 }
100 }
101 }
102
EmitServiceImplMethodDecl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)103 void CppServiceImplCodeEmitter::EmitServiceImplMethodDecl(
104 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
105 {
106 if (method->GetParameterNumber() == 0) {
107 sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().c_str());
108 } else {
109 StringBuilder paramStr;
110 paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
111 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
112 AutoPtr<ASTParameter> param = method->GetParameter(i);
113 EmitInterfaceMethodParameter(param, paramStr, "");
114 if (i + 1 < method->GetParameterNumber()) {
115 paramStr.Append(", ");
116 }
117 }
118
119 paramStr.Append(") override;");
120
121 sb.Append(SpecificationParam(paramStr, prefix + TAB));
122 sb.Append("\n");
123 }
124 }
125
EmitImplSourceFile()126 void CppServiceImplCodeEmitter::EmitImplSourceFile()
127 {
128 std::string filePath = File::AdapterPath(
129 StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(implName_).c_str()));
130 File file(filePath, File::WRITE);
131 StringBuilder sb;
132
133 EmitLicense(sb);
134 EmitImplSourceInclusions(sb);
135 sb.Append("\n");
136 EmitLogTagMacro(sb, FileName(implName_));
137 sb.Append("\n");
138 EmitBeginNamespace(sb);
139 EmitServiceImplGetMethodImpl(sb, "");
140 EmitServiceImplMethodImpls(sb, "");
141 EmitEndNamespace(sb);
142
143 std::string data = sb.ToString();
144 file.WriteData(data.c_str(), data.size());
145 file.Flush();
146 file.Close();
147 }
148
EmitImplSourceInclusions(StringBuilder & sb)149 void CppServiceImplCodeEmitter::EmitImplSourceInclusions(StringBuilder &sb)
150 {
151 HeaderFile::HeaderFileSet headerFiles;
152 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
153 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
154
155 for (const auto &file : headerFiles) {
156 sb.AppendFormat("%s\n", file.ToString().c_str());
157 }
158 }
159
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)160 void CppServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
161 {
162 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
163 }
164
EmitServiceImplMethodImpls(StringBuilder & sb,const std::string & prefix)165 void CppServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix)
166 {
167 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
168 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
169 EmitServiceImplMethodImpl(method, sb, prefix);
170 if (i + 1 < interface_->GetMethodNumber()) {
171 sb.Append("\n");
172 }
173 }
174 }
175
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)176 void CppServiceImplCodeEmitter::EmitServiceImplMethodImpl(
177 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
178 {
179 if (method->GetParameterNumber() == 0) {
180 sb.Append(prefix).AppendFormat("int32_t %sService::%s()\n", baseName_.c_str(), method->GetName().c_str());
181 } else {
182 StringBuilder paramStr;
183 paramStr.Append(prefix).AppendFormat("int32_t %sService::%s(", baseName_.c_str(), method->GetName().c_str());
184 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
185 AutoPtr<ASTParameter> param = method->GetParameter(i);
186 EmitInterfaceMethodParameter(param, paramStr, "");
187 if (i + 1 < method->GetParameterNumber()) {
188 paramStr.Append(", ");
189 }
190 }
191
192 paramStr.AppendFormat(")");
193
194 sb.Append(SpecificationParam(paramStr, prefix + TAB));
195 sb.Append("\n");
196 }
197
198 sb.Append(prefix).Append("{\n");
199 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
200 sb.Append(prefix).Append("}\n");
201 }
202
EmitServiceImplGetMethodImpl(StringBuilder & sb,const std::string & prefix)203 void CppServiceImplCodeEmitter::EmitServiceImplGetMethodImpl(StringBuilder &sb, const std::string &prefix)
204 {
205 if (!interface_->IsSerializable()) {
206 sb.Append(prefix).AppendFormat(
207 "extern \"C\" %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
208 sb.Append(prefix).Append("{\n");
209 sb.Append(prefix + TAB).AppendFormat("return new (std::nothrow) %s();\n", implName_.c_str());
210 sb.Append(prefix).Append("}\n\n");
211 }
212 }
213 } // namespace HDI
214 } // namespace OHOS