mirror of
https://github.com/edubart/otclient.git
synced 2025-10-17 13:03:27 +02:00
Optimize overall memory usage
* Fixes in otbm loader * Rework BinaryTree
This commit is contained in:
@@ -23,21 +23,54 @@
|
||||
#include "binarytree.h"
|
||||
#include "filestream.h"
|
||||
|
||||
void BinaryTree::unserialize(const FileStreamPtr& fin)
|
||||
BinaryTree::BinaryTree(const FileStreamPtr& fin) :
|
||||
m_fin(fin), m_pos(0xFFFFFFFF)
|
||||
{
|
||||
m_startPos = fin->tell();
|
||||
}
|
||||
|
||||
BinaryTree::~BinaryTree()
|
||||
{
|
||||
}
|
||||
|
||||
void BinaryTree::skipNodes()
|
||||
{
|
||||
while(true) {
|
||||
uint8 byte = fin->getU8();
|
||||
uint8 byte = m_fin->getU8();
|
||||
switch(byte) {
|
||||
case BINARYTREE_NODE_START: {
|
||||
BinaryTreePtr node(new BinaryTree(shared_from_this()));
|
||||
m_children.push_back(node);
|
||||
node->unserialize(fin);
|
||||
skipNodes();
|
||||
break;
|
||||
}
|
||||
case BINARYTREE_NODE_END:
|
||||
return;
|
||||
case BINARYTREE_ESCAPE_CHAR:
|
||||
m_buffer.add(fin->getU8());
|
||||
m_fin->getU8();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryTree::unserialize()
|
||||
{
|
||||
if(m_pos != 0xFFFFFFFF)
|
||||
return;
|
||||
m_pos = 0;
|
||||
|
||||
m_fin->seek(m_startPos);
|
||||
while(true) {
|
||||
uint8 byte = m_fin->getU8();
|
||||
switch(byte) {
|
||||
case BINARYTREE_NODE_START: {
|
||||
skipNodes();
|
||||
break;
|
||||
}
|
||||
case BINARYTREE_NODE_END:
|
||||
return;
|
||||
case BINARYTREE_ESCAPE_CHAR:
|
||||
m_buffer.add(m_fin->getU8());
|
||||
break;
|
||||
default:
|
||||
m_buffer.add(byte);
|
||||
@@ -46,13 +79,33 @@ void BinaryTree::unserialize(const FileStreamPtr& fin)
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryTree::serialize(const FileStreamPtr& fin)
|
||||
BinaryTreeVec BinaryTree::getChildren()
|
||||
{
|
||||
|
||||
BinaryTreeVec children;
|
||||
m_fin->seek(m_startPos);
|
||||
while(true) {
|
||||
uint8 byte = m_fin->getU8();
|
||||
switch(byte) {
|
||||
case BINARYTREE_NODE_START: {
|
||||
BinaryTreePtr node(new BinaryTree(m_fin));
|
||||
children.push_back(node);
|
||||
node->skipNodes();
|
||||
break;
|
||||
}
|
||||
case BINARYTREE_NODE_END:
|
||||
return children;
|
||||
case BINARYTREE_ESCAPE_CHAR:
|
||||
m_fin->getU8();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryTree::seek(uint pos)
|
||||
{
|
||||
unserialize();
|
||||
if(pos > m_buffer.size())
|
||||
stdext::throw_exception("BinaryTree: seek failed");
|
||||
m_pos = pos;
|
||||
@@ -60,6 +113,7 @@ void BinaryTree::seek(uint pos)
|
||||
|
||||
uint8 BinaryTree::getU8()
|
||||
{
|
||||
unserialize();
|
||||
if(m_pos+1 > m_buffer.size())
|
||||
stdext::throw_exception("BinaryTree: getU8 failed");
|
||||
uint8 v = m_buffer[m_pos];
|
||||
@@ -69,6 +123,7 @@ uint8 BinaryTree::getU8()
|
||||
|
||||
uint16 BinaryTree::getU16()
|
||||
{
|
||||
unserialize();
|
||||
if(m_pos+2 > m_buffer.size())
|
||||
stdext::throw_exception("BinaryTree: getU16 failed");
|
||||
uint16 v = stdext::readLE16(&m_buffer[m_pos]);
|
||||
@@ -78,6 +133,7 @@ uint16 BinaryTree::getU16()
|
||||
|
||||
uint32 BinaryTree::getU32()
|
||||
{
|
||||
unserialize();
|
||||
if(m_pos+4 > m_buffer.size())
|
||||
stdext::throw_exception("BinaryTree: getU32 failed");
|
||||
uint32 v = stdext::readLE32(&m_buffer[m_pos]);
|
||||
@@ -87,6 +143,7 @@ uint32 BinaryTree::getU32()
|
||||
|
||||
uint64 BinaryTree::getU64()
|
||||
{
|
||||
unserialize();
|
||||
if(m_pos+8 > m_buffer.size())
|
||||
stdext::throw_exception("BinaryTree: getU64 failed");
|
||||
uint64 v = stdext::readLE64(&m_buffer[m_pos]);
|
||||
@@ -96,10 +153,8 @@ uint64 BinaryTree::getU64()
|
||||
|
||||
std::string BinaryTree::getString()
|
||||
{
|
||||
unserialize();
|
||||
uint16 len = getU16();
|
||||
if(len == 0 || len > 8192)
|
||||
stdext::throw_exception("BinaryTree: getString failed: invalid or too large string length");
|
||||
|
||||
if(m_pos+len > m_buffer.size())
|
||||
stdext::throw_exception("BinaryTree: getString failed: string length exceeded buffer size.");
|
||||
|
||||
|
@@ -32,18 +32,16 @@ enum {
|
||||
BINARYTREE_NODE_END = 0xFF
|
||||
};
|
||||
|
||||
class BinaryTree : public std::enable_shared_from_this<BinaryTree>
|
||||
class BinaryTree
|
||||
{
|
||||
public:
|
||||
BinaryTree(const BinaryTreePtr& parent = nullptr) : m_pos(0), m_parent(parent) { }
|
||||
|
||||
void unserialize(const FileStreamPtr& fin);
|
||||
void serialize(const FileStreamPtr& fin);
|
||||
BinaryTree(const FileStreamPtr& fin);
|
||||
~BinaryTree();
|
||||
|
||||
void seek(uint pos);
|
||||
void skip(uint len) { seek(tell() + len); }
|
||||
uint tell() { return m_pos; }
|
||||
uint size() { return m_buffer.size(); }
|
||||
uint size() { unserialize(); return m_buffer.size(); }
|
||||
|
||||
uint8 getU8();
|
||||
uint16 getU16();
|
||||
@@ -51,16 +49,17 @@ public:
|
||||
uint64 getU64();
|
||||
std::string getString();
|
||||
|
||||
BinaryTreeVec getChildren() { return m_children; }
|
||||
BinaryTreePtr getParent() { return m_parent.lock(); }
|
||||
bool canRead() { return m_pos < m_buffer.size(); }
|
||||
BinaryTreeVec getChildren();
|
||||
bool canRead() { unserialize(); return m_pos < m_buffer.size(); }
|
||||
|
||||
private:
|
||||
uint m_pos;
|
||||
void unserialize();
|
||||
void skipNodes();
|
||||
|
||||
BinaryTreeVec m_children;
|
||||
BinaryTreeWeakPtr m_parent;
|
||||
FileStreamPtr m_fin;
|
||||
DataBuffer<uint8> m_buffer;
|
||||
uint m_pos;
|
||||
uint m_startPos;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -143,7 +143,7 @@ void FileStream::skip(uint len)
|
||||
seek(tell() + len);
|
||||
}
|
||||
|
||||
int FileStream::size()
|
||||
uint FileStream::size()
|
||||
{
|
||||
if(!m_caching)
|
||||
return PHYSFS_fileLength(m_fileHandle);
|
||||
@@ -151,7 +151,7 @@ int FileStream::size()
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
int FileStream::tell()
|
||||
uint FileStream::tell()
|
||||
{
|
||||
if(!m_caching)
|
||||
return PHYSFS_tell(m_fileHandle);
|
||||
@@ -249,13 +249,11 @@ std::string FileStream::getString()
|
||||
|
||||
BinaryTreePtr FileStream::getBinaryTree()
|
||||
{
|
||||
BinaryTreePtr root = BinaryTreePtr(new BinaryTree);
|
||||
uint8 byte = getU8();
|
||||
if(byte == BINARYTREE_NODE_START)
|
||||
root->unserialize(asFileStream());
|
||||
else
|
||||
if(byte != BINARYTREE_NODE_START)
|
||||
stdext::throw_exception(stdext::format("failed to read node start (getBinaryTree): %d", byte));
|
||||
return root;
|
||||
|
||||
return BinaryTreePtr(new BinaryTree(asFileStream()));
|
||||
}
|
||||
|
||||
void FileStream::addU8(uint8 v)
|
||||
|
@@ -43,8 +43,8 @@ public:
|
||||
int read(void *buffer, uint size, uint nmemb = 1);
|
||||
void seek(uint pos);
|
||||
void skip(uint len);
|
||||
int size();
|
||||
int tell();
|
||||
uint size();
|
||||
uint tell();
|
||||
std::string name() { return m_name; }
|
||||
|
||||
uint8 getU8();
|
||||
|
Reference in New Issue
Block a user