Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:51

0001 
0002 //              Copyright Catch2 Authors
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //   (See accompanying file LICENSE.txt or copy at
0005 //        https://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // SPDX-License-Identifier: BSL-1.0
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      * Helper for XML-encoding text (escaping angle brackets, quotes, etc)
0029      *
0030      * Note: doesn't take ownership of passed strings, and thus the
0031      *       encoded string must outlive the encoding instance.
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                       // Without this SFINAE, this overload is a better match
0069                       // for `std::string`, `char const*`, `char const[N]` args.
0070                       // While it would still work, it would cause code bloat
0071                       // and multiple iteration over the strings
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         //! The attribute content is XML-encoded
0098         XmlWriter& writeAttribute( StringRef name, StringRef attribute );
0099 
0100         //! Writes the attribute as "true/false"
0101         XmlWriter& writeAttribute( StringRef name, bool attribute );
0102 
0103         //! The attribute content is XML-encoded
0104         XmlWriter& writeAttribute( StringRef name, char const* attribute );
0105 
0106         //! The attribute value must provide op<<(ostream&, T). The resulting
0107         //! serialization is XML-encoded
0108         template <typename T,
0109                   // Without this SFINAE, this overload is a better match
0110                   // for `std::string`, `char const*`, `char const[N]` args.
0111                   // While it would still work, it would cause code bloat
0112                   // and multiple iteration over the strings
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         //! Writes escaped `text` in a element
0122         XmlWriter& writeText( StringRef text,
0123                               XmlFormatting fmt = XmlFormatting::Newline |
0124                                                   XmlFormatting::Indent );
0125 
0126         //! Writes XML comment as "<!-- text -->"
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 // CATCH_XMLWRITER_HPP_INCLUDED