Line data Source code
1 : /* Copyright (C) 2021 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "AtlasObject.h"
19 : #include "AtlasObjectImpl.h"
20 :
21 : #include <assert.h>
22 : #include <sstream>
23 :
24 : #define ATSMARTPTR_IMPL(T) \
25 : template<> void AtSmartPtr<T>::inc_ref() \
26 : { \
27 : if (ptr) ++ptr->m_Refcount; \
28 : } \
29 : \
30 : template<> void AtSmartPtr<T>::dec_ref() \
31 : { \
32 : if (ptr && --ptr->m_Refcount == 0) \
33 : delete ptr; \
34 : } // (Don't set ptr=NULL, since it should never be possible for an
35 : // unreferenced pointer to exist; I would rather see it die in debug
36 : // mode if that ever happens, instead of just silently ignoring the error.)
37 :
38 :
39 42 : ATSMARTPTR_IMPL(AtNode)
40 402 : ATSMARTPTR_IMPL(const AtNode)
41 0 : ATSMARTPTR_IMPL(AtIterImpl)
42 :
43 :
44 : //////////////////////////////////////////////////////////////////////////
45 :
46 0 : const AtIter AtIter::operator [] (const char* key) const
47 : {
48 0 : if (m_Impl)
49 0 : return m_Impl->iter->second->getChild(key);
50 : else
51 0 : return AtIter();
52 : }
53 :
54 0 : AtIter::operator const char* () const
55 : {
56 0 : return m_Impl ? m_Impl->iter->second->m_Value.c_str() : "";
57 : }
58 :
59 : //AtIter::operator const AtObj () const
60 0 : const AtObj AtIter::operator * () const
61 : {
62 0 : if (m_Impl)
63 : {
64 0 : AtObj ret;
65 0 : ret.m_Node = m_Impl->iter->second;
66 0 : return ret;
67 : }
68 : else
69 0 : return AtObj();
70 : }
71 :
72 :
73 0 : AtIter& AtIter::operator ++ ()
74 : {
75 0 : assert(m_Impl);
76 :
77 : // Increment the internal iterator, and stop if we've run out children
78 : // to iterate over.
79 0 : if (m_Impl && ++m_Impl->iter == m_Impl->iter_upperbound)
80 0 : m_Impl = nullptr;
81 :
82 0 : return *this;
83 : }
84 :
85 0 : bool AtIter::defined() const
86 : {
87 0 : return static_cast<bool>(m_Impl);
88 : }
89 :
90 0 : bool AtIter::hasContent() const
91 : {
92 0 : if (!m_Impl)
93 0 : return false;
94 :
95 0 : if (!m_Impl->iter->second)
96 0 : return false;
97 :
98 0 : return m_Impl->iter->second->hasContent();
99 : }
100 :
101 0 : size_t AtIter::count() const
102 : {
103 0 : if (!m_Impl)
104 0 : return 0;
105 :
106 0 : return std::distance(m_Impl->iter, m_Impl->iter_upperbound);
107 : }
108 :
109 : //////////////////////////////////////////////////////////////////////////
110 :
111 0 : const AtIter AtObj::operator [] (const char* key) const
112 : {
113 0 : if (m_Node)
114 0 : return m_Node->getChild(key);
115 : else
116 : // This object doesn't exist, so return another object that doesn't exist
117 0 : return AtIter();
118 : }
119 :
120 0 : AtObj::operator const char* () const
121 : {
122 0 : return m_Node ? m_Node->m_Value.c_str() : "";
123 : }
124 :
125 0 : double AtObj::getDouble() const
126 : {
127 0 : double val = 0;
128 0 : if (m_Node)
129 0 : static_cast<std::stringstream>(m_Node->m_Value) >> val;
130 0 : return val;
131 : }
132 :
133 0 : int AtObj::getInt() const
134 : {
135 0 : int val = 0;
136 0 : if (m_Node)
137 0 : static_cast<std::stringstream>(m_Node->m_Value) >> val;
138 0 : return val;
139 : }
140 :
141 0 : long AtObj::getLong() const
142 : {
143 0 : long val = 0;
144 0 : if (m_Node)
145 0 : static_cast<std::stringstream>(m_Node->m_Value) >> val;
146 0 : return val;
147 : }
148 :
149 0 : void AtObj::add(const char* key, AtObj& data)
150 : {
151 0 : if (!m_Node)
152 0 : m_Node = new AtNode();
153 :
154 0 : m_Node = m_Node->addChild(key, data.m_Node);
155 0 : }
156 :
157 0 : void AtObj::add(const char* key, const char* value)
158 : {
159 0 : const AtNode* o = new AtNode(value);
160 :
161 0 : if (!m_Node)
162 0 : m_Node = new AtNode();
163 :
164 0 : m_Node = m_Node->addChild(key, AtNode::Ptr(o));
165 0 : }
166 :
167 13 : void AtObj::set(const char* key, AtObj& data)
168 : {
169 13 : if (!m_Node)
170 13 : m_Node = new AtNode();
171 :
172 13 : m_Node = m_Node->setChild(key, data.m_Node);
173 13 : }
174 :
175 0 : void AtObj::set(const char* key, const char* value)
176 : {
177 0 : const AtNode* o = new AtNode(value);
178 :
179 0 : if (!m_Node)
180 0 : m_Node = new AtNode();
181 :
182 0 : m_Node = m_Node->setChild(key, AtNode::Ptr(o));
183 0 : }
184 :
185 0 : void AtObj::unset(const char* key)
186 : {
187 0 : if (!m_Node)
188 0 : m_Node = new AtNode();
189 :
190 0 : m_Node = m_Node->unsetChild(key);
191 0 : }
192 :
193 0 : void AtObj::setBool(const char* key, bool value)
194 : {
195 0 : AtNode* o = new AtNode(value ? "true" : "false");
196 0 : o->m_Children.insert(AtNode::child_pairtype("@boolean", AtNode::Ptr(new AtNode())));
197 :
198 0 : if (!m_Node)
199 0 : m_Node = new AtNode();
200 :
201 0 : m_Node = m_Node->setChild(key, AtNode::Ptr(o));
202 0 : }
203 :
204 0 : void AtObj::setDouble(const char* key, double value)
205 : {
206 0 : std::stringstream str;
207 0 : str << value;
208 0 : AtNode* o = new AtNode(str.str().c_str());
209 0 : o->m_Children.insert(AtNode::child_pairtype("@number", AtNode::Ptr(new AtNode())));
210 :
211 0 : if (!m_Node)
212 0 : m_Node = new AtNode();
213 :
214 0 : m_Node = m_Node->setChild(key, AtNode::Ptr(o));
215 0 : }
216 :
217 0 : void AtObj::setInt(const char* key, int value)
218 : {
219 0 : std::stringstream str;
220 0 : str << value;
221 0 : AtNode* o = new AtNode(str.str().c_str());
222 0 : o->m_Children.insert(AtNode::child_pairtype("@number", AtNode::Ptr(new AtNode())));
223 :
224 0 : if (!m_Node)
225 0 : m_Node = new AtNode();
226 :
227 0 : m_Node = m_Node->setChild(key, AtNode::Ptr(o));
228 0 : }
229 :
230 0 : void AtObj::setString(const char* value)
231 : {
232 0 : if (!m_Node)
233 0 : m_Node = new AtNode();
234 :
235 0 : m_Node = m_Node->setValue(value);
236 0 : }
237 :
238 0 : void AtObj::addOverlay(AtObj& data)
239 : {
240 0 : if (!m_Node)
241 0 : m_Node = new AtNode();
242 :
243 0 : m_Node = m_Node->addOverlay(data.m_Node);
244 0 : }
245 :
246 0 : bool AtObj::hasContent() const
247 : {
248 0 : if (!m_Node)
249 0 : return false;
250 :
251 0 : return m_Node->hasContent();
252 : }
253 :
254 : //////////////////////////////////////////////////////////////////////////
255 :
256 0 : const AtIter AtNode::getChild(const char* key) const
257 : {
258 : // Find the range of matching children
259 0 : AtNode::child_maptype::const_iterator it = m_Children.lower_bound(key);
260 0 : AtNode::child_maptype::const_iterator it_upper = m_Children.upper_bound(key);
261 :
262 0 : if (it == it_upper) // No match found
263 0 : return AtIter();
264 :
265 0 : AtIter obj;
266 0 : obj.m_Impl = new AtIterImpl(it, it_upper);
267 0 : return obj;
268 : }
269 :
270 0 : bool AtNode::hasContent() const
271 : {
272 0 : if (m_Value.length())
273 0 : return true;
274 :
275 0 : for (const child_maptype::value_type& child : m_Children)
276 0 : if (child.second && child.second->hasContent())
277 0 : return true;
278 :
279 0 : return false;
280 : }
281 :
282 0 : const AtNode::Ptr AtNode::setValue(const char* value) const
283 : {
284 0 : AtNode* newNode = new AtNode();
285 0 : newNode->m_Children = m_Children;
286 0 : newNode->m_Value = value;
287 0 : return AtNode::Ptr(newNode);
288 : }
289 :
290 13 : const AtNode::Ptr AtNode::setChild(const char* key, const AtNode::Ptr &data) const
291 : {
292 13 : AtNode* newNode = new AtNode(this);
293 13 : newNode->m_Children.erase(key);
294 13 : newNode->m_Children.insert(AtNode::child_pairtype(key, data));
295 13 : return AtNode::Ptr(newNode);
296 : }
297 :
298 0 : const AtNode::Ptr AtNode::unsetChild(const char* key) const
299 : {
300 0 : AtNode* newNode = new AtNode(this);
301 0 : newNode->m_Children.erase(key);
302 0 : return AtNode::Ptr(newNode);
303 : }
304 :
305 0 : const AtNode::Ptr AtNode::addChild(const char* key, const AtNode::Ptr &data) const
306 : {
307 0 : AtNode* newNode = new AtNode(this);
308 0 : newNode->m_Children.insert(AtNode::child_pairtype(key, data));
309 0 : return AtNode::Ptr(newNode);
310 : }
311 :
312 0 : const AtNode::Ptr AtNode::addOverlay(const AtNode::Ptr &data) const
313 : {
314 0 : AtNode* newNode = new AtNode(this);
315 :
316 : // Delete old childs that are also in the overlay
317 0 : for (AtNode::child_maptype::const_iterator it = data->m_Children.begin(); it != data->m_Children.end(); ++it)
318 0 : newNode->m_Children.erase(it->first);
319 :
320 : // Add the overlay childs back in
321 0 : for (AtNode::child_maptype::const_iterator it = data->m_Children.begin(); it != data->m_Children.end(); ++it)
322 0 : newNode->m_Children.insert(*it);
323 :
324 0 : return AtNode::Ptr(newNode);
325 : }
326 : //////////////////////////////////////////////////////////////////////////
327 :
328 0 : AtObj AtlasObject::TrimEmptyChildren(AtObj& obj)
329 : {
330 0 : AtObj ret;
331 :
332 0 : for (const AtNode::child_maptype::value_type& child : obj.m_Node->m_Children)
333 : {
334 0 : if (child.second && child.second->hasContent())
335 : {
336 0 : AtObj node;
337 0 : node.m_Node = child.second;
338 0 : ret.add(child.first.c_str(), node);
339 : }
340 : }
341 :
342 0 : return ret;
343 : }
|