#ifndef RFL_XML_WRITE_HPP_ #define RFL_XML_WRITE_HPP_ #include #include #include #include #include #include "../Processors.hpp" #include "../internal/StringLiteral.hpp" #include "../internal/get_type_name.hpp" #include "../internal/remove_namespaces.hpp" #include "../parsing/Parent.hpp" #include "Parser.hpp" namespace rfl { namespace xml { template consteval auto get_root_name() { if constexpr (_root != internal::StringLiteral("")) { return _root; } else { return internal::remove_namespaces< internal::get_type_name>()>(); } } /// Writes a XML into an ostream. template std::ostream& write(const auto& _obj, std::ostream& _stream, const std::string& _indent = " ") { using T = std::remove_cvref_t; using ParentType = parsing::Parent; constexpr auto root_name = get_root_name<_root, T>(); static_assert( root_name.string_view().find("<") == std::string_view::npos && root_name.string_view().find(">") == std::string_view::npos, "The name of an XML root node cannot contain '<' or '>'. " "Please assign an " "explicit root name to rfl::xml::write(...) like this: " "rfl::xml::write<\"root_name\">(...)."); const auto doc = rfl::Ref::make(); auto declaration_node = doc->append_child(pugi::node_declaration); declaration_node.append_attribute("version") = "1.0"; declaration_node.append_attribute("encoding") = "UTF-8"; auto w = Writer(doc, root_name.str()); Parser>::write(w, _obj, typename ParentType::Root {}); doc->save(_stream, _indent.c_str()); return _stream; } /// Returns a XML string. template std::string write(const auto& _obj, const std::string& _indent = " ") { std::stringstream stream; write<_root, Ps...>(_obj, stream); return stream.str(); } } // namespace xml } // namespace rfl #endif // XML_PARSER_HPP_