blob: e280b66707b432a6e061fcc0cf0480b839e50350 [file] [log] [blame]
#include "image_io/xml/xml_writer.h"
#include <iomanip>
#include <string>
namespace photos_editing_formats {
namespace image_io {
using std::ostream;
using std::string;
using std::vector;
namespace {
const char kXmlnsColon[] = "xmlns:";
} // namespace
XmlWriter::XmlWriter(std::ostream& os)
: os_(os), element_count_(0), quote_mark_('"') {}
void XmlWriter::WriteXmlns(const string& prefix, const string& uri) {
string name = string(kXmlnsColon) + prefix;
WriteAttributeNameAndValue(name, uri, true);
}
size_t XmlWriter::StartWritingElement(const string& element_name) {
MaybeWriteCloseBracket(true);
size_t current_depth = element_data_.size();
if (current_depth > 0) {
element_data_.back().has_children = true;
}
element_data_.emplace_back(element_name);
os_ << indent_ << "<" << element_name;
indent_ += " ";
element_count_ += 1;
return current_depth;
}
void XmlWriter::FinishWritingElement() {
if (!element_data_.empty()) {
if (indent_.size() >= 2) {
indent_.resize(indent_.size() - 2);
}
auto& data = element_data_.back();
if (!data.has_content && !data.has_children) {
if (!data.has_attributes || data.has_children) {
os_ << indent_;
}
os_ << "/>" << std::endl;
} else {
if (!data.has_content) {
os_ << indent_;
}
os_ << "</" << data.name << ">" << std::endl;
}
element_data_.pop_back();
}
}
void XmlWriter::FinishWritingElementsToDepth(size_t depth) {
if (!element_data_.empty()) {
for (size_t index = element_data_.size(); index > depth; --index) {
FinishWritingElement();
}
}
}
size_t XmlWriter::StartWritingElements(const vector<string>& element_names) {
size_t current_depth = element_data_.size();
for (const auto& element_name : element_names) {
StartWritingElement(element_name);
}
return current_depth;
}
void XmlWriter::WriteElementAndContent(const string& element_name,
const string& content) {
StartWritingElement(element_name);
WriteContent(content);
FinishWritingElement();
}
void XmlWriter::WriteContent(const string& content) {
MaybeWriteCloseBracket(false);
if (!element_data_.empty()) {
auto& data = element_data_.back();
data.has_content = true;
os_ << content;
}
}
void XmlWriter::WriteAttributeNameAndValue(const string& name,
const string& value,
bool add_quote_marks) {
WriteAttributeName(name);
WriteAttributeValue(add_quote_marks, value, add_quote_marks);
}
void XmlWriter::WriteAttributeName(const string& name) {
if (!element_data_.empty()) {
os_ << std::endl << indent_ << name << "=";
element_data_.back().has_attributes = true;
}
}
void XmlWriter::WriteAttributeValue(bool add_leading_quote_mark,
const string& value,
bool add_trailing_quote_mark) {
if (!element_data_.empty()) {
if (add_leading_quote_mark) os_ << quote_mark_;
os_ << value;
if (add_trailing_quote_mark) os_ << quote_mark_;
}
}
void XmlWriter::WriteComment(const std::string& comment) {
MaybeWriteCloseBracket(true);
os_ << indent_ << "<!-- " << comment << " -->" << std::endl;
if (!element_data_.empty()) {
auto& data = element_data_.back();
data.has_children = true;
}
}
bool XmlWriter::MaybeWriteCloseBracket(bool with_trailing_newline) {
if (!element_data_.empty()) {
auto& data = element_data_.back();
if (!data.has_content && !data.has_children) {
os_ << ">";
if (with_trailing_newline) {
os_ << std::endl;
}
return true;
}
}
return false;
}
} // namespace image_io
} // namespace photos_editing_formats