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