vrshoot
diff libs/assimp/irrXML/CXMLReaderImpl.h @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/irrXML/CXMLReaderImpl.h Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,809 @@ 1.4 +// Copyright (C) 2002-2005 Nikolaus Gebhardt 1.5 +// This file is part of the "Irrlicht Engine" and the "irrXML" project. 1.6 +// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h 1.7 + 1.8 +#ifndef __ICXML_READER_IMPL_H_INCLUDED__ 1.9 +#define __ICXML_READER_IMPL_H_INCLUDED__ 1.10 + 1.11 +#include "irrXML.h" 1.12 +#include "irrString.h" 1.13 +#include "irrArray.h" 1.14 + 1.15 +using namespace Assimp; 1.16 + 1.17 +#ifdef _DEBUG 1.18 +#define IRR_DEBUGPRINT(x) printf((x)); 1.19 +#else // _DEBUG 1.20 +#define IRR_DEBUGPRINT(x) 1.21 +#endif // _DEBUG 1.22 + 1.23 + 1.24 +namespace irr 1.25 +{ 1.26 +namespace io 1.27 +{ 1.28 + 1.29 + 1.30 +//! implementation of the IrrXMLReader 1.31 +template<class char_type, class superclass> 1.32 +class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass> 1.33 +{ 1.34 +public: 1.35 + 1.36 + //! Constructor 1.37 + CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) 1.38 + : TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), 1.39 + SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII) 1.40 + { 1.41 + if (!callback) 1.42 + return; 1.43 + 1.44 + storeTargetFormat(); 1.45 + 1.46 + // read whole xml file 1.47 + 1.48 + readFile(callback); 1.49 + 1.50 + // clean up 1.51 + 1.52 + if (deleteCallBack) 1.53 + delete callback; 1.54 + 1.55 + // create list with special characters 1.56 + 1.57 + createSpecialCharacterList(); 1.58 + 1.59 + // set pointer to text begin 1.60 + P = TextBegin; 1.61 + } 1.62 + 1.63 + 1.64 + //! Destructor 1.65 + virtual ~CXMLReaderImpl() 1.66 + { 1.67 + delete [] TextData; 1.68 + } 1.69 + 1.70 + 1.71 + //! Reads forward to the next xml node. 1.72 + //! \return Returns false, if there was no further node. 1.73 + virtual bool read() 1.74 + { 1.75 + // if not end reached, parse the node 1.76 + if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0) 1.77 + { 1.78 + parseCurrentNode(); 1.79 + return true; 1.80 + } 1.81 + 1.82 + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 1.83 + return false; 1.84 + } 1.85 + 1.86 + 1.87 + //! Returns the type of the current XML node. 1.88 + virtual EXML_NODE getNodeType() const 1.89 + { 1.90 + return CurrentNodeType; 1.91 + } 1.92 + 1.93 + 1.94 + //! Returns attribute count of the current XML node. 1.95 + virtual int getAttributeCount() const 1.96 + { 1.97 + return Attributes.size(); 1.98 + } 1.99 + 1.100 + 1.101 + //! Returns name of an attribute. 1.102 + virtual const char_type* getAttributeName(int idx) const 1.103 + { 1.104 + if (idx < 0 || idx >= (int)Attributes.size()) 1.105 + return 0; 1.106 + 1.107 + return Attributes[idx].Name.c_str(); 1.108 + } 1.109 + 1.110 + 1.111 + //! Returns the value of an attribute. 1.112 + virtual const char_type* getAttributeValue(int idx) const 1.113 + { 1.114 + if (idx < 0 || idx >= (int)Attributes.size()) 1.115 + return 0; 1.116 + 1.117 + return Attributes[idx].Value.c_str(); 1.118 + } 1.119 + 1.120 + 1.121 + //! Returns the value of an attribute. 1.122 + virtual const char_type* getAttributeValue(const char_type* name) const 1.123 + { 1.124 + const SAttribute* attr = getAttributeByName(name); 1.125 + if (!attr) 1.126 + return 0; 1.127 + 1.128 + return attr->Value.c_str(); 1.129 + } 1.130 + 1.131 + 1.132 + //! Returns the value of an attribute 1.133 + virtual const char_type* getAttributeValueSafe(const char_type* name) const 1.134 + { 1.135 + const SAttribute* attr = getAttributeByName(name); 1.136 + if (!attr) 1.137 + return EmptyString.c_str(); 1.138 + 1.139 + return attr->Value.c_str(); 1.140 + } 1.141 + 1.142 + 1.143 + 1.144 + //! Returns the value of an attribute as integer. 1.145 + int getAttributeValueAsInt(const char_type* name) const 1.146 + { 1.147 + return (int)getAttributeValueAsFloat(name); 1.148 + } 1.149 + 1.150 + 1.151 + //! Returns the value of an attribute as integer. 1.152 + int getAttributeValueAsInt(int idx) const 1.153 + { 1.154 + return (int)getAttributeValueAsFloat(idx); 1.155 + } 1.156 + 1.157 + 1.158 + //! Returns the value of an attribute as float. 1.159 + float getAttributeValueAsFloat(const char_type* name) const 1.160 + { 1.161 + const SAttribute* attr = getAttributeByName(name); 1.162 + if (!attr) 1.163 + return 0; 1.164 + 1.165 + core::stringc c = attr->Value.c_str(); 1.166 + return fast_atof(c.c_str()); 1.167 + } 1.168 + 1.169 + 1.170 + //! Returns the value of an attribute as float. 1.171 + float getAttributeValueAsFloat(int idx) const 1.172 + { 1.173 + const char_type* attrvalue = getAttributeValue(idx); 1.174 + if (!attrvalue) 1.175 + return 0; 1.176 + 1.177 + core::stringc c = attrvalue; 1.178 + return fast_atof(c.c_str()); 1.179 + } 1.180 + 1.181 + 1.182 + //! Returns the name of the current node. 1.183 + virtual const char_type* getNodeName() const 1.184 + { 1.185 + return NodeName.c_str(); 1.186 + } 1.187 + 1.188 + 1.189 + //! Returns data of the current node. 1.190 + virtual const char_type* getNodeData() const 1.191 + { 1.192 + return NodeName.c_str(); 1.193 + } 1.194 + 1.195 + 1.196 + //! Returns if an element is an empty element, like <foo /> 1.197 + virtual bool isEmptyElement() const 1.198 + { 1.199 + return IsEmptyElement; 1.200 + } 1.201 + 1.202 + //! Returns format of the source xml file. 1.203 + virtual ETEXT_FORMAT getSourceFormat() const 1.204 + { 1.205 + return SourceFormat; 1.206 + } 1.207 + 1.208 + //! Returns format of the strings returned by the parser. 1.209 + virtual ETEXT_FORMAT getParserFormat() const 1.210 + { 1.211 + return TargetFormat; 1.212 + } 1.213 + 1.214 +private: 1.215 + 1.216 + // Reads the current xml node 1.217 + void parseCurrentNode() 1.218 + { 1.219 + char_type* start = P; 1.220 + 1.221 + // more forward until '<' found 1.222 + while(*P != L'<' && *P) 1.223 + ++P; 1.224 + 1.225 + if (!*P) 1.226 + return; 1.227 + 1.228 + if (P - start > 0) 1.229 + { 1.230 + // we found some text, store it 1.231 + if (setText(start, P)) 1.232 + return; 1.233 + } 1.234 + 1.235 + ++P; 1.236 + 1.237 + // based on current token, parse and report next element 1.238 + switch(*P) 1.239 + { 1.240 + case L'/': 1.241 + parseClosingXMLElement(); 1.242 + break; 1.243 + case L'?': 1.244 + ignoreDefinition(); 1.245 + break; 1.246 + case L'!': 1.247 + if (!parseCDATA()) 1.248 + parseComment(); 1.249 + break; 1.250 + default: 1.251 + parseOpeningXMLElement(); 1.252 + break; 1.253 + } 1.254 + } 1.255 + 1.256 + 1.257 + //! sets the state that text was found. Returns true if set should be set 1.258 + bool setText(char_type* start, char_type* end) 1.259 + { 1.260 + // check if text is more than 2 characters, and if not, check if there is 1.261 + // only white space, so that this text won't be reported 1.262 + if (end - start < 3) 1.263 + { 1.264 + char_type* p = start; 1.265 + for(; p != end; ++p) 1.266 + if (!isWhiteSpace(*p)) 1.267 + break; 1.268 + 1.269 + if (p == end) 1.270 + return false; 1.271 + } 1.272 + 1.273 + // set current text to the parsed text, and replace xml special characters 1.274 + core::string<char_type> s(start, (int)(end - start)); 1.275 + NodeName = replaceSpecialCharacters(s); 1.276 + 1.277 + // current XML node type is text 1.278 + CurrentNodeType = EXN_TEXT; 1.279 + 1.280 + return true; 1.281 + } 1.282 + 1.283 + 1.284 + 1.285 + //! ignores an xml definition like <?xml something /> 1.286 + void ignoreDefinition() 1.287 + { 1.288 + CurrentNodeType = EXN_UNKNOWN; 1.289 + 1.290 + // move until end marked with '>' reached 1.291 + while(*P != L'>') 1.292 + ++P; 1.293 + 1.294 + ++P; 1.295 + } 1.296 + 1.297 + 1.298 + //! parses a comment 1.299 + void parseComment() 1.300 + { 1.301 + CurrentNodeType = EXN_COMMENT; 1.302 + P += 1; 1.303 + 1.304 + char_type *pCommentBegin = P; 1.305 + 1.306 + int count = 1; 1.307 + 1.308 + // move until end of comment reached 1.309 + while(count) 1.310 + { 1.311 + if (*P == L'>') 1.312 + --count; 1.313 + else 1.314 + if (*P == L'<') 1.315 + ++count; 1.316 + 1.317 + ++P; 1.318 + } 1.319 + 1.320 + P -= 3; 1.321 + NodeName = core::string<char_type>(pCommentBegin+2, (int)(P - pCommentBegin-2)); 1.322 + P += 3; 1.323 + } 1.324 + 1.325 + 1.326 + //! parses an opening xml element and reads attributes 1.327 + void parseOpeningXMLElement() 1.328 + { 1.329 + CurrentNodeType = EXN_ELEMENT; 1.330 + IsEmptyElement = false; 1.331 + Attributes.clear(); 1.332 + 1.333 + // find name 1.334 + const char_type* startName = P; 1.335 + 1.336 + // find end of element 1.337 + while(*P != L'>' && !isWhiteSpace(*P)) 1.338 + ++P; 1.339 + 1.340 + const char_type* endName = P; 1.341 + 1.342 + // find Attributes 1.343 + while(*P != L'>') 1.344 + { 1.345 + if (isWhiteSpace(*P)) 1.346 + ++P; 1.347 + else 1.348 + { 1.349 + if (*P != L'/') 1.350 + { 1.351 + // we've got an attribute 1.352 + 1.353 + // read the attribute names 1.354 + const char_type* attributeNameBegin = P; 1.355 + 1.356 + while(!isWhiteSpace(*P) && *P != L'=') 1.357 + ++P; 1.358 + 1.359 + const char_type* attributeNameEnd = P; 1.360 + ++P; 1.361 + 1.362 + // read the attribute value 1.363 + // check for quotes and single quotes, thx to murphy 1.364 + while( (*P != L'\"') && (*P != L'\'') && *P) 1.365 + ++P; 1.366 + 1.367 + if (!*P) // malformatted xml file 1.368 + return; 1.369 + 1.370 + const char_type attributeQuoteChar = *P; 1.371 + 1.372 + ++P; 1.373 + const char_type* attributeValueBegin = P; 1.374 + 1.375 + while(*P != attributeQuoteChar && *P) 1.376 + ++P; 1.377 + 1.378 + if (!*P) // malformatted xml file 1.379 + return; 1.380 + 1.381 + const char_type* attributeValueEnd = P; 1.382 + ++P; 1.383 + 1.384 + SAttribute attr; 1.385 + attr.Name = core::string<char_type>(attributeNameBegin, 1.386 + (int)(attributeNameEnd - attributeNameBegin)); 1.387 + 1.388 + core::string<char_type> s(attributeValueBegin, 1.389 + (int)(attributeValueEnd - attributeValueBegin)); 1.390 + 1.391 + attr.Value = replaceSpecialCharacters(s); 1.392 + Attributes.push_back(attr); 1.393 + } 1.394 + else 1.395 + { 1.396 + // tag is closed directly 1.397 + ++P; 1.398 + IsEmptyElement = true; 1.399 + break; 1.400 + } 1.401 + } 1.402 + } 1.403 + 1.404 + // check if this tag is closing directly 1.405 + if (endName > startName && *(endName-1) == L'/') 1.406 + { 1.407 + // directly closing tag 1.408 + IsEmptyElement = true; 1.409 + endName--; 1.410 + } 1.411 + 1.412 + NodeName = core::string<char_type>(startName, (int)(endName - startName)); 1.413 + 1.414 + ++P; 1.415 + } 1.416 + 1.417 + 1.418 + //! parses an closing xml tag 1.419 + void parseClosingXMLElement() 1.420 + { 1.421 + CurrentNodeType = EXN_ELEMENT_END; 1.422 + IsEmptyElement = false; 1.423 + Attributes.clear(); 1.424 + 1.425 + ++P; 1.426 + const char_type* pBeginClose = P; 1.427 + 1.428 + while(*P != L'>') 1.429 + ++P; 1.430 + 1.431 + // remove trailing whitespace, if any 1.432 + while( isspace( P[-1])) 1.433 + --P; 1.434 + 1.435 + NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose)); 1.436 + ++P; 1.437 + } 1.438 + 1.439 + //! parses a possible CDATA section, returns false if begin was not a CDATA section 1.440 + bool parseCDATA() 1.441 + { 1.442 + if (*(P+1) != L'[') 1.443 + return false; 1.444 + 1.445 + CurrentNodeType = EXN_CDATA; 1.446 + 1.447 + // skip '<![CDATA[' 1.448 + int count=0; 1.449 + while( *P && count<8 ) 1.450 + { 1.451 + ++P; 1.452 + ++count; 1.453 + } 1.454 + 1.455 + if (!*P) 1.456 + return true; 1.457 + 1.458 + char_type *cDataBegin = P; 1.459 + char_type *cDataEnd = 0; 1.460 + 1.461 + // find end of CDATA 1.462 + while(*P && !cDataEnd) 1.463 + { 1.464 + if (*P == L'>' && 1.465 + (*(P-1) == L']') && 1.466 + (*(P-2) == L']')) 1.467 + { 1.468 + cDataEnd = P - 2; 1.469 + } 1.470 + 1.471 + ++P; 1.472 + } 1.473 + 1.474 + if ( cDataEnd ) 1.475 + NodeName = core::string<char_type>(cDataBegin, (int)(cDataEnd - cDataBegin)); 1.476 + else 1.477 + NodeName = ""; 1.478 + 1.479 + return true; 1.480 + } 1.481 + 1.482 + 1.483 + // structure for storing attribute-name pairs 1.484 + struct SAttribute 1.485 + { 1.486 + core::string<char_type> Name; 1.487 + core::string<char_type> Value; 1.488 + }; 1.489 + 1.490 + // finds a current attribute by name, returns 0 if not found 1.491 + const SAttribute* getAttributeByName(const char_type* name) const 1.492 + { 1.493 + if (!name) 1.494 + return 0; 1.495 + 1.496 + core::string<char_type> n = name; 1.497 + 1.498 + for (int i=0; i<(int)Attributes.size(); ++i) 1.499 + if (Attributes[i].Name == n) 1.500 + return &Attributes[i]; 1.501 + 1.502 + return 0; 1.503 + } 1.504 + 1.505 + // replaces xml special characters in a string and creates a new one 1.506 + core::string<char_type> replaceSpecialCharacters( 1.507 + core::string<char_type>& origstr) 1.508 + { 1.509 + int pos = origstr.findFirst(L'&'); 1.510 + int oldPos = 0; 1.511 + 1.512 + if (pos == -1) 1.513 + return origstr; 1.514 + 1.515 + core::string<char_type> newstr; 1.516 + 1.517 + while(pos != -1 && pos < origstr.size()-2) 1.518 + { 1.519 + // check if it is one of the special characters 1.520 + 1.521 + int specialChar = -1; 1.522 + for (int i=0; i<(int)SpecialCharacters.size(); ++i) 1.523 + { 1.524 + const char_type* p = &origstr.c_str()[pos]+1; 1.525 + 1.526 + if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) 1.527 + { 1.528 + specialChar = i; 1.529 + break; 1.530 + } 1.531 + } 1.532 + 1.533 + if (specialChar != -1) 1.534 + { 1.535 + newstr.append(origstr.subString(oldPos, pos - oldPos)); 1.536 + newstr.append(SpecialCharacters[specialChar][0]); 1.537 + pos += SpecialCharacters[specialChar].size(); 1.538 + } 1.539 + else 1.540 + { 1.541 + newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); 1.542 + pos += 1; 1.543 + } 1.544 + 1.545 + // find next & 1.546 + oldPos = pos; 1.547 + pos = origstr.findNext(L'&', pos); 1.548 + } 1.549 + 1.550 + if (oldPos < origstr.size()-1) 1.551 + newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); 1.552 + 1.553 + return newstr; 1.554 + } 1.555 + 1.556 + 1.557 + 1.558 + //! reads the xml file and converts it into the wanted character format. 1.559 + bool readFile(IFileReadCallBack* callback) 1.560 + { 1.561 + int size = callback->getSize(); 1.562 + size += 4; // We need two terminating 0's at the end. 1.563 + // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. 1.564 + 1.565 + char* data8 = new char[size]; 1.566 + 1.567 + if (!callback->read(data8, size-4)) 1.568 + { 1.569 + delete [] data8; 1.570 + return false; 1.571 + } 1.572 + 1.573 + // add zeros at end 1.574 + 1.575 + data8[size-1] = 0; 1.576 + data8[size-2] = 0; 1.577 + data8[size-3] = 0; 1.578 + data8[size-4] = 0; 1.579 + 1.580 + char16* data16 = reinterpret_cast<char16*>(data8); 1.581 + char32* data32 = reinterpret_cast<char32*>(data8); 1.582 + 1.583 + // now we need to convert the data to the desired target format 1.584 + // based on the byte order mark. 1.585 + 1.586 + const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; 1.587 + const int UTF16_BE = 0xFFFE; 1.588 + const int UTF16_LE = 0xFEFF; 1.589 + const int UTF32_BE = 0xFFFE0000; 1.590 + const int UTF32_LE = 0x0000FEFF; 1.591 + 1.592 + // check source for all utf versions and convert to target data format 1.593 + 1.594 + if (size >= 4 && data32[0] == (char32)UTF32_BE) 1.595 + { 1.596 + // UTF-32, big endian 1.597 + SourceFormat = ETF_UTF32_BE; 1.598 + convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header 1.599 + } 1.600 + else 1.601 + if (size >= 4 && data32[0] == (char32)UTF32_LE) 1.602 + { 1.603 + // UTF-32, little endian 1.604 + SourceFormat = ETF_UTF32_LE; 1.605 + convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header 1.606 + } 1.607 + else 1.608 + if (size >= 2 && data16[0] == UTF16_BE) 1.609 + { 1.610 + // UTF-16, big endian 1.611 + SourceFormat = ETF_UTF16_BE; 1.612 + convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header 1.613 + } 1.614 + else 1.615 + if (size >= 2 && data16[0] == UTF16_LE) 1.616 + { 1.617 + // UTF-16, little endian 1.618 + SourceFormat = ETF_UTF16_LE; 1.619 + convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header 1.620 + } 1.621 + else 1.622 + if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2]) 1.623 + { 1.624 + // UTF-8 1.625 + SourceFormat = ETF_UTF8; 1.626 + convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header 1.627 + } 1.628 + else 1.629 + { 1.630 + // ASCII 1.631 + SourceFormat = ETF_ASCII; 1.632 + convertTextData(data8, data8, size); 1.633 + } 1.634 + 1.635 + return true; 1.636 + } 1.637 + 1.638 + 1.639 + //! converts the text file into the desired format. 1.640 + //! \param source: begin of the text (without byte order mark) 1.641 + //! \param pointerToStore: pointer to text data block which can be 1.642 + //! stored or deleted based on the nesessary conversion. 1.643 + //! \param sizeWithoutHeader: Text size in characters without header 1.644 + template<class src_char_type> 1.645 + void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) 1.646 + { 1.647 + // convert little to big endian if necessary 1.648 + if (sizeof(src_char_type) > 1 && 1.649 + isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) 1.650 + convertToLittleEndian(source); 1.651 + 1.652 + // check if conversion is necessary: 1.653 + if (sizeof(src_char_type) == sizeof(char_type)) 1.654 + { 1.655 + // no need to convert 1.656 + TextBegin = (char_type*)source; 1.657 + TextData = (char_type*)pointerToStore; 1.658 + TextSize = sizeWithoutHeader; 1.659 + } 1.660 + else 1.661 + { 1.662 + // convert source into target data format. 1.663 + // TODO: implement a real conversion. This one just 1.664 + // copies bytes. This is a problem when there are 1.665 + // unicode symbols using more than one character. 1.666 + 1.667 + TextData = new char_type[sizeWithoutHeader]; 1.668 + 1.669 + // MSVC debugger complains here about loss of data ... 1.670 + 1.671 + 1.672 + // FIXME - gcc complains about 'shift width larger than width of type' 1.673 + // for T == unsigned long. Avoid it by messing around volatile .. 1.674 + volatile unsigned int c = 3; 1.675 + const src_char_type cc = (src_char_type)((((uint64_t)1u << (sizeof( char_type)<<c)) - 1)); 1.676 + for (int i=0; i<sizeWithoutHeader; ++i) 1.677 + TextData[i] = char_type( source[i] & cc); 1.678 + 1.679 + TextBegin = TextData; 1.680 + TextSize = sizeWithoutHeader; 1.681 + 1.682 + // delete original data because no longer needed 1.683 + delete [] pointerToStore; 1.684 + } 1.685 + } 1.686 + 1.687 + //! converts whole text buffer to little endian 1.688 + template<class src_char_type> 1.689 + void convertToLittleEndian(src_char_type* t) 1.690 + { 1.691 + if (sizeof(src_char_type) == 4) 1.692 + { 1.693 + // 32 bit 1.694 + 1.695 + while(*t) 1.696 + { 1.697 + *t = ((*t & 0xff000000) >> 24) | 1.698 + ((*t & 0x00ff0000) >> 8) | 1.699 + ((*t & 0x0000ff00) << 8) | 1.700 + ((*t & 0x000000ff) << 24); 1.701 + ++t; 1.702 + } 1.703 + } 1.704 + else 1.705 + { 1.706 + // 16 bit 1.707 + 1.708 + while(*t) 1.709 + { 1.710 + *t = (*t >> 8) | (*t << 8); 1.711 + ++t; 1.712 + } 1.713 + } 1.714 + } 1.715 + 1.716 + //! returns if a format is little endian 1.717 + inline bool isLittleEndian(ETEXT_FORMAT f) 1.718 + { 1.719 + return f == ETF_ASCII || 1.720 + f == ETF_UTF8 || 1.721 + f == ETF_UTF16_LE || 1.722 + f == ETF_UTF32_LE; 1.723 + } 1.724 + 1.725 + 1.726 + //! returns true if a character is whitespace 1.727 + inline bool isWhiteSpace(char_type c) 1.728 + { 1.729 + return (c==' ' || c=='\t' || c=='\n' || c=='\r'); 1.730 + } 1.731 + 1.732 + 1.733 + //! generates a list with xml special characters 1.734 + void createSpecialCharacterList() 1.735 + { 1.736 + // list of strings containing special symbols, 1.737 + // the first character is the special character, 1.738 + // the following is the symbol string without trailing &. 1.739 + 1.740 + SpecialCharacters.push_back("&"); 1.741 + SpecialCharacters.push_back("<lt;"); 1.742 + SpecialCharacters.push_back(">gt;"); 1.743 + SpecialCharacters.push_back("\"quot;"); 1.744 + SpecialCharacters.push_back("'apos;"); 1.745 + 1.746 + } 1.747 + 1.748 + 1.749 + //! compares the first n characters of the strings 1.750 + bool equalsn(const char_type* str1, const char_type* str2, int len) 1.751 + { 1.752 + int i; 1.753 + for(i=0; str1[i] && str2[i] && i < len; ++i) 1.754 + if (str1[i] != str2[i]) 1.755 + return false; 1.756 + 1.757 + // if one (or both) of the strings was smaller then they 1.758 + // are only equal if they have the same lenght 1.759 + return (i == len) || (str1[i] == 0 && str2[i] == 0); 1.760 + } 1.761 + 1.762 + 1.763 + //! stores the target text format 1.764 + void storeTargetFormat() 1.765 + { 1.766 + // get target format. We could have done this using template specialization, 1.767 + // but VisualStudio 6 don't like it and we want to support it. 1.768 + 1.769 + switch(sizeof(char_type)) 1.770 + { 1.771 + case 1: 1.772 + TargetFormat = ETF_UTF8; 1.773 + break; 1.774 + case 2: 1.775 + TargetFormat = ETF_UTF16_LE; 1.776 + break; 1.777 + case 4: 1.778 + TargetFormat = ETF_UTF32_LE; 1.779 + break; 1.780 + default: 1.781 + TargetFormat = ETF_ASCII; // should never happen. 1.782 + } 1.783 + } 1.784 + 1.785 + 1.786 + // instance variables: 1.787 + 1.788 + char_type* TextData; // data block of the text file 1.789 + char_type* P; // current point in text to parse 1.790 + char_type* TextBegin; // start of text to parse 1.791 + unsigned int TextSize; // size of text to parse in characters, not bytes 1.792 + 1.793 + EXML_NODE CurrentNodeType; // type of the currently parsed node 1.794 + ETEXT_FORMAT SourceFormat; // source format of the xml file 1.795 + ETEXT_FORMAT TargetFormat; // output format of this parser 1.796 + 1.797 + core::string<char_type> NodeName; // name of the node currently in 1.798 + core::string<char_type> EmptyString; // empty string to be returned by getSafe() methods 1.799 + 1.800 + bool IsEmptyElement; // is the currently parsed node empty? 1.801 + 1.802 + core::array< core::string<char_type> > SpecialCharacters; // see createSpecialCharacterList() 1.803 + 1.804 + core::array<SAttribute> Attributes; // attributes of current element 1.805 + 1.806 +}; // end CXMLReaderImpl 1.807 + 1.808 + 1.809 +} // end namespace 1.810 +} // end namespace 1.811 + 1.812 +#endif