1 /* 2 * Copyright (c) 2021 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 PANDA_LIBPANDAFILE_PROTO_DATA_ACCESSOR_INL_H_ 17 #define PANDA_LIBPANDAFILE_PROTO_DATA_ACCESSOR_INL_H_ 18 19 #include "helpers.h" 20 21 #include "file_items.h" 22 #include "proto_data_accessor.h" 23 24 namespace panda::panda_file { 25 26 constexpr size_t SHORTY_ELEM_SIZE = sizeof(uint16_t); 27 constexpr size_t SHORTY_ELEM_WIDTH = 4; 28 constexpr size_t SHORTY_ELEM_MASK = 0xf; 29 constexpr size_t SHORTY_ELEM_PER16 = std::numeric_limits<uint16_t>::digits / SHORTY_ELEM_WIDTH; 30 SkipShorty()31inline void ProtoDataAccessor::SkipShorty() 32 { 33 EnumerateTypes([](Type /* unused */) {}); 34 } 35 36 template <class Callback> EnumerateTypes(const Callback & c)37inline void ProtoDataAccessor::EnumerateTypes(const Callback &c) 38 { 39 auto sp = panda_file_.GetSpanFromId(proto_id_); 40 41 uint32_t v = helpers::Read<SHORTY_ELEM_SIZE>(&sp); 42 uint32_t num_ref = 0; 43 size_ = SHORTY_ELEM_SIZE; 44 while (v != 0) { 45 size_t shift = (elem_num_ % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; 46 uint8_t elem = (v >> shift) & SHORTY_ELEM_MASK; 47 if (elem == 0) { 48 break; 49 } 50 51 Type t(static_cast<Type::TypeId>(elem)); 52 c(t); 53 if (!t.IsPrimitive()) { 54 ++num_ref; 55 } 56 57 ++elem_num_; 58 59 if ((elem_num_ % SHORTY_ELEM_PER16) == 0) { 60 v = helpers::Read<SHORTY_ELEM_SIZE>(&sp); 61 size_ += SHORTY_ELEM_SIZE; 62 } 63 } 64 65 size_ += num_ref * IDX_SIZE; 66 67 ref_types_sp_ = sp; 68 } 69 GetNumArgs()70inline uint32_t ProtoDataAccessor::GetNumArgs() 71 { 72 if (ref_types_sp_.data() == nullptr) { 73 SkipShorty(); 74 } 75 76 return elem_num_ - 1; 77 } 78 GetReferenceType(size_t i)79inline File::EntityId ProtoDataAccessor::GetReferenceType(size_t i) 80 { 81 if (ref_types_sp_.data() == nullptr) { 82 SkipShorty(); 83 } 84 85 auto sp = ref_types_sp_.SubSpan(i * IDX_SIZE); 86 auto class_idx = helpers::Read<IDX_SIZE>(&sp); 87 return panda_file_.ResolveClassIndex(proto_id_, class_idx); 88 } 89 GetType(size_t idx)90inline Type ProtoDataAccessor::GetType(size_t idx) const 91 { 92 size_t block_idx = idx / SHORTY_ELEM_PER16; 93 size_t elem_shift = (idx % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; 94 95 auto sp = panda_file_.GetSpanFromId(proto_id_); 96 sp = sp.SubSpan(SHORTY_ELEM_SIZE * block_idx); 97 98 uint32_t v = helpers::Read<SHORTY_ELEM_SIZE>(&sp); 99 return Type(static_cast<Type::TypeId>((v >> elem_shift) & SHORTY_ELEM_MASK)); 100 } 101 GetReturnType()102inline Type ProtoDataAccessor::GetReturnType() const 103 { 104 return GetType(0); 105 } 106 GetArgType(size_t idx)107inline Type ProtoDataAccessor::GetArgType(size_t idx) const 108 { 109 return GetType(idx + 1); 110 } 111 112 } // namespace panda::panda_file 113 114 #endif // PANDA_LIBPANDAFILE_PROTO_DATA_ACCESSOR_INL_H_ 115