1 /*
2 * Copyright (c) 2021 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 #ifndef PANDA_LIBPANDAFILE_CLASS_DATA_ACCESSOR_INL_H_
17 #define PANDA_LIBPANDAFILE_CLASS_DATA_ACCESSOR_INL_H_
18
19 #include "class_data_accessor.h"
20 #include "field_data_accessor-inl.h"
21 #include "method_data_accessor-inl.h"
22
23 #include "helpers.h"
24
25 namespace panda::panda_file {
26
SkipSourceLang()27 inline void ClassDataAccessor::SkipSourceLang()
28 {
29 GetSourceLang();
30 }
31
SkipRuntimeAnnotations()32 inline void ClassDataAccessor::SkipRuntimeAnnotations()
33 {
34 EnumerateRuntimeAnnotations([](File::EntityId /* unused */) {});
35 }
36
SkipAnnotations()37 inline void ClassDataAccessor::SkipAnnotations()
38 {
39 EnumerateAnnotations([](File::EntityId /* unused */) {});
40 }
41
SkipSourceFile()42 inline void ClassDataAccessor::SkipSourceFile()
43 {
44 GetSourceFileId();
45 }
46
SkipFields()47 inline void ClassDataAccessor::SkipFields()
48 {
49 EnumerateFields([](const FieldDataAccessor & /* unused */) {});
50 }
51
SkipMethods()52 inline void ClassDataAccessor::SkipMethods()
53 {
54 EnumerateMethods([](const MethodDataAccessor & /* unused */) {});
55 }
56
57 template <class Callback>
EnumerateInterfaces(const Callback & cb)58 inline void ClassDataAccessor::EnumerateInterfaces(const Callback &cb)
59 {
60 auto sp = ifaces_offsets_sp_;
61
62 for (size_t i = 0; i < num_ifaces_; i++) {
63 auto index = helpers::Read<IDX_SIZE>(&sp);
64 cb(panda_file_.ResolveClassIndex(class_id_, index));
65 }
66 }
67
GetInterfaceId(size_t idx)68 inline File::EntityId ClassDataAccessor::GetInterfaceId(size_t idx) const
69 {
70 ASSERT(idx < num_ifaces_);
71 auto sp = ifaces_offsets_sp_.SubSpan(idx * IDX_SIZE);
72 auto index = helpers::Read<IDX_SIZE>(&sp);
73 return panda_file_.ResolveClassIndex(class_id_, index);
74 }
75
GetSourceLang()76 inline std::optional<SourceLang> ClassDataAccessor::GetSourceLang()
77 {
78 return helpers::GetOptionalTaggedValue<SourceLang>(source_lang_sp_, ClassTag::SOURCE_LANG,
79 &runtime_annotations_sp_);
80 }
81
82 template <class Callback>
EnumerateRuntimeAnnotations(const Callback & cb)83 inline void ClassDataAccessor::EnumerateRuntimeAnnotations(const Callback &cb)
84 {
85 if (runtime_annotations_sp_.data() == nullptr) {
86 SkipSourceLang();
87 }
88
89 helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(
90 runtime_annotations_sp_, ClassTag::RUNTIME_ANNOTATION, cb, &annotations_sp_);
91 }
92
93 template <class Callback>
EnumerateAnnotations(const Callback & cb)94 inline void ClassDataAccessor::EnumerateAnnotations(const Callback &cb)
95 {
96 if (annotations_sp_.data() == nullptr) {
97 SkipRuntimeAnnotations();
98 }
99
100 helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(annotations_sp_, ClassTag::ANNOTATION, cb,
101 &source_file_sp_);
102 }
103
GetSourceFileId()104 inline std::optional<File::EntityId> ClassDataAccessor::GetSourceFileId()
105 {
106 if (source_file_sp_.data() == nullptr) {
107 SkipAnnotations();
108 }
109
110 auto v = helpers::GetOptionalTaggedValue<File::EntityId>(source_file_sp_, ClassTag::SOURCE_FILE, &fields_sp_);
111
112 fields_sp_ = fields_sp_.SubSpan(TAG_SIZE); // NOTHING tag
113
114 return v;
115 }
116
117 template <class Callback, class Accessor>
EnumerateClassElements(const File & pf,Span<const uint8_t> sp,size_t elem_num,const Callback & cb,Span<const uint8_t> * next)118 static void EnumerateClassElements(const File &pf, Span<const uint8_t> sp, size_t elem_num, const Callback &cb,
119 Span<const uint8_t> *next)
120 {
121 for (size_t i = 0; i < elem_num; i++) {
122 File::EntityId id = pf.GetIdFromPointer(sp.data());
123 Accessor data_accessor(pf, id);
124 cb(data_accessor);
125 sp = sp.SubSpan(data_accessor.GetSize());
126 }
127
128 *next = sp;
129 }
130
131 template <class Callback>
EnumerateFields(const Callback & cb)132 inline void ClassDataAccessor::EnumerateFields(const Callback &cb)
133 {
134 if (fields_sp_.data() == nullptr) {
135 SkipSourceFile();
136 }
137
138 EnumerateClassElements<Callback, FieldDataAccessor>(panda_file_, fields_sp_, num_fields_, cb, &methods_sp_);
139 }
140
141 template <class Callback>
EnumerateMethods(const Callback & cb)142 inline void ClassDataAccessor::EnumerateMethods(const Callback &cb)
143 {
144 if (methods_sp_.data() == nullptr) {
145 SkipFields();
146 }
147
148 Span<const uint8_t> sp {nullptr, nullptr};
149 EnumerateClassElements<Callback, MethodDataAccessor>(panda_file_, methods_sp_, num_methods_, cb, &sp);
150
151 size_ = panda_file_.GetIdFromPointer(sp.data()).GetOffset() - class_id_.GetOffset();
152 }
153
GetAnnotationsNumber()154 inline uint32_t ClassDataAccessor::GetAnnotationsNumber()
155 {
156 size_t n = 0;
157 EnumerateAnnotations([&n](File::EntityId /* unused */) { n++; });
158 return n;
159 }
160
GetRuntimeAnnotationsNumber()161 inline uint32_t ClassDataAccessor::GetRuntimeAnnotationsNumber()
162 {
163 size_t n = 0;
164 EnumerateRuntimeAnnotations([&n](File::EntityId /* unused */) { n++; });
165 return n;
166 }
167
168 } // namespace panda::panda_file
169
170 #endif // PANDA_LIBPANDAFILE_CLASS_DATA_ACCESSOR_INL_H_
171