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_PROTO_DATA_ACCESSOR_INL_H_ 17 #define 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 ark::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 = pandaFile_.GetSpanFromId(protoId_); 40 41 uint32_t v = helpers::Read<SHORTY_ELEM_SIZE>(&sp); 42 uint32_t numRef = 0; 43 size_ = SHORTY_ELEM_SIZE; 44 while (v != 0) { 45 size_t shift = (elemNum_ % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; 46 uint8_t elem = (v >> shift) & SHORTY_ELEM_MASK; 47 48 if (elem == 0) { 49 break; 50 } 51 52 Type t(static_cast<Type::TypeId>(elem)); 53 c(t); 54 55 if (!t.IsPrimitive()) { 56 ++numRef; 57 } 58 59 ++elemNum_; 60 61 if ((elemNum_ % SHORTY_ELEM_PER16) == 0) { 62 v = helpers::Read<SHORTY_ELEM_SIZE>(&sp); 63 size_ += SHORTY_ELEM_SIZE; 64 } 65 } 66 67 size_ += numRef * IDX_SIZE; 68 refTypesNum_ = numRef; 69 refTypesSp_ = sp; 70 } 71 IsEqual(ProtoDataAccessor * other)72inline bool ProtoDataAccessor::IsEqual(ProtoDataAccessor *other) 73 { 74 size_t refNum = 0; 75 size_t shortyIdx = 0; 76 auto sp1 = pandaFile_.GetSpanFromId(protoId_); 77 auto sp2 = other->pandaFile_.GetSpanFromId(other->protoId_); 78 auto v1 = helpers::Read<SHORTY_ELEM_SIZE>(&sp1); 79 auto v2 = helpers::Read<SHORTY_ELEM_SIZE>(&sp2); 80 while (true) { 81 size_t shift = (shortyIdx % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; 82 uint8_t s1 = (v1 >> shift) & SHORTY_ELEM_MASK; // NOLINT(hicpp-signed-bitwise) 83 uint8_t s2 = (v2 >> shift) & SHORTY_ELEM_MASK; // NOLINT(hicpp-signed-bitwise) 84 if (s1 != s2) { 85 return false; 86 } 87 if (s1 == 0) { 88 break; 89 } 90 panda_file::Type t(static_cast<panda_file::Type::TypeId>(s1)); 91 if (!t.IsPrimitive()) { 92 ++refNum; 93 } 94 if ((++shortyIdx % SHORTY_ELEM_PER16) == 0) { 95 v1 = helpers::Read<SHORTY_ELEM_SIZE>(&sp1); 96 v2 = helpers::Read<SHORTY_ELEM_SIZE>(&sp2); 97 } 98 } 99 100 // compare ref types 101 for (size_t refIdx = 0; refIdx < refNum; ++refIdx) { 102 auto id1 = pandaFile_.ResolveClassIndex(protoId_, helpers::Read<IDX_SIZE>(&sp1)); 103 auto id2 = other->pandaFile_.ResolveClassIndex(other->protoId_, helpers::Read<IDX_SIZE>(&sp2)); 104 if (pandaFile_.GetStringData(id1) != other->pandaFile_.GetStringData(id2)) { 105 return false; 106 } 107 } 108 109 return true; 110 } 111 GetNumElements()112inline uint32_t ProtoDataAccessor::GetNumElements() 113 { 114 if (refTypesSp_.data() == nullptr) { 115 SkipShorty(); 116 } 117 118 return elemNum_; 119 } 120 GetNumArgs()121inline uint32_t ProtoDataAccessor::GetNumArgs() 122 { 123 return GetNumElements() - 1; 124 } 125 GetReferenceType(size_t i)126inline File::EntityId ProtoDataAccessor::GetReferenceType(size_t i) 127 { 128 if (refTypesSp_.data() == nullptr) { 129 SkipShorty(); 130 } 131 132 auto sp = refTypesSp_.SubSpan(i * IDX_SIZE); 133 auto classIdx = helpers::Read<IDX_SIZE>(&sp); 134 return pandaFile_.ResolveClassIndex(protoId_, classIdx); 135 } 136 GetType(size_t idx)137inline Type ProtoDataAccessor::GetType(size_t idx) const 138 { 139 size_t blockIdx = idx / SHORTY_ELEM_PER16; 140 size_t elemShift = (idx % SHORTY_ELEM_PER16) * SHORTY_ELEM_WIDTH; 141 142 auto sp = pandaFile_.GetSpanFromId(protoId_); 143 144 sp = sp.SubSpan(SHORTY_ELEM_SIZE * blockIdx); 145 146 uint32_t v = helpers::Read<SHORTY_ELEM_SIZE>(&sp); 147 return Type(static_cast<Type::TypeId>((v >> elemShift) & SHORTY_ELEM_MASK)); 148 } 149 GetReturnType()150inline Type ProtoDataAccessor::GetReturnType() const 151 { 152 return GetType(0); 153 } 154 GetArgType(size_t idx)155inline Type ProtoDataAccessor::GetArgType(size_t idx) const 156 { 157 return GetType(idx + 1); 158 } 159 160 } // namespace ark::panda_file 161 162 #endif // LIBPANDAFILE_PROTO_DATA_ACCESSOR_INL_H_ 163