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 "hdi_enum_type_emitter.h"
17 
18 namespace OHOS {
19 namespace Idl {
SetBaseTypeName(const std::string & name)20 void HdiEnumTypeEmitter::SetBaseTypeName(const std::string &name)
21 {
22     baseTypeName_ = name;
23 }
24 
GetTypeKind()25 TypeKind HdiEnumTypeEmitter::GetTypeKind()
26 {
27     return TypeKind::TYPE_ENUM;
28 }
29 
EmitCType(TypeMode mode) const30 std::string HdiEnumTypeEmitter::EmitCType(TypeMode mode) const
31 {
32     switch (mode) {
33         case TypeMode::NO_MODE:
34             return StringHelper::Format("enum %s", name_.c_str());
35         case TypeMode::PARAM_IN:
36             return StringHelper::Format("enum %s", name_.c_str());
37         case TypeMode::PARAM_OUT:
38             return StringHelper::Format("enum %s*", name_.c_str());
39         case TypeMode::LOCAL_VAR:
40             return StringHelper::Format("enum %s", name_.c_str());
41         default:
42             return "unknown type";
43     }
44 }
45 
EmitCppType(TypeMode mode) const46 std::string HdiEnumTypeEmitter::EmitCppType(TypeMode mode) const
47 {
48     switch (mode) {
49         case TypeMode::NO_MODE:
50         case TypeMode::PARAM_IN:
51         case TypeMode::LOCAL_VAR:
52             return StringHelper::Format("%s", typeName_.c_str());
53         case TypeMode::PARAM_OUT:
54             return StringHelper::Format("%s&", typeName_.c_str());
55         default:
56             return "unknown type";
57     }
58 }
59 
EmitJavaType(TypeMode mode,bool isInnerType) const60 std::string HdiEnumTypeEmitter::EmitJavaType(TypeMode mode, bool isInnerType) const
61 {
62     // currently, Java does not support the enum type.
63     return "/";
64 }
65 
EmitCTypeDecl() const66 std::string HdiEnumTypeEmitter::EmitCTypeDecl() const
67 {
68     StringBuilder sb;
69     sb.AppendFormat("enum %s {\n", name_.c_str());
70 
71     for (auto it : members_) {
72         if (it->GetValue().empty()) {
73             sb.Append(TAB).AppendFormat("%s,\n", it->GetValueName().c_str());
74         } else {
75             sb.Append(TAB).AppendFormat("%s = %s,\n", it->GetValueName().c_str(), it->GetValue().c_str());
76         }
77     }
78 
79     sb.Append("};");
80     return sb.ToString();
81 }
82 
EmitCppTypeDecl() const83 std::string HdiEnumTypeEmitter::EmitCppTypeDecl() const
84 {
85     StringBuilder sb;
86     if (baseTypeName_.empty()) {
87         sb.AppendFormat("enum %s {\n", name_.c_str());
88     } else {
89         sb.AppendFormat("enum %s : %s {\n", name_.c_str(), baseTypeName_.c_str());
90     }
91 
92     for (auto it : members_) {
93         if (it->GetValue().empty()) {
94             sb.Append(TAB).AppendFormat("%s,\n", it->GetValueName().c_str());
95         } else {
96             sb.Append(TAB).AppendFormat("%s = %s,\n", it->GetValueName().c_str(), it->GetValue().c_str());
97         }
98     }
99 
100     sb.Append("};");
101     return sb.ToString();
102 }
103 
EmitCWriteVar(TypeMode mode,const std::string & name,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const104 void HdiEnumTypeEmitter::EmitCWriteVar(TypeMode mode, const std::string &name,
105     const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
106 {
107     std::string parcelName = (mode == TypeMode::PARAM_IN) ? dataParcelName_ : replyParcelName_;
108     sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(%s, (uint64_t)%s)) {\n", parcelName.c_str(), name.c_str());
109     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
110     sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.c_str());
111     sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
112     sb.Append(prefix).Append("}\n");
113 }
114 
EmitCProxyReadVar(const std::string & name,bool isInnerType,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const115 void HdiEnumTypeEmitter::EmitCProxyReadVar(const std::string &name, bool isInnerType, const std::string &gotoLabel,
116     StringBuilder &sb, const std::string &prefix) const
117 {
118     std::string tmpVarName = "enumTmp";
119     sb.Append(prefix).Append("{\n");
120     sb.Append(prefix + TAB).AppendFormat("uint64_t %s = 0;\n", tmpVarName.c_str());
121     sb.Append(prefix + TAB)
122         .AppendFormat("if (!HdfSbufReadUint64(%s, &%s)) {\n", replyParcelName_.c_str(), tmpVarName.c_str());
123     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
124     sb.Append(prefix + TAB + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.c_str());
125     sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
126     sb.Append(prefix + TAB).Append("}\n\n");
127     sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.c_str());
128     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: invlid parameter %s\", __func__);\n",
129         name.c_str());
130     sb.Append(prefix + TAB + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.c_str());
131     sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
132     sb.Append(prefix + TAB).Append("}\n\n");
133     sb.Append(prefix + TAB).AppendFormat("*%s = (%s)%s;\n", name.c_str(), EmitCType().c_str(), tmpVarName.c_str());
134     sb.Append(prefix).Append("}\n");
135 }
136 
EmitCStubReadVar(const std::string & name,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const137 void HdiEnumTypeEmitter::EmitCStubReadVar(const std::string &name, const std::string &gotoLabel, StringBuilder &sb,
138     const std::string &prefix) const
139 {
140     std::string tmpVarName = "enumTmp";
141     sb.Append(prefix).Append("{\n");
142     sb.Append(prefix + TAB).AppendFormat("uint64_t %s = 0;\n", tmpVarName.c_str());
143     sb.Append(prefix + TAB)
144         .AppendFormat("if (!HdfSbufReadUint64(%s, &%s)) {\n", dataParcelName_.c_str(), tmpVarName.c_str());
145     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
146     sb.Append(prefix + TAB + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.c_str());
147     sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
148     sb.Append(prefix + TAB).Append("}\n");
149     sb.Append(prefix + TAB).AppendFormat("%s = (%s)%s;\n", name.c_str(), EmitCType().c_str(), tmpVarName.c_str());
150     sb.Append(prefix).Append("}\n");
151 }
152 
EmitCppWriteVar(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,unsigned int innerLevel) const153 void HdiEnumTypeEmitter::EmitCppWriteVar(const std::string &parcelName, const std::string &name,
154     StringBuilder &sb, const std::string &prefix, unsigned int innerLevel) const
155 {
156     sb.Append(prefix).AppendFormat("if (!%s.WriteUint64(static_cast<uint64_t>(%s))) {\n", parcelName.c_str(),
157         name.c_str());
158     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
159     sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
160     sb.Append(prefix).Append("}\n");
161 }
162 
EmitCppReadVar(const std::string & name,StringBuilder & sb,const std::string & prefix,TypeMode mode,unsigned int innerLevel) const163 void HdiEnumTypeEmitter::EmitCppReadVar(const std::string &name, StringBuilder &sb, const std::string &prefix,
164     TypeMode mode, unsigned int innerLevel) const
165 {
166     std::string tmpVarName = "enumTmp";
167     std::string parcelName = (mode == TypeMode::PARAM_IN) ? dataParcelName_ : replyParcelName_;
168     if ((mode == TypeMode::PARAM_IN) || (innerLevel > 0)) {
169         sb.Append(prefix).AppendFormat("%s %s = static_cast<%s>(0);\n", EmitCppType().c_str(), name.c_str(),
170             EmitCType().c_str());
171     }
172     sb.Append(prefix).Append("{\n");
173     sb.Append(prefix + TAB).AppendFormat("uint64_t %s = 0;\n", tmpVarName.c_str());
174     sb.Append(prefix + TAB).AppendFormat("if (!%s.ReadUint64(%s)) {\n", parcelName.c_str(), tmpVarName.c_str());
175     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n",
176         name.c_str());
177     sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
178     sb.Append(prefix + TAB).Append("}\n");
179     sb.Append(prefix + TAB).AppendFormat("%s = static_cast<%s>(%s);\n", name.c_str(), EmitCType().c_str(),
180         tmpVarName.c_str());
181     sb.Append(prefix).Append("}\n");
182 }
183 
EmitCMarshalling(const std::string & name,StringBuilder & sb,const std::string & prefix) const184 void HdiEnumTypeEmitter::EmitCMarshalling(const std::string &name, StringBuilder &sb, const std::string &prefix) const
185 {
186     sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(data, (uint64_t)%s)) {\n", name.c_str());
187     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
188     sb.Append(prefix + TAB).Append("return false;\n");
189     sb.Append(prefix).Append("}\n");
190 }
191 
EmitCUnMarshalling(const std::string & name,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix,std::vector<std::string> & freeObjStatements) const192 void HdiEnumTypeEmitter::EmitCUnMarshalling(const std::string &name, const std::string &gotoLabel,
193     StringBuilder &sb, const std::string &prefix, std::vector<std::string> &freeObjStatements) const
194 {
195     std::string tmpVarName = "enumTmp";
196     sb.Append(prefix).Append("{\n");
197     sb.Append(prefix + TAB).AppendFormat("uint64_t %s = 0;\n", tmpVarName.c_str());
198     sb.Append(prefix + TAB).AppendFormat("if (!HdfSbufReadUint64(data, &%s)) {\n", tmpVarName.c_str());
199     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
200     sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
201     sb.Append(prefix + TAB).Append("}\n");
202     sb.Append(prefix + TAB).AppendFormat("%s = (%s)%s;\n", name.c_str(), EmitCType().c_str(), tmpVarName.c_str());
203     sb.Append(prefix).Append("}\n");
204 }
205 
EmitCppMarshalling(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,unsigned int innerLevel) const206 void HdiEnumTypeEmitter::EmitCppMarshalling(const std::string &parcelName, const std::string &name,
207     StringBuilder &sb, const std::string &prefix, unsigned int innerLevel) const
208 {
209     sb.Append(prefix).AppendFormat(
210         "if (!%s.WriteUint64(static_cast<uint64_t>(%s))) {\n", parcelName.c_str(), name.c_str());
211     sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.c_str());
212     sb.Append(prefix + TAB).Append("return false;\n");
213     sb.Append(prefix).Append("}\n");
214 }
215 
EmitCppUnMarshalling(const std::string & parcelName,const std::string & name,StringBuilder & sb,const std::string & prefix,unsigned int innerLevel) const216 void HdiEnumTypeEmitter::EmitCppUnMarshalling(const std::string &parcelName, const std::string &name,
217     StringBuilder &sb, const std::string &prefix, unsigned int innerLevel) const
218 {
219     std::string tmpVarName = "enumTmp";
220     if (innerLevel > 0) {
221         sb.Append(prefix).AppendFormat("%s %s = static_cast<%s>(0);\n", EmitCppType().c_str(), name.c_str(),
222             EmitCType().c_str());
223     }
224     sb.Append(prefix).Append("{\n");
225     sb.Append(prefix + TAB).AppendFormat("uint64_t %s = 0;\n", tmpVarName.c_str());
226     sb.Append(prefix + TAB).AppendFormat("if (!%s.ReadUint64(%s)) {\n", parcelName.c_str(), tmpVarName.c_str());
227     sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n",
228         name.c_str());
229     sb.Append(prefix + TAB + TAB).Append("return false;\n");
230     sb.Append(prefix + TAB).Append("}\n");
231     sb.Append(prefix + TAB).AppendFormat("%s = static_cast<%s>(%s);\n", name.c_str(), EmitCType().c_str(),
232         tmpVarName.c_str());
233     sb.Append(prefix).Append("}\n");
234 }
235 } // namespace Idl
236 } // namespace OHOS
237