1#include "Library/Yaml/ByamlData.h"
2
3#include <byteswap.h>
4
5namespace al {
6
7ByamlData::ByamlData() = default;
8
9void ByamlData::set(const ByamlHashPair* hash_pair, bool isRev) {
10 mType = hash_pair->getType();
11 mValue = hash_pair->getValue(isRev);
12}
13
14void ByamlData::set(u8 type, u32 value, bool isRev) {
15 mType = (ByamlDataType)type;
16 mValue = isRev ? bswap_32(value) : value;
17}
18
19ByamlDataType ByamlData::getType() const {
20 return mType;
21}
22
23u32 ByamlData::getValue() const {
24 return mValue;
25}
26
27s32 ByamlHashPair::getKey(bool isRev) const {
28 return isRev ? bswap_24(mData) : mData & 0xFFFFFF;
29}
30
31ByamlDataType ByamlHashPair::getType() const {
32 return (ByamlDataType)(mData >> 24);
33}
34
35s32 ByamlHashPair::getValue(bool isRev) const {
36 return isRev ? bswap_32(mValue) : mValue;
37}
38
39ByamlHashIter::ByamlHashIter(const u8* data, bool isRev_) : mData(data), mIsRev(isRev_) {}
40
41ByamlHashIter::ByamlHashIter() : mData(nullptr), mIsRev(false) {}
42
43const ByamlHashPair* ByamlHashIter::findPair(s32 key) const {
44 const ByamlHashPair* pairTable = getPairTable();
45 if (!mData)
46 return nullptr;
47
48 s32 lowerBound = 0;
49 s32 upperBound = getSize();
50 asm(""); // solves isRev leaking over between getSize() and getKey()
51 while (lowerBound < upperBound) {
52 s32 avg = (lowerBound + upperBound) / 2;
53 const ByamlHashPair* pair = &pairTable[avg];
54 s32 result = key - pair->getKey(isRev: mIsRev);
55 if (result == 0)
56 return pair;
57
58 if (result > 0)
59 lowerBound = avg + 1;
60 else
61 upperBound = avg;
62 }
63 return nullptr;
64}
65
66bool ByamlHashIter::getDataByIndex(ByamlData* data, s32 index) const {
67 if (!mData)
68 return false;
69 if (((s32)getSize()) < 1)
70 return false;
71
72 data->set(hash_pair: &getPairTable()[index], isRev: mIsRev);
73 return true;
74}
75
76// NON_MATCHING: minor additional instructions, probably not inlined
77bool ByamlHashIter::getDataByKey(ByamlData* data, s32 key) const {
78 if (!mData)
79 return false;
80 if (((s32)getSize()) < 1)
81 return false;
82
83 // probably inlined from findPair()
84 const ByamlHashPair* pairTable = getPairTable();
85 if (!mData)
86 return false;
87 s32 lowerBound = 0;
88 s32 upperBound = getSize();
89 const ByamlHashPair* pair;
90
91 if (lowerBound >= upperBound)
92 return false;
93 while (true) {
94 s32 avg = (lowerBound + upperBound) / 2;
95 pair = &pairTable[avg];
96 s32 result = key - pair->getKey(isRev: mIsRev);
97 if (result == 0)
98 break;
99
100 if (result > 0)
101 lowerBound = avg + 1;
102 else
103 upperBound = avg;
104 if (lowerBound >= upperBound)
105 return false;
106 }
107 if (pair == nullptr)
108 return false;
109 data->set(hash_pair: pair, isRev: mIsRev);
110 return true;
111}
112
113const u8* ByamlHashIter::getOffsetData(u32 off) const {
114 return &mData[off];
115}
116
117const ByamlHashPair* ByamlHashIter::getPairByIndex(s32 index) const {
118 if (index < 0)
119 return nullptr;
120 if (((s32)getSize()) <= index)
121 return nullptr;
122
123 return &getPairTable()[index];
124}
125
126const ByamlHashPair* ByamlHashIter::getPairTable() const {
127 if (!mData)
128 return nullptr;
129 return reinterpret_cast<const ByamlHashPair*>(mData + 4);
130}
131
132u32 ByamlHashIter::getSize() const {
133 if (!mData)
134 return 0;
135 u32 val = *reinterpret_cast<const u32*>(mData);
136 return mIsRev ? bswap_24(val >> 8) : val >> 8;
137}
138
139ByamlArrayIter::ByamlArrayIter(const u8* data, bool isRev_) : mData(data), mIsRev(isRev_) {}
140
141ByamlArrayIter::ByamlArrayIter() : mData(nullptr), mIsRev(false) {}
142
143bool ByamlArrayIter::getDataByIndex(ByamlData* data, s32 index) const {
144 if (index < 0)
145 return false;
146 if (((s32)getSize()) <= index)
147 return false;
148
149 data->set(type: getTypeTable()[index], value: getDataTable()[index], isRev: mIsRev);
150 return true;
151}
152
153// NON_MATCHING: regalloc
154const u32* ByamlArrayIter::getDataTable() const {
155 return reinterpret_cast<const u32*>(getOffsetData(off: (getSize() + 7) & 0xFFFFFFFC));
156}
157
158const u8* ByamlArrayIter::getOffsetData(u32 off) const {
159 return &mData[off];
160}
161
162u32 ByamlArrayIter::getSize() const {
163 u32 val = *reinterpret_cast<const u32*>(mData);
164 return mIsRev ? bswap_24(val >> 8) : val >> 8;
165}
166
167const u8* ByamlArrayIter::getTypeTable() const {
168 return mData + 4;
169}
170} // namespace al
171