#ifndef TOOLS_GN_XML_ELEMENT_WRITER_H_
#define TOOLS_GN_XML_ELEMENT_WRITER_H_
#include <memory>
#include <ostream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
class XmlAttributes
: public std::vector<std::pair<std::string_view, std::string_view>> {
public:
XmlAttributes();
XmlAttributes(std::string_view attr_key, std::string_view attr_value);
XmlAttributes& add(std::string_view attr_key, std::string_view attr_value);
};
class XmlElementWriter {
public:
XmlElementWriter(std::ostream& out,
const std::string& tag,
const XmlAttributes& attributes);
XmlElementWriter(std::ostream& out,
const std::string& tag,
const XmlAttributes& attributes,
int indent);
template <class Writer>
XmlElementWriter(std::ostream& out,
const std::string& tag,
const std::string& attribute_name,
const Writer& attribute_value_writer,
int indent);
~XmlElementWriter();
void Text(std::string_view content);
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);
std::ostream& StartContent(bool start_new_line);
private:
std::ostream& out_;
std::string tag_;
int indent_;
bool opening_tag_finished_;
bool one_line_;
XmlElementWriter(const XmlElementWriter&) = delete;
XmlElementWriter& operator=(const XmlElementWriter&) = delete;
};
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