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_builder.h"
17#include <cstring>
18#include "securec.h"
19#include "ast/ast_array_type.h"
20#include "ast/ast_map_type.h"
21#include "util/logger.h"
22
23#define ALIGN8(v) (((v) + 7) & ~7)
24
25namespace OHOS {
26namespace Idl {
27std::string MetadataBuilder::tag_ = "MetadataBuilder";
28std::shared_ptr<MetaComponent> MetadataBuilder::Build()
29{
30    if (!module_->IsValid()) {
31        Logger::E(tag_.c_str(), "The module is not validate.");
32        return nullptr;
33    }
34
35    size_ = CalculateMetadataSize();
36    if (size_ > 0) {
37        void* metadata =  calloc(size_, 1);
38        if (metadata == nullptr) {
39            Logger::E(tag_.c_str(), "Out of memory.");
40            return nullptr;
41        }
42        metaComponent_.reset(
43            new(metadata) MetaComponent, [](MetaComponent* p) { free(p); });
44
45        WriteMetadata(reinterpret_cast<uintptr_t>(metadata));
46    } else {
47        return nullptr;
48    }
49
50    return metaComponent_;
51}
52
53size_t MetadataBuilder::CalculateMetadataSize()
54{
55    baseAddr_ = 0;
56    CalculateMetaComponent(module_);
57    return baseAddr_;
58}
59
60void MetadataBuilder::CalculateMetaComponent(AST* module)
61{
62    size_t namespaceNumber = module->GetNamespaceNumber();
63    size_t sequenceableNumber = module->GetSequenceableDefNumber();
64    size_t interfaceNumber = module->GetInterfaceDefNumber();
65    size_t typeNumber = module->GetTypeNumber();
66
67    // begin address
68    baseAddr_ = ALIGN8(baseAddr_);
69    stringPool_.Add(module_->GetName());
70    // namespaces_'s address
71    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaComponent));
72    // sequenceables_'s address
73    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber);
74    // interfaces_'s address
75    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaSequenceable*) * sequenceableNumber);
76    // types_'s address
77    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface*) * interfaceNumber);
78    // stringPool_'s address
79    baseAddr_ = baseAddr_ + sizeof(MetaType*) * typeNumber;
80
81    for (size_t i = 0; i < namespaceNumber; i++) {
82        CalculateMetaNamespace(module->GetNamespace(i));
83    }
84
85    for (size_t i = 0; i < sequenceableNumber; i++) {
86        CalculateMetaSequenceable(module->GetSequenceableDef(i));
87    }
88
89    for (size_t i = 0; i < interfaceNumber; i++) {
90        CalculateMetaInterface(module->GetInterfaceDef(i));
91    }
92
93    const AST::TypeStringMap& types = module_->GetTypes();
94    for (const auto& pair : types) {
95        CalculateMetaType(pair.second);
96    }
97
98    // end address
99    CalculateStringPool();
100}
101
102void MetadataBuilder::CalculateMetaNamespace(ASTNamespace* nspace)
103{
104    size_t sequenceableNumber = nspace->GetSequenceableNumber();
105    size_t interfaceNumber = nspace->GetInterfaceNumber();
106    size_t namespaceNumber = nspace->GetNamespaceNumber();
107
108    // begin address
109    baseAddr_ = ALIGN8(baseAddr_);
110    stringPool_.Add(nspace->GetName());
111    // sequenceables_'s address
112    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace));
113    // interfaces_'s address
114    baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * sequenceableNumber);
115    // namespaces_'s address
116    baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * interfaceNumber);
117    // end address
118    baseAddr_ = baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber;
119
120    for (size_t i = 0; i < namespaceNumber; i++) {
121        CalculateMetaNamespace(nspace->GetNamespace(i));
122    }
123}
124
125void MetadataBuilder::CalculateMetaSequenceable(ASTSequenceableType* sequenceable)
126{
127    // begin address
128    baseAddr_ = ALIGN8(baseAddr_);
129    stringPool_.Add(sequenceable->GetName());
130    stringPool_.Add(sequenceable->GetNamespace()->ToString());
131    // end address
132    baseAddr_ = baseAddr_ + sizeof(MetaSequenceable);
133}
134
135void MetadataBuilder::CalculateMetaInterface(ASTInterfaceType* interface)
136{
137    size_t methodNumber = interface->GetMethodNumber();
138
139    // begin address
140    baseAddr_ = ALIGN8(baseAddr_);
141    stringPool_.Add(interface->GetLicense());
142    stringPool_.Add(interface->GetName());
143    stringPool_.Add(interface->GetNamespace()->ToString());
144    // methods_'s address
145    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface));
146    // end address
147    baseAddr_ = baseAddr_ + sizeof(MetaMethod*) * methodNumber;
148
149    for (size_t i = 0; i < methodNumber; i++) {
150        CalculateMetaMethod(interface->GetMethod(i));
151    }
152}
153
154void MetadataBuilder::CalculateMetaMethod(ASTMethod* method)
155{
156    size_t parameterNumber = method->GetParameterNumber();
157
158    // begin address
159    baseAddr_ = ALIGN8(baseAddr_);
160    stringPool_.Add(method->GetName());
161    stringPool_.Add(method->GetSignature());
162    // parameters_'s address
163    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaMethod));
164    // end address
165    baseAddr_ = baseAddr_ + sizeof(MetaParameter*) * parameterNumber;
166
167    for (size_t i = 0; i < parameterNumber; i++) {
168        CalculateMetaParameter(method->GetParameter(i));
169    }
170}
171
172void MetadataBuilder::CalculateMetaParameter(ASTParameter* parameter)
173{
174    // begin address
175    baseAddr_ = ALIGN8(baseAddr_);
176    stringPool_.Add(parameter->GetName());
177    // end address
178    baseAddr_ = baseAddr_ + sizeof(MetaParameter);
179}
180
181void MetadataBuilder::CalculateMetaType(ASTType* type)
182{
183    // begin address
184    baseAddr_ = ALIGN8(baseAddr_);
185    // nestedTypeIndexes_'s address
186    baseAddr_ = baseAddr_ + sizeof(MetaType);
187    if (type->IsListType()) {
188        baseAddr_ = ALIGN8(baseAddr_);
189        // end address
190        baseAddr_ = baseAddr_ + sizeof(int*);
191    } else if (type->IsMapType()) {
192        // end address
193        size_t typeNumber = 2;
194        baseAddr_ = baseAddr_ + sizeof(int*) * typeNumber;
195    } else if (type->IsArrayType()) {
196        baseAddr_ = baseAddr_ + sizeof(int*);
197    }
198}
199
200void MetadataBuilder::CalculateStringPool()
201{
202    // begin address
203    baseAddr_ = ALIGN8(baseAddr_);
204    // end address
205    baseAddr_ = baseAddr_ + stringPool_.GetSize();
206}
207
208void MetadataBuilder::WriteMetadata(uintptr_t base)
209{
210    baseAddr_ = base;
211    WriteMetaComponent(module_);
212}
213
214void MetadataBuilder::WriteMetaComponent(AST* module)
215{
216    size_t namespaceNumber = module->GetNamespaceNumber();
217    size_t sequenceableNumber = module->GetSequenceableDefNumber();
218    size_t interfaceNumber = module->GetInterfaceDefNumber();
219    size_t typeNumber = module->GetTypeNumber();
220
221    // begin address
222    baseAddr_ = ALIGN8(baseAddr_);
223    MetaComponent* mc = reinterpret_cast<MetaComponent*>(baseAddr_);
224    mc->magic_ = METADATA_MAGIC_NUMBER;
225    mc->size_ = static_cast<int>(size_);
226    mc->namespaceNumber_ = static_cast<int>(namespaceNumber);
227    mc->sequenceableNumber_ = static_cast<int>(sequenceableNumber);
228    mc->interfaceNumber_ = static_cast<int>(interfaceNumber);
229    mc->typeNumber_ = static_cast<int>(typeNumber);
230    mc->stringPoolSize_ = static_cast<int>(stringPool_.GetSize());
231    // namespaces_'s address
232    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaComponent));
233    mc->namespaces_ = reinterpret_cast<MetaNamespace**>(baseAddr_);
234    // sequenceables_'s address
235    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber);
236    mc->sequenceables_ = reinterpret_cast<MetaSequenceable**>(baseAddr_);
237    // interfaces_'s address
238    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaSequenceable*) * sequenceableNumber);
239    mc->interfaces_ = reinterpret_cast<MetaInterface**>(baseAddr_);
240    // types_'s address
241    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface*) * interfaceNumber);
242    mc->types_ = reinterpret_cast<MetaType**>(baseAddr_);
243    // stringPool_'s address
244    baseAddr_ = baseAddr_ + sizeof(MetaType*) * typeNumber;
245    mc->stringPool_ = reinterpret_cast<char*>(baseAddr_);
246    // end address
247    baseAddr_ = baseAddr_ + stringPool_.GetSize();
248    (void)memcpy_s(mc->stringPool_, stringPool_.GetSize(), stringPool_.GetData(), stringPool_.GetSize());
249
250    mc->name_ = WriteString(module->GetName());
251
252    for (size_t i = 0; i < namespaceNumber; i++) {
253        mc->namespaces_[i] = WriteMetaNamespace(module->GetNamespace(i));
254    }
255
256    for (size_t i = 0; i < sequenceableNumber; i++) {
257        mc->sequenceables_[i] = WriteMetaSequenceable(module->GetSequenceableDef(i));
258    }
259
260    for (size_t i = 0; i < interfaceNumber; i++) {
261        mc->interfaces_[i] = WriteMetaInterface(module->GetInterfaceDef(i));
262    }
263
264    const AST::TypeStringMap& types = module->GetTypes();
265    int i = 0;
266    for (const auto& pair : types) {
267        mc->types_[i++] = WriteMetaType(pair.second);
268    }
269}
270
271MetaNamespace* MetadataBuilder::WriteMetaNamespace(ASTNamespace* nspace)
272{
273    size_t sequenceableNumber = nspace->GetSequenceableNumber();
274    size_t interfaceNumber = nspace->GetInterfaceNumber();
275    size_t namespaceNumber = nspace->GetNamespaceNumber();
276
277    // begin address
278    baseAddr_ = ALIGN8(baseAddr_);
279    MetaNamespace* mn = reinterpret_cast<MetaNamespace*>(baseAddr_);
280    mn->name_ = WriteString(nspace->GetName());
281    mn->sequenceableNumber_ = static_cast<int>(sequenceableNumber);
282    mn->interfaceNumber_ = static_cast<int>(interfaceNumber);
283    mn->namespaceNumber_ = static_cast<int>(namespaceNumber);
284    // sequenceables_'s address
285    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace));
286    mn->sequenceableIndexes_ = reinterpret_cast<int*>(baseAddr_);
287    // interfaces_'s address
288    baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * sequenceableNumber);
289    mn->interfaceIndexes_ = reinterpret_cast<int*>(baseAddr_);
290    // namespaces_'s address
291    baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * interfaceNumber);
292    mn->namespaces_ = reinterpret_cast<MetaNamespace**>(baseAddr_);
293    // end address
294    baseAddr_ = baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber;
295
296    for (size_t i = 0; i < sequenceableNumber; i++) {
297        AutoPtr<ASTSequenceableType> sequenceable = nspace->GetSequenceable(i);
298        mn->sequenceableIndexes_[i] = module_->IndexOf(sequenceable.Get());
299    }
300
301    for (size_t i = 0; i < interfaceNumber; i++) {
302        AutoPtr<ASTInterfaceType> interface = nspace->GetInterface(i);
303        mn->interfaceIndexes_[i] = module_->IndexOf(interface.Get());
304    }
305
306    for (size_t i = 0; i < namespaceNumber; i++) {
307        AutoPtr<ASTNamespace> inner = nspace->GetNamespace(i);
308        mn->namespaces_[i] = WriteMetaNamespace(inner);
309    }
310
311    return mn;
312}
313
314MetaSequenceable* MetadataBuilder::WriteMetaSequenceable(ASTSequenceableType* parcelabe)
315{
316    // begin address
317    baseAddr_ = ALIGN8(baseAddr_);
318    MetaSequenceable* mp = reinterpret_cast<MetaSequenceable*>(baseAddr_);
319    mp->name_ = WriteString(parcelabe->GetName());
320    mp->namespace_ = WriteString(parcelabe->GetNamespace()->ToString());
321    // end address
322    baseAddr_ = baseAddr_ + sizeof(MetaSequenceable);
323
324    return mp;
325}
326
327MetaInterface* MetadataBuilder::WriteMetaInterface(ASTInterfaceType* interface)
328{
329    size_t methodNumber = interface->GetMethodNumber();
330
331    // begin address
332    baseAddr_ = ALIGN8(baseAddr_);
333    MetaInterface* mi = reinterpret_cast<MetaInterface*>(baseAddr_);
334    mi->license_ = WriteString(interface->GetLicense());
335    mi->name_ = WriteString(interface->GetName());
336    mi->namespace_ = WriteString(interface->GetNamespace()->ToString());
337    mi->properties_ = interface->GetAttribute()->GetValue() == ASTAttr::ONEWAY ? INTERFACE_PROPERTY_ONEWAY : 0;
338    mi->methodNumber_ = static_cast<int>(methodNumber);
339    mi->external_ = interface->IsExternal();
340    // methods_'s address
341    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface));
342    mi->methods_ = reinterpret_cast<MetaMethod**>(baseAddr_);
343    // end address
344    baseAddr_ = baseAddr_ + sizeof(MetaMethod*) * methodNumber;
345
346    for (size_t i = 0; i < methodNumber; i++) {
347        mi->methods_[i] = WriteMetaMethod(interface->GetMethod(i));
348    }
349
350    return mi;
351}
352
353MetaMethod* MetadataBuilder::WriteMetaMethod(ASTMethod* method)
354{
355    size_t parameterNumber = method->GetParameterNumber();
356
357    // begin address
358    baseAddr_ = ALIGN8(baseAddr_);
359    MetaMethod* mm = reinterpret_cast<MetaMethod*>(baseAddr_);
360    mm->name_ = WriteString(method->GetName());
361    mm->signature_ = WriteString(method->GetSignature());
362    mm->properties_ = method->GetAttribute()->GetValue() == ASTAttr::ONEWAY ? METHOD_PROPERTY_ONEWAY : 0;
363    mm->returnTypeIndex_ = module_->IndexOf(method->GetReturnType());
364    mm->parameterNumber_ = static_cast<int>(parameterNumber);
365    // parameters_'s address
366    baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaMethod));
367    mm->parameters_ = reinterpret_cast<MetaParameter**>(baseAddr_);
368    // end address
369    baseAddr_ = baseAddr_ + sizeof(MetaParameter*) * parameterNumber;
370
371    for (size_t i = 0; i < parameterNumber; i++) {
372        mm->parameters_[i] = WriteMetaParameter(method->GetParameter(i));
373    }
374
375    return mm;
376}
377
378MetaParameter* MetadataBuilder::WriteMetaParameter(ASTParameter* parameter)
379{
380    // begin address
381    baseAddr_ = ALIGN8(baseAddr_);
382    MetaParameter* mp = reinterpret_cast<MetaParameter*>(baseAddr_);
383    mp->name_ = WriteString(parameter->GetName());
384    if (parameter->GetAttribute() & ASTParamAttr::PARAM_IN) {
385        mp->attributes_ |= ATTR_IN;
386    }
387    if (parameter->GetAttribute() & ASTParamAttr::PARAM_OUT) {
388        mp->attributes_ |= ATTR_OUT;
389    }
390    mp->typeIndex_ = module_->IndexOf(parameter->GetType());
391    // end address
392    baseAddr_ = baseAddr_ + sizeof(MetaParameter);
393
394    return mp;
395}
396
397MetaType* MetadataBuilder::WriteMetaType(ASTType* type)
398{
399    // begin address
400    baseAddr_ = ALIGN8(baseAddr_);
401    MetaType* mt = reinterpret_cast<MetaType*>(baseAddr_);
402    mt->kind_ = Type2Kind(type);
403    if (type->IsSequenceableType()) {
404        mt->index_ = module_->IndexOf(static_cast<ASTSequenceableType*>(type));
405    } else if (type->IsInterfaceType()) {
406        mt->index_ = module_->IndexOf(static_cast<ASTInterfaceType*>(type));
407    } else {
408        mt->index_ = module_->IndexOf(type);
409    }
410    baseAddr_ = baseAddr_ + sizeof(MetaType);
411    if (type->IsListType()) {
412        mt->nestedTypeNumber_ = 1;
413        // nestedTypeIndexes_'s address
414        baseAddr_ = ALIGN8(baseAddr_);
415        mt->nestedTypeIndexes_ = reinterpret_cast<int*>(baseAddr_);
416        AutoPtr<ASTType> elementType = (static_cast<ASTListType*>(type))->GetElementType();
417        mt->nestedTypeIndexes_[0] = module_->IndexOf(elementType);
418        // end address
419        baseAddr_ = baseAddr_ + sizeof(int*);
420    } else if (type->IsMapType()) {
421        size_t typeNumber = 2;
422        mt->nestedTypeNumber_ = static_cast<int>(typeNumber);
423        // nestedTypeIndexes_'s address
424        baseAddr_ = ALIGN8(baseAddr_);
425        mt->nestedTypeIndexes_ = reinterpret_cast<int*>(baseAddr_);
426        AutoPtr<ASTType> keyType = (static_cast<ASTMapType*>(type))->GetKeyType();
427        AutoPtr<ASTType> valueType = (static_cast<ASTMapType*>(type))->GetValueType();
428        mt->nestedTypeIndexes_[0] = module_->IndexOf(keyType);
429        mt->nestedTypeIndexes_[1] = module_->IndexOf(valueType);
430        // end address
431        baseAddr_ = baseAddr_ + sizeof(int*) * typeNumber;
432    } else if (type->IsArrayType()) {
433        mt->nestedTypeNumber_ = 1;
434        // nestedTypeIndexes_'s address
435        baseAddr_ = ALIGN8(baseAddr_);
436        mt->nestedTypeIndexes_ = reinterpret_cast<int*>(baseAddr_);
437        AutoPtr<ASTType> elementType = (static_cast<ASTArrayType*>(type))->GetElementType();
438        mt->nestedTypeIndexes_[0] = module_->IndexOf(elementType);
439        // end address
440        baseAddr_ = baseAddr_ + sizeof(int*);
441    }
442
443    return mt;
444}
445
446char* MetadataBuilder::WriteString(const std::string& string)
447{
448    return string.empty() ? nullptr : metaComponent_->stringPool_ + stringPool_.GetOffset(string);
449}
450
451MetaTypeKind MetadataBuilder::Type2Kind(ASTType* type)
452{
453    if (type->IsCharType()) {
454        return MetaTypeKind::Char;
455    } else if (type->IsBooleanType()) {
456        return MetaTypeKind::Boolean;
457    } else if (type->IsByteType()) {
458        return MetaTypeKind::Byte;
459    } else if (type->IsShortType()) {
460        return MetaTypeKind::Short;
461    } else if (type->IsIntegerType()) {
462        return MetaTypeKind::Integer;
463    } else if (type->IsLongType()) {
464        return MetaTypeKind::Long;
465    } else if (type->IsFloatType()) {
466        return MetaTypeKind::Float;
467    } else if (type->IsDoubleType()) {
468        return MetaTypeKind::Double;
469    } else if (type->IsStringType()) {
470        return MetaTypeKind::String;
471    } else if (type->IsVoidType()) {
472        return MetaTypeKind::Void;
473    } else if (type->IsSequenceableType()) {
474        return MetaTypeKind::Sequenceable;
475    } else if (type->IsInterfaceType()) {
476        return MetaTypeKind::Interface;
477    } else if (type->IsListType()) {
478        return MetaTypeKind::List;
479    } else if (type->IsMapType()) {
480        return MetaTypeKind::Map;
481    } else if (type->IsArrayType()) {
482        return MetaTypeKind::Array;
483    }
484    return MetaTypeKind::Unknown;
485}
486} // namespace Idl
487} // namespace OHOS
488