// <-- Strange class for a bug fix. Search for STL_STRING_BUG TiXmlBaseA::StringToBuffer::StringToBuffer( const TIXMLA_STRING& str ) { buffer = new char[ str.length()+1 ]; if ( buffer ) { strcpy( buffer, str.c_str() ); } }
bool TiXmlDocumentA::LoadUnicodeFilePath( const TCHAR* filename ) { // Delete the existing data: Clear(); location.Clear(); // There was a really terrifying little bug here. The code: // value = filename // in the STL case, cause the assignment method of the string to // be called. What is strange, is that the string had the same // address as it's c_str() method, and so bad things happen. Looks // like a bug in the Microsoft STL implementation. // See STL_STRING_BUG above. // Fixed with the StringToBuffer class. FILE* file = generic_fopen(filename, TEXT("r")); if ( file ) { // Get the file size, so we can pre-allocate the generic_string. HUGE speed impact. long length = 0; fseek( file, 0, SEEK_END ); length = ftell( file ); fseek( file, 0, SEEK_SET ); // Strange case, but good to handle up front. if ( length == 0 ) { fclose( file ); return false; } // If we have a file, assume it is all one big XML file, and read it in. // The document parser may decide the document ends sooner than the entire file, however. TIXMLA_STRING data; data.reserve( length ); const int BUF_SIZE = 2048; char buf[BUF_SIZE]; while( fgets( buf, BUF_SIZE, file ) ) { data += buf; } fclose( file ); Parse( data.c_str(), 0 ); if ( Error() ) return false; else return true; } SetError( TIXMLA_ERROR_OPENING_FILE, 0, 0 ); return false; }
void TiXmlBaseA::PutString( const TIXMLA_STRING& str, TIXMLA_STRING* outString ) { int i=0; while( i<(int)str.length() ) { int c = str[i]; if ( c == '&' && i < ( static_cast<int>(str.length()) - 2 ) && str[i+1] == '#' && str[i+2] == 'x' ) { // Hexadecimal character reference. // Pass through unchanged. // © -- copyright symbol, for example. while (i < static_cast<int>(str.length())) { outString->append( str.c_str() + i, 1 ); ++i; if ( str[i] == ';' ) break; } } else if ( c == '&' ) { outString->append( entity[0].str, entity[0].strLength ); ++i; } else if ( c == '<' ) { outString->append( entity[1].str, entity[1].strLength ); ++i; } else if ( c == '>' ) { outString->append( entity[2].str, entity[2].strLength ); ++i; } else if ( c == '\"' ) { outString->append( entity[3].str, entity[3].strLength ); ++i; } else if ( c == '\'' ) { outString->append( entity[4].str, entity[4].strLength ); ++i; } else if ( c < 32 || c > 126 ) { // Easy pass at non-alpha/numeric/symbol // 127 is the delete key. Below 32 is symbolic. char buf[ 32 ]; sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); outString->append( buf, strlen( buf ) ); ++i; } else { char realc = static_cast<char>(c); outString->append( &realc, 1 ); ++i; } } }
void TiXmlTextA::Print( FILE* cfile, int /*depth*/ ) const { TIXMLA_STRING buffer; PutString( value, &buffer ); fprintf( cfile, "%s", buffer.c_str() ); }
{ TiXmlAttributeA* node; for( node = sentinel.next; node != &sentinel; node = node->next ) { if ( node->name == name ) return node; } return 0; } #ifdef TIXMLA_USE_STL TIXMLA_ISTREAM & operator >> (TIXMLA_ISTREAM & in, TiXmlNodeA & base) { TIXMLA_STRING tag; tag.reserve( 8 * 1000 ); base.StreamIn( &in, &tag ); base.Parse( tag.c_str(), 0 ); return in; } #endif TIXMLA_OSTREAM & operator<< (TIXMLA_OSTREAM & out, const TiXmlNodeA & base) { base.StreamOut (& out); return out; }
const char* TiXmlElementA::Parse( const char* p, TiXmlParsingDataA* data ) { p = SkipWhiteSpace( p ); TiXmlDocumentA* document = GetDocument(); if ( !p || !*p ) { if ( document ) document->SetError( TIXMLA_ERROR_PARSING_ELEMENT, 0, 0 ); return 0; } // TiXmlParsingDataA data( p, prevData ); if ( data ) { data->Stamp( p ); location = data->Cursor(); } if ( *p != '<' ) { if ( document ) document->SetError( TIXMLA_ERROR_PARSING_ELEMENT, p, data ); return 0; } p = SkipWhiteSpace( p+1 ); // Read the name. const char* pErr = p; p = ReadName( p, &value ); if ( !p || !*p ) { if ( document ) document->SetError( TIXMLA_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data ); return 0; } TIXMLA_STRING endTag ("</"); endTag += value; endTag += ">"; // Check for and read attributes. Also look for an empty // tag or an end tag. while ( p && *p ) { pErr = p; p = SkipWhiteSpace( p ); if ( !p || !*p ) { if ( document ) document->SetError( TIXMLA_ERROR_READING_ATTRIBUTES, pErr, data ); return 0; } if ( *p == '/' ) { ++p; // Empty tag. if ( *p != '>' ) { if ( document ) document->SetError( TIXMLA_ERROR_PARSING_EMPTY, p, data ); return 0; } return (p+1); } else if ( *p == '>' ) { // Done with attributes (if there were any.) // Read the value -- which can include other // elements -- read the end tag, and return. ++p; p = ReadValue( p, data ); // Note this is an Element method, and will set the error if one happens. if ( !p || !*p ) return 0; // We should find the end tag now if ( StringEqual( p, endTag.c_str(), false ) ) { p += endTag.length(); return p; } else { if ( document ) document->SetError( TIXMLA_ERROR_READING_END_TAG, p, data ); return 0; } } else { // Try to read an attribute: TiXmlAttributeA* attrib = new TiXmlAttributeA(); if ( !attrib ) { if ( document ) document->SetError( TIXMLA_ERROR_OUT_OF_MEMORY, pErr, data ); return 0; } attrib->SetDocument( document ); const char* pErr = p; p = attrib->Parse( p, data ); if ( !p || !*p ) { if ( document ) document->SetError( TIXMLA_ERROR_PARSING_ELEMENT, pErr, data ); delete attrib; return 0; } // Handle the strange case of double attributes: TiXmlAttributeA* node = attributeSet.Find( attrib->Name() ); if ( node ) { node->SetValue( attrib->Value() ); delete attrib; return 0; } attributeSet.Add( attrib ); } } return p; }