File indexing completed on 2025-01-30 10:02:51
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef CATCH_XMLWRITER_HPP_INCLUDED
0009 #define CATCH_XMLWRITER_HPP_INCLUDED
0010
0011 #include <catch2/internal/catch_reusable_string_stream.hpp>
0012 #include <catch2/internal/catch_stringref.hpp>
0013
0014 #include <iosfwd>
0015 #include <vector>
0016
0017 namespace Catch {
0018 enum class XmlFormatting {
0019 None = 0x00,
0020 Indent = 0x01,
0021 Newline = 0x02,
0022 };
0023
0024 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs);
0025 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs);
0026
0027
0028
0029
0030
0031
0032
0033 class XmlEncode {
0034 public:
0035 enum ForWhat { ForTextNodes, ForAttributes };
0036
0037 XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes );
0038
0039 void encodeTo( std::ostream& os ) const;
0040
0041 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
0042
0043 private:
0044 StringRef m_str;
0045 ForWhat m_forWhat;
0046 };
0047
0048 class XmlWriter {
0049 public:
0050
0051 class ScopedElement {
0052 public:
0053 ScopedElement( XmlWriter* writer, XmlFormatting fmt );
0054
0055 ScopedElement( ScopedElement&& other ) noexcept;
0056 ScopedElement& operator=( ScopedElement&& other ) noexcept;
0057
0058 ~ScopedElement();
0059
0060 ScopedElement&
0061 writeText( StringRef text,
0062 XmlFormatting fmt = XmlFormatting::Newline |
0063 XmlFormatting::Indent );
0064
0065 ScopedElement& writeAttribute( StringRef name,
0066 StringRef attribute );
0067 template <typename T,
0068
0069
0070
0071
0072 typename = typename std::enable_if_t<
0073 !std::is_convertible<T, StringRef>::value>>
0074 ScopedElement& writeAttribute( StringRef name,
0075 T const& attribute ) {
0076 m_writer->writeAttribute( name, attribute );
0077 return *this;
0078 }
0079
0080 private:
0081 XmlWriter* m_writer = nullptr;
0082 XmlFormatting m_fmt;
0083 };
0084
0085 XmlWriter( std::ostream& os );
0086 ~XmlWriter();
0087
0088 XmlWriter( XmlWriter const& ) = delete;
0089 XmlWriter& operator=( XmlWriter const& ) = delete;
0090
0091 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
0092
0093 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
0094
0095 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
0096
0097
0098 XmlWriter& writeAttribute( StringRef name, StringRef attribute );
0099
0100
0101 XmlWriter& writeAttribute( StringRef name, bool attribute );
0102
0103
0104 XmlWriter& writeAttribute( StringRef name, char const* attribute );
0105
0106
0107
0108 template <typename T,
0109
0110
0111
0112
0113 typename = typename std::enable_if_t<
0114 !std::is_convertible<T, StringRef>::value>>
0115 XmlWriter& writeAttribute( StringRef name, T const& attribute ) {
0116 ReusableStringStream rss;
0117 rss << attribute;
0118 return writeAttribute( name, rss.str() );
0119 }
0120
0121
0122 XmlWriter& writeText( StringRef text,
0123 XmlFormatting fmt = XmlFormatting::Newline |
0124 XmlFormatting::Indent );
0125
0126
0127 XmlWriter& writeComment( StringRef text,
0128 XmlFormatting fmt = XmlFormatting::Newline |
0129 XmlFormatting::Indent );
0130
0131 void writeStylesheetRef( StringRef url );
0132
0133 void ensureTagClosed();
0134
0135 private:
0136
0137 void applyFormatting(XmlFormatting fmt);
0138
0139 void writeDeclaration();
0140
0141 void newlineIfNecessary();
0142
0143 bool m_tagIsOpen = false;
0144 bool m_needsNewline = false;
0145 std::vector<std::string> m_tags;
0146 std::string m_indent;
0147 std::ostream& m_os;
0148 };
0149
0150 }
0151
0152 #endif