1 /* 2 * Created by Phil on 09/12/2010. 3 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 #ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED 9 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED 10 11 #include "catch_stream.h" 12 #include "catch_compiler_capabilities.h" 13 14 #include <vector> 15 16 namespace Catch { 17 enum class XmlFormatting { 18 None = 0x00, 19 Indent = 0x01, 20 Newline = 0x02, 21 }; 22 23 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); 24 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); 25 26 class XmlEncode { 27 public: 28 enum ForWhat { ForTextNodes, ForAttributes }; 29 30 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); 31 32 void encodeTo( std::ostream& os ) const; 33 34 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); 35 36 private: 37 std::string m_str; 38 ForWhat m_forWhat; 39 }; 40 41 class XmlWriter { 42 public: 43 44 class ScopedElement { 45 public: 46 ScopedElement( XmlWriter* writer, XmlFormatting fmt ); 47 48 ScopedElement( ScopedElement&& other ) noexcept; 49 ScopedElement& operator=( ScopedElement&& other ) noexcept; 50 51 ~ScopedElement(); 52 53 ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); 54 55 template<typename T> writeAttribute(std::string const & name,T const & attribute)56 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { 57 m_writer->writeAttribute( name, attribute ); 58 return *this; 59 } 60 61 private: 62 mutable XmlWriter* m_writer = nullptr; 63 XmlFormatting m_fmt; 64 }; 65 66 XmlWriter( std::ostream& os = Catch::cout() ); 67 ~XmlWriter(); 68 69 XmlWriter( XmlWriter const& ) = delete; 70 XmlWriter& operator=( XmlWriter const& ) = delete; 71 72 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 73 74 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 75 76 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 77 78 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); 79 80 XmlWriter& writeAttribute( std::string const& name, bool attribute ); 81 82 template<typename T> writeAttribute(std::string const & name,T const & attribute)83 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { 84 ReusableStringStream rss; 85 rss << attribute; 86 return writeAttribute( name, rss.str() ); 87 } 88 89 XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 90 91 XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 92 93 void writeStylesheetRef( std::string const& url ); 94 95 XmlWriter& writeBlankLine(); 96 97 void ensureTagClosed(); 98 99 private: 100 101 void applyFormatting(XmlFormatting fmt); 102 103 void writeDeclaration(); 104 105 void newlineIfNecessary(); 106 107 bool m_tagIsOpen = false; 108 bool m_needsNewline = false; 109 std::vector<std::string> m_tags; 110 std::string m_indent; 111 std::ostream& m_os; 112 }; 113 114 } 115 116 #endif // TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED 117