2016-09-27 22:01:08 +03:00
|
|
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
2005-01-18 21:41:23 +03:00
|
|
|
#include "cmXMLParser.h"
|
2016-04-29 16:40:20 +03:00
|
|
|
|
2006-10-19 23:00:10 +04:00
|
|
|
#include <cm_expat.h>
|
2016-08-17 02:08:13 +03:00
|
|
|
#include <cmsys/FStream.hxx>
|
2005-01-18 23:54:20 +03:00
|
|
|
#include <ctype.h>
|
2016-08-17 02:08:13 +03:00
|
|
|
#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()
|
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
if (this->Parser) {
|
2005-01-18 21:41:23 +03:00
|
|
|
this->CleanupParser();
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2005-01-18 21:41:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int cmXMLParser::Parse(const char* string)
|
|
|
|
{
|
2006-03-30 22:49:56 +04:00
|
|
|
return (int)this->InitializeParser() &&
|
2016-05-16 17:34:04 +03:00
|
|
|
this->ParseChunk(string, strlen(string)) && this->CleanupParser();
|
2005-01-18 21:41:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int cmXMLParser::ParseFile(const char* file)
|
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!file) {
|
2005-01-18 21:41:23 +03:00
|
|
|
return 0;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2005-01-18 21:41:23 +03:00
|
|
|
|
2014-01-04 09:47:13 +04:00
|
|
|
cmsys::ifstream ifs(file);
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!ifs) {
|
2005-01-18 21:41:23 +03:00
|
|
|
return 0;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2005-01-18 21:41:23 +03:00
|
|
|
|
2015-01-05 22:31:31 +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()
|
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
if (this->Parser) {
|
2005-01-18 21:41:23 +03:00
|
|
|
std::cerr << "Parser already initialized" << std::endl;
|
|
|
|
this->ParseError = 1;
|
|
|
|
return 0;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
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),
|
2016-05-16 17:34:04 +03:00
|
|
|
&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;
|
|
|
|
}
|
|
|
|
|
2012-08-13 21:42:58 +04:00
|
|
|
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
|
|
|
{
|
2016-05-16 17:34:04 +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;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2005-01-18 21:41:23 +03:00
|
|
|
int res;
|
|
|
|
res = this->ParseBuffer(inputString, length);
|
2016-05-16 17:34:04 +03:00
|
|
|
if (res == 0) {
|
2005-01-18 21:41:23 +03:00
|
|
|
this->ParseError = 1;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2005-01-18 21:41:23 +03:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int cmXMLParser::CleanupParser()
|
|
|
|
{
|
2016-05-16 17:34:04 +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;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2005-01-18 21:41:23 +03:00
|
|
|
int result = !this->ParseError;
|
2016-05-16 17:34:04 +03:00
|
|
|
if (result) {
|
2005-01-18 21:41:23 +03:00
|
|
|
// Tell the expat XML parser about the end-of-input.
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1)) {
|
2005-01-18 21:41:23 +03:00
|
|
|
this->ReportXmlParseError();
|
|
|
|
result = 0;
|
|
|
|
}
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2012-08-13 21:42:58 +04:00
|
|
|
|
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;
|
2012-08-13 21:42:58 +04:00
|
|
|
|
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.
|
2016-05-16 17:34:04 +03:00
|
|
|
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;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-02-22 04:05:55 +04:00
|
|
|
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*/,
|
2016-05-16 17:34:04 +03:00
|
|
|
int /*inLength*/)
|
2005-01-18 21:41:23 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int cmXMLParser::IsSpace(char c)
|
|
|
|
{
|
|
|
|
return isspace(c);
|
|
|
|
}
|
|
|
|
|
2009-02-24 23:43:49 +03:00
|
|
|
const char* cmXMLParser::FindAttribute(const char** atts,
|
|
|
|
const char* attribute)
|
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
if (atts && attribute) {
|
|
|
|
for (const char** a = atts; *a && *(a + 1); a += 2) {
|
|
|
|
if (strcmp(*a, attribute) == 0) {
|
|
|
|
return *(a + 1);
|
2009-02-24 23:43:49 +03:00
|
|
|
}
|
|
|
|
}
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2016-09-06 00:18:05 +03:00
|
|
|
return CM_NULLPTR;
|
2009-02-24 23:43:49 +03:00
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
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,
|
2016-05-16 17:34:04 +03:00
|
|
|
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()
|
|
|
|
{
|
2009-06-11 17:03:56 +04:00
|
|
|
XML_Parser parser = static_cast<XML_Parser>(this->Parser);
|
2009-02-24 23:43:37 +03:00
|
|
|
this->ReportError(XML_GetCurrentLineNumber(parser),
|
|
|
|
XML_GetCurrentColumnNumber(parser),
|
|
|
|
XML_ErrorString(XML_GetErrorCode(parser)));
|
2005-01-18 21:41:23 +03:00
|
|
|
}
|
|
|
|
|
2016-08-17 02:49:57 +03:00
|
|
|
void cmXMLParser::ReportError(int line, int /*unused*/, const char* msg)
|
2009-02-24 23:43:37 +03:00
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
if (this->ReportCallback) {
|
2014-07-15 01:01:47 +04:00
|
|
|
this->ReportCallback(line, msg, this->ReportCallbackData);
|
2016-05-16 17:34:04 +03:00
|
|
|
} else {
|
|
|
|
std::cerr << "Error parsing XML in stream at line " << line << ": " << msg
|
|
|
|
<< std::endl;
|
|
|
|
}
|
2009-02-24 23:43:37 +03:00
|
|
|
}
|