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