• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()31 inline 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)38 inline 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)74 inline 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()114 inline uint32_t ProtoDataAccessor::GetNumElements()
115 {
116     if (refTypesSp_.data() == nullptr) {
117         SkipShorty();
118     }
119 
120     return elemNum_;
121 }
122 
GetNumArgs()123 inline uint32_t ProtoDataAccessor::GetNumArgs()
124 {
125     return GetNumElements() - 1;
126 }
127 
GetReferenceType(size_t i)128 inline 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)139 inline 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()152 inline Type ProtoDataAccessor::GetReturnType() const
153 {
154     return GetType(0);
155 }
156 
GetArgType(size_t idx)157 inline 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