mirror of
https://github.com/edubart/otclient.git
synced 2025-05-04 11:39:20 +02:00
204 lines
5.8 KiB
C++
204 lines
5.8 KiB
C++
/*
|
|
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
#include "otmlnode.h"
|
|
#include "otmlemitter.h"
|
|
#include "otmldocument.h"
|
|
|
|
OTMLNodePtr OTMLNode::create(std::string tag, bool unique)
|
|
{
|
|
OTMLNodePtr node(new OTMLNode);
|
|
node->setTag(tag);
|
|
node->setUnique(unique);
|
|
return node;
|
|
}
|
|
|
|
OTMLNodePtr OTMLNode::create(std::string tag, std::string value)
|
|
{
|
|
OTMLNodePtr node(new OTMLNode);
|
|
node->setTag(tag);
|
|
node->setValue(value);
|
|
node->setUnique(true);
|
|
return node;
|
|
}
|
|
|
|
bool OTMLNode::hasChildren() const
|
|
{
|
|
int count = 0;
|
|
for(const OTMLNodePtr& child : m_children) {
|
|
if(!child->isNull())
|
|
count++;
|
|
}
|
|
return count > 0;
|
|
}
|
|
|
|
OTMLNodePtr OTMLNode::get(const std::string& childTag) const
|
|
{
|
|
for(const OTMLNodePtr& child : m_children) {
|
|
if(child->tag() == childTag && !child->isNull())
|
|
return child;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
OTMLNodePtr OTMLNode::getIndex(int childIndex) const
|
|
{
|
|
if(childIndex < size() && childIndex >= 0)
|
|
return m_children[childIndex];
|
|
return nullptr;
|
|
}
|
|
|
|
OTMLNodePtr OTMLNode::at(const std::string& childTag)
|
|
{
|
|
OTMLNodePtr res;
|
|
for(const OTMLNodePtr& child : m_children) {
|
|
if(child->tag() == childTag && !child->isNull()) {
|
|
res = child;
|
|
break;
|
|
}
|
|
}
|
|
if(!res)
|
|
throw OTMLException(shared_from_this(), stdext::format("child node with tag '%s' not found", childTag));
|
|
return res;
|
|
}
|
|
|
|
OTMLNodePtr OTMLNode::atIndex(int childIndex)
|
|
{
|
|
if(childIndex >= size() || childIndex < 0)
|
|
throw OTMLException(shared_from_this(), stdext::mkstr("child node with index '%d' not found", childIndex));
|
|
return m_children[childIndex];
|
|
}
|
|
|
|
void OTMLNode::addChild(const OTMLNodePtr& newChild)
|
|
{
|
|
// replace is needed when the tag is marked as unique
|
|
if(newChild->hasTag()) {
|
|
for(const OTMLNodePtr& node : m_children) {
|
|
if(node->tag() == newChild->tag() && (node->isUnique() || newChild->isUnique())) {
|
|
newChild->setUnique(true);
|
|
|
|
if(node->hasChildren() && newChild->hasChildren()) {
|
|
OTMLNodePtr tmpNode = node->clone();
|
|
tmpNode->merge(newChild);
|
|
newChild->copy(tmpNode);
|
|
}
|
|
|
|
replaceChild(node, newChild);
|
|
|
|
// remove any other child with the same tag
|
|
auto it = m_children.begin();
|
|
while(it != m_children.end()) {
|
|
OTMLNodePtr node = (*it);
|
|
if(node != newChild && node->tag() == newChild->tag()) {
|
|
node->setParent(nullptr);
|
|
it = m_children.erase(it);
|
|
} else
|
|
++it;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_children.push_back(newChild);
|
|
newChild->setParent(shared_from_this());
|
|
}
|
|
|
|
bool OTMLNode::removeChild(const OTMLNodePtr& oldChild)
|
|
{
|
|
auto it = std::find(m_children.begin(), m_children.end(), oldChild);
|
|
if(it != m_children.end()) {
|
|
m_children.erase(it);
|
|
oldChild->setParent(nullptr);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool OTMLNode::replaceChild(const OTMLNodePtr& oldChild, const OTMLNodePtr& newChild)
|
|
{
|
|
auto it = std::find(m_children.begin(), m_children.end(), oldChild);
|
|
if(it != m_children.end()) {
|
|
oldChild->setParent(nullptr);
|
|
newChild->setParent(shared_from_this());
|
|
it = m_children.erase(it);
|
|
m_children.insert(it, newChild);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void OTMLNode::copy(const OTMLNodePtr& node)
|
|
{
|
|
setTag(node->tag());
|
|
setValue(node->value());
|
|
setUnique(node->isUnique());
|
|
setNull(node->isNull());
|
|
setSource(node->source());
|
|
clear();
|
|
for(const OTMLNodePtr& child : node->m_children)
|
|
addChild(child->clone());
|
|
}
|
|
|
|
void OTMLNode::merge(const OTMLNodePtr& node)
|
|
{
|
|
for(const OTMLNodePtr& child : node->m_children)
|
|
addChild(child->clone());
|
|
setTag(node->tag());
|
|
setSource(node->source());
|
|
}
|
|
|
|
void OTMLNode::clear()
|
|
{
|
|
for(const OTMLNodePtr& child : m_children)
|
|
child->setParent(nullptr);
|
|
m_children.clear();
|
|
}
|
|
|
|
OTMLNodeList OTMLNode::children() const
|
|
{
|
|
OTMLNodeList children;
|
|
for(const OTMLNodePtr& child : m_children)
|
|
if(!child->isNull())
|
|
children.push_back(child);
|
|
return children;
|
|
}
|
|
|
|
OTMLNodePtr OTMLNode::clone() const
|
|
{
|
|
OTMLNodePtr myClone(new OTMLNode);
|
|
myClone->setTag(m_tag);
|
|
myClone->setValue(m_value);
|
|
myClone->setUnique(m_unique);
|
|
myClone->setNull(m_null);
|
|
myClone->setSource(m_source);
|
|
for(const OTMLNodePtr& child : m_children)
|
|
myClone->addChild(child->clone());
|
|
return myClone;
|
|
}
|
|
|
|
std::string OTMLNode::emit()
|
|
{
|
|
return OTMLEmitter::emitNode(shared_from_this(), 0);
|
|
}
|
|
|