daemon: Fix possible use-after-free.
[jackhill/guix/guix.git] / nix / libutil / xml-writer.cc
CommitLineData
36457566
LC
1#include <assert.h>
2
3#include "xml-writer.hh"
4
5
6namespace nix {
7
8
9XMLWriter::XMLWriter(bool indent, std::ostream & output)
10 : output(output), indent(indent)
11{
12 output << "<?xml version='1.0' encoding='utf-8'?>" << std::endl;
13 closed = false;
14}
15
16
17XMLWriter::~XMLWriter()
18{
19 close();
20}
21
22
23void XMLWriter::close()
24{
25 if (closed) return;
26 while (!pendingElems.empty()) closeElement();
27 closed = true;
28}
29
30
31void XMLWriter::indent_(unsigned int depth)
32{
33 if (!indent) return;
34 output << string(depth * 2, ' ');
35}
36
37
38void XMLWriter::openElement(const string & name,
39 const XMLAttrs & attrs)
40{
41 assert(!closed);
42 indent_(pendingElems.size());
43 output << "<" << name;
44 writeAttrs(attrs);
45 output << ">";
46 if (indent) output << std::endl;
47 pendingElems.push_back(name);
48}
49
50
51void XMLWriter::closeElement()
52{
53 assert(!pendingElems.empty());
54 indent_(pendingElems.size() - 1);
55 output << "</" << pendingElems.back() << ">";
56 if (indent) output << std::endl;
57 pendingElems.pop_back();
58 if (pendingElems.empty()) closed = true;
59}
60
61
62void XMLWriter::writeEmptyElement(const string & name,
63 const XMLAttrs & attrs)
64{
65 assert(!closed);
66 indent_(pendingElems.size());
67 output << "<" << name;
68 writeAttrs(attrs);
69 output << " />";
70 if (indent) output << std::endl;
71}
72
73
74void XMLWriter::writeAttrs(const XMLAttrs & attrs)
75{
76 for (XMLAttrs::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
77 output << " " << i->first << "=\"";
78 for (unsigned int j = 0; j < i->second.size(); ++j) {
79 char c = i->second[j];
80 if (c == '"') output << "&quot;";
81 else if (c == '<') output << "&lt;";
82 else if (c == '>') output << "&gt;";
83 else if (c == '&') output << "&amp;";
84 /* Escape newlines to prevent attribute normalisation (see
85 XML spec, section 3.3.3. */
86 else if (c == '\n') output << "&#xA;";
87 else output << c;
88 }
89 output << "\"";
90 }
91}
92
93
94}