Civ backgrounds for minimap
[0ad.git] / source / ps / XMB / XMBData.h
blob06185ecca28b3ec50646e67b9e43e444bc68064f
1 /* Copyright (C) 2021 Wildfire Games.
2 * This file is part of 0 A.D.
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.
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.
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/>.
19 Xeromyces - XMB reading library
21 Brief outline:
23 XMB originated as a binary representation of XML, with some limitations
24 but much more efficiency (particularly for loading simple data
25 classes that don't need much initialisation).
27 Theoretical file structure:
29 XMB_File {
30 char Header[4]; // because everyone has one; currently "XMB0"
31 u32 Version;
33 int OffsetFromStartToElementNames;
34 int ElementNameCount;
36 int OffsetFromStartToAttributeNames;
37 int AttributeNameCount;
39 XMB_Node Root;
41 ZStr8 ElementNames[];
42 ZStr8 AttributeNames[];
46 XMB_Node {
47 0) int Length; // of entire struct, so it can be skipped over
49 4) int ElementName;
51 8) int AttributeCount;
52 12) int ChildCount;
54 16) int ChildrenOffset; // == sizeof(Text)+sizeof(Attributes)
55 20) XMB_Text Text;
56 XMB_Attribute Attributes[];
57 XMB_Node Children[];
61 XMB_Attribute {
62 int Name;
63 ZStr8 Value;
66 ZStr8 {
67 int Length; // in bytes
68 char* Text; // null-terminated UTF8
71 XMB_Text {
72 20) int Length; // 0 if there's no text, else 4+sizeof(Text) in bytes including terminator
73 // If Length != 0:
74 24) int LineNumber; // for e.g. debugging scripts
75 28) char* Text; // null-terminated UTF8
80 #ifndef INCLUDED_XEROXMB
81 #define INCLUDED_XEROXMB
83 #include "ps/CStr.h"
85 #include <string>
86 #include <string_view>
88 class XMBStorage;
90 class XMBElement;
91 class XMBElementList;
92 class XMBAttributeList;
95 class XMBData
97 public:
99 XMBData() : m_Pointer(nullptr) {}
102 * Initialise from the contents of an XMBStorage.
103 * @param doc must remain allocated and unchanged while
104 * the XMBData is being used.
105 * @return indication of success; main cause for failure is attempting to
106 * load a partially valid XMB file (e.g. if the game was interrupted
107 * while writing it), which we detect by checking the magic string.
108 * It also fails when trying to load an XMB file with a different version.
110 bool Initialise(const XMBStorage& doc);
112 // Returns the root element
113 XMBElement GetRoot() const;
115 // Returns internal ID for a given element/attribute string.
116 int GetElementID(const char* Name) const;
117 int GetAttributeID(const char* Name) const;
119 // Returns element/attribute string for a given internal ID.
120 const char* GetElementString(const int ID) const;
121 const char* GetAttributeString(const int ID) const;
123 std::string_view GetElementStringView(const int ID) const;
124 std::string_view GetAttributeStringView(const int ID) const;
126 private:
127 const char* m_Pointer;
129 int m_ElementNameCount;
130 int m_AttributeNameCount;
131 const char* m_ElementPointer;
132 const char* m_AttributePointer;
135 class XMBElement
137 public:
138 XMBElement()
139 : m_Pointer(0) {}
141 XMBElement(const char* offset)
142 : m_Pointer(offset) {}
144 int GetNodeName() const;
145 XMBElementList GetChildNodes() const;
146 XMBAttributeList GetAttributes() const;
147 CStr8 GetText() const;
148 // Returns the line number of the text within this element,
149 // or -1 if there is no text
150 int GetLineNumber() const;
152 private:
153 // Pointer to the start of the node
154 const char* m_Pointer;
157 class XMBElementList
159 public:
160 XMBElementList(const char* offset, size_t count, const char* endoffset)
161 : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
163 // Get first element in list with the given name.
164 // Performance is linear in the number of elements in the list.
165 XMBElement GetFirstNamedItem(const int ElementName) const;
167 // Linear in the number of elements in the list
168 XMBElement operator[](size_t id); // returns Children[id]
170 class iterator
172 public:
173 typedef ptrdiff_t difference_type;
174 typedef XMBElement value_type;
175 typedef XMBElement reference; // Because we need to construct the object
176 typedef XMBElement pointer; // Because we need to construct the object
177 typedef std::forward_iterator_tag iterator_category;
179 iterator(size_t size, const char* ptr, const char* endptr = NULL)
180 : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr) {}
181 XMBElement operator*() const { return XMBElement(m_CurPointer); }
182 XMBElement operator->() const { return **this; }
183 iterator& operator++();
185 bool operator==(const iterator& rhs) const
187 return m_Size == rhs.m_Size &&
188 m_CurItemID == rhs.m_CurItemID &&
189 m_CurPointer == rhs.m_CurPointer;
191 bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
192 private:
193 size_t m_Size;
194 size_t m_CurItemID;
195 const char* m_CurPointer;
197 iterator begin() { return iterator(m_Size, m_Pointer); }
198 iterator end() { return iterator(m_Size, m_Pointer, m_EndPointer); }
200 size_t size() const { return m_Size; }
201 bool empty() const { return m_Size == 0; }
203 private:
204 size_t m_Size;
206 const char* m_Pointer;
208 // For optimised sequential access:
209 size_t m_CurItemID;
210 const char* m_CurPointer;
212 const char* m_EndPointer;
216 struct XMBAttribute
218 XMBAttribute() {}
219 XMBAttribute(int name, const CStr8& value)
220 : Name(name), Value(value) {};
222 int Name;
223 CStr8 Value; // UTF-8 encoded
226 class XMBAttributeList
228 public:
229 XMBAttributeList(const char* offset, size_t count, const char* endoffset)
230 : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
232 // Get the attribute value directly
233 CStr8 GetNamedItem(const int AttributeName) const;
235 // Linear in the number of elements in the list
236 XMBAttribute operator[](size_t id); // returns Children[id]
238 class iterator
240 public:
241 typedef ptrdiff_t difference_type;
242 typedef XMBAttribute value_type;
243 typedef XMBAttribute reference; // Because we need to construct the object
244 typedef XMBAttribute pointer; // Because we need to construct the object
245 typedef std::forward_iterator_tag iterator_category;
247 iterator(size_t size, const char* ptr, const char* endptr = NULL)
248 : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr) {}
249 XMBAttribute operator*() const;
250 XMBAttribute operator->() const { return **this; }
251 iterator& operator++();
253 bool operator==(const iterator& rhs) const
255 return m_Size == rhs.m_Size &&
256 m_CurItemID == rhs.m_CurItemID &&
257 m_CurPointer == rhs.m_CurPointer;
259 bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
260 private:
261 size_t m_Size;
262 size_t m_CurItemID;
263 const char* m_CurPointer;
265 iterator begin() const { return iterator(m_Size, m_Pointer); }
266 iterator end() const { return iterator(m_Size, m_Pointer, m_EndPointer); }
268 size_t size() const { return m_Size; }
269 bool empty() const { return m_Size == 0; }
271 private:
272 size_t m_Size;
274 // Pointer to start of attribute list
275 const char* m_Pointer;
277 // For optimised sequential access:
278 size_t m_CurItemID;
279 const char* m_CurPointer;
281 const char* m_EndPointer;
284 #endif // INCLUDED_XEROXMB