xref: /aosp_15_r20/external/image_io/src/xml/xml_writer.cc (revision ca0779eb572efbbfda2e47f806647c3c7eeea8c3)
1*ca0779ebSJerome Gaillard #include "image_io/xml/xml_writer.h"
2*ca0779ebSJerome Gaillard 
3*ca0779ebSJerome Gaillard #include <iomanip>
4*ca0779ebSJerome Gaillard #include <string>
5*ca0779ebSJerome Gaillard 
6*ca0779ebSJerome Gaillard namespace photos_editing_formats {
7*ca0779ebSJerome Gaillard namespace image_io {
8*ca0779ebSJerome Gaillard 
9*ca0779ebSJerome Gaillard using std::ostream;
10*ca0779ebSJerome Gaillard using std::string;
11*ca0779ebSJerome Gaillard using std::vector;
12*ca0779ebSJerome Gaillard 
13*ca0779ebSJerome Gaillard namespace {
14*ca0779ebSJerome Gaillard 
15*ca0779ebSJerome Gaillard const char kXmlnsColon[] = "xmlns:";
16*ca0779ebSJerome Gaillard 
17*ca0779ebSJerome Gaillard }  // namespace
18*ca0779ebSJerome Gaillard 
XmlWriter(std::ostream & os)19*ca0779ebSJerome Gaillard XmlWriter::XmlWriter(std::ostream& os)
20*ca0779ebSJerome Gaillard     : os_(os), element_count_(0), quote_mark_('"') {}
21*ca0779ebSJerome Gaillard 
WriteXmlns(const string & prefix,const string & uri)22*ca0779ebSJerome Gaillard void XmlWriter::WriteXmlns(const string& prefix, const string& uri) {
23*ca0779ebSJerome Gaillard   string name = string(kXmlnsColon) + prefix;
24*ca0779ebSJerome Gaillard   WriteAttributeNameAndValue(name, uri, true);
25*ca0779ebSJerome Gaillard }
26*ca0779ebSJerome Gaillard 
StartWritingElement(const string & element_name)27*ca0779ebSJerome Gaillard size_t XmlWriter::StartWritingElement(const string& element_name) {
28*ca0779ebSJerome Gaillard   MaybeWriteCloseBracket(true);
29*ca0779ebSJerome Gaillard   size_t current_depth = element_data_.size();
30*ca0779ebSJerome Gaillard   if (current_depth > 0) {
31*ca0779ebSJerome Gaillard     element_data_.back().has_children = true;
32*ca0779ebSJerome Gaillard   }
33*ca0779ebSJerome Gaillard   element_data_.emplace_back(element_name);
34*ca0779ebSJerome Gaillard   os_ << indent_ << "<" << element_name;
35*ca0779ebSJerome Gaillard   indent_ += "  ";
36*ca0779ebSJerome Gaillard   element_count_ += 1;
37*ca0779ebSJerome Gaillard   return current_depth;
38*ca0779ebSJerome Gaillard }
39*ca0779ebSJerome Gaillard 
FinishWritingElement()40*ca0779ebSJerome Gaillard void XmlWriter::FinishWritingElement() {
41*ca0779ebSJerome Gaillard   if (!element_data_.empty()) {
42*ca0779ebSJerome Gaillard     if (indent_.size() >= 2) {
43*ca0779ebSJerome Gaillard       indent_.resize(indent_.size() - 2);
44*ca0779ebSJerome Gaillard     }
45*ca0779ebSJerome Gaillard     auto& data = element_data_.back();
46*ca0779ebSJerome Gaillard     if (!data.has_content && !data.has_children) {
47*ca0779ebSJerome Gaillard       if (!data.has_attributes || data.has_children) {
48*ca0779ebSJerome Gaillard         os_ << indent_;
49*ca0779ebSJerome Gaillard       }
50*ca0779ebSJerome Gaillard       os_ << "/>" << std::endl;
51*ca0779ebSJerome Gaillard     } else {
52*ca0779ebSJerome Gaillard       if (!data.has_content) {
53*ca0779ebSJerome Gaillard         os_ << indent_;
54*ca0779ebSJerome Gaillard       }
55*ca0779ebSJerome Gaillard       os_ << "</" << data.name << ">" << std::endl;
56*ca0779ebSJerome Gaillard     }
57*ca0779ebSJerome Gaillard     element_data_.pop_back();
58*ca0779ebSJerome Gaillard   }
59*ca0779ebSJerome Gaillard }
60*ca0779ebSJerome Gaillard 
FinishWritingElementsToDepth(size_t depth)61*ca0779ebSJerome Gaillard void XmlWriter::FinishWritingElementsToDepth(size_t depth) {
62*ca0779ebSJerome Gaillard   if (!element_data_.empty()) {
63*ca0779ebSJerome Gaillard     for (size_t index = element_data_.size(); index > depth; --index) {
64*ca0779ebSJerome Gaillard       FinishWritingElement();
65*ca0779ebSJerome Gaillard     }
66*ca0779ebSJerome Gaillard   }
67*ca0779ebSJerome Gaillard }
68*ca0779ebSJerome Gaillard 
StartWritingElements(const vector<string> & element_names)69*ca0779ebSJerome Gaillard size_t XmlWriter::StartWritingElements(const vector<string>& element_names) {
70*ca0779ebSJerome Gaillard   size_t current_depth = element_data_.size();
71*ca0779ebSJerome Gaillard   for (const auto& element_name : element_names) {
72*ca0779ebSJerome Gaillard     StartWritingElement(element_name);
73*ca0779ebSJerome Gaillard   }
74*ca0779ebSJerome Gaillard   return current_depth;
75*ca0779ebSJerome Gaillard }
76*ca0779ebSJerome Gaillard 
WriteElementAndContent(const string & element_name,const string & content)77*ca0779ebSJerome Gaillard void XmlWriter::WriteElementAndContent(const string& element_name,
78*ca0779ebSJerome Gaillard                                        const string& content) {
79*ca0779ebSJerome Gaillard   StartWritingElement(element_name);
80*ca0779ebSJerome Gaillard   WriteContent(content);
81*ca0779ebSJerome Gaillard   FinishWritingElement();
82*ca0779ebSJerome Gaillard }
83*ca0779ebSJerome Gaillard 
WriteContent(const string & content)84*ca0779ebSJerome Gaillard void XmlWriter::WriteContent(const string& content) {
85*ca0779ebSJerome Gaillard   MaybeWriteCloseBracket(false);
86*ca0779ebSJerome Gaillard   if (!element_data_.empty()) {
87*ca0779ebSJerome Gaillard     auto& data = element_data_.back();
88*ca0779ebSJerome Gaillard     data.has_content = true;
89*ca0779ebSJerome Gaillard     os_ << content;
90*ca0779ebSJerome Gaillard   }
91*ca0779ebSJerome Gaillard }
92*ca0779ebSJerome Gaillard 
WriteAttributeNameAndValue(const string & name,const string & value,bool add_quote_marks)93*ca0779ebSJerome Gaillard void XmlWriter::WriteAttributeNameAndValue(const string& name,
94*ca0779ebSJerome Gaillard                                            const string& value,
95*ca0779ebSJerome Gaillard                                            bool add_quote_marks) {
96*ca0779ebSJerome Gaillard   WriteAttributeName(name);
97*ca0779ebSJerome Gaillard   WriteAttributeValue(add_quote_marks, value, add_quote_marks);
98*ca0779ebSJerome Gaillard }
99*ca0779ebSJerome Gaillard 
WriteAttributeName(const string & name)100*ca0779ebSJerome Gaillard void XmlWriter::WriteAttributeName(const string& name) {
101*ca0779ebSJerome Gaillard   if (!element_data_.empty()) {
102*ca0779ebSJerome Gaillard     os_ << std::endl << indent_ << name << "=";
103*ca0779ebSJerome Gaillard     element_data_.back().has_attributes = true;
104*ca0779ebSJerome Gaillard   }
105*ca0779ebSJerome Gaillard }
106*ca0779ebSJerome Gaillard 
WriteAttributeValue(bool add_leading_quote_mark,const string & value,bool add_trailing_quote_mark)107*ca0779ebSJerome Gaillard void XmlWriter::WriteAttributeValue(bool add_leading_quote_mark,
108*ca0779ebSJerome Gaillard                                     const string& value,
109*ca0779ebSJerome Gaillard                                     bool add_trailing_quote_mark) {
110*ca0779ebSJerome Gaillard   if (!element_data_.empty()) {
111*ca0779ebSJerome Gaillard     if (add_leading_quote_mark) os_ << quote_mark_;
112*ca0779ebSJerome Gaillard     os_ << value;
113*ca0779ebSJerome Gaillard     if (add_trailing_quote_mark) os_ << quote_mark_;
114*ca0779ebSJerome Gaillard   }
115*ca0779ebSJerome Gaillard }
116*ca0779ebSJerome Gaillard 
WriteComment(const std::string & comment)117*ca0779ebSJerome Gaillard void XmlWriter::WriteComment(const std::string& comment) {
118*ca0779ebSJerome Gaillard   MaybeWriteCloseBracket(true);
119*ca0779ebSJerome Gaillard   os_ << indent_ << "<!-- " << comment << " -->" << std::endl;
120*ca0779ebSJerome Gaillard   if (!element_data_.empty()) {
121*ca0779ebSJerome Gaillard     auto& data = element_data_.back();
122*ca0779ebSJerome Gaillard     data.has_children = true;
123*ca0779ebSJerome Gaillard   }
124*ca0779ebSJerome Gaillard }
125*ca0779ebSJerome Gaillard 
MaybeWriteCloseBracket(bool with_trailing_newline)126*ca0779ebSJerome Gaillard bool XmlWriter::MaybeWriteCloseBracket(bool with_trailing_newline) {
127*ca0779ebSJerome Gaillard   if (!element_data_.empty()) {
128*ca0779ebSJerome Gaillard     auto& data = element_data_.back();
129*ca0779ebSJerome Gaillard     if (!data.has_content && !data.has_children) {
130*ca0779ebSJerome Gaillard       os_ << ">";
131*ca0779ebSJerome Gaillard       if (with_trailing_newline) {
132*ca0779ebSJerome Gaillard         os_ << std::endl;
133*ca0779ebSJerome Gaillard       }
134*ca0779ebSJerome Gaillard       return true;
135*ca0779ebSJerome Gaillard     }
136*ca0779ebSJerome Gaillard   }
137*ca0779ebSJerome Gaillard   return false;
138*ca0779ebSJerome Gaillard }
139*ca0779ebSJerome Gaillard 
140*ca0779ebSJerome Gaillard }  // namespace image_io
141*ca0779ebSJerome Gaillard }  // namespace photos_editing_formats
142