2015-08-12 20:21:10 +00:00
|
|
|
#include "DefinitionNode.h"
|
2013-10-30 11:46:18 +00:00
|
|
|
|
2015-08-13 21:46:50 +00:00
|
|
|
#include "Logs.h"
|
2013-11-03 12:00:31 +00:00
|
|
|
#include "PackStream.h"
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
DefinitionNode::DefinitionNode(DefinitionNode* parent, const std::string &name):
|
2015-08-12 15:02:27 +00:00
|
|
|
parent(parent), name(name)
|
2013-10-30 11:46:18 +00:00
|
|
|
{
|
2013-10-30 14:39:56 +00:00
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
root = parent->root;
|
2015-08-12 15:02:27 +00:00
|
|
|
parent->addChild(this);
|
2013-10-30 14:39:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
root = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
DefinitionNode::~DefinitionNode()
|
2013-10-30 14:39:56 +00:00
|
|
|
{
|
2015-08-12 15:02:27 +00:00
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
parent->removeChild(this);
|
|
|
|
parent = NULL;
|
|
|
|
}
|
|
|
|
|
2015-08-12 17:29:28 +00:00
|
|
|
// Work on a copy, because the child destructor will modify the array by removing itself using removeChild
|
2015-08-12 20:21:10 +00:00
|
|
|
std::vector<DefinitionNode*> children_copy = children;
|
2015-08-12 17:29:28 +00:00
|
|
|
for (auto child:children_copy)
|
2013-10-30 14:39:56 +00:00
|
|
|
{
|
2015-08-12 15:02:27 +00:00
|
|
|
if (child->getParent() == this)
|
|
|
|
{
|
|
|
|
delete child;
|
|
|
|
}
|
2013-10-30 14:39:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
void DefinitionNode::setName(const std::string &name)
|
2013-10-30 14:39:56 +00:00
|
|
|
{
|
2013-10-31 16:59:18 +00:00
|
|
|
this->name = name;
|
2013-10-30 14:39:56 +00:00
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
Scenery* DefinitionNode::getScenery()
|
2013-11-17 21:36:18 +00:00
|
|
|
{
|
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
return parent->getScenery();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
std::string DefinitionNode::toString(int indent) const
|
2015-08-12 15:02:27 +00:00
|
|
|
{
|
|
|
|
std::string result;
|
|
|
|
for (int i = 0; i < indent; i++)
|
|
|
|
{
|
|
|
|
result += " ";
|
|
|
|
}
|
|
|
|
result += name;
|
|
|
|
if (not children.empty())
|
|
|
|
{
|
|
|
|
for (auto &child: children)
|
|
|
|
{
|
|
|
|
result += "\n" + child->toString(indent + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
void DefinitionNode::save(PackStream* stream) const
|
2013-10-30 14:39:56 +00:00
|
|
|
{
|
2015-08-13 21:46:50 +00:00
|
|
|
int children_count = (int)children.size();
|
|
|
|
stream->write(&children_count);
|
|
|
|
|
2013-12-10 21:32:58 +00:00
|
|
|
for (auto child: children)
|
2013-10-30 14:39:56 +00:00
|
|
|
{
|
2015-08-13 21:46:50 +00:00
|
|
|
stream->write(child->name);
|
|
|
|
|
|
|
|
int child_size = child->getStreamSize();
|
|
|
|
if (child_size >= 0)
|
|
|
|
{
|
|
|
|
stream->write(&child_size);
|
|
|
|
child->save(stream);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Child size not known, write it to a temporary stream to know it
|
|
|
|
Logs::debug() << "Unknown size for child " << child->name << ", unefficient writing to temporary stream" << std::endl;
|
|
|
|
PackStream substream;
|
|
|
|
child->save(&substream);
|
|
|
|
stream->writeFromBuffer(substream, true);
|
|
|
|
}
|
2013-10-30 14:39:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
void DefinitionNode::load(PackStream* stream)
|
2013-10-30 14:39:56 +00:00
|
|
|
{
|
2015-08-13 21:46:50 +00:00
|
|
|
int children_count;
|
|
|
|
|
|
|
|
stream->read(&children_count);
|
|
|
|
|
|
|
|
for (int i = 0; i < children_count; i++)
|
2013-10-30 14:39:56 +00:00
|
|
|
{
|
2015-08-13 21:46:50 +00:00
|
|
|
std::string child_name = stream->readString();
|
|
|
|
|
|
|
|
int child_size;
|
|
|
|
stream->read(&child_size);
|
|
|
|
|
|
|
|
DefinitionNode *child = findChildByName(child_name);
|
|
|
|
if (child)
|
|
|
|
{
|
|
|
|
// TODO type check
|
|
|
|
child->load(stream);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO Ask subclass if it can instanciate a child
|
|
|
|
// Else skip length of unknown child
|
|
|
|
stream->skipBytes(child_size);
|
|
|
|
Logs::warning() << "Skipped unknown child '" << child_name << "'" << std::endl;
|
|
|
|
}
|
2013-10-30 14:39:56 +00:00
|
|
|
}
|
2013-10-30 11:46:18 +00:00
|
|
|
}
|
2013-10-31 16:59:18 +00:00
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
void DefinitionNode::copy(DefinitionNode* destination) const
|
2013-10-31 16:59:18 +00:00
|
|
|
{
|
2013-10-31 23:09:51 +00:00
|
|
|
destination->setName(name);
|
|
|
|
// can't copy children as we don't know their types...
|
2013-10-31 16:59:18 +00:00
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
void DefinitionNode::validate()
|
2013-10-31 16:59:18 +00:00
|
|
|
{
|
2013-12-10 21:32:58 +00:00
|
|
|
for (auto child: children)
|
2013-10-31 16:59:18 +00:00
|
|
|
{
|
2013-12-10 21:32:58 +00:00
|
|
|
child->validate();
|
2013-10-31 16:59:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
void DefinitionNode::addChild(DefinitionNode* child)
|
2013-10-31 16:59:18 +00:00
|
|
|
{
|
2013-12-15 14:33:54 +00:00
|
|
|
if (std::find(children.begin(), children.end(), child) == children.end())
|
2013-10-31 16:59:18 +00:00
|
|
|
{
|
2013-12-10 21:32:58 +00:00
|
|
|
children.push_back(child);
|
2013-10-31 16:59:18 +00:00
|
|
|
child->parent = this;
|
|
|
|
child->root = this->root;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 20:21:10 +00:00
|
|
|
void DefinitionNode::removeChild(DefinitionNode* child)
|
2013-10-31 16:59:18 +00:00
|
|
|
{
|
2015-08-12 20:21:10 +00:00
|
|
|
std::vector<DefinitionNode*>::iterator it = std::find(children.begin(), children.end(), child);
|
2013-12-10 21:32:58 +00:00
|
|
|
if (it != children.end())
|
|
|
|
{
|
2015-08-12 15:02:27 +00:00
|
|
|
child->parent = NULL;
|
2013-12-10 21:32:58 +00:00
|
|
|
children.erase(it);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-08-13 21:46:50 +00:00
|
|
|
Logs::warning() << "Trying to remove not found child '" << child->name << "' from '" << name << "'" << std::endl;
|
2013-12-10 21:32:58 +00:00
|
|
|
}
|
2013-10-31 16:59:18 +00:00
|
|
|
}
|
2015-08-13 21:46:50 +00:00
|
|
|
|
|
|
|
DefinitionNode *DefinitionNode::findChildByName(const std::string name)
|
|
|
|
{
|
|
|
|
for (auto child: children)
|
|
|
|
{
|
|
|
|
if (child->name == name)
|
|
|
|
{
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DefinitionNode::getStreamSize() const
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|