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

Generated by: LCOV version 2.0-1