LCOV - code coverage report
Current view: top level - app/libs/rapidxml - rapidxml.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 343 567 60.5 %
Date: 2023-08-17 16:45:52 Functions: 22 31 71.0 %

          Line data    Source code
       1             : #ifndef RAPIDXML_HPP_INCLUDED
       2             : #define RAPIDXML_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.hpp This file contains rapidxml parser and DOM implementation
       8             : 
       9             : // If standard library is disabled, user must provide implementations of required functions and typedefs
      10             : #if !defined(RAPIDXML_NO_STDLIB)
      11             :     #include <cstdlib>      // For std::size_t
      12             :     #include <cassert>      // For assert
      13             :     #include <new>          // For placement new
      14             : #endif
      15             : 
      16             : // On MSVC, disable "conditional expression is constant" warning (level 4).
      17             : // This warning is almost impossible to avoid with certain types of templated code
      18             : #ifdef _MSC_VER
      19             :     #pragma warning(push)
      20             :     #pragma warning(disable:4127)   // Conditional expression is constant
      21             : #endif
      22             : 
      23             : ///////////////////////////////////////////////////////////////////////////
      24             : // RAPIDXML_PARSE_ERROR
      25             : 
      26             : #if defined(RAPIDXML_NO_EXCEPTIONS)
      27             : 
      28             : #define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
      29             : #define RAPIDXML_EOF_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
      30             : 
      31             : namespace rapidxml
      32             : {
      33             :     //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS,
      34             :     //! this function is called to notify user about the error.
      35             :     //! It must be defined by the user.
      36             :     //! <br><br>
      37             :     //! This function cannot return. If it does, the results are undefined.
      38             :     //! <br><br>
      39             :     //! A very simple definition might look like that:
      40             :     //! <pre>
      41             :     //! void %rapidxml::%parse_error_handler(const char *what, void *where)
      42             :     //! {
      43             :     //!     std::cout << "Parse error: " << what << "\n";
      44             :     //!     std::abort();
      45             :     //! }
      46             :     //! </pre>
      47             :     //! \param what Human readable description of the error.
      48             :     //! \param where Pointer to character data where error was detected.
      49             :     void parse_error_handler(const char *what, void *where);
      50             : }
      51             : 
      52             : #else
      53             : 
      54             : #include <stdexcept>    // For std::runtime_error
      55             : 
      56             : #define RAPIDXML_PARSE_ERROR(what, where) {if (*where == Ch(0)) throw eof_error(what, where); else throw parse_error(what, where);} (void)0
      57             : #define RAPIDXML_EOF_ERROR(what, where) throw eof_error(what, where)
      58             : 
      59             : namespace rapidxml
      60             : {
      61             : 
      62             :     //! Parse error exception.
      63             :     //! This exception is thrown by the parser when an error occurs.
      64             :     //! Use what() function to get human-readable error message.
      65             :     //! Use where() function to get a pointer to position within source text where error was detected.
      66             :     //! <br><br>
      67             :     //! If throwing exceptions by the parser is undesirable,
      68             :     //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
      69             :     //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
      70             :     //! This function must be defined by the user.
      71             :     //! <br><br>
      72             :     //! This class derives from <code>std::exception</code> class.
      73             :     class parse_error: public std::runtime_error
      74             :     {
      75             : 
      76             :     public:
      77             : 
      78             :         //! Constructs parse error
      79           0 :         parse_error(const char *what, void *where)
      80           0 :             : std::runtime_error(what)
      81           0 :             , m_where(where)
      82             :         {
      83             :         }
      84             : 
      85             :         //! Gets pointer to character data where error happened.
      86             :         //! Ch should be the same as char type of xml_document that produced the error.
      87             :         //! \return Pointer to location within the parsed string where error occured.
      88             :         template<class Ch>
      89             :         Ch *where() const
      90             :         {
      91             :             return reinterpret_cast<Ch *>(m_where);
      92             :         }
      93             : 
      94             :     private:
      95             :         void *m_where;
      96             :     };
      97             : 
      98             :     class eof_error : public parse_error {
      99             :     public:
     100           0 :         eof_error(const char * what, void * where) : parse_error(what, where) {}
     101             :     };
     102             : 
     103             :     class validation_error : public std::runtime_error
     104             :     {
     105             :     public:
     106             :         validation_error(const char * what)
     107             :             : std::runtime_error(what) {}
     108             :     };
     109             : }
     110             : 
     111             : #endif
     112             : 
     113             : ///////////////////////////////////////////////////////////////////////////
     114             : // Pool sizes
     115             : 
     116             : #ifndef RAPIDXML_STATIC_POOL_SIZE
     117             :     // Size of static memory block of memory_pool.
     118             :     // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
     119             :     // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
     120             :     #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
     121             : #endif
     122             : 
     123             : #ifndef RAPIDXML_DYNAMIC_POOL_SIZE
     124             :     // Size of dynamic memory block of memory_pool.
     125             :     // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
     126             :     // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
     127             :     #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
     128             : #endif
     129             : 
     130             : #ifndef RAPIDXML_ALIGNMENT
     131             :     // Memory allocation alignment.
     132             :     // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
     133             :     // All memory allocations for nodes, attributes and strings will be aligned to this value.
     134             :     // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
     135             :     #define RAPIDXML_ALIGNMENT sizeof(void *)
     136             : #endif
     137             : 
     138             : namespace rapidxml
     139             : {
     140             :     // Forward declarations
     141             :     template<class Ch> class xml_node;
     142             :     template<class Ch> class xml_attribute;
     143             :     template<class Ch> class xml_document;
     144             : 
     145             :     //! Enumeration listing all node types produced by the parser.
     146             :     //! Use xml_node::type() function to query node type.
     147             :     enum node_type
     148             :     {
     149             :         node_document,      //!< A document node. Name and value are empty.
     150             :         node_element,       //!< An element node. Name contains element name. Value contains text of first data node.
     151             :         node_data,          //!< A data node. Name is empty. Value contains data text.
     152             :         node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.
     153             :         node_comment,       //!< A comment node. Name is empty. Value contains comment text.
     154             :         node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
     155             :         node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
     156             :         node_pi,            //!< A PI node. Name contains target. Value contains instructions.
     157             :         node_literal        //!< Value is unencoded text (used for inserting pre-rendered XML).
     158             :     };
     159             : 
     160             :     ///////////////////////////////////////////////////////////////////////
     161             :     // Parsing flags
     162             : 
     163             :     //! Parse flag instructing the parser to not create data nodes.
     164             :     //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
     165             :     //! Can be combined with other flags by use of | operator.
     166             :     //! <br><br>
     167             :     //! See xml_document::parse() function.
     168             :     const int parse_no_data_nodes = 0x1;
     169             : 
     170             :     //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
     171             :     //! Can be combined with other flags by use of | operator.
     172             :     //! Note that child data nodes of element node take precendence over its value when printing.
     173             :     //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
     174             :     //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
     175             :     //! <br><br>
     176             :     //! See xml_document::parse() function.
     177             :     const int parse_no_element_values = 0x2;
     178             : 
     179             :     //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
     180             :     //! By default zero terminators are placed, modifying source text.
     181             :     //! Can be combined with other flags by use of | operator.
     182             :     //! <br><br>
     183             :     //! See xml_document::parse() function.
     184             :     const int parse_no_string_terminators = 0x4;
     185             : 
     186             :     //! Parse flag instructing the parser to not translate entities in the source text.
     187             :     //! By default entities are translated, modifying source text.
     188             :     //! Can be combined with other flags by use of | operator.
     189             :     //! <br><br>
     190             :     //! See xml_document::parse() function.
     191             :     const int parse_no_entity_translation = 0x8;
     192             : 
     193             :     //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
     194             :     //! By default, UTF-8 handling is enabled.
     195             :     //! Can be combined with other flags by use of | operator.
     196             :     //! <br><br>
     197             :     //! See xml_document::parse() function.
     198             :     const int parse_no_utf8 = 0x10;
     199             : 
     200             :     //! Parse flag instructing the parser to create XML declaration node.
     201             :     //! By default, declaration node is not created.
     202             :     //! Can be combined with other flags by use of | operator.
     203             :     //! <br><br>
     204             :     //! See xml_document::parse() function.
     205             :     const int parse_declaration_node = 0x20;
     206             : 
     207             :     //! Parse flag instructing the parser to create comments nodes.
     208             :     //! By default, comment nodes are not created.
     209             :     //! Can be combined with other flags by use of | operator.
     210             :     //! <br><br>
     211             :     //! See xml_document::parse() function.
     212             :     const int parse_comment_nodes = 0x40;
     213             : 
     214             :     //! Parse flag instructing the parser to create DOCTYPE node.
     215             :     //! By default, doctype node is not created.
     216             :     //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
     217             :     //! Can be combined with other flags by use of | operator.
     218             :     //! <br><br>
     219             :     //! See xml_document::parse() function.
     220             :     const int parse_doctype_node = 0x80;
     221             : 
     222             :     //! Parse flag instructing the parser to create PI nodes.
     223             :     //! By default, PI nodes are not created.
     224             :     //! Can be combined with other flags by use of | operator.
     225             :     //! <br><br>
     226             :     //! See xml_document::parse() function.
     227             :     const int parse_pi_nodes = 0x100;
     228             : 
     229             :     //! Parse flag instructing the parser to validate closing tag names.
     230             :     //! If not set, name inside closing tag is irrelevant to the parser.
     231             :     //! By default, closing tags are not validated.
     232             :     //! Can be combined with other flags by use of | operator.
     233             :     //! <br><br>
     234             :     //! See xml_document::parse() function.
     235             :     const int parse_validate_closing_tags = 0x200;
     236             : 
     237             :     //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
     238             :     //! By default, whitespace is not trimmed.
     239             :     //! This flag does not cause the parser to modify source text.
     240             :     //! Can be combined with other flags by use of | operator.
     241             :     //! <br><br>
     242             :     //! See xml_document::parse() function.
     243             :     const int parse_trim_whitespace = 0x400;
     244             : 
     245             :     //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
     246             :     //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
     247             :     //! By default, whitespace is not normalized.
     248             :     //! If this flag is specified, source text will be modified.
     249             :     //! Can be combined with other flags by use of | operator.
     250             :     //! <br><br>
     251             :     //! See xml_document::parse() function.
     252             :     const int parse_normalize_whitespace = 0x800;
     253             : 
     254             :     //! Parse flag to say "Parse only the initial element opening."
     255             :     //! Useful for XMLstreams used in XMPP.
     256             :     const int parse_open_only = 0x1000;
     257             : 
     258             :     //! Parse flag to say "Toss the children of the top node and parse off
     259             :     //! one element.
     260             :     //! Useful for parsing off XMPP top-level elements.
     261             :     const int parse_parse_one = 0x2000;
     262             : 
     263             :     //! Parse flag to say "Validate XML namespaces fully."
     264             :     //! This will generate additional errors, including unbound prefixes
     265             :     //! and duplicate attributes (with different prefices)
     266             :     const int parse_validate_xmlns = 0x4000;
     267             : 
     268             :     // Compound flags
     269             : 
     270             :     //! Parse flags which represent default behaviour of the parser.
     271             :     //! This is always equal to 0, so that all other flags can be simply ored together.
     272             :     //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
     273             :     //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
     274             :     //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
     275             :     //! and using the flag will disable it.
     276             :     //! <br><br>
     277             :     //! See xml_document::parse() function.
     278             :     const int parse_default = 0;
     279             : 
     280             :     //! A combination of parse flags that forbids any modifications of the source text.
     281             :     //! This also results in faster parsing. However, note that the following will occur:
     282             :     //! <ul>
     283             :     //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
     284             :     //! <li>entities will not be translated</li>
     285             :     //! <li>whitespace will not be normalized</li>
     286             :     //! </ul>
     287             :     //! See xml_document::parse() function.
     288             :     const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
     289             : 
     290             :     //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
     291             :     //! <br><br>
     292             :     //! See xml_document::parse() function.
     293             :     const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
     294             : 
     295             :     //! A combination of parse flags resulting in largest amount of data being extracted.
     296             :     //! This usually results in slowest parsing.
     297             :     //! <br><br>
     298             :     //! See xml_document::parse() function.
     299             :     const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
     300             : 
     301             :     ///////////////////////////////////////////////////////////////////////
     302             :     // Internals
     303             : 
     304             :     //! \cond internal
     305             :     namespace internal
     306             :     {
     307             : 
     308             :         // Struct that contains lookup tables for the parser
     309             :         // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
     310             :         template<int Dummy>
     311             :         struct lookup_tables
     312             :         {
     313             :             static const unsigned char lookup_whitespace[256];              // Whitespace table
     314             :             static const unsigned char lookup_node_name[256];               // Node name table
     315             :             static const unsigned char lookup_element_name[256];            // Element name table
     316             :             static const unsigned char lookup_text[256];                    // Text table
     317             :             static const unsigned char lookup_text_pure_no_ws[256];         // Text table
     318             :             static const unsigned char lookup_text_pure_with_ws[256];       // Text table
     319             :             static const unsigned char lookup_attribute_name[256];          // Attribute name table
     320             :             static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote
     321             :             static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote
     322             :             static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes
     323             :             static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes
     324             :             static const unsigned char lookup_digits[256];                  // Digits
     325             :             static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters
     326             :         };
     327             : 
     328             :         // Find length of the string
     329             :         template<class Ch>
     330           0 :         inline std::size_t measure(const Ch *p)
     331             :         {
     332     2487850 :             const Ch *tmp = p;
     333    12160091 :             while (*tmp)
     334    12316290 :                 ++tmp;
     335     2331632 :             return tmp - p;
     336             :         }
     337             : 
     338             :         // Compare strings for equality
     339             :         template<class Ch>
     340     6640727 :         inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
     341             :         {
     342     6640727 :             if (size1 != size2)
     343             :                 return false;
     344     1964286 :             if (case_sensitive)
     345             :             {
     346     7518177 :                 for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
     347     6235018 :                     if (*p1 != *p2)
     348             :                         return false;
     349             :             }
     350             :             else
     351             :             {
     352           0 :                 for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
     353           0 :                     if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
     354             :                         return false;
     355             :             }
     356             :             return true;
     357             :         }
     358             :     }
     359             :     //! \endcond
     360             : 
     361             :     ///////////////////////////////////////////////////////////////////////
     362             :     // Memory pool
     363             : 
     364             :     //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
     365             :     //! In most cases, you will not need to use this class directly.
     366             :     //! However, if you need to create nodes manually or modify names/values of nodes,
     367             :     //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
     368             :     //! Not only is this faster than allocating them by using <code>new</code> operator,
     369             :     //! but also their lifetime will be tied to the lifetime of document,
     370             :     //! possibly simplyfing memory management.
     371             :     //! <br><br>
     372             :     //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
     373             :     //! You can also call allocate_string() function to allocate strings.
     374             :     //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
     375             :     //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
     376             :     //! or when the pool is destroyed.
     377             :     //! <br><br>
     378             :     //! It is also possible to create a standalone memory_pool, and use it
     379             :     //! to allocate nodes, whose lifetime will not be tied to any document.
     380             :     //! <br><br>
     381             :     //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
     382             :     //! Until static memory is exhausted, no dynamic memory allocations are done.
     383             :     //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
     384             :     //! by using global <code>new[]</code> and <code>delete[]</code> operators.
     385             :     //! This behaviour can be changed by setting custom allocation routines.
     386             :     //! Use set_allocator() function to set them.
     387             :     //! <br><br>
     388             :     //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
     389             :     //! This value defaults to the size of pointer on target architecture.
     390             :     //! <br><br>
     391             :     //! To obtain absolutely top performance from the parser,
     392             :     //! it is important that all nodes are allocated from a single, contiguous block of memory.
     393             :     //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
     394             :     //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code>
     395             :     //! to obtain best wasted memory to performance compromise.
     396             :     //! To do it, define their values before rapidxml.hpp file is included.
     397             :     //! \param Ch Character type of created nodes.
     398             :     template<class Ch = char>
     399             :     class memory_pool
     400             :     {
     401             : 
     402             :     public:
     403             : 
     404             :         //! \cond internal
     405             :         typedef void *(alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory
     406             :         typedef void (free_func)(void *);              // Type of user-defined function used to free memory
     407             :         //! \endcond
     408             : 
     409             :         //! Constructs empty pool with default allocator functions.
     410           6 :         memory_pool()
     411             :             : m_alloc_func(0)
     412           6 :             , m_free_func(0)
     413             :         {
     414           6 :             init();
     415             :         }
     416             : 
     417             :         //! Destroys pool and frees all the memory.
     418             :         //! This causes memory occupied by nodes allocated by the pool to be freed.
     419             :         //! Nodes allocated from the pool are no longer valid.
     420           6 :         ~memory_pool()
     421             :         {
     422           6 :             clear();
     423             :         }
     424             : 
     425             :         //! Allocates a new node from the pool, and optionally assigns name and value to it.
     426             :         //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
     427             :         //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
     428             :         //! will call rapidxml::parse_error_handler() function.
     429             :         //! \param type Type of node to create.
     430             :         //! \param name Name to assign to the node, or 0 to assign no name.
     431             :         //! \param value Value to assign to the node, or 0 to assign no value.
     432             :         //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
     433             :         //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
     434             :         //! \return Pointer to allocated node. This pointer will never be NULL.
     435      204926 :         xml_node<Ch> *allocate_node(node_type type,
     436             :                                     const Ch *name = 0, const Ch *value = 0,
     437             :                                     std::size_t name_size = 0, std::size_t value_size = 0)
     438             :         {
     439      204926 :             void *memory = allocate_aligned(sizeof(xml_node<Ch>));
     440      204926 :             xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
     441      204926 :             if (name)
     442             :             {
     443       19306 :                 if (name_size > 0)
     444      204926 :                     node->name(name, name_size);
     445             :                 else
     446       96538 :                     node->name(name);
     447             :             }
     448             :             else
     449             :             {
     450      576166 :                 node->name(this->nullstr(), 0);
     451             :             }
     452      204926 :             if (value)
     453             :             {
     454           0 :                 if (value_size > 0)
     455      204926 :                     node->value(value, value_size);
     456             :                 else
     457           0 :                     node->value(value);
     458             :             }
     459             :             else
     460             :             {
     461      614778 :                 node->value(this->nullstr(), 0);
     462             :             }
     463      204926 :             return node;
     464             :         }
     465             : 
     466             :         //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
     467             :         //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
     468             :         //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
     469             :         //! will call rapidxml::parse_error_handler() function.
     470             :         //! \param name Name to assign to the attribute, or 0 to assign no name.
     471             :         //! \param value Value to assign to the attribute, or 0 to assign no value.
     472             :         //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
     473             :         //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
     474             :         //! \return Pointer to allocated attribute. This pointer will never be NULL.
     475     1047403 :         xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0,
     476             :                                               std::size_t name_size = 0, std::size_t value_size = 0)
     477             :         {
     478     1959680 :             void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
     479     1047403 :             xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
     480      135130 :             if (name)
     481             :             {
     482      135130 :                 if (name_size > 0)
     483     1047403 :                     attribute->name(name, name_size);
     484             :                 else
     485     1877483 :                     attribute->name(name);
     486             :             }
     487      135130 :             if (value)
     488             :             {
     489      135130 :                 if (value_size > 0)
     490     1047403 :                     attribute->value(value, value_size);
     491             :                 else
     492     2338373 :                     attribute->value(value);
     493             :             }
     494      135130 :             return attribute;
     495             :         }
     496             : 
     497             :         //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
     498             :         //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
     499             :         //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
     500             :         //! will call rapidxml::parse_error_handler() function.
     501             :         //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
     502             :         //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
     503             :         //! \return Pointer to allocated char array. This pointer will never be NULL.
     504             :         template<typename Sch>
     505           6 :         Ch *allocate_string(const Sch *source = 0, std::size_t size = 0)
     506             :         {
     507           6 :             assert(source || size);     // Either source or size (or both) must be specified
     508           6 :             if (size == 0)
     509           6 :                 size = internal::measure(source) + 1;
     510           6 :             Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
     511           6 :             if (source)
     512          12 :                 for (std::size_t i = 0; i < size; ++i)
     513           6 :                     result[i] = source[i];
     514           6 :             return result;
     515             :         }
     516             : 
     517      576084 :         Ch * nullstr()
     518             :         {
     519      390546 :             if (!m_nullstr)
     520           6 :                 m_nullstr = allocate_string("");
     521      576084 :             return m_nullstr;
     522             :         }
     523           0 :         Ch * xmlns_xml(std::size_t & xmlns_size)
     524             :         {
     525           0 :             if (!m_xmlns_xml)
     526           0 :                 m_xmlns_xml = allocate_string("http://www.w3.org/XML/1998/namespace");
     527           0 :             xmlns_size = internal::measure(m_xmlns_xml);
     528           0 :             return m_xmlns_xml;
     529             :         }
     530           0 :         Ch * xmlns_xmlns(std::size_t & xmlns_size)
     531             :         {
     532           0 :             if (!m_xmlns_xmlns)
     533           0 :                 m_xmlns_xmlns = allocate_string("http://www.w3.org/2000/xmlns/");
     534           0 :             xmlns_size = internal::measure(m_xmlns_xmlns);
     535           0 :             return m_xmlns_xmlns;
     536             :         }
     537             : 
     538             : 
     539             :         //! Clones an xml_node and its hierarchy of child nodes and attributes.
     540             :         //! Nodes and attributes are allocated from this memory pool.
     541             :         //! Names and values are not cloned, they are shared between the clone and the source.
     542             :         //! Result node can be optionally specified as a second parameter,
     543             :         //! in which case its contents will be replaced with cloned source node.
     544             :         //! This is useful when you want to clone entire document.
     545             :         //! \param source Node to clone.
     546             :         //! \param result Node to put results in, or 0 to automatically allocate result node
     547             :         //! \return Pointer to cloned node. This pointer will never be NULL.
     548             :         xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
     549             :         {
     550             :             // Prepare result node
     551             :             if (result)
     552             :             {
     553             :                 result->remove_all_attributes();
     554             :                 result->remove_all_nodes();
     555             :                 result->type(source->type());
     556             :             }
     557             :             else
     558             :                 result = allocate_node(source->type());
     559             : 
     560             :             // Clone name and value
     561             :             result->name(source->name(), source->name_size());
     562             :             result->value(source->value(), source->value_size());
     563             : 
     564             :             // Clone child nodes and attributes
     565             :             for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
     566             :                 result->append_node(clone_node(child));
     567             :             for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
     568             :                 result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
     569             : 
     570             :             return result;
     571             :         }
     572             : 
     573             :         //! Clears the pool.
     574             :         //! This causes memory occupied by nodes allocated by the pool to be freed.
     575             :         //! Any nodes or strings allocated from the pool will no longer be valid.
     576           6 :         void clear()
     577             :         {
     578        1732 :             while (m_begin != m_static_memory)
     579             :             {
     580        1726 :                 char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
     581        1726 :                 if (m_free_func)
     582           0 :                     m_free_func(m_begin);
     583             :                 else
     584        1726 :                     delete[] m_begin;
     585        1726 :                 m_begin = previous_begin;
     586             :             }
     587           6 :             init();
     588           6 :         }
     589             : 
     590             :         //! Sets or resets the user-defined memory allocation functions for the pool.
     591             :         //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
     592             :         //! Allocation function must not return invalid pointer on failure. It should either throw,
     593             :         //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
     594             :         //! If it returns invalid pointer, results are undefined.
     595             :         //! <br><br>
     596             :         //! User defined allocation functions must have the following forms:
     597             :         //! <br><code>
     598             :         //! <br>void *allocate(std::size_t size);
     599             :         //! <br>void free(void *pointer);
     600             :         //! </code><br>
     601             :         //! \param af Allocation function, or 0 to restore default function
     602             :         //! \param ff Free function, or 0 to restore default function
     603             :         void set_allocator(alloc_func *af, free_func *ff)
     604             :         {
     605             :             assert(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet
     606             :             m_alloc_func = af;
     607             :             m_free_func = ff;
     608             :         }
     609             : 
     610             :     private:
     611             : 
     612             :         struct header
     613             :         {
     614             :             char *previous_begin;
     615             :         };
     616             : 
     617          12 :         void init()
     618             :         {
     619          12 :             m_begin = m_static_memory;
     620          12 :             m_ptr = align(m_begin);
     621          12 :             m_end = m_static_memory + sizeof(m_static_memory);
     622          12 :             m_nullstr = 0;
     623          12 :             m_xmlns_xml = 0;
     624          12 :             m_xmlns_xmlns = 0;
     625             :         }
     626             : 
     627     1255801 :         char *align(char *ptr)
     628             :         {
     629     1255795 :             std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
     630        1726 :             return ptr + alignment;
     631             :         }
     632             : 
     633             :         char *allocate_raw(std::size_t size)
     634             :         {
     635             :             // Allocate
     636             :             void *memory;
     637             :             if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]
     638             :             {
     639             :                 memory = m_alloc_func(size);
     640             :                 assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
     641             :             }
     642             :             else
     643             :             {
     644             :                 memory = new char[size];
     645             : #ifdef RAPIDXML_NO_EXCEPTIONS
     646             :                 if (!memory)            // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
     647             :                     RAPIDXML_PARSE_ERROR("out of memory", 0);
     648             : #endif
     649             :             }
     650             :             return static_cast<char *>(memory);
     651             :         }
     652             : 
     653     1252336 :         void *allocate_aligned(std::size_t size)
     654             :         {
     655             :             // Calculate aligned pointer
     656     1252336 :             char *result = align(m_ptr);
     657             : 
     658             :             // If not enough memory left in current pool, allocate a new pool
     659     1252336 :             if (result + size > m_end)
     660             :             {
     661             :                 // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
     662        1726 :                 std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
     663             :                 if (pool_size < size)
     664             :                     pool_size = size;
     665             : 
     666             :                 // Allocate
     667        1726 :                 std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size;     // 2 alignments required in worst case: one for header, one for actual allocation
     668        1726 :                 char *raw_memory = allocate_raw(alloc_size);
     669             : 
     670             :                 // Setup new pool in allocated memory
     671        1726 :                 char *pool = align(raw_memory);
     672        1726 :                 header *new_header = reinterpret_cast<header *>(pool);
     673        1726 :                 new_header->previous_begin = m_begin;
     674        1726 :                 m_begin = raw_memory;
     675        1726 :                 m_ptr = pool + sizeof(header);
     676        1726 :                 m_end = raw_memory + alloc_size;
     677             : 
     678             :                 // Calculate aligned pointer again using new pool
     679        1726 :                 result = align(m_ptr);
     680             :             }
     681             : 
     682             :             // Update pool and return aligned pointer
     683     1252336 :             m_ptr = result + size;
     684     1252336 :             return result;
     685             :         }
     686             : 
     687             :         char *m_begin;                                      // Start of raw memory making up current pool
     688             :         char *m_ptr;                                        // First free byte in current pool
     689             :         char *m_end;                                        // One past last available byte in current pool
     690             :         char m_static_memory[RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory
     691             :         alloc_func *m_alloc_func;                           // Allocator function, or 0 if default is to be used
     692             :         free_func *m_free_func;                             // Free function, or 0 if default is to be used
     693             :         Ch * m_nullstr;
     694             :         Ch * m_xmlns_xml;
     695             :         Ch * m_xmlns_xmlns;
     696             :     };
     697             : 
     698             :     ///////////////////////////////////////////////////////////////////////////
     699             :     // XML base
     700             : 
     701             :     //! Base class for xml_node and xml_attribute implementing common functions:
     702             :     //! name(), name_size(), value(), value_size() and parent().
     703             :     //! \param Ch Character type to use
     704             :     template<class Ch = char>
     705             :     class xml_base
     706             :     {
     707             : 
     708             :     public:
     709             : 
     710             :         ///////////////////////////////////////////////////////////////////////////
     711             :         // Construction & destruction
     712             : 
     713             :         // Construct a base with empty name, value and parent
     714     1252332 :         xml_base()
     715             :             : m_name(0)
     716             :             , m_value(0)
     717             :             , m_name_size(0)
     718             :             , m_value_size(0)
     719     1252332 :             , m_parent(0)
     720             :         {
     721             :         }
     722             : 
     723             :         ///////////////////////////////////////////////////////////////////////////
     724             :         // Node data access
     725             : 
     726             :         //! Gets name of the node.
     727             :         //! Interpretation of name depends on type of node.
     728             :         //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
     729             :         //! <br><br>
     730             :         //! Use name_size() function to determine length of the name.
     731             :         //! \return Name of node, or empty string if node has no name.
     732      300705 :         Ch *name() const
     733             :         {
     734             :             return m_name;
     735             :         }
     736             : 
     737             :         //! Gets size of node name, not including terminator character.
     738             :         //! This function works correctly irrespective of whether name is or is not zero terminated.
     739             :         //! \return Size of node name, in characters.
     740     7707520 :         std::size_t name_size() const
     741             :         {
     742     7707520 :             return m_name ? m_name_size : 0;
     743             :         }
     744             : 
     745             :         //! Gets value of node.
     746             :         //! Interpretation of value depends on type of node.
     747             :         //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
     748             :         //! <br><br>
     749             :         //! Use value_size() function to determine length of the value.
     750             :         //! \return Value of node, or empty string if node has no value.
     751     1317483 :         Ch *value() const
     752             :         {
     753             :             return m_value;
     754             :         }
     755             : 
     756             :         //! Gets size of node value, not including terminator character.
     757             :         //! This function works correctly irrespective of whether value is or is not zero terminated.
     758             :         //! \return Size of node value, in characters.
     759     1201839 :         std::size_t value_size() const
     760             :         {
     761     1201839 :             return m_value ? m_value_size : 0;
     762             :         }
     763             :         ///////////////////////////////////////////////////////////////////////////
     764             :         // Node modification
     765             : 
     766             :         //! Sets name of node to a non zero-terminated string.
     767             :         //! See \ref ownership_of_strings.
     768             :         //! <br><br>
     769             :         //! Note that node does not own its name or value, it only stores a pointer to it.
     770             :         //! It will not delete or otherwise free the pointer on destruction.
     771             :         //! It is reponsibility of the user to properly manage lifetime of the string.
     772             :         //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
     773             :         //! on destruction of the document the string will be automatically freed.
     774             :         //! <br><br>
     775             :         //! Size of name must be specified separately, because name does not have to be zero terminated.
     776             :         //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
     777             :         //! \param name Name of node to set. Does not have to be zero terminated.
     778             :         //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
     779     1437946 :         void name(const Ch *name, std::size_t size)
     780             :         {
     781     1437946 :             m_name = const_cast<Ch *>(name);
     782     1437946 :             m_name_size = size;
     783      185620 :         }
     784             : 
     785             :         //! Sets name of node to a zero-terminated string.
     786             :         //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
     787             :         //! \param name Name of node to set. Must be zero terminated.
     788             :         void name(const Ch *name)
     789             :         {
     790      154436 :             this->name(name, internal::measure(name));
     791      154436 :         }
     792             : 
     793             :         //! Sets value of node to a non zero-terminated string.
     794             :         //! See \ref ownership_of_strings.
     795             :         //! <br><br>
     796             :         //! Note that node does not own its name or value, it only stores a pointer to it.
     797             :         //! It will not delete or otherwise free the pointer on destruction.
     798             :         //! It is reponsibility of the user to properly manage lifetime of the string.
     799             :         //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
     800             :         //! on destruction of the document the string will be automatically freed.
     801             :         //! <br><br>
     802             :         //! Size of value must be specified separately, because it does not have to be zero terminated.
     803             :         //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
     804             :         //! <br><br>
     805             :         //! If an element has a child node of type node_data, it will take precedence over element value when printing.
     806             :         //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
     807             :         //! \param value value of node to set. Does not have to be zero terminated.
     808             :         //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
     809     1252326 :         void value(const Ch *value, std::size_t size)
     810             :         {
     811     1252326 :             m_value = const_cast<Ch *>(value);
     812     1252326 :             m_value_size = size;
     813      204926 :         }
     814             : 
     815             :         //! Sets value of node to a zero-terminated string.
     816             :         //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
     817             :         //! \param value Vame of node to set. Must be zero terminated.
     818             :         void value(const Ch *value)
     819             :         {
     820      135130 :             this->value(value, internal::measure(value));
     821      135130 :         }
     822             :         ///////////////////////////////////////////////////////////////////////////
     823             :         // Related nodes access
     824             : 
     825             :         //! Gets node parent.
     826             :         //! \return Pointer to parent node, or 0 if there is no parent.
     827     2533416 :         xml_node<Ch> *parent() const
     828             :         {
     829             :             return m_parent;
     830             :         }
     831             : 
     832             :     protected:
     833             :         Ch *m_name;                         // Name of node, or 0 if no name
     834             :         Ch *m_value;                        // Value of node, or 0 if no value
     835             :         std::size_t m_name_size;            // Length of node name, or undefined of no name
     836             :         std::size_t m_value_size;           // Length of node value, or undefined if no value
     837             :         xml_node<Ch> *m_parent;             // Pointer to parent node, or 0 if none
     838             : 
     839             :     };
     840             : 
     841             :     //! Class representing attribute node of XML document.
     842             :     //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
     843             :     //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
     844             :     //! Thus, this text must persist in memory for the lifetime of attribute.
     845             :     //! \param Ch Character type to use.
     846             :     template<class Ch = char>
     847             :     class xml_attribute: public xml_base<Ch>
     848             :     {
     849             : 
     850             :         friend class xml_node<Ch>;
     851             : 
     852             :     public:
     853             : 
     854             :         ///////////////////////////////////////////////////////////////////////////
     855             :         // Construction & destruction
     856             : 
     857             :         //! Constructs an empty attribute with the specified type.
     858             :         //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
     859     1047403 :         xml_attribute() : m_prev_attribute(0), m_next_attribute(0), m_xmlns(0), m_xmlns_size(0), m_local_name(0)
     860             :         {
     861             :         }
     862             : 
     863             :         ///////////////////////////////////////////////////////////////////////////
     864             :         // Related nodes access
     865             : 
     866             :         //! Gets document of which attribute is a child.
     867             :         //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
     868             :         xml_document<Ch> *document() const
     869             :         {
     870             :             if (xml_node<Ch> *node = this->parent())
     871             :             {
     872             :                 while (node->parent())
     873             :                     node = node->parent();
     874             :                 return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
     875             :             }
     876             :             else
     877             :                 return 0;
     878             :         }
     879             : 
     880             :         Ch * xmlns() const
     881             :         {
     882             :             if (m_xmlns) return m_xmlns;
     883             :             Ch * p;
     884             :             Ch * name = this->name();
     885             :             for (p = name; *p && *p != ':'; ++p)
     886             :                 if ((p - name) >= this->name_size()) break;
     887             :             if (!*p || ((p - name) >= this->name_size())) {
     888             :                 m_xmlns = document()->nullstr();
     889             :                 m_xmlns_size = 0;
     890             :                 return m_xmlns;
     891             :             }
     892             :             xml_node<Ch> * element = this->parent();
     893             :             if (element) element->xmlns_lookup(m_xmlns, m_xmlns_size, name, p - name);
     894             :             return m_xmlns;
     895             :         }
     896             :         std::size_t xmlns_size() const
     897             :         {
     898             :             return this->xmlns() ? m_xmlns_size : 0;
     899             :         }
     900             :         //! Gets previous attribute, optionally matching attribute name.
     901             :         //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
     902             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
     903             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
     904             :         //! \return Pointer to found attribute, or 0 if not found.
     905             :         xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
     906             :         {
     907             :             if (name)
     908             :             {
     909             :                 if (name_size == 0)
     910             :                     name_size = internal::measure(name);
     911             :                 for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
     912             :                     if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
     913             :                         return attribute;
     914             :                 return 0;
     915             :             }
     916             :             else
     917             :                 return this->m_parent ? m_prev_attribute : 0;
     918             :         }
     919             : 
     920             :         //! Gets next attribute, optionally matching attribute name.
     921             :         //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
     922             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
     923             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
     924             :         //! \return Pointer to found attribute, or 0 if not found.
     925      135130 :         xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
     926             :         {
     927             :             if (name)
     928             :             {
     929             :                 if (name_size == 0)
     930             :                     name_size = internal::measure(name);
     931             :                 for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
     932             :                     if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
     933             :                         return attribute;
     934             :                 return 0;
     935             :             }
     936             :             else
     937      135130 :                 return this->m_parent ? m_next_attribute : 0;
     938             :         }
     939             : 
     940             :         Ch * local_name() const
     941             :         {
     942             :             if (m_local_name) return m_local_name;
     943             :             Ch * p = this->name();
     944             :             for (; *p && *p != Ch(':'); ++p);
     945             :             if (*p)
     946             :                 m_local_name = p + 1;
     947             :             else
     948             :                 m_local_name = this->name();
     949             :             return m_local_name;
     950             :         }
     951             : 
     952             :         std::size_t local_name_size() const
     953             :         {
     954             :             return this->name_size() - (this->local_name() - this->name());
     955             :         }
     956             : 
     957             :     private:
     958             : 
     959             :         xml_attribute<Ch> *m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
     960             :         xml_attribute<Ch> *m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
     961             :         mutable Ch * m_xmlns;
     962             :         mutable std::size_t m_xmlns_size;
     963             :         mutable Ch * m_local_name; // ATTN: points inside m_name.
     964             :     };
     965             : 
     966             :     ///////////////////////////////////////////////////////////////////////////
     967             :     // XML node
     968             : 
     969             :     //! Class representing a node of XML document.
     970             :     //! Each node may have associated name and value strings, which are available through name() and value() functions.
     971             :     //! Interpretation of name and value depends on type of the node.
     972             :     //! Type of node can be determined by using type() function.
     973             :     //! <br><br>
     974             :     //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
     975             :     //! Thus, this text must persist in the memory for the lifetime of node.
     976             :     //! \param Ch Character type to use.
     977             :     template<class Ch = char>
     978             :     class xml_node: public xml_base<Ch>
     979             :     {
     980             : 
     981             :     public:
     982             : 
     983             :         ///////////////////////////////////////////////////////////////////////////
     984             :         // Construction & destruction
     985             : 
     986             :         //! Constructs an empty node with the specified type.
     987             :         //! Consider using memory_pool of appropriate document to allocate nodes manually.
     988             :         //! \param type Type of node to construct.
     989      204932 :         xml_node(node_type type)
     990             :             : m_prefix(0)
     991             :             , m_xmlns(0)
     992             :             , m_prefix_size(0)
     993             :             , m_xmlns_size(0)
     994             :             , m_type(type)
     995             :             , m_first_node(0)
     996             :             , m_last_node(0)
     997             :             , m_first_attribute(0)
     998             :             , m_last_attribute(0)
     999             :             , m_prev_sibling(0)
    1000             :             , m_next_sibling(0)
    1001             :             , m_contents(0)
    1002      204926 :             , m_contents_size(0)
    1003             :         {
    1004             :         }
    1005             : 
    1006             :         ///////////////////////////////////////////////////////////////////////////
    1007             :         // Node data access
    1008             : 
    1009             :         //! Gets type of node.
    1010             :         //! \return Type of node.
    1011      409772 :         node_type type() const
    1012             :         {
    1013             :             return m_type;
    1014             :         }
    1015             : 
    1016           0 :         void prefix(const Ch *prefix, std::size_t size)
    1017             :         {
    1018           0 :             m_prefix = const_cast<Ch *>(prefix);
    1019           0 :             m_prefix_size = size;
    1020             :         }
    1021             :         void prefix(const Ch *prefix)
    1022             :         {
    1023             :             this->prefix(prefix, internal::measure(prefix));
    1024             :         }
    1025             : 
    1026      185620 :         Ch *prefix() const
    1027             :         {
    1028             :             return m_prefix;
    1029             :         }
    1030             : 
    1031           0 :         std::size_t prefix_size() const
    1032             :         {
    1033           0 :             return m_prefix ? m_prefix_size : 0;
    1034             :         }
    1035             : 
    1036       47699 :         void contents(Ch const * contents, std::size_t contents_size)
    1037             :         {
    1038       47699 :             m_contents = contents;
    1039       47699 :             m_contents_size = contents_size;
    1040       47699 :         }
    1041             :         Ch const * contents() const
    1042             :         {
    1043             :             return m_contents;
    1044             :         }
    1045             :         std::size_t contents_size() const
    1046             :         {
    1047             :             return m_contents ? m_contents_size : 0;
    1048             :         }
    1049             : 
    1050      605013 :         Ch *xmlns() const
    1051             :         {
    1052      419481 :             if (m_xmlns) return m_xmlns;
    1053      185538 :             xmlns_lookup(m_xmlns, m_xmlns_size, m_prefix, m_prefix_size);
    1054      185538 :             return m_xmlns;
    1055             :         }
    1056             : 
    1057      185538 :         void xmlns_lookup(Ch *& xmlns, size_t &xmlns_size, Ch * prefix, size_t prefix_size) const
    1058             :         {
    1059      185538 :             Ch * freeme = 0;
    1060             :             Ch * attrname;
    1061      185538 :             if (prefix) {
    1062             :                 // Check if the prefix begins "xml".
    1063           0 :                 if (prefix_size >= 3
    1064           0 :                     && prefix[0] == Ch('x')
    1065           0 :                     && prefix[1] == Ch('m')
    1066           0 :                     && prefix[2] == Ch('l')) {
    1067           0 :                     if (prefix_size == 3) {
    1068           0 :                         xmlns = this->document()->xmlns_xml(xmlns_size);
    1069           0 :                         return;
    1070           0 :                     } else if (prefix_size == 5
    1071           0 :                                && prefix[3] == Ch('n')
    1072           0 :                                && prefix[4] == Ch('s')) {
    1073           0 :                         xmlns = this->document()->xmlns_xmlns(xmlns_size);
    1074           0 :                         return;
    1075             :                     }
    1076             :                 }
    1077           0 :                 freeme = attrname = new Ch[prefix_size + 7];
    1078           0 :                 const char * p1="xmlns";
    1079           0 :                 while (*p1) *attrname++ = *p1++;
    1080           0 :                 Ch * p = prefix;
    1081           0 :                 *attrname++ = Ch(':');
    1082           0 :                 while (*p) {
    1083           0 :                     *attrname++ = *p++;
    1084           0 :                     if ((attrname - freeme) >= std::ptrdiff_t(prefix_size + 6)) break;
    1085             :                 }
    1086           0 :                 *attrname = Ch(0);
    1087           0 :                 attrname = freeme;
    1088             :             } else {
    1089      185538 :                 freeme = attrname = new Ch[6];
    1090      185538 :                 const char * p1="xmlns";
    1091     1113230 :                 while (*p1) *attrname++ = *p1++;
    1092      185538 :                 *attrname = Ch(0);
    1093      185538 :                 attrname = freeme;
    1094             :             }
    1095      826083 :             for (const xml_node<Ch> * node = this;
    1096             :                  node;
    1097      640545 :                  node = node->parent()) {
    1098      640545 :                 const xml_attribute<Ch> * attr = node->first_attribute(attrname);
    1099      640545 :                 if (attr) {
    1100           0 :                     xmlns = attr->value();
    1101           0 :                     if (xmlns) {
    1102           0 :                         xmlns_size = attr->value_size();
    1103             :                     }
    1104             :                     break;
    1105             :                 }
    1106             :             }
    1107      185538 :             if (!xmlns) {
    1108      185538 :                 if (!prefix) {
    1109      185538 :                     xmlns = document()->nullstr();
    1110      185538 :                     xmlns_size = 0;
    1111             :                 }
    1112             :             }
    1113      185538 :             if (freeme) delete[] freeme;
    1114             :         }
    1115             : 
    1116      419481 :         std::size_t xmlns_size() const
    1117             :         {
    1118      233949 :             if (m_xmlns) return m_xmlns_size;
    1119      185532 :             this->xmlns();
    1120      185532 :             return m_xmlns_size;
    1121             :         }
    1122             : 
    1123             :         ///////////////////////////////////////////////////////////////////////////
    1124             :         // Related nodes access
    1125             : 
    1126             :         //! Gets document of which node is a child.
    1127             :         //! \return Pointer to document that contains this node, or 0 if there is no parent document.
    1128           0 :         xml_document<Ch> *document() const
    1129             :         {
    1130           0 :             xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
    1131      640545 :             while (node->parent())
    1132             :                 node = node->parent();
    1133      185538 :             return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
    1134             :         }
    1135             : 
    1136             :         //! Gets first child node, optionally matching node name.
    1137             :         //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    1138             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
    1139             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
    1140             :         //! \return Pointer to found child, or 0 if not found.
    1141      272674 :         xml_node<Ch> *first_node(const Ch *name = 0, const Ch *xmlns = 0, std::size_t name_size = 0, std::size_t xmlns_size = 0, bool case_sensitive = true) const
    1142             :         {
    1143      321095 :             if (name && !name_size) name_size = internal::measure(name);
    1144      272674 :             if (xmlns && !xmlns_size) xmlns_size = internal::measure(xmlns);
    1145      272674 :             if (!xmlns && name) {
    1146             :                 // No XMLNS asked for, but a name is present.
    1147             :                 // Assume "same XMLNS".
    1148       48421 :                 xmlns = this->xmlns();
    1149      272674 :                 xmlns_size = this->xmlns_size();
    1150             :             }
    1151      399303 :             for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
    1152      348924 :                 if ((!name || internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
    1153      427365 :                     && (!xmlns || internal::compare(child->xmlns(), child->xmlns_size(), xmlns, xmlns_size, case_sensitive)))
    1154      205070 :                     return child;
    1155             :             return 0;
    1156             :         }
    1157             : 
    1158             :         //! Gets last child node, optionally matching node name.
    1159             :         //! Behaviour is undefined if node has no children.
    1160             :         //! Use first_node() to test if node has children.
    1161             :         //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    1162             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
    1163             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
    1164             :         //! \return Pointer to found child, or 0 if not found.
    1165             :         xml_node<Ch> *last_node(const Ch *name = 0, const Ch *xmlns = 0, std::size_t name_size = 0, std::size_t xmlns_size = 0, bool case_sensitive = true) const
    1166             :         {
    1167             :             assert(m_first_node);  // Cannot query for last child if node has no children
    1168             :             if (name && !name_size) name_size = internal::measure(name);
    1169             :             if (xmlns && !xmlns_size) xmlns_size = internal::measure(xmlns);
    1170             :             if (!xmlns && name) {
    1171             :                 // No XMLNS asked for, but a name is present.
    1172             :                 // Assume "same XMLNS".
    1173             :                 xmlns = this->xmlns();
    1174             :                 xmlns_size = this->xmlns_size();
    1175             :             }
    1176             :             for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
    1177             :                 if ((!name || internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
    1178             :                     && (!xmlns || internal::compare(child->xmlns(), child->xmlns_size(), xmlns, xmlns_size, case_sensitive)))
    1179             :                     return child;
    1180             :             return 0;
    1181             :         }
    1182             : 
    1183             :         //! Gets previous sibling node, optionally matching node name.
    1184             :         //! Behaviour is undefined if node has no parent.
    1185             :         //! Use parent() to test if node has a parent.
    1186             :         //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    1187             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
    1188             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
    1189             :         //! \return Pointer to found sibling, or 0 if not found.
    1190             :         xml_node<Ch> *previous_sibling(const Ch *name = 0, const Ch *xmlns = 0, std::size_t name_size = 0, std::size_t xmlns_size = 0, bool case_sensitive = true) const
    1191             :         {
    1192             :             assert(this->m_parent);     // Cannot query for siblings if node has no parent
    1193             :             if (name)
    1194             :             {
    1195             :                 if (name_size == 0)
    1196             :                     name_size = internal::measure(name);
    1197             :                 if (xmlns && !xmlns_size) xmlns_size = internal::measure(xmlns);
    1198             :                 if (!xmlns && name) {
    1199             :                     // No XMLNS asked for, but a name is present.
    1200             :                     // Assume "same XMLNS".
    1201             :                     xmlns = this->xmlns();
    1202             :                     xmlns_size = this->xmlns_size();
    1203             :                 }
    1204             :                 for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
    1205             :                     if ((!name || internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
    1206             :                         && (!xmlns || internal::compare(sibling->xmlns(), sibling->xmlns_size(), xmlns, xmlns_size, case_sensitive)))
    1207             :                         return sibling;
    1208             :                 return 0;
    1209             :             }
    1210             :             else
    1211             :                 return m_prev_sibling;
    1212             :         }
    1213             : 
    1214             :         //! Gets next sibling node, optionally matching node name.
    1215             :         //! Behaviour is undefined if node has no parent.
    1216             :         //! Use parent() to test if node has a parent.
    1217             :         //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    1218             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
    1219             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
    1220             :         //! \return Pointer to found sibling, or 0 if not found.
    1221      331465 :         xml_node<Ch> *next_sibling(const Ch *name = 0, const Ch *xmlns = 0, std::size_t name_size = 0, std::size_t xmlns_size = 0, bool case_sensitive = true) const
    1222             :         {
    1223      331465 :             assert(this->m_parent);     // Cannot query for siblings if node has no parent
    1224      185528 :             if (name)
    1225             :             {
    1226      185528 :                 if (name_size == 0)
    1227      185528 :                     name_size = internal::measure(name);
    1228      185528 :                 if (xmlns && !xmlns_size) xmlns_size = internal::measure(xmlns);
    1229      185528 :                 if (!xmlns && name) {
    1230             :                     // No XMLNS asked for, but a name is present.
    1231             :                     // Assume "same XMLNS".
    1232      185528 :                     xmlns = this->xmlns();
    1233      185528 :                     xmlns_size = this->xmlns_size();
    1234             :                 }
    1235      372708 :                 for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
    1236      649758 :                     if ((!name || internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
    1237      275398 :                         && (!xmlns || internal::compare(sibling->xmlns(), sibling->xmlns_size(), xmlns, xmlns_size, case_sensitive)))
    1238      137699 :                         return sibling;
    1239             :                 return 0;
    1240             :             }
    1241             :             else
    1242      145937 :                 return m_next_sibling;
    1243             :         }
    1244             : 
    1245             :         //! Gets first attribute of node, optionally matching attribute name.
    1246             :         //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    1247             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
    1248             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
    1249             :         //! \return Pointer to found attribute, or 0 if not found.
    1250     2874825 :         xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
    1251             :         {
    1252     1808114 :             if (name)
    1253             :             {
    1254     1808114 :                 if (name_size == 0)
    1255     1808114 :                     name_size = internal::measure(name);
    1256     6851865 :                 for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
    1257    11911690 :                     if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
    1258      912093 :                         return attribute;
    1259             :                 return 0;
    1260             :             }
    1261             :             else
    1262       19306 :                 return m_first_attribute;
    1263             :         }
    1264             : 
    1265             :         //! Gets last attribute of node, optionally matching attribute name.
    1266             :         //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    1267             :         //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
    1268             :         //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
    1269             :         //! \return Pointer to found attribute, or 0 if not found.
    1270             :         xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
    1271             :         {
    1272             :             if (name)
    1273             :             {
    1274             :                 if (name_size == 0)
    1275             :                     name_size = internal::measure(name);
    1276             :                 for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
    1277             :                     if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
    1278             :                         return attribute;
    1279             :                 return 0;
    1280             :             }
    1281             :             else
    1282             :                 return m_first_attribute ? m_last_attribute : 0;
    1283             :         }
    1284             : 
    1285             :         ///////////////////////////////////////////////////////////////////////////
    1286             :         // Node modification
    1287             : 
    1288             :         //! Sets type of node.
    1289             :         //! \param type Type of node to set.
    1290             :         void type(node_type type)
    1291             :         {
    1292             :             m_type = type;
    1293             :         }
    1294             : 
    1295             :         ///////////////////////////////////////////////////////////////////////////
    1296             :         // Node manipulation
    1297             : 
    1298             :         //! Prepends a new child node.
    1299             :         //! The prepended child becomes the first child, and all existing children are moved one position back.
    1300             :         //! \param child Node to prepend.
    1301             :         void prepend_node(xml_node<Ch> *child)
    1302             :         {
    1303             :             assert(child && !child->parent() && child->type() != node_document);
    1304             :             if (first_node())
    1305             :             {
    1306             :                 child->m_next_sibling = m_first_node;
    1307             :                 m_first_node->m_prev_sibling = child;
    1308             :             }
    1309             :             else
    1310             :             {
    1311             :                 child->m_next_sibling = 0;
    1312             :                 m_last_node = child;
    1313             :             }
    1314             :             m_first_node = child;
    1315             :             child->m_parent = this;
    1316             :             child->m_prev_sibling = 0;
    1317             :         }
    1318             : 
    1319             :         //! Appends a new child node.
    1320             :         //! The appended child becomes the last child.
    1321             :         //! \param child Node to append.
    1322      204926 :         void append_node(xml_node<Ch> *child)
    1323             :         {
    1324      204926 :             assert(child && !child->parent() && child->type() != node_document);
    1325      204926 :             if (first_node())
    1326             :             {
    1327      157219 :                 child->m_prev_sibling = m_last_node;
    1328      157219 :                 m_last_node->m_next_sibling = child;
    1329             :             }
    1330             :             else
    1331             :             {
    1332       47707 :                 child->m_prev_sibling = 0;
    1333       47707 :                 m_first_node = child;
    1334             :             }
    1335      204926 :             m_last_node = child;
    1336      204926 :             child->m_parent = this;
    1337      204926 :             child->m_next_sibling = 0;
    1338      204926 :         }
    1339             : 
    1340             :         //! Inserts a new child node at specified place inside the node.
    1341             :         //! All children after and including the specified node are moved one position back.
    1342             :         //! \param where Place where to insert the child, or 0 to insert at the back.
    1343             :         //! \param child Node to insert.
    1344             :         void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
    1345             :         {
    1346             :             assert(!where || where->parent() == this);
    1347             :             assert(child && !child->parent() && child->type() != node_document);
    1348             :             if (where == m_first_node)
    1349             :                 prepend_node(child);
    1350             :             else if (where == 0)
    1351             :                 append_node(child);
    1352             :             else
    1353             :             {
    1354             :                 child->m_prev_sibling = where->m_prev_sibling;
    1355             :                 child->m_next_sibling = where;
    1356             :                 where->m_prev_sibling->m_next_sibling = child;
    1357             :                 where->m_prev_sibling = child;
    1358             :                 child->m_parent = this;
    1359             :             }
    1360             :         }
    1361             : 
    1362             :         //! Removes first child node.
    1363             :         //! If node has no children, behaviour is undefined.
    1364             :         //! Use first_node() to test if node has children.
    1365             :         void remove_first_node()
    1366             :         {
    1367             :             assert(first_node());
    1368             :             xml_node<Ch> *child = m_first_node;
    1369             :             m_first_node = child->m_next_sibling;
    1370             :             if (child->m_next_sibling)
    1371             :                 child->m_next_sibling->m_prev_sibling = 0;
    1372             :             else
    1373             :                 m_last_node = 0;
    1374             :             child->m_parent = 0;
    1375             :         }
    1376             : 
    1377             :         //! Removes last child of the node.
    1378             :         //! If node has no children, behaviour is undefined.
    1379             :         //! Use first_node() to test if node has children.
    1380             :         void remove_last_node()
    1381             :         {
    1382             :             assert(first_node());
    1383             :             xml_node<Ch> *child = m_last_node;
    1384             :             if (child->m_prev_sibling)
    1385             :             {
    1386             :                 m_last_node = child->m_prev_sibling;
    1387             :                 child->m_prev_sibling->m_next_sibling = 0;
    1388             :             }
    1389             :             else
    1390             :                 m_first_node = 0;
    1391             :             child->m_parent = 0;
    1392             :         }
    1393             : 
    1394             :         //! Removes specified child from the node
    1395             :         // \param where Pointer to child to be removed.
    1396             :         void remove_node(xml_node<Ch> *where)
    1397             :         {
    1398             :             assert(where && where->parent() == this);
    1399             :             assert(first_node());
    1400             :             if (where == m_first_node)
    1401             :                 remove_first_node();
    1402             :             else if (where == m_last_node)
    1403             :                 remove_last_node();
    1404             :             else
    1405             :             {
    1406             :                 where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
    1407             :                 where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
    1408             :                 where->m_parent = 0;
    1409             :             }
    1410             :         }
    1411             : 
    1412             :         //! Removes all child nodes (but not attributes).
    1413           5 :         void remove_all_nodes()
    1414             :         {
    1415           5 :             for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
    1416           0 :                 node->m_parent = 0;
    1417           5 :             m_first_node = 0;
    1418           5 :         }
    1419             : 
    1420             :         //! Prepends a new attribute to the node.
    1421             :         //! \param attribute Attribute to prepend.
    1422             :         void prepend_attribute(xml_attribute<Ch> *attribute)
    1423             :         {
    1424             :             assert(attribute && !attribute->parent());
    1425             :             if (first_attribute())
    1426             :             {
    1427             :                 attribute->m_next_attribute = m_first_attribute;
    1428             :                 m_first_attribute->m_prev_attribute = attribute;
    1429             :             }
    1430             :             else
    1431             :             {
    1432             :                 attribute->m_next_attribute = 0;
    1433             :                 m_last_attribute = attribute;
    1434             :             }
    1435             :             m_first_attribute = attribute;
    1436             :             attribute->m_parent = this;
    1437             :             attribute->m_prev_attribute = 0;
    1438             :         }
    1439             : 
    1440             :         //! Appends a new attribute to the node.
    1441             :         //! \param attribute Attribute to append.
    1442     1047403 :         void append_attribute(xml_attribute<Ch> *attribute)
    1443             :         {
    1444     1047403 :             assert(attribute && !attribute->parent());
    1445     1047403 :             if (first_attribute())
    1446             :             {
    1447      842480 :                 attribute->m_prev_attribute = m_last_attribute;
    1448      842480 :                 m_last_attribute->m_next_attribute = attribute;
    1449             :             }
    1450             :             else
    1451             :             {
    1452      204923 :                 attribute->m_prev_attribute = 0;
    1453      204923 :                 m_first_attribute = attribute;
    1454             :             }
    1455     1047403 :             m_last_attribute = attribute;
    1456     1047403 :             attribute->m_parent = this;
    1457     1047403 :             attribute->m_next_attribute = 0;
    1458     1047403 :         }
    1459             : 
    1460             :         //! Inserts a new attribute at specified place inside the node.
    1461             :         //! All attributes after and including the specified attribute are moved one position back.
    1462             :         //! \param where Place where to insert the attribute, or 0 to insert at the back.
    1463             :         //! \param attribute Attribute to insert.
    1464             :         void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
    1465             :         {
    1466             :             assert(!where || where->parent() == this);
    1467             :             assert(attribute && !attribute->parent());
    1468             :             if (where == m_first_attribute)
    1469             :                 prepend_attribute(attribute);
    1470             :             else if (where == 0)
    1471             :                 append_attribute(attribute);
    1472             :             else
    1473             :             {
    1474             :                 attribute->m_prev_attribute = where->m_prev_attribute;
    1475             :                 attribute->m_next_attribute = where;
    1476             :                 where->m_prev_attribute->m_next_attribute = attribute;
    1477             :                 where->m_prev_attribute = attribute;
    1478             :                 attribute->m_parent = this;
    1479             :             }
    1480             :         }
    1481             : 
    1482             :         //! Removes first attribute of the node.
    1483             :         //! If node has no attributes, behaviour is undefined.
    1484             :         //! Use first_attribute() to test if node has attributes.
    1485             :         void remove_first_attribute()
    1486             :         {
    1487             :             assert(first_attribute());
    1488             :             xml_attribute<Ch> *attribute = m_first_attribute;
    1489             :             if (attribute->m_next_attribute)
    1490             :             {
    1491             :                 attribute->m_next_attribute->m_prev_attribute = 0;
    1492             :             }
    1493             :             else
    1494             :                 m_last_attribute = 0;
    1495             :             attribute->m_parent = 0;
    1496             :             m_first_attribute = attribute->m_next_attribute;
    1497             :         }
    1498             : 
    1499             :         //! Removes last attribute of the node.
    1500             :         //! If node has no attributes, behaviour is undefined.
    1501             :         //! Use first_attribute() to test if node has attributes.
    1502             :         void remove_last_attribute()
    1503             :         {
    1504             :             assert(first_attribute());
    1505             :             xml_attribute<Ch> *attribute = m_last_attribute;
    1506             :             if (attribute->m_prev_attribute)
    1507             :             {
    1508             :                 attribute->m_prev_attribute->m_next_attribute = 0;
    1509             :                 m_last_attribute = attribute->m_prev_attribute;
    1510             :             }
    1511             :             else
    1512             :                 m_first_attribute = 0;
    1513             :             attribute->m_parent = 0;
    1514             :         }
    1515             : 
    1516             :         //! Removes specified attribute from node.
    1517             :         //! \param where Pointer to attribute to be removed.
    1518             :         void remove_attribute(xml_attribute<Ch> *where)
    1519             :         {
    1520             :             assert(first_attribute() && where->parent() == this);
    1521             :             if (where == m_first_attribute)
    1522             :                 remove_first_attribute();
    1523             :             else if (where == m_last_attribute)
    1524             :                 remove_last_attribute();
    1525             :             else
    1526             :             {
    1527             :                 where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
    1528             :                 where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
    1529             :                 where->m_parent = 0;
    1530             :             }
    1531             :         }
    1532             : 
    1533             :         //! Removes all attributes of node.
    1534           5 :         void remove_all_attributes()
    1535             :         {
    1536           5 :             for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
    1537           0 :                 attribute->m_parent = 0;
    1538           5 :             m_first_attribute = 0;
    1539             :         }
    1540             : 
    1541             :         void validate() const
    1542             :         {
    1543             :             if (this->xmlns() == 0)
    1544             :                 throw validation_error("Element XMLNS unbound");
    1545             :             for (xml_node<Ch> * child = this->first_node();
    1546             :                  child;
    1547             :                  child = child->next_sibling()) {
    1548             :                 child->validate();
    1549             :             }
    1550             :             for (xml_attribute<Ch> *attribute = first_attribute();
    1551             :                  attribute;
    1552             :                  attribute = attribute->m_next_attribute) {
    1553             :                 if (attribute->xmlns() == 0)
    1554             :                     throw validation_error("Attribute XMLNS unbound");
    1555             :                 for (xml_attribute<Ch> *otherattr = first_attribute();
    1556             :                      otherattr != attribute;
    1557             :                      otherattr = otherattr->m_next_attribute) {
    1558             :                     if (internal::compare(attribute->name(), attribute->name_size(), otherattr->name(), otherattr->name_size(), true)) {
    1559             :                         throw validation_error("Attribute doubled");
    1560             :                     }
    1561             :                     if (internal::compare(attribute->local_name(), attribute->local_name_size(), otherattr->local_name(), otherattr->local_name_size(), true)
    1562             :                         && internal::compare(attribute->xmlns(), attribute->xmlns_size(), otherattr->xmlns(), otherattr->xmlns_size(), true))
    1563             :                         throw validation_error("Attribute XMLNS doubled");
    1564             :                 }
    1565             :             }
    1566             :         }
    1567             : 
    1568             :     private:
    1569             : 
    1570             :         ///////////////////////////////////////////////////////////////////////////
    1571             :         // Restrictions
    1572             : 
    1573             :         // No copying
    1574             :         xml_node(const xml_node &);
    1575             :         void operator =(const xml_node &);
    1576             : 
    1577             :         ///////////////////////////////////////////////////////////////////////////
    1578             :         // Data members
    1579             : 
    1580             :         // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
    1581             :         // This is required for maximum performance, as it allows the parser to omit initialization of
    1582             :         // unneded/redundant values.
    1583             :         //
    1584             :         // The rules are as follows:
    1585             :         // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
    1586             :         // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
    1587             :         // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
    1588             : 
    1589             :         Ch *m_prefix;
    1590             :         mutable Ch *m_xmlns; // Cache
    1591             :         std::size_t m_prefix_size;
    1592             :         mutable std::size_t m_xmlns_size;
    1593             :         node_type m_type;                       // Type of node; always valid
    1594             :         xml_node<Ch> *m_first_node;             // Pointer to first child node, or 0 if none; always valid
    1595             :         xml_node<Ch> *m_last_node;              // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
    1596             :         xml_attribute<Ch> *m_first_attribute;   // Pointer to first attribute of node, or 0 if none; always valid
    1597             :         xml_attribute<Ch> *m_last_attribute;    // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
    1598             :         xml_node<Ch> *m_prev_sibling;           // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
    1599             :         xml_node<Ch> *m_next_sibling;           // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
    1600             :         Ch const *m_contents;                   // Pointer to original contents in buffer.
    1601             :         std::size_t m_contents_size;
    1602             :     };
    1603             : 
    1604             :     ///////////////////////////////////////////////////////////////////////////
    1605             :     // XML document
    1606             : 
    1607             :     //! This class represents root of the DOM hierarchy.
    1608             :     //! It is also an xml_node and a memory_pool through public inheritance.
    1609             :     //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
    1610             :     //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
    1611             :     //! which are inherited from memory_pool.
    1612             :     //! To access root node of the document, use the document itself, as if it was an xml_node.
    1613             :     //! \param Ch Character type to use.
    1614             :     template<class Ch = char>
    1615           6 :     class xml_document: public xml_node<Ch>, public memory_pool<Ch>
    1616             :     {
    1617             : 
    1618             :     public:
    1619             : 
    1620             :         //! Constructs empty XML document
    1621           6 :         xml_document()
    1622           6 :             : xml_node<Ch>(node_document)
    1623             :         {
    1624             :         }
    1625             : 
    1626             :         //! Parses zero-terminated XML string according to given flags.
    1627             :         //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
    1628             :         //! The string must persist for the lifetime of the document.
    1629             :         //! In case of error, rapidxml::parse_error exception will be thrown.
    1630             :         //! <br><br>
    1631             :         //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
    1632             :         //! Make sure that data is zero-terminated.
    1633             :         //! <br><br>
    1634             :         //! Document can be parsed into multiple times.
    1635             :         //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
    1636             :         //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
    1637             :         template<int Flags>
    1638           5 :         Ch * parse(Ch * text, xml_document<Ch> * parent = 0)
    1639             :         {
    1640           5 :             assert(text);
    1641             : 
    1642             :             // Remove current contents
    1643           5 :             this->remove_all_nodes();
    1644           5 :             this->remove_all_attributes();
    1645           5 :             this->m_parent = parent ? parent->first_node() : 0;
    1646             : 
    1647             :             // Parse BOM, if any
    1648          23 :             parse_bom<Flags>(text);
    1649             : 
    1650             :             // Parse children
    1651             :             while (1)
    1652             :             {
    1653             :                 // Skip whitespace before node
    1654          18 :                 skip<whitespace_pred, Flags>(text);
    1655          18 :                 if (*text == 0)
    1656             :                     break;
    1657             : 
    1658             :                 // Parse and append new child
    1659          13 :                 if (*text == Ch('<'))
    1660             :                 {
    1661          13 :                     ++text;     // Skip '<'
    1662          13 :                     if (xml_node<Ch> *node = parse_node<Flags>(text)) {
    1663           5 :                         this->append_node(node);
    1664             :                         if (Flags & (parse_open_only|parse_parse_one)) {
    1665             :                             if (node->type() == node_element)
    1666             :                                 break;
    1667             :                         }
    1668             :                     }
    1669             :                 }
    1670             :                 else
    1671           0 :                     RAPIDXML_PARSE_ERROR("expected <", text);
    1672             :             }
    1673           5 :             if (!this->first_node()) RAPIDXML_PARSE_ERROR("no root element", text);
    1674           5 :             return text;
    1675             :         }
    1676             :         template<int Flags>
    1677             :         Ch * parse(Ch * text, xml_document<Ch> & parent)
    1678             :         {
    1679             :             return parse<Flags>(text, &parent);
    1680             :         }
    1681             : 
    1682             :         //! Clears the document by deleting all nodes and clearing the memory pool.
    1683             :         //! All nodes owned by document pool are destroyed.
    1684             :         void clear()
    1685             :         {
    1686             :             this->remove_all_nodes();
    1687             :             this->remove_all_attributes();
    1688             :             memory_pool<Ch>::clear();
    1689             :         }
    1690             : 
    1691             :         //! Terminates and/or decodes existing parsed tree,
    1692             :         //! optionally recursively.
    1693             :         template<int Flags>
    1694             :         void fixup(xml_node<Ch> * element, bool recurse)
    1695             :         {
    1696             :             // Check the type.
    1697             :             if (element->type() == node_element) {
    1698             :                 // Terminate name and attributes
    1699             :                 if (!(Flags & parse_no_string_terminators))
    1700             :                     element->name()[element->name_size()] = 0;
    1701             :                 for (xml_attribute<Ch> *attr = element->first_attribute();
    1702             :                      attr;
    1703             :                      attr = attr->next_attribute()) {
    1704             :                     if (!(Flags & parse_no_string_terminators))
    1705             :                         attr->name()[attr->name_size()] = 0;
    1706             :                     Ch * value = attr->value();
    1707             :                     Ch * p = value;
    1708             :                     Ch * end;
    1709             :                     const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes
    1710             :                     Ch quote = value[-1];
    1711             :                     if (quote == Ch('\''))
    1712             :                         end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(p);
    1713             :                     else
    1714             :                         end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(p);
    1715             :                     attr->value(value, end - value);
    1716             :                     if (!(Flags & parse_no_string_terminators))
    1717             :                         attr->value()[attr->value_size()] = 0;
    1718             :                 }
    1719             :                 if (recurse) {
    1720             :                     for (xml_node<Ch> *child = element->first_node();
    1721             :                          child;
    1722             :                          child = child->next_sibling()) {
    1723             :                         this->fixup<Flags>(child, true);
    1724             :                     }
    1725             :                     if (!(Flags & parse_no_string_terminators) && element->value())
    1726             :                         element->value()[element->value_size()] = 0;
    1727             :                 }
    1728             :             }
    1729             :         }
    1730             : 
    1731             : 
    1732             :         void validate() const
    1733             :         {
    1734             :             for (xml_node<Ch> * child = this->first_node();
    1735             :                  child;
    1736             :                  child = child->next_sibling()) {
    1737             :                 child->validate();
    1738             :             }
    1739             :         }
    1740             : 
    1741             :     private:
    1742             : 
    1743             :         ///////////////////////////////////////////////////////////////////////
    1744             :         // Internal character utility functions
    1745             : 
    1746             :         // Detect whitespace character
    1747             :         struct whitespace_pred
    1748             :         {
    1749     5831310 :             static unsigned char test(Ch ch)
    1750             :             {
    1751     5831310 :                 return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
    1752             :             }
    1753             :         };
    1754             : 
    1755             :         // Detect node name character
    1756             :         struct node_name_pred
    1757             :         {
    1758      273026 :             static unsigned char test(Ch ch)
    1759             :             {
    1760      273026 :                 return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
    1761             :             }
    1762             :         };
    1763             : 
    1764             :         // Detect element name character
    1765             :         struct element_name_pred
    1766             :         {
    1767     1394400 :             static unsigned char test(Ch ch)
    1768             :             {
    1769     1394400 :                 return internal::lookup_tables<0>::lookup_element_name[static_cast<unsigned char>(ch)];
    1770             :             }
    1771             :         };
    1772             : 
    1773             :         // Detect attribute name character
    1774             :         struct attribute_name_pred
    1775             :         {
    1776     5324170 :             static unsigned char test(Ch ch)
    1777             :             {
    1778     5324170 :                 return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
    1779             :             }
    1780             :         };
    1781             : 
    1782             :         // Detect text character (PCDATA)
    1783             :         struct text_pred
    1784             :         {
    1785           0 :             static unsigned char test(Ch ch)
    1786             :             {
    1787           0 :                 return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
    1788             :             }
    1789             :         };
    1790             : 
    1791             :         // Detect text character (PCDATA) that does not require processing
    1792             :         struct text_pure_no_ws_pred
    1793             :         {
    1794           0 :             static unsigned char test(Ch ch)
    1795             :             {
    1796           0 :                 return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
    1797             :             }
    1798             :         };
    1799             : 
    1800             :         // Detect text character (PCDATA) that does not require processing
    1801             :         struct text_pure_with_ws_pred
    1802             :         {
    1803             :             static unsigned char test(Ch ch)
    1804             :             {
    1805             :                 return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
    1806             :             }
    1807             :         };
    1808             : 
    1809             :         // Detect attribute value character
    1810             :         template<Ch Quote>
    1811             :         struct attribute_value_pred
    1812             :         {
    1813      912273 :             static unsigned char test(Ch ch)
    1814             :             {
    1815             :                 if (Quote == Ch('\''))
    1816           0 :                     return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
    1817             :                 if (Quote == Ch('\"'))
    1818      912273 :                     return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
    1819             :                 return 0;       // Should never be executed, to avoid warnings on Comeau
    1820             :             }
    1821             :         };
    1822             : 
    1823             :         // Detect attribute value character
    1824             :         template<Ch Quote>
    1825             :         struct attribute_value_pure_pred
    1826             :         {
    1827     9464830 :             static unsigned char test(Ch ch)
    1828             :             {
    1829             :                 if (Quote == Ch('\''))
    1830           0 :                     return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
    1831             :                 if (Quote == Ch('\"'))
    1832     9464830 :                     return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
    1833             :                 return 0;       // Should never be executed, to avoid warnings on Comeau
    1834             :             }
    1835             :         };
    1836             : 
    1837             :         // Insert coded character, using UTF8 or 8-bit ASCII
    1838             :         template<int Flags>
    1839           0 :         static void insert_coded_character(Ch *&text, unsigned long code)
    1840             :         {
    1841             :             if (Flags & parse_no_utf8)
    1842             :             {
    1843             :                 // Insert 8-bit ASCII character
    1844             :                 // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
    1845             :                 text[0] = static_cast<unsigned char>(code);
    1846             :                 text += 1;
    1847             :             }
    1848             :             else
    1849             :             {
    1850             :                 // Insert UTF8 sequence
    1851           0 :                 if (code < 0x80)    // 1 byte sequence
    1852             :                 {
    1853           0 :                         text[0] = static_cast<unsigned char>(code);
    1854           0 :                     text += 1;
    1855             :                 }
    1856           0 :                 else if (code < 0x800)  // 2 byte sequence
    1857             :                 {
    1858           0 :                         text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
    1859           0 :                         text[0] = static_cast<unsigned char>(code | 0xC0);
    1860           0 :                     text += 2;
    1861             :                 }
    1862           0 :                     else if (code < 0x10000)    // 3 byte sequence
    1863             :                 {
    1864           0 :                         text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
    1865           0 :                         text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
    1866           0 :                         text[0] = static_cast<unsigned char>(code | 0xE0);
    1867           0 :                     text += 3;
    1868             :                 }
    1869           0 :                     else if (code < 0x110000)   // 4 byte sequence
    1870             :                 {
    1871           0 :                         text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
    1872           0 :                         text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
    1873           0 :                         text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
    1874           0 :                         text[0] = static_cast<unsigned char>(code | 0xF0);
    1875           0 :                     text += 4;
    1876             :                 }
    1877             :                 else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
    1878             :                 {
    1879           0 :                     RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
    1880             :                 }
    1881             :             }
    1882           0 :         }
    1883             : 
    1884             :         // Skip characters until predicate evaluates to true
    1885             :         template<class StopPred, int Flags>
    1886     5261340 :         static void skip(Ch *&text)
    1887             :         {
    1888          18 :             Ch *tmp = text;
    1889    21189800 :             while (StopPred::test(*tmp))
    1890    15928500 :                 ++tmp;
    1891          18 :             text = tmp;
    1892      912273 :         }
    1893             : 
    1894             :         // Skip characters until predicate evaluates to true while doing the following:
    1895             :         // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
    1896             :         // - condensing whitespace sequences to single space character
    1897             :         template<class StopPred, class StopPredPure, int Flags>
    1898      912273 :         static Ch *skip_and_expand_character_refs(Ch *&text)
    1899             :         {
    1900             :             // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
    1901             :             if (Flags & parse_no_entity_translation &&
    1902             :                 !(Flags & parse_normalize_whitespace) &&
    1903             :                 !(Flags & parse_trim_whitespace))
    1904             :             {
    1905             :                 skip<StopPred, Flags>(text);
    1906             :                 return text;
    1907             :             }
    1908             : 
    1909             :             // Use simple skip until first modification is detected
    1910      912273 :             skip<StopPredPure, Flags>(text);
    1911             : 
    1912             :             // Use translation skip
    1913      912273 :             Ch *src = text;
    1914      912273 :             Ch *dest = src;
    1915      912273 :             while (StopPred::test(*src))
    1916             :             {
    1917             :                 // If entity translation is enabled
    1918             :                 if (!(Flags & parse_no_entity_translation))
    1919             :                 {
    1920             :                     // Test if replacement is needed
    1921           0 :                     if (src[0] == Ch('&'))
    1922             :                     {
    1923           0 :                         switch (src[1])
    1924             :                         {
    1925             : 
    1926             :                         // &amp; &apos;
    1927           0 :                         case Ch('a'):
    1928           0 :                             if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
    1929             :                             {
    1930           0 :                                 *dest = Ch('&');
    1931           0 :                                 ++dest;
    1932           0 :                                 src += 5;
    1933           0 :                                 continue;
    1934             :                             }
    1935           0 :                             if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
    1936             :                             {
    1937           0 :                                 *dest = Ch('\'');
    1938           0 :                                 ++dest;
    1939           0 :                                 src += 6;
    1940           0 :                                 continue;
    1941             :                             }
    1942             :                             break;
    1943             : 
    1944             :                         // &quot;
    1945           0 :                         case Ch('q'):
    1946           0 :                             if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
    1947             :                             {
    1948           0 :                                 *dest = Ch('"');
    1949           0 :                                 ++dest;
    1950           0 :                                 src += 6;
    1951           0 :                                 continue;
    1952             :                             }
    1953             :                             break;
    1954             : 
    1955             :                         // &gt;
    1956           0 :                         case Ch('g'):
    1957           0 :                             if (src[2] == Ch('t') && src[3] == Ch(';'))
    1958             :                             {
    1959           0 :                                 *dest = Ch('>');
    1960           0 :                                 ++dest;
    1961           0 :                                 src += 4;
    1962           0 :                                 continue;
    1963             :                             }
    1964             :                             break;
    1965             : 
    1966             :                         // &lt;
    1967           0 :                         case Ch('l'):
    1968           0 :                             if (src[2] == Ch('t') && src[3] == Ch(';'))
    1969             :                             {
    1970           0 :                                 *dest = Ch('<');
    1971           0 :                                 ++dest;
    1972           0 :                                 src += 4;
    1973           0 :                                 continue;
    1974             :                             }
    1975             :                             break;
    1976             : 
    1977             :                         // &#...; - assumes ASCII
    1978           0 :                         case Ch('#'):
    1979           0 :                             if (src[2] == Ch('x'))
    1980             :                             {
    1981           0 :                                 unsigned long code = 0;
    1982           0 :                                 src += 3;   // Skip &#x
    1983           0 :                                 while (1)
    1984             :                                 {
    1985           0 :                                     unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
    1986           0 :                                     if (digit == 0xFF)
    1987             :                                         break;
    1988           0 :                                     code = code * 16 + digit;
    1989           0 :                                     ++src;
    1990             :                                 }
    1991           0 :                                 insert_coded_character<Flags>(dest, code);    // Put character in output
    1992             :                             }
    1993             :                             else
    1994             :                             {
    1995           0 :                                 unsigned long code = 0;
    1996           0 :                                 src += 2;   // Skip &#
    1997           0 :                                 while (1)
    1998             :                                 {
    1999           0 :                                     unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
    2000           0 :                                     if (digit == 0xFF)
    2001             :                                         break;
    2002           0 :                                     code = code * 10 + digit;
    2003           0 :                                     ++src;
    2004             :                                 }
    2005           0 :                                 insert_coded_character<Flags>(dest, code);    // Put character in output
    2006             :                             }
    2007           0 :                             if (*src == Ch(';'))
    2008           0 :                                 ++src;
    2009             :                             else
    2010           0 :                                 RAPIDXML_PARSE_ERROR("expected ;", src);
    2011           0 :                             continue;
    2012             : 
    2013             :                         // Something else
    2014             :                         default:
    2015             :                             // Ignore, just copy '&' verbatim
    2016           0 :                             break;
    2017             : 
    2018             :                         }
    2019             :                     }
    2020             :                 }
    2021             : 
    2022             :                 // If whitespace condensing is enabled
    2023             :                 if (Flags & parse_normalize_whitespace)
    2024             :                 {
    2025             :                     // Test if condensing is needed
    2026             :                     if (whitespace_pred::test(*src))
    2027             :                     {
    2028             :                         *dest = Ch(' '); ++dest;    // Put single space in dest
    2029             :                         ++src;                      // Skip first whitespace char
    2030             :                         // Skip remaining whitespace chars
    2031             :                         while (whitespace_pred::test(*src))
    2032             :                             ++src;
    2033             :                         continue;
    2034             :                     }
    2035             :                 }
    2036             : 
    2037             :                 // No replacement, only copy character
    2038           0 :                 *dest++ = *src++;
    2039             : 
    2040             :             }
    2041             : 
    2042             :             // Return new end
    2043      912273 :             text = src;
    2044      912273 :             return dest;
    2045             : 
    2046             :         }
    2047             : 
    2048             :         ///////////////////////////////////////////////////////////////////////
    2049             :         // Internal parsing functions
    2050             : 
    2051             :         // Parse BOM, if any
    2052             :         template<int Flags>
    2053           5 :         void parse_bom(Ch *&text)
    2054             :         {
    2055             :             // UTF-8?
    2056           5 :             if (static_cast<unsigned char>(text[0]) == 0xEF &&
    2057           0 :                 static_cast<unsigned char>(text[1]) == 0xBB &&
    2058           0 :                 static_cast<unsigned char>(text[2]) == 0xBF)
    2059             :             {
    2060           0 :                 text += 3;      // Skup utf-8 bom
    2061             :             }
    2062             :         }
    2063             : 
    2064             :         // Parse XML declaration (<?xml...)
    2065             :         template<int Flags>
    2066           4 :         xml_node<Ch> *parse_xml_declaration(Ch *&text)
    2067             :         {
    2068             :             // If parsing of declaration is disabled
    2069             :             if (!(Flags & parse_declaration_node))
    2070             :             {
    2071             :                 // Skip until end of declaration
    2072         124 :                 while (text[0] != Ch('?') || text[1] != Ch('>'))
    2073             :                 {
    2074         120 :                     if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2075         120 :                     ++text;
    2076             :                 }
    2077           4 :                 text += 2;    // Skip '?>'
    2078             :                 return 0;
    2079             :             }
    2080             : 
    2081             :             // Create declaration
    2082             :             xml_node<Ch> *declaration = this->allocate_node(node_declaration);
    2083             : 
    2084             :             // Skip whitespace before attributes or ?>
    2085             :             skip<whitespace_pred, Flags>(text);
    2086             : 
    2087             :             // Parse declaration attributes
    2088             :             parse_node_attributes<Flags>(text, declaration);
    2089             : 
    2090             :             // Skip ?>
    2091             :             if (text[0] != Ch('?') || text[1] != Ch('>')) RAPIDXML_PARSE_ERROR("expected ?>", text);
    2092             :             text += 2;
    2093             : 
    2094             :             return declaration;
    2095             :         }
    2096             : 
    2097             :         // Parse XML comment (<!--...)
    2098             :         template<int Flags>
    2099           4 :         xml_node<Ch> *parse_comment(Ch *&text)
    2100             :         {
    2101             :             // If parsing of comments is disabled
    2102             :             if (!(Flags & parse_comment_nodes))
    2103             :             {
    2104             :                 // Skip until end of comment
    2105        3642 :                 while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
    2106             :                 {
    2107        3638 :                     if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2108        3638 :                     ++text;
    2109             :                 }
    2110           4 :                 text += 3;     // Skip '-->'
    2111             :                 return 0;      // Do not produce comment node
    2112             :             }
    2113             : 
    2114             :             // Remember value start
    2115             :             Ch *value = text;
    2116             : 
    2117             :             // Skip until end of comment
    2118             :             while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
    2119             :             {
    2120             :                 if (!text[0]) RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2121             :                 ++text;
    2122             :             }
    2123             : 
    2124             :             // Create comment node
    2125             :             xml_node<Ch> *comment = this->allocate_node(node_comment);
    2126             :             comment->value(value, text - value);
    2127             : 
    2128             :             // Place zero terminator after comment value
    2129             :             if (!(Flags & parse_no_string_terminators))
    2130             :                 *text = Ch('\0');
    2131             : 
    2132             :             text += 3;     // Skip '-->'
    2133             :             return comment;
    2134             :         }
    2135             : 
    2136             :         // Parse DOCTYPE
    2137             :         template<int Flags>
    2138           0 :         xml_node<Ch> *parse_doctype(Ch *&text)
    2139             :         {
    2140             :             // Remember value start
    2141           0 :             Ch *value = text;
    2142             : 
    2143             :             // Skip to >
    2144           0 :             while (*text != Ch('>'))
    2145             :             {
    2146             :                 // Determine character type
    2147           0 :                 switch (*text)
    2148             :                 {
    2149             : 
    2150             :                 // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
    2151             :                 // This works for all W3C test files except for 2 most wicked
    2152           0 :                 case Ch('['):
    2153             :                 {
    2154           0 :                     ++text;     // Skip '['
    2155           0 :                     int depth = 1;
    2156           0 :                     while (depth > 0)
    2157             :                     {
    2158           0 :                         switch (*text)
    2159             :                         {
    2160           0 :                             case Ch('['): ++depth; break;
    2161           0 :                             case Ch(']'): --depth; break;
    2162           0 :                             case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2163             :                         }
    2164           0 :                         ++text;
    2165             :                     }
    2166             :                     break;
    2167             :                 }
    2168             : 
    2169             :                 // Error on end of text
    2170           0 :                 case Ch('\0'):
    2171           0 :                     RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2172             : 
    2173             :                 // Other character, skip it
    2174           0 :                 default:
    2175           0 :                     ++text;
    2176             : 
    2177             :                 }
    2178             :             }
    2179             : 
    2180             :             // If DOCTYPE nodes enabled
    2181             :             if (Flags & parse_doctype_node)
    2182             :             {
    2183             :                 // Create a new doctype node
    2184             :                 xml_node<Ch> *doctype = this->allocate_node(node_doctype);
    2185             :                 doctype->value(value, text - value);
    2186             : 
    2187             :                 // Place zero terminator after value
    2188             :                 if (!(Flags & parse_no_string_terminators))
    2189             :                     *text = Ch('\0');
    2190             : 
    2191             :                 text += 1;      // skip '>'
    2192             :                 return doctype;
    2193             :             }
    2194             :             else
    2195             :             {
    2196           0 :                 text += 1;      // skip '>'
    2197             :                 return 0;
    2198             :             }
    2199             : 
    2200             :         }
    2201             : 
    2202             :         // Parse PI
    2203             :         template<int Flags>
    2204           0 :         xml_node<Ch> *parse_pi(Ch *&text)
    2205             :         {
    2206             :             // If creation of PI nodes is enabled
    2207             :             if (Flags & parse_pi_nodes)
    2208             :             {
    2209             :                 // Create pi node
    2210             :                 xml_node<Ch> *pi = this->allocate_node(node_pi);
    2211             : 
    2212             :                 // Extract PI target name
    2213             :                 Ch *name = text;
    2214             :                 skip<node_name_pred, Flags>(text);
    2215             :                 if (text == name) RAPIDXML_PARSE_ERROR("expected PI target", text);
    2216             :                 pi->name(name, text - name);
    2217             : 
    2218             :                 // Skip whitespace between pi target and pi
    2219             :                 skip<whitespace_pred, Flags>(text);
    2220             : 
    2221             :                 // Remember start of pi
    2222             :                 Ch *value = text;
    2223             : 
    2224             :                 // Skip to '?>'
    2225             :                 while (text[0] != Ch('?') || text[1] != Ch('>'))
    2226             :                 {
    2227             :                     if (*text == Ch('\0'))
    2228             :                         RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2229             :                     ++text;
    2230             :                 }
    2231             : 
    2232             :                 // Set pi value (verbatim, no entity expansion or whitespace normalization)
    2233             :                 pi->value(value, text - value);
    2234             : 
    2235             :                 // Place zero terminator after name and value
    2236             :                 if (!(Flags & parse_no_string_terminators))
    2237             :                 {
    2238             :                     pi->name()[pi->name_size()] = Ch('\0');
    2239             :                     pi->value()[pi->value_size()] = Ch('\0');
    2240             :                 }
    2241             : 
    2242             :                 text += 2;                          // Skip '?>'
    2243             :                 return pi;
    2244             :             }
    2245             :             else
    2246             :             {
    2247             :                 // Skip to '?>'
    2248           0 :                 while (text[0] != Ch('?') || text[1] != Ch('>'))
    2249             :                 {
    2250           0 :                     if (*text == Ch('\0'))
    2251           0 :                         RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2252           0 :                     ++text;
    2253             :                 }
    2254           0 :                 text += 2;    // Skip '?>'
    2255             :                 return 0;
    2256             :             }
    2257             :         }
    2258             : 
    2259             :         // Parse and append data
    2260             :         // Return character that ends data.
    2261             :         // This is necessary because this character might have been overwritten by a terminating 0
    2262             :         template<int Flags>
    2263           0 :         Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
    2264             :         {
    2265             :             // Backup to contents start if whitespace trimming is disabled
    2266             :             if (!(Flags & parse_trim_whitespace))
    2267           0 :                 text = contents_start;
    2268             : 
    2269             :             // Skip until end of data
    2270           0 :             Ch *value = text, *end;
    2271             :             if (Flags & parse_normalize_whitespace)
    2272             :                 end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
    2273             :             else
    2274           0 :                 end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
    2275             : 
    2276             :             // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
    2277             :             if (Flags & parse_trim_whitespace)
    2278             :             {
    2279             :                 if (Flags & parse_normalize_whitespace)
    2280             :                 {
    2281             :                     // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
    2282             :                     if (*(end - 1) == Ch(' '))
    2283             :                         --end;
    2284             :                 }
    2285             :                 else
    2286             :                 {
    2287             :                     // Backup until non-whitespace character is found
    2288             :                     while (whitespace_pred::test(*(end - 1)))
    2289             :                         --end;
    2290             :                 }
    2291             :             }
    2292             : 
    2293             :             // If characters are still left between end and value (this test is only necessary if normalization is enabled)
    2294             :             // Create new data node
    2295             :             if (!(Flags & parse_no_data_nodes))
    2296             :             {
    2297           0 :                 xml_node<Ch> *data = this->allocate_node(node_data);
    2298           0 :                 data->value(value, end - value);
    2299           0 :                 node->append_node(data);
    2300             :             }
    2301             : 
    2302             :             // Add data to parent node if no data exists yet
    2303             :             if (!(Flags & parse_no_element_values))
    2304           0 :                 if (*node->value() == Ch('\0'))
    2305           0 :                     node->value(value, end - value);
    2306             : 
    2307             :             // Place zero terminator after value
    2308             :             if (!(Flags & parse_no_string_terminators))
    2309             :             {
    2310           0 :                 Ch ch = *text;
    2311           0 :                 *end = Ch('\0');
    2312             :                 return ch;      // Return character that ends data; this is required because zero terminator overwritten it
    2313             :             }
    2314             : 
    2315             :             // Return character that ends data
    2316             :             return *text;
    2317             :         }
    2318             : 
    2319             :         // Parse CDATA
    2320             :         template<int Flags>
    2321           0 :         xml_node<Ch> *parse_cdata(Ch *&text)
    2322             :         {
    2323             :             // If CDATA is disabled
    2324             :             if (Flags & parse_no_data_nodes)
    2325             :             {
    2326             :                 // Skip until end of cdata
    2327             :                 while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
    2328             :                 {
    2329             :                     if (!text[0])
    2330             :                         RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2331             :                     ++text;
    2332             :                 }
    2333             :                 text += 3;      // Skip ]]>
    2334             :                 return 0;       // Do not produce CDATA node
    2335             :             }
    2336             : 
    2337             :             // Skip until end of cdata
    2338           0 :             Ch *value = text;
    2339           0 :             while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
    2340             :             {
    2341           0 :                 if (!text[0])
    2342           0 :                     RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2343           0 :                 ++text;
    2344             :             }
    2345             : 
    2346             :             // Create new cdata node
    2347           0 :             xml_node<Ch> *cdata = this->allocate_node(node_cdata);
    2348           0 :             cdata->value(value, text - value);
    2349             : 
    2350             :             // Place zero terminator after value
    2351             :             if (!(Flags & parse_no_string_terminators))
    2352           0 :                 *text = Ch('\0');
    2353             : 
    2354           0 :             text += 3;      // Skip ]]>
    2355             :             return cdata;
    2356             :         }
    2357             : 
    2358             :         // Parse element node
    2359             :         template<int Flags>
    2360      185620 :         xml_node<Ch> *parse_element(Ch *&text)
    2361             :         {
    2362             :             // Create element node
    2363      185620 :             xml_node<Ch> *element = this->allocate_node(node_element);
    2364             : 
    2365             :             // Extract element name
    2366      185620 :             Ch *prefix = text;
    2367      185620 :             skip<element_name_pred, Flags>(text);
    2368      185620 :             if (text == prefix)
    2369           0 :                 RAPIDXML_PARSE_ERROR("expected element name or prefix", text);
    2370      185620 :             if (*text == Ch(':')) {
    2371           0 :                 element->prefix(prefix, text - prefix);
    2372           0 :                 ++text;
    2373           0 :                 Ch *name = text;
    2374           0 :                 skip<node_name_pred, Flags>(text);
    2375           0 :                 if (text == name)
    2376           0 :                     RAPIDXML_PARSE_ERROR("expected element local name", text);
    2377           0 :                 element->name(name, text - name);
    2378             :             } else {
    2379      185620 :                 element->name(prefix, text - prefix);
    2380             :             }
    2381             : 
    2382             :             // Skip whitespace between element name and attributes or >
    2383      185620 :             skip<whitespace_pred, Flags>(text);
    2384             : 
    2385             :             // Parse attributes, if any
    2386      185620 :             parse_node_attributes<Flags>(text, element);
    2387             : 
    2388             :             // Determine ending type
    2389      185620 :             if (*text == Ch('>'))
    2390             :             {
    2391       47699 :                 Ch const * contents = ++text;
    2392       47699 :                 Ch const * contents_end = 0;
    2393             :                 if (!(Flags & parse_open_only))
    2394       47699 :                     contents_end = parse_node_contents<Flags>(text, element);
    2395       47699 :                 std::size_t sz = contents_end - contents;
    2396       47699 :                 if (sz) element->contents(contents, sz);
    2397             :             }
    2398      137921 :             else if (*text == Ch('/'))
    2399             :             {
    2400      137921 :                 ++text;
    2401      137921 :                 if (*text != Ch('>'))
    2402           0 :                     RAPIDXML_PARSE_ERROR("expected >", text);
    2403      137921 :                 ++text;
    2404             :                 if (Flags & parse_open_only)
    2405             :                     RAPIDXML_PARSE_ERROR("open_only, but closed", text);
    2406             :             }
    2407             :             else
    2408           0 :                 RAPIDXML_PARSE_ERROR("expected >", text);
    2409             : 
    2410             :             // Place zero terminator after name
    2411             :             if (!(Flags & parse_no_string_terminators)) {
    2412      185620 :                 element->name()[element->name_size()] = Ch('\0');
    2413      185620 :                 if (element->prefix()) element->prefix()[element->prefix_size()] = Ch('\0');
    2414             :             }
    2415             : 
    2416             :             // Return parsed element
    2417      185620 :             return element;
    2418             :         }
    2419             : 
    2420             :         // Determine node type, and parse it
    2421             :         template<int Flags>
    2422      185628 :         xml_node<Ch> *parse_node(Ch *&text)
    2423             :         {
    2424             :             // Parse proper node type
    2425      185628 :             switch (text[0])
    2426             :             {
    2427             : 
    2428             :             // <...
    2429      185620 :             default:
    2430             :                 // Parse and append element node
    2431      185620 :                 return parse_element<Flags>(text);
    2432             : 
    2433             :             // <?...
    2434           4 :             case Ch('?'):
    2435           4 :                 ++text;     // Skip ?
    2436           8 :                 if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
    2437           4 :                     (text[1] == Ch('m') || text[1] == Ch('M')) &&
    2438           8 :                     (text[2] == Ch('l') || text[2] == Ch('L')) &&
    2439           4 :                     whitespace_pred::test(text[3]))
    2440             :                 {
    2441             :                     // '<?xml ' - xml declaration
    2442           4 :                     text += 4;      // Skip 'xml '
    2443           4 :                     return parse_xml_declaration<Flags>(text);
    2444             :                 }
    2445             :                 else
    2446             :                 {
    2447             :                     // Parse PI
    2448           0 :                     return parse_pi<Flags>(text);
    2449             :                 }
    2450             : 
    2451             :             // <!...
    2452           4 :             case Ch('!'):
    2453             : 
    2454             :                 // Parse proper subset of <! node
    2455           4 :                 switch (text[1])
    2456             :                 {
    2457             : 
    2458             :                 // <!-
    2459           4 :                 case Ch('-'):
    2460           4 :                     if (text[2] == Ch('-'))
    2461             :                     {
    2462             :                         // '<!--' - xml comment
    2463           4 :                         text += 3;     // Skip '!--'
    2464           4 :                         return parse_comment<Flags>(text);
    2465             :                     }
    2466             :                     break;
    2467             : 
    2468             :                 // <![
    2469           0 :                 case Ch('['):
    2470           0 :                     if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
    2471           0 :                         text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
    2472             :                     {
    2473             :                         // '<![CDATA[' - cdata
    2474           0 :                         text += 8;     // Skip '![CDATA['
    2475           0 :                         return parse_cdata<Flags>(text);
    2476             :                     }
    2477             :                     break;
    2478             : 
    2479             :                 // <!D
    2480           0 :                 case Ch('D'):
    2481           0 :                     if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
    2482           0 :                         text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
    2483           0 :                         whitespace_pred::test(text[8]))
    2484             :                     {
    2485             :                         // '<!DOCTYPE ' - doctype
    2486           0 :                         text += 9;      // skip '!DOCTYPE '
    2487           0 :                         return parse_doctype<Flags>(text);
    2488             :                     }
    2489             : 
    2490             :                 }   // switch
    2491             : 
    2492             :                 // Attempt to skip other, unrecognized node types starting with <!
    2493           0 :                 ++text;     // Skip !
    2494           0 :                 while (*text != Ch('>'))
    2495             :                 {
    2496           0 :                     if (*text == 0)
    2497           0 :                         RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2498           0 :                     ++text;
    2499             :                 }
    2500           0 :                 ++text;     // Skip '>'
    2501           0 :                 return 0;   // No node recognized
    2502             : 
    2503             :             }
    2504             :         }
    2505             : 
    2506             :         // Parse contents of the node - children, data etc.
    2507             :         // Return end pointer.
    2508             :         template<int Flags>
    2509       47699 :         Ch * parse_node_contents(Ch *&text, xml_node<Ch> *node)
    2510             :         {
    2511       47699 :             Ch * retval = 0;
    2512             :             // For all children and text
    2513             :             while (1)
    2514             :             {
    2515             :                 // Skip whitespace between > and node contents
    2516      233314 :                 Ch *contents_start = text;      // Store start of node contents before whitespace is skipped
    2517      233314 :                 skip<whitespace_pred, Flags>(text);
    2518      233314 :                 Ch next_char = *text;
    2519             : 
    2520             :             // After data nodes, instead of continuing the loop, control jumps here.
    2521             :             // This is because zero termination inside parse_and_append_data() function
    2522             :             // would wreak havoc with the above code.
    2523             :             // Also, skipping whitespace after data nodes is unnecessary.
    2524      233314 :             after_data_node:
    2525             : 
    2526             :                 // Determine what comes next: node closing, child node, data node, or 0?
    2527      233314 :                 switch (next_char)
    2528             :                 {
    2529             : 
    2530             :                 // Node closing or child node
    2531      233314 :                 case Ch('<'):
    2532      233314 :                     if (text[1] == Ch('/'))
    2533             :                     {
    2534             :                         // Node closing
    2535       47699 :                         retval = text;
    2536       47699 :                         text += 2;      // Skip '</'
    2537             :                         if (Flags & parse_validate_closing_tags)
    2538             :                         {
    2539             :                             // Skip and validate closing tag name
    2540             :                             Ch *closing_name = text;
    2541             :                             skip<node_name_pred, Flags>(text);
    2542             :                             if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
    2543             :                                 RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
    2544             :                         }
    2545             :                         else
    2546             :                         {
    2547             :                             // No validation, just skip name
    2548       47699 :                             skip<node_name_pred, Flags>(text);
    2549             :                         }
    2550             :                         // Skip remaining whitespace after node name
    2551       47699 :                         skip<whitespace_pred, Flags>(text);
    2552       47699 :                         if (*text != Ch('>'))
    2553           0 :                             RAPIDXML_PARSE_ERROR("expected >", text);
    2554       47699 :                         ++text;     // Skip '>'
    2555             :                         if (Flags & parse_open_only)
    2556             :                             RAPIDXML_PARSE_ERROR("Unclosed element actually closed.", text);
    2557             :                         return retval;     // Node closed, finished parsing contents
    2558             :                     }
    2559             :                     else
    2560             :                     {
    2561             :                         // Child node
    2562      185615 :                         ++text;     // Skip '<'
    2563      185615 :                         if (xml_node<Ch> *child = parse_node<Flags & ~parse_open_only>(text))
    2564      185615 :                             node->append_node(child);
    2565             :                     }
    2566             :                     break;
    2567             : 
    2568             :                 // End of data - error unless we expected this.
    2569             :                 case Ch('\0'):
    2570             :                     if (Flags & parse_open_only) {
    2571             :                         return 0;
    2572             :                     } else {
    2573           0 :                         RAPIDXML_PARSE_ERROR("unexpected end of data", text);
    2574             :                     }
    2575             : 
    2576             :                 // Data node
    2577           0 :                 default:
    2578           0 :                     next_char = parse_and_append_data<Flags>(node, text, contents_start);
    2579           0 :                     goto after_data_node;   // Bypass regular processing after data nodes
    2580             : 
    2581             :                 }
    2582             :             }
    2583             :         }
    2584             : 
    2585             :         // Parse XML attributes of the node
    2586             :         template<int Flags>
    2587      185620 :         void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
    2588             :         {
    2589             :             // For all attributes
    2590     1097890 :             while (attribute_name_pred::test(*text))
    2591             :             {
    2592             :                 // Extract attribute name
    2593      912273 :                 Ch *name = text;
    2594      912273 :                 ++text;     // Skip first character of attribute name
    2595      912273 :                 skip<attribute_name_pred, Flags>(text);
    2596      912273 :                 if (text == name)
    2597           0 :                     RAPIDXML_PARSE_ERROR("expected attribute name", name);
    2598             : 
    2599             :                 // Create new attribute
    2600      912273 :                 xml_attribute<Ch> *attribute = this->allocate_attribute();
    2601      912273 :                 attribute->name(name, text - name);
    2602      912273 :                 node->append_attribute(attribute);
    2603             : 
    2604             :                 // Skip whitespace after attribute name
    2605      912273 :                 skip<whitespace_pred, Flags>(text);
    2606             : 
    2607             :                 // Skip =
    2608      912273 :                 if (*text != Ch('='))
    2609           0 :                     RAPIDXML_PARSE_ERROR("expected =", text);
    2610      912273 :                 ++text;
    2611             : 
    2612             :                 // Add terminating zero after name
    2613             :                 if (!(Flags & parse_no_string_terminators))
    2614     1824550 :                     attribute->name()[attribute->name_size()] = 0;
    2615             : 
    2616             :                 // Skip whitespace after =
    2617      912273 :                 skip<whitespace_pred, Flags>(text);
    2618             : 
    2619             :                 // Skip quote and remember if it was ' or "
    2620      912273 :                 Ch quote = *text;
    2621      912273 :                 if (quote != Ch('\'') && quote != Ch('"'))
    2622           0 :                     RAPIDXML_PARSE_ERROR("expected ' or \"", text);
    2623      912273 :                 ++text;
    2624             : 
    2625             :                 // Extract attribute value and expand char refs in it
    2626      912273 :                 Ch *value = text, *end;
    2627      912273 :                 const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes
    2628      912273 :                 if (quote == Ch('\''))
    2629           0 :                     end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
    2630             :                 else
    2631      912273 :                     end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
    2632             : 
    2633             :                 // Set attribute value
    2634      912273 :                 attribute->value(value, end - value);
    2635             : 
    2636             :                 // Make sure that end quote is present
    2637      912273 :                 if (*text != quote)
    2638           0 :                     RAPIDXML_PARSE_ERROR("expected ' or \"", text);
    2639      912273 :                 ++text;     // Skip quote
    2640             : 
    2641             :                 // Add terminating zero after value
    2642             :                 if (!(Flags & parse_no_string_terminators))
    2643     1824550 :                     attribute->value()[attribute->value_size()] = 0;
    2644             : 
    2645             :                 // Skip whitespace after attribute value
    2646     1097890 :                 skip<whitespace_pred, Flags>(text);
    2647             :             }
    2648      185620 :         }
    2649             : 
    2650             :     };
    2651             : 
    2652             :     //! \cond internal
    2653             :     namespace internal
    2654             :     {
    2655             : 
    2656             :         // Whitespace (space \n \r \t)
    2657             :         template<int Dummy>
    2658             :         const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
    2659             :         {
    2660             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2661             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0
    2662             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
    2663             :              1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2
    2664             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3
    2665             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4
    2666             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5
    2667             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6
    2668             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7
    2669             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8
    2670             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9
    2671             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A
    2672             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B
    2673             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C
    2674             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D
    2675             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E
    2676             :              0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F
    2677             :         };
    2678             : 
    2679             :         // Element name (anything but space \n \r \t / > ? \0 and :)
    2680             :         template<int Dummy>
    2681             :         const unsigned char lookup_tables<Dummy>::lookup_element_name[256] =
    2682             :         {
    2683             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2684             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
    2685             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2686             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
    2687             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  0,  0,  // 3
    2688             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2689             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2690             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2691             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2692             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2693             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2694             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2695             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2696             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2697             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2698             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2699             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2700             :         };
    2701             : 
    2702             :         // Node name (anything but space \n \r \t / > ? \0)
    2703             :         template<int Dummy>
    2704             :         const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
    2705             :         {
    2706             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2707             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
    2708             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2709             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
    2710             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
    2711             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2712             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2713             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2714             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2715             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2716             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2717             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2718             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2719             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2720             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2721             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2722             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2723             :         };
    2724             : 
    2725             :         // Text (i.e. PCDATA) (anything but < \0)
    2726             :         template<int Dummy>
    2727             :         const unsigned char lookup_tables<Dummy>::lookup_text[256] =
    2728             :         {
    2729             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2730             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
    2731             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2732             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
    2733             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
    2734             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2735             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2736             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2737             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2738             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2739             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2740             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2741             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2742             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2743             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2744             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2745             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2746             :         };
    2747             : 
    2748             :         // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
    2749             :         // (anything but < \0 &)
    2750             :         template<int Dummy>
    2751             :         const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
    2752             :         {
    2753             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2754             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
    2755             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2756             :              1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
    2757             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
    2758             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2759             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2760             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2761             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2762             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2763             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2764             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2765             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2766             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2767             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2768             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2769             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2770             :         };
    2771             : 
    2772             :         // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
    2773             :         // (anything but < \0 & space \n \r \t)
    2774             :         template<int Dummy>
    2775             :         const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
    2776             :         {
    2777             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2778             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
    2779             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2780             :              0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
    2781             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
    2782             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2783             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2784             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2785             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2786             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2787             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2788             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2789             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2790             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2791             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2792             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2793             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2794             :         };
    2795             : 
    2796             :         // Attribute name (anything but space \n \r \t / < > = ? ! \0)
    2797             :         template<int Dummy>
    2798             :         const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
    2799             :         {
    2800             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2801             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
    2802             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2803             :              0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
    2804             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3
    2805             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2806             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2807             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2808             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2809             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2810             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2811             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2812             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2813             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2814             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2815             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2816             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2817             :         };
    2818             : 
    2819             :         // Attribute data with single quote (anything but ' \0)
    2820             :         template<int Dummy>
    2821             :         const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
    2822             :         {
    2823             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2824             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
    2825             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2826             :              1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
    2827             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
    2828             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2829             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2830             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2831             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2832             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2833             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2834             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2835             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2836             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2837             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2838             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2839             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2840             :         };
    2841             : 
    2842             :         // Attribute data with single quote that does not require processing (anything but ' \0 &)
    2843             :         template<int Dummy>
    2844             :         const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
    2845             :         {
    2846             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2847             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
    2848             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2849             :              1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
    2850             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
    2851             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2852             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2853             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2854             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2855             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2856             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2857             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2858             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2859             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2860             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2861             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2862             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2863             :         };
    2864             : 
    2865             :         // Attribute data with double quote (anything but " \0)
    2866             :         template<int Dummy>
    2867             :         const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
    2868             :         {
    2869             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2870             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
    2871             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2872             :              1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
    2873             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
    2874             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2875             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2876             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2877             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2878             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2879             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2880             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2881             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2882             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2883             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2884             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2885             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2886             :         };
    2887             : 
    2888             :         // Attribute data with double quote that does not require processing (anything but " \0 &)
    2889             :         template<int Dummy>
    2890             :         const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
    2891             :         {
    2892             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2893             :              0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
    2894             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
    2895             :              1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
    2896             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
    2897             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
    2898             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
    2899             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
    2900             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
    2901             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
    2902             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
    2903             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
    2904             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
    2905             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
    2906             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
    2907             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
    2908             :              1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
    2909             :         };
    2910             : 
    2911             :         // Digits (dec and hex, 255 denotes end of numeric character reference)
    2912             :         template<int Dummy>
    2913             :         const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
    2914             :         {
    2915             :           // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    2916             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0
    2917             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1
    2918             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2
    2919             :              0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,  // 3
    2920             :            255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4
    2921             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5
    2922             :            255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6
    2923             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7
    2924             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8
    2925             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9
    2926             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A
    2927             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B
    2928             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C
    2929             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D
    2930             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E
    2931             :            255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F
    2932             :         };
    2933             : 
    2934             :         // Upper case conversion
    2935             :         template<int Dummy>
    2936             :         const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
    2937             :         {
    2938             :           // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F
    2939             :            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0
    2940             :            16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1
    2941             :            32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2
    2942             :            48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3
    2943             :            64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4
    2944             :            80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5
    2945             :            96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6
    2946             :            80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127,  // 7
    2947             :            128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,  // 8
    2948             :            144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,  // 9
    2949             :            160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,  // A
    2950             :            176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,  // B
    2951             :            192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,  // C
    2952             :            208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,  // D
    2953             :            224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,  // E
    2954             :            240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255   // F
    2955             :         };
    2956             :     }
    2957             :     //! \endcond
    2958             : 
    2959             : }
    2960             : 
    2961             : // Undefine internal macros
    2962             : #undef RAPIDXML_PARSE_ERROR
    2963             : 
    2964             : // On MSVC, restore warnings state
    2965             : #ifdef _MSC_VER
    2966             :     #pragma warning(pop)
    2967             : #endif
    2968             : 
    2969             : #endif

Generated by: LCOV version 1.14