/** * 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_PROTO_DATA_ACCESSOR_INL_H_ #define LIBPANDAFILE_PROTO_DATA_ACCESSOR_INL_H_ #include "helpers.h" #include "file_items.h" #include "proto_data_accessor.h" namespace panda::panda_file { constexpr size_t SHORTY_ELEM_SIZE = sizeof(uint16_t); constexpr size_t SHORTY_ELEM_WIDTH = 4; constexpr size_t SHORTY_ELEM_MASK = 0xf; constexpr size_t SHORTY_ELEM_PER16 = std::numeric_limits::digits / SHORTY_ELEM_WIDTH; inline void ProtoDataAccessor::SkipShorty() { EnumerateTypes([](Type /* unused */) {}); } template inline void ProtoDataAccessor::EnumerateTypes(const Callback &c) { auto sp = panda_file_.GetSpanFromId(proto_id_); uint32_t v = helpers::Read(&sp); uint32_t num_ref = 0; size_ = SHORTY_ELEM_SIZE; while (v != 0) { size_t shift = (elem_num_ % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; uint8_t elem = (v >> shift) & SHORTY_ELEM_MASK; if (elem == 0) { break; } Type t(static_cast(elem)); c(t); if (!t.IsPrimitive()) { ++num_ref; } ++elem_num_; if ((elem_num_ % SHORTY_ELEM_PER16) == 0) { v = helpers::Read(&sp); size_ += SHORTY_ELEM_SIZE; } } size_ += num_ref * IDX_SIZE; ref_types_num_ = num_ref; ref_types_sp_ = sp; } inline bool ProtoDataAccessor::IsEqual(ProtoDataAccessor *other) { size_t ref_num = 0; size_t shorty_idx = 0; auto sp1 = panda_file_.GetSpanFromId(proto_id_); auto sp2 = other->panda_file_.GetSpanFromId(other->proto_id_); auto v1 = helpers::Read(&sp1); auto v2 = helpers::Read(&sp2); while (true) { size_t shift = (shorty_idx % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; uint8_t s1 = (v1 >> shift) & SHORTY_ELEM_MASK; // NOLINT(hicpp-signed-bitwise) uint8_t s2 = (v2 >> shift) & SHORTY_ELEM_MASK; // NOLINT(hicpp-signed-bitwise) if (s1 != s2) { return false; } if (s1 == 0) { break; } panda_file::Type t(static_cast(s1)); if (!t.IsPrimitive()) { ++ref_num; } if ((++shorty_idx % SHORTY_ELEM_PER16) == 0) { v1 = helpers::Read(&sp1); v2 = helpers::Read(&sp2); } } // compare ref types for (size_t ref_idx = 0; ref_idx < ref_num; ++ref_idx) { auto id1 = panda_file_.ResolveClassIndex(proto_id_, helpers::Read(&sp1)); auto id2 = other->panda_file_.ResolveClassIndex(other->proto_id_, helpers::Read(&sp2)); if (panda_file_.GetStringData(id1) != other->panda_file_.GetStringData(id2)) { return false; } } return true; } inline uint32_t ProtoDataAccessor::GetNumArgs() { if (ref_types_sp_.data() == nullptr) { SkipShorty(); } return elem_num_ - 1; } inline File::EntityId ProtoDataAccessor::GetReferenceType(size_t i) { if (ref_types_sp_.data() == nullptr) { SkipShorty(); } auto sp = ref_types_sp_.SubSpan(i * IDX_SIZE); auto class_idx = helpers::Read(&sp); return panda_file_.ResolveClassIndex(proto_id_, class_idx); } inline Type ProtoDataAccessor::GetType(size_t idx) const { size_t block_idx = idx / SHORTY_ELEM_PER16; size_t elem_shift = (idx % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; auto sp = panda_file_.GetSpanFromId(proto_id_); sp = sp.SubSpan(SHORTY_ELEM_SIZE * block_idx); uint32_t v = helpers::Read(&sp); return Type(static_cast((v >> elem_shift) & SHORTY_ELEM_MASK)); } inline Type ProtoDataAccessor::GetReturnType() const { return GetType(0); } inline Type ProtoDataAccessor::GetArgType(size_t idx) const { return GetType(idx + 1); } } // namespace panda::panda_file #endif // LIBPANDAFILE_PROTO_DATA_ACCESSOR_INL_H_