// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "tools/gn/xml_element_writer.h" #include XmlAttributes::XmlAttributes() = default; XmlAttributes::XmlAttributes(const base::StringPiece& attr_key, const base::StringPiece& attr_value) { add(attr_key, attr_value); } XmlAttributes& XmlAttributes::add(const base::StringPiece& attr_key, const base::StringPiece& attr_value) { push_back(std::make_pair(attr_key, attr_value)); return *this; } XmlElementWriter::XmlElementWriter(std::ostream& out, const std::string& tag, const XmlAttributes& attributes) : XmlElementWriter(out, tag, attributes, 0) {} XmlElementWriter::XmlElementWriter(std::ostream& out, const std::string& tag, const XmlAttributes& attributes, int indent) : out_(out), tag_(tag), indent_(indent), opening_tag_finished_(false), one_line_(true) { out << std::string(indent, ' ') << '<' << tag; for (auto attribute : attributes) out << ' ' << attribute.first << "=\"" << attribute.second << '"'; } XmlElementWriter::~XmlElementWriter() { if (!opening_tag_finished_) { // The XML spec does not require a space before the closing slash. However, // Eclipse is unable to parse XML settings files if there is no space. out_ << " />" << std::endl; } else { if (!one_line_) out_ << std::string(indent_, ' '); out_ << "' << std::endl; } } void XmlElementWriter::Text(const base::StringPiece& content) { StartContent(false); out_ << content; } std::unique_ptr XmlElementWriter::SubElement( const std::string& tag) { return SubElement(tag, XmlAttributes()); } std::unique_ptr XmlElementWriter::SubElement( const std::string& tag, const XmlAttributes& attributes) { StartContent(true); return std::make_unique(out_, tag, attributes, indent_ + 2); } std::ostream& XmlElementWriter::StartContent(bool start_new_line) { if (!opening_tag_finished_) { out_ << '>'; opening_tag_finished_ = true; if (start_new_line && one_line_) { out_ << std::endl; one_line_ = false; } } return out_; } std::string XmlEscape(const std::string& value) { std::string result; for (char c : value) { switch (c) { case '\n': result += " "; break; case '\r': result += " "; break; case '\t': result += " "; break; case '"': result += """; break; case '<': result += "<"; break; case '>': result += ">"; break; case '&': result += "&"; break; default: result += c; } } return result; }