xref: /aosp_15_r20/external/clpeak/include/xml_writer.h (revision 1cd03ba3888297bc945f2c84574e105e3ced3e34)
1*1cd03ba3SJeremy Kemp /*
2*1cd03ba3SJeremy Kemp  * Courtesy: https://gist.github.com/sebclaeys/1227644
3*1cd03ba3SJeremy Kemp  */
4*1cd03ba3SJeremy Kemp 
5*1cd03ba3SJeremy Kemp 
6*1cd03ba3SJeremy Kemp #ifndef XML_WRITER_H
7*1cd03ba3SJeremy Kemp # define XML_WRITER_H
8*1cd03ba3SJeremy Kemp 
9*1cd03ba3SJeremy Kemp # define HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
10*1cd03ba3SJeremy Kemp # define INDENT "  "
11*1cd03ba3SJeremy Kemp # define NEWLINE "\n"
12*1cd03ba3SJeremy Kemp 
13*1cd03ba3SJeremy Kemp # include <string>
14*1cd03ba3SJeremy Kemp # include <stack>
15*1cd03ba3SJeremy Kemp # include <iostream>
16*1cd03ba3SJeremy Kemp 
17*1cd03ba3SJeremy Kemp class xmlWriter
18*1cd03ba3SJeremy Kemp {
19*1cd03ba3SJeremy Kemp public:
20*1cd03ba3SJeremy Kemp 
xmlWriter(std::ostream & os)21*1cd03ba3SJeremy Kemp   xmlWriter(std::ostream& os) : os(os), tag_open(false), new_line(true) {os << HEADER;}
~xmlWriter()22*1cd03ba3SJeremy Kemp   ~xmlWriter() {}
23*1cd03ba3SJeremy Kemp 
openElt(const char * tag)24*1cd03ba3SJeremy Kemp   xmlWriter& openElt(const char* tag) {
25*1cd03ba3SJeremy Kemp     this->closeTag();
26*1cd03ba3SJeremy Kemp     if (elt_stack.size() > 0)
27*1cd03ba3SJeremy Kemp       os << NEWLINE;
28*1cd03ba3SJeremy Kemp     this->indent();
29*1cd03ba3SJeremy Kemp     this->os << "<" << tag;
30*1cd03ba3SJeremy Kemp     elt_stack.push(tag);
31*1cd03ba3SJeremy Kemp     tag_open = true;
32*1cd03ba3SJeremy Kemp     new_line = false;
33*1cd03ba3SJeremy Kemp     return *this;
34*1cd03ba3SJeremy Kemp   }
35*1cd03ba3SJeremy Kemp 
closeElt()36*1cd03ba3SJeremy Kemp   xmlWriter& closeElt() {
37*1cd03ba3SJeremy Kemp     this->closeTag();
38*1cd03ba3SJeremy Kemp     std::string elt = elt_stack.top();
39*1cd03ba3SJeremy Kemp     this->elt_stack.pop();
40*1cd03ba3SJeremy Kemp     if (new_line)
41*1cd03ba3SJeremy Kemp     {
42*1cd03ba3SJeremy Kemp       os << NEWLINE;
43*1cd03ba3SJeremy Kemp       this->indent();
44*1cd03ba3SJeremy Kemp     }
45*1cd03ba3SJeremy Kemp     new_line = true;
46*1cd03ba3SJeremy Kemp     this->os << "</" << elt << ">";
47*1cd03ba3SJeremy Kemp     return *this;
48*1cd03ba3SJeremy Kemp   }
49*1cd03ba3SJeremy Kemp 
closeAll()50*1cd03ba3SJeremy Kemp   xmlWriter& closeAll() {
51*1cd03ba3SJeremy Kemp     while (elt_stack.size())
52*1cd03ba3SJeremy Kemp       this->closeElt();
53*1cd03ba3SJeremy Kemp     return *this;
54*1cd03ba3SJeremy Kemp   }
55*1cd03ba3SJeremy Kemp 
attr(const char * key,const char * val)56*1cd03ba3SJeremy Kemp   xmlWriter& attr(const char* key, const char* val) {
57*1cd03ba3SJeremy Kemp     this->os << " " << key << "=\"";
58*1cd03ba3SJeremy Kemp     this->write_escape(val);
59*1cd03ba3SJeremy Kemp     this->os << "\"";
60*1cd03ba3SJeremy Kemp     return *this;
61*1cd03ba3SJeremy Kemp   }
62*1cd03ba3SJeremy Kemp 
attr(const char * key,std::string val)63*1cd03ba3SJeremy Kemp   xmlWriter& attr(const char* key, std::string val) {
64*1cd03ba3SJeremy Kemp     return attr(key, val.c_str());
65*1cd03ba3SJeremy Kemp   }
66*1cd03ba3SJeremy Kemp 
content(const char * val)67*1cd03ba3SJeremy Kemp   xmlWriter& content(const char* val) {
68*1cd03ba3SJeremy Kemp     this->closeTag();
69*1cd03ba3SJeremy Kemp     this->write_escape(val);
70*1cd03ba3SJeremy Kemp     return *this;
71*1cd03ba3SJeremy Kemp   }
72*1cd03ba3SJeremy Kemp 
73*1cd03ba3SJeremy Kemp private:
74*1cd03ba3SJeremy Kemp   std::ostream& os;
75*1cd03ba3SJeremy Kemp   bool tag_open;
76*1cd03ba3SJeremy Kemp   bool new_line;
77*1cd03ba3SJeremy Kemp   std::stack<std::string> elt_stack;
78*1cd03ba3SJeremy Kemp 
closeTag()79*1cd03ba3SJeremy Kemp   inline void closeTag() {
80*1cd03ba3SJeremy Kemp     if (tag_open)
81*1cd03ba3SJeremy Kemp     {
82*1cd03ba3SJeremy Kemp       this->os << ">";
83*1cd03ba3SJeremy Kemp       tag_open = false;
84*1cd03ba3SJeremy Kemp     }
85*1cd03ba3SJeremy Kemp   }
86*1cd03ba3SJeremy Kemp 
indent()87*1cd03ba3SJeremy Kemp   inline void indent() {
88*1cd03ba3SJeremy Kemp     for (int i = 0; i < (int)elt_stack.size(); i++)
89*1cd03ba3SJeremy Kemp       os << (INDENT);
90*1cd03ba3SJeremy Kemp   }
91*1cd03ba3SJeremy Kemp 
write_escape(const char * str)92*1cd03ba3SJeremy Kemp   inline void write_escape(const char* str) {
93*1cd03ba3SJeremy Kemp     for (; *str; str++)
94*1cd03ba3SJeremy Kemp       switch (*str) {
95*1cd03ba3SJeremy Kemp       case '&': os << "&amp;"; break;
96*1cd03ba3SJeremy Kemp       case '<': os << "&lt;"; break;
97*1cd03ba3SJeremy Kemp       case '>': os << "&gt;"; break;
98*1cd03ba3SJeremy Kemp       case '\'': os << "&apos;"; break;
99*1cd03ba3SJeremy Kemp       case '"': os << "&quot;"; break;
100*1cd03ba3SJeremy Kemp       default: os.put(*str); break;
101*1cd03ba3SJeremy Kemp       }
102*1cd03ba3SJeremy Kemp   }
103*1cd03ba3SJeremy Kemp };
104*1cd03ba3SJeremy Kemp 
105*1cd03ba3SJeremy Kemp #endif /* !XML_WRITER_H */
106