TWRP-ify AOSP code

Pull in most TWRP sources
Stub out partition management code
Make it compile -- probably will not boot
Kind of a mess but have to start somewhere
diff --git a/gui/rapidxml.hpp b/gui/rapidxml.hpp
new file mode 100644
index 0000000..d98173e
--- /dev/null
+++ b/gui/rapidxml.hpp
@@ -0,0 +1,2598 @@
+#ifndef RAPIDXML_HPP_INCLUDED

+#define RAPIDXML_HPP_INCLUDED

+

+#define RAPIDXML_NO_EXCEPTIONS

+

+// Copyright (C) 2006, 2009 Marcin Kalicinski

+// Version 1.13

+// Revision $DateTime: 2009/05/13 01:46:17 $

+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation

+

+// If standard library is disabled, user must provide implementations of required functions and typedefs

+#if !defined(RAPIDXML_NO_STDLIB)

+    #include <cstdlib>      // For std::size_t

+    #include <cassert>      // For assert

+    #include <new>          // For placement new

+#endif

+

+// On MSVC, disable "conditional expression is constant" warning (level 4). 

+// This warning is almost impossible to avoid with certain types of templated code

+#ifdef _MSC_VER

+    #pragma warning(push)

+    #pragma warning(disable:4127)   // Conditional expression is constant

+#endif

+

+///////////////////////////////////////////////////////////////////////////

+// RAPIDXML_PARSE_ERROR

+    

+#if defined(RAPIDXML_NO_EXCEPTIONS)

+

+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }

+

+namespace rapidxml

+{

+    //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, 

+    //! this function is called to notify user about the error.

+    //! It must be defined by the user.

+    //! <br><br>

+    //! This function cannot return. If it does, the results are undefined.

+    //! <br><br>

+    //! A very simple definition might look like that:

+    //! <pre>

+    //! void %rapidxml::%parse_error_handler(const char *what, void *where)

+    //! {

+    //!     std::cout << "Parse error: " << what << "\n";

+    //!     std::abort();

+    //! }

+    //! </pre>

+    //! \param what Human readable description of the error.

+    //! \param where Pointer to character data where error was detected.

+    void parse_error_handler(const char *what, void *where);

+}

+

+#else

+    

+#include <exception>    // For std::exception

+

+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)

+

+namespace rapidxml

+{

+

+    //! Parse error exception. 

+    //! This exception is thrown by the parser when an error occurs. 

+    //! Use what() function to get human-readable error message. 

+    //! Use where() function to get a pointer to position within source text where error was detected.

+    //! <br><br>

+    //! If throwing exceptions by the parser is undesirable, 

+    //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.

+    //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.

+    //! This function must be defined by the user.

+    //! <br><br>

+    //! This class derives from <code>std::exception</code> class.

+    class parse_error: public std::exception

+    {

+    

+    public:

+    

+        //! Constructs parse error

+        parse_error(const char *what, void *where)

+            : m_what(what)

+            , m_where(where)

+        {

+        }

+

+        //! Gets human readable description of error.

+        //! \return Pointer to null terminated description of the error.

+        virtual const char *what() const throw()

+        {

+            return m_what;

+        }

+

+        //! Gets pointer to character data where error happened.

+        //! Ch should be the same as char type of xml_document that produced the error.

+        //! \return Pointer to location within the parsed string where error occured.

+        template<class Ch>

+        Ch *where() const

+        {

+            return reinterpret_cast<Ch *>(m_where);

+        }

+

+    private:  

+

+        const char *m_what;

+        void *m_where;

+

+    };

+}

+

+#endif

+

+///////////////////////////////////////////////////////////////////////////

+// Pool sizes

+

+#ifndef RAPIDXML_STATIC_POOL_SIZE

+    // Size of static memory block of memory_pool.

+    // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.

+    // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.

+    #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)

+#endif

+

+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE

+    // Size of dynamic memory block of memory_pool.

+    // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.

+    // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.

+    #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)

+#endif

+

+#ifndef RAPIDXML_ALIGNMENT

+    // Memory allocation alignment.

+    // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.

+    // All memory allocations for nodes, attributes and strings will be aligned to this value.

+    // This must be a power of 2 and at least 1, otherwise memory_pool will not work.

+    #define RAPIDXML_ALIGNMENT sizeof(void *)

+#endif

+

+namespace rapidxml

+{

+    // Forward declarations

+    template<class Ch> class xml_node;

+    template<class Ch> class xml_attribute;

+    template<class Ch> class xml_document;

+    

+    //! Enumeration listing all node types produced by the parser.

+    //! Use xml_node::type() function to query node type.

+    enum node_type

+    {

+        node_document,      //!< A document node. Name and value are empty.

+        node_element,       //!< An element node. Name contains element name. Value contains text of first data node.

+        node_data,          //!< A data node. Name is empty. Value contains data text.

+        node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.

+        node_comment,       //!< A comment node. Name is empty. Value contains comment text.

+        node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.

+        node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.

+        node_pi             //!< A PI node. Name contains target. Value contains instructions.

+    };

+

+    ///////////////////////////////////////////////////////////////////////

+    // Parsing flags

+

+    //! Parse flag instructing the parser to not create data nodes. 

+    //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_no_data_nodes = 0x1;            

+

+    //! Parse flag instructing the parser to not use text of first data node as a value of parent element.

+    //! Can be combined with other flags by use of | operator.

+    //! Note that child data nodes of element node take precendence over its value when printing. 

+    //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.

+    //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_no_element_values = 0x2;

+    

+    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.

+    //! By default zero terminators are placed, modifying source text.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_no_string_terminators = 0x4;

+    

+    //! Parse flag instructing the parser to not translate entities in the source text.

+    //! By default entities are translated, modifying source text.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_no_entity_translation = 0x8;

+    

+    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.

+    //! By default, UTF-8 handling is enabled.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_no_utf8 = 0x10;

+    

+    //! Parse flag instructing the parser to create XML declaration node.

+    //! By default, declaration node is not created.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_declaration_node = 0x20;

+    

+    //! Parse flag instructing the parser to create comments nodes.

+    //! By default, comment nodes are not created.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_comment_nodes = 0x40;

+    

+    //! Parse flag instructing the parser to create DOCTYPE node.

+    //! By default, doctype node is not created.

+    //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_doctype_node = 0x80;

+    

+    //! Parse flag instructing the parser to create PI nodes.

+    //! By default, PI nodes are not created.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_pi_nodes = 0x100;

+    

+    //! Parse flag instructing the parser to validate closing tag names. 

+    //! If not set, name inside closing tag is irrelevant to the parser.

+    //! By default, closing tags are not validated.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_validate_closing_tags = 0x200;

+    

+    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.

+    //! By default, whitespace is not trimmed. 

+    //! This flag does not cause the parser to modify source text.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_trim_whitespace = 0x400;

+

+    //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.

+    //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.

+    //! By default, whitespace is not normalized. 

+    //! If this flag is specified, source text will be modified.

+    //! Can be combined with other flags by use of | operator.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_normalize_whitespace = 0x800;

+

+    // Compound flags

+    

+    //! Parse flags which represent default behaviour of the parser. 

+    //! This is always equal to 0, so that all other flags can be simply ored together.

+    //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.

+    //! This also means that meaning of each flag is a <i>negation</i> of the default setting. 

+    //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,

+    //! and using the flag will disable it.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_default = 0;

+    

+    //! A combination of parse flags that forbids any modifications of the source text. 

+    //! This also results in faster parsing. However, note that the following will occur:

+    //! <ul>

+    //! <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>

+    //! <li>entities will not be translated</li>

+    //! <li>whitespace will not be normalized</li>

+    //! </ul>

+    //! See xml_document::parse() function.

+    const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;

+    

+    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_fastest = parse_non_destructive | parse_no_data_nodes;

+    

+    //! A combination of parse flags resulting in largest amount of data being extracted. 

+    //! This usually results in slowest parsing.

+    //! <br><br>

+    //! See xml_document::parse() function.

+    const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;

+

+    ///////////////////////////////////////////////////////////////////////

+    // Internals

+

+    //! \cond internal

+    namespace internal

+    {

+

+        // Struct that contains lookup tables for the parser

+        // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).

+        template<int Dummy>

+        struct lookup_tables

+        {

+            static const unsigned char lookup_whitespace[256];              // Whitespace table

+            static const unsigned char lookup_node_name[256];               // Node name table

+            static const unsigned char lookup_text[256];                    // Text table

+            static const unsigned char lookup_text_pure_no_ws[256];         // Text table

+            static const unsigned char lookup_text_pure_with_ws[256];       // Text table

+            static const unsigned char lookup_attribute_name[256];          // Attribute name table

+            static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote

+            static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote

+            static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes

+            static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes

+            static const unsigned char lookup_digits[256];                  // Digits

+            static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters

+        };

+

+        // Find length of the string

+        template<class Ch>

+        inline std::size_t measure(const Ch *p)

+        {

+            const Ch *tmp = p;

+            while (*tmp) 

+                ++tmp;

+            return tmp - p;

+        }

+

+        // Compare strings for equality

+        template<class Ch>

+        inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)

+        {

+            if (size1 != size2)

+                return false;

+            if (case_sensitive)

+            {

+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)

+                    if (*p1 != *p2)

+                        return false;

+            }

+            else

+            {

+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)

+                    if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])

+                        return false;

+            }

+            return true;

+        }

+    }

+    //! \endcond

+

+    ///////////////////////////////////////////////////////////////////////

+    // Memory pool

+    

+    //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.

+    //! In most cases, you will not need to use this class directly. 

+    //! However, if you need to create nodes manually or modify names/values of nodes, 

+    //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. 

+    //! Not only is this faster than allocating them by using <code>new</code> operator, 

+    //! but also their lifetime will be tied to the lifetime of document, 

+    //! possibly simplyfing memory management. 

+    //! <br><br>

+    //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. 

+    //! You can also call allocate_string() function to allocate strings.

+    //! Such strings can then be used as names or values of nodes without worrying about their lifetime.

+    //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called, 

+    //! or when the pool is destroyed.

+    //! <br><br>

+    //! It is also possible to create a standalone memory_pool, and use it 

+    //! to allocate nodes, whose lifetime will not be tied to any document.

+    //! <br><br>

+    //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory. 

+    //! Until static memory is exhausted, no dynamic memory allocations are done.

+    //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,

+    //! by using global <code>new[]</code> and <code>delete[]</code> operators. 

+    //! This behaviour can be changed by setting custom allocation routines. 

+    //! Use set_allocator() function to set them.

+    //! <br><br>

+    //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.

+    //! This value defaults to the size of pointer on target architecture.

+    //! <br><br>

+    //! To obtain absolutely top performance from the parser,

+    //! it is important that all nodes are allocated from a single, contiguous block of memory.

+    //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.

+    //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code> 

+    //! to obtain best wasted memory to performance compromise.

+    //! To do it, define their values before rapidxml.hpp file is included.

+    //! \param Ch Character type of created nodes. 

+    template<class Ch = char>

+    class memory_pool

+    {

+        

+    public:

+

+        //! \cond internal

+        typedef void *(alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory

+        typedef void (free_func)(void *);              // Type of user-defined function used to free memory

+        //! \endcond

+        

+        //! Constructs empty pool with default allocator functions.

+        memory_pool()

+            : m_alloc_func(0)

+            , m_free_func(0)

+        {

+            init();

+        }

+

+        //! Destroys pool and frees all the memory. 

+        //! This causes memory occupied by nodes allocated by the pool to be freed.

+        //! Nodes allocated from the pool are no longer valid.

+        ~memory_pool()

+        {

+            clear();

+        }

+

+        //! Allocates a new node from the pool, and optionally assigns name and value to it. 

+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.

+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function

+        //! will call rapidxml::parse_error_handler() function.

+        //! \param type Type of node to create.

+        //! \param name Name to assign to the node, or 0 to assign no name.

+        //! \param value Value to assign to the node, or 0 to assign no value.

+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.

+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.

+        //! \return Pointer to allocated node. This pointer will never be NULL.

+        xml_node<Ch> *allocate_node(node_type type, 

+                                    const Ch *name = 0, const Ch *value = 0, 

+                                    std::size_t name_size = 0, std::size_t value_size = 0)

+        {

+            void *memory = allocate_aligned(sizeof(xml_node<Ch>));

+            xml_node<Ch> *node = new(memory) xml_node<Ch>(type);

+            if (name)

+            {

+                if (name_size > 0)

+                    node->name(name, name_size);

+                else

+                    node->name(name);

+            }

+            if (value)

+            {

+                if (value_size > 0)

+                    node->value(value, value_size);

+                else

+                    node->value(value);

+            }

+            return node;

+        }

+

+        //! Allocates a new attribute from the pool, and optionally assigns name and value to it.

+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.

+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function

+        //! will call rapidxml::parse_error_handler() function.

+        //! \param name Name to assign to the attribute, or 0 to assign no name.

+        //! \param value Value to assign to the attribute, or 0 to assign no value.

+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.

+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.

+        //! \return Pointer to allocated attribute. This pointer will never be NULL.

+        xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0, 

+                                              std::size_t name_size = 0, std::size_t value_size = 0)

+        {

+            void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));

+            xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;

+            if (name)

+            {

+                if (name_size > 0)

+                    attribute->name(name, name_size);

+                else

+                    attribute->name(name);

+            }

+            if (value)

+            {

+                if (value_size > 0)

+                    attribute->value(value, value_size);

+                else

+                    attribute->value(value);

+            }

+            return attribute;

+        }

+

+        //! Allocates a char array of given size from the pool, and optionally copies a given string to it.

+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.

+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function

+        //! will call rapidxml::parse_error_handler() function.

+        //! \param source String to initialize the allocated memory with, or 0 to not initialize it.

+        //! \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.

+        //! \return Pointer to allocated char array. This pointer will never be NULL.

+        Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)

+        {

+            assert(source || size);     // Either source or size (or both) must be specified

+            if (size == 0)

+                size = internal::measure(source) + 1;

+            Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));

+            if (source)

+                for (std::size_t i = 0; i < size; ++i)

+                    result[i] = source[i];

+            return result;

+        }

+

+        //! Clones an xml_node and its hierarchy of child nodes and attributes.

+        //! Nodes and attributes are allocated from this memory pool.

+        //! Names and values are not cloned, they are shared between the clone and the source.

+        //! Result node can be optionally specified as a second parameter, 

+        //! in which case its contents will be replaced with cloned source node.

+        //! This is useful when you want to clone entire document.

+        //! \param source Node to clone.

+        //! \param result Node to put results in, or 0 to automatically allocate result node

+        //! \return Pointer to cloned node. This pointer will never be NULL.

+        xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)

+        {

+            // Prepare result node

+            if (result)

+            {

+                result->remove_all_attributes();

+                result->remove_all_nodes();

+                result->type(source->type());

+            }

+            else

+                result = allocate_node(source->type());

+

+            // Clone name and value

+            result->name(source->name(), source->name_size());

+            result->value(source->value(), source->value_size());

+

+            // Clone child nodes and attributes

+            for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())

+                result->append_node(clone_node(child));

+            for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())

+                result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));

+

+            return result;

+        }

+

+        //! Clears the pool. 

+        //! This causes memory occupied by nodes allocated by the pool to be freed.

+        //! Any nodes or strings allocated from the pool will no longer be valid.

+        void clear()

+        {

+            while (m_begin != m_static_memory)

+            {

+                char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;

+                if (m_free_func)

+                    m_free_func(m_begin);

+                else

+                    delete[] m_begin;

+                m_begin = previous_begin;

+            }

+            init();

+        }

+

+        //! Sets or resets the user-defined memory allocation functions for the pool.

+        //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.

+        //! Allocation function must not return invalid pointer on failure. It should either throw,

+        //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program. 

+        //! If it returns invalid pointer, results are undefined.

+        //! <br><br>

+        //! User defined allocation functions must have the following forms:

+        //! <br><code>

+        //! <br>void *allocate(std::size_t size);

+        //! <br>void free(void *pointer);

+        //! </code><br>

+        //! \param af Allocation function, or 0 to restore default function

+        //! \param ff Free function, or 0 to restore default function

+        void set_allocator(alloc_func *af, free_func *ff)

+        {

+            assert(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet

+            m_alloc_func = af;

+            m_free_func = ff;

+        }

+

+    private:

+

+        struct header

+        {

+            char *previous_begin;

+        };

+

+        void init()

+        {

+            m_begin = m_static_memory;

+            m_ptr = align(m_begin);

+            m_end = m_static_memory + sizeof(m_static_memory);

+        }

+        

+        char *align(char *ptr)

+        {

+            std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));

+            return ptr + alignment;

+        }

+        

+        char *allocate_raw(std::size_t size)

+        {

+            // Allocate

+            void *memory;   

+            if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]

+            {

+                memory = m_alloc_func(size);

+                assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp

+            }

+            else

+            {

+                memory = new char[size];

+#ifdef RAPIDXML_NO_EXCEPTIONS

+                if (!memory)            // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc

+                    RAPIDXML_PARSE_ERROR("out of memory", 0);

+#endif

+            }

+            return static_cast<char *>(memory);

+        }

+        

+        void *allocate_aligned(std::size_t size)

+        {

+            // Calculate aligned pointer

+            char *result = align(m_ptr);

+

+            // If not enough memory left in current pool, allocate a new pool

+            if (result + size > m_end)

+            {

+                // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)

+                std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;

+                if (pool_size < size)

+                    pool_size = size;

+                

+                // Allocate

+                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

+                char *raw_memory = allocate_raw(alloc_size);

+                    

+                // Setup new pool in allocated memory

+                char *pool = align(raw_memory);

+                header *new_header = reinterpret_cast<header *>(pool);

+                new_header->previous_begin = m_begin;

+                m_begin = raw_memory;

+                m_ptr = pool + sizeof(header);

+                m_end = raw_memory + alloc_size;

+

+                // Calculate aligned pointer again using new pool

+                result = align(m_ptr);

+            }

+

+            // Update pool and return aligned pointer

+            m_ptr = result + size;

+            return result;

+        }

+

+        char *m_begin;                                      // Start of raw memory making up current pool

+        char *m_ptr;                                        // First free byte in current pool

+        char *m_end;                                        // One past last available byte in current pool

+        char m_static_memory[RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory

+        alloc_func *m_alloc_func;                           // Allocator function, or 0 if default is to be used

+        free_func *m_free_func;                             // Free function, or 0 if default is to be used

+    };

+

+    ///////////////////////////////////////////////////////////////////////////

+    // XML base

+

+    //! Base class for xml_node and xml_attribute implementing common functions: 

+    //! name(), name_size(), value(), value_size() and parent().

+    //! \param Ch Character type to use

+    template<class Ch = char>

+    class xml_base

+    {

+

+    public:

+        

+        ///////////////////////////////////////////////////////////////////////////

+        // Construction & destruction

+    

+        // Construct a base with empty name, value and parent

+        xml_base()

+            : m_name(0)

+            , m_value(0)

+            , m_parent(0)

+        {

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Node data access

+    

+        //! Gets name of the node. 

+        //! Interpretation of name depends on type of node.

+        //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

+        //! <br><br>

+        //! Use name_size() function to determine length of the name.

+        //! \return Name of node, or empty string if node has no name.

+        Ch *name() const

+        {

+            return m_name ? m_name : nullstr();

+        }

+

+        //! Gets size of node name, not including terminator character.

+        //! This function works correctly irrespective of whether name is or is not zero terminated.

+        //! \return Size of node name, in characters.

+        std::size_t name_size() const

+        {

+            return m_name ? m_name_size : 0;

+        }

+

+        //! Gets value of node. 

+        //! Interpretation of value depends on type of node.

+        //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

+        //! <br><br>

+        //! Use value_size() function to determine length of the value.

+        //! \return Value of node, or empty string if node has no value.

+        Ch *value() const

+        {

+            return m_value ? m_value : nullstr();

+        }

+

+        //! Gets size of node value, not including terminator character.

+        //! This function works correctly irrespective of whether value is or is not zero terminated.

+        //! \return Size of node value, in characters.

+        std::size_t value_size() const

+        {

+            return m_value ? m_value_size : 0;

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Node modification

+    

+        //! Sets name of node to a non zero-terminated string.

+        //! See \ref ownership_of_strings.

+        //! <br><br>

+        //! Note that node does not own its name or value, it only stores a pointer to it. 

+        //! It will not delete or otherwise free the pointer on destruction.

+        //! It is reponsibility of the user to properly manage lifetime of the string.

+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -

+        //! on destruction of the document the string will be automatically freed.

+        //! <br><br>

+        //! Size of name must be specified separately, because name does not have to be zero terminated.

+        //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).

+        //! \param name Name of node to set. Does not have to be zero terminated.

+        //! \param size Size of name, in characters. This does not include zero terminator, if one is present.

+        void name(const Ch *name, std::size_t size)

+        {

+            m_name = const_cast<Ch *>(name);

+            m_name_size = size;

+        }

+

+        //! Sets name of node to a zero-terminated string.

+        //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).

+        //! \param name Name of node to set. Must be zero terminated.

+        void name(const Ch *name)

+        {

+            this->name(name, internal::measure(name));

+        }

+

+        //! Sets value of node to a non zero-terminated string.

+        //! See \ref ownership_of_strings.

+        //! <br><br>

+        //! Note that node does not own its name or value, it only stores a pointer to it. 

+        //! It will not delete or otherwise free the pointer on destruction.

+        //! It is reponsibility of the user to properly manage lifetime of the string.

+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -

+        //! on destruction of the document the string will be automatically freed.

+        //! <br><br>

+        //! Size of value must be specified separately, because it does not have to be zero terminated.

+        //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).

+        //! <br><br>

+        //! If an element has a child node of type node_data, it will take precedence over element value when printing.

+        //! 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.

+        //! \param value value of node to set. Does not have to be zero terminated.

+        //! \param size Size of value, in characters. This does not include zero terminator, if one is present.

+        void value(const Ch *value, std::size_t size)

+        {

+            m_value = const_cast<Ch *>(value);

+            m_value_size = size;

+        }

+

+        //! Sets value of node to a zero-terminated string.

+        //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).

+        //! \param value Vame of node to set. Must be zero terminated.

+        void value(const Ch *value)

+        {

+            this->value(value, internal::measure(value));

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Related nodes access

+    

+        //! Gets node parent.

+        //! \return Pointer to parent node, or 0 if there is no parent.

+        xml_node<Ch> *parent() const

+        {

+            return m_parent;

+        }

+

+    protected:

+

+        // Return empty string

+        static Ch *nullstr()

+        {

+            static Ch zero = Ch('\0');

+            return &zero;

+        }

+

+        Ch *m_name;                         // Name of node, or 0 if no name

+        Ch *m_value;                        // Value of node, or 0 if no value

+        std::size_t m_name_size;            // Length of node name, or undefined of no name

+        std::size_t m_value_size;           // Length of node value, or undefined if no value

+        xml_node<Ch> *m_parent;             // Pointer to parent node, or 0 if none

+

+    };

+

+    //! Class representing attribute node of XML document. 

+    //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).

+    //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. 

+    //! Thus, this text must persist in memory for the lifetime of attribute.

+    //! \param Ch Character type to use.

+    template<class Ch = char>

+    class xml_attribute: public xml_base<Ch>

+    {

+

+        friend class xml_node<Ch>;

+    

+    public:

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Construction & destruction

+    

+        //! Constructs an empty attribute with the specified type. 

+        //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.

+        xml_attribute()

+        {

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Related nodes access

+    

+        //! Gets document of which attribute is a child.

+        //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.

+        xml_document<Ch> *document() const

+        {

+            if (xml_node<Ch> *node = this->parent())

+            {

+                while (node->parent())

+                    node = node->parent();

+                return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;

+            }

+            else

+                return 0;

+        }

+

+        //! Gets previous attribute, optionally matching attribute name. 

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found attribute, or 0 if not found.

+        xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)

+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))

+                        return attribute;

+                return 0;

+            }

+            else

+                return this->m_parent ? m_prev_attribute : 0;

+        }

+

+        //! Gets next attribute, optionally matching attribute name. 

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found attribute, or 0 if not found.

+        xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)

+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))

+                        return attribute;

+                return 0;

+            }

+            else

+                return this->m_parent ? m_next_attribute : 0;

+        }

+

+    private:

+

+        xml_attribute<Ch> *m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero

+        xml_attribute<Ch> *m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero

+    

+    };

+

+    ///////////////////////////////////////////////////////////////////////////

+    // XML node

+

+    //! Class representing a node of XML document. 

+    //! Each node may have associated name and value strings, which are available through name() and value() functions. 

+    //! Interpretation of name and value depends on type of the node.

+    //! Type of node can be determined by using type() function.

+    //! <br><br>

+    //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. 

+    //! Thus, this text must persist in the memory for the lifetime of node.

+    //! \param Ch Character type to use.

+    template<class Ch = char>

+    class xml_node: public xml_base<Ch>

+    {

+

+    public:

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Construction & destruction

+    

+        //! Constructs an empty node with the specified type. 

+        //! Consider using memory_pool of appropriate document to allocate nodes manually.

+        //! \param type Type of node to construct.

+        xml_node(node_type type)

+            : m_type(type)

+            , m_first_node(0)

+            , m_first_attribute(0)

+        {

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Node data access

+    

+        //! Gets type of node.

+        //! \return Type of node.

+        node_type type() const

+        {

+            return m_type;

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Related nodes access

+    

+        //! Gets document of which node is a child.

+        //! \return Pointer to document that contains this node, or 0 if there is no parent document.

+        xml_document<Ch> *document() const

+        {

+            xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);

+            while (node->parent())

+                node = node->parent();

+            return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;

+        }

+

+        //! Gets first child node, optionally matching node name.

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found child, or 0 if not found.

+        xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())

+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))

+                        return child;

+                return 0;

+            }

+            else

+                return m_first_node;

+        }

+

+        //! Gets last child node, optionally matching node name. 

+        //! Behaviour is undefined if node has no children.

+        //! Use first_node() to test if node has children.

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found child, or 0 if not found.

+        xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            assert(m_first_node);  // Cannot query for last child if node has no children

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())

+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))

+                        return child;

+                return 0;

+            }

+            else

+                return m_last_node;

+        }

+

+        //! Gets previous sibling node, optionally matching node name. 

+        //! Behaviour is undefined if node has no parent.

+        //! Use parent() to test if node has a parent.

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found sibling, or 0 if not found.

+        xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            assert(this->m_parent);     // Cannot query for siblings if node has no parent

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)

+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))

+                        return sibling;

+                return 0;

+            }

+            else

+                return m_prev_sibling;

+        }

+

+        //! Gets next sibling node, optionally matching node name. 

+        //! Behaviour is undefined if node has no parent.

+        //! Use parent() to test if node has a parent.

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found sibling, or 0 if not found.

+        xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            assert(this->m_parent);     // Cannot query for siblings if node has no parent

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)

+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))

+                        return sibling;

+                return 0;

+            }

+            else

+                return m_next_sibling;

+        }

+

+        //! Gets first attribute of node, optionally matching attribute name.

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found attribute, or 0 if not found.

+        xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)

+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))

+                        return attribute;

+                return 0;

+            }

+            else

+                return m_first_attribute;

+        }

+

+        //! Gets last attribute of node, optionally matching attribute name.

+        //! \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

+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string

+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

+        //! \return Pointer to found attribute, or 0 if not found.

+        xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const

+        {

+            if (name)

+            {

+                if (name_size == 0)

+                    name_size = internal::measure(name);

+                for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)

+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))

+                        return attribute;

+                return 0;

+            }

+            else

+                return m_first_attribute ? m_last_attribute : 0;

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Node modification

+    

+        //! Sets type of node.

+        //! \param type Type of node to set.

+        void type(node_type type)

+        {

+            m_type = type;

+        }

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Node manipulation

+

+        //! Prepends a new child node.

+        //! The prepended child becomes the first child, and all existing children are moved one position back.

+        //! \param child Node to prepend.

+        void prepend_node(xml_node<Ch> *child)

+        {

+            assert(child && !child->parent() && child->type() != node_document);

+            if (first_node())

+            {

+                child->m_next_sibling = m_first_node;

+                m_first_node->m_prev_sibling = child;

+            }

+            else

+            {

+                child->m_next_sibling = 0;

+                m_last_node = child;

+            }

+            m_first_node = child;

+            child->m_parent = this;

+            child->m_prev_sibling = 0;

+        }

+

+        //! Appends a new child node. 

+        //! The appended child becomes the last child.

+        //! \param child Node to append.

+        void append_node(xml_node<Ch> *child)

+        {

+            assert(child && !child->parent() && child->type() != node_document);

+            if (first_node())

+            {

+                child->m_prev_sibling = m_last_node;

+                m_last_node->m_next_sibling = child;

+            }

+            else

+            {

+                child->m_prev_sibling = 0;

+                m_first_node = child;

+            }

+            m_last_node = child;

+            child->m_parent = this;

+            child->m_next_sibling = 0;

+        }

+

+        //! Inserts a new child node at specified place inside the node. 

+        //! All children after and including the specified node are moved one position back.

+        //! \param where Place where to insert the child, or 0 to insert at the back.

+        //! \param child Node to insert.

+        void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)

+        {

+            assert(!where || where->parent() == this);

+            assert(child && !child->parent() && child->type() != node_document);

+            if (where == m_first_node)

+                prepend_node(child);

+            else if (where == 0)

+                append_node(child);

+            else

+            {

+                child->m_prev_sibling = where->m_prev_sibling;

+                child->m_next_sibling = where;

+                where->m_prev_sibling->m_next_sibling = child;

+                where->m_prev_sibling = child;

+                child->m_parent = this;

+            }

+        }

+

+        //! Removes first child node. 

+        //! If node has no children, behaviour is undefined.

+        //! Use first_node() to test if node has children.

+        void remove_first_node()

+        {

+            assert(first_node());

+            xml_node<Ch> *child = m_first_node;

+            m_first_node = child->m_next_sibling;

+            if (child->m_next_sibling)

+                child->m_next_sibling->m_prev_sibling = 0;

+            else

+                m_last_node = 0;

+            child->m_parent = 0;

+        }

+

+        //! Removes last child of the node. 

+        //! If node has no children, behaviour is undefined.

+        //! Use first_node() to test if node has children.

+        void remove_last_node()

+        {

+            assert(first_node());

+            xml_node<Ch> *child = m_last_node;

+            if (child->m_prev_sibling)

+            {

+                m_last_node = child->m_prev_sibling;

+                child->m_prev_sibling->m_next_sibling = 0;

+            }

+            else

+                m_first_node = 0;

+            child->m_parent = 0;

+        }

+

+        //! Removes specified child from the node

+        // \param where Pointer to child to be removed.

+        void remove_node(xml_node<Ch> *where)

+        {

+            assert(where && where->parent() == this);

+            assert(first_node());

+            if (where == m_first_node)

+                remove_first_node();

+            else if (where == m_last_node)

+                remove_last_node();

+            else

+            {

+                where->m_prev_sibling->m_next_sibling = where->m_next_sibling;

+                where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;

+                where->m_parent = 0;

+            }

+        }

+

+        //! Removes all child nodes (but not attributes).

+        void remove_all_nodes()

+        {

+            for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)

+                node->m_parent = 0;

+            m_first_node = 0;

+        }

+

+        //! Prepends a new attribute to the node.

+        //! \param attribute Attribute to prepend.

+        void prepend_attribute(xml_attribute<Ch> *attribute)

+        {

+            assert(attribute && !attribute->parent());

+            if (first_attribute())

+            {

+                attribute->m_next_attribute = m_first_attribute;

+                m_first_attribute->m_prev_attribute = attribute;

+            }

+            else

+            {

+                attribute->m_next_attribute = 0;

+                m_last_attribute = attribute;

+            }

+            m_first_attribute = attribute;

+            attribute->m_parent = this;

+            attribute->m_prev_attribute = 0;

+        }

+

+        //! Appends a new attribute to the node.

+        //! \param attribute Attribute to append.

+        void append_attribute(xml_attribute<Ch> *attribute)

+        {

+            assert(attribute && !attribute->parent());

+            if (first_attribute())

+            {

+                attribute->m_prev_attribute = m_last_attribute;

+                m_last_attribute->m_next_attribute = attribute;

+            }

+            else

+            {

+                attribute->m_prev_attribute = 0;

+                m_first_attribute = attribute;

+            }

+            m_last_attribute = attribute;

+            attribute->m_parent = this;

+            attribute->m_next_attribute = 0;

+        }

+

+        //! Inserts a new attribute at specified place inside the node. 

+        //! All attributes after and including the specified attribute are moved one position back.

+        //! \param where Place where to insert the attribute, or 0 to insert at the back.

+        //! \param attribute Attribute to insert.

+        void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)

+        {

+            assert(!where || where->parent() == this);

+            assert(attribute && !attribute->parent());

+            if (where == m_first_attribute)

+                prepend_attribute(attribute);

+            else if (where == 0)

+                append_attribute(attribute);

+            else

+            {

+                attribute->m_prev_attribute = where->m_prev_attribute;

+                attribute->m_next_attribute = where;

+                where->m_prev_attribute->m_next_attribute = attribute;

+                where->m_prev_attribute = attribute;

+                attribute->m_parent = this;

+            }

+        }

+

+        //! Removes first attribute of the node. 

+        //! If node has no attributes, behaviour is undefined.

+        //! Use first_attribute() to test if node has attributes.

+        void remove_first_attribute()

+        {

+            assert(first_attribute());

+            xml_attribute<Ch> *attribute = m_first_attribute;

+            if (attribute->m_next_attribute)

+            {

+                attribute->m_next_attribute->m_prev_attribute = 0;

+            }

+            else

+                m_last_attribute = 0;

+            attribute->m_parent = 0;

+            m_first_attribute = attribute->m_next_attribute;

+        }

+

+        //! Removes last attribute of the node. 

+        //! If node has no attributes, behaviour is undefined.

+        //! Use first_attribute() to test if node has attributes.

+        void remove_last_attribute()

+        {

+            assert(first_attribute());

+            xml_attribute<Ch> *attribute = m_last_attribute;

+            if (attribute->m_prev_attribute)

+            {

+                attribute->m_prev_attribute->m_next_attribute = 0;

+                m_last_attribute = attribute->m_prev_attribute;

+            }

+            else

+                m_first_attribute = 0;

+            attribute->m_parent = 0;

+        }

+

+        //! Removes specified attribute from node.

+        //! \param where Pointer to attribute to be removed.

+        void remove_attribute(xml_attribute<Ch> *where)

+        {

+            assert(first_attribute() && where->parent() == this);

+            if (where == m_first_attribute)

+                remove_first_attribute();

+            else if (where == m_last_attribute)

+                remove_last_attribute();

+            else

+            {

+                where->m_prev_attribute->m_next_attribute = where->m_next_attribute;

+                where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;

+                where->m_parent = 0;

+            }

+        }

+

+        //! Removes all attributes of node.

+        void remove_all_attributes()

+        {

+            for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)

+                attribute->m_parent = 0;

+            m_first_attribute = 0;

+        }

+        

+    private:

+

+        ///////////////////////////////////////////////////////////////////////////

+        // Restrictions

+

+        // No copying

+        xml_node(const xml_node &);

+        void operator =(const xml_node &);

+    

+        ///////////////////////////////////////////////////////////////////////////

+        // Data members

+    

+        // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.

+        // This is required for maximum performance, as it allows the parser to omit initialization of 

+        // unneded/redundant values.

+        //

+        // The rules are as follows:

+        // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively

+        // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage

+        // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage

+

+        node_type m_type;                       // Type of node; always valid

+        xml_node<Ch> *m_first_node;             // Pointer to first child node, or 0 if none; always valid

+        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

+        xml_attribute<Ch> *m_first_attribute;   // Pointer to first attribute of node, or 0 if none; always valid

+        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

+        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

+        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

+

+    };

+

+    ///////////////////////////////////////////////////////////////////////////

+    // XML document

+    

+    //! This class represents root of the DOM hierarchy. 

+    //! It is also an xml_node and a memory_pool through public inheritance.

+    //! Use parse() function to build a DOM tree from a zero-terminated XML text string.

+    //! parse() function allocates memory for nodes and attributes by using functions of xml_document, 

+    //! which are inherited from memory_pool.

+    //! To access root node of the document, use the document itself, as if it was an xml_node.

+    //! \param Ch Character type to use.

+    template<class Ch = char>

+    class xml_document: public xml_node<Ch>, public memory_pool<Ch>

+    {

+    

+    public:

+

+        //! Constructs empty XML document

+        xml_document()

+            : xml_node<Ch>(node_document)

+        {

+        }

+

+        //! Parses zero-terminated XML string according to given flags.

+        //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.

+        //! The string must persist for the lifetime of the document.

+        //! In case of error, rapidxml::parse_error exception will be thrown.

+        //! <br><br>

+        //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.

+        //! Make sure that data is zero-terminated.

+        //! <br><br>

+        //! Document can be parsed into multiple times. 

+        //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.

+        //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.

+        template<int Flags>

+        void parse(Ch *text)

+        {

+            assert(text);

+            

+            // Remove current contents

+            this->remove_all_nodes();

+            this->remove_all_attributes();

+            

+            // Parse BOM, if any

+            parse_bom<Flags>(text);

+            

+            // Parse children

+            while (1)

+            {

+                // Skip whitespace before node

+                skip<whitespace_pred, Flags>(text);

+                if (*text == 0)

+                    break;

+

+                // Parse and append new child

+                if (*text == Ch('<'))

+                {

+                    ++text;     // Skip '<'

+                    if (xml_node<Ch> *node = parse_node<Flags>(text))

+                        this->append_node(node);

+                }

+                else

+                    RAPIDXML_PARSE_ERROR("expected <", text);

+            }

+

+        }

+

+        //! Clears the document by deleting all nodes and clearing the memory pool.

+        //! All nodes owned by document pool are destroyed.

+        void clear()

+        {

+            this->remove_all_nodes();

+            this->remove_all_attributes();

+            memory_pool<Ch>::clear();

+        }

+        

+    private:

+

+        ///////////////////////////////////////////////////////////////////////

+        // Internal character utility functions

+        

+        // Detect whitespace character

+        struct whitespace_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];

+            }

+        };

+

+        // Detect node name character

+        struct node_name_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];

+            }

+        };

+

+        // Detect attribute name character

+        struct attribute_name_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];

+            }

+        };

+

+        // Detect text character (PCDATA)

+        struct text_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];

+            }

+        };

+

+        // Detect text character (PCDATA) that does not require processing

+        struct text_pure_no_ws_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];

+            }

+        };

+

+        // Detect text character (PCDATA) that does not require processing

+        struct text_pure_with_ws_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];

+            }

+        };

+

+        // Detect attribute value character

+        template<Ch Quote>

+        struct attribute_value_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                if (Quote == Ch('\''))

+                    return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];

+                if (Quote == Ch('\"'))

+                    return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];

+                return 0;       // Should never be executed, to avoid warnings on Comeau

+            }

+        };

+

+        // Detect attribute value character

+        template<Ch Quote>

+        struct attribute_value_pure_pred

+        {

+            static unsigned char test(Ch ch)

+            {

+                if (Quote == Ch('\''))

+                    return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];

+                if (Quote == Ch('\"'))

+                    return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];

+                return 0;       // Should never be executed, to avoid warnings on Comeau

+            }

+        };

+

+        // Insert coded character, using UTF8 or 8-bit ASCII

+        template<int Flags>

+        static void insert_coded_character(Ch *&text, unsigned long code)

+        {

+            if (Flags & parse_no_utf8)

+            {

+                // Insert 8-bit ASCII character

+                // Todo: possibly verify that code is less than 256 and use replacement char otherwise?

+                text[0] = static_cast<unsigned char>(code);

+                text += 1;

+            }

+            else

+            {

+                // Insert UTF8 sequence

+                if (code < 0x80)    // 1 byte sequence

+                {

+	                text[0] = static_cast<unsigned char>(code);

+                    text += 1;

+                }

+                else if (code < 0x800)  // 2 byte sequence

+                {

+	                text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;

+	                text[0] = static_cast<unsigned char>(code | 0xC0);

+                    text += 2;

+                }

+	            else if (code < 0x10000)    // 3 byte sequence

+                {

+	                text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;

+	                text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;

+	                text[0] = static_cast<unsigned char>(code | 0xE0);

+                    text += 3;

+                }

+	            else if (code < 0x110000)   // 4 byte sequence

+                {

+	                text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;

+	                text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;

+	                text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;

+	                text[0] = static_cast<unsigned char>(code | 0xF0);

+                    text += 4;

+                }

+                else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode

+                {

+                    RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);

+                }

+            }

+        }

+

+        // Skip characters until predicate evaluates to true

+        template<class StopPred, int Flags>

+        static void skip(Ch *&text)

+        {

+            Ch *tmp = text;

+            while (StopPred::test(*tmp))

+                ++tmp;

+            text = tmp;

+        }

+

+        // Skip characters until predicate evaluates to true while doing the following:

+        // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)

+        // - condensing whitespace sequences to single space character

+        template<class StopPred, class StopPredPure, int Flags>

+        static Ch *skip_and_expand_character_refs(Ch *&text)

+        {

+            // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip

+            if (Flags & parse_no_entity_translation && 

+                !(Flags & parse_normalize_whitespace) &&

+                !(Flags & parse_trim_whitespace))

+            {

+                skip<StopPred, Flags>(text);

+                return text;

+            }

+            

+            // Use simple skip until first modification is detected

+            skip<StopPredPure, Flags>(text);

+

+            // Use translation skip

+            Ch *src = text;

+            Ch *dest = src;

+            while (StopPred::test(*src))

+            {

+                // If entity translation is enabled    

+                if (!(Flags & parse_no_entity_translation))

+                {

+                    // Test if replacement is needed

+                    if (src[0] == Ch('&'))

+                    {

+                        switch (src[1])

+                        {

+

+                        // &amp; &apos;

+                        case Ch('a'): 

+                            if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))

+                            {

+                                *dest = Ch('&');

+                                ++dest;

+                                src += 5;

+                                continue;

+                            }

+                            if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))

+                            {

+                                *dest = Ch('\'');

+                                ++dest;

+                                src += 6;

+                                continue;

+                            }

+                            break;

+

+                        // &quot;

+                        case Ch('q'): 

+                            if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))

+                            {

+                                *dest = Ch('"');

+                                ++dest;

+                                src += 6;

+                                continue;

+                            }

+                            break;

+

+                        // &gt;

+                        case Ch('g'): 

+                            if (src[2] == Ch('t') && src[3] == Ch(';'))

+                            {

+                                *dest = Ch('>');

+                                ++dest;

+                                src += 4;

+                                continue;

+                            }

+                            break;

+

+                        // &lt;

+                        case Ch('l'): 

+                            if (src[2] == Ch('t') && src[3] == Ch(';'))

+                            {

+                                *dest = Ch('<');

+                                ++dest;

+                                src += 4;

+                                continue;

+                            }

+                            break;

+

+                        // &#...; - assumes ASCII

+                        case Ch('#'): 

+                            if (src[2] == Ch('x'))

+                            {

+                                unsigned long code = 0;

+                                src += 3;   // Skip &#x

+                                while (1)

+                                {

+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];

+                                    if (digit == 0xFF)

+                                        break;

+                                    code = code * 16 + digit;

+                                    ++src;

+                                }

+                                insert_coded_character<Flags>(dest, code);    // Put character in output

+                            }

+                            else

+                            {

+                                unsigned long code = 0;

+                                src += 2;   // Skip &#

+                                while (1)

+                                {

+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];

+                                    if (digit == 0xFF)

+                                        break;

+                                    code = code * 10 + digit;

+                                    ++src;

+                                }

+                                insert_coded_character<Flags>(dest, code);    // Put character in output

+                            }

+                            if (*src == Ch(';'))

+                                ++src;

+                            else

+                                RAPIDXML_PARSE_ERROR("expected ;", src);

+                            continue;

+

+                        // Something else

+                        default:

+                            // Ignore, just copy '&' verbatim

+                            break;

+

+                        }

+                    }

+                }

+                

+                // If whitespace condensing is enabled

+                if (Flags & parse_normalize_whitespace)

+                {

+                    // Test if condensing is needed                 

+                    if (whitespace_pred::test(*src))

+                    {

+                        *dest = Ch(' '); ++dest;    // Put single space in dest

+                        ++src;                      // Skip first whitespace char

+                        // Skip remaining whitespace chars

+                        while (whitespace_pred::test(*src))

+                            ++src;

+                        continue;

+                    }

+                }

+

+                // No replacement, only copy character

+                *dest++ = *src++;

+

+            }

+

+            // Return new end

+            text = src;

+            return dest;

+

+        }

+

+        ///////////////////////////////////////////////////////////////////////

+        // Internal parsing functions

+        

+        // Parse BOM, if any

+        template<int Flags>

+        void parse_bom(Ch *&text)

+        {

+            // UTF-8?

+            if (static_cast<unsigned char>(text[0]) == 0xEF && 

+                static_cast<unsigned char>(text[1]) == 0xBB && 

+                static_cast<unsigned char>(text[2]) == 0xBF)

+            {

+                text += 3;      // Skup utf-8 bom

+            }

+        }

+

+        // Parse XML declaration (<?xml...)

+        template<int Flags>

+        xml_node<Ch> *parse_xml_declaration(Ch *&text)

+        {

+            // If parsing of declaration is disabled

+            if (!(Flags & parse_declaration_node))

+            {

+                // Skip until end of declaration

+                while (text[0] != Ch('?') || text[1] != Ch('>'))

+                {

+                    if (!text[0])

+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                    ++text;

+                }

+                text += 2;    // Skip '?>'

+                return 0;

+            }

+

+            // Create declaration

+            xml_node<Ch> *declaration = this->allocate_node(node_declaration);

+

+            // Skip whitespace before attributes or ?>

+            skip<whitespace_pred, Flags>(text);

+

+            // Parse declaration attributes

+            parse_node_attributes<Flags>(text, declaration);

+            

+            // Skip ?>

+            if (text[0] != Ch('?') || text[1] != Ch('>'))

+                RAPIDXML_PARSE_ERROR("expected ?>", text);

+            text += 2;

+            

+            return declaration;

+        }

+

+        // Parse XML comment (<!--...)

+        template<int Flags>

+        xml_node<Ch> *parse_comment(Ch *&text)

+        {

+            // If parsing of comments is disabled

+            if (!(Flags & parse_comment_nodes))

+            {

+                // Skip until end of comment

+                while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))

+                {

+                    if (!text[0])

+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                    ++text;

+                }

+                text += 3;     // Skip '-->'

+                return 0;      // Do not produce comment node

+            }

+

+            // Remember value start

+            Ch *value = text;

+

+            // Skip until end of comment

+            while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))

+            {

+                if (!text[0])

+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                ++text;

+            }

+

+            // Create comment node

+            xml_node<Ch> *comment = this->allocate_node(node_comment);

+            comment->value(value, text - value);

+            

+            // Place zero terminator after comment value

+            if (!(Flags & parse_no_string_terminators))

+                *text = Ch('\0');

+            

+            text += 3;     // Skip '-->'

+            return comment;

+        }

+

+        // Parse DOCTYPE

+        template<int Flags>

+        xml_node<Ch> *parse_doctype(Ch *&text)

+        {

+            // Remember value start

+            Ch *value = text;

+

+            // Skip to >

+            while (*text != Ch('>'))

+            {

+                // Determine character type

+                switch (*text)

+                {

+                

+                // If '[' encountered, scan for matching ending ']' using naive algorithm with depth

+                // This works for all W3C test files except for 2 most wicked

+                case Ch('['):

+                {

+                    ++text;     // Skip '['

+                    int depth = 1;

+                    while (depth > 0)

+                    {

+                        switch (*text)

+                        {

+                            case Ch('['): ++depth; break;

+                            case Ch(']'): --depth; break;

+                            case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                        }

+                        ++text;

+                    }

+                    break;

+                }

+                

+                // Error on end of text

+                case Ch('\0'):

+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                

+                // Other character, skip it

+                default:

+                    ++text;

+

+                }

+            }

+            

+            // If DOCTYPE nodes enabled

+            if (Flags & parse_doctype_node)

+            {

+                // Create a new doctype node

+                xml_node<Ch> *doctype = this->allocate_node(node_doctype);

+                doctype->value(value, text - value);

+                

+                // Place zero terminator after value

+                if (!(Flags & parse_no_string_terminators))

+                    *text = Ch('\0');

+

+                text += 1;      // skip '>'

+                return doctype;

+            }

+            else

+            {

+                text += 1;      // skip '>'

+                return 0;

+            }

+

+        }

+

+        // Parse PI

+        template<int Flags>

+        xml_node<Ch> *parse_pi(Ch *&text)

+        {

+            // If creation of PI nodes is enabled

+            if (Flags & parse_pi_nodes)

+            {

+                // Create pi node

+                xml_node<Ch> *pi = this->allocate_node(node_pi);

+

+                // Extract PI target name

+                Ch *name = text;

+                skip<node_name_pred, Flags>(text);

+                if (text == name)

+                    RAPIDXML_PARSE_ERROR("expected PI target", text);

+                pi->name(name, text - name);

+                

+                // Skip whitespace between pi target and pi

+                skip<whitespace_pred, Flags>(text);

+

+                // Remember start of pi

+                Ch *value = text;

+                

+                // Skip to '?>'

+                while (text[0] != Ch('?') || text[1] != Ch('>'))

+                {

+                    if (*text == Ch('\0'))

+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                    ++text;

+                }

+

+                // Set pi value (verbatim, no entity expansion or whitespace normalization)

+                pi->value(value, text - value);     

+                

+                // Place zero terminator after name and value

+                if (!(Flags & parse_no_string_terminators))

+                {

+                    pi->name()[pi->name_size()] = Ch('\0');

+                    pi->value()[pi->value_size()] = Ch('\0');

+                }

+                

+                text += 2;                          // Skip '?>'

+                return pi;

+            }

+            else

+            {

+                // Skip to '?>'

+                while (text[0] != Ch('?') || text[1] != Ch('>'))

+                {

+                    if (*text == Ch('\0'))

+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                    ++text;

+                }

+                text += 2;    // Skip '?>'

+                return 0;

+            }

+        }

+

+        // Parse and append data

+        // Return character that ends data.

+        // This is necessary because this character might have been overwritten by a terminating 0

+        template<int Flags>

+        Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)

+        {

+            // Backup to contents start if whitespace trimming is disabled

+            if (!(Flags & parse_trim_whitespace))

+                text = contents_start;     

+            

+            // Skip until end of data

+            Ch *value = text, *end;

+            if (Flags & parse_normalize_whitespace)

+                end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);   

+            else

+                end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);

+

+            // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >

+            if (Flags & parse_trim_whitespace)

+            {

+                if (Flags & parse_normalize_whitespace)

+                {

+                    // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end

+                    if (*(end - 1) == Ch(' '))

+                        --end;

+                }

+                else

+                {

+                    // Backup until non-whitespace character is found

+                    while (whitespace_pred::test(*(end - 1)))

+                        --end;

+                }

+            }

+            

+            // If characters are still left between end and value (this test is only necessary if normalization is enabled)

+            // Create new data node

+            if (!(Flags & parse_no_data_nodes))

+            {

+                xml_node<Ch> *data = this->allocate_node(node_data);

+                data->value(value, end - value);

+                node->append_node(data);

+            }

+

+            // Add data to parent node if no data exists yet

+            if (!(Flags & parse_no_element_values)) 

+                if (*node->value() == Ch('\0'))

+                    node->value(value, end - value);

+

+            // Place zero terminator after value

+            if (!(Flags & parse_no_string_terminators))

+            {

+                Ch ch = *text;

+                *end = Ch('\0');

+                return ch;      // Return character that ends data; this is required because zero terminator overwritten it

+            }

+

+            // Return character that ends data

+            return *text;

+        }

+

+        // Parse CDATA

+        template<int Flags>

+        xml_node<Ch> *parse_cdata(Ch *&text)

+        {

+            // If CDATA is disabled

+            if (Flags & parse_no_data_nodes)

+            {

+                // Skip until end of cdata

+                while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))

+                {

+                    if (!text[0])

+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                    ++text;

+                }

+                text += 3;      // Skip ]]>

+                return 0;       // Do not produce CDATA node

+            }

+

+            // Skip until end of cdata

+            Ch *value = text;

+            while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))

+            {

+                if (!text[0])

+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                ++text;

+            }

+

+            // Create new cdata node

+            xml_node<Ch> *cdata = this->allocate_node(node_cdata);

+            cdata->value(value, text - value);

+

+            // Place zero terminator after value

+            if (!(Flags & parse_no_string_terminators))

+                *text = Ch('\0');

+

+            text += 3;      // Skip ]]>

+            return cdata;

+        }

+        

+        // Parse element node

+        template<int Flags>

+        xml_node<Ch> *parse_element(Ch *&text)

+        {

+            // Create element node

+            xml_node<Ch> *element = this->allocate_node(node_element);

+

+            // Extract element name

+            Ch *name = text;

+            skip<node_name_pred, Flags>(text);

+            if (text == name)

+                RAPIDXML_PARSE_ERROR("expected element name", text);

+            element->name(name, text - name);

+            

+            // Skip whitespace between element name and attributes or >

+            skip<whitespace_pred, Flags>(text);

+

+            // Parse attributes, if any

+            parse_node_attributes<Flags>(text, element);

+

+            // Determine ending type

+            if (*text == Ch('>'))

+            {

+                ++text;

+                parse_node_contents<Flags>(text, element);

+            }

+            else if (*text == Ch('/'))

+            {

+                ++text;

+                if (*text != Ch('>'))

+                    RAPIDXML_PARSE_ERROR("expected >", text);

+                ++text;

+            }

+            else

+                RAPIDXML_PARSE_ERROR("expected >", text);

+

+            // Place zero terminator after name

+            if (!(Flags & parse_no_string_terminators))

+                element->name()[element->name_size()] = Ch('\0');

+

+            // Return parsed element

+            return element;

+        }

+

+        // Determine node type, and parse it

+        template<int Flags>

+        xml_node<Ch> *parse_node(Ch *&text)

+        {

+            // Parse proper node type

+            switch (text[0])

+            {

+

+            // <...

+            default: 

+                // Parse and append element node

+                return parse_element<Flags>(text);

+

+            // <?...

+            case Ch('?'): 

+                ++text;     // Skip ?

+                if ((text[0] == Ch('x') || text[0] == Ch('X')) &&

+                    (text[1] == Ch('m') || text[1] == Ch('M')) && 

+                    (text[2] == Ch('l') || text[2] == Ch('L')) &&

+                    whitespace_pred::test(text[3]))

+                {

+                    // '<?xml ' - xml declaration

+                    text += 4;      // Skip 'xml '

+                    return parse_xml_declaration<Flags>(text);

+                }

+                else

+                {

+                    // Parse PI

+                    return parse_pi<Flags>(text);

+                }

+            

+            // <!...

+            case Ch('!'): 

+

+                // Parse proper subset of <! node

+                switch (text[1])    

+                {

+                

+                // <!-

+                case Ch('-'):

+                    if (text[2] == Ch('-'))

+                    {

+                        // '<!--' - xml comment

+                        text += 3;     // Skip '!--'

+                        return parse_comment<Flags>(text);

+                    }

+                    break;

+

+                // <![

+                case Ch('['):

+                    if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') && 

+                        text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))

+                    {

+                        // '<![CDATA[' - cdata

+                        text += 8;     // Skip '![CDATA['

+                        return parse_cdata<Flags>(text);

+                    }

+                    break;

+

+                // <!D

+                case Ch('D'):

+                    if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') && 

+                        text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') && 

+                        whitespace_pred::test(text[8]))

+                    {

+                        // '<!DOCTYPE ' - doctype

+                        text += 9;      // skip '!DOCTYPE '

+                        return parse_doctype<Flags>(text);

+                    }

+

+                }   // switch

+

+                // Attempt to skip other, unrecognized node types starting with <!

+                ++text;     // Skip !

+                while (*text != Ch('>'))

+                {

+                    if (*text == 0)

+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+                    ++text;

+                }

+                ++text;     // Skip '>'

+                return 0;   // No node recognized

+

+            }

+        }

+

+        // Parse contents of the node - children, data etc.

+        template<int Flags>

+        void parse_node_contents(Ch *&text, xml_node<Ch> *node)

+        {

+            // For all children and text

+            while (1)

+            {

+                // Skip whitespace between > and node contents

+                Ch *contents_start = text;      // Store start of node contents before whitespace is skipped

+                skip<whitespace_pred, Flags>(text);

+                Ch next_char = *text;

+

+            // After data nodes, instead of continuing the loop, control jumps here.

+            // This is because zero termination inside parse_and_append_data() function

+            // would wreak havoc with the above code.

+            // Also, skipping whitespace after data nodes is unnecessary.

+            after_data_node:    

+                

+                // Determine what comes next: node closing, child node, data node, or 0?

+                switch (next_char)

+                {

+                

+                // Node closing or child node

+                case Ch('<'):

+                    if (text[1] == Ch('/'))

+                    {

+                        // Node closing

+                        text += 2;      // Skip '</'

+                        if (Flags & parse_validate_closing_tags)

+                        {

+                            // Skip and validate closing tag name

+                            Ch *closing_name = text;

+                            skip<node_name_pred, Flags>(text);

+                            if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))

+                                RAPIDXML_PARSE_ERROR("invalid closing tag name", text);

+                        }

+                        else

+                        {

+                            // No validation, just skip name

+                            skip<node_name_pred, Flags>(text);

+                        }

+                        // Skip remaining whitespace after node name

+                        skip<whitespace_pred, Flags>(text);

+                        if (*text != Ch('>'))

+                            RAPIDXML_PARSE_ERROR("expected >", text);

+                        ++text;     // Skip '>'

+                        return;     // Node closed, finished parsing contents

+                    }

+                    else

+                    {

+                        // Child node

+                        ++text;     // Skip '<'

+                        if (xml_node<Ch> *child = parse_node<Flags>(text))

+                            node->append_node(child);

+                    }

+                    break;

+

+                // End of data - error

+                case Ch('\0'):

+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);

+

+                // Data node

+                default:

+                    next_char = parse_and_append_data<Flags>(node, text, contents_start);

+                    goto after_data_node;   // Bypass regular processing after data nodes

+

+                }

+            }

+        }

+        

+        // Parse XML attributes of the node

+        template<int Flags>

+        void parse_node_attributes(Ch *&text, xml_node<Ch> *node)

+        {

+            // For all attributes 

+            while (attribute_name_pred::test(*text))

+            {

+                // Extract attribute name

+                Ch *name = text;

+                ++text;     // Skip first character of attribute name

+                skip<attribute_name_pred, Flags>(text);

+                if (text == name)

+                    RAPIDXML_PARSE_ERROR("expected attribute name", name);

+

+                // Create new attribute

+                xml_attribute<Ch> *attribute = this->allocate_attribute();

+                attribute->name(name, text - name);

+                node->append_attribute(attribute);

+

+                // Skip whitespace after attribute name

+                skip<whitespace_pred, Flags>(text);

+

+                // Skip =

+                if (*text != Ch('='))

+                    RAPIDXML_PARSE_ERROR("expected =", text);

+                ++text;

+

+                // Add terminating zero after name

+                if (!(Flags & parse_no_string_terminators))

+                    attribute->name()[attribute->name_size()] = 0;

+

+                // Skip whitespace after =

+                skip<whitespace_pred, Flags>(text);

+

+                // Skip quote and remember if it was ' or "

+                Ch quote = *text;

+                if (quote != Ch('\'') && quote != Ch('"'))

+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);

+                ++text;

+

+                // Extract attribute value and expand char refs in it

+                Ch *value = text, *end;

+                const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes

+                if (quote == Ch('\''))

+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);

+                else

+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);

+                

+                // Set attribute value

+                attribute->value(value, end - value);

+                

+                // Make sure that end quote is present

+                if (*text != quote)

+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);

+                ++text;     // Skip quote

+

+                // Add terminating zero after value

+                if (!(Flags & parse_no_string_terminators))

+                    attribute->value()[attribute->value_size()] = 0;

+

+                // Skip whitespace after attribute value

+                skip<whitespace_pred, Flags>(text);

+            }

+        }

+

+    };

+

+    //! \cond internal

+    namespace internal

+    {

+

+        // Whitespace (space \n \r \t)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1

+             1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E

+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F

+        };

+

+        // Node name (anything but space \n \r \t / > ? \0)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_node_name[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Text (i.e. PCDATA) (anything but < \0)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_text[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled 

+        // (anything but < \0 &)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled

+        // (anything but < \0 & space \n \r \t)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Attribute name (anything but space \n \r \t / < > = ? ! \0)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Attribute data with single quote (anything but ' \0)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Attribute data with single quote that does not require processing (anything but ' \0 &)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Attribute data with double quote (anything but " \0)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Attribute data with double quote that does not require processing (anything but " \0 &)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1

+             1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E

+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F

+        };

+

+        // Digits (dec and hex, 255 denotes end of numeric character reference)

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_digits[256] = 

+        {

+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2

+             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,  // 3

+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5

+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E

+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F

+        };

+    

+        // Upper case conversion

+        template<int Dummy>

+        const unsigned char lookup_tables<Dummy>::lookup_upcase[256] = 

+        {

+          // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F

+           0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0

+           16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1

+           32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2

+           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3

+           64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4

+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5

+           96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6

+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127,  // 7

+           128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,  // 8

+           144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,  // 9

+           160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,  // A

+           176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,  // B

+           192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,  // C

+           208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,  // D

+           224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,  // E

+           240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255   // F

+        };

+    }

+    //! \endcond

+

+}

+

+// Undefine internal macros

+#undef RAPIDXML_PARSE_ERROR

+

+// On MSVC, restore warnings state

+#ifdef _MSC_VER

+    #pragma warning(pop)

+#endif

+

+#endif