/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmXMLParser.h"

#include <cctype>
#include <cstring>
#include <iostream>
#include <sstream>

#include <cm3p/expat.h>

#include "cmsys/FStream.hxx"

cmXMLParser::cmXMLParser()
{
  this->Parser = nullptr;
  this->ParseError = 0;
  this->ReportCallback = nullptr;
  this->ReportCallbackData = nullptr;
}

cmXMLParser::~cmXMLParser()
{
  if (this->Parser) {
    this->CleanupParser();
  }
}

int cmXMLParser::Parse(const char* string)
{
  return 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(nullptr);
  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 = nullptr;

  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 nullptr;
}

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(static_cast<int>(XML_GetCurrentLineNumber(parser)),
                    static_cast<int>(XML_GetCurrentColumnNumber(parser)),
                    XML_ErrorString(XML_GetErrorCode(parser)));
}

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;
  }
}
