Otclient 1.0  14/8/2020
otmlnode.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 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 "otmlnode.h"
24 #include "otmlemitter.h"
25 #include "otmldocument.h"
26 
27 OTMLNodePtr OTMLNode::create(std::string tag, bool unique)
28 {
29  OTMLNodePtr node(new OTMLNode);
30  node->setTag(tag);
31  node->setUnique(unique);
32  return node;
33 }
34 
35 OTMLNodePtr OTMLNode::create(std::string tag, std::string value)
36 {
37  OTMLNodePtr node(new OTMLNode);
38  node->setTag(tag);
39  node->setValue(value);
40  node->setUnique(true);
41  return node;
42 }
43 
45 {
46  int count = 0;
47  for (const OTMLNodePtr& child : m_children) {
48  if (!child->isNull())
49  count++;
50  }
51  return count > 0;
52 }
53 
54 OTMLNodePtr OTMLNode::get(const std::string& childTag)
55 {
56  for (const OTMLNodePtr& child : m_children) {
57  if (child->tag() == childTag && !child->isNull())
58  return child;
59  }
60  return nullptr;
61 }
62 
64 {
65  if (childIndex < size() && childIndex >= 0)
66  return m_children[childIndex];
67  return nullptr;
68 }
69 
70 OTMLNodePtr OTMLNode::at(const std::string& childTag)
71 {
72  OTMLNodePtr res;
73  for (const OTMLNodePtr& child : m_children) {
74  if (child->tag() == childTag && !child->isNull()) {
75  res = child;
76  break;
77  }
78  }
79  if (!res)
80  throw OTMLException(asOTMLNode(), stdext::format("child node with tag '%s' not found", childTag));
81  return res;
82 }
83 
85 {
86  if (childIndex >= size() || childIndex < 0)
87  throw OTMLException(asOTMLNode(), stdext::format("child node with index '%d' not found", childIndex));
88  return m_children[childIndex];
89 }
90 
91 void OTMLNode::addChild(const OTMLNodePtr& newChild)
92 {
93  // replace is needed when the tag is marked as unique
94  if (newChild->hasTag()) {
95  for (const OTMLNodePtr& node : m_children) {
96  if (node->tag() == newChild->tag() && (node->isUnique() || newChild->isUnique())) {
97  newChild->setUnique(true);
98 
99  if (node->hasChildren() && newChild->hasChildren()) {
100  OTMLNodePtr tmpNode = node->clone();
101  tmpNode->merge(newChild);
102  newChild->copy(tmpNode);
103  }
104 
105  replaceChild(node, newChild);
106 
107  // remove any other child with the same tag
108  auto it = m_children.begin();
109  while (it != m_children.end()) {
110  const OTMLNodePtr nodeChild = (*it);
111  if (nodeChild != newChild && nodeChild->tag() == newChild->tag()) {
112  it = m_children.erase(it);
113  }
114  else
115  ++it;
116  }
117  return;
118  }
119  }
120  }
121 
122  m_children.push_back(newChild);
123 }
124 
125 bool OTMLNode::removeChild(const OTMLNodePtr& oldChild)
126 {
127  auto it = std::find(m_children.begin(), m_children.end(), oldChild);
128  if (it != m_children.end()) {
129  m_children.erase(it);
130  return true;
131  }
132  return false;
133 }
134 
135 bool OTMLNode::replaceChild(const OTMLNodePtr& oldChild, const OTMLNodePtr& newChild)
136 {
137  auto it = std::find(m_children.begin(), m_children.end(), oldChild);
138  if (it != m_children.end()) {
139  it = m_children.erase(it);
140  m_children.insert(it, newChild);
141  return true;
142  }
143  return false;
144 }
145 
146 void OTMLNode::copy(const OTMLNodePtr& node)
147 {
148  setTag(node->tag());
149  setValue(node->rawValue());
150  setUnique(node->isUnique());
151  setNull(node->isNull());
152  setSource(node->source());
153  clear();
154  for (const OTMLNodePtr& child : node->m_children)
155  addChild(child->clone());
156 }
157 
158 void OTMLNode::merge(const OTMLNodePtr& node)
159 {
160  for (const OTMLNodePtr& child : node->m_children)
161  addChild(child->clone());
162  setTag(node->tag());
163  setSource(node->source());
164 }
165 
167 {
168  m_children.clear();
169 }
170 
172 {
174  for (const OTMLNodePtr& child : m_children)
175  if (!child->isNull())
176  children.push_back(child);
177  return children;
178 }
179 
181 {
182  OTMLNodePtr myClone(new OTMLNode);
183  myClone->setTag(m_tag);
184  myClone->setValue(m_value);
185  myClone->setUnique(m_unique);
186  myClone->setNull(m_null);
187  myClone->setSource(m_source);
188  for (const OTMLNodePtr& child : m_children)
189  myClone->addChild(child->clone());
190  return myClone;
191 }
192 
193 std::string OTMLNode::emit()
194 {
195  return OTMLEmitter::emitNode(asOTMLNode(), 0);
196 }
OTMLNode::setTag
void setTag(const std::string &tag)
Definition: otmlnode.h:50
OTMLNode::setSource
void setSource(const std::string &source)
Definition: otmlnode.h:54
OTMLNode::source
std::string source()
Definition: otmlnode.h:38
OTMLNode
Definition: otmlnode.h:28
OTMLException
All OTML errors throw this exception.
Definition: otmlexception.h:29
OTMLNode::hasChildren
bool hasChildren()
Definition: otmlnode.cpp:44
OTMLNode::m_null
bool m_null
Definition: otmlnode.h:102
OTMLNode::removeChild
bool removeChild(const OTMLNodePtr &oldChild)
Definition: otmlnode.cpp:125
OTMLNode::m_children
OTMLNodeList m_children
Definition: otmlnode.h:97
OTMLNode::children
OTMLNodeList children()
Definition: otmlnode.cpp:171
OTMLEmitter::emitNode
static std::string emitNode(const OTMLNodePtr &node, int currentDepth=-1)
Emits a node and it's children to a std::string.
Definition: otmlemitter.cpp:26
stdext::format
std::string format()
Definition: format.h:84
OTMLNode::addChild
void addChild(const OTMLNodePtr &newChild)
Definition: otmlnode.cpp:91
OTMLNode::replaceChild
bool replaceChild(const OTMLNodePtr &oldChild, const OTMLNodePtr &newChild)
Definition: otmlnode.cpp:135
otmldocument.h
OTMLNode::isUnique
bool isUnique()
Definition: otmlnode.h:41
OTMLNode::setNull
void setNull(bool null)
Definition: otmlnode.h:52
OTMLNode::tag
std::string tag()
Definition: otmlnode.h:36
OTMLNode::setUnique
void setUnique(bool unique)
Definition: otmlnode.h:53
OTMLNode::emit
virtual std::string emit()
Definition: otmlnode.cpp:193
OTMLNode::getIndex
OTMLNodePtr getIndex(int childIndex)
Definition: otmlnode.cpp:63
OTMLNode::value
T value()
Definition: otmlnode.h:122
OTMLNode::rawValue
std::string rawValue()
Definition: otmlnode.h:39
OTMLNode::clone
OTMLNodePtr clone()
Definition: otmlnode.cpp:180
OTMLNode::setValue
void setValue(const std::string &value)
Definition: otmlnode.h:51
OTMLNodeList
std::vector< OTMLNodePtr > OTMLNodeList
Definition: declarations.h:35
OTMLNode::size
int size()
Definition: otmlnode.h:37
OTMLNode::get
OTMLNodePtr get(const std::string &childTag)
Definition: otmlnode.cpp:54
OTMLNode::m_value
std::string m_value
Definition: otmlnode.h:99
OTMLNode::hasTag
bool hasTag()
Definition: otmlnode.h:44
OTMLNode::asOTMLNode
OTMLNodePtr asOTMLNode()
Definition: otmlnode.h:92
OTMLNode::m_source
std::string m_source
Definition: otmlnode.h:100
otmlnode.h
stdext::shared_object_ptr< OTMLNode >
OTMLNode::merge
void merge(const OTMLNodePtr &node)
Definition: otmlnode.cpp:158
OTMLNode::copy
void copy(const OTMLNodePtr &node)
Definition: otmlnode.cpp:146
OTMLNode::isNull
bool isNull()
Definition: otmlnode.h:42
otmlemitter.h
OTMLNode::m_tag
std::string m_tag
Definition: otmlnode.h:98
OTMLNode::clear
void clear()
Definition: otmlnode.cpp:166
OTMLNode::m_unique
bool m_unique
Definition: otmlnode.h:101
OTMLNode::atIndex
OTMLNodePtr atIndex(int childIndex)
Definition: otmlnode.cpp:84
OTMLNode::at
OTMLNodePtr at(const std::string &childTag)
Definition: otmlnode.cpp:70
OTMLNode::create
static OTMLNodePtr create(std::string tag="", bool unique=false)
Definition: otmlnode.cpp:27