|  | // 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. | 
|  |  | 
|  | #ifndef TOOLS_GN_XML_ELEMENT_WRITER_H_ | 
|  | #define TOOLS_GN_XML_ELEMENT_WRITER_H_ | 
|  |  | 
|  | #include <iosfwd> | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/strings/string_piece.h" | 
|  |  | 
|  | // Vector of XML attribute key-value pairs. | 
|  | class XmlAttributes | 
|  | : public std::vector<std::pair<base::StringPiece, base::StringPiece>> { | 
|  | public: | 
|  | XmlAttributes(); | 
|  | XmlAttributes(const base::StringPiece& attr_key, | 
|  | const base::StringPiece& attr_value); | 
|  |  | 
|  | XmlAttributes& add(const base::StringPiece& attr_key, | 
|  | const base::StringPiece& attr_value); | 
|  | }; | 
|  |  | 
|  | // Helper class for writing XML elements. New XML element is started in | 
|  | // XmlElementWriter constructor and ended in its destructor. XmlElementWriter | 
|  | // handles XML file formatting in order to produce human-readable document. | 
|  | class XmlElementWriter { | 
|  | public: | 
|  | // Starts new XML element. This constructor adds no indentation and is | 
|  | // designed for XML root element. | 
|  | XmlElementWriter(std::ostream& out, | 
|  | const std::string& tag, | 
|  | const XmlAttributes& attributes); | 
|  | // Starts new XML element with specified indentation. | 
|  | XmlElementWriter(std::ostream& out, | 
|  | const std::string& tag, | 
|  | const XmlAttributes& attributes, | 
|  | int indent); | 
|  | // Starts new XML element with specified indentation. Specialized constructor | 
|  | // that allows writting XML element with single attribute without copying | 
|  | // attribute value. | 
|  | template <class Writer> | 
|  | XmlElementWriter(std::ostream& out, | 
|  | const std::string& tag, | 
|  | const std::string& attribute_name, | 
|  | const Writer& attribute_value_writer, | 
|  | int indent); | 
|  | // Ends XML element. All sub-elements should be ended at this point. | 
|  | ~XmlElementWriter(); | 
|  |  | 
|  | // Writes arbitrary XML element text. | 
|  | void Text(const base::StringPiece& content); | 
|  |  | 
|  | // Starts new XML sub-element. Caller must ensure that parent element outlives | 
|  | // its children. | 
|  | std::unique_ptr<XmlElementWriter> SubElement(const std::string& tag); | 
|  | std::unique_ptr<XmlElementWriter> SubElement(const std::string& tag, | 
|  | const XmlAttributes& attributes); | 
|  | template <class Writer> | 
|  | std::unique_ptr<XmlElementWriter> SubElement( | 
|  | const std::string& tag, | 
|  | const std::string& attribute_name, | 
|  | const Writer& attribute_value_writer); | 
|  |  | 
|  | // Finishes opening tag if it isn't finished yet and optionally starts new | 
|  | // document line. Returns the stream where XML element content can be written. | 
|  | // This is an alternative to Text() and SubElement() methods. | 
|  | std::ostream& StartContent(bool start_new_line); | 
|  |  | 
|  | private: | 
|  | // Output stream. XmlElementWriter objects for XML element and its | 
|  | // sub-elements share the same output stream. | 
|  | std::ostream& out_; | 
|  |  | 
|  | // XML element tag name. | 
|  | std::string tag_; | 
|  |  | 
|  | // XML element indentation in the document. | 
|  | int indent_; | 
|  |  | 
|  | // Flag indicating if opening tag is finished with '>' character already. | 
|  | bool opening_tag_finished_; | 
|  |  | 
|  | // Flag indicating if XML element should be written in one document line. | 
|  | bool one_line_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(XmlElementWriter); | 
|  | }; | 
|  |  | 
|  | template <class Writer> | 
|  | XmlElementWriter::XmlElementWriter(std::ostream& out, | 
|  | const std::string& tag, | 
|  | const std::string& attribute_name, | 
|  | const Writer& attribute_value_writer, | 
|  | int indent) | 
|  | : out_(out), | 
|  | tag_(tag), | 
|  | indent_(indent), | 
|  | opening_tag_finished_(false), | 
|  | one_line_(true) { | 
|  | out << std::string(indent, ' ') << '<' << tag; | 
|  | out << ' ' << attribute_name << "=\""; | 
|  | attribute_value_writer(out); | 
|  | out << '\"'; | 
|  | } | 
|  |  | 
|  | template <class Writer> | 
|  | std::unique_ptr<XmlElementWriter> XmlElementWriter::SubElement( | 
|  | const std::string& tag, | 
|  | const std::string& attribute_name, | 
|  | const Writer& attribute_value_writer) { | 
|  | StartContent(true); | 
|  | return std::make_unique<XmlElementWriter>( | 
|  | out_, tag, attribute_name, attribute_value_writer, indent_ + 2); | 
|  | } | 
|  |  | 
|  | std::string XmlEscape(const std::string& value); | 
|  |  | 
|  | #endif  // TOOLS_GN_XML_ELEMENT_WRITER_H_ |