• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #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 #include "annotation_data_accessor.h"
23 
24 #include "helpers.h"
25 
26 namespace ark::panda_file {
27 
SkipSourceLang()28 inline void ClassDataAccessor::SkipSourceLang()
29 {
30     GetSourceLang();
31 }
32 
SkipRuntimeAnnotations()33 inline void ClassDataAccessor::SkipRuntimeAnnotations()
34 {
35     EnumerateRuntimeAnnotations([](File::EntityId /* unused */) {});
36 }
37 
SkipAnnotations()38 inline void ClassDataAccessor::SkipAnnotations()
39 {
40     EnumerateAnnotations([](File::EntityId /* unused */) {});
41 }
42 
SkipSourceFile()43 inline void ClassDataAccessor::SkipSourceFile()
44 {
45     GetSourceFileId();
46 }
47 
SkipFields()48 inline void ClassDataAccessor::SkipFields()
49 {
50     EnumerateFields([](const FieldDataAccessor & /* unused */) {});
51 }
52 
SkipMethods()53 inline void ClassDataAccessor::SkipMethods()
54 {
55     EnumerateMethods([](const MethodDataAccessor & /* unused */) {});
56 }
57 
SkipRuntimeTypeAnnotations()58 inline void ClassDataAccessor::SkipRuntimeTypeAnnotations()
59 {
60     EnumerateRuntimeTypeAnnotations([](File::EntityId /* unused */) {});
61 }
62 
SkipTypeAnnotations()63 inline void ClassDataAccessor::SkipTypeAnnotations()
64 {
65     EnumerateTypeAnnotations([](File::EntityId /* unused */) {});
66 }
67 
68 template <class Callback>
EnumerateInterfaces(const Callback & cb)69 inline void ClassDataAccessor::EnumerateInterfaces(const Callback &cb)
70 {
71     auto sp = ifacesOffsetsSp_;
72 
73     for (size_t i = 0; i < numIfaces_; i++) {
74         auto index = helpers::Read<IDX_SIZE>(&sp);
75         cb(pandaFile_.ResolveClassIndex(classId_, index));
76     }
77 }
78 
GetInterfaceId(size_t idx)79 inline File::EntityId ClassDataAccessor::GetInterfaceId(size_t idx) const
80 {
81     ASSERT(idx < numIfaces_);
82     auto sp = ifacesOffsetsSp_.SubSpan(idx * IDX_SIZE);
83     auto index = helpers::Read<IDX_SIZE>(&sp);
84     return pandaFile_.ResolveClassIndex(classId_, index);
85 }
86 
GetSourceLang()87 inline std::optional<SourceLang> ClassDataAccessor::GetSourceLang()
88 {
89     return helpers::GetOptionalTaggedValue<SourceLang>(sourceLangSp_, ClassTag::SOURCE_LANG, &runtimeAnnotationsSp_);
90 }
91 
92 template <class Callback>
EnumerateRuntimeAnnotations(const Callback & cb)93 inline void ClassDataAccessor::EnumerateRuntimeAnnotations(const Callback &cb)
94 {
95     if (runtimeAnnotationsSp_.data() == nullptr) {
96         SkipSourceLang();
97     }
98 
99     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(
100         runtimeAnnotationsSp_, ClassTag::RUNTIME_ANNOTATION, cb, &annotationsSp_);
101 }
102 
103 template <class Callback>
EnumerateAnnotations(const Callback & cb)104 inline void ClassDataAccessor::EnumerateAnnotations(const Callback &cb)
105 {
106     if (annotationsSp_.data() == nullptr) {
107         SkipRuntimeAnnotations();
108     }
109 
110     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(annotationsSp_, ClassTag::ANNOTATION, cb,
111                                                                        &runtimeTypeAnnotationSp_);
112 }
113 
114 template <class Callback>
EnumerateRuntimeAnnotationsWithEarlyStop(const Callback & cb)115 inline bool ClassDataAccessor::EnumerateRuntimeAnnotationsWithEarlyStop(const Callback &cb)
116 {
117     if (runtimeAnnotationsSp_.data() == nullptr) {
118         SkipSourceLang();
119     }
120 
121     return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, ClassTag, Callback>(
122         runtimeAnnotationsSp_, 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 (annotationsSp_.data() == nullptr) {
129         SkipRuntimeAnnotations();
130     }
131 
132     return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, ClassTag, Callback>(annotationsSp_,
133                                                                                            ClassTag::ANNOTATION, cb);
134 }
135 
136 template <class Callback>
EnumerateAnnotation(const char * name,const Callback & cb)137 auto ClassDataAccessor::EnumerateAnnotation(const char *name, const Callback &cb)
138 {
139     std::optional<std::invoke_result_t<const Callback &, panda_file::AnnotationDataAccessor &>> result {};
140     EnumerateAnnotationsWithEarlyStop([&cb, &pf = pandaFile_, name, &result](panda_file::File::EntityId annotationId) {
141         panda_file::AnnotationDataAccessor ada(pf, annotationId);
142         auto *annotationName = pf.GetStringData(ada.GetClassId()).data;
143         if (utf::IsEqual(utf::CStringAsMutf8(name), annotationName)) {
144             result = cb(ada);
145             return true;
146         }
147         return false;
148     });
149     return result;
150 }
151 
GetSourceFileId()152 inline std::optional<File::EntityId> ClassDataAccessor::GetSourceFileId()
153 {
154     if (sourceFileSp_.data() == nullptr) {
155         SkipTypeAnnotations();
156     }
157 
158     auto v = helpers::GetOptionalTaggedValue<File::EntityId>(sourceFileSp_, ClassTag::SOURCE_FILE, &fieldsSp_);
159 
160     fieldsSp_ = fieldsSp_.SubSpan(TAG_SIZE);  // NOTHING tag
161 
162     return v;
163 }
164 
165 template <class Callback, class Accessor>
EnumerateClassElements(const File & pf,Span<const uint8_t> sp,size_t elemNum,const Callback & cb,Span<const uint8_t> * next)166 inline void ClassDataAccessor::EnumerateClassElements(const File &pf, Span<const uint8_t> sp, size_t elemNum,
167                                                       const Callback &cb, Span<const uint8_t> *next)
168 {
169     for (size_t i = 0; i < elemNum; i++) {
170         File::EntityId id = pf.GetIdFromPointer(sp.data());
171         Accessor dataAccessor(pf, id);
172         cb(dataAccessor);
173         sp = sp.SubSpan(dataAccessor.GetSize());
174     }
175 
176     *next = sp;
177 }
178 
179 template <class Callback>
EnumerateFields(const Callback & cb)180 inline void ClassDataAccessor::EnumerateFields(const Callback &cb)
181 {
182     if (fieldsSp_.data() == nullptr) {
183         SkipSourceFile();
184     }
185 
186     EnumerateClassElements<Callback, FieldDataAccessor>(pandaFile_, fieldsSp_, numFields_, cb, &methodsSp_);
187 }
188 
189 template <class Callback>
EnumerateMethods(const Callback & cb)190 inline void ClassDataAccessor::EnumerateMethods(const Callback &cb)
191 {
192     if (methodsSp_.data() == nullptr) {
193         SkipFields();
194     }
195 
196     Span<const uint8_t> sp {nullptr, nullptr};
197 
198     EnumerateClassElements<Callback, MethodDataAccessor>(pandaFile_, methodsSp_, numMethods_, cb, &sp);
199 
200     size_ = pandaFile_.GetIdFromPointer(sp.data()).GetOffset() - classId_.GetOffset();
201 }
202 
203 template <class Callback>
EnumerateRuntimeTypeAnnotations(const Callback & cb)204 inline void ClassDataAccessor::EnumerateRuntimeTypeAnnotations(const Callback &cb)
205 {
206     if (runtimeTypeAnnotationSp_.data() == nullptr) {
207         SkipAnnotations();
208     }
209 
210     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(
211         runtimeTypeAnnotationSp_, ClassTag::RUNTIME_TYPE_ANNOTATION, cb, &typeAnnotationSp_);
212 }
213 
214 template <class Callback>
EnumerateTypeAnnotations(const Callback & cb)215 inline void ClassDataAccessor::EnumerateTypeAnnotations(const Callback &cb)
216 {
217     if (typeAnnotationSp_.data() == nullptr) {
218         SkipRuntimeTypeAnnotations();
219     }
220 
221     helpers::EnumerateTaggedValues<File::EntityId, ClassTag, Callback>(typeAnnotationSp_, ClassTag::TYPE_ANNOTATION, cb,
222                                                                        &sourceFileSp_);
223 }
224 
GetAnnotationsNumber()225 inline uint32_t ClassDataAccessor::GetAnnotationsNumber()
226 {
227     size_t n = 0;
228     EnumerateAnnotations([&n](File::EntityId /* unused */) { n++; });
229     return n;
230 }
231 
GetRuntimeAnnotationsNumber()232 inline uint32_t ClassDataAccessor::GetRuntimeAnnotationsNumber()
233 {
234     size_t n = 0;
235     EnumerateRuntimeAnnotations([&n](File::EntityId /* unused */) { n++; });
236     return n;
237 }
238 
239 }  // namespace ark::panda_file
240 
241 #endif  // LIBPANDAFILE_CLASS_DATA_ACCESSOR_INL_H_
242