• 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 "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