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