* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIBPANDAFILE_FIELD_DATA_ACCESSOR_INL_H
#define LIBPANDAFILE_FIELD_DATA_ACCESSOR_INL_H
#include "field_data_accessor.h"
#include "helpers.h"
#include "utils/bit_utils.h"
#include <type_traits>
namespace panda::panda_file {
inline File::EntityId FieldDataAccessor::GetTypeId(const File &panda_file, File::EntityId field_id)
{
auto sp = panda_file.GetSpanFromId(field_id).SubSpan(IDX_SIZE);
auto type_idx = helpers::Read<panda_file::IDX_SIZE>(&sp);
return panda_file.ResolveClassIndex(field_id, type_idx);
}
inline File::EntityId FieldDataAccessor::GetNameId(const File &panda_file, File::EntityId field_id)
{
auto sp = panda_file.GetSpanFromId(field_id).SubSpan(IDX_SIZE * 2);
return File::EntityId(helpers::Read<panda_file::ID_SIZE>(&sp));
}
template <class T>
inline std::optional<T> FieldDataAccessor::GetValue()
{
if (is_external_) {
std::optional<T> novalue = {};
return novalue;
}
auto v = GetValueInternal();
if (!v.has_value()) {
std::optional<T> novalue = {};
return novalue;
}
FieldValue field_value = *v;
if constexpr (std::is_integral_v<T>) {
if constexpr (sizeof(T) <= sizeof(uint32_t)) {
return static_cast<T>(std::get<uint32_t>(field_value));
} else {
return static_cast<T>(std::get<uint64_t>(field_value));
}
} else {
if constexpr (sizeof(T) <= sizeof(uint32_t)) {
return bit_cast<T, uint32_t>(std::get<uint32_t>(field_value));
} else {
return bit_cast<T, uint64_t>(std::get<uint64_t>(field_value));
}
}
}
template <>
inline std::optional<File::EntityId> FieldDataAccessor::GetValue()
{
if (is_external_) {
return {};
}
auto v = GetValueInternal();
if (!v.has_value()) {
return {};
}
FieldValue field_value = *v;
return File::EntityId(std::get<uint32_t>(field_value));
}
inline void FieldDataAccessor::SkipValue()
{
GetValueInternal();
}
inline void FieldDataAccessor::SkipRuntimeAnnotations()
{
EnumerateRuntimeAnnotations([](File::EntityId ) {});
}
inline void FieldDataAccessor::SkipAnnotations()
{
EnumerateAnnotations([](File::EntityId ) {});
}
inline void FieldDataAccessor::SkipRuntimeTypeAnnotations()
{
EnumerateRuntimeTypeAnnotations([](File::EntityId ) {});
}
inline void FieldDataAccessor::SkipTypeAnnotations()
{
EnumerateTypeAnnotations([](File::EntityId ) {});
}
template <class Callback>
inline void FieldDataAccessor::EnumerateRuntimeAnnotations(const Callback &cb)
{
if (is_external_) {
return;
}
if (runtime_annotations_sp_.data() == nullptr) {
SkipValue();
}
helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(
runtime_annotations_sp_, FieldTag::RUNTIME_ANNOTATION, cb, &annotations_sp_);
}
template <class Callback>
inline void FieldDataAccessor::EnumerateAnnotations(const Callback &cb)
{
if (is_external_) {
return;
}
if (annotations_sp_.data() == nullptr) {
SkipRuntimeAnnotations();
}
helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(annotations_sp_, FieldTag::ANNOTATION, cb,
&runtime_type_annotations_sp_);
}
template <class Callback>
inline void FieldDataAccessor::EnumerateRuntimeTypeAnnotations(const Callback &cb)
{
if (is_external_) {
return;
}
if (runtime_type_annotations_sp_.data() == nullptr) {
SkipAnnotations();
}
helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(runtime_type_annotations_sp_,
FieldTag::ANNOTATION, cb, &type_annotations_sp_);
}
template <class Callback>
inline void FieldDataAccessor::EnumerateTypeAnnotations(const Callback &cb)
{
if (is_external_) {
return;
}
if (type_annotations_sp_.data() == nullptr) {
SkipRuntimeTypeAnnotations();
}
Span<const uint8_t> sp {nullptr, nullptr};
helpers::EnumerateTaggedValues<File::EntityId, FieldTag, Callback>(type_annotations_sp_, FieldTag::ANNOTATION, cb,
&sp);
size_ = panda_file_.GetIdFromPointer(sp.data()).GetOffset() - field_id_.GetOffset() + 1;
}
template <class Callback>
inline bool FieldDataAccessor::EnumerateRuntimeAnnotationsWithEarlyStop(const Callback &cb)
{
if (is_external_) {
return false;
}
if (runtime_annotations_sp_.data() == nullptr) {
SkipValue();
}
return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, FieldTag, Callback>(
runtime_annotations_sp_, FieldTag::RUNTIME_ANNOTATION, cb);
}
template <class Callback>
inline bool FieldDataAccessor::EnumerateAnnotationsWithEarlyStop(const Callback &cb)
{
if (is_external_) {
return false;
}
if (annotations_sp_.data() == nullptr) {
SkipRuntimeAnnotations();
}
return helpers::EnumerateTaggedValuesWithEarlyStop<File::EntityId, FieldTag, Callback>(annotations_sp_,
FieldTag::ANNOTATION, cb);
}
inline uint32_t FieldDataAccessor::GetAnnotationsNumber()
{
size_t n = 0;
EnumerateRuntimeAnnotations([&n](File::EntityId ) { n++; });
return n;
}
inline uint32_t FieldDataAccessor::GetRuntimeAnnotationsNumber()
{
size_t n = 0;
EnumerateRuntimeAnnotations([&n](File::EntityId ) { n++; });
return n;
}
inline uint32_t FieldDataAccessor::GetRuntimeTypeAnnotationsNumber()
{
size_t n = 0;
EnumerateRuntimeTypeAnnotations([&n](File::EntityId ) { n++; });
return n;
}
inline uint32_t FieldDataAccessor::GetTypeAnnotationsNumber()
{
size_t n = 0;
EnumerateTypeAnnotations([&n](File::EntityId ) { n++; });
return n;
}
}
#endif