Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
XeroXMB.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011 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 "precompiled.h"
19 
20 #include "Xeromyces.h"
21 
22 #include "lib/byte_order.h" // FOURCC_LE
23 #include "ps/utf16string.h"
24 
25 // external linkage (also used by Xeromyces.cpp)
26 const char* HeaderMagicStr = "XMB0";
27 const char* UnfinishedHeaderMagicStr = "XMBu";
28 
29 // Warning: May contain traces of pointer abuse
30 
31 bool XMBFile::Initialise(const char* FileData)
32 {
33  m_Pointer = FileData;
34  char Header[5] = { 0 };
35  strncpy_s(Header, 5, m_Pointer, 4);
36  m_Pointer += 4;
37  // (c.f. @return documentation of this function)
38  if(!strcmp(Header, UnfinishedHeaderMagicStr))
39  return false;
40  ENSURE(!strcmp(Header, HeaderMagicStr) && "Invalid XMB header!");
41 
42  int i;
43 
44  // FIXME Check that m_Pointer doesn't end up past the end of the buffer
45  // (it shouldn't be all that dangerous since we're only doing read-only
46  // access, but it might crash on an invalid file, reading a couple of
47  // billion random element names from RAM)
48 
49 #ifdef XERO_USEMAP
50  // Build a std::map of all the names->ids
51  u32 ElementNameCount = *(u32*)m_Pointer; m_Pointer += 4;
52  for (i = 0; i < ElementNameCount; ++i)
53  m_ElementNames[ReadZStrA()] = i;
54 
55  u32 AttributeNameCount = *(u32*)m_Pointer; m_Pointer += 4;
56  for (i = 0; i < AttributeNameCount; ++i)
57  m_AttributeNames[ReadZStrA()] = i;
58 #else
59  // Ignore all the names for now, and skip over them
60  // (remembering the position of the first)
61  m_ElementNameCount = *(int*)m_Pointer; m_Pointer += 4;
63  for (i = 0; i < m_ElementNameCount; ++i)
64  m_Pointer += 4 + *(int*)m_Pointer; // skip over the string
65 
68  for (i = 0; i < m_AttributeNameCount; ++i)
69  m_Pointer += 4 + *(int*)m_Pointer; // skip over the string
70 #endif
71 
72  return true; // success
73 }
74 
75 std::string XMBFile::ReadZStrA()
76 {
77  int Length = *(int*)m_Pointer;
78  m_Pointer += 4;
79  std::string String (m_Pointer); // reads up until the first NULL
80  m_Pointer += Length;
81  return String;
82 }
83 
85 {
86  return XMBElement(m_Pointer);
87 }
88 
89 
90 #ifdef XERO_USEMAP
91 
92 int XMBFile::GetElementID(const char* Name) const
93 {
94  return m_ElementNames[Name];
95 }
96 
97 int XMBFile::GetAttributeID(const char* Name) const
98 {
99  return m_AttributeNames[Name];
100 }
101 
102 #else // #ifdef XERO_USEMAP
103 
104 int XMBFile::GetElementID(const char* Name) const
105 {
106  const char* Pos = m_ElementPointer;
107 
108  int len = (int)strlen(Name)+1; // count bytes, including null terminator
109 
110  // Loop through each string to find a match
111  for (int i = 0; i < m_ElementNameCount; ++i)
112  {
113  // See if this could be the right string, checking its
114  // length and then its contents
115  if (*(int*)Pos == len && strncasecmp(Pos+4, Name, len) == 0)
116  return i;
117  // If not, jump to the next string
118  Pos += 4 + *(int*)Pos;
119  }
120  // Failed
121  return -1;
122 }
123 
124 int XMBFile::GetAttributeID(const char* Name) const
125 {
126  const char* Pos = m_AttributePointer;
127 
128  int len = (int)strlen(Name)+1; // count bytes, including null terminator
129 
130  // Loop through each string to find a match
131  for (int i = 0; i < m_AttributeNameCount; ++i)
132  {
133  // See if this could be the right string, checking its
134  // length and then its contents
135  if (*(int*)Pos == len && strncasecmp(Pos+4, Name, len) == 0)
136  return i;
137  // If not, jump to the next string
138  Pos += 4 + *(int*)Pos;
139  }
140  // Failed
141  return -1;
142 }
143 #endif // #ifdef XERO_USEMAP / #else
144 
145 
146 // Relatively inefficient, so only use when
147 // laziness overcomes the need for speed
148 std::string XMBFile::GetElementString(const int ID) const
149 {
150  const char* Pos = m_ElementPointer;
151  for (int i = 0; i < ID; ++i)
152  Pos += 4 + *(int*)Pos;
153  return std::string(Pos+4);
154 }
155 
156 std::string XMBFile::GetAttributeString(const int ID) const
157 {
158  const char* Pos = m_AttributePointer;
159  for (int i = 0; i < ID; ++i)
160  Pos += 4 + *(int*)Pos;
161  return std::string(Pos+4);
162 }
163 
164 
165 
167 {
168  if (m_Pointer == NULL)
169  return -1;
170 
171  return *(int*)(m_Pointer + 4); // == ElementName
172 }
173 
175 {
176  if (m_Pointer == NULL)
177  return XMBElementList(NULL, 0);
178 
179  return XMBElementList(
180  m_Pointer + 20 + *(int*)(m_Pointer + 16), // == Children[]
181  *(int*)(m_Pointer + 12) // == ChildCount
182  );
183 }
184 
186 {
187  if (m_Pointer == NULL)
188  return XMBAttributeList(NULL, 0);
189 
190  return XMBAttributeList(
191  m_Pointer + 24 + *(int*)(m_Pointer + 20), // == Attributes[]
192  *(int*)(m_Pointer + 8) // == AttributeCount
193  );
194 }
195 
196 CStr8 XMBElement::GetText() const
197 {
198  // Return empty string if there's no text
199  if (m_Pointer == NULL || *(int*)(m_Pointer + 20) == 0)
200  return CStr8();
201 
202  return CStrW(utf16string((utf16_t*)(m_Pointer + 28))).ToUTF8();
203 }
204 
206 {
207  // Make sure there actually was some text to record the line of
208  if (m_Pointer == NULL || *(int*)(m_Pointer + 20) == 0)
209  return -1;
210  else
211  return *(int*)(m_Pointer + 24);
212 }
213 
214 XMBElement XMBElementList::GetFirstNamedItem(const int ElementName) const
215 {
216  const char* Pos = m_Pointer;
217 
218  // Maybe not the cleverest algorithm, but it should be
219  // fast enough with half a dozen attributes:
220  for (int i = 0; i < Count; ++i)
221  {
222  int Length = *(int*)Pos;
223  int Name = *(int*)(Pos+4);
224  if (Name == ElementName)
225  return XMBElement(Pos);
226  Pos += Length;
227  }
228 
229  // Can't find element
230  return XMBElement();
231 }
232 
234 {
235  ENSURE(id >= 0 && id < Count && "Element ID out of range");
236  const char* Pos;
237 
238  // If access is sequential, don't bother scanning
239  // through all the nodes to find the next one
240  if (id == m_LastItemID+1)
241  {
242  Pos = m_LastPointer;
243  Pos += *(int*)Pos; // skip over the last node
244  }
245  else
246  {
247  Pos = m_Pointer;
248  // Skip over each preceding node
249  for (int i=0; i<id; ++i)
250  Pos += *(int*)Pos;
251  }
252  // Cache information about this node
253  m_LastItemID = id;
254  m_LastPointer = Pos;
255 
256  return XMBElement(Pos);
257 }
258 
259 CStr8 XMBAttributeList::GetNamedItem(const int AttributeName) const
260 {
261  const char* Pos = m_Pointer;
262 
263  // Maybe not the cleverest algorithm, but it should be
264  // fast enough with half a dozen attributes:
265  for (int i = 0; i < Count; ++i)
266  {
267  if (*(int*)Pos == AttributeName)
268  return CStrW(utf16string((utf16_t*)(Pos+8))).ToUTF8();
269  Pos += 8 + *(int*)(Pos+4); // Skip over the string
270  }
271 
272  // Can't find attribute
273  return CStr8();
274 }
275 
277 {
278  ENSURE(id >= 0 && id < Count && "Attribute ID out of range");
279  const char* Pos;
280 
281  // If access is sequential, don't bother scanning through
282  // all the nodes to find the right one
283  if (id == m_LastItemID+1)
284  {
285  Pos = m_LastPointer;
286  // Skip over the last attribute
287  Pos += 8 + *(int*)(Pos+4);
288  }
289  else
290  {
291  Pos = m_Pointer;
292  // Skip over each preceding attribute
293  for (int i=0; i<id; ++i)
294  Pos += 8 + *(int*)(Pos+4); // skip ID, length, and string data
295  }
296  // Cache information about this attribute
297  m_LastItemID = id;
298  m_LastPointer = Pos;
299 
300  return XMBAttribute(*(int*)Pos, CStrW(utf16string( (const utf16_t*)(Pos+8) )).ToUTF8());
301 }
const char * m_Pointer
Definition: XeroXMB.h:188
uint16_t utf16_t
Definition: utf16string.h:32
const char * m_Pointer
Definition: XeroXMB.h:245
const char * UnfinishedHeaderMagicStr
Definition: XeroXMB.cpp:27
int m_AttributeNameCount
Definition: XeroXMB.h:161
const char * HeaderMagicStr
Definition: XeroXMB.cpp:26
XMBElement GetFirstNamedItem(const int ElementName) const
Definition: XeroXMB.cpp:214
int GetElementID(const char *Name) const
Definition: XeroXMB.cpp:104
XMBAttributeList GetAttributes() const
Definition: XeroXMB.cpp:185
XMBElementList GetChildNodes() const
Definition: XeroXMB.cpp:174
int GetLineNumber() const
Definition: XeroXMB.cpp:205
const char * m_LastPointer
Definition: XeroXMB.h:215
const char * m_LastPointer
Definition: XeroXMB.h:249
std::string ReadZStrA()
Definition: XeroXMB.cpp:75
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
bool Initialise(const char *FileData)
Definition: XeroXMB.cpp:31
const char * m_Pointer
Definition: XeroXMB.h:211
CStr8 GetText() const
Definition: XeroXMB.cpp:196
XMBAttribute Item(const int id)
Definition: XeroXMB.cpp:276
CStr8 GetNamedItem(const int AttributeName) const
Definition: XeroXMB.cpp:259
std::string GetElementString(const int ID) const
Definition: XeroXMB.cpp:148
const char * m_ElementPointer
Definition: XeroXMB.h:162
std::basic_string< utf16_t, utf16_traits > utf16string
Definition: utf16string.h:109
XMBElement GetRoot() const
Definition: XeroXMB.cpp:84
#define u32
Definition: types.h:41
int strncpy_s(char *dst, size_t max_dst_chars, const char *src, size_t max_src_chars)
const char * m_Pointer
Definition: XeroXMB.h:154
const char * m_AttributePointer
Definition: XeroXMB.h:163
int m_LastItemID
Definition: XeroXMB.h:214
int GetAttributeID(const char *Name) const
Definition: XeroXMB.cpp:124
std::string GetAttributeString(const int ID) const
Definition: XeroXMB.cpp:156
XMBElement Item(const int id)
Definition: XeroXMB.cpp:233
static float Length(const SVec3 v)
Definition: mikktspace.cpp:112
int m_ElementNameCount
Definition: XeroXMB.h:160
int GetNodeName() const
Definition: XeroXMB.cpp:166