CMake/Source/cmXMLParser.cxx

212 lines
5.5 KiB
C++
Raw Normal View History

/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
2005-01-18 21:41:23 +03:00
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
2005-01-18 21:41:23 +03:00
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.
============================================================================*/
2005-01-18 21:41:23 +03:00
#include "cmXMLParser.h"
#include <cm_expat.h>
#include <cmsys/FStream.hxx>
#include <ctype.h>
#include <iostream>
#include <sstream>
#include <string.h>
2005-01-18 21:41:23 +03:00
cmXMLParser::cmXMLParser()
{
2016-09-06 00:18:05 +03:00
this->Parser = CM_NULLPTR;
2005-01-18 21:41:23 +03:00
this->ParseError = 0;
2016-09-06 00:18:05 +03:00
this->ReportCallback = CM_NULLPTR;
this->ReportCallbackData = CM_NULLPTR;
2005-01-18 21:41:23 +03:00
}
cmXMLParser::~cmXMLParser()
{
if (this->Parser) {
2005-01-18 21:41:23 +03:00
this->CleanupParser();
}
2005-01-18 21:41:23 +03:00
}
int cmXMLParser::Parse(const char* string)
{
return (int)this->InitializeParser() &&
this->ParseChunk(string, strlen(string)) && this->CleanupParser();
2005-01-18 21:41:23 +03:00
}
int cmXMLParser::ParseFile(const char* file)
{
if (!file) {
2005-01-18 21:41:23 +03:00
return 0;
}
2005-01-18 21:41:23 +03:00
cmsys::ifstream ifs(file);
if (!ifs) {
2005-01-18 21:41:23 +03:00
return 0;
}
2005-01-18 21:41:23 +03:00
std::ostringstream str;
2005-01-18 21:41:23 +03:00
str << ifs.rdbuf();
return this->Parse(str.str().c_str());
}
int cmXMLParser::InitializeParser()
{
if (this->Parser) {
2005-01-18 21:41:23 +03:00
std::cerr << "Parser already initialized" << std::endl;
this->ParseError = 1;
return 0;
}
2005-01-18 21:41:23 +03:00
// Create the expat XML parser.
2016-09-06 00:18:05 +03:00
this->Parser = XML_ParserCreate(CM_NULLPTR);
2005-01-18 21:41:23 +03:00
XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
&cmXMLParserStartElement, &cmXMLParserEndElement);
2005-01-18 21:41:23 +03:00
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,
2007-07-25 17:22:19 +04:00
std::string::size_type length)
2005-01-18 21:41:23 +03:00
{
if (!this->Parser) {
2005-01-18 21:41:23 +03:00
std::cerr << "Parser not initialized" << std::endl;
this->ParseError = 1;
return 0;
}
2005-01-18 21:41:23 +03:00
int res;
res = this->ParseBuffer(inputString, length);
if (res == 0) {
2005-01-18 21:41:23 +03:00
this->ParseError = 1;
}
2005-01-18 21:41:23 +03:00
return res;
}
int cmXMLParser::CleanupParser()
{
if (!this->Parser) {
2005-01-18 21:41:23 +03:00
std::cerr << "Parser not initialized" << std::endl;
this->ParseError = 1;
return 0;
}
2005-01-18 21:41:23 +03:00
int result = !this->ParseError;
if (result) {
2005-01-18 21:41:23 +03:00
// Tell the expat XML parser about the end-of-input.
if (!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1)) {
2005-01-18 21:41:23 +03:00
this->ReportXmlParseError();
result = 0;
}
}
2005-01-18 21:41:23 +03:00
// Clean up the parser.
XML_ParserFree(static_cast<XML_Parser>(this->Parser));
2016-09-06 00:18:05 +03:00
this->Parser = CM_NULLPTR;
2005-01-18 21:41:23 +03:00
return result;
}
2007-07-26 22:36:06 +04:00
int cmXMLParser::ParseBuffer(const char* buffer, std::string::size_type count)
2005-01-18 21:41:23 +03:00
{
// Pass the buffer to the expat XML parser.
if (!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer,
static_cast<int>(count), 0)) {
2005-01-18 21:41:23 +03:00
this->ReportXmlParseError();
return 0;
}
2005-01-18 21:41:23 +03:00
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*/)
2005-01-18 21:41:23 +03:00
{
std::cout << "Start element: " << name << std::endl;
}
void cmXMLParser::EndElement(const std::string& name)
2005-01-18 21:41:23 +03:00
{
std::cout << "End element: " << name << std::endl;
}
void cmXMLParser::CharacterDataHandler(const char* /*inData*/,
int /*inLength*/)
2005-01-18 21:41:23 +03:00
{
}
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);
}
}
}
2016-09-06 00:18:05 +03:00
return CM_NULLPTR;
}
void cmXMLParserStartElement(void* parser, const char* name, const char** atts)
2005-01-18 21:41:23 +03:00
{
// 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)
2005-01-18 21:41:23 +03:00
{
// 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)
2005-01-18 21:41:23 +03:00
{
// 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)));
2005-01-18 21:41:23 +03:00
}
void cmXMLParser::ReportError(int line, int /*unused*/, 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;
}
}