Pyrogenesis  trunk
XeroXMB.h
Go to the documentation of this file.
1 /* Copyright (C) 2015 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 /*
19  Xeromyces - XMB reading library
20 */
21 
22 /*
23 
24 Brief outline:
25 
26 XMB is a binary representation of XML, with some limitations
27 but much more efficiency (particularly for loading simple data
28 classes that don't need much initialisation).
29 
30 Main limitations:
31  * Can't correctly handle mixed text/elements inside elements -
32  "<div> <b> Text </b> </div>" and "<div> Te<b/>xt </div>" are
33  considered identical.
34  * Tries to avoid using strings - you usually have to load the
35  numeric IDs and use them instead.
36  * Case-sensitive (but converts all element/attribute names in
37  the XML file to lowercase, so you only have to be careful in
38  the code)
39 
40 
41 Theoretical file structure:
42 
43 XMB_File {
44  char Header[4]; // because everyone has one; currently "XMB0"
45  u32 Version;
46 
47  int ElementNameCount;
48  ZStr8 ElementNames[];
49 
50  int AttributeNameCount;
51  ZStr8 AttributeNames[];
52 
53  XMB_Node Root;
54 }
55 
56 XMB_Node {
57 0) int Length; // of entire struct, so it can be skipped over
58 
59 4) int ElementName;
60 
61 8) int AttributeCount;
62 12) int ChildCount;
63 
64 16) int ChildrenOffset; // == sizeof(Text)+sizeof(Attributes)
65 20) XMB_Text Text;
66  XMB_Attribute Attributes[];
67  XMB_Node Children[];
68 
69 }
70 
71 XMB_Attribute {
72  int Name;
73  ZStr8 Value;
74 }
75 
76 ZStr8 {
77  int Length; // in bytes
78  char* Text; // null-terminated UTF8
79 }
80 
81 XMB_Text {
82 20) int Length; // 0 if there's no text, else 4+sizeof(Text) in bytes including terminator
83  // If Length != 0:
84 24) int LineNumber; // for e.g. debugging scripts
85 28) char* Text; // null-terminated UTF8
86 }
87 
88 */
89 
90 #ifndef INCLUDED_XEROXMB
91 #define INCLUDED_XEROXMB
92 
93 // Define to use a std::map for name lookups rather than a linear search.
94 // (The map is usually slower.)
95 //#define XERO_USEMAP
96 
97 #include <string>
98 
99 #ifdef XERO_USEMAP
100 # include <map>
101 #endif
102 
103 #include "ps/CStr.h"
104 
105 // File headers, to make sure it doesn't try loading anything other than an XMB
106 extern const char* HeaderMagicStr;
107 extern const char* UnfinishedHeaderMagicStr;
108 extern const u32 XMBVersion;
109 
110 class XMBElement;
111 class XMBElementList;
112 class XMBAttributeList;
113 
114 
115 class XMBFile
116 {
117 public:
118 
119  XMBFile() : m_Pointer(NULL) {}
120 
121  // Initialise from the contents of an XMB file.
122  // FileData must remain allocated and unchanged while
123  // the XMBFile is being used.
124  // @return indication of success; main cause for failure is attempting to
125  // load a partially valid XMB file (e.g. if the game was interrupted
126  // while writing it), which we detect by checking the magic string.
127  // It also fails when trying to load an XMB file with a different version.
128  bool Initialise(const char* FileData);
129 
130  // Returns the root element
131  XMBElement GetRoot() const;
132 
133 
134  // Returns internal ID for a given element/attribute string.
135  int GetElementID(const char* Name) const;
136  int GetAttributeID(const char* Name) const;
137 
138  // For lazy people (e.g. me) when speed isn't vital:
139 
140  // Returns element/attribute string for a given internal ID
141  std::string GetElementString(const int ID) const;
142  std::string GetAttributeString(const int ID) const;
143 
144 private:
145  const char* m_Pointer;
146 
147 #ifdef XERO_USEMAP
148  std::map<std::string, int> m_ElementNames;
149  std::map<std::string, int> m_AttributeNames;
150 #else
153  const char* m_ElementPointer;
154  const char* m_AttributePointer;
155 #endif
156 
157  std::string ReadZStr8();
158 };
159 
161 {
162 public:
164  : m_Pointer(0) {}
165 
166  XMBElement(const char* offset)
167  : m_Pointer(offset) {}
168 
169  int GetNodeName() const;
170  XMBElementList GetChildNodes() const;
171  XMBAttributeList GetAttributes() const;
172  CStr8 GetText() const;
173  // Returns the line number of the text within this element,
174  // or -1 if there is no text
175  int GetLineNumber() const;
176 
177 private:
178  // Pointer to the start of the node
179  const char* m_Pointer;
180 };
181 
183 {
184 public:
185  XMBElementList(const char* offset, size_t count, const char* endoffset)
186  : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
187 
188  // Get first element in list with the given name.
189  // Performance is linear in the number of elements in the list.
190  XMBElement GetFirstNamedItem(const int ElementName) const;
191 
192  // Linear in the number of elements in the list
193  XMBElement operator[](size_t id); // returns Children[id]
194 
195  class iterator
196  {
197  public:
198  typedef ptrdiff_t difference_type;
200  typedef XMBElement reference; // Because we need to construct the object
201  typedef XMBElement pointer; // Because we need to construct the object
202  typedef std::forward_iterator_tag iterator_category;
203 
204  iterator(size_t size, const char* ptr, const char* endptr = NULL)
205  : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr), m_Pointer(ptr) {}
206  XMBElement operator*() const { return XMBElement(m_CurPointer); }
207  XMBElement operator->() const { return **this; }
208  iterator& operator++();
209 
210  bool operator==(const iterator& rhs) const
211  {
212  return m_Size == rhs.m_Size &&
213  m_CurItemID == rhs.m_CurItemID &&
214  m_CurPointer == rhs.m_CurPointer;
215  }
216  bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
217  private:
218  size_t m_Size;
219  size_t m_CurItemID;
220  const char* m_CurPointer;
221  const char* m_Pointer;
222  };
223  iterator begin() { return iterator(m_Size, m_Pointer); }
224  iterator end() { return iterator(m_Size, m_Pointer, m_EndPointer); }
225 
226  size_t size() const { return m_Size; }
227  bool empty() const { return m_Size == 0; }
228 
229 private:
230  size_t m_Size;
231 
232  const char* m_Pointer;
233 
234  // For optimised sequential access:
235  size_t m_CurItemID;
236  const char* m_CurPointer;
237 
238  const char* m_EndPointer;
239 };
240 
241 
243 {
245  XMBAttribute(int name, const CStr8& value)
246  : Name(name), Value(value) {};
247 
248  int Name;
249  CStr8 Value; // UTF-8 encoded
250 };
251 
253 {
254 public:
255  XMBAttributeList(const char* offset, size_t count, const char* endoffset)
256  : m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
257 
258  // Get the attribute value directly
259  CStr8 GetNamedItem(const int AttributeName) const;
260 
261  // Linear in the number of elements in the list
262  XMBAttribute operator[](size_t id); // returns Children[id]
263 
264  class iterator
265  {
266  public:
267  typedef ptrdiff_t difference_type;
269  typedef XMBAttribute reference; // Because we need to construct the object
270  typedef XMBAttribute pointer; // Because we need to construct the object
271  typedef std::forward_iterator_tag iterator_category;
272 
273  iterator(size_t size, const char* ptr, const char* endptr = NULL)
274  : m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr), m_Pointer(ptr) {}
275  XMBAttribute operator*() const;
276  XMBAttribute operator->() const { return **this; }
277  iterator& operator++();
278 
279  bool operator==(const iterator& rhs) const
280  {
281  return m_Size == rhs.m_Size &&
282  m_CurItemID == rhs.m_CurItemID &&
283  m_CurPointer == rhs.m_CurPointer;
284  }
285  bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
286  private:
287  size_t m_Size;
288  size_t m_CurItemID;
289  const char* m_CurPointer;
290  const char* m_Pointer;
291  };
292  iterator begin() const { return iterator(m_Size, m_Pointer); }
293  iterator end() const { return iterator(m_Size, m_Pointer, m_EndPointer); }
294 
295  size_t size() const { return m_Size; }
296  bool empty() const { return m_Size == 0; }
297 
298 private:
299  size_t m_Size;
300 
301  // Pointer to start of attribute list
302  const char* m_Pointer;
303 
304  // For optimised sequential access:
305  size_t m_CurItemID;
306  const char* m_CurPointer;
307 
308  const char* m_EndPointer;
309 };
310 
311 #endif // INCLUDED_XEROXMB
const char * UnfinishedHeaderMagicStr
Definition: XeroXMB.cpp:26
const char * m_EndPointer
Definition: XeroXMB.h:308
const char * m_Pointer
Definition: XeroXMB.h:179
int Name
Definition: XeroXMB.h:246
const char * m_CurPointer
Definition: XeroXMB.h:289
size_t m_Size
Definition: XeroXMB.h:218
Definition: XeroXMB.h:252
ptrdiff_t difference_type
Definition: XeroXMB.h:267
const char * m_Pointer
Definition: XeroXMB.h:302
const u32 XMBVersion
Definition: XeroXMB.cpp:29
int m_AttributeNameCount
Definition: XeroXMB.h:152
size_t size() const
Definition: XeroXMB.h:295
size_t m_CurItemID
Definition: XeroXMB.h:288
int GetElementID(const char *Name) const
Definition: XeroXMB.cpp:117
const char * m_Pointer
Definition: XeroXMB.h:221
XMBElement operator->() const
Definition: XeroXMB.h:207
size_t m_Size
Definition: XeroXMB.h:230
iterator begin()
Definition: XeroXMB.h:223
Definition: XeroXMB.h:182
Definition: XeroXMB.h:160
XMBAttributeList(const char *offset, size_t count, const char *endoffset)
Definition: XeroXMB.h:255
iterator(size_t size, const char *ptr, const char *endptr=NULL)
Definition: XeroXMB.h:204
const char * HeaderMagicStr
Definition: XeroXMB.cpp:25
XMBElement(const char *offset)
Definition: XeroXMB.h:166
iterator(size_t size, const char *ptr, const char *endptr=NULL)
Definition: XeroXMB.h:273
XMBAttribute pointer
Definition: XeroXMB.h:270
bool empty() const
Definition: XeroXMB.h:227
bool operator==(const iterator &rhs) const
Definition: XeroXMB.h:210
XMBAttribute operator->() const
Definition: XeroXMB.h:276
bool operator==(const iterator &rhs) const
Definition: XeroXMB.h:279
bool operator!=(const iterator &rhs) const
Definition: XeroXMB.h:216
bool Initialise(const char *FileData)
Definition: XeroXMB.cpp:39
uint32_t u32
Definition: types.h:39
Definition: XeroXMB.h:195
const char * m_Pointer
Definition: XeroXMB.h:232
Config::Value_type Value
Definition: json_spirit_value.h:181
XMBElement reference
Definition: XeroXMB.h:200
std::string ReadZStr8()
Definition: XeroXMB.cpp:88
XMBElement operator*() const
Definition: XeroXMB.h:206
size_t m_CurItemID
Definition: XeroXMB.h:219
XMBElement pointer
Definition: XeroXMB.h:201
const char * m_CurPointer
Definition: XeroXMB.h:236
Definition: XeroXMB.h:242
std::forward_iterator_tag iterator_category
Definition: XeroXMB.h:202
XMBFile()
Definition: XeroXMB.h:119
const char * m_EndPointer
Definition: XeroXMB.h:238
bool empty() const
Definition: XeroXMB.h:296
XMBElement()
Definition: XeroXMB.h:163
std::string GetElementString(const int ID) const
Definition: XeroXMB.cpp:161
Definition: XeroXMB.h:115
const char * m_ElementPointer
Definition: XeroXMB.h:153
CStr8 Value
Definition: XeroXMB.h:249
const char * m_CurPointer
Definition: XeroXMB.h:220
XMBAttribute()
Definition: XeroXMB.h:244
XMBElement GetRoot() const
Definition: XeroXMB.cpp:97
iterator end() const
Definition: XeroXMB.h:293
Definition: XeroXMB.h:264
XMBAttribute reference
Definition: XeroXMB.h:269
XMBElement value_type
Definition: XeroXMB.h:199
size_t m_CurItemID
Definition: XeroXMB.h:235
const char * m_CurPointer
Definition: XeroXMB.h:306
size_t m_CurItemID
Definition: XeroXMB.h:305
const char * m_Pointer
Definition: XeroXMB.h:145
const char * m_AttributePointer
Definition: XeroXMB.h:154
int GetAttributeID(const char *Name) const
Definition: XeroXMB.cpp:137
size_t size() const
Definition: XeroXMB.h:226
std::string GetAttributeString(const int ID) const
Definition: XeroXMB.cpp:169
XMBAttribute(int name, const CStr8 &value)
Definition: XeroXMB.h:245
int m_ElementNameCount
Definition: XeroXMB.h:151
iterator begin() const
Definition: XeroXMB.h:292
XMBAttribute value_type
Definition: XeroXMB.h:268
iterator end()
Definition: XeroXMB.h:224
std::forward_iterator_tag iterator_category
Definition: XeroXMB.h:271
size_t m_Size
Definition: XeroXMB.h:287
const char * m_Pointer
Definition: XeroXMB.h:290
XMBElementList(const char *offset, size_t count, const char *endoffset)
Definition: XeroXMB.h:185
bool operator!=(const iterator &rhs) const
Definition: XeroXMB.h:285
size_t m_Size
Definition: XeroXMB.h:299
ptrdiff_t difference_type
Definition: XeroXMB.h:198