resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmXMLWriter.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmXMLWriter.h"
4
5 #include <cassert>
6
7 #include "cmsys/FStream.hxx"
8
9 cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
10   : Output(output)
11   , IndentationElement(1, '\t')
12   , Level(level)
13 {
14 }
15
16 cmXMLWriter::~cmXMLWriter()
17 {
18   assert(this->Indent == 0);
19 }
20
21 void cmXMLWriter::StartDocument(const char* encoding)
22 {
23   this->Output << R"(<?xml version="1.0" encoding=")" << encoding << "\"?>";
24 }
25
26 void cmXMLWriter::EndDocument()
27 {
28   assert(this->Indent == 0);
29   this->Output << '\n';
30 }
31
32 void cmXMLWriter::StartElement(std::string const& name)
33 {
34   this->CloseStartElement();
35   this->ConditionalLineBreak(!this->IsContent);
36   this->Output << '<' << name;
37   this->Elements.push(name);
38   ++this->Indent;
39   this->ElementOpen = true;
40   this->BreakAttrib = false;
41 }
42
43 void cmXMLWriter::EndElement()
44 {
45   assert(this->Indent > 0);
46   --this->Indent;
47   if (this->ElementOpen) {
48     this->Output << "/>";
49   } else {
50     this->ConditionalLineBreak(!this->IsContent);
51     this->IsContent = false;
52     this->Output << "</" << this->Elements.top() << '>';
53   }
54   this->Elements.pop();
55   this->ElementOpen = false;
56 }
57
58 void cmXMLWriter::Element(const char* name)
59 {
60   this->CloseStartElement();
61   this->ConditionalLineBreak(!this->IsContent);
62   this->Output << '<' << name << "/>";
63 }
64
65 void cmXMLWriter::BreakAttributes()
66 {
67   this->BreakAttrib = true;
68 }
69
70 void cmXMLWriter::Comment(const char* comment)
71 {
72   this->CloseStartElement();
73   this->ConditionalLineBreak(!this->IsContent);
74   this->Output << "<!-- " << comment << " -->";
75 }
76
77 void cmXMLWriter::CData(std::string const& data)
78 {
79   this->PreContent();
80   this->Output << "<![CDATA[" << data << "]]>";
81 }
82
83 void cmXMLWriter::Doctype(const char* doctype)
84 {
85   this->CloseStartElement();
86   this->ConditionalLineBreak(!this->IsContent);
87   this->Output << "<!DOCTYPE " << doctype << ">";
88 }
89
90 void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
91 {
92   this->CloseStartElement();
93   this->ConditionalLineBreak(!this->IsContent);
94   this->Output << "<?" << target << ' ' << data << "?>";
95 }
96
97 void cmXMLWriter::FragmentFile(const char* fname)
98 {
99   this->CloseStartElement();
100   cmsys::ifstream fin(fname, std::ios::in | std::ios::binary);
101   this->Output << fin.rdbuf();
102 }
103
104 void cmXMLWriter::SetIndentationElement(std::string const& element)
105 {
106   this->IndentationElement = element;
107 }
108
109 void cmXMLWriter::ConditionalLineBreak(bool condition)
110 {
111   if (condition) {
112     this->Output << '\n';
113     for (std::size_t i = 0; i < this->Indent + this->Level; ++i) {
114       this->Output << this->IndentationElement;
115     }
116   }
117 }
118
119 void cmXMLWriter::PreAttribute()
120 {
121   assert(this->ElementOpen);
122   this->ConditionalLineBreak(this->BreakAttrib);
123   if (!this->BreakAttrib) {
124     this->Output << ' ';
125   }
126 }
127
128 void cmXMLWriter::PreContent()
129 {
130   this->CloseStartElement();
131   this->IsContent = true;
132 }
133
134 void cmXMLWriter::CloseStartElement()
135 {
136   if (this->ElementOpen) {
137     this->ConditionalLineBreak(this->BreakAttrib);
138     this->Output << '>';
139     this->ElementOpen = false;
140   }
141 }