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 : // Public interface to almost all of AtlasObject.
19 : // (See AtlasObjectText for the rest of it).
20 : //
21 : // Tries to include as few headers as possible, to minimise its impact
22 : // on compile times.
23 :
24 : #ifndef INCLUDED_ATLASOBJECT
25 : #define INCLUDED_ATLASOBJECT
26 :
27 : #if defined(_WIN32)
28 : # define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2008
29 : #endif
30 :
31 : #include <string>
32 :
33 : class wxString;
34 :
35 : //////////////////////////////////////////////////////////////////////////
36 : // Mostly-private bits:
37 :
38 : // Helper class to let us define a conversion operator only for AtSmartPtr<not const>
39 : template<class ConstSmPtr, class T> struct ConstCastHelper { operator ConstSmPtr (); };
40 : template<class ConstSmPtr, class T> struct ConstCastHelper<ConstSmPtr, const T> { };
41 :
42 : // Simple reference-counted pointer. class T must contain a reference count,
43 : // initialised to 0. An external implementation (in AtlasObjectImpl.cpp)
44 : // provides the inc_ref and dec_ref methods, so that this header file doesn't
45 : // need to know their implementations.
46 : template<class T> class AtSmartPtr : public ConstCastHelper<AtSmartPtr<const T>, T>
47 : {
48 : friend struct ConstCastHelper<AtSmartPtr<const T>, T>;
49 : private:
50 : void inc_ref();
51 : void dec_ref();
52 : T* ptr;
53 : public:
54 : // Constructors
55 26 : AtSmartPtr() : ptr(NULL) {}
56 62 : explicit AtSmartPtr(T* p) : ptr(p) { inc_ref(); }
57 : // Copy constructor
58 108 : AtSmartPtr(const AtSmartPtr<T>& r) : ptr(r.ptr) { inc_ref(); }
59 : // Assignment operators
60 13 : AtSmartPtr<T>& operator=(T* p) { dec_ref(); ptr = p; inc_ref(); return *this; }
61 26 : AtSmartPtr<T>& operator=(const AtSmartPtr<T>& r) { if (&r != this) { dec_ref(); ptr = r.ptr; inc_ref(); } return *this; }
62 : // Destructor
63 196 : ~AtSmartPtr() { dec_ref(); }
64 : // Allow conversion from non-const T* to const T*
65 : //operator AtSmartPtr<const T> () { return AtSmartPtr<const T>(ptr); } // (actually provided by ConstCastHelper)
66 : // Override ->
67 212 : T* operator->() const { return ptr; }
68 : // Test whether the pointer is pointing to anything
69 67 : explicit operator bool() const { return ptr != nullptr; }
70 : };
71 :
72 : template<class ConstSmPtr, class T>
73 21 : ConstCastHelper<ConstSmPtr, T>::operator ConstSmPtr ()
74 : {
75 21 : return ConstSmPtr(static_cast<AtSmartPtr<T>*>(this)->ptr);
76 : }
77 :
78 : // A few required declarations
79 : class AtObj;
80 : class AtNode;
81 : class AtIterImpl;
82 :
83 :
84 : //////////////////////////////////////////////////////////////////////////
85 : // Public bits:
86 :
87 :
88 : // AtIter is an iterator over AtObjs - use it like:
89 : //
90 : // for (AtIter thing = whatever["thing"]; thing.defined(); ++thing)
91 : // DoStuff(thing);
92 : //
93 : // to handle XML data like:
94 : //
95 : // <whatever>
96 : // <thing>Stuff 1</thing>
97 : // <thing>Stuff 2</thing>
98 : // </whatever>
99 :
100 0 : class AtIter
101 : {
102 : public:
103 : // Increment the iterator; or make it undefined, if there weren't any
104 : // AtObjs left to iterate over
105 : AtIter& operator++ ();
106 : // Return whether this iterator has an AtObj to point to
107 : bool defined() const;
108 : // Return whether this iterator is pointing to a non-contentless AtObj
109 : bool hasContent() const;
110 : // Return the number of AtObjs that will be iterated over (including the current one)
111 : size_t count() const;
112 :
113 : // Return an iterator to the children matching 'key'. (That is, children
114 : // of the AtObj currently pointed to by this iterator)
115 : const AtIter operator[] (const char* key) const;
116 :
117 : // Return the AtObj currently pointed to by this iterator
118 : const AtObj operator* () const;
119 :
120 : // Return the string value of the AtObj currently pointed to by this iterator
121 : operator const char* () const;
122 :
123 : // Private implementation. (But not 'private:', because it's a waste of time
124 : // adding loads of friend functions)
125 : AtSmartPtr<AtIterImpl> m_Impl;
126 : };
127 :
128 :
129 39 : class AtObj
130 : {
131 : public:
132 26 : AtObj() {}
133 13 : AtObj(const AtObj& r) : m_Node(r.m_Node) {}
134 : AtObj& operator=(const AtObj& r)
135 : {
136 : m_Node = r.m_Node;
137 : return *this;
138 : }
139 :
140 : // Return an iterator to the children matching 'key'
141 : const AtIter operator[] (const char* key) const;
142 :
143 : // Return the string value of this object
144 : operator const char* () const;
145 :
146 : // Return the floating point value of this object
147 : double getDouble() const;
148 :
149 : // Return the integer value of this object
150 : int getInt() const;
151 : long getLong() const;
152 :
153 : // Check whether the object contains anything (even if those things are empty)
154 : bool defined() const { return static_cast<bool>(m_Node); }
155 :
156 : // Check recursively whether there's actually any non-empty data in the object
157 : bool hasContent() const;
158 :
159 : // Add or set a child. The char* version creates a new AtObj with
160 : // the appropriate string value, then uses that as the child.
161 : //
162 : // These alter the AtObj's internal pointer, and the pointed-to data is
163 : // never actually altered. Copies of this AtObj (including copies stored
164 : // inside other AtObjs) will not be affected.
165 : void add(const char* key, const char* value);
166 : void add(const char* key, AtObj& data);
167 : void set(const char* key, const char* value);
168 : void set(const char* key, AtObj& data);
169 : void unset(const char* key);
170 : void setBool(const char* key, bool value);
171 : void setDouble(const char* key, double value);
172 : void setInt(const char* key, int value);
173 : void setString(const char* value);
174 : void addOverlay(AtObj& data);
175 :
176 : AtSmartPtr<const AtNode> m_Node;
177 : };
178 :
179 :
180 : // Miscellaneous utility functions:
181 : namespace AtlasObject
182 : {
183 : // Returns AtObj() on failure - test with AtObj::defined()
184 : AtObj LoadFromXML(const std::string& xml);
185 :
186 : // Returns AtObj() on failure - test with AtObj::defined()
187 : AtObj LoadFromJSON(const std::string& json);
188 :
189 : // Returns UTF-8-encoded XML document string.
190 : // Returns empty string on failure.
191 : std::string SaveToXML(AtObj& obj);
192 :
193 : // Returns UTF-8-encoded JSON string.
194 : // Returns empty string on failure.
195 : std::string SaveToJSON(AtObj& obj);
196 :
197 : AtObj TrimEmptyChildren(AtObj& obj);
198 : }
199 :
200 : #endif // INCLUDED_ATLASOBJECT
|