diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CXMLReaderImpl.h')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CXMLReaderImpl.h | 1640 |
1 files changed, 820 insertions, 820 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CXMLReaderImpl.h b/libraries/irrlicht-1.8/source/Irrlicht/CXMLReaderImpl.h index f87be65..0b0c8eb 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CXMLReaderImpl.h +++ b/libraries/irrlicht-1.8/source/Irrlicht/CXMLReaderImpl.h | |||
@@ -1,820 +1,820 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine" and the "irrXML" project. | 2 | // This file is part of the "Irrlicht Engine" and the "irrXML" project. |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h |
4 | 4 | ||
5 | #ifndef __ICXML_READER_IMPL_H_INCLUDED__ | 5 | #ifndef __ICXML_READER_IMPL_H_INCLUDED__ |
6 | #define __ICXML_READER_IMPL_H_INCLUDED__ | 6 | #define __ICXML_READER_IMPL_H_INCLUDED__ |
7 | 7 | ||
8 | #include "irrXML.h" | 8 | #include "irrXML.h" |
9 | #include "irrString.h" | 9 | #include "irrString.h" |
10 | #include "irrArray.h" | 10 | #include "irrArray.h" |
11 | #include "fast_atof.h" | 11 | #include "fast_atof.h" |
12 | 12 | ||
13 | #ifdef _DEBUG | 13 | #ifdef _DEBUG |
14 | #define IRR_DEBUGPRINT(x) printf((x)); | 14 | #define IRR_DEBUGPRINT(x) printf((x)); |
15 | #else // _DEBUG | 15 | #else // _DEBUG |
16 | #define IRR_DEBUGPRINT(x) | 16 | #define IRR_DEBUGPRINT(x) |
17 | #endif // _DEBUG | 17 | #endif // _DEBUG |
18 | 18 | ||
19 | 19 | ||
20 | namespace irr | 20 | namespace irr |
21 | { | 21 | { |
22 | namespace io | 22 | namespace io |
23 | { | 23 | { |
24 | 24 | ||
25 | 25 | ||
26 | //! implementation of the IrrXMLReader | 26 | //! implementation of the IrrXMLReader |
27 | template<class char_type, class superclass> | 27 | template<class char_type, class superclass> |
28 | class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass> | 28 | class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass> |
29 | { | 29 | { |
30 | public: | 30 | public: |
31 | 31 | ||
32 | //! Constructor | 32 | //! Constructor |
33 | CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) | 33 | CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) |
34 | : IgnoreWhitespaceText(true), TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), | 34 | : IgnoreWhitespaceText(true), TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), |
35 | SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII), IsEmptyElement(false) | 35 | SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII), IsEmptyElement(false) |
36 | { | 36 | { |
37 | if (!callback) | 37 | if (!callback) |
38 | return; | 38 | return; |
39 | 39 | ||
40 | storeTargetFormat(); | 40 | storeTargetFormat(); |
41 | 41 | ||
42 | // read whole xml file | 42 | // read whole xml file |
43 | 43 | ||
44 | readFile(callback); | 44 | readFile(callback); |
45 | 45 | ||
46 | // clean up | 46 | // clean up |
47 | 47 | ||
48 | if (deleteCallBack) | 48 | if (deleteCallBack) |
49 | delete callback; | 49 | delete callback; |
50 | 50 | ||
51 | // create list with special characters | 51 | // create list with special characters |
52 | 52 | ||
53 | createSpecialCharacterList(); | 53 | createSpecialCharacterList(); |
54 | 54 | ||
55 | // set pointer to text begin | 55 | // set pointer to text begin |
56 | P = TextBegin; | 56 | P = TextBegin; |
57 | } | 57 | } |
58 | 58 | ||
59 | 59 | ||
60 | //! Destructor | 60 | //! Destructor |
61 | virtual ~CXMLReaderImpl() | 61 | virtual ~CXMLReaderImpl() |
62 | { | 62 | { |
63 | delete [] TextData; | 63 | delete [] TextData; |
64 | } | 64 | } |
65 | 65 | ||
66 | 66 | ||
67 | //! Reads forward to the next xml node. | 67 | //! Reads forward to the next xml node. |
68 | //! \return Returns false, if there was no further node. | 68 | //! \return Returns false, if there was no further node. |
69 | virtual bool read() | 69 | virtual bool read() |
70 | { | 70 | { |
71 | // if not end reached, parse the node | 71 | // if not end reached, parse the node |
72 | if (P && ((unsigned int)(P - TextBegin) < TextSize - 1) && (*P != 0)) | 72 | if (P && ((unsigned int)(P - TextBegin) < TextSize - 1) && (*P != 0)) |
73 | { | 73 | { |
74 | return parseCurrentNode(); | 74 | return parseCurrentNode(); |
75 | } | 75 | } |
76 | 76 | ||
77 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | 77 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; |
78 | return false; | 78 | return false; |
79 | } | 79 | } |
80 | 80 | ||
81 | 81 | ||
82 | //! Returns the type of the current XML node. | 82 | //! Returns the type of the current XML node. |
83 | virtual EXML_NODE getNodeType() const | 83 | virtual EXML_NODE getNodeType() const |
84 | { | 84 | { |
85 | return CurrentNodeType; | 85 | return CurrentNodeType; |
86 | } | 86 | } |
87 | 87 | ||
88 | 88 | ||
89 | //! Returns attribute count of the current XML node. | 89 | //! Returns attribute count of the current XML node. |
90 | virtual unsigned int getAttributeCount() const | 90 | virtual unsigned int getAttributeCount() const |
91 | { | 91 | { |
92 | return Attributes.size(); | 92 | return Attributes.size(); |
93 | } | 93 | } |
94 | 94 | ||
95 | 95 | ||
96 | //! Returns name of an attribute. | 96 | //! Returns name of an attribute. |
97 | virtual const char_type* getAttributeName(int idx) const | 97 | virtual const char_type* getAttributeName(int idx) const |
98 | { | 98 | { |
99 | if ((u32)idx >= Attributes.size()) | 99 | if ((u32)idx >= Attributes.size()) |
100 | return 0; | 100 | return 0; |
101 | 101 | ||
102 | return Attributes[idx].Name.c_str(); | 102 | return Attributes[idx].Name.c_str(); |
103 | } | 103 | } |
104 | 104 | ||
105 | 105 | ||
106 | //! Returns the value of an attribute. | 106 | //! Returns the value of an attribute. |
107 | virtual const char_type* getAttributeValue(int idx) const | 107 | virtual const char_type* getAttributeValue(int idx) const |
108 | { | 108 | { |
109 | if ((unsigned int)idx >= Attributes.size()) | 109 | if ((unsigned int)idx >= Attributes.size()) |
110 | return 0; | 110 | return 0; |
111 | 111 | ||
112 | return Attributes[idx].Value.c_str(); | 112 | return Attributes[idx].Value.c_str(); |
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
116 | //! Returns the value of an attribute. | 116 | //! Returns the value of an attribute. |
117 | virtual const char_type* getAttributeValue(const char_type* name) const | 117 | virtual const char_type* getAttributeValue(const char_type* name) const |
118 | { | 118 | { |
119 | const SAttribute* attr = getAttributeByName(name); | 119 | const SAttribute* attr = getAttributeByName(name); |
120 | if (!attr) | 120 | if (!attr) |
121 | return 0; | 121 | return 0; |
122 | 122 | ||
123 | return attr->Value.c_str(); | 123 | return attr->Value.c_str(); |
124 | } | 124 | } |
125 | 125 | ||
126 | 126 | ||
127 | //! Returns the value of an attribute | 127 | //! Returns the value of an attribute |
128 | virtual const char_type* getAttributeValueSafe(const char_type* name) const | 128 | virtual const char_type* getAttributeValueSafe(const char_type* name) const |
129 | { | 129 | { |
130 | const SAttribute* attr = getAttributeByName(name); | 130 | const SAttribute* attr = getAttributeByName(name); |
131 | if (!attr) | 131 | if (!attr) |
132 | return EmptyString.c_str(); | 132 | return EmptyString.c_str(); |
133 | 133 | ||
134 | return attr->Value.c_str(); | 134 | return attr->Value.c_str(); |
135 | } | 135 | } |
136 | 136 | ||
137 | 137 | ||
138 | 138 | ||
139 | //! Returns the value of an attribute as integer. | 139 | //! Returns the value of an attribute as integer. |
140 | int getAttributeValueAsInt(const char_type* name) const | 140 | int getAttributeValueAsInt(const char_type* name) const |
141 | { | 141 | { |
142 | const SAttribute* attr = getAttributeByName(name); | 142 | const SAttribute* attr = getAttributeByName(name); |
143 | if (!attr) | 143 | if (!attr) |
144 | return 0; | 144 | return 0; |
145 | 145 | ||
146 | core::stringc c(attr->Value.c_str()); | 146 | core::stringc c(attr->Value.c_str()); |
147 | return core::strtol10(c.c_str()); | 147 | return core::strtol10(c.c_str()); |
148 | } | 148 | } |
149 | 149 | ||
150 | 150 | ||
151 | //! Returns the value of an attribute as integer. | 151 | //! Returns the value of an attribute as integer. |
152 | int getAttributeValueAsInt(int idx) const | 152 | int getAttributeValueAsInt(int idx) const |
153 | { | 153 | { |
154 | const char_type* attrvalue = getAttributeValue(idx); | 154 | const char_type* attrvalue = getAttributeValue(idx); |
155 | if (!attrvalue) | 155 | if (!attrvalue) |
156 | return 0; | 156 | return 0; |
157 | 157 | ||
158 | core::stringc c(attrvalue); | 158 | core::stringc c(attrvalue); |
159 | return core::strtol10(c.c_str()); | 159 | return core::strtol10(c.c_str()); |
160 | } | 160 | } |
161 | 161 | ||
162 | 162 | ||
163 | //! Returns the value of an attribute as float. | 163 | //! Returns the value of an attribute as float. |
164 | float getAttributeValueAsFloat(const char_type* name) const | 164 | float getAttributeValueAsFloat(const char_type* name) const |
165 | { | 165 | { |
166 | const SAttribute* attr = getAttributeByName(name); | 166 | const SAttribute* attr = getAttributeByName(name); |
167 | if (!attr) | 167 | if (!attr) |
168 | return 0; | 168 | return 0; |
169 | 169 | ||
170 | core::stringc c = attr->Value.c_str(); | 170 | core::stringc c = attr->Value.c_str(); |
171 | return core::fast_atof(c.c_str()); | 171 | return core::fast_atof(c.c_str()); |
172 | } | 172 | } |
173 | 173 | ||
174 | 174 | ||
175 | //! Returns the value of an attribute as float. | 175 | //! Returns the value of an attribute as float. |
176 | float getAttributeValueAsFloat(int idx) const | 176 | float getAttributeValueAsFloat(int idx) const |
177 | { | 177 | { |
178 | const char_type* attrvalue = getAttributeValue(idx); | 178 | const char_type* attrvalue = getAttributeValue(idx); |
179 | if (!attrvalue) | 179 | if (!attrvalue) |
180 | return 0; | 180 | return 0; |
181 | 181 | ||
182 | core::stringc c = attrvalue; | 182 | core::stringc c = attrvalue; |
183 | return core::fast_atof(c.c_str()); | 183 | return core::fast_atof(c.c_str()); |
184 | } | 184 | } |
185 | 185 | ||
186 | 186 | ||
187 | //! Returns the name of the current node. | 187 | //! Returns the name of the current node. |
188 | virtual const char_type* getNodeName() const | 188 | virtual const char_type* getNodeName() const |
189 | { | 189 | { |
190 | return NodeName.c_str(); | 190 | return NodeName.c_str(); |
191 | } | 191 | } |
192 | 192 | ||
193 | 193 | ||
194 | //! Returns data of the current node. | 194 | //! Returns data of the current node. |
195 | virtual const char_type* getNodeData() const | 195 | virtual const char_type* getNodeData() const |
196 | { | 196 | { |
197 | return NodeName.c_str(); | 197 | return NodeName.c_str(); |
198 | } | 198 | } |
199 | 199 | ||
200 | 200 | ||
201 | //! Returns if an element is an empty element, like <foo /> | 201 | //! Returns if an element is an empty element, like <foo /> |
202 | virtual bool isEmptyElement() const | 202 | virtual bool isEmptyElement() const |
203 | { | 203 | { |
204 | return IsEmptyElement; | 204 | return IsEmptyElement; |
205 | } | 205 | } |
206 | 206 | ||
207 | //! Returns format of the source xml file. | 207 | //! Returns format of the source xml file. |
208 | virtual ETEXT_FORMAT getSourceFormat() const | 208 | virtual ETEXT_FORMAT getSourceFormat() const |
209 | { | 209 | { |
210 | return SourceFormat; | 210 | return SourceFormat; |
211 | } | 211 | } |
212 | 212 | ||
213 | //! Returns format of the strings returned by the parser. | 213 | //! Returns format of the strings returned by the parser. |
214 | virtual ETEXT_FORMAT getParserFormat() const | 214 | virtual ETEXT_FORMAT getParserFormat() const |
215 | { | 215 | { |
216 | return TargetFormat; | 216 | return TargetFormat; |
217 | } | 217 | } |
218 | 218 | ||
219 | private: | 219 | private: |
220 | 220 | ||
221 | // Reads the current xml node | 221 | // Reads the current xml node |
222 | // return false if no further node is found | 222 | // return false if no further node is found |
223 | bool parseCurrentNode() | 223 | bool parseCurrentNode() |
224 | { | 224 | { |
225 | char_type* start = P; | 225 | char_type* start = P; |
226 | 226 | ||
227 | // more forward until '<' found | 227 | // more forward until '<' found |
228 | while(*P != L'<' && *P) | 228 | while(*P != L'<' && *P) |
229 | ++P; | 229 | ++P; |
230 | 230 | ||
231 | // not a node, so return false | 231 | // not a node, so return false |
232 | if (!*P) | 232 | if (!*P) |
233 | return false; | 233 | return false; |
234 | 234 | ||
235 | if (P - start > 0) | 235 | if (P - start > 0) |
236 | { | 236 | { |
237 | // we found some text, store it | 237 | // we found some text, store it |
238 | if (setText(start, P)) | 238 | if (setText(start, P)) |
239 | return true; | 239 | return true; |
240 | } | 240 | } |
241 | 241 | ||
242 | ++P; | 242 | ++P; |
243 | 243 | ||
244 | // based on current token, parse and report next element | 244 | // based on current token, parse and report next element |
245 | switch(*P) | 245 | switch(*P) |
246 | { | 246 | { |
247 | case L'/': | 247 | case L'/': |
248 | parseClosingXMLElement(); | 248 | parseClosingXMLElement(); |
249 | break; | 249 | break; |
250 | case L'?': | 250 | case L'?': |
251 | ignoreDefinition(); | 251 | ignoreDefinition(); |
252 | break; | 252 | break; |
253 | case L'!': | 253 | case L'!': |
254 | if (!parseCDATA()) | 254 | if (!parseCDATA()) |
255 | parseComment(); | 255 | parseComment(); |
256 | break; | 256 | break; |
257 | default: | 257 | default: |
258 | parseOpeningXMLElement(); | 258 | parseOpeningXMLElement(); |
259 | break; | 259 | break; |
260 | } | 260 | } |
261 | return true; | 261 | return true; |
262 | } | 262 | } |
263 | 263 | ||
264 | 264 | ||
265 | //! sets the state that text was found. Returns true if set should be set | 265 | //! sets the state that text was found. Returns true if set should be set |
266 | bool setText(char_type* start, char_type* end) | 266 | bool setText(char_type* start, char_type* end) |
267 | { | 267 | { |
268 | // By default xml preserves all whitespace. But Irrlicht dropped some whitespace by default | 268 | // By default xml preserves all whitespace. But Irrlicht dropped some whitespace by default |
269 | // in the past which did lead to OS dependent behavior. We just ignore all whitespace for now | 269 | // in the past which did lead to OS dependent behavior. We just ignore all whitespace for now |
270 | // as it's the closest to fixing behavior without breaking downward compatibility too much. | 270 | // as it's the closest to fixing behavior without breaking downward compatibility too much. |
271 | if ( IgnoreWhitespaceText ) | 271 | if ( IgnoreWhitespaceText ) |
272 | { | 272 | { |
273 | char_type* p = start; | 273 | char_type* p = start; |
274 | for(; p != end; ++p) | 274 | for(; p != end; ++p) |
275 | if (!isWhiteSpace(*p)) | 275 | if (!isWhiteSpace(*p)) |
276 | break; | 276 | break; |
277 | 277 | ||
278 | if (p == end) | 278 | if (p == end) |
279 | return false; | 279 | return false; |
280 | } | 280 | } |
281 | 281 | ||
282 | // set current text to the parsed text, and replace xml special characters | 282 | // set current text to the parsed text, and replace xml special characters |
283 | core::string<char_type> s(start, (int)(end - start)); | 283 | core::string<char_type> s(start, (int)(end - start)); |
284 | NodeName = replaceSpecialCharacters(s); | 284 | NodeName = replaceSpecialCharacters(s); |
285 | 285 | ||
286 | // current XML node type is text | 286 | // current XML node type is text |
287 | CurrentNodeType = EXN_TEXT; | 287 | CurrentNodeType = EXN_TEXT; |
288 | 288 | ||
289 | return true; | 289 | return true; |
290 | } | 290 | } |
291 | 291 | ||
292 | 292 | ||
293 | 293 | ||
294 | //! ignores an xml definition like <?xml something /> | 294 | //! ignores an xml definition like <?xml something /> |
295 | void ignoreDefinition() | 295 | void ignoreDefinition() |
296 | { | 296 | { |
297 | CurrentNodeType = EXN_UNKNOWN; | 297 | CurrentNodeType = EXN_UNKNOWN; |
298 | 298 | ||
299 | // move until end marked with '>' reached | 299 | // move until end marked with '>' reached |
300 | while(*P != L'>') | 300 | while(*P != L'>') |
301 | ++P; | 301 | ++P; |
302 | 302 | ||
303 | ++P; | 303 | ++P; |
304 | } | 304 | } |
305 | 305 | ||
306 | 306 | ||
307 | //! parses a comment | 307 | //! parses a comment |
308 | void parseComment() | 308 | void parseComment() |
309 | { | 309 | { |
310 | CurrentNodeType = EXN_COMMENT; | 310 | CurrentNodeType = EXN_COMMENT; |
311 | P += 1; | 311 | P += 1; |
312 | 312 | ||
313 | char_type *pCommentBegin = P; | 313 | char_type *pCommentBegin = P; |
314 | 314 | ||
315 | int count = 1; | 315 | int count = 1; |
316 | 316 | ||
317 | // move until end of comment reached | 317 | // move until end of comment reached |
318 | while(count) | 318 | while(count) |
319 | { | 319 | { |
320 | if (*P == L'>') | 320 | if (*P == L'>') |
321 | --count; | 321 | --count; |
322 | else | 322 | else |
323 | if (*P == L'<') | 323 | if (*P == L'<') |
324 | ++count; | 324 | ++count; |
325 | 325 | ||
326 | ++P; | 326 | ++P; |
327 | } | 327 | } |
328 | 328 | ||
329 | P -= 3; | 329 | P -= 3; |
330 | NodeName = core::string<char_type>(pCommentBegin+2, (int)(P - pCommentBegin-2)); | 330 | NodeName = core::string<char_type>(pCommentBegin+2, (int)(P - pCommentBegin-2)); |
331 | P += 3; | 331 | P += 3; |
332 | } | 332 | } |
333 | 333 | ||
334 | 334 | ||
335 | //! parses an opening xml element and reads attributes | 335 | //! parses an opening xml element and reads attributes |
336 | void parseOpeningXMLElement() | 336 | void parseOpeningXMLElement() |
337 | { | 337 | { |
338 | CurrentNodeType = EXN_ELEMENT; | 338 | CurrentNodeType = EXN_ELEMENT; |
339 | IsEmptyElement = false; | 339 | IsEmptyElement = false; |
340 | Attributes.clear(); | 340 | Attributes.clear(); |
341 | 341 | ||
342 | // find name | 342 | // find name |
343 | const char_type* startName = P; | 343 | const char_type* startName = P; |
344 | 344 | ||
345 | // find end of element | 345 | // find end of element |
346 | while(*P != L'>' && !isWhiteSpace(*P)) | 346 | while(*P != L'>' && !isWhiteSpace(*P)) |
347 | ++P; | 347 | ++P; |
348 | 348 | ||
349 | const char_type* endName = P; | 349 | const char_type* endName = P; |
350 | 350 | ||
351 | // find Attributes | 351 | // find Attributes |
352 | while(*P != L'>') | 352 | while(*P != L'>') |
353 | { | 353 | { |
354 | if (isWhiteSpace(*P)) | 354 | if (isWhiteSpace(*P)) |
355 | ++P; | 355 | ++P; |
356 | else | 356 | else |
357 | { | 357 | { |
358 | if (*P != L'/') | 358 | if (*P != L'/') |
359 | { | 359 | { |
360 | // we've got an attribute | 360 | // we've got an attribute |
361 | 361 | ||
362 | // read the attribute names | 362 | // read the attribute names |
363 | const char_type* attributeNameBegin = P; | 363 | const char_type* attributeNameBegin = P; |
364 | 364 | ||
365 | while(!isWhiteSpace(*P) && *P != L'=') | 365 | while(!isWhiteSpace(*P) && *P != L'=') |
366 | ++P; | 366 | ++P; |
367 | 367 | ||
368 | const char_type* attributeNameEnd = P; | 368 | const char_type* attributeNameEnd = P; |
369 | ++P; | 369 | ++P; |
370 | 370 | ||
371 | // read the attribute value | 371 | // read the attribute value |
372 | // check for quotes and single quotes, thx to murphy | 372 | // check for quotes and single quotes, thx to murphy |
373 | while( (*P != L'\"') && (*P != L'\'') && *P) | 373 | while( (*P != L'\"') && (*P != L'\'') && *P) |
374 | ++P; | 374 | ++P; |
375 | 375 | ||
376 | if (!*P) // malformatted xml file | 376 | if (!*P) // malformatted xml file |
377 | return; | 377 | return; |
378 | 378 | ||
379 | const char_type attributeQuoteChar = *P; | 379 | const char_type attributeQuoteChar = *P; |
380 | 380 | ||
381 | ++P; | 381 | ++P; |
382 | const char_type* attributeValueBegin = P; | 382 | const char_type* attributeValueBegin = P; |
383 | 383 | ||
384 | while(*P != attributeQuoteChar && *P) | 384 | while(*P != attributeQuoteChar && *P) |
385 | ++P; | 385 | ++P; |
386 | 386 | ||
387 | if (!*P) // malformatted xml file | 387 | if (!*P) // malformatted xml file |
388 | return; | 388 | return; |
389 | 389 | ||
390 | const char_type* attributeValueEnd = P; | 390 | const char_type* attributeValueEnd = P; |
391 | ++P; | 391 | ++P; |
392 | 392 | ||
393 | SAttribute attr; | 393 | SAttribute attr; |
394 | attr.Name = core::string<char_type>(attributeNameBegin, | 394 | attr.Name = core::string<char_type>(attributeNameBegin, |
395 | (int)(attributeNameEnd - attributeNameBegin)); | 395 | (int)(attributeNameEnd - attributeNameBegin)); |
396 | 396 | ||
397 | core::string<char_type> s(attributeValueBegin, | 397 | core::string<char_type> s(attributeValueBegin, |
398 | (int)(attributeValueEnd - attributeValueBegin)); | 398 | (int)(attributeValueEnd - attributeValueBegin)); |
399 | 399 | ||
400 | attr.Value = replaceSpecialCharacters(s); | 400 | attr.Value = replaceSpecialCharacters(s); |
401 | Attributes.push_back(attr); | 401 | Attributes.push_back(attr); |
402 | } | 402 | } |
403 | else | 403 | else |
404 | { | 404 | { |
405 | // tag is closed directly | 405 | // tag is closed directly |
406 | ++P; | 406 | ++P; |
407 | IsEmptyElement = true; | 407 | IsEmptyElement = true; |
408 | break; | 408 | break; |
409 | } | 409 | } |
410 | } | 410 | } |
411 | } | 411 | } |
412 | 412 | ||
413 | // check if this tag is closing directly | 413 | // check if this tag is closing directly |
414 | if (endName > startName && *(endName-1) == L'/') | 414 | if (endName > startName && *(endName-1) == L'/') |
415 | { | 415 | { |
416 | // directly closing tag | 416 | // directly closing tag |
417 | IsEmptyElement = true; | 417 | IsEmptyElement = true; |
418 | endName--; | 418 | endName--; |
419 | } | 419 | } |
420 | 420 | ||
421 | NodeName = core::string<char_type>(startName, (int)(endName - startName)); | 421 | NodeName = core::string<char_type>(startName, (int)(endName - startName)); |
422 | 422 | ||
423 | ++P; | 423 | ++P; |
424 | } | 424 | } |
425 | 425 | ||
426 | 426 | ||
427 | //! parses an closing xml tag | 427 | //! parses an closing xml tag |
428 | void parseClosingXMLElement() | 428 | void parseClosingXMLElement() |
429 | { | 429 | { |
430 | CurrentNodeType = EXN_ELEMENT_END; | 430 | CurrentNodeType = EXN_ELEMENT_END; |
431 | IsEmptyElement = false; | 431 | IsEmptyElement = false; |
432 | Attributes.clear(); | 432 | Attributes.clear(); |
433 | 433 | ||
434 | ++P; | 434 | ++P; |
435 | const char_type* pBeginClose = P; | 435 | const char_type* pBeginClose = P; |
436 | 436 | ||
437 | while(*P != L'>') | 437 | while(*P != L'>') |
438 | ++P; | 438 | ++P; |
439 | 439 | ||
440 | NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose)); | 440 | NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose)); |
441 | ++P; | 441 | ++P; |
442 | } | 442 | } |
443 | 443 | ||
444 | //! parses a possible CDATA section, returns false if begin was not a CDATA section | 444 | //! parses a possible CDATA section, returns false if begin was not a CDATA section |
445 | bool parseCDATA() | 445 | bool parseCDATA() |
446 | { | 446 | { |
447 | if (*(P+1) != L'[') | 447 | if (*(P+1) != L'[') |
448 | return false; | 448 | return false; |
449 | 449 | ||
450 | CurrentNodeType = EXN_CDATA; | 450 | CurrentNodeType = EXN_CDATA; |
451 | 451 | ||
452 | // skip '<![CDATA[' | 452 | // skip '<![CDATA[' |
453 | int count=0; | 453 | int count=0; |
454 | while( *P && count<8 ) | 454 | while( *P && count<8 ) |
455 | { | 455 | { |
456 | ++P; | 456 | ++P; |
457 | ++count; | 457 | ++count; |
458 | } | 458 | } |
459 | 459 | ||
460 | if (!*P) | 460 | if (!*P) |
461 | return true; | 461 | return true; |
462 | 462 | ||
463 | char_type *cDataBegin = P; | 463 | char_type *cDataBegin = P; |
464 | char_type *cDataEnd = 0; | 464 | char_type *cDataEnd = 0; |
465 | 465 | ||
466 | // find end of CDATA | 466 | // find end of CDATA |
467 | while(*P && !cDataEnd) | 467 | while(*P && !cDataEnd) |
468 | { | 468 | { |
469 | if (*P == L'>' && | 469 | if (*P == L'>' && |
470 | (*(P-1) == L']') && | 470 | (*(P-1) == L']') && |
471 | (*(P-2) == L']')) | 471 | (*(P-2) == L']')) |
472 | { | 472 | { |
473 | cDataEnd = P - 2; | 473 | cDataEnd = P - 2; |
474 | } | 474 | } |
475 | 475 | ||
476 | ++P; | 476 | ++P; |
477 | } | 477 | } |
478 | 478 | ||
479 | if ( cDataEnd ) | 479 | if ( cDataEnd ) |
480 | NodeName = core::string<char_type>(cDataBegin, (int)(cDataEnd - cDataBegin)); | 480 | NodeName = core::string<char_type>(cDataBegin, (int)(cDataEnd - cDataBegin)); |
481 | else | 481 | else |
482 | NodeName = ""; | 482 | NodeName = ""; |
483 | 483 | ||
484 | return true; | 484 | return true; |
485 | } | 485 | } |
486 | 486 | ||
487 | 487 | ||
488 | // structure for storing attribute-name pairs | 488 | // structure for storing attribute-name pairs |
489 | struct SAttribute | 489 | struct SAttribute |
490 | { | 490 | { |
491 | core::string<char_type> Name; | 491 | core::string<char_type> Name; |
492 | core::string<char_type> Value; | 492 | core::string<char_type> Value; |
493 | }; | 493 | }; |
494 | 494 | ||
495 | // finds a current attribute by name, returns 0 if not found | 495 | // finds a current attribute by name, returns 0 if not found |
496 | const SAttribute* getAttributeByName(const char_type* name) const | 496 | const SAttribute* getAttributeByName(const char_type* name) const |
497 | { | 497 | { |
498 | if (!name) | 498 | if (!name) |
499 | return 0; | 499 | return 0; |
500 | 500 | ||
501 | core::string<char_type> n = name; | 501 | core::string<char_type> n = name; |
502 | 502 | ||
503 | for (int i=0; i<(int)Attributes.size(); ++i) | 503 | for (int i=0; i<(int)Attributes.size(); ++i) |
504 | if (Attributes[i].Name == n) | 504 | if (Attributes[i].Name == n) |
505 | return &Attributes[i]; | 505 | return &Attributes[i]; |
506 | 506 | ||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | // replaces xml special characters in a string and creates a new one | 510 | // replaces xml special characters in a string and creates a new one |
511 | core::string<char_type> replaceSpecialCharacters( | 511 | core::string<char_type> replaceSpecialCharacters( |
512 | core::string<char_type>& origstr) | 512 | core::string<char_type>& origstr) |
513 | { | 513 | { |
514 | int pos = origstr.findFirst(L'&'); | 514 | int pos = origstr.findFirst(L'&'); |
515 | int oldPos = 0; | 515 | int oldPos = 0; |
516 | 516 | ||
517 | if (pos == -1) | 517 | if (pos == -1) |
518 | return origstr; | 518 | return origstr; |
519 | 519 | ||
520 | core::string<char_type> newstr; | 520 | core::string<char_type> newstr; |
521 | 521 | ||
522 | while(pos != -1 && pos < (int)origstr.size()-2) | 522 | while(pos != -1 && pos < (int)origstr.size()-2) |
523 | { | 523 | { |
524 | // check if it is one of the special characters | 524 | // check if it is one of the special characters |
525 | 525 | ||
526 | int specialChar = -1; | 526 | int specialChar = -1; |
527 | for (int i=0; i<(int)SpecialCharacters.size(); ++i) | 527 | for (int i=0; i<(int)SpecialCharacters.size(); ++i) |
528 | { | 528 | { |
529 | const char_type* p = &origstr.c_str()[pos]+1; | 529 | const char_type* p = &origstr.c_str()[pos]+1; |
530 | 530 | ||
531 | if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) | 531 | if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) |
532 | { | 532 | { |
533 | specialChar = i; | 533 | specialChar = i; |
534 | break; | 534 | break; |
535 | } | 535 | } |
536 | } | 536 | } |
537 | 537 | ||
538 | if (specialChar != -1) | 538 | if (specialChar != -1) |
539 | { | 539 | { |
540 | newstr.append(origstr.subString(oldPos, pos - oldPos)); | 540 | newstr.append(origstr.subString(oldPos, pos - oldPos)); |
541 | newstr.append(SpecialCharacters[specialChar][0]); | 541 | newstr.append(SpecialCharacters[specialChar][0]); |
542 | pos += SpecialCharacters[specialChar].size(); | 542 | pos += SpecialCharacters[specialChar].size(); |
543 | } | 543 | } |
544 | else | 544 | else |
545 | { | 545 | { |
546 | newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); | 546 | newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); |
547 | pos += 1; | 547 | pos += 1; |
548 | } | 548 | } |
549 | 549 | ||
550 | // find next & | 550 | // find next & |
551 | oldPos = pos; | 551 | oldPos = pos; |
552 | pos = origstr.findNext(L'&', pos); | 552 | pos = origstr.findNext(L'&', pos); |
553 | } | 553 | } |
554 | 554 | ||
555 | if (oldPos < (int)origstr.size()-1) | 555 | if (oldPos < (int)origstr.size()-1) |
556 | newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); | 556 | newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); |
557 | 557 | ||
558 | return newstr; | 558 | return newstr; |
559 | } | 559 | } |
560 | 560 | ||
561 | 561 | ||
562 | 562 | ||
563 | //! reads the xml file and converts it into the wanted character format. | 563 | //! reads the xml file and converts it into the wanted character format. |
564 | bool readFile(IFileReadCallBack* callback) | 564 | bool readFile(IFileReadCallBack* callback) |
565 | { | 565 | { |
566 | long size = callback->getSize(); | 566 | long size = callback->getSize(); |
567 | if (size<0) | 567 | if (size<0) |
568 | return false; | 568 | return false; |
569 | size += 4; // We need four terminating 0's at the end. | 569 | size += 4; // We need four terminating 0's at the end. |
570 | // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. | 570 | // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. |
571 | 571 | ||
572 | char* data8 = new char[size]; | 572 | char* data8 = new char[size]; |
573 | 573 | ||
574 | if (!callback->read(data8, size-4)) | 574 | if (!callback->read(data8, size-4)) |
575 | { | 575 | { |
576 | delete [] data8; | 576 | delete [] data8; |
577 | return false; | 577 | return false; |
578 | } | 578 | } |
579 | 579 | ||
580 | // add zeros at end | 580 | // add zeros at end |
581 | 581 | ||
582 | memset(data8+size-4, 0, 4); | 582 | memset(data8+size-4, 0, 4); |
583 | 583 | ||
584 | char16* data16 = reinterpret_cast<char16*>(data8); | 584 | char16* data16 = reinterpret_cast<char16*>(data8); |
585 | char32* data32 = reinterpret_cast<char32*>(data8); | 585 | char32* data32 = reinterpret_cast<char32*>(data8); |
586 | 586 | ||
587 | // now we need to convert the data to the desired target format | 587 | // now we need to convert the data to the desired target format |
588 | // based on the byte order mark. | 588 | // based on the byte order mark. |
589 | 589 | ||
590 | const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; | 590 | const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; |
591 | const u16 UTF16_BE = 0xFFFE; | 591 | const u16 UTF16_BE = 0xFFFE; |
592 | const u16 UTF16_LE = 0xFEFF; | 592 | const u16 UTF16_LE = 0xFEFF; |
593 | const u32 UTF32_BE = 0xFFFE0000; | 593 | const u32 UTF32_BE = 0xFFFE0000; |
594 | const u32 UTF32_LE = 0x0000FEFF; | 594 | const u32 UTF32_LE = 0x0000FEFF; |
595 | 595 | ||
596 | // check source for all utf versions and convert to target data format | 596 | // check source for all utf versions and convert to target data format |
597 | 597 | ||
598 | if (size >= 4 && data32[0] == static_cast<char32>(UTF32_BE)) | 598 | if (size >= 4 && data32[0] == static_cast<char32>(UTF32_BE)) |
599 | { | 599 | { |
600 | // UTF-32, big endian | 600 | // UTF-32, big endian |
601 | SourceFormat = ETF_UTF32_BE; | 601 | SourceFormat = ETF_UTF32_BE; |
602 | convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header | 602 | convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header |
603 | } | 603 | } |
604 | else | 604 | else |
605 | if (size >= 4 && data32[0] == static_cast<char32>(UTF32_LE)) | 605 | if (size >= 4 && data32[0] == static_cast<char32>(UTF32_LE)) |
606 | { | 606 | { |
607 | // UTF-32, little endian | 607 | // UTF-32, little endian |
608 | SourceFormat = ETF_UTF32_LE; | 608 | SourceFormat = ETF_UTF32_LE; |
609 | convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header | 609 | convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header |
610 | } | 610 | } |
611 | else | 611 | else |
612 | if (size >= 2 && data16[0] == UTF16_BE) | 612 | if (size >= 2 && data16[0] == UTF16_BE) |
613 | { | 613 | { |
614 | // UTF-16, big endian | 614 | // UTF-16, big endian |
615 | SourceFormat = ETF_UTF16_BE; | 615 | SourceFormat = ETF_UTF16_BE; |
616 | convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header | 616 | convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header |
617 | } | 617 | } |
618 | else | 618 | else |
619 | if (size >= 2 && data16[0] == UTF16_LE) | 619 | if (size >= 2 && data16[0] == UTF16_LE) |
620 | { | 620 | { |
621 | // UTF-16, little endian | 621 | // UTF-16, little endian |
622 | SourceFormat = ETF_UTF16_LE; | 622 | SourceFormat = ETF_UTF16_LE; |
623 | convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header | 623 | convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header |
624 | } | 624 | } |
625 | else | 625 | else |
626 | if (size >= 3 && memcmp(data8,UTF8,3)==0) | 626 | if (size >= 3 && memcmp(data8,UTF8,3)==0) |
627 | { | 627 | { |
628 | // UTF-8 | 628 | // UTF-8 |
629 | SourceFormat = ETF_UTF8; | 629 | SourceFormat = ETF_UTF8; |
630 | convertTextData(data8+3, data8, size-3); // data8+3 because we need to skip the header | 630 | convertTextData(data8+3, data8, size-3); // data8+3 because we need to skip the header |
631 | } | 631 | } |
632 | else | 632 | else |
633 | { | 633 | { |
634 | // ASCII | 634 | // ASCII |
635 | SourceFormat = ETF_ASCII; | 635 | SourceFormat = ETF_ASCII; |
636 | convertTextData(data8, data8, size); | 636 | convertTextData(data8, data8, size); |
637 | } | 637 | } |
638 | 638 | ||
639 | return true; | 639 | return true; |
640 | } | 640 | } |
641 | 641 | ||
642 | 642 | ||
643 | //! converts the text file into the desired format. | 643 | //! converts the text file into the desired format. |
644 | /** \param source: begin of the text (without byte order mark) | 644 | /** \param source: begin of the text (without byte order mark) |
645 | \param pointerToStore: pointer to text data block which can be | 645 | \param pointerToStore: pointer to text data block which can be |
646 | stored or deleted based on the nesessary conversion. | 646 | stored or deleted based on the nesessary conversion. |
647 | \param sizeWithoutHeader: Text size in characters without header | 647 | \param sizeWithoutHeader: Text size in characters without header |
648 | */ | 648 | */ |
649 | template<class src_char_type> | 649 | template<class src_char_type> |
650 | void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) | 650 | void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) |
651 | { | 651 | { |
652 | // convert little to big endian if necessary | 652 | // convert little to big endian if necessary |
653 | if (sizeof(src_char_type) > 1 && | 653 | if (sizeof(src_char_type) > 1 && |
654 | isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) | 654 | isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) |
655 | convertToLittleEndian(source); | 655 | convertToLittleEndian(source); |
656 | 656 | ||
657 | // check if conversion is necessary: | 657 | // check if conversion is necessary: |
658 | if (sizeof(src_char_type) == sizeof(char_type)) | 658 | if (sizeof(src_char_type) == sizeof(char_type)) |
659 | { | 659 | { |
660 | // no need to convert | 660 | // no need to convert |
661 | TextBegin = (char_type*)source; | 661 | TextBegin = (char_type*)source; |
662 | TextData = (char_type*)pointerToStore; | 662 | TextData = (char_type*)pointerToStore; |
663 | TextSize = sizeWithoutHeader; | 663 | TextSize = sizeWithoutHeader; |
664 | } | 664 | } |
665 | else | 665 | else |
666 | { | 666 | { |
667 | // convert source into target data format. | 667 | // convert source into target data format. |
668 | // TODO: implement a real conversion. This one just | 668 | // TODO: implement a real conversion. This one just |
669 | // copies bytes. This is a problem when there are | 669 | // copies bytes. This is a problem when there are |
670 | // unicode symbols using more than one character. | 670 | // unicode symbols using more than one character. |
671 | 671 | ||
672 | TextData = new char_type[sizeWithoutHeader]; | 672 | TextData = new char_type[sizeWithoutHeader]; |
673 | 673 | ||
674 | if ( sizeof(src_char_type) == 1 ) | 674 | if ( sizeof(src_char_type) == 1 ) |
675 | { | 675 | { |
676 | // we have to cast away negative numbers or results might add the sign instead of just doing a copy | 676 | // we have to cast away negative numbers or results might add the sign instead of just doing a copy |
677 | for (int i=0; i<sizeWithoutHeader; ++i) | 677 | for (int i=0; i<sizeWithoutHeader; ++i) |
678 | { | 678 | { |
679 | TextData[i] = static_cast<char_type>(static_cast<unsigned char>(source[i])); | 679 | TextData[i] = static_cast<char_type>(static_cast<unsigned char>(source[i])); |
680 | } | 680 | } |
681 | } | 681 | } |
682 | else | 682 | else |
683 | { | 683 | { |
684 | for (int i=0; i<sizeWithoutHeader; ++i) | 684 | for (int i=0; i<sizeWithoutHeader; ++i) |
685 | TextData[i] = static_cast<char_type>(source[i]); | 685 | TextData[i] = static_cast<char_type>(source[i]); |
686 | } | 686 | } |
687 | TextBegin = TextData; | 687 | TextBegin = TextData; |
688 | TextSize = sizeWithoutHeader; | 688 | TextSize = sizeWithoutHeader; |
689 | 689 | ||
690 | // delete original data because no longer needed | 690 | // delete original data because no longer needed |
691 | delete [] pointerToStore; | 691 | delete [] pointerToStore; |
692 | } | 692 | } |
693 | } | 693 | } |
694 | 694 | ||
695 | //! converts whole text buffer to little endian | 695 | //! converts whole text buffer to little endian |
696 | template<class src_char_type> | 696 | template<class src_char_type> |
697 | void convertToLittleEndian(src_char_type* t) | 697 | void convertToLittleEndian(src_char_type* t) |
698 | { | 698 | { |
699 | if (sizeof(src_char_type) == 4) | 699 | if (sizeof(src_char_type) == 4) |
700 | { | 700 | { |
701 | // 32 bit | 701 | // 32 bit |
702 | 702 | ||
703 | while(*t) | 703 | while(*t) |
704 | { | 704 | { |
705 | *t = ((*t & 0xff000000) >> 24) | | 705 | *t = ((*t & 0xff000000) >> 24) | |
706 | ((*t & 0x00ff0000) >> 8) | | 706 | ((*t & 0x00ff0000) >> 8) | |
707 | ((*t & 0x0000ff00) << 8) | | 707 | ((*t & 0x0000ff00) << 8) | |
708 | ((*t & 0x000000ff) << 24); | 708 | ((*t & 0x000000ff) << 24); |
709 | ++t; | 709 | ++t; |
710 | } | 710 | } |
711 | } | 711 | } |
712 | else | 712 | else |
713 | { | 713 | { |
714 | // 16 bit | 714 | // 16 bit |
715 | 715 | ||
716 | while(*t) | 716 | while(*t) |
717 | { | 717 | { |
718 | *t = (*t >> 8) | (*t << 8); | 718 | *t = (*t >> 8) | (*t << 8); |
719 | ++t; | 719 | ++t; |
720 | } | 720 | } |
721 | } | 721 | } |
722 | } | 722 | } |
723 | 723 | ||
724 | //! returns if a format is little endian | 724 | //! returns if a format is little endian |
725 | inline bool isLittleEndian(ETEXT_FORMAT f) | 725 | inline bool isLittleEndian(ETEXT_FORMAT f) |
726 | { | 726 | { |
727 | return f == ETF_ASCII || | 727 | return f == ETF_ASCII || |
728 | f == ETF_UTF8 || | 728 | f == ETF_UTF8 || |
729 | f == ETF_UTF16_LE || | 729 | f == ETF_UTF16_LE || |
730 | f == ETF_UTF32_LE; | 730 | f == ETF_UTF32_LE; |
731 | } | 731 | } |
732 | 732 | ||
733 | 733 | ||
734 | //! returns true if a character is whitespace | 734 | //! returns true if a character is whitespace |
735 | inline bool isWhiteSpace(char_type c) | 735 | inline bool isWhiteSpace(char_type c) |
736 | { | 736 | { |
737 | return (c==' ' || c=='\t' || c=='\n' || c=='\r'); | 737 | return (c==' ' || c=='\t' || c=='\n' || c=='\r'); |
738 | } | 738 | } |
739 | 739 | ||
740 | 740 | ||
741 | //! generates a list with xml special characters | 741 | //! generates a list with xml special characters |
742 | void createSpecialCharacterList() | 742 | void createSpecialCharacterList() |
743 | { | 743 | { |
744 | // list of strings containing special symbols, | 744 | // list of strings containing special symbols, |
745 | // the first character is the special character, | 745 | // the first character is the special character, |
746 | // the following is the symbol string without trailing &. | 746 | // the following is the symbol string without trailing &. |
747 | 747 | ||
748 | SpecialCharacters.push_back("&"); | 748 | SpecialCharacters.push_back("&"); |
749 | SpecialCharacters.push_back("<lt;"); | 749 | SpecialCharacters.push_back("<lt;"); |
750 | SpecialCharacters.push_back(">gt;"); | 750 | SpecialCharacters.push_back(">gt;"); |
751 | SpecialCharacters.push_back("\"quot;"); | 751 | SpecialCharacters.push_back("\"quot;"); |
752 | SpecialCharacters.push_back("'apos;"); | 752 | SpecialCharacters.push_back("'apos;"); |
753 | 753 | ||
754 | } | 754 | } |
755 | 755 | ||
756 | 756 | ||
757 | //! compares the first n characters of the strings | 757 | //! compares the first n characters of the strings |
758 | bool equalsn(const char_type* str1, const char_type* str2, int len) | 758 | bool equalsn(const char_type* str1, const char_type* str2, int len) |
759 | { | 759 | { |
760 | int i; | 760 | int i; |
761 | for(i=0; str1[i] && str2[i] && i < len; ++i) | 761 | for(i=0; str1[i] && str2[i] && i < len; ++i) |
762 | if (str1[i] != str2[i]) | 762 | if (str1[i] != str2[i]) |
763 | return false; | 763 | return false; |
764 | 764 | ||
765 | // if one (or both) of the strings was smaller then they | 765 | // if one (or both) of the strings was smaller then they |
766 | // are only equal if they have the same lenght | 766 | // are only equal if they have the same lenght |
767 | return (i == len) || (str1[i] == 0 && str2[i] == 0); | 767 | return (i == len) || (str1[i] == 0 && str2[i] == 0); |
768 | } | 768 | } |
769 | 769 | ||
770 | 770 | ||
771 | //! stores the target text format | 771 | //! stores the target text format |
772 | void storeTargetFormat() | 772 | void storeTargetFormat() |
773 | { | 773 | { |
774 | // get target format. We could have done this using template specialization, | 774 | // get target format. We could have done this using template specialization, |
775 | // but VisualStudio 6 don't like it and we want to support it. | 775 | // but VisualStudio 6 don't like it and we want to support it. |
776 | 776 | ||
777 | switch(sizeof(char_type)) | 777 | switch(sizeof(char_type)) |
778 | { | 778 | { |
779 | case 1: | 779 | case 1: |
780 | TargetFormat = ETF_UTF8; | 780 | TargetFormat = ETF_UTF8; |
781 | break; | 781 | break; |
782 | case 2: | 782 | case 2: |
783 | TargetFormat = ETF_UTF16_LE; | 783 | TargetFormat = ETF_UTF16_LE; |
784 | break; | 784 | break; |
785 | case 4: | 785 | case 4: |
786 | TargetFormat = ETF_UTF32_LE; | 786 | TargetFormat = ETF_UTF32_LE; |
787 | break; | 787 | break; |
788 | default: | 788 | default: |
789 | TargetFormat = ETF_ASCII; // should never happen. | 789 | TargetFormat = ETF_ASCII; // should never happen. |
790 | } | 790 | } |
791 | } | 791 | } |
792 | 792 | ||
793 | 793 | ||
794 | // instance variables: | 794 | // instance variables: |
795 | bool IgnoreWhitespaceText; // do not return EXN_TEXT nodes for pure whitespace | 795 | bool IgnoreWhitespaceText; // do not return EXN_TEXT nodes for pure whitespace |
796 | char_type* TextData; // data block of the text file | 796 | char_type* TextData; // data block of the text file |
797 | char_type* P; // current point in text to parse | 797 | char_type* P; // current point in text to parse |
798 | char_type* TextBegin; // start of text to parse | 798 | char_type* TextBegin; // start of text to parse |
799 | unsigned int TextSize; // size of text to parse in characters, not bytes | 799 | unsigned int TextSize; // size of text to parse in characters, not bytes |
800 | 800 | ||
801 | EXML_NODE CurrentNodeType; // type of the currently parsed node | 801 | EXML_NODE CurrentNodeType; // type of the currently parsed node |
802 | ETEXT_FORMAT SourceFormat; // source format of the xml file | 802 | ETEXT_FORMAT SourceFormat; // source format of the xml file |
803 | ETEXT_FORMAT TargetFormat; // output format of this parser | 803 | ETEXT_FORMAT TargetFormat; // output format of this parser |
804 | 804 | ||
805 | core::string<char_type> NodeName; // name of the node currently in - also used for text | 805 | core::string<char_type> NodeName; // name of the node currently in - also used for text |
806 | core::string<char_type> EmptyString; // empty string to be returned by getSafe() methods | 806 | core::string<char_type> EmptyString; // empty string to be returned by getSafe() methods |
807 | 807 | ||
808 | bool IsEmptyElement; // is the currently parsed node empty? | 808 | bool IsEmptyElement; // is the currently parsed node empty? |
809 | 809 | ||
810 | core::array< core::string<char_type> > SpecialCharacters; // see createSpecialCharacterList() | 810 | core::array< core::string<char_type> > SpecialCharacters; // see createSpecialCharacterList() |
811 | 811 | ||
812 | core::array<SAttribute> Attributes; // attributes of current element | 812 | core::array<SAttribute> Attributes; // attributes of current element |
813 | 813 | ||
814 | }; // end CXMLReaderImpl | 814 | }; // end CXMLReaderImpl |
815 | 815 | ||
816 | 816 | ||
817 | } // end namespace | 817 | } // end namespace |
818 | } // end namespace | 818 | } // end namespace |
819 | 819 | ||
820 | #endif | 820 | #endif |