• 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>
EnumerateTypes(const Callback & c)37 inline 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)72 inline 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()112 inline uint32_t ProtoDataAccessor::GetNumElements()
113 {
114     if (refTypesSp_.data() == nullptr) {
115         SkipShorty();
116     }
117 
118     return elemNum_;
119 }
120 
GetNumArgs()121 inline uint32_t ProtoDataAccessor::GetNumArgs()
122 {
123     return GetNumElements() - 1;
124 }
125 
GetReferenceType(size_t i)126 inline 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)137 inline 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()150 inline Type ProtoDataAccessor::GetReturnType() const
151 {
152     return GetType(0);
153 }
154 
GetArgType(size_t idx)155 inline 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