LCOV - code coverage report
Current view: top level - app/libs/rapidxml - rapidxml_print.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 73 196 37.2 %
Date: 2023-08-17 16:45:52 Functions: 5 12 41.7 %

          Line data    Source code
       1             : #ifndef RAPIDXML_PRINT_HPP_INCLUDED
       2             : #define RAPIDXML_PRINT_HPP_INCLUDED
       3             : 
       4             : // Copyright (C) 2006, 2009 Marcin Kalicinski
       5             : // Version 1.13
       6             : // Revision $DateTime: 2009/05/13 01:46:17 $
       7             : //! \file rapidxml_print.hpp This file contains rapidxml printer implementation
       8             : 
       9             : #include "rapidxml.hpp"
      10             : 
      11             : // Only include streams if not disabled
      12             : #ifndef RAPIDXML_NO_STREAMS
      13             :     #include <ostream>
      14             :     #include <iterator>
      15             : #endif
      16             : 
      17             : namespace rapidxml
      18             : {
      19             : 
      20             :     ///////////////////////////////////////////////////////////////////////
      21             :     // Printing flags
      22             : 
      23             :     const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
      24             : 
      25             :     ///////////////////////////////////////////////////////////////////////
      26             :     // Internal
      27             : 
      28             :     //! \cond internal
      29             :     namespace internal
      30             :     {
      31             :         
      32             :         ///////////////////////////////////////////////////////////////////////////
      33             :         // Internal character operations
      34             :     
      35             :         // Copy characters from given range to given output iterator
      36             :         template<class OutIt, class Ch>
      37      154438 :         inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
      38             :         {
      39     1061770 :             while (begin != end)
      40      907328 :                 *out++ = *begin++;
      41      154438 :             return out;
      42             :         }
      43             :         
      44             :         // Copy characters from given range to given output iterator and expand
      45             :         // characters into references (&lt; &gt; &apos; &quot; &amp;)
      46             :         template<class OutIt, class Ch>
      47      135130 :         inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
      48             :         {
      49     1426100 :             while (begin != end)
      50             :             {
      51     1290970 :                 if (*begin == noexpand)
      52             :                 {
      53           0 :                     *out++ = *begin;    // No expansion, copy character
      54             :                 }
      55             :                 else
      56             :                 {
      57     1290970 :                     switch (*begin)
      58             :                     {
      59           0 :                     case Ch('<'):
      60           0 :                         *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
      61             :                         break;
      62           0 :                     case Ch('>'): 
      63           0 :                         *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
      64             :                         break;
      65           0 :                     case Ch('\''): 
      66           0 :                         *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
      67             :                         break;
      68           0 :                     case Ch('"'): 
      69           0 :                         *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
      70             :                         break;
      71           0 :                     case Ch('&'): 
      72           0 :                         *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
      73             :                         break;
      74             :                     default:
      75     1290970 :                         *out++ = *begin;    // No expansion, copy character
      76             :                     }
      77             :                 }
      78     1290970 :                 ++begin;    // Step to next character
      79             :             }
      80      135130 :             return out;
      81             :         }
      82             : 
      83             :         // Fill given output iterator with repetitions of the same character
      84             :         template<class OutIt, class Ch>
      85             :         inline OutIt fill_chars(OutIt out, int n, Ch ch)
      86             :         {
      87       38610 :             for (int i = 0; i < n; ++i)
      88       38610 :                 *out++ = ch;
      89       19308 :             return out;
      90             :         }
      91             : 
      92             :         // Find character
      93             :         template<class Ch, Ch ch>
      94      135130 :         inline bool find_char(const Ch *begin, const Ch *end)
      95             :         {
      96     1426100 :             while (begin != end)
      97     1290970 :                 if (*begin++ == ch)
      98             :                     return true;
      99             :             return false;
     100             :         }
     101             : 
     102             :         ///////////////////////////////////////////////////////////////////////////
     103             :         // Internal printing operations
     104             : 
     105             :         // Print node
     106             :         template<class OutIt, class Ch>
     107             :         inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
     108             :     
     109             :         // Print children of the node                               
     110             :         template<class OutIt, class Ch>
     111           3 :         inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     112             :         {
     113       19309 :             for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
     114       19306 :                 out = print_node(out, child, flags, indent);
     115           3 :             return out;
     116             :         }
     117             : 
     118             :         // Print attributes of the node
     119             :         template<class OutIt, class Ch>
     120       19306 :         inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
     121             :         {
     122      154436 :             for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
     123             :             {
     124      135130 :                 if (attribute->name() && attribute->value())
     125             :                 {
     126             :                     // Print attribute name
     127      135130 :                     *out = Ch(' '), ++out;
     128      270260 :                     out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
     129      135130 :                     *out = Ch('='), ++out;
     130             :                     // Print attribute value using appropriate quote type
     131      405390 :                     if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
     132             :                     {
     133           0 :                         *out = Ch('\''), ++out;
     134           0 :                         out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
     135           0 :                         *out = Ch('\''), ++out;
     136             :                     }
     137             :                     else
     138             :                     {
     139      135130 :                         *out = Ch('"'), ++out;
     140      270260 :                         out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
     141      135130 :                         *out = Ch('"'), ++out;
     142             :                     }
     143             :                 }
     144             :             }
     145       19306 :             return out;
     146             :         }
     147             : 
     148             :         // Print data node
     149             :         template<class OutIt, class Ch>
     150           0 :         inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     151             :         {
     152           0 :             assert(node->type() == node_data);
     153           0 :             if (!(flags & print_no_indenting))
     154           0 :                 out = fill_chars(out, indent, Ch('\t'));
     155           0 :             out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
     156           0 :             return out;
     157             :         }
     158             : 
     159             :         // Print data node
     160             :         template<class OutIt, class Ch>
     161           0 :         inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     162             :         {
     163           0 :             assert(node->type() == node_cdata);
     164           0 :             if (!(flags & print_no_indenting))
     165           0 :                 out = fill_chars(out, indent, Ch('\t'));
     166           0 :             *out = Ch('<'); ++out;
     167           0 :             *out = Ch('!'); ++out;
     168           0 :             *out = Ch('['); ++out;
     169           0 :             *out = Ch('C'); ++out;
     170           0 :             *out = Ch('D'); ++out;
     171           0 :             *out = Ch('A'); ++out;
     172           0 :             *out = Ch('T'); ++out;
     173           0 :             *out = Ch('A'); ++out;
     174           0 :             *out = Ch('['); ++out;
     175           0 :             out = copy_chars(node->value(), node->value() + node->value_size(), out);
     176           0 :             *out = Ch(']'); ++out;
     177           0 :             *out = Ch(']'); ++out;
     178           0 :             *out = Ch('>'); ++out;
     179           0 :             return out;
     180             :         }
     181             : 
     182             :         // Print element node
     183             :         template<class OutIt, class Ch>
     184       19306 :         inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     185             :         {
     186       19306 :             assert(node->type() == node_element);
     187             : 
     188             :             // Print element name and attributes, if any
     189       19306 :             if (!(flags & print_no_indenting))
     190       57915 :                 out = fill_chars(out, indent, Ch('\t'));
     191       19306 :             *out = Ch('<'), ++out;
     192       38612 :             out = copy_chars(node->name(), node->name() + node->name_size(), out);
     193       19306 :             out = print_attributes(out, node, flags);
     194             :             
     195             :             // If node is childless
     196       19306 :             if (node->value_size() == 0 && !node->first_node())
     197             :             {
     198             :                 // Print childless node tag ending
     199       19304 :                 *out = Ch('/'), ++out;
     200       19304 :                 *out = Ch('>'), ++out;
     201             :             }
     202             :             else
     203             :             {
     204             :                 // Print normal node tag ending
     205           2 :                 *out = Ch('>'), ++out;
     206             : 
     207             :                 // Test if node contains a single data node only (and no other nodes)
     208           2 :                 xml_node<Ch> *child = node->first_node();
     209           2 :                 if (!child)
     210             :                 {
     211             :                     // If node has no children, only print its value without indenting
     212           0 :                     out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
     213             :                 }
     214           2 :                 else if (child->next_sibling() == 0 && child->type() == node_data)
     215             :                 {
     216             :                     // If node has a sole data child, only print its value without indenting
     217           0 :                     out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
     218             :                 }
     219             :                 else
     220             :                 {
     221             :                     // Print all children with full indenting
     222           2 :                     if (!(flags & print_no_indenting))
     223           2 :                         *out = Ch('\n'), ++out;
     224           2 :                     out = print_children(out, node, flags, indent + 1);
     225           2 :                     if (!(flags & print_no_indenting))
     226           3 :                         out = fill_chars(out, indent, Ch('\t'));
     227             :                 }
     228             : 
     229             :                 // Print node end
     230           2 :                 *out = Ch('<'), ++out;
     231           2 :                 *out = Ch('/'), ++out;
     232           4 :                 out = copy_chars(node->name(), node->name() + node->name_size(), out);
     233           2 :                 *out = Ch('>'), ++out;
     234             :             }
     235       19306 :             return out;
     236             :         }
     237             : 
     238             :         // Print declaration node
     239             :         template<class OutIt, class Ch>
     240           0 :         inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     241             :         {
     242             :             // Print declaration start
     243           0 :             if (!(flags & print_no_indenting))
     244           0 :                 out = fill_chars(out, indent, Ch('\t'));
     245           0 :             *out = Ch('<'), ++out;
     246           0 :             *out = Ch('?'), ++out;
     247           0 :             *out = Ch('x'), ++out;
     248           0 :             *out = Ch('m'), ++out;
     249           0 :             *out = Ch('l'), ++out;
     250             : 
     251             :             // Print attributes
     252           0 :             out = print_attributes(out, node, flags);
     253             :             
     254             :             // Print declaration end
     255           0 :             *out = Ch('?'), ++out;
     256           0 :             *out = Ch('>'), ++out;
     257             :             
     258           0 :             return out;
     259             :         }
     260             : 
     261             :         // Print comment node
     262             :         template<class OutIt, class Ch>
     263           0 :         inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     264             :         {
     265           0 :             assert(node->type() == node_comment);
     266           0 :             if (!(flags & print_no_indenting))
     267           0 :                 out = fill_chars(out, indent, Ch('\t'));
     268           0 :             *out = Ch('<'), ++out;
     269           0 :             *out = Ch('!'), ++out;
     270           0 :             *out = Ch('-'), ++out;
     271           0 :             *out = Ch('-'), ++out;
     272           0 :             out = copy_chars(node->value(), node->value() + node->value_size(), out);
     273           0 :             *out = Ch('-'), ++out;
     274           0 :             *out = Ch('-'), ++out;
     275           0 :             *out = Ch('>'), ++out;
     276           0 :             return out;
     277             :         }
     278             : 
     279             :         // Print doctype node
     280             :         template<class OutIt, class Ch>
     281           0 :         inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     282             :         {
     283           0 :             assert(node->type() == node_doctype);
     284           0 :             if (!(flags & print_no_indenting))
     285           0 :                 out = fill_chars(out, indent, Ch('\t'));
     286           0 :             *out = Ch('<'), ++out;
     287           0 :             *out = Ch('!'), ++out;
     288           0 :             *out = Ch('D'), ++out;
     289           0 :             *out = Ch('O'), ++out;
     290           0 :             *out = Ch('C'), ++out;
     291           0 :             *out = Ch('T'), ++out;
     292           0 :             *out = Ch('Y'), ++out;
     293           0 :             *out = Ch('P'), ++out;
     294           0 :             *out = Ch('E'), ++out;
     295           0 :             *out = Ch(' '), ++out;
     296           0 :             out = copy_chars(node->value(), node->value() + node->value_size(), out);
     297           0 :             *out = Ch('>'), ++out;
     298           0 :             return out;
     299             :         }
     300             : 
     301             :         // Print pi node
     302             :         template<class OutIt, class Ch>
     303           0 :         inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     304             :         {
     305           0 :             assert(node->type() == node_pi);
     306           0 :             if (!(flags & print_no_indenting))
     307           0 :                 out = fill_chars(out, indent, Ch('\t'));
     308           0 :             *out = Ch('<'), ++out;
     309           0 :             *out = Ch('?'), ++out;
     310           0 :             out = copy_chars(node->name(), node->name() + node->name_size(), out);
     311           0 :             *out = Ch(' '), ++out;
     312           0 :             out = copy_chars(node->value(), node->value() + node->value_size(), out);
     313           0 :             *out = Ch('?'), ++out;
     314           0 :             *out = Ch('>'), ++out;
     315           0 :             return out;
     316             :         }
     317             : 
     318             :         // Print literal node
     319             :         template<class OutIt, class Ch>
     320           0 :         inline OutIt print_literal_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     321             :         {
     322           0 :             assert(node->type() == node_literal);
     323           0 :             if (!(flags & print_no_indenting))
     324           0 :                 out = fill_chars(out, indent, Ch('\t'));
     325           0 :             out = copy_chars(node->value(), node->value() + node->value_size(), out);
     326           0 :             return out;
     327             :         }
     328             : 
     329             :         // Print node
     330             :         // Print node
     331             :         template<class OutIt, class Ch>
     332       19307 :         inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     333             :         {
     334             :             // Print proper node type
     335       19307 :             switch (node->type())
     336             :             {
     337             : 
     338             :             // Document
     339           1 :             case node_document:
     340           1 :                 out = print_children(out, node, flags, indent);
     341           1 :                 break;
     342             : 
     343             :             // Element
     344       19306 :             case node_element:
     345       19306 :                 out = print_element_node(out, node, flags, indent);
     346       19306 :                 break;
     347             :             
     348             :             // Data
     349           0 :             case node_data:
     350           0 :                 out = print_data_node(out, node, flags, indent);
     351           0 :                 break;
     352             :             
     353             :             // CDATA
     354           0 :             case node_cdata:
     355           0 :                 out = print_cdata_node(out, node, flags, indent);
     356           0 :                 break;
     357             : 
     358             :             // Declaration
     359           0 :             case node_declaration:
     360           0 :                 out = print_declaration_node(out, node, flags, indent);
     361           0 :                 break;
     362             : 
     363             :             // Comment
     364           0 :             case node_comment:
     365           0 :                 out = print_comment_node(out, node, flags, indent);
     366           0 :                 break;
     367             :             
     368             :             // Doctype
     369           0 :             case node_doctype:
     370           0 :                 out = print_doctype_node(out, node, flags, indent);
     371           0 :                 break;
     372             : 
     373             :             // Pi
     374           0 :             case node_pi:
     375           0 :                 out = print_pi_node(out, node, flags, indent);
     376           0 :                 break;
     377             : 
     378           0 :             case node_literal:
     379           0 :                 out = print_literal_node(out, node, flags, indent);
     380           0 :                 break;
     381             : 
     382             :                 // Unknown
     383           0 :             default:
     384           0 :                 assert(0);
     385             :                 break;
     386             :             }
     387             :             
     388             :             // If indenting not disabled, add line break after node
     389       19307 :             if (!(flags & print_no_indenting))
     390       19307 :                 *out = Ch('\n'), ++out;
     391             : 
     392             :             // Return modified iterator
     393       19307 :             return out;
     394             :         }
     395             :         
     396             :     }
     397             :     //! \endcond
     398             : 
     399             :     ///////////////////////////////////////////////////////////////////////////
     400             :     // Printing
     401             : 
     402             :     //! Prints XML to given output iterator.
     403             :     //! \param out Output iterator to print to.
     404             :     //! \param node Node to be printed. Pass xml_document to print entire document.
     405             :     //! \param flags Flags controlling how XML is printed.
     406             :     //! \return Output iterator pointing to position immediately after last character of printed text.
     407             :     template<class OutIt, class Ch> 
     408           1 :     inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
     409             :     {
     410           1 :         return internal::print_node(out, &node, flags, 0);
     411             :     }
     412             : 
     413             : #ifndef RAPIDXML_NO_STREAMS
     414             : 
     415             :     //! Prints XML to given output stream.
     416             :     //! \param out Output stream to print to.
     417             :     //! \param node Node to be printed. Pass xml_document to print entire document.
     418             :     //! \param flags Flags controlling how XML is printed.
     419             :     //! \return Output stream.
     420             :     template<class Ch> 
     421           1 :     inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
     422             :     {
     423           1 :         print(std::ostream_iterator<Ch>(out), node, flags);
     424             :         return out;
     425             :     }
     426             : 
     427             :     //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
     428             :     //! \param out Output stream to print to.
     429             :     //! \param node Node to be printed.
     430             :     //! \return Output stream.
     431             :     template<class Ch> 
     432           1 :     inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
     433             :     {
     434           1 :         return print(out, node);
     435             :     }
     436             : 
     437             : #endif
     438             : 
     439             : }
     440             : 
     441             : #endif

Generated by: LCOV version 1.14