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 "sa_cpp_custom_types_code_emitter.h"
17 #include "util/file.h"
18
19 namespace OHOS {
20 namespace Idl {
21
EmitCode()22 void SaCppCustomTypesCodeEmitter::EmitCode()
23 {
24 SaTypeEmitter::circleCount_ = 0;
25 EmitCustomTypesHeaderFile();
26 EmitCustomTypesSourceFile();
27 }
28
EmitCustomTypesHeaderFile()29 void SaCppCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
30 {
31 std::string filePath =
32 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
33 File file(filePath, File::WRITE);
34 std::string marcoName = StringHelper::Format("%s.%s", ast_->GetPackageName().c_str(), baseName_.c_str());
35 StringBuilder sb;
36
37 EmitLicense(sb);
38 EmitHeadMacro(sb, marcoName);
39 sb.Append("\n");
40 EmitHeaderFileInclusions(sb);
41 sb.Append("\n");
42 EmitBeginNamespace(sb);
43 sb.Append("\n");
44 EmitCustomTypeDecls(sb);
45 sb.Append("\n");
46 EmitCustomTypeFuncDecl(sb);
47 sb.Append("\n");
48 EmitEndNamespace(sb);
49 sb.Append("\n");
50 EmitTailMacro(sb, marcoName);
51
52 std::string data = sb.ToString();
53 file.WriteData(data.c_str(), data.size());
54 file.Flush();
55 file.Close();
56 }
57
EmitHeaderFileInclusions(StringBuilder & sb)58 void SaCppCustomTypesCodeEmitter::EmitHeaderFileInclusions(StringBuilder &sb)
59 {
60 HeaderFile::HeaderFileSet headerFiles;
61 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdbool");
62 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdint");
63 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
64 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iremote_proxy");
65 GetStdlibInclusions(headerFiles);
66 GetImportInclusions(headerFiles);
67
68 bool needLogh = false;
69 bool needSecurec = false;
70 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
71 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
72 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
73 AutoPtr<ASTStructType> structType = static_cast<ASTStructType *>(type.Get());
74 if (!type->IsPod() && logOn_) {
75 needLogh = true;
76 }
77 if (EmitCustomTypeNeedSecurec(structType)) {
78 needSecurec = true;
79 }
80 if (needLogh && needSecurec) {
81 break;
82 }
83 }
84 }
85
86 if (needSecurec) {
87 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
88 }
89 if (needLogh) {
90 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, "hilog/log");
91 }
92 for (const auto &file : headerFiles) {
93 sb.AppendFormat("%s\n", file.ToString().c_str());
94 }
95 if (needLogh && !domainId_.empty() && !logTag_.empty()) {
96 sb.AppendFormat(
97 "static constexpr OHOS::HiviewDFX::HiLogLabel %s_LABEL = {LOG_CORE, %s, \"%s\"};\n",
98 StringHelper::StrToUpper(baseName_).c_str(), domainId_.c_str(), logTag_.c_str());
99 }
100 }
101
EmitCustomTypeNeedSecurec(const AutoPtr<ASTStructType> & type) const102 bool SaCppCustomTypesCodeEmitter::EmitCustomTypeNeedSecurec(const AutoPtr<ASTStructType> &type) const
103 {
104 if (type->IsPod()) {
105 return true;
106 } else {
107 for (size_t j = 0; j < type->GetMemberNumber(); j++) {
108 AutoPtr<ASTType> memberType = type->GetMemberType(j);
109 if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) {
110 return true;
111 }
112 }
113 }
114 return false;
115 }
116
EmitDefineConstant(StringBuilder & sb) const117 void SaCppCustomTypesCodeEmitter::EmitDefineConstant(StringBuilder &sb) const
118 {
119 sb.Append(
120 "[[maybe_unused]] static constexpr int VECTOR_MAX_SIZE = 102400;\n"
121 "[[maybe_unused]] static constexpr int LIST_MAX_SIZE = 102400;\n"
122 "[[maybe_unused]] static constexpr int SET_MAX_SIZE = 102400;\n"
123 "[[maybe_unused]] static constexpr int MAP_MAX_SIZE = 102400;\n");
124 }
125
EmitCustomTypeDecls(StringBuilder & sb) const126 void SaCppCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder &sb) const
127 {
128 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
129 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(ast_->GetTypeDefintion(i));
130 if (typeEmitter == nullptr) {
131 return;
132 }
133 sb.Append(typeEmitter->EmitCppTypeDecl()).Append("\n");
134 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
135 sb.Append("\n");
136 }
137 }
138 }
139
EmitCustomTypeFuncDecl(StringBuilder & sb) const140 void SaCppCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder &sb) const
141 {
142 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
143 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
144 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
145 EmitCustomTypeMarshallFuncDecl(sb, type);
146 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
147 sb.Append("\n");
148 }
149 }
150 }
151 }
152
EmitCustomTypeMarshallFuncDecl(StringBuilder & sb,const AutoPtr<ASTType> & type) const153 void SaCppCustomTypesCodeEmitter::EmitCustomTypeMarshallFuncDecl(StringBuilder &sb, const AutoPtr<ASTType> &type) const
154 {
155 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(type);
156 if (typeEmitter == nullptr) {
157 return;
158 }
159 std::string objName("dataBlock");
160 sb.AppendFormat("ErrCode %sBlockMarshalling(OHOS::MessageParcel &data, const %s& %s);\n\n", type->GetName().c_str(),
161 typeEmitter->EmitCppType().c_str(), objName.c_str());
162 sb.AppendFormat("ErrCode %sBlockUnmarshalling(OHOS::MessageParcel &data, %s& %s);\n", type->GetName().c_str(),
163 typeEmitter->EmitCppType().c_str(), objName.c_str());
164 }
165
EmitCustomTypesSourceFile()166 void SaCppCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
167 {
168 std::string filePath =
169 File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(baseName_).c_str()));
170 File file(filePath, File::WRITE);
171 StringBuilder sb;
172
173 EmitLicense(sb);
174 EmitSourceFileInclusions(sb);
175 sb.Append("\n");
176 if (hitraceOn_) {
177 sb.Append("#include \"hitrace_meter.h\"\n");
178 }
179 if (logOn_) {
180 sb.Append(
181 "#include \"hilog/log.h\"\n"
182 "using OHOS::HiviewDFX::HiLog;\n\n");
183 }
184 EmitBeginNamespace(sb);
185 sb.Append("\n");
186 EmitDefineConstant(sb);
187 sb.Append("\n");
188 EmitCustomTypeDataProcess(sb);
189 EmitEndNamespace(sb);
190
191 std::string data = sb.ToString();
192
193 std::string customLabel = "(" + StringHelper::StrToUpper(baseName_) + "_LABEL,";
194 std::string oldLabel = "(LABEL,";
195
196 size_t pos = 0;
197 while ((pos = data.find(oldLabel, pos)) != std::string::npos) {
198 data.replace(pos, oldLabel.size(), customLabel);
199 pos += customLabel.length();
200 }
201
202 file.WriteData(data.c_str(), data.size());
203 file.Flush();
204 file.Close();
205 }
206
EmitSourceFileInclusions(StringBuilder & sb)207 void SaCppCustomTypesCodeEmitter::EmitSourceFileInclusions(StringBuilder &sb)
208 {
209 HeaderFile::HeaderFileSet headerFiles;
210
211 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_));
212
213 for (const auto &file : headerFiles) {
214 sb.AppendFormat("%s\n", file.ToString().c_str());
215 }
216 }
217
EmitCustomTypeDataProcess(StringBuilder & sb) const218 void SaCppCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder &sb) const
219 {
220 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
221 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
222 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
223 AutoPtr<ASTStructType> structType = static_cast<ASTStructType *>(type.Get());
224 if (structType == nullptr) {
225 continue;
226 }
227 EmitCustomTypeMarshallingImpl(sb, structType);
228 EmitCustomTypeUnmarshallingImpl(sb, structType);
229 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
230 sb.Append("\n");
231 }
232 }
233 }
234 }
235
EmitCustomTypeMarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type) const236 void SaCppCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(
237 StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
238 {
239 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(type.Get());
240 if (typeEmitter == nullptr) {
241 return;
242 }
243 std::string typeName = typeEmitter->EmitCppType();
244 std::string objName("dataBlock");
245
246 sb.AppendFormat("ErrCode %sBlockMarshalling(OHOS::MessageParcel& data, const %s& %s)\n", type->GetName().c_str(),
247 typeName.c_str(), objName.c_str());
248 sb.Append("{\n");
249
250 if (type->IsPod()) {
251 sb.Append(TAB).AppendFormat("if (!data.WriteUnpadBuffer(&%s, sizeof(%s))) {\n",
252 objName.c_str(), typeName.c_str());
253 sb.Append(TAB).Append(TAB).Append("return ERR_INVALID_DATA;\n");
254 sb.Append(TAB).Append("}\n");
255 } else {
256 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
257 std::string memberName = type->GetMemberName(i);
258 std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
259 typeEmitter = GetTypeEmitter(type->GetMemberType(i));
260 if (typeEmitter == nullptr) {
261 continue;
262 }
263 typeEmitter->EmitCppWriteVar("data.", name, sb, TAB);
264 if (i + 1 < type->GetMemberNumber()) {
265 sb.Append("\n");
266 }
267 }
268 }
269
270 sb.Append(TAB).Append("return ERR_NONE;\n");
271 sb.Append("}\n\n");
272 }
273
EmitCustomTypeUnmarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type) const274 void SaCppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(
275 StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
276 {
277 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(type.Get());
278 if (typeEmitter == nullptr) {
279 return;
280 }
281 std::string typeName = typeEmitter->EmitCppType();
282 std::string objName("dataBlock");
283
284 sb.AppendFormat("ErrCode %sBlockUnmarshalling(OHOS::MessageParcel& data, %s& %s)\n", type->GetName().c_str(),
285 typeName.c_str(), objName.c_str());
286 sb.Append("{\n");
287
288 if (type->IsPod()) {
289 std::string objPtrName = StringHelper::Format("%sPtr", objName.c_str());
290 sb.Append(TAB).AppendFormat("const %s *%s = reinterpret_cast<const %s *>(data.ReadUnpadBuffer(sizeof(%s)));\n",
291 typeName.c_str(), objPtrName.c_str(), typeName.c_str(), typeName.c_str());
292 sb.Append(TAB).AppendFormat("if (%s == nullptr) {\n", objPtrName.c_str());
293 sb.Append(TAB).Append(TAB).Append("return ERR_INVALID_DATA;\n");
294 sb.Append(TAB).Append("}\n\n");
295 sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", objName.c_str(),
296 typeName.c_str(), objPtrName.c_str(), typeName.c_str());
297 sb.Append(TAB).Append(TAB).Append("return ERR_INVALID_DATA;\n");
298 sb.Append(TAB).Append("}\n");
299 } else {
300 EmitCustomTypeUnmarshallingImplNoPod(sb, type);
301 }
302 sb.Append(TAB).AppendFormat("return ERR_NONE;\n");
303 sb.Append("}\n");
304 }
305
EmitCustomTypeUnmarshallingImplNoPod(StringBuilder & sb,const AutoPtr<ASTStructType> & type) const306 void SaCppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImplNoPod(
307 StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
308 {
309 std::string objName("dataBlock");
310 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
311 AutoPtr<ASTType> memberType = type->GetMemberType(i);
312 std::string memberName = type->GetMemberName(i);
313 std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
314 if (i > 0) {
315 sb.Append("\n");
316 }
317
318 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(memberType);
319 if (typeEmitter == nullptr) {
320 return;
321 }
322 if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) {
323 std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
324 typeEmitter->EmitCppReadVar("data.", cpName, sb, TAB);
325 sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
326 name.c_str(), typeEmitter->EmitCppType().c_str(), cpName.c_str(),
327 typeEmitter->EmitCppType().c_str());
328 if (logOn_) {
329 sb.Append(TAB).Append(TAB).AppendFormat("HiLog::Error(LABEL, \"memcpy [%s] failed!\");\n",
330 name.c_str());
331 }
332 sb.Append(TAB).Append(TAB).Append("return false;\n");
333 sb.Append(TAB).Append("}\n");
334 } else if (memberType->GetTypeKind() == TypeKind::TYPE_STRING) {
335 std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
336 typeEmitter->EmitCppReadVar("data.", cpName, sb, TAB);
337 sb.Append(TAB).AppendFormat("%s = %s;\n", name.c_str(), cpName.c_str());
338 } else {
339 typeEmitter->EmitCppReadVar("data.", name, sb, TAB, false);
340 }
341 }
342 }
343
EmitBeginNamespace(StringBuilder & sb)344 void SaCppCustomTypesCodeEmitter::EmitBeginNamespace(StringBuilder &sb)
345 {
346 std::string fullnamespace = ast_->GetPackageName();
347 std::vector<std::string> namespaceVec = StringHelper::Split(fullnamespace, ".");
348
349 for (const auto &nspace : namespaceVec) {
350 sb.AppendFormat("namespace %s {\n", nspace.c_str());
351 }
352 }
353
EmitEndNamespace(StringBuilder & sb)354 void SaCppCustomTypesCodeEmitter::EmitEndNamespace(StringBuilder &sb)
355 {
356 std::string fullnamespace = ast_->GetPackageName();
357 std::vector<std::string> namespaceVec = StringHelper::Split(fullnamespace, ".");
358
359 for (std::vector<std::string>::const_reverse_iterator nspaceIter = namespaceVec.rbegin();
360 nspaceIter != namespaceVec.rend(); ++nspaceIter) {
361 sb.AppendFormat("} // namespace %s\n", nspaceIter->c_str());
362 }
363 }
364
365 } // namespace Idl
366 } // namespace OHOS
367