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

#include <cassert>

#include "cmsys/FStream.hxx"

cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
  : Output(output)
  , IndentationElement(1, '\t')
  , Level(level)
  , Indent(0)
  , ElementOpen(false)
  , BreakAttrib(false)
  , IsContent(false)
{
}

cmXMLWriter::~cmXMLWriter()
{
  assert(this->Indent == 0);
}

void cmXMLWriter::StartDocument(const char* encoding)
{
  this->Output << R"(<?xml version="1.0" encoding=")" << encoding << "\"?>";
}

void cmXMLWriter::EndDocument()
{
  assert(this->Indent == 0);
  this->Output << '\n';
}

void cmXMLWriter::StartElement(std::string const& name)
{
  this->CloseStartElement();
  this->ConditionalLineBreak(!this->IsContent);
  this->Output << '<' << name;
  this->Elements.push(name);
  ++this->Indent;
  this->ElementOpen = true;
  this->BreakAttrib = false;
}

void cmXMLWriter::EndElement()
{
  assert(this->Indent > 0);
  --this->Indent;
  if (this->ElementOpen) {
    this->Output << "/>";
  } else {
    this->ConditionalLineBreak(!this->IsContent);
    this->IsContent = false;
    this->Output << "</" << this->Elements.top() << '>';
  }
  this->Elements.pop();
  this->ElementOpen = false;
}

void cmXMLWriter::Element(const char* name)
{
  this->CloseStartElement();
  this->ConditionalLineBreak(!this->IsContent);
  this->Output << '<' << name << "/>";
}

void cmXMLWriter::BreakAttributes()
{
  this->BreakAttrib = true;
}

void cmXMLWriter::Comment(const char* comment)
{
  this->CloseStartElement();
  this->ConditionalLineBreak(!this->IsContent);
  this->Output << "<!-- " << comment << " -->";
}

void cmXMLWriter::CData(std::string const& data)
{
  this->PreContent();
  this->Output << "<![CDATA[" << data << "]]>";
}

void cmXMLWriter::Doctype(const char* doctype)
{
  this->CloseStartElement();
  this->ConditionalLineBreak(!this->IsContent);
  this->Output << "<!DOCTYPE " << doctype << ">";
}

void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
{
  this->CloseStartElement();
  this->ConditionalLineBreak(!this->IsContent);
  this->Output << "<?" << target << ' ' << data << "?>";
}

void cmXMLWriter::FragmentFile(const char* fname)
{
  this->CloseStartElement();
  cmsys::ifstream fin(fname, std::ios::in | std::ios::binary);
  this->Output << fin.rdbuf();
}

void cmXMLWriter::SetIndentationElement(std::string const& element)
{
  this->IndentationElement = element;
}

void cmXMLWriter::ConditionalLineBreak(bool condition)
{
  if (condition) {
    this->Output << '\n';
    for (std::size_t i = 0; i < this->Indent + this->Level; ++i) {
      this->Output << this->IndentationElement;
    }
  }
}

void cmXMLWriter::PreAttribute()
{
  assert(this->ElementOpen);
  this->ConditionalLineBreak(this->BreakAttrib);
  if (!this->BreakAttrib) {
    this->Output << ' ';
  }
}

void cmXMLWriter::PreContent()
{
  this->CloseStartElement();
  this->IsContent = true;
}

void cmXMLWriter::CloseStartElement()
{
  if (this->ElementOpen) {
    this->ConditionalLineBreak(this->BreakAttrib);
    this->Output << '>';
    this->ElementOpen = false;
  }
}
