binarytree.cpp

main 216 lines · 5.3 KB Raw
Alex Alex Commit Client Upload Part 2 19/10/2026 00:06
1/*
2 * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "binarytree.h"
24#include "filestream.h"
25
26BinaryTree::BinaryTree(const FileStreamPtr& fin)
27 : m_fin(fin), m_pos(0xFFFFFFFF) {
28 m_startPos = fin->tell();
29}
30
31BinaryTree::~BinaryTree() {}
32
33void BinaryTree::skipNodes() {
34 while (true) {
35 uint8 byte = m_fin->getU8();
36 switch (byte) {
37 case BINARYTREE_NODE_START: {
38 skipNodes();
39 break;
40 }
41 case BINARYTREE_NODE_END:
42 return;
43 case BINARYTREE_ESCAPE_CHAR:
44 m_fin->getU8();
45 break;
46 default:
47 break;
48 }
49 }
50}
51
52void BinaryTree::unserialize() {
53 if (m_pos != 0xFFFFFFFF) return;
54 m_pos = 0;
55
56 m_fin->seek(m_startPos);
57 while (true) {
58 uint8 byte = m_fin->getU8();
59 switch (byte) {
60 case BINARYTREE_NODE_START: {
61 skipNodes();
62 break;
63 }
64 case BINARYTREE_NODE_END:
65 return;
66 case BINARYTREE_ESCAPE_CHAR:
67 m_buffer.add(m_fin->getU8());
68 break;
69 default:
70 m_buffer.add(byte);
71 break;
72 }
73 }
74}
75
76BinaryTreeVec BinaryTree::getChildren() {
77 BinaryTreeVec children;
78 m_fin->seek(m_startPos);
79 while (true) {
80 uint8 byte = m_fin->getU8();
81 switch (byte) {
82 case BINARYTREE_NODE_START: {
83 BinaryTreePtr node(new BinaryTree(m_fin));
84 children.push_back(node);
85 node->skipNodes();
86 break;
87 }
88 case BINARYTREE_NODE_END:
89 return children;
90 case BINARYTREE_ESCAPE_CHAR:
91 m_fin->getU8();
92 break;
93 default:
94 break;
95 }
96 }
97}
98
99void BinaryTree::seek(uint pos) {
100 unserialize();
101 if (pos > m_buffer.size()) stdext::throw_exception("BinaryTree: seek failed");
102 m_pos = pos;
103}
104
105void BinaryTree::skip(uint len) {
106 unserialize();
107 seek(tell() + len);
108}
109
110uint8 BinaryTree::getU8() {
111 unserialize();
112 if (m_pos + 1 > m_buffer.size())
113 stdext::throw_exception("BinaryTree: getU8 failed");
114 uint8 v = m_buffer[m_pos];
115 m_pos += 1;
116 return v;
117}
118
119uint16 BinaryTree::getU16() {
120 unserialize();
121 if (m_pos + 2 > m_buffer.size())
122 stdext::throw_exception("BinaryTree: getU16 failed");
123 uint16 v = stdext::readULE16(&m_buffer[m_pos]);
124 m_pos += 2;
125 return v;
126}
127
128uint32 BinaryTree::getU32() {
129 unserialize();
130 if (m_pos + 4 > m_buffer.size())
131 stdext::throw_exception("BinaryTree: getU32 failed");
132 uint32 v = stdext::readULE32(&m_buffer[m_pos]);
133 m_pos += 4;
134 return v;
135}
136
137uint64 BinaryTree::getU64() {
138 unserialize();
139 if (m_pos + 8 > m_buffer.size())
140 stdext::throw_exception("BinaryTree: getU64 failed");
141 uint64 v = stdext::readULE64(&m_buffer[m_pos]);
142 m_pos += 8;
143 return v;
144}
145
146std::string BinaryTree::getString(uint16 len) {
147 unserialize();
148 if (len == 0) len = getU16();
149
150 if (m_pos + len > m_buffer.size())
151 stdext::throw_exception(
152 "BinaryTree: getString failed: string length exceeded buffer size.");
153
154 std::string ret((char*)&m_buffer[m_pos], len);
155 m_pos += len;
156 return ret;
157}
158
159Point BinaryTree::getPoint() {
160 Point ret;
161 ret.x = getU8();
162 ret.y = getU8();
163 return ret;
164}
165
166OutputBinaryTree::OutputBinaryTree(const FileStreamPtr& fin) : m_fin(fin) {
167 startNode(0);
168}
169
170void OutputBinaryTree::addU8(uint8 v) { write(&v, 1); }
171
172void OutputBinaryTree::addU16(uint16 v) {
173 uint8 data[2];
174 stdext::writeULE16(data, v);
175 write(data, 2);
176}
177
178void OutputBinaryTree::addU32(uint32 v) {
179 uint8 data[4];
180 stdext::writeULE32(data, v);
181 write(data, 4);
182}
183
184void OutputBinaryTree::addString(const std::string& v) {
185 if (v.size() > 0xFFFF) stdext::throw_exception("too long string");
186
187 addU16(v.length());
188 write((const uint8*)v.c_str(), v.length());
189}
190
191void OutputBinaryTree::addPos(uint16 x, uint16 y, uint8 z) {
192 addU16(x);
193 addU16(y);
194 addU8(z);
195}
196
197void OutputBinaryTree::addPoint(const Point& point) {
198 addU8(point.x);
199 addU8(point.y);
200}
201
202void OutputBinaryTree::startNode(uint8 node) {
203 m_fin->addU8(BINARYTREE_NODE_START);
204 write(&node, 1);
205}
206
207void OutputBinaryTree::endNode() { m_fin->addU8(BINARYTREE_NODE_END); }
208
209void OutputBinaryTree::write(const uint8* data, size_t size) {
210 for (size_t i = 0; i < size; ++i) {
211 if (data[i] == BINARYTREE_NODE_START || data[i] == BINARYTREE_NODE_END ||
212 data[i] == BINARYTREE_ESCAPE_CHAR)
213 m_fin->addU8(BINARYTREE_ESCAPE_CHAR);
214 m_fin->addU8(data[i]);
215 }
216}
Top