/src/libprotobuf-mutator/examples/xml/xml_writer.cc
Line | Count | Source |
1 | | // Copyright 2017 Google Inc. All rights reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "examples/xml/xml_writer.h" |
16 | | |
17 | | #include <algorithm> |
18 | | #include <sstream> |
19 | | |
20 | | #include "examples/xml/xml.pb.h" |
21 | | |
22 | | namespace protobuf_mutator { |
23 | | namespace xml { |
24 | | |
25 | | namespace { |
26 | | |
27 | | class XmlWriter { |
28 | | public: |
29 | | XmlWriter(); |
30 | | std::string ToXml(const Document& doc); |
31 | | |
32 | | private: |
33 | | void ToXml(const std::string& name, const std::string& value); |
34 | | void ToXml(const Element& element); |
35 | | void ToXml(const Content& content); |
36 | | void ToXml(const Misk& misk); |
37 | | void ToXml(const DoctypeDecl& doctype); |
38 | | |
39 | | std::ostringstream out_; |
40 | | }; |
41 | | |
42 | 32.3k | XmlWriter::XmlWriter() {} |
43 | | |
44 | 17.6k | void XmlWriter::ToXml(const std::string& name, const std::string& value) { |
45 | 17.6k | char quote = (name.size() % 2) ? '"' : '\''; |
46 | 17.6k | out_ << " " << name << "=" << quote << value << quote; |
47 | 17.6k | } |
48 | | |
49 | 1.74k | void XmlWriter::ToXml(const Misk& misk) { |
50 | 1.74k | if (misk.has_pi()) { |
51 | 465 | out_ << "<?" << misk.pi().target() << misk.pi().data() << "?>"; |
52 | 465 | } |
53 | | |
54 | 1.74k | if (misk.has_comment()) { |
55 | 1.25k | out_ << "<!--" << misk.comment() << "-->"; |
56 | 1.25k | } |
57 | 1.74k | } |
58 | | |
59 | 13.8k | void XmlWriter::ToXml(const DoctypeDecl& doctype) { |
60 | 13.8k | out_ << "<!DOCTYPE " << doctype.name(); |
61 | 13.8k | if (doctype.has_external_id()) out_ << " " << doctype.external_id(); |
62 | 13.8k | if (doctype.has_int_subset()) out_ << " [" << doctype.int_subset() << "]"; |
63 | 14.1k | for (int i = 0; i < doctype.misk_size(); ++i) ToXml(doctype.misk(i)); |
64 | 13.8k | out_ << ">"; |
65 | 13.8k | } |
66 | | |
67 | 6.64k | void XmlWriter::ToXml(const Content& content) { |
68 | 6.64k | if (content.has_char_data()) out_ << content.char_data(); |
69 | 6.64k | if (content.has_element()) ToXml(content.element()); |
70 | 6.64k | if (content.has_reference()) { |
71 | 31 | out_ << (content.reference().entry() ? '&' : '%') |
72 | 31 | << content.reference().name() << ';'; |
73 | 31 | } |
74 | 6.64k | if (content.has_cdsect()) out_ << "<![CDATA[" << content.cdsect() << "]]>"; |
75 | | |
76 | 6.64k | if (content.has_misk()) ToXml(content.misk()); |
77 | 6.64k | } |
78 | | |
79 | 32.9k | void XmlWriter::ToXml(const Element& element) { |
80 | 32.9k | std::string tag; |
81 | 32.9k | std::string name; |
82 | 32.9k | tag += element.tag().name(); |
83 | 32.9k | out_ << "<" << tag; |
84 | | |
85 | 33.7k | for (int i = 0; i < element.tag().attribute_size(); ++i) { |
86 | 804 | ToXml(element.tag().attribute(i).name(), |
87 | 804 | element.tag().attribute(i).value()); |
88 | 804 | } |
89 | | |
90 | 32.9k | if (element.content_size() == 0) { |
91 | 26.7k | out_ << "/>"; |
92 | 26.7k | } else { |
93 | 6.25k | out_ << ">"; |
94 | 12.9k | for (int i = 0; i < element.content_size(); ++i) ToXml(element.content(i)); |
95 | 6.25k | out_ << "</" << tag << ">"; |
96 | 6.25k | } |
97 | 32.9k | } |
98 | | |
99 | 32.3k | std::string XmlWriter::ToXml(const Document& doc) { |
100 | 32.3k | out_.str(""); |
101 | | |
102 | 32.3k | if (doc.has_version() || doc.has_encoding() || doc.has_standalone()) { |
103 | 15.5k | out_ << "<?xml"; |
104 | 15.5k | if (doc.has_version()) |
105 | 12.3k | ToXml("version", (doc.version().size() == 7) ? "1.0" : doc.version()); |
106 | 15.5k | if (doc.has_encoding()) ToXml("encoding", doc.encoding()); |
107 | 15.5k | if (doc.has_standalone()) |
108 | 138 | ToXml("encoding", doc.standalone() ? "yes" : "no"); |
109 | 15.5k | out_ << "?>"; |
110 | 15.5k | } |
111 | | |
112 | 32.7k | for (int i = 0; i < doc.misk1_size(); ++i) ToXml(doc.misk1(i)); |
113 | 32.3k | if (doc.has_doctype()) ToXml(doc.doctype()); |
114 | 32.3k | ToXml(doc.element()); |
115 | 33.3k | for (int i = 0; i < doc.misk2_size(); ++i) ToXml(doc.misk2(i)); |
116 | | |
117 | 32.3k | return out_.str(); |
118 | 32.3k | } |
119 | | |
120 | | } // namespace |
121 | | |
122 | 32.3k | std::string MessageToXml(const Document& document) { |
123 | 32.3k | XmlWriter writer; |
124 | 32.3k | return writer.ToXml(document); |
125 | 32.3k | } |
126 | | |
127 | | } // namespace xml |
128 | | } // namespace protobuf_mutator |