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_reader.h"
17
18#include "metadata/metadata_serializer.h"
19#include "util/file.h"
20#include "util/logger.h"
21
22namespace OHOS {
23namespace Idl {
24std::string MetadataReader::tag_ = "MetadataReader";
25
26std::shared_ptr<MetaComponent> MetadataReader::ReadMetadataFromFile(const std::string& filePath)
27{
28    File file(filePath, File::READ);
29    if (!file.IsValid()) {
30        Logger::E(tag_.c_str(), "Open \"%s\" file failed.", filePath.c_str());
31        return nullptr;
32    }
33
34    if (!file.Reset()) {
35        Logger::E(tag_.c_str(), "Reset \"%s\" file failed.", filePath.c_str());
36        return nullptr;
37    }
38
39    MetaComponent header;
40
41    if (!file.ReadData((void*)&header, sizeof(MetaComponent))) {
42        Logger::E(tag_.c_str(), "Read \"%s\" file failed.", filePath.c_str());
43        return nullptr;
44    }
45
46    if (header.magic_ != METADATA_MAGIC_NUMBER || header.size_ < 0) {
47        Logger::E(tag_.c_str(), "The metadata in \"%s\" file is bad.", filePath.c_str());
48        return nullptr;
49    }
50
51    if (!file.Reset()) {
52        Logger::E(tag_.c_str(), "Reset \"%s\" file failed.", filePath.c_str());
53        return nullptr;
54    }
55
56    void* data = malloc(header.size_);
57    if (data == nullptr) {
58        Logger::E(tag_.c_str(), "Malloc metadata failed.");
59        return nullptr;
60    }
61
62    if (!file.ReadData(data, header.size_)) {
63        Logger::E(tag_.c_str(), "Read \"%s\" file failed.", filePath.c_str());
64        free(data);
65        return nullptr;
66    }
67
68    std::shared_ptr<MetaComponent> metadata(reinterpret_cast<MetaComponent *>(data), [](MetaComponent* p) { free(p); });
69
70    MetadataSerializer serializer((uintptr_t)data);
71    serializer.Deserialize();
72
73    return metadata;
74}
75
76std::unordered_map<std::string, AutoPtr<AST>> MetadataReader::ReadMetadataToAst()
77{
78    std::unordered_map<std::string, AutoPtr<AST>> allAsts;
79
80    ast_ = new AST();
81    for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) {
82        ReadMetaSequenceable(metaComponent_->sequenceables_[i]);
83    }
84
85    for (int i = 0; i < metaComponent_->interfaceNumber_; i++) {
86        ReadMetaInterface(metaComponent_->interfaces_[i]);
87    }
88
89    ast_->SetFullName(std::string(reinterpret_cast<char*>(metaComponent_->name_)));
90    ast_->SetAStFileType(ASTFileType::AST_IFACE);
91    allAsts[std::string(reinterpret_cast<char*>(metaComponent_->name_))] = ast_;
92
93    return allAsts;
94}
95
96void MetadataReader::ReadMetaSequenceable(MetaSequenceable* mp)
97{
98    AutoPtr<ASTSequenceableType> seqType = new ASTSequenceableType();
99
100    seqType->SetName(std::string(reinterpret_cast<char*>(mp->name_)));
101    seqType->SetNamespace(ast_->ParseNamespace(std::string(reinterpret_cast<char*>(mp->namespace_))));
102    AutoPtr<AST> seqAst = new AST();
103    seqAst->SetFullName(seqType->GetFullName());
104    seqAst->AddSequenceableDef(seqType);
105    seqAst->SetAStFileType(ASTFileType::AST_SEQUENCEABLE);
106    ast_->AddImport(seqAst);
107    ast_->AddSequenceableDef(seqType);
108}
109
110void MetadataReader::ReadMetaInterface(MetaInterface* mi)
111{
112    AutoPtr<ASTInterfaceType> interface = new ASTInterfaceType();
113    AutoPtr<ASTAttr> infAttr = new ASTAttr();
114    if (mi->properties_ == INTERFACE_PROPERTY_ONEWAY) {
115        infAttr->SetValue(ASTAttr::ONEWAY);
116    }
117    interface->SetAttribute(infAttr);
118    if (!mi->external_) {
119        interface->SetLicense(std::string(reinterpret_cast<char*>(mi->license_)));
120        ast_->SetLicense(std::string(reinterpret_cast<char*>(mi->license_)));
121    }
122    interface->SetName(std::string(reinterpret_cast<char*>(mi->name_)));
123
124    interface->SetNamespace(ast_->ParseNamespace(std::string(reinterpret_cast<char*>(mi->namespace_))));
125    interface->SetExternal(mi->external_);
126    ast_->AddInterfaceDef(interface);
127    for (int i = 0; i < mi->methodNumber_; i++) {
128        ReadMetaMethod(interface, mi->methods_[i]);
129    }
130}
131
132void MetadataReader::ReadMetaMethod(AutoPtr<ASTInterfaceType>& interface, MetaMethod* mm)
133{
134    AutoPtr<ASTMethod> method = new ASTMethod();
135    AutoPtr<ASTAttr> methodAttr = new ASTAttr();
136    if (mm->properties_ == METHOD_PROPERTY_ONEWAY) {
137        methodAttr->SetValue(ASTAttr::ONEWAY);
138    }
139    method->SetAttribute(methodAttr);
140
141    MetaType* type = metaComponent_->types_[mm->returnTypeIndex_];
142    method->SetReturnType(ReadMetaType(type));
143    method->SetName(std::string(reinterpret_cast<char*>((mm->name_))));
144    for (int i = 0; i < mm->parameterNumber_; i++) {
145        ReadMetaParam(method, mm->parameters_[i]);
146    }
147    interface->AddMethod(method);
148}
149
150void MetadataReader::ReadMetaParam(AutoPtr<ASTMethod>& method, MetaParameter* mp)
151{
152    AutoPtr<ASTParamAttr> attr = new ASTParamAttr(ASTParamAttr::PARAM_NONE);
153
154    if ((mp->attributes_ & ATTR_IN) == ATTR_IN) {
155        attr->value_ |= ASTParamAttr::PARAM_IN;
156    }
157
158    if ((mp->attributes_ & ATTR_OUT) == ATTR_OUT) {
159        attr->value_ |= ASTParamAttr::PARAM_OUT;
160    }
161
162    MetaType* type = metaComponent_->types_[mp->typeIndex_];
163    AutoPtr<ASTParameter> param = new ASTParameter(std::string(reinterpret_cast<char*>((mp->name_))),
164        attr, ReadMetaType(type));
165    method->AddParameter(param);
166}
167
168AutoPtr<ASTType> MetadataReader::ReadMetaType(MetaType* type)
169{
170    std::string typeName = MetaTypeName(type);
171    AutoPtr<ASTType> astType = ast_->FindType(typeName);
172    switch (type->kind_) {
173        case MetaTypeKind::List:
174            if (astType == nullptr) {
175                MetaType* elementMt = metaComponent_->types_[type->nestedTypeIndexes_[0]];
176                AutoPtr<ASTListType> listType = new ASTListType();
177                listType->SetElementType(ReadMetaType(elementMt));
178                astType = listType.Get();
179            }
180            break;
181        case MetaTypeKind::Map:
182            if (astType == nullptr) {
183                MetaType* keyMt = metaComponent_->types_[type->nestedTypeIndexes_[0]];
184                MetaType* valueMt = metaComponent_->types_[type->nestedTypeIndexes_[1]];
185                AutoPtr<ASTMapType> mapType = new ASTMapType();
186                mapType->SetKeyType(ReadMetaType(keyMt));
187                mapType->SetValueType(ReadMetaType(valueMt));
188                astType = mapType.Get();
189            }
190            break;
191        case MetaTypeKind::Array:
192            if (astType == nullptr) {
193                MetaType* elementMt = metaComponent_->types_[type->nestedTypeIndexes_[0]];
194                AutoPtr<ASTArrayType> arrayType = new ASTArrayType();
195                arrayType->SetElementType(ReadMetaType(elementMt));
196                astType = arrayType.Get();
197            }
198            break;
199        default:
200            break;
201    }
202    ast_->AddType(astType);
203    return astType;
204}
205
206std::string MetadataReader::MetaTypeName(MetaType* mt)
207{
208    switch (mt->kind_) {
209        case MetaTypeKind::Char:
210            return "char";
211        case MetaTypeKind::Boolean:
212            return "boolean";
213        case MetaTypeKind::Byte:
214            return "byte";
215        case MetaTypeKind::Short:
216            return "short";
217        case MetaTypeKind::Integer:
218            return "int";
219        case MetaTypeKind::Long:
220            return "long";
221        case MetaTypeKind::Float:
222            return "float";
223        case MetaTypeKind::Double:
224            return "double";
225        case MetaTypeKind::String:
226            return "String";
227        case MetaTypeKind::Void:
228            return "void";
229        case MetaTypeKind::Sequenceable: {
230            MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_];
231            return reinterpret_cast<char*>(mp->name_);
232        }
233        case MetaTypeKind::Interface: {
234            MetaInterface* mi = metaComponent_->interfaces_[mt->index_];
235            return reinterpret_cast<char*>(mi->name_);
236        }
237        case MetaTypeKind::List: {
238            MetaType* elementMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
239            return "List<" + MetaTypeName(elementMt) + ">";
240        }
241        case MetaTypeKind::Map: {
242            MetaType* keyMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
243            MetaType* valueMt = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
244            return "Map<" + MetaTypeName(keyMt) + ", " + MetaTypeName(valueMt) + ">";
245        }
246        case MetaTypeKind::Array: {
247            MetaType* elementMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
248            return MetaTypeName(elementMt) + "[]";
249        }
250        case MetaTypeKind::Unknown:
251        default:
252            printf("Unknown %d\n", mt->index_);
253            return "unknown";
254    }
255}
256} // namespace Idl
257} // namespace OHOS
258