• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "codegen/code_emitter.h"
17 
18 #include <cctype>
19 
20 #include "util/file.h"
21 #include "util/options.h"
22 
23 namespace OHOS {
24 namespace Idl {
EmitLicense(StringBuilder & sb)25 void CodeEmitter::EmitLicense(StringBuilder &sb)
26 {
27     if (ast_->GetLicense().empty()) {
28         return;
29     }
30     sb.Append(ast_->GetLicense()).Append("\n\n");
31 }
32 
NeedFlag(const AutoPtr<ASTMethod> & method) const33 bool CodeEmitter::NeedFlag(const AutoPtr<ASTMethod> &method) const
34 {
35     for (size_t i = 0; i < method->GetParameterNumber(); i++) {
36         AutoPtr<ASTParameter> param = method->GetParameter(i);
37         if (param == nullptr) {
38             return false;
39         }
40         AutoPtr<ASTType> type = param->GetType();
41         if ((param->GetAttribute() & ASTParamAttr::PARAM_OUT) &&
42             (type->IsStringType() || type->IsArrayType() || type->IsListType())) {
43             return true;
44         }
45     }
46     return false;
47 }
48 
49 /*
50  * -r option: -r ohos.hdi:./drivers/interface
51  * outDir: ./out
52  * package: ohos.hdi.foo.v1_0
53  * subPackage: foo.v1_0
54  * subPath: foo/v1_0
55  * GenPath: ./out/foo/v1_0/
56  */
GetFileParentPath(const std::string & outDir) const57 std::string CodeEmitter::GetFileParentPath(const std::string &outDir) const
58 {
59     if (outDir.size() > SIZE_MAX) {
60         return std::string("");
61     }
62     std::string outPath = StringHelper::EndWith(outDir, SEPARATOR) ? outDir.substr(0, outDir.size() - 1) : outDir;
63     std::string subPackage = Options::GetInstance().GetSubPackage(ast_->GetPackageName());
64     std::string subPath = StringHelper::Replace(subPackage, '.', SEPARATOR);
65     if (subPath.empty()) {
66         return File::AdapterPath(StringHelper::Format("%s/", outPath.c_str(), subPath.c_str()));
67     } else {
68         return File::AdapterPath(StringHelper::Format("%s/%s/", outPath.c_str(), subPath.c_str()));
69     }
70 }
71 
PackageToFilePath(const std::string & packageName) const72 std::string CodeEmitter::PackageToFilePath(const std::string &packageName) const
73 {
74     std::vector<std::string> packageVec = StringHelper::Split(Options::GetInstance().GetSubPackage(packageName), ".");
75     StringBuilder filePath;
76     for (auto iter = packageVec.begin(); iter != packageVec.end(); iter++) {
77         filePath.Append(FileName(*iter));
78         if (iter != packageVec.end() - 1) {
79             filePath.Append(SEPARATOR);
80         }
81     }
82 
83     return filePath.ToString();
84 }
85 
InterfaceToFilePath(const std::string & interfaceName) const86 std::string CodeEmitter::InterfaceToFilePath(const std::string &interfaceName) const
87 {
88     std::string fullName = interfaceName;
89     size_t index;
90     if (StringHelper::EndWith(fullName, "]")) {
91         index = fullName.find("[");
92         fullName = fullName.substr(0, index);
93     }
94 
95     index = fullName.rfind(".");
96     std::string prefix = fullName.substr(0, index + 1);
97     std::string suffix = fullName.substr(index + 1);
98     std::string fileName = prefix + (StringHelper::StartWith(suffix, "I") ? suffix.substr(1) : suffix) + "Proxy";
99     return PackageToFilePath(fileName);
100 }
101 
EmitMethodCmdID(const AutoPtr<ASTMethod> & method)102 std::string CodeEmitter::EmitMethodCmdID(const AutoPtr<ASTMethod> &method)
103 {
104     return StringHelper::Format("CMD_%s_%s%s",
105         ConstantName(baseName_).c_str(), ConstantName(method->GetName()).c_str(),
106         method->GetMethodIdentifier().c_str());
107 }
108 
EmitInterfaceMethodCommands(StringBuilder & sb,const std::string & prefix)109 void CodeEmitter::EmitInterfaceMethodCommands(StringBuilder &sb, const std::string &prefix)
110 {
111     sb.Append(prefix).AppendFormat("enum {\n");
112     sb.Append(prefix + TAB).Append(EmitMethodCmdID(interface_->GetVersionMethod())).Append(" = 0,\n");
113     int i = 0;
114     for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
115         sb.Append(prefix + TAB).Append(EmitMethodCmdID(method)).AppendFormat(" = %d", i + 1).Append(",\n");
116         i++;
117     }
118     sb.Append(prefix).Append("};\n");
119 }
120 
EmitVersionHeaderName(const std::string & name) const121 std::string CodeEmitter::EmitVersionHeaderName(const std::string &name) const
122 {
123     InterfaceType interfaceType = Options::GetInstance().GetInterfaceType();
124     if (interfaceType == InterfaceType::SA) {
125         return StringHelper::Format("%s", FileName(name).c_str());
126     }
127     return StringHelper::Format("v%u_%u/%s", ast_->GetMajorVer(), ast_->GetMinorVer(), FileName(name).c_str());
128 }
129 
EmitLogTagMacro(StringBuilder & sb,const std::string & name) const130 void CodeEmitter::EmitLogTagMacro(StringBuilder &sb, const std::string &name) const
131 {
132     sb.AppendFormat("#define HDF_LOG_TAG    %s\n", name.c_str());
133 }
134 
ConstantName(const std::string & name) const135 std::string CodeEmitter::ConstantName(const std::string &name) const
136 {
137     StringBuilder sb;
138 
139     if (name.empty()) {
140         return name;
141     }
142 
143     for (size_t i = 0; i < name.size(); i++) {
144         char c = name[i];
145         if (isupper(c) != 0) {
146             if (i > 1) {
147                 sb.Append('_');
148             }
149             sb.Append(c);
150         } else {
151             sb.Append(toupper(c));
152         }
153     }
154 
155     return sb.ToString();
156 }
157 
PascalName(const std::string & name) const158 std::string CodeEmitter::PascalName(const std::string &name) const
159 {
160     if (name.empty()) {
161         return name;
162     }
163 
164     StringBuilder sb;
165     for (size_t i = 0; i < name.size(); i++) {
166         char c = name[i];
167         if (i == 0) {
168             if (islower(c)) {
169                 c = toupper(c);
170             }
171             sb.Append(c);
172         } else {
173             if (c == '_') {
174                 continue;
175             }
176 
177             if (islower(c) && name[i - 1] == '_') {
178                 c = toupper(c);
179             }
180             sb.Append(c);
181         }
182     }
183 
184     return sb.ToString();
185 }
186 
FileName(const std::string & name) const187 std::string CodeEmitter::FileName(const std::string &name) const
188 {
189     if (name.empty()) {
190         return name;
191     }
192 
193     StringBuilder sb;
194     for (size_t i = 0; i < name.size(); i++) {
195         char c = name[i];
196         if (isupper(c) != 0) {
197             // 2->Index of the last char array.
198             if ((i > 1) && (name[i - 1] != '.') && (name[i - 2] != '.')) {
199                 sb.Append('_');
200             }
201             sb.Append(tolower(c));
202         } else {
203             sb.Append(c);
204         }
205     }
206 
207     return StringHelper::Replace(sb.ToString(), '.', '/');
208 }
209 
GetNamespace(const std::string & fpnp) const210 std::string CodeEmitter::GetNamespace(const std::string &fpnp) const
211 {
212     size_t pos = fpnp.find("..");
213     if (pos == std::string::npos) {
214         return fpnp;
215     }
216 
217     return fpnp.substr(pos + strlen(".."));
218 }
219 
EmitHeadMacro(StringBuilder & sb,const std::string & fullName) const220 void CodeEmitter::EmitHeadMacro(StringBuilder &sb, const std::string &fullName) const
221 {
222     std::string macroName = MacroName(fullName);
223     sb.Append("#ifndef ").Append(macroName).Append("\n");
224     sb.Append("#define ").Append(macroName).Append("\n");
225 }
226 
EmitTailMacro(StringBuilder & sb,const std::string & fullName) const227 void CodeEmitter::EmitTailMacro(StringBuilder &sb, const std::string &fullName) const
228 {
229     std::string macroName = MacroName(fullName);
230     sb.Append("#endif // ").Append(macroName.c_str()).Append("\n\n");
231 }
232 
EmitHeadExternC(StringBuilder & sb) const233 void CodeEmitter::EmitHeadExternC(StringBuilder &sb) const
234 {
235     sb.Append("#ifdef __cplusplus\n");
236     sb.Append("extern \"C\" {\n");
237     sb.Append("#endif /* __cplusplus */\n");
238 }
239 
EmitTailExternC(StringBuilder & sb) const240 void CodeEmitter::EmitTailExternC(StringBuilder &sb) const
241 {
242     sb.Append("#ifdef __cplusplus\n");
243     sb.Append("}\n");
244     sb.Append("#endif /* __cplusplus */\n");
245 }
246 
MacroName(const std::string & name) const247 std::string CodeEmitter::MacroName(const std::string &name) const
248 {
249     if (name.empty()) {
250         return name;
251     }
252 
253     std::string macro = StringHelper::StrToUpper(StringHelper::Replace(name, '.', '_')) + "_H";
254     return macro;
255 }
256 } // namespace Idl
257 } // namespace OHOS
258