LCOV - code coverage report
Current view: top level - ugbase/common/parser/rapidxml - rapidxml_print.hpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 166 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 11 0

            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              :         inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
      38              :         {
      39            0 :             while (begin != end)
      40            0 :                 *out++ = *begin++;
      41              :             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            0 :         inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
      48              :         {
      49            0 :             while (begin != end)
      50              :             {
      51            0 :                 if (*begin == noexpand)
      52              :                 {
      53            0 :                     *out++ = *begin;    // No expansion, copy character
      54              :                 }
      55              :                 else
      56              :                 {
      57            0 :                     switch (*begin)
      58              :                     {
      59            0 :                     case Ch('<'):
      60            0 :                         *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
      61            0 :                         break;
      62            0 :                     case Ch('>'): 
      63            0 :                         *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
      64            0 :                         break;
      65            0 :                     case Ch('\''): 
      66            0 :                         *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
      67            0 :                         break;
      68            0 :                     case Ch('"'): 
      69            0 :                         *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
      70            0 :                         break;
      71            0 :                     case Ch('&'): 
      72            0 :                         *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
      73            0 :                         break;
      74              :                     default:
      75            0 :                         *out++ = *begin;    // No expansion, copy character
      76              :                     }
      77              :                 }
      78            0 :                 ++begin;    // Step to next character
      79              :             }
      80            0 :             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            0 :             for (int i = 0; i < n; ++i)
      88            0 :                 *out++ = ch;
      89              :             return out;
      90              :         }
      91              : 
      92              :         // Find character
      93              :         template<class Ch, Ch ch>
      94              :         inline bool find_char(const Ch *begin, const Ch *end)
      95              :         {
      96            0 :             while (begin != end)
      97            0 :                 if (*begin++ == ch)
      98              :                     return true;
      99              :             return false;
     100              :         }
     101              : 
     102              :         ///////////////////////////////////////////////////////////////////////////
     103              :         // Internal printing operations
     104              : 
     105              :         // predeclaration
     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            0 :         inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     112              :         {
     113            0 :             for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
     114            0 :                 out = print_node(out, child, flags, indent);
     115            0 :             return out;
     116              :         }
     117              : 
     118              :         // Print attributes of the node
     119              :         template<class OutIt, class Ch>
     120            0 :         inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
     121              :         {
     122            0 :             for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
     123              :             {
     124              :                 if (attribute->name() && attribute->value())
     125              :                 {
     126              :                     // Print attribute name
     127            0 :                     *out = Ch(' '), ++out;
     128            0 :                     out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
     129            0 :                     *out = Ch('='), ++out;
     130              :                     // Print attribute value using appropriate quote type
     131            0 :                     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            0 :                         *out = Ch('"'), ++out;
     140            0 :                         out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
     141            0 :                         *out = Ch('"'), ++out;
     142              :                     }
     143              :                 }
     144              :             }
     145            0 :             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              :             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              :             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            0 :         inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     185              :         {
     186              :             assert(node->type() == node_element);
     187              : 
     188              :             // Print element name and attributes, if any
     189            0 :             if (!(flags & print_no_indenting))
     190            0 :                 out = fill_chars(out, indent, Ch('\t'));
     191            0 :             *out = Ch('<'), ++out;
     192            0 :             out = copy_chars(node->name(), node->name() + node->name_size(), out);
     193            0 :             out = print_attributes(out, node, flags);
     194              :             
     195              :             // If node is childless
     196            0 :             if (node->value_size() == 0 && !node->first_node())
     197              :             {
     198              :                 // Print childless node tag ending
     199            0 :                 *out = Ch('/'), ++out;
     200            0 :                 *out = Ch('>'), ++out;
     201              :             }
     202              :             else
     203              :             {
     204              :                 // Print normal node tag ending
     205            0 :                 *out = Ch('>'), ++out;
     206              : 
     207              :                 // Test if node contains a single data node only (and no other nodes)
     208              :                 xml_node<Ch> *child = node->first_node();
     209            0 :                 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            0 :                 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            0 :                     if (!(flags & print_no_indenting))
     223            0 :                         *out = Ch('\n'), ++out;
     224            0 :                     out = print_children(out, node, flags, indent + 1);
     225            0 :                     if (!(flags & print_no_indenting))
     226            0 :                         out = fill_chars(out, indent, Ch('\t'));
     227              :                 }
     228              : 
     229              :                 // Print node end
     230            0 :                 *out = Ch('<'), ++out;
     231            0 :                 *out = Ch('/'), ++out;
     232            0 :                 out = copy_chars(node->name(), node->name() + node->name_size(), out);
     233            0 :                 *out = Ch('>'), ++out;
     234              :             }
     235            0 :             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              :             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              :             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              :             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 node
     319              :          template<class OutIt, class Ch>
     320            0 :          inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
     321              :          {
     322              :              // Print proper node type
     323            0 :              switch (node->type())
     324              :              {
     325              : 
     326              :              // Document
     327              :              case node_document:
     328            0 :                  out = print_children(out, node, flags, indent);
     329            0 :                  break;
     330              : 
     331              :              // Element
     332              :              case node_element:
     333            0 :                  out = print_element_node(out, node, flags, indent);
     334            0 :                  break;
     335              : 
     336              :              // Data
     337              :              case node_data:
     338            0 :                  out = print_data_node(out, node, flags, indent);
     339            0 :                  break;
     340              : 
     341              :              // CDATA
     342              :              case node_cdata:
     343            0 :                  out = print_cdata_node(out, node, flags, indent);
     344            0 :                  break;
     345              : 
     346              :              // Declaration
     347              :              case node_declaration:
     348            0 :                  out = print_declaration_node(out, node, flags, indent);
     349            0 :                  break;
     350              : 
     351              :              // Comment
     352              :              case node_comment:
     353            0 :                  out = print_comment_node(out, node, flags, indent);
     354            0 :                  break;
     355              : 
     356              :              // Doctype
     357              :              case node_doctype:
     358            0 :                  out = print_doctype_node(out, node, flags, indent);
     359            0 :                  break;
     360              : 
     361              :              // Pi
     362              :              case node_pi:
     363            0 :                  out = print_pi_node(out, node, flags, indent);
     364            0 :                  break;
     365              : 
     366              :                  // Unknown
     367              :              default:
     368              :                  assert(0);
     369              :                  break;
     370              :              }
     371              : 
     372              :              // If indenting not disabled, add line break after node
     373            0 :              if (!(flags & print_no_indenting))
     374            0 :                  *out = Ch('\n'), ++out;
     375              : 
     376              :              // Return modified iterator
     377            0 :              return out;
     378              :          }
     379              :     }
     380              :     //! \endcond
     381              : 
     382              :     ///////////////////////////////////////////////////////////////////////////
     383              :     // Printing
     384              : 
     385              :     //! Prints XML to given output iterator.
     386              :     //! \param out Output iterator to print to.
     387              :     //! \param node Node to be printed. Pass xml_document to print entire document.
     388              :     //! \param flags Flags controlling how XML is printed.
     389              :     //! \return Output iterator pointing to position immediately after last character of printed text.
     390              :     template<class OutIt, class Ch> 
     391              :     inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
     392              :     {
     393            0 :         return internal::print_node(out, &node, flags, 0);
     394              :     }
     395              : 
     396              : #ifndef RAPIDXML_NO_STREAMS
     397              : 
     398              :     //! Prints XML to given output stream.
     399              :     //! \param out Output stream to print to.
     400              :     //! \param node Node to be printed. Pass xml_document to print entire document.
     401              :     //! \param flags Flags controlling how XML is printed.
     402              :     //! \return Output stream.
     403              :     template<class Ch> 
     404              :     inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
     405              :     {
     406            0 :         print(std::ostream_iterator<Ch>(out), node, flags);
     407              :         return out;
     408              :     }
     409              : 
     410              :     //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
     411              :     //! \param out Output stream to print to.
     412              :     //! \param node Node to be printed.
     413              :     //! \return Output stream.
     414              :     template<class Ch> 
     415              :     inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
     416              :     {
     417              :         return print(out, node);
     418              :     }
     419              : 
     420              : #endif
     421              : 
     422              : }
     423              : 
     424              : #endif
        

Generated by: LCOV version 2.0-1