diff options
Diffstat (limited to 'Source/cmXMLParser.cxx')
-rw-r--r-- | Source/cmXMLParser.cxx | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx new file mode 100644 index 0000000..1d3e0e9 --- /dev/null +++ b/Source/cmXMLParser.cxx @@ -0,0 +1,247 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmXMLParser.h" +#include <cmsys/FStream.hxx> + +#include <cm_expat.h> +#include <ctype.h> + +//---------------------------------------------------------------------------- +cmXMLParser::cmXMLParser() +{ + this->Parser = 0; + this->ParseError = 0; + this->ReportCallback = 0; + this->ReportCallbackData = 0; +} + +//---------------------------------------------------------------------------- +cmXMLParser::~cmXMLParser() +{ + if ( this->Parser ) + { + this->CleanupParser(); + } +} + +//---------------------------------------------------------------------------- +int cmXMLParser::Parse(const char* string) +{ + return (int)this->InitializeParser() && + this->ParseChunk(string, strlen(string)) && + this->CleanupParser(); +} + +int cmXMLParser::ParseFile(const char* file) +{ + if ( !file ) + { + return 0; + } + + cmsys::ifstream ifs(file); + if ( !ifs ) + { + return 0; + } + + std::ostringstream str; + str << ifs.rdbuf(); + return this->Parse(str.str().c_str()); +} + +//---------------------------------------------------------------------------- +int cmXMLParser::InitializeParser() +{ + if ( this->Parser ) + { + std::cerr << "Parser already initialized" << std::endl; + this->ParseError = 1; + return 0; + } + + // Create the expat XML parser. + this->Parser = XML_ParserCreate(0); + XML_SetElementHandler(static_cast<XML_Parser>(this->Parser), + &cmXMLParserStartElement, + &cmXMLParserEndElement); + XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser), + &cmXMLParserCharacterDataHandler); + XML_SetUserData(static_cast<XML_Parser>(this->Parser), this); + this->ParseError = 0; + return 1; +} + +//---------------------------------------------------------------------------- +int cmXMLParser::ParseChunk(const char* inputString, + std::string::size_type length) +{ + if ( !this->Parser ) + { + std::cerr << "Parser not initialized" << std::endl; + this->ParseError = 1; + return 0; + } + int res; + res = this->ParseBuffer(inputString, length); + if ( res == 0 ) + { + this->ParseError = 1; + } + return res; +} + +//---------------------------------------------------------------------------- +int cmXMLParser::CleanupParser() +{ + if ( !this->Parser ) + { + std::cerr << "Parser not initialized" << std::endl; + this->ParseError = 1; + return 0; + } + int result = !this->ParseError; + if(result) + { + // Tell the expat XML parser about the end-of-input. + if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1)) + { + this->ReportXmlParseError(); + result = 0; + } + } + + // Clean up the parser. + XML_ParserFree(static_cast<XML_Parser>(this->Parser)); + this->Parser = 0; + + return result; +} + +//---------------------------------------------------------------------------- +int cmXMLParser::ParseBuffer(const char* buffer, std::string::size_type count) +{ + // Pass the buffer to the expat XML parser. + if(!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer, + static_cast<int>(count), 0)) + { + this->ReportXmlParseError(); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int cmXMLParser::ParseBuffer(const char* buffer) +{ + return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer))); +} + +//---------------------------------------------------------------------------- +int cmXMLParser::ParsingComplete() +{ + // Default behavior is to parse to end of stream. + return 0; +} + +//---------------------------------------------------------------------------- +void cmXMLParser::StartElement(const std::string& name, + const char ** /*atts*/) +{ + std::cout << "Start element: " << name << std::endl; +} + +//---------------------------------------------------------------------------- +void cmXMLParser::EndElement(const std::string& name) +{ + std::cout << "End element: " << name << std::endl; +} + +//---------------------------------------------------------------------------- +void cmXMLParser::CharacterDataHandler(const char* /*inData*/, + int /*inLength*/) +{ +} + +//---------------------------------------------------------------------------- +int cmXMLParser::IsSpace(char c) +{ + return isspace(c); +} + +//---------------------------------------------------------------------------- +const char* cmXMLParser::FindAttribute(const char** atts, + const char* attribute) +{ + if(atts && attribute) + { + for(const char** a = atts; *a && *(a+1); a += 2) + { + if(strcmp(*a, attribute) == 0) + { + return *(a+1); + } + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void cmXMLParserStartElement(void* parser, const char *name, + const char **atts) +{ + // Begin element handler that is registered with the XML_Parser. + // This just casts the user data to a cmXMLParser and calls + // StartElement. + static_cast<cmXMLParser*>(parser)->StartElement(name, atts); +} + +//---------------------------------------------------------------------------- +void cmXMLParserEndElement(void* parser, const char *name) +{ + // End element handler that is registered with the XML_Parser. This + // just casts the user data to a cmXMLParser and calls EndElement. + static_cast<cmXMLParser*>(parser)->EndElement(name); +} + +//---------------------------------------------------------------------------- +void cmXMLParserCharacterDataHandler(void* parser, const char* data, + int length) +{ + // Character data handler that is registered with the XML_Parser. + // This just casts the user data to a cmXMLParser and calls + // CharacterDataHandler. + static_cast<cmXMLParser*>(parser)->CharacterDataHandler(data, length); +} + +//---------------------------------------------------------------------------- +void cmXMLParser::ReportXmlParseError() +{ + XML_Parser parser = static_cast<XML_Parser>(this->Parser); + this->ReportError(XML_GetCurrentLineNumber(parser), + XML_GetCurrentColumnNumber(parser), + XML_ErrorString(XML_GetErrorCode(parser))); +} + +//---------------------------------------------------------------------------- +void cmXMLParser::ReportError(int line, int, const char* msg) +{ + if(this->ReportCallback) + { + this->ReportCallback(line, msg, this->ReportCallbackData); + } + else + { + std::cerr << "Error parsing XML in stream at line " + << line << ": " << msg << std::endl; + } +} |