• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 LIBPANDAFILE_CLASS_DATA_ACCESSOR_INL_H
17 #define 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 
SkipRuntimeTypeAnnotations()57 inline void ClassDataAccessor::SkipRuntimeTypeAnnotations()
58 {
59     EnumerateRuntimeTypeAnnotations([](File::EntityId /* unused */) {});
60 }
61 
SkipTypeAnnotations()62 inline void ClassDataAccessor::SkipTypeAnnotations()
63 {
64     EnumerateTypeAnnotations([](File::EntityId /* unused */) {});
65 }
66 
67 template <class Callback>
EnumerateInterfaces(const Callback & cb)68 inline void ClassDataAccessor::EnumerateInterfaces(const Callback &cb)
69 {
70     auto sp = ifaces_offsets_sp_;
71 
72     for (size_t i = 0; i < num_ifaces_; i++) {
73         auto index = helpers::Read<IDX_SIZE>(&sp);
74         cb(panda_file_.ResolveClassIndex(class_id_, index));
75     }
76 }
77 
GetInterfaceId(size_t idx)78 inline File::EntityId ClassDataAccessor::GetInterfaceId(size_t idx) const
79 {
80     ASSERT(idx < num_ifaces_);
81     auto sp = ifaces_offsets_sp_.SubSpan(idx * IDX_SIZE);
82     auto index = helpers::Read<IDX_SIZE>(&sp);
83     return panda_file_.ResolveClassIndex(class_id_, index);
84 }
85 
GetSourceLang()86 inline std::optional<SourceLang> ClassDataAccessor::GetSourceLang()
87 {
88     return helpers::GetOptionalTaggedValue<SourceLang>(source_lang_sp_, ClassTag::SOURCE_LANG,
89                                                        &runtime_annotations_sp_);
90 }
91 
92 template <class Callback>
EnumerateRuntimeAnnotations(const Callback & cb)93 inline void ClassDataAccessor::EnumerateRuntimeAnnotations(const Callback &cb)
94 {
95     if (runtime_annotations_sp_.data() == nullptr) {
96         SkipSourceLang();
97     }
98 
99     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(
100         runtime_annotations_sp_, ClassTag::RUNTIME_ANNOTATION, cb, &annotations_sp_);
101 }
102 
103 template <class Callback>
EnumerateAnnotations(const Callback & cb)104 inline void ClassDataAccessor::EnumerateAnnotations(const Callback &cb)
105 {
106     if (annotations_sp_.data() == nullptr) {
107         SkipRuntimeAnnotations();
108     }
109 
110     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(annotations_sp_, ClassTag::ANNOTATION, cb,
111                                                                        &runtime_type_annotation_sp_);
112 }
113 
114 template <class Callback>
EnumerateRuntimeAnnotationsWithEarlyStop(const Callback & cb)115 inline bool ClassDataAccessor::EnumerateRuntimeAnnotationsWithEarlyStop(const Callback &cb)
116 {
117     if (runtime_annotations_sp_.data() == nullptr) {
118         SkipSourceLang();
119     }
120 
121     return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, ClassTag, Callback>(
122         runtime_annotations_sp_, ClassTag::RUNTIME_ANNOTATION, cb);
123 }
124 
125 template <class Callback>
EnumerateAnnotationsWithEarlyStop(const Callback & cb)126 inline bool ClassDataAccessor::EnumerateAnnotationsWithEarlyStop(const Callback &cb)
127 {
128     if (annotations_sp_.data() == nullptr) {
129         SkipRuntimeAnnotations();
130     }
131 
132     return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, ClassTag, Callback>(annotations_sp_,
133                                                                                            ClassTag::ANNOTATION, cb);
134 }
135 
GetSourceFileId()136 inline std::optional<File::EntityId> ClassDataAccessor::GetSourceFileId()
137 {
138     if (source_file_sp_.data() == nullptr) {
139         SkipTypeAnnotations();
140     }
141 
142     auto v = helpers::GetOptionalTaggedValue<File::EntityId>(source_file_sp_, ClassTag::SOURCE_FILE, &fields_sp_);
143 
144     fields_sp_ = fields_sp_.SubSpan(TAG_SIZE);  // NOTHING tag
145 
146     return v;
147 }
148 
149 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)150 static void EnumerateClassElements(const File &pf, Span<const uint8_t> sp, size_t elem_num, const Callback &cb,
151                                    Span<const uint8_t> *next)
152 {
153     for (size_t i = 0; i < elem_num; i++) {
154         File::EntityId id = pf.GetIdFromPointer(sp.data());
155         Accessor data_accessor(pf, id);
156         cb(data_accessor);
157         sp = sp.SubSpan(data_accessor.GetSize());
158     }
159 
160     *next = sp;
161 }
162 
163 template <class Callback>
EnumerateFields(const Callback & cb)164 inline void ClassDataAccessor::EnumerateFields(const Callback &cb)
165 {
166     if (fields_sp_.data() == nullptr) {
167         SkipSourceFile();
168     }
169 
170     EnumerateClassElements<Callback, FieldDataAccessor>(panda_file_, fields_sp_, num_fields_, cb, &methods_sp_);
171 }
172 
173 template <class Callback>
EnumerateMethods(const Callback & cb)174 inline void ClassDataAccessor::EnumerateMethods(const Callback &cb)
175 {
176     if (methods_sp_.data() == nullptr) {
177         SkipFields();
178     }
179 
180     Span<const uint8_t> sp {nullptr, nullptr};
181 
182     EnumerateClassElements<Callback, MethodDataAccessor>(panda_file_, methods_sp_, num_methods_, cb, &sp);
183 
184     size_ = panda_file_.GetIdFromPointer(sp.data()).GetOffset() - class_id_.GetOffset();
185 }
186 
187 template <class Callback>
EnumerateRuntimeTypeAnnotations(const Callback & cb)188 inline void ClassDataAccessor::EnumerateRuntimeTypeAnnotations(const Callback &cb)
189 {
190     if (runtime_type_annotation_sp_.data() == nullptr) {
191         SkipAnnotations();
192     }
193 
194     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(
195         runtime_type_annotation_sp_, ClassTag::RUNTIME_TYPE_ANNOTATION, cb, &type_annotation_sp_);
196 }
197 
198 template <class Callback>
EnumerateTypeAnnotations(const Callback & cb)199 inline void ClassDataAccessor::EnumerateTypeAnnotations(const Callback &cb)
200 {
201     if (type_annotation_sp_.data() == nullptr) {
202         SkipRuntimeTypeAnnotations();
203     }
204 
205     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(type_annotation_sp_, ClassTag::TYPE_ANNOTATION,
206                                                                        cb, &source_file_sp_);
207 }
208 
GetAnnotationsNumber()209 inline uint32_t ClassDataAccessor::GetAnnotationsNumber()
210 {
211     size_t n = 0;
212     EnumerateAnnotations([&n](File::EntityId /* unused */) { n++; });
213     return n;
214 }
215 
GetRuntimeAnnotationsNumber()216 inline uint32_t ClassDataAccessor::GetRuntimeAnnotationsNumber()
217 {
218     size_t n = 0;
219     EnumerateRuntimeAnnotations([&n](File::EntityId /* unused */) { n++; });
220     return n;
221 }
222 
223 }  // namespace panda::panda_file
224 
225 #endif  // LIBPANDAFILE_CLASS_DATA_ACCESSOR_INL_H
226