• 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_FIELD_DATA_ACCESSOR_INL_H
17 #define LIBPANDAFILE_FIELD_DATA_ACCESSOR_INL_H
18 
19 #include "field_data_accessor.h"
20 #include "helpers.h"
21 
22 #include "utils/bit_utils.h"
23 
24 #include <type_traits>
25 
26 namespace panda::panda_file {
27 
28 // static
GetTypeId(const File & panda_file,File::EntityId field_id)29 inline File::EntityId FieldDataAccessor::GetTypeId(const File &panda_file, File::EntityId field_id)
30 {
31     auto sp = panda_file.GetSpanFromId(field_id).SubSpan(IDX_SIZE);  // skip class_idx
32     auto type_idx = helpers::Read<panda_file::IDX_SIZE>(&sp);
33     return panda_file.ResolveClassIndex(field_id, type_idx);
34 }
35 
36 // static
GetNameId(const File & panda_file,File::EntityId field_id)37 inline File::EntityId FieldDataAccessor::GetNameId(const File &panda_file, File::EntityId field_id)
38 {
39     auto sp = panda_file.GetSpanFromId(field_id).SubSpan(IDX_SIZE * 2);  // skip class_idx, type_idx
40     return File::EntityId(helpers::Read<panda_file::ID_SIZE>(&sp));
41 }
42 
43 template <class T>
GetValue()44 inline std::optional<T> FieldDataAccessor::GetValue()
45 {
46     if (is_external_) {
47         // NB! This is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635
48         // which fails Release builds for GCC 8 and 9.
49         std::optional<T> novalue = {};
50         return novalue;
51     }
52 
53     auto v = GetValueInternal();
54 
55     if (!v.has_value()) {
56         // NB! This is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635
57         // which fails Release builds for GCC 8 and 9.
58         std::optional<T> novalue = {};
59         return novalue;
60     }
61 
62     FieldValue field_value = *v;
63 
64     // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
65     // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
66     if constexpr (std::is_integral_v<T>) {
67         // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
68         if constexpr (sizeof(T) <= sizeof(uint32_t)) {
69             return static_cast<T>(std::get<uint32_t>(field_value));
70             // NOLINTNEXTLINE(readability-misleading-indentation)
71         } else {
72             return static_cast<T>(std::get<uint64_t>(field_value));
73         }
74         // NOLINTNEXTLINE(readability-misleading-indentation)
75     } else {
76         // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
77         if constexpr (sizeof(T) <= sizeof(uint32_t)) {
78             return bit_cast<T, uint32_t>(std::get<uint32_t>(field_value));
79             // NOLINTNEXTLINE(readability-misleading-indentation)
80         } else {
81             return bit_cast<T, uint64_t>(std::get<uint64_t>(field_value));
82         }
83     }
84 }
85 
86 template <>
GetValue()87 inline std::optional<File::EntityId> FieldDataAccessor::GetValue()
88 {
89     if (is_external_) {
90         return {};
91     }
92 
93     auto v = GetValueInternal();
94 
95     if (!v.has_value()) {
96         return {};
97     }
98 
99     FieldValue field_value = *v;
100 
101     return File::EntityId(std::get<uint32_t>(field_value));
102 }
103 
SkipValue()104 inline void FieldDataAccessor::SkipValue()
105 {
106     GetValueInternal();
107 }
108 
SkipRuntimeAnnotations()109 inline void FieldDataAccessor::SkipRuntimeAnnotations()
110 {
111     EnumerateRuntimeAnnotations([](File::EntityId /* unused */) {});
112 }
113 
SkipAnnotations()114 inline void FieldDataAccessor::SkipAnnotations()
115 {
116     EnumerateAnnotations([](File::EntityId /* unused */) {});
117 }
118 
SkipRuntimeTypeAnnotations()119 inline void FieldDataAccessor::SkipRuntimeTypeAnnotations()
120 {
121     EnumerateRuntimeTypeAnnotations([](File::EntityId /* unused */) {});
122 }
123 
SkipTypeAnnotations()124 inline void FieldDataAccessor::SkipTypeAnnotations()
125 {
126     EnumerateTypeAnnotations([](File::EntityId /* unused */) {});
127 }
128 
129 template <class Callback>
EnumerateRuntimeAnnotations(const Callback & cb)130 inline void FieldDataAccessor::EnumerateRuntimeAnnotations(const Callback &cb)
131 {
132     if (is_external_) {
133         return;
134     }
135 
136     if (runtime_annotations_sp_.data() == nullptr) {
137         SkipValue();
138     }
139 
140     helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(
141         runtime_annotations_sp_, FieldTag::RUNTIME_ANNOTATION, cb, &annotations_sp_);
142 }
143 
144 template <class Callback>
EnumerateAnnotations(const Callback & cb)145 inline void FieldDataAccessor::EnumerateAnnotations(const Callback &cb)
146 {
147     if (is_external_) {
148         return;
149     }
150 
151     if (annotations_sp_.data() == nullptr) {
152         SkipRuntimeAnnotations();
153     }
154 
155     helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(annotations_sp_, FieldTag::ANNOTATION, cb,
156                                                                        &runtime_type_annotations_sp_);
157 }
158 
159 template <class Callback>
EnumerateRuntimeTypeAnnotations(const Callback & cb)160 inline void FieldDataAccessor::EnumerateRuntimeTypeAnnotations(const Callback &cb)
161 {
162     if (is_external_) {
163         return;
164     }
165 
166     if (runtime_type_annotations_sp_.data() == nullptr) {
167         SkipAnnotations();
168     }
169 
170     helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(runtime_type_annotations_sp_,
171                                                                        FieldTag::ANNOTATION, cb, &type_annotations_sp_);
172 }
173 
174 template <class Callback>
EnumerateTypeAnnotations(const Callback & cb)175 inline void FieldDataAccessor::EnumerateTypeAnnotations(const Callback &cb)
176 {
177     if (is_external_) {
178         return;
179     }
180 
181     if (type_annotations_sp_.data() == nullptr) {
182         SkipRuntimeTypeAnnotations();
183     }
184 
185     Span<const uint8_t> sp {nullptr, nullptr};
186     helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(type_annotations_sp_, FieldTag::ANNOTATION, cb,
187                                                                        &sp);
188 
189     size_ = panda_file_.GetIdFromPointer(sp.data()).GetOffset() - field_id_.GetOffset() + 1;  // + 1 for NOTHING tag
190 }
191 
192 template <class Callback>
EnumerateRuntimeAnnotationsWithEarlyStop(const Callback & cb)193 inline bool FieldDataAccessor::EnumerateRuntimeAnnotationsWithEarlyStop(const Callback &cb)
194 {
195     if (is_external_) {
196         return false;
197     }
198 
199     if (runtime_annotations_sp_.data() == nullptr) {
200         SkipValue();
201     }
202 
203     return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, FieldTag, Callback>(
204         runtime_annotations_sp_, FieldTag::RUNTIME_ANNOTATION, cb);
205 }
206 
207 template <class Callback>
EnumerateAnnotationsWithEarlyStop(const Callback & cb)208 inline bool FieldDataAccessor::EnumerateAnnotationsWithEarlyStop(const Callback &cb)
209 {
210     if (is_external_) {
211         return false;
212     }
213 
214     if (annotations_sp_.data() == nullptr) {
215         SkipRuntimeAnnotations();
216     }
217 
218     return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, FieldTag, Callback>(annotations_sp_,
219                                                                                            FieldTag::ANNOTATION, cb);
220 }
221 
GetAnnotationsNumber()222 inline uint32_t FieldDataAccessor::GetAnnotationsNumber()
223 {
224     size_t n = 0;
225     EnumerateRuntimeAnnotations([&n](File::EntityId /* unused */) { n++; });
226     return n;
227 }
228 
GetRuntimeAnnotationsNumber()229 inline uint32_t FieldDataAccessor::GetRuntimeAnnotationsNumber()
230 {
231     size_t n = 0;
232     EnumerateRuntimeAnnotations([&n](File::EntityId /* unused */) { n++; });
233     return n;
234 }
235 
GetRuntimeTypeAnnotationsNumber()236 inline uint32_t FieldDataAccessor::GetRuntimeTypeAnnotationsNumber()
237 {
238     size_t n = 0;
239     EnumerateRuntimeTypeAnnotations([&n](File::EntityId /* unused */) { n++; });
240     return n;
241 }
242 
GetTypeAnnotationsNumber()243 inline uint32_t FieldDataAccessor::GetTypeAnnotationsNumber()
244 {
245     size_t n = 0;
246     EnumerateTypeAnnotations([&n](File::EntityId /* unused */) { n++; });
247     return n;
248 }
249 
250 }  // namespace panda::panda_file
251 
252 #endif  // LIBPANDAFILE_FIELD_DATA_ACCESSOR_INL_H
253