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 "metadata/metadata_dumper.h"
17#include "util/string_builder.h"
18
19namespace OHOS {
20namespace Idl {
21std::string MetadataDumper::tab_ = "    ";
22std::string MetadataDumper::Dump(const std::string& prefix)
23{
24    if (metaComponent_ == nullptr) {
25        return "";
26    }
27
28    return DumpMetaComponent(metaComponent_, prefix);
29}
30
31std::string MetadataDumper::DumpMetaComponent(MetaComponent* mc, const std::string& prefix)
32{
33    StringBuilder sb;
34
35    sb.Append(prefix).Append("MetaComponent\n");
36    sb.Append(prefix).Append("{\n");
37    sb.Append(prefix + tab_).AppendFormat("\"magic_\" : \"0x%x\",\n", mc->magic_);
38    sb.Append(prefix + tab_).AppendFormat("\"size_\" : \"%d\",\n", mc->size_);
39    sb.Append(prefix + tab_).AppendFormat("\"name_\" : \"%s\",\n", mc->name_);
40    sb.Append(prefix + tab_).AppendFormat("\"namespaceNumber_\" : \"%d\",\n", mc->namespaceNumber_);
41    sb.Append(prefix + tab_).AppendFormat("\"sequenceableNumber_\" : \"%d\",\n", mc->sequenceableNumber_);
42    sb.Append(prefix + tab_).AppendFormat("\"interfaceNumber_\" : \"%d\",\n", mc->interfaceNumber_);
43    sb.Append(prefix + tab_).AppendFormat("\"typeNumber_\" : \"%d\",\n", mc->typeNumber_);
44
45    DumpMetaNamespaces(sb, mc, prefix);
46    DumpMetaSequenceables(sb, mc, prefix);
47    DumpMetaInterfaces(sb, mc, prefix);
48
49    sb.Append(prefix + tab_).AppendFormat("\"stringPoolSize_\" : \"%d\"\n", mc->stringPoolSize_);
50
51    sb.Append(prefix).Append("}\n");
52
53    return sb.ToString();
54}
55
56void MetadataDumper::DumpMetaNamespaces(StringBuilder& sb, MetaComponent* mc, const std::string& prefix)
57{
58    if (mc->namespaceNumber_ == 0) {
59        sb.Append(prefix + tab_).Append("\"namespaces_\" : [],\n");
60    } else {
61        sb.Append(prefix + tab_).Append("\"namespaces_\" : [\n");
62        for (int i = 0; i < mc->namespaceNumber_; i++) {
63            DumpMetaNamespace(sb, mc->namespaces_[i], prefix + tab_ + tab_);
64            if (i != mc->namespaceNumber_ - 1) {
65                sb.Append(",\n");
66            }
67        }
68        sb.Append("\n" + prefix + tab_).Append("],\n");
69    }
70}
71
72void MetadataDumper::DumpMetaNamespace(StringBuilder& sb, MetaNamespace* mn, const std::string& prefix)
73{
74    sb.Append(prefix).Append("{\n");
75    sb.Append(prefix + tab_).AppendFormat("\"name_\" : \"%s\",\n", mn->name_);
76    sb.Append(prefix + tab_).AppendFormat("\"sequenceableNumber_\" : \"%d\",\n", mn->sequenceableNumber_);
77    sb.Append(prefix + tab_).AppendFormat("\"interfaceNumber_\" : \"%d\",\n", mn->interfaceNumber_);
78    sb.Append(prefix + tab_).AppendFormat("\"namespaceNumber_\" : \"%d\",\n", mn->namespaceNumber_);
79
80    if (mn->sequenceableNumber_ == 0) {
81        sb.Append(prefix + tab_).Append("\"sequenceableIndexes_\" : [],\n");
82    } else {
83        sb.Append(prefix + tab_).Append("\"sequenceableIndexes_\" : [\n");
84        for (int i = 0; i < mn->sequenceableNumber_; i++) {
85            MetaSequenceable* mp = metaComponent_->sequenceables_[i];
86            sb.Append(prefix + tab_ + tab_).AppendFormat("{ \"name\" : \"%s\" }", mp->name_);
87            if (i != mn->sequenceableNumber_ - 1) {
88                sb.Append(",\n");
89            }
90        }
91        sb.Append("\n" + prefix + tab_).Append("],\n");
92    }
93
94    if (mn->interfaceNumber_ == 0) {
95        sb.Append(prefix + tab_).Append("\"interfaceIndexes_\" : [],\n");
96    } else {
97        sb.Append(prefix + tab_).Append("\"interfaceIndexes_\" : [\n");
98        for (int i = 0; i < mn->interfaceNumber_; i++) {
99            MetaInterface* mi = metaComponent_->interfaces_[mn->interfaceIndexes_[i]];
100            sb.Append(prefix + tab_ + tab_).AppendFormat("{ \"name\" : \"%s\" }", mi->name_);
101            if (i != mn->interfaceNumber_ - 1) {
102                sb.Append(",\n");
103            }
104        }
105        sb.Append("\n" + prefix + tab_).Append("],\n");
106    }
107
108    if (mn->namespaceNumber_ == 0) {
109        sb.Append(prefix + tab_).Append("\"namespaces_\" : []\n");
110    } else {
111        sb.Append(prefix + tab_).Append("\"namespaces_\" : [\n");
112        for (int i = 0; i < mn->namespaceNumber_; i++) {
113            MetaNamespace* innermn = mn->namespaces_[i];
114            DumpMetaNamespace(sb, innermn, prefix + tab_ + tab_);
115            if (i != mn->namespaceNumber_ - 1) {
116                sb.Append(",\n");
117            }
118        }
119        sb.Append("\n" + prefix + tab_).Append("]\n");
120    }
121
122    sb.Append(prefix).Append("}");
123}
124
125void MetadataDumper::DumpMetaSequenceables(StringBuilder& sb, MetaComponent* mc, const std::string& prefix)
126{
127    if (mc->sequenceableNumber_ == 0) {
128        sb.Append(prefix + tab_).Append("\"sequenceables_\" : [],\n");
129    } else {
130        sb.Append(prefix + tab_).Append("\"sequenceables_\" : [\n");
131        for (int i = 0; i < mc->sequenceableNumber_; i++) {
132            DumpMetaSequenceable(sb, mc->sequenceables_[i], prefix + tab_ + tab_);
133            if (i != mc->sequenceableNumber_ - 1) {
134                sb.Append(",\n");
135            }
136        }
137        sb.Append("\n" + prefix + tab_).Append("],\n");
138    }
139}
140
141void MetadataDumper::DumpMetaSequenceable(StringBuilder& sb, MetaSequenceable* mp, const std::string& prefix)
142{
143    sb.Append(prefix).Append("{\n");
144    sb.Append(prefix + tab_).AppendFormat("\"name_\" : \"%s\",\n", mp->name_);
145    sb.Append(prefix + tab_).AppendFormat("\"namespace_\" : \"%s\"\n", mp->namespace_);
146    sb.Append(prefix).Append("}");
147}
148
149void MetadataDumper::DumpMetaInterfaces(StringBuilder& sb, MetaComponent* mc, const std::string& prefix)
150{
151    if (mc->interfaceNumber_ == 0) {
152        sb.Append(prefix + tab_).Append("\"interfaces_\" : [],\n");
153    } else {
154        sb.Append(prefix + tab_).Append("\"interfaces_\" : [\n");
155        for (int i = 0; i < mc->interfaceNumber_; i++) {
156            DumpMetaInterface(sb, mc->interfaces_[i], prefix + tab_ + tab_);
157            if (i != mc->interfaceNumber_ - 1) {
158                sb.Append(",\n");
159            }
160        }
161        sb.Append("\n" + prefix + tab_).Append("],\n");
162    }
163}
164
165void MetadataDumper::DumpMetaInterface(StringBuilder& sb, MetaInterface* mi, const std::string& prefix)
166{
167    sb.Append(prefix).Append("{\n");
168    sb.Append(prefix + tab_).AppendFormat("\"name_\" : \"%s\",\n", mi->name_);
169    sb.Append(prefix + tab_).AppendFormat("\"namespace_\" : \"%s\",\n", mi->namespace_);
170    sb.Append(prefix + tab_).AppendFormat("\"properties_\" : \"%s\",\n",
171        (mi->properties_ & INTERFACE_PROPERTY_ONEWAY) != 0 ? "oneway" : "");
172    sb.Append(prefix + tab_).AppendFormat("\"methodNumber_\" : \"%d\",\n", mi->methodNumber_);
173    sb.Append(prefix + tab_).AppendFormat("\"external_\" : \"%d\",\n", mi->external_);
174
175    if (mi->methodNumber_ == 0) {
176        sb.Append(prefix + tab_).Append("\"methods_\" : []\n");
177    } else {
178        sb.Append(prefix + tab_).Append("\"methods_\" : [\n");
179        for (int i = 0; i < mi->methodNumber_; i++) {
180            DumpMetaMethod(sb, mi->methods_[i], prefix + tab_ + tab_);
181            if (i != mi->methodNumber_ - 1) {
182                sb.Append(",\n");
183            }
184        }
185        sb.Append("\n" + prefix + tab_).Append("]\n");
186    }
187
188    sb.Append(prefix).Append("}");
189}
190
191void MetadataDumper::DumpMetaMethod(StringBuilder& sb, MetaMethod* mm, const std::string& prefix)
192{
193    sb.Append(prefix).Append("{\n");
194    sb.Append(prefix + tab_).AppendFormat("\"name_\" : \"%s\",\n", mm->name_);
195    sb.Append(prefix + tab_).AppendFormat("\"signature_\" : \"%s\",\n", mm->signature_);
196    sb.Append(prefix + tab_).AppendFormat("\"properties_\" : \"%s\",\n",
197        (mm->properties_ & METHOD_PROPERTY_ONEWAY) != 0 ? "oneway" : "");
198    MetaType* type = metaComponent_->types_[mm->returnTypeIndex_];
199    sb.Append(prefix + tab_).AppendFormat("\"returnType_\" : \"%s\",\n", DumpMetaType(type).c_str());
200    sb.Append(prefix + tab_).AppendFormat("\"parameterNumber_\" : \"%d\",\n", mm->parameterNumber_);
201
202    if (mm->parameterNumber_ == 0) {
203        sb.Append(prefix + tab_).Append("\"parameters_\" : []\n");
204    } else {
205        sb.Append(prefix + tab_).Append("\"parameters_\" : [\n");
206        for (int i = 0; i < mm->parameterNumber_; i++) {
207            DumpMetaParameter(sb, mm->parameters_[i], prefix + tab_ + tab_);
208            if (i != mm->parameterNumber_ - 1) {
209                sb.Append(",\n");
210            }
211        }
212        sb.Append("\n" + prefix + tab_).Append("]\n");
213    }
214
215    sb.Append(prefix).Append("}");
216}
217
218void MetadataDumper::DumpMetaParameter(StringBuilder& sb, MetaParameter* mp, const std::string& prefix)
219{
220    sb.Append(prefix).Append("{\n");
221    sb.Append(prefix + tab_).AppendFormat("\"name_\" : \"%s\",\n", mp->name_);
222    sb.Append(prefix + tab_).Append("\"attributes_\" : \"");
223    bool addComma = false;
224    if ((mp->attributes_ & ATTR_IN) == ATTR_IN) {
225        sb.Append("in");
226        addComma = true;
227    }
228    if ((mp->attributes_ & ATTR_OUT) == ATTR_OUT) {
229        sb.Append(addComma ? ", out" : "out");
230    }
231    sb.Append("\",\n");
232    MetaType* type = metaComponent_->types_[mp->typeIndex_];
233    sb.Append(prefix + tab_).AppendFormat("\"type_\" : \"%s\"\n", DumpMetaType(type).c_str());
234
235    sb.Append(prefix).Append("}");
236}
237
238std::string MetadataDumper::DumpMetaType(MetaType* mt)
239{
240    switch (mt->kind_) {
241        case MetaTypeKind::Char:
242            return "char";
243        case MetaTypeKind::Boolean:
244            return "boolean";
245        case MetaTypeKind::Byte:
246            return "byte";
247        case MetaTypeKind::Short:
248            return "short";
249        case MetaTypeKind::Integer:
250            return "int";
251        case MetaTypeKind::Long:
252            return "long";
253        case MetaTypeKind::Float:
254            return "float";
255        case MetaTypeKind::Double:
256            return "double";
257        case MetaTypeKind::String:
258            return "String";
259        case MetaTypeKind::Void:
260            return "void";
261        case MetaTypeKind::Sequenceable: {
262            MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_];
263            return reinterpret_cast<char*>(mp->name_);
264        }
265        case MetaTypeKind::Interface: {
266            MetaInterface* mi = metaComponent_->interfaces_[mt->index_];
267            return reinterpret_cast<char*>(mi->name_);
268        }
269        case MetaTypeKind::List: {
270            MetaType* elementMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
271            return "List<" + DumpMetaType(elementMt) + ">";
272        }
273        case MetaTypeKind::Map: {
274            MetaType* keyMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
275            MetaType* valueMt = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
276            return "Map<" + DumpMetaType(keyMt) + ", " + DumpMetaType(valueMt) + ">";
277        }
278        case MetaTypeKind::Array: {
279            MetaType* elementMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
280            return DumpMetaType(elementMt) + "[]";
281        }
282        case MetaTypeKind::Unknown:
283        default:
284            printf("Unknown %d\n", mt->index_);
285            return "unknown";
286    }
287}
288} // namespace Idl
289} // namespace OHOS
290