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#ifndef OTMLNODE_H
24#define OTMLNODE_H
25
26#include "declarations.h"
27
28class OTMLNode : public stdext::shared_object
29{
30public:
31 virtual ~OTMLNode() { }
32
33 static OTMLNodePtr create(std::string tag = "", bool unique = false);
34 static OTMLNodePtr create(std::string tag, std::string value);
35
36 std::string tag() { return m_tag; }
37 int size() { return m_children.size(); }
38 std::string source() { return m_source; }
39 std::string rawValue() { return m_value; }
40
41 bool isUnique() { return m_unique; }
42 bool isNull() { return m_null; }
43
44 bool hasTag() { return !m_tag.empty(); }
45 bool hasValue() { return !m_value.empty(); }
46 bool hasChildren();
47 bool hasChildAt(const std::string& childTag) { return !!get(childTag); }
48 size_t getIndex() { return m_index; }
49
50 void setTag(const std::string& tag);
51 void setValue(const std::string& value) { m_value = value; }
52 void setNull(bool null) { m_null = null; }
53 void setUnique(bool unique) { m_unique = unique; }
54 void setSource(const std::string& source) { m_source = source; }
55 void setIndex(size_t index) { m_index = index; }
56
57 void lockTag() {
58 m_tagLocked = true;
59 }
60
61 OTMLNodePtr get(const std::string& childTag);
62 OTMLNodePtr getIndex(int childIndex);
63
64 OTMLNodePtr at(const std::string& childTag);
65
66 void addChild(const OTMLNodePtr& newChild);
67 bool removeChild(const OTMLNodePtr& oldChild);
68 void copy(const OTMLNodePtr& node);
69 void merge(const OTMLNodePtr& node);
70 void clear();
71
72 OTMLNodeList children();
73 OTMLNodePtr clone();
74
75 template<typename T = std::string>
76 T value();
77 template<typename T = std::string>
78 T valueAt(const std::string& childTag);
79 template<typename T = std::string>
80 T valueAtIndex(int childIndex);
81 template<typename T = std::string>
82 T valueAt(const std::string& childTag, const T& def);
83 template<typename T = std::string>
84 T valueAtIndex(int childIndex, const T& def);
85
86 template<typename T>
87 void write(const T& v);
88 template<typename T>
89 void writeAt(const std::string& childTag, const T& v);
90 template<typename T>
91 void writeIn(const T& v);
92
93 virtual std::string emit();
94
95 OTMLNodePtr asOTMLNode() { return static_self_cast<OTMLNode>(); }
96
97protected:
98 OTMLNode() : m_unique(false), m_null(false) { }
99
100 std::unordered_map<std::string, std::vector<OTMLNodePtr>> m_children;
101 std::string m_tag;
102 std::string m_value;
103 std::string m_source;
104 size_t m_index = 0;
105 bool m_unique;
106 bool m_null;
107 bool m_tagLocked = false;
108};
109
110#include "otmlexception.h"
111
112template<>
113inline std::string OTMLNode::value<std::string>() {
114 std::string value = m_value;
115 if(stdext::starts_with(value, "\"") && stdext::ends_with(value, "\"")) {
116 value = value.substr(1, value.length()-2);
117 stdext::replace_all(value, "\\\\", "\\");
118 stdext::replace_all(value, "\\\"", "\"");
119 stdext::replace_all(value, "\\t", "\t");
120 stdext::replace_all(value, "\\n", "\n");
121 stdext::replace_all(value, "\\'", "\'");
122 }
123 return value;
124}
125
126template<typename T>
127T OTMLNode::value() {
128 T ret;
129 if(!stdext::cast(m_value, ret))
130 throw OTMLException(asOTMLNode(), stdext::format("failed to cast node value '%s' to type '%s'", m_value, stdext::demangle_type<T>()));
131 return ret;
132}
133
134template<typename T>
135T OTMLNode::valueAt(const std::string& childTag) {
136 OTMLNodePtr node = at(childTag);
137 return node->value<T>();
138}
139
140template<typename T>
141T OTMLNode::valueAt(const std::string& childTag, const T& def) {
142 if(OTMLNodePtr node = get(childTag))
143 if(!node->isNull())
144 return node->value<T>();
145 return def;
146}
147
148template<typename T>
149T OTMLNode::valueAtIndex(int childIndex, const T& def) {
150 if(OTMLNodePtr node = getIndex(childIndex))
151 return node->value<T>();
152 return def;
153}
154
155template<typename T>
156void OTMLNode::write(const T& v) {
157 m_value = stdext::safe_cast<std::string>(v);
158}
159
160template<typename T>
161void OTMLNode::writeAt(const std::string& childTag, const T& v) {
162 OTMLNodePtr child = OTMLNode::create(childTag);
163 child->setUnique(true);
164 child->write<T>(v);
165 addChild(child);
166}
167
168template<typename T>
169void OTMLNode::writeIn(const T& v) {
170 OTMLNodePtr child = OTMLNode::create();
171 child->write<T>(v);
172 addChild(child);
173}
174
175#endif
176
177