[PPM] Modify Protocol Plugin Manager for Android platform.
authorYounghyun Joo <yh_.joo@samsung.com>
Fri, 20 Mar 2015 04:55:39 +0000 (13:55 +0900)
committerUze Choi <uzchoi@samsung.com>
Fri, 20 Mar 2015 05:12:10 +0000 (05:12 +0000)
1. Modify Protocol Plugin Manager for Android platform.
2. Change the rapidxml directory from "service/protocol-plugin/lib" to "extlibs"

Change-Id: I045269f3522e9e69b502e1e4706331ff4f991647
Signed-off-by: Younghyun Joo <yh_.joo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/497
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
24 files changed:
extlibs/rapidxml/rapidxml.hpp [new file with mode: 0644]
extlibs/rapidxml/rapidxml_iterators.hpp [new file with mode: 0644]
extlibs/rapidxml/rapidxml_print.hpp [moved from service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp with 76% similarity]
extlibs/rapidxml/rapidxml_utils.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml.hpp [deleted file]
service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp [deleted file]
service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp [deleted file]
service/protocol-plugin/plugin-manager/SConscript
service/protocol-plugin/plugin-manager/build/linux/Makefile
service/protocol-plugin/plugin-manager/src/Config.cpp
service/protocol-plugin/plugin-manager/src/Config.h
service/protocol-plugin/plugin-manager/src/CpluffAdapter.cpp
service/protocol-plugin/plugin-manager/src/CpluffAdapter.h
service/protocol-plugin/plugin-manager/src/FelixAdapter.cpp
service/protocol-plugin/plugin-manager/src/FelixAdapter.h
service/protocol-plugin/plugin-manager/src/Plugin.cpp
service/protocol-plugin/plugin-manager/src/Plugin.h
service/protocol-plugin/plugin-manager/src/PluginManager.cpp
service/protocol-plugin/plugin-manager/src/PluginManager.h
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.cpp
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.h
service/protocol-plugin/plugins/SConscript
service/protocol-plugin/sample-app/linux/SConscript
service/protocol-plugin/sample-app/linux/mqtt/Makefile

diff --git a/extlibs/rapidxml/rapidxml.hpp b/extlibs/rapidxml/rapidxml.hpp
new file mode 100644 (file)
index 0000000..0845cfb
--- /dev/null
@@ -0,0 +1,2638 @@
+#ifndef RAPIDXML_HPP_INCLUDED
+#define RAPIDXML_HPP_INCLUDED
+
+// 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);
+                                        default: break;
+                                    }
+                                    ++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);
+                                }
+                                break;
+
+                            default:
+                                break;
+
+                        }   // 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
diff --git a/extlibs/rapidxml/rapidxml_iterators.hpp b/extlibs/rapidxml/rapidxml_iterators.hpp
new file mode 100644 (file)
index 0000000..2960a39
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
+#define RAPIDXML_ITERATORS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
+
+#include "rapidxml.hpp"
+
+namespace rapidxml
+{
+
+    //! Iterator of child nodes of xml_node
+    template<class Ch>
+    class node_iterator
+    {
+
+        public:
+
+            typedef typename xml_node<Ch> value_type;
+            typedef typename xml_node<Ch> &reference;
+            typedef typename xml_node<Ch> *pointer;
+            typedef std::ptrdiff_t difference_type;
+            typedef std::bidirectional_iterator_tag iterator_category;
+
+            node_iterator()
+                : m_node(0)
+            {
+            }
+
+            node_iterator(xml_node<Ch> *node)
+                : m_node(node->first_node())
+            {
+            }
+
+            reference operator *() const
+            {
+                assert(m_node);
+                return *m_node;
+            }
+
+            pointer operator->() const
+            {
+                assert(m_node);
+                return m_node;
+            }
+
+            node_iterator &operator++()
+            {
+                assert(m_node);
+                m_node = m_node->next_sibling();
+                return *this;
+            }
+
+            node_iterator operator++(int)
+            {
+                node_iterator tmp = *this;
+                ++this;
+                return tmp;
+            }
+
+            node_iterator &operator--()
+            {
+                assert(m_node && m_node->previous_sibling());
+                m_node = m_node->previous_sibling();
+                return *this;
+            }
+
+            node_iterator operator--(int)
+            {
+                node_iterator tmp = *this;
+                ++this;
+                return tmp;
+            }
+
+            bool operator ==(const node_iterator<Ch> &rhs)
+            {
+                return m_node == rhs.m_node;
+            }
+
+            bool operator !=(const node_iterator<Ch> &rhs)
+            {
+                return m_node != rhs.m_node;
+            }
+
+        private:
+
+            xml_node<Ch> *m_node;
+
+    };
+
+    //! Iterator of child attributes of xml_node
+    template<class Ch>
+    class attribute_iterator
+    {
+
+        public:
+
+            typedef typename xml_attribute<Ch> value_type;
+            typedef typename xml_attribute<Ch> &reference;
+            typedef typename xml_attribute<Ch> *pointer;
+            typedef std::ptrdiff_t difference_type;
+            typedef std::bidirectional_iterator_tag iterator_category;
+
+            attribute_iterator()
+                : m_attribute(0)
+            {
+            }
+
+            attribute_iterator(xml_node<Ch> *node)
+                : m_attribute(node->first_attribute())
+            {
+            }
+
+            reference operator *() const
+            {
+                assert(m_attribute);
+                return *m_attribute;
+            }
+
+            pointer operator->() const
+            {
+                assert(m_attribute);
+                return m_attribute;
+            }
+
+            attribute_iterator &operator++()
+            {
+                assert(m_attribute);
+                m_attribute = m_attribute->next_attribute();
+                return *this;
+            }
+
+            attribute_iterator operator++(int)
+            {
+                attribute_iterator tmp = *this;
+                ++this;
+                return tmp;
+            }
+
+            attribute_iterator &operator--()
+            {
+                assert(m_attribute && m_attribute->previous_attribute());
+                m_attribute = m_attribute->previous_attribute();
+                return *this;
+            }
+
+            attribute_iterator operator--(int)
+            {
+                attribute_iterator tmp = *this;
+                ++this;
+                return tmp;
+            }
+
+            bool operator ==(const attribute_iterator<Ch> &rhs)
+            {
+                return m_attribute == rhs.m_attribute;
+            }
+
+            bool operator !=(const attribute_iterator<Ch> &rhs)
+            {
+                return m_attribute != rhs.m_attribute;
+            }
+
+        private:
+
+            xml_attribute<Ch> *m_attribute;
+
+    };
+
+}
+
+#endif
@@ -10,8 +10,8 @@
 
 // Only include streams if not disabled
 #ifndef RAPIDXML_NO_STREAMS
-    #include <ostream>
-    #include <iterator>
+#include <ostream>
+#include <iterator>
 #endif
 
 namespace rapidxml
@@ -20,7 +20,8 @@ namespace rapidxml
     ///////////////////////////////////////////////////////////////////////
     // Printing flags
 
-    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
+    const int print_no_indenting =
+        0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
 
     ///////////////////////////////////////////////////////////////////////
     // Internal
@@ -28,10 +29,10 @@ namespace rapidxml
     //! \cond internal
     namespace internal
     {
-        
+
         ///////////////////////////////////////////////////////////////////////////
         // Internal character operations
-    
+
         // Copy characters from given range to given output iterator
         template<class OutIt, class Ch>
         inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
@@ -40,7 +41,7 @@ namespace rapidxml
                 *out++ = *begin++;
             return out;
         }
-        
+
         // Copy characters from given range to given output iterator and expand
         // characters into references (&lt; &gt; &apos; &quot; &amp;)
         template<class OutIt, class Ch>
@@ -56,23 +57,25 @@ namespace rapidxml
                 {
                     switch (*begin)
                     {
-                    case Ch('<'):
-                        *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
-                        break;
-                    case Ch('>'): 
-                        *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
-                        break;
-                    case Ch('\''): 
-                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
-                        break;
-                    case Ch('"'): 
-                        *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
-                        break;
-                    case Ch('&'): 
-                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
-                        break;
-                    default:
-                        *out++ = *begin;    // No expansion, copy character
+                        case Ch('<'):
+                            *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
+                            break;
+                        case Ch('>'):
+                            *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
+                            break;
+                        case Ch('\''):
+                            *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s');
+                            *out++ = Ch(';');
+                            break;
+                        case Ch('"'):
+                            *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t');
+                            *out++ = Ch(';');
+                            break;
+                        case Ch('&'):
+                            *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
+                            break;
+                        default:
+                            *out++ = *begin;    // No expansion, copy character
                     }
                 }
                 ++begin;    // Step to next character
@@ -102,7 +105,7 @@ namespace rapidxml
         template<class OutIt, class Ch>
         inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
 
-        // Print children of the node                               
+        // Print children of the node
         template<class OutIt, class Ch>
         inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
         {
@@ -115,7 +118,8 @@ namespace rapidxml
         template<class OutIt, class Ch>
         inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
         {
-            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
+            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute;
+                 attribute = attribute->next_attribute())
             {
                 if (attribute->name() && attribute->value())
                 {
@@ -127,13 +131,15 @@ namespace rapidxml
                     if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
                     {
                         *out = Ch('\''), ++out;
-                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(),
+                                                    Ch('"'), out);
                         *out = Ch('\''), ++out;
                     }
                     else
                     {
                         *out = Ch('"'), ++out;
-                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(),
+                                                    Ch('\''), out);
                         *out = Ch('"'), ++out;
                     }
                 }
@@ -187,7 +193,7 @@ namespace rapidxml
             *out = Ch('<'), ++out;
             out = copy_chars(node->name(), node->name() + node->name_size(), out);
             out = print_attributes(out, node, flags);
-            
+
             // If node is childless
             if (node->value_size() == 0 && !node->first_node())
             {
@@ -246,11 +252,11 @@ namespace rapidxml
 
             // Print attributes
             out = print_attributes(out, node, flags);
-            
+
             // Print declaration end
             *out = Ch('?'), ++out;
             *out = Ch('>'), ++out;
-            
+
             return out;
         }
 
@@ -311,69 +317,69 @@ namespace rapidxml
             return out;
         }
         ///////////////////////////////////////////////////////////////////////////
-                // Internal printing operations
+        // Internal printing operations
 
-                // Print node
-                template<class OutIt, class Ch>
-                inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
-                {
-                    // Print proper node type
-                    switch (node->type())
-                    {
+        // Print node
+        template<class OutIt, class Ch>
+        inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            // Print proper node type
+            switch (node->type())
+            {
 
-                    // Document
-                    case node_document:
-                        out = print_children(out, node, flags, indent);
-                        break;
-
-                    // Element
-                    case node_element:
-                        out = print_element_node(out, node, flags, indent);
-                        break;
-
-                    // Data
-                    case node_data:
-                        out = print_data_node(out, node, flags, indent);
-                        break;
-
-                    // CDATA
-                    case node_cdata:
-                        out = print_cdata_node(out, node, flags, indent);
-                        break;
-
-                    // Declaration
-                    case node_declaration:
-                        out = print_declaration_node(out, node, flags, indent);
-                        break;
-
-                    // Comment
-                    case node_comment:
-                        out = print_comment_node(out, node, flags, indent);
-                        break;
-
-                    // Doctype
-                    case node_doctype:
-                        out = print_doctype_node(out, node, flags, indent);
-                        break;
-
-                    // Pi
-                    case node_pi:
-                        out = print_pi_node(out, node, flags, indent);
-                        break;
-
-                        // Unknown
-                    default:
-                        assert(0);
-                        break;
-                    }
+                // Document
+                case node_document:
+                    out = print_children(out, node, flags, indent);
+                    break;
+
+                // Element
+                case node_element:
+                    out = print_element_node(out, node, flags, indent);
+                    break;
+
+                // Data
+                case node_data:
+                    out = print_data_node(out, node, flags, indent);
+                    break;
+
+                // CDATA
+                case node_cdata:
+                    out = print_cdata_node(out, node, flags, indent);
+                    break;
+
+                // Declaration
+                case node_declaration:
+                    out = print_declaration_node(out, node, flags, indent);
+                    break;
+
+                // Comment
+                case node_comment:
+                    out = print_comment_node(out, node, flags, indent);
+                    break;
+
+                // Doctype
+                case node_doctype:
+                    out = print_doctype_node(out, node, flags, indent);
+                    break;
+
+                // Pi
+                case node_pi:
+                    out = print_pi_node(out, node, flags, indent);
+                    break;
+
+                // Unknown
+                default:
+                    assert(0);
+                    break;
+            }
 
-                    // If indenting not disabled, add line break after node
-                    if (!(flags & print_no_indenting))
-                        *out = Ch('\n'), ++out;
+            // If indenting not disabled, add line break after node
+            if (!(flags & print_no_indenting))
+                *out = Ch('\n'), ++out;
 
-                    // Return modified iterator
-                    return out;
-                }
+            // Return modified iterator
+            return out;
+        }
     }
     //! \endcond
 
@@ -385,7 +391,7 @@ namespace rapidxml
     //! \param node Node to be printed. Pass xml_document to print entire document.
     //! \param flags Flags controlling how XML is printed.
     //! \return Output iterator pointing to position immediately after last character of printed text.
-    template<class OutIt, class Ch> 
+    template<class OutIt, class Ch>
     inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
     {
         return internal::print_node(out, &node, flags, 0);
@@ -398,8 +404,9 @@ namespace rapidxml
     //! \param node Node to be printed. Pass xml_document to print entire document.
     //! \param flags Flags controlling how XML is printed.
     //! \return Output stream.
-    template<class Ch> 
-    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
+    template<class Ch>
+    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node,
+                                         int flags = 0)
     {
         print(std::ostream_iterator<Ch>(out), node, flags);
         return out;
@@ -409,7 +416,7 @@ namespace rapidxml
     //! \param out Output stream to print to.
     //! \param node Node to be printed.
     //! \return Output stream.
-    template<class Ch> 
+    template<class Ch>
     inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
     {
         return print(out, node);
diff --git a/extlibs/rapidxml/rapidxml_utils.hpp b/extlibs/rapidxml/rapidxml_utils.hpp
new file mode 100644 (file)
index 0000000..30e7369
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef RAPIDXML_UTILS_HPP_INCLUDED
+#define RAPIDXML_UTILS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
+//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
+
+#include "rapidxml.hpp"
+#include <vector>
+#include <string>
+#include <fstream>
+#include <stdexcept>
+
+namespace rapidxml
+{
+
+    //! Represents data loaded from a file
+    template<class Ch = char>
+    class file
+    {
+
+        public:
+
+            //! Loads file into the memory. Data will be automatically destroyed by the destructor.
+            //! \param filename Filename to load.
+            file(const char *filename)
+            {
+                using namespace std;
+
+                // Open stream
+                basic_ifstream<Ch> stream(filename, ios::binary);
+                if (!stream)
+                    throw runtime_error(string("cannot open file ") + filename);
+                stream.unsetf(ios::skipws);
+
+                // Determine stream size
+                stream.seekg(0, ios::end);
+                size_t size = stream.tellg();
+                stream.seekg(0);
+
+                // Load data and add terminating 0
+                m_data.resize(size + 1);
+                stream.read(&m_data.front(), static_cast<streamsize>(size));
+                m_data[size] = 0;
+            }
+
+            //! Loads file into the memory. Data will be automatically destroyed by the destructor
+            //! \param stream Stream to load from
+            file(std::basic_istream<Ch> &stream)
+            {
+                using namespace std;
+
+                // Load data and add terminating 0
+                stream.unsetf(ios::skipws);
+                m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
+                if (stream.fail() || stream.bad())
+                    throw runtime_error("error reading stream");
+                m_data.push_back(0);
+            }
+
+            //! Gets file data.
+            //! \return Pointer to data of file.
+            Ch *data()
+            {
+                return &m_data.front();
+            }
+
+            //! Gets file data.
+            //! \return Pointer to data of file.
+            const Ch *data() const
+            {
+                return &m_data.front();
+            }
+
+            //! Gets file data size.
+            //! \return Size of file data, in characters.
+            std::size_t size() const
+            {
+                return m_data.size();
+            }
+
+        private:
+
+            std::vector<Ch> m_data;   // File data
+
+    };
+
+    //! Counts children of node. Time complexity is O(n).
+    //! \return Number of children of node
+    template<class Ch>
+    inline std::size_t count_children(xml_node<Ch> *node)
+    {
+        xml_node<Ch> *child = node->first_node();
+        std::size_t count = 0;
+        while (child)
+        {
+            ++count;
+            child = child->next_sibling();
+        }
+        return count;
+    }
+
+    //! Counts attributes of node. Time complexity is O(n).
+    //! \return Number of attributes of node
+    template<class Ch>
+    inline std::size_t count_attributes(xml_node<Ch> *node)
+    {
+        xml_attribute<Ch> *attr = node->first_attribute();
+        std::size_t count = 0;
+        while (attr)
+        {
+            ++count;
+            attr = attr->next_attribute();
+        }
+        return count;
+    }
+
+}
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml.hpp
deleted file mode 100644 (file)
index 9ddf195..0000000
+++ /dev/null
@@ -1,2601 +0,0 @@
-#ifndef RAPIDXML_HPP_INCLUDED
-#define RAPIDXML_HPP_INCLUDED
-
-// 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);
-                                                       default: break;
-                        }
-                        ++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);
-                    }
-                                       break;
-                               
-                               default:
-                                       break;
-
-                }   // 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
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp
deleted file mode 100644 (file)
index 52ebc29..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
-#define RAPIDXML_ITERATORS_HPP_INCLUDED
-
-// Copyright (C) 2006, 2009 Marcin Kalicinski
-// Version 1.13
-// Revision $DateTime: 2009/05/13 01:46:17 $
-//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
-
-#include "rapidxml.hpp"
-
-namespace rapidxml
-{
-
-    //! Iterator of child nodes of xml_node
-    template<class Ch>
-    class node_iterator
-    {
-    
-    public:
-
-        typedef typename xml_node<Ch> value_type;
-        typedef typename xml_node<Ch> &reference;
-        typedef typename xml_node<Ch> *pointer;
-        typedef std::ptrdiff_t difference_type;
-        typedef std::bidirectional_iterator_tag iterator_category;
-        
-        node_iterator()
-            : m_node(0)
-        {
-        }
-
-        node_iterator(xml_node<Ch> *node)
-            : m_node(node->first_node())
-        {
-        }
-        
-        reference operator *() const
-        {
-            assert(m_node);
-            return *m_node;
-        }
-
-        pointer operator->() const
-        {
-            assert(m_node);
-            return m_node;
-        }
-
-        node_iterator& operator++()
-        {
-            assert(m_node);
-            m_node = m_node->next_sibling();
-            return *this;
-        }
-
-        node_iterator operator++(int)
-        {
-            node_iterator tmp = *this;
-            ++this;
-            return tmp;
-        }
-
-        node_iterator& operator--()
-        {
-            assert(m_node && m_node->previous_sibling());
-            m_node = m_node->previous_sibling();
-            return *this;
-        }
-
-        node_iterator operator--(int)
-        {
-            node_iterator tmp = *this;
-            ++this;
-            return tmp;
-        }
-
-        bool operator ==(const node_iterator<Ch> &rhs)
-        {
-            return m_node == rhs.m_node;
-        }
-
-        bool operator !=(const node_iterator<Ch> &rhs)
-        {
-            return m_node != rhs.m_node;
-        }
-
-    private:
-
-        xml_node<Ch> *m_node;
-
-    };
-
-    //! Iterator of child attributes of xml_node
-    template<class Ch>
-    class attribute_iterator
-    {
-    
-    public:
-
-        typedef typename xml_attribute<Ch> value_type;
-        typedef typename xml_attribute<Ch> &reference;
-        typedef typename xml_attribute<Ch> *pointer;
-        typedef std::ptrdiff_t difference_type;
-        typedef std::bidirectional_iterator_tag iterator_category;
-        
-        attribute_iterator()
-            : m_attribute(0)
-        {
-        }
-
-        attribute_iterator(xml_node<Ch> *node)
-            : m_attribute(node->first_attribute())
-        {
-        }
-        
-        reference operator *() const
-        {
-            assert(m_attribute);
-            return *m_attribute;
-        }
-
-        pointer operator->() const
-        {
-            assert(m_attribute);
-            return m_attribute;
-        }
-
-        attribute_iterator& operator++()
-        {
-            assert(m_attribute);
-            m_attribute = m_attribute->next_attribute();
-            return *this;
-        }
-
-        attribute_iterator operator++(int)
-        {
-            attribute_iterator tmp = *this;
-            ++this;
-            return tmp;
-        }
-
-        attribute_iterator& operator--()
-        {
-            assert(m_attribute && m_attribute->previous_attribute());
-            m_attribute = m_attribute->previous_attribute();
-            return *this;
-        }
-
-        attribute_iterator operator--(int)
-        {
-            attribute_iterator tmp = *this;
-            ++this;
-            return tmp;
-        }
-
-        bool operator ==(const attribute_iterator<Ch> &rhs)
-        {
-            return m_attribute == rhs.m_attribute;
-        }
-
-        bool operator !=(const attribute_iterator<Ch> &rhs)
-        {
-            return m_attribute != rhs.m_attribute;
-        }
-
-    private:
-
-        xml_attribute<Ch> *m_attribute;
-
-    };
-
-}
-
-#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp
deleted file mode 100644 (file)
index 37c2953..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef RAPIDXML_UTILS_HPP_INCLUDED
-#define RAPIDXML_UTILS_HPP_INCLUDED
-
-// Copyright (C) 2006, 2009 Marcin Kalicinski
-// Version 1.13
-// Revision $DateTime: 2009/05/13 01:46:17 $
-//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
-//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
-
-#include "rapidxml.hpp"
-#include <vector>
-#include <string>
-#include <fstream>
-#include <stdexcept>
-
-namespace rapidxml
-{
-
-    //! Represents data loaded from a file
-    template<class Ch = char>
-    class file
-    {
-        
-    public:
-        
-        //! Loads file into the memory. Data will be automatically destroyed by the destructor.
-        //! \param filename Filename to load.
-        file(const char *filename)
-        {
-            using namespace std;
-
-            // Open stream
-            basic_ifstream<Ch> stream(filename, ios::binary);
-            if (!stream)
-                throw runtime_error(string("cannot open file ") + filename);
-            stream.unsetf(ios::skipws);
-            
-            // Determine stream size
-            stream.seekg(0, ios::end);
-            size_t size = stream.tellg();
-            stream.seekg(0);   
-            
-            // Load data and add terminating 0
-            m_data.resize(size + 1);
-            stream.read(&m_data.front(), static_cast<streamsize>(size));
-            m_data[size] = 0;
-        }
-
-        //! Loads file into the memory. Data will be automatically destroyed by the destructor
-        //! \param stream Stream to load from
-        file(std::basic_istream<Ch> &stream)
-        {
-            using namespace std;
-
-            // Load data and add terminating 0
-            stream.unsetf(ios::skipws);
-            m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
-            if (stream.fail() || stream.bad())
-                throw runtime_error("error reading stream");
-            m_data.push_back(0);
-        }
-        
-        //! Gets file data.
-        //! \return Pointer to data of file.
-        Ch *data()
-        {
-            return &m_data.front();
-        }
-
-        //! Gets file data.
-        //! \return Pointer to data of file.
-        const Ch *data() const
-        {
-            return &m_data.front();
-        }
-
-        //! Gets file data size.
-        //! \return Size of file data, in characters.
-        std::size_t size() const
-        {
-            return m_data.size();
-        }
-
-    private:
-
-        std::vector<Ch> m_data;   // File data
-
-    };
-
-    //! Counts children of node. Time complexity is O(n).
-    //! \return Number of children of node
-    template<class Ch>
-    inline std::size_t count_children(xml_node<Ch> *node)
-    {
-        xml_node<Ch> *child = node->first_node();
-        std::size_t count = 0;
-        while (child)
-        {
-            ++count;
-            child = child->next_sibling();
-        }
-        return count;
-    }
-
-    //! Counts attributes of node. Time complexity is O(n).
-    //! \return Number of attributes of node
-    template<class Ch>
-    inline std::size_t count_attributes(xml_node<Ch> *node)
-    {
-        xml_attribute<Ch> *attr = node->first_attribute();
-        std::size_t count = 0;
-        while (attr)
-        {
-            ++count;
-            attr = attr->next_attribute();
-        }
-        return count;
-    }
-
-}
-
-#endif
index 5f074fa..17bc795 100644 (file)
@@ -16,7 +16,7 @@ target_os = env.get('TARGET_OS')
 plugin_manager_env.AppendUnique(CPPPATH = [
                '../lib/cpluff/libcpluff',
                'src',
-               '../lib/rapidxml'
+               env.get('SRC_DIR')+'/extlibs/rapidxml'
                ])
 
 if target_os not in ['windows', 'winrt']:
index 453451f..520550f 100644 (file)
@@ -7,7 +7,7 @@ CPLUFF_DIR = $(LIB)/cpluff/libcpluff
 SRC = ../../src/
 
 CXX_INC    = -I. -I$(CPLUFF_DIR)
-CXX_INC += -I$(LIB)/rapidxml 
+CXX_INC += -I../../../../../extlibs/rapidxml 
 
 LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread 
 CXX_LIBS = $(CPLUFF_DIR)/.libs/libcpluff.a 
index 6f4bba8..48898ef 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file Config.cpp
+
+/// @brief
+
 
 #include "Config.h"
 
@@ -34,7 +34,7 @@ Config *Config::s_configinstance = NULL;
 
 Config::Config()
 {
-    if (loadConfigFile("/storage/emulated/0/Download/pluginmanager.xml") != PM_S_OK)
+    if (loadConfigFile("./pluginmanager.xml") != PM_S_OK)
     {
         fprintf(stderr, "PM Configuration file is not exist current Folder.\n" );
         exit(EXIT_FAILURE);
@@ -68,9 +68,6 @@ PMRESULT Config::loadConfigFile(const std::string configfilepath)
     xml_node<> *pluginInfo = root_node->first_node("pluginInfo");
 
     getXmlData(pluginInfo, "pluginPath");
-    getXmlData(pluginInfo, "maxMEM");
-    getXmlData(pluginInfo, "version");
-    getXmlData(pluginInfo, "name");
 
     return PM_S_OK;
 }
@@ -112,10 +109,11 @@ void Config::setValue(const std::string key, const std::string value)
     m_configurationMap.insert( std::pair<std::string, std::string>(key, value));
 }
 
-std::string  Config::getValue(const std::string key)
+std::string Config::getValue(const std::string key)
 {
     std::map<std::string, std::string>::iterator m_iterator;
 
+    // Find the value for key
     m_iterator = m_configurationMap.find(key.c_str());
 
     if (m_iterator != m_configurationMap.end())
@@ -128,10 +126,11 @@ std::string  Config::getValue(const std::string key)
     }
 }
 
-std::string  Config::getVersion()
+std::string Config::getVersion()
 {
     std::map<std::string, std::string>::iterator m_iterator;
 
+    // Find the value for key - version
     m_iterator = m_configurationMap.find("version");
 
     if (m_iterator != m_configurationMap.end())
@@ -144,10 +143,11 @@ std::string  Config::getVersion()
     }
 }
 
-std::string  Config::getPluginPath()
+std::string Config::getPluginPath()
 {
     std::map<std::string, std::string>::iterator m_iterator;
 
+    // Find the value for key - pluginPath
     m_iterator = m_configurationMap.find("pluginPath");
 
     if (m_iterator != m_configurationMap.end())
@@ -158,4 +158,4 @@ std::string  Config::getPluginPath()
     {
         return "";
     }
-}
+}
\ No newline at end of file
index cf9dcf8..ae73065 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file Config.h
+
+/// @brief
 
 #ifndef __CONFIG_H
 #define __CONFIG_H
@@ -90,6 +89,7 @@ namespace OIC
             static Config *s_configinstance;
             typedef std::map<std::string, std::string> configmap;
             configmap m_configurationMap;
+
             /**
             * Constructor for Config.
             * During construction time, configuration file  will be loaded.
index bdd12cb..ee83f66 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file CpluffAdapter.cpp
+
+/// @brief
 
 #include "CpluffAdapter.h"
 
@@ -212,7 +211,6 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
             m_plugins.push_back(*plugin);
             delete(plugin);
         }
-        //printf("plugin size = %d\n",m_plugins.size());
     }
 
     return TRUE;
@@ -220,7 +218,6 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
 
 int CpluffAdapter::registerPlugin(const std::string path)
 {
-    //printf("CpluffAdapter register\n");
     int flag = FALSE;
 
     if (path == "")
@@ -239,7 +236,6 @@ int CpluffAdapter::registerPlugin(const std::string path)
 
 int CpluffAdapter::registerAllPlugin(const std::string path)
 {
-    //printf("CpluffAdapter register\n");
     int flag = FALSE;
     if (path == "")
     {
@@ -325,6 +321,7 @@ std::vector<Plugin> *CpluffAdapter::findPlugins(const std::string key, const std
 
     return re_plugins;
 }
+
 /*
 Plugin *CpluffAdapter::getPlugin(const std::string plugID)
 {
@@ -339,6 +336,7 @@ Plugin *CpluffAdapter::getPlugin(const std::string plugID)
     return nullptr;
 }
 */
+
 bool CpluffAdapter::getFileList(File_list &list, const std::string strDir)
 {
     struct stat statinfo;
@@ -446,21 +444,14 @@ void CpluffAdapter::printPluginList()
 
 int CpluffAdapter::start(Plugin *const plugin, void *const arg)
 {
-    //printf("start\n");
     std::string id;
     cp_status_t status;
-    cp_context_t *ctx;
 
     id = plugin->getID();
     for (unsigned int i = 0 ; i < m_plugins.size(); i++)
     {
         if (*plugin == m_plugins[i])
         {
-            ctx = cpi_new_context((cp_plugin_t *)hnode_get(hash_lookup(m_context->env->plugins, id.c_str())),
-                                  m_context->env, &status);
-            //cp_define_symbol(ctx, "START_ARGUMENT", arg);
-            //printf("start ocplatform address : %x\n", arg);
-
             if ((status = cp_start_plugin(m_context, (char *)id.c_str()) ) != CP_OK)
             {
                 printf("API function CpluffAdapter::start() faild with error code.\n");
@@ -511,18 +502,17 @@ bool CpluffAdapter::isStarted(Plugin *plugin)
     }
     return FALSE;
 }
-//Auto plugin detection is disabled
+
+// Auto plugin detection is disabled
 /*
 void CpluffAdapter::observePluginPath(void *str)
 {
-    //printf("start observePluginPath\n");
     int length;
     int i = 0;
     int fd;
     int wd;
     char *str1 = (char *)str;
     std::string original_path(str1);
-    //printf("Directory is %s\n",(char*)str1));
     char buffer[BUF_LEN];
 
     fd = inotify_init();
@@ -547,7 +537,6 @@ void CpluffAdapter::observePluginPath(void *str)
             printf("observePluginPath read\n");
         }
         std::string filepath = original_path;
-        //printf("filepath = %s\n",filepath.c_str());
         while ( i < length )
         {
             if (i < (signed)(BUF_LEN  - ( sizeof( struct inotify_event) + 16)) && i > -1)
@@ -560,12 +549,8 @@ void CpluffAdapter::observePluginPath(void *str)
                 }
                 else
                 {
-                    //filepath += "/";
-                    //filepath += std::string(event->name);
                     std::vector<Plugin> *resource_plugin = findPlugins("Path", filepath.c_str()); //add foldername
 
-                    //printf("plugin size is %d\n",resource_plugin->size());
-                    //printf("plugin file path is %s\n",resource_plugin->());
                     if (resource_plugin->size() == 1)
                     {
                         unregisterPlugin(&(resource_plugin->at(0)));
@@ -577,8 +562,6 @@ void CpluffAdapter::observePluginPath(void *str)
                     delete(resource_plugin);
                     resource_plugin = nullptr;
                 }
-                //printf("observePluginPath path = %s \n",str1);
-                //printf("observePluginPath directory name = %s \n",event->name);
                 i += EVENT_SIZE + event->len;
             }
         }
@@ -587,10 +570,10 @@ void CpluffAdapter::observePluginPath(void *str)
     }
     ( void ) inotify_rm_watch( fd, wd );
     ( void ) close( fd );
-    //printf("observePluginPath end\n");
 }
 */
+
 const std::string CpluffAdapter::getState(const std::string plugID)
 {
     return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
-}
+}
\ No newline at end of file
index 1f96a13..a6c9257 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file CpluffAdapter.h
+
+/// @brief
 
 #ifndef __CPLUFFADAPTER_H
 #define __CPLUFFADAPTER_H
index a2a5637..5b5cfca 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file FelixAdapter.cpp
+
+/// @brief
 
 #include "FelixAdapter.h"
 #include <sstream>
@@ -72,94 +71,96 @@ int FelixAdapter::loadPluginInfoToManager(const std::string path)
 
 int FelixAdapter::registerPlugin(const std::string path)
 {
-    int flag = FALSE;
-
     if (path == "")
     {
         printf("FelixAdapter path == null\n");
-        return flag;
+        return 0;
     }
 
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     jstring jpath = env->NewStringUTF(path.c_str());
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "registerPlugin", "(Ljava/lang/String;)I");
 
-    flag =  (int)env->CallStaticIntMethod(cls, mid, jpath);
-    return flag;
+    // call registerPlugin() function
+    return  (int)env->CallStaticIntMethod(cls, mid, jpath);
 }
 
 int FelixAdapter::registerAllPlugin(const std::string path)
 {
-    int flag = FALSE;
-
     if (path == "")
     {
         printf("FelixAdapter path == null\n");
-        return flag;
+        return 0;
     }
 
-
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     jstring jpath = env->NewStringUTF(path.c_str());
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "registerAllPlugin", "(Ljava/lang/String;)I");
 
-    flag = (int)env->CallStaticIntMethod(cls, mid, jpath);
-
-    return flag;
+    // call registerAllPlugin() function
+    return (int)env->CallStaticIntMethod(cls, mid, jpath);
 }
 
 int FelixAdapter::unregisterPlugin(Plugin *const plugin)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     const char *cpath = plugin->getID().c_str();
     jstring jpath = env->NewStringUTF(cpath);
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "unregisterPlugin", "(Ljava/lang/String;)I");
-   
+
+    // call unregisterPlugin() function
     return (int)env->CallStaticIntMethod(cls, mid, jpath);
 }
 
 int FelixAdapter::unregisterAllPlugin(void)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "unregisterAllPlugin", "()I");
-   
+
+    // call registerAllPlugin() function
     return (int)env->CallStaticIntMethod(cls, mid);
 }
 
 std::vector<Plugin> &FelixAdapter::getAllPlugins(void)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
 
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "getAllPlugins", "()[Lorg/osgi/framework/Bundle;");
+
+    // call getAllPlugins() function
     jobjectArray jresultArray = (jobjectArray)env->CallStaticObjectMethod(cls, mid);
     jint size = env->GetArrayLength(jresultArray);
     m_plugins.clear();
 
-    for(int i = 0; i < (int)size; i++) {
+    for (int i = 0; i < (int)size; i++)
+    {
         Plugin *plugin = new Plugin;
 
         jobject result = env->GetObjectArrayElement(jresultArray, i);
         cls = env->GetObjectClass(result);
+        // set Language value
         plugin->setValue("Language", "JAVA");
+        // set Id value
         mid = env->GetMethodID(cls, "getSymbolicName", "()Ljava/lang/String;");
         jstring jid = (jstring)env->CallObjectMethod(result, mid);
         std::string id = env->GetStringUTFChars(jid, 0);
         plugin->setValue("Id", id);
+        // set Version value
         mid = env->GetMethodID(cls, "getVersion", "()Lorg/osgi/framework/Version;");
         jobject jversion_object = env->CallObjectMethod(result, mid);
         jclass vcls = env->GetObjectClass(jversion_object);
@@ -167,17 +168,22 @@ std::vector<Plugin> &FelixAdapter::getAllPlugins(void)
         jstring jversion = (jstring)env->CallObjectMethod(jversion_object, mid);
         std::string version = env->GetStringUTFChars(jversion, 0);
         plugin->setValue("Version", version);
+        // set Name value
         cls = env->FindClass("org/oic/android/FelixManager");
-        mid = env->GetStaticMethodID(cls, "getValue", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+        mid = env->GetStaticMethodID(cls, "getValue",
+                                     "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
         std::string key = "Name";
-        jstring jname = (jstring)env->CallStaticObjectMethod(cls, mid, jid, env->NewStringUTF(key.c_str()));
+        jstring jname = (jstring)env->CallStaticObjectMethod(cls, mid, jid, 
+                        env->NewStringUTF(key.c_str()));
         std::string name = env->GetStringUTFChars(jname, 0);
         plugin->setValue("Name", name);
+        // set ResourceType value
         key = "ResourceType";
-        jstring jresourcetype = (jstring)env->CallStaticObjectMethod(cls, mid, jid, env->NewStringUTF(key.c_str()));
+        jstring jresourcetype = (jstring)env->CallStaticObjectMethod(cls, mid, jid,
+                                env->NewStringUTF(key.c_str()));
         std::string resourcetype = env->GetStringUTFChars(jresourcetype, 0);
-        //LOGD("ResourceType:");
         plugin->setValue("ResourceType", resourcetype);
+        // push the plugin into the vector
         m_plugins.push_back(*plugin);
     }
 
@@ -187,31 +193,38 @@ std::vector<Plugin> &FelixAdapter::getAllPlugins(void)
 std::vector<Plugin> *FelixAdapter::findPlugins(const std::string key, const std::string value)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     jstring jkey = env->NewStringUTF(key.c_str());
     jstring jvalue = env->NewStringUTF(value.c_str());
 
     jclass cls = env->FindClass("org/oic/android/FelixManager");
-    jmethodID mid = env->GetStaticMethodID(cls, "findPlugins", "(Ljava/lang/String;Ljava/lang/String;)[Lorg/osgi/framework/Bundle;");
+    jmethodID mid = env->GetStaticMethodID(cls, "findPlugins",
+                        "(Ljava/lang/String;Ljava/lang/String;)[Lorg/osgi/framework/Bundle;");
 
-    jobjectArray jresultArray = (jobjectArray)env->CallStaticObjectMethod(cls, mid, (jstring)jkey, (jstring)jvalue);
+    // call findPlugins() function
+    jobjectArray jresultArray = (jobjectArray)env->CallStaticObjectMethod(cls, mid, (jstring)jkey,
+                                (jstring)jvalue);
 
     jint size = env->GetArrayLength(jresultArray);
-    
+
     std::vector<Plugin> *re_plugins;
     re_plugins = new std::vector<Plugin>;
 
-    for(int i = 0; i < (int)size; i++) {
+    for (int i = 0; i < (int)size; i++)
+    {
         Plugin *plugin = new Plugin;
 
-                jobject result = env->GetObjectArrayElement(jresultArray, i);
+        jobject result = env->GetObjectArrayElement(jresultArray, i);
         cls = env->GetObjectClass(result);
+        // set Language value
         plugin->setValue("Language", "JAVA");
+        // set Id value
         mid = env->GetMethodID(cls, "getSymbolicName", "()Ljava/lang/String;");
         jstring jid = (jstring)env->CallObjectMethod(result, mid);
         std::string id = env->GetStringUTFChars(jid, 0);
         plugin->setValue("Id", id);
+        // set Version value
         mid = env->GetMethodID(cls, "getVersion", "()Lorg/osgi/framework/Version;");
         jobject jversion_object = env->CallObjectMethod(result, mid);
         jclass vcls = env->GetObjectClass(jversion_object);
@@ -219,18 +232,25 @@ std::vector<Plugin> *FelixAdapter::findPlugins(const std::string key, const std:
         jstring jversion = (jstring)env->CallObjectMethod(jversion_object, mid);
         std::string version = env->GetStringUTFChars(jversion, 0);
         plugin->setValue("Version", version);
+        // set Name value
         cls = env->FindClass("org/oic/android/FelixManager");
-        mid = env->GetStaticMethodID(cls, "getValue", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+        mid = env->GetStaticMethodID(cls, "getValue",
+                    "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
         std::string key = "Name";
-        jstring jname = (jstring)env->CallStaticObjectMethod(cls, mid, jid, env->NewStringUTF(key.c_str()));
+        jstring jname = (jstring)env->CallStaticObjectMethod(cls, mid, jid, 
+                        env->NewStringUTF(key.c_str()));
         std::string name = env->GetStringUTFChars(jname, 0);
         plugin->setValue("Name", name);
+        // set ResourceType value
         key = "ResourceType";
-        jstring jresourcetype = (jstring)env->CallStaticObjectMethod(cls, mid, jid, env->NewStringUTF(key.c_str()));
-        //LOGD("ResourceType:");
+        jstring jresourcetype = (jstring)env->CallStaticObjectMethod(cls, mid, jid,
+                                env->NewStringUTF(key.c_str()));
+        std::string resourcetype = env->GetStringUTFChars(jresourcetype, 0);
+        plugin->setValue("ResourceType", resourcetype);
+        // push the plugin into the vector
         m_plugins.push_back(*plugin);
     }
-    
+
     return re_plugins;
 }
 /*
@@ -253,56 +273,63 @@ void FelixAdapter::printPluginList(cp_plugin_info_t **plugins)
 int FelixAdapter::start(Plugin *const plugin, void *const arg)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     const char *cid = plugin->getID().c_str();
     jstring jid = env->NewStringUTF(cid);
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "start", "(Ljava/lang/String;)I");
-   
+
+    // call start() function
     return (int)env->CallStaticIntMethod(cls, mid, jid);
 }
 
 int FelixAdapter::stop(Plugin *const plugin)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     const char *cid = plugin->getID().c_str();
     jstring jid = env->NewStringUTF(cid);
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "stop", "(Ljava/lang/String;)I");
-   
+
+    // call stop() function
     return (int)env->CallStaticIntMethod(cls, mid, jid);
 }
 
 bool FelixAdapter::isStarted(Plugin *plugin)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     const char *cid = plugin->getID().c_str();
     jstring jid = env->NewStringUTF(cid);
     jclass cls = env->FindClass("org/oic/android/FelixManager");
     jmethodID mid = env->GetStaticMethodID(cls, "isStarted", "(Ljava/lang/String;)Z");
-   
+
+    // call isStarted() function
     return (bool)env->CallStaticBooleanMethod(cls, mid, jid);
 }
+
 /*
 void FelixAdapter::observePluginPath(void *str)
 {
 
 }
 */
+
 const std::string FelixAdapter::getState(const std::string plugID)
 {
     JNIEnv *env;
-    jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
 
     jstring jplugID = env->NewStringUTF(plugID.c_str());
     jclass cls = env->FindClass("org/oic/android/FelixManager");
-    jmethodID mid = env->GetStaticMethodID(cls, "getState", "(Ljava/lang/String;)Ljava/lang/String;");
-   
+    jmethodID mid = env->GetStaticMethodID(cls, "getState", 
+                    "(Ljava/lang/String;)Ljava/lang/String;");
+
+    // call getState() function
     jstring jresult = (jstring)env->CallStaticObjectMethod(cls, mid, jplugID);
     return env->GetStringUTFChars(jresult, 0);
-}
+}
\ No newline at end of file
index 918c1c3..f4d655d 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file FelixAdapter.h
+
+/// @brief
 
 #ifndef __FELIXADAPTER_H__
 #define __FELIXADAPTER_H__
@@ -170,7 +169,7 @@ namespace OIC
             *
             * @return OICPluginManager pointer Address.
             */
-            static FelixAdapter *Getinstance(void *args=NULL)
+            static FelixAdapter *Getinstance(void *args = NULL)
             {
                 if (NULL == s_pinstance)
                 {
@@ -183,19 +182,12 @@ namespace OIC
 
 
         private:
-                       JavaVM *jvm;
+            JavaVM *jvm;
             Config *config;
             typedef std::map<std::string, bool> File_list;
             std::vector<Plugin> m_plugins;
             boost::thread m_file_detect_thread;
-            /*
-            cp_context_t *m_context;
-            cp_status_t m_status;
-            cp_plugin_info_t **m_cp_plugins;
-            cp_plugin_info_t *m_plugin;
-            boost::thread_group m_thread_g;
-            std::string m_path;
-            */
+
             static FelixAdapter *s_pinstance;
 
             /**
index 2da8756..7ef312c 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file Plugin.cpp
+
+/// @brief
+
 
 #include "Plugin.h"
 
index f4fd572..6b4b1c7 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file Plugin.h
+
+/// @brief
+
 
 #ifndef __Plugin_H__
 #define __Plugin_H__
@@ -73,68 +73,67 @@ namespace OIC
             */
             virtual ~Plugin(void);
 
+
             /**
-            * Get unique ID of the plug-in
+            * Get unique ID of the plugin.
             *
-            * @return unique id string of the pluin. if ID is not exist, it return ""
+            * @return unique id string of the pluin. if ID is not exist, it return "".
             */
             std::string getID(void);
 
 
             /**
-            * Get version of the plug-in
-            *
-            * @return version information string of the plugin. if Version is not exist, it return ""
+            * Get version of the plugin.
             *
+            * @return version information string of the plugin. if Version is not exist, it return "".
             */
             std::string getVersion(void);
 
 
             /**
-            * Get name of the plug-in
+            * Get name of the plugin.
             *
-            * @return name string of the plugin. if Name is not exist, it return ""
+            * @return name string of the plugin. if Name is not exist, it return "".
             */
             std::string getName(void);
 
 
             /**
-            * Get provider name of the plug-in
-            *
-            * @return provider name of the plugin. if ProviderName is not exist, it return ""
+            * Get provider name of the plugin.
             *
+            * @return provider name of the plugin. if ProviderName is not exist, it return "".
             */
             std::string getProviderName(void);
 
 
             /**
-            * Get value for the attributes
-            *
-            * @param attribute attriubute string to get value
-            * @return value of the attribute. if "attribute" is not exist, it return ""
+            * Get value for the attributes.
             *
+            * @param attriubute string to get value.
+            * @return value of the attribute. if "attribute" is not exist, it return "".
             */
             std::string getValueByAttribute(const std::string attribute);
 
+
             /**
             * Check whether the plugin same or not.
             *
-            * @param plugin
-            * @return true if same, else return false
-            *
+            * @param plugin.
+            * @return true if same, else return false.
             */
             bool operator==(Plugin &plugin);
 
         private:
             friend class CpluffAdapter;
             friend class FelixAdapter;
+
+
             /**
             * Set key, value. key is attribute name.
             *
             * @param key is atrribute name.
             * @param value for the attribute.
-            * @return void
-            *
+            * @return void.
             */
             void setValue(const std::string key, const std::string value);
 
index a620feb..acdaeb9 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file PluginManager.cpp
+
+/// @brief
+
 
 #include "PluginManager.h"
 
@@ -35,8 +35,8 @@ PluginManager::PluginManager()
         fprintf(stderr, "%s\n", dlerror());
         exit(EXIT_FAILURE);
     }
-    PluginManagerImpl* (*create)(void*);
-    create = (PluginManagerImpl * (*)(void*))dlsym(handle, "create_object");
+    PluginManagerImpl* (*create)(void *);
+    create = (PluginManagerImpl * (*)(void *))dlsym(handle, "create_object");
     destroy = (void (*)(PluginManagerImpl *))dlsym(handle, "destroy_object");
     pluginManagerImpl = (PluginManagerImpl *)create(NULL);
 }
@@ -70,4 +70,4 @@ std::vector<Plugin> PluginManager::getPlugins(void)
 std::string PluginManager::getState(const std::string plugID)
 {
     return pluginManagerImpl->getState(plugID);
-}
+}
\ No newline at end of file
index a407317..f1fe50f 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file PluginManager.h
+
+/// @brief
 
 #ifndef __PLUGINMANAGER_H
 #define __PLUGINMANAGER_H
@@ -54,19 +53,20 @@ namespace OIC
             * Virtual destructor
             */
             ~PluginManager(void);
+
             /**
-            * Start  plugins by resource type
-            *
-            * @param type resouce type string to be started.
+            * Start plugins by key-value pair.
             *
+            * @param key-value pair string to be started.
+            * @return int, 1 is success, 0 is fail.
             */
             int startPlugins(const std::string key, const std::string value);
 
             /**
-            * Stop  plugins by resource type
-            *
-            * @param type resouce type string to be started.
+            * Stop plugins by key-value pair.
             *
+            * @param key-value pair string to be stopped.
+            * @return int, 1 is success, 0 is fail.
             */
             int stopPlugins(const std::string key, const std::string value);
 
@@ -74,25 +74,24 @@ namespace OIC
             * Rescan Plugin.
             * This function will call rescan function of plugins in the configuration folder
             *
-            * @param Plugin
+            * @param void.
             * @return int, 1 is success, 0 is fail.
             */
-            int rescanPlugin();
+            int rescanPlugin(void);
 
             /**
             * Get Plugin list.
             *
-            *
-            *
-            * @return
+            * @param void.
+            * @return Plugin vector
             */
             std::vector<Plugin> getPlugins(void);
 
             /**
             * Get Plugin state.
             *
-            * @param Plugin ID
-            * @return Plugin state.
+            * @param Plugin ID string.
+            * @return Plugin state string.
             */
             std::string getState(const std::string plugID);
 
@@ -102,4 +101,4 @@ namespace OIC
             void *handle;
     };
 }
-#endif //__PLUGINMANAGER_H
+#endif //__PLUGINMANAGER_H
\ No newline at end of file
index a7fafa6..1920fe0 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file PluginManagerImpl.cpp
+
+/// @brief
 
 #include "PluginManagerImpl.h"
 
@@ -41,15 +40,15 @@ extern "C" void destroy_object( PluginManagerImpl *object )
     delete object;
 }
 
-PluginManagerImpl::PluginManagerImpl(voidargs)
+PluginManagerImpl::PluginManagerImpl(void *args)
 {
     cppm = CpluffAdapter::Getinstance();
-    #ifdef ANDROID
-        if(args)
-            javappm = FelixAdapter::Getinstance(args);
-        else
-            javappm = NULL;
-    #endif
+#ifdef ANDROID
+    if (args)
+        javappm = FelixAdapter::Getinstance(args);
+    else
+        javappm = NULL;
+#endif
     refreshPluginInfo();
 }
 
@@ -62,10 +61,10 @@ int PluginManagerImpl::registerPlugin(std::string path)
 {
     int flag = 0;
     flag = cppm->registerPlugin(path);
-    #ifdef ANDROID
-        if(javappm)
-            flag = javappm->registerPlugin(path);
-    #endif
+#ifdef ANDROID
+    if (javappm)
+        flag = javappm->registerPlugin(path);
+#endif
     refreshPluginInfo();
     return flag;
 }
@@ -75,10 +74,10 @@ int PluginManagerImpl::registerAllPlugin(std::string path)
     int flag = 0;
     flag = cppm->registerAllPlugin(path);
 
-    #ifdef ANDROID
-        if(javappm)
-            flag = javappm->registerAllPlugin(path);
-    #endif
+#ifdef ANDROID
+    if (javappm)
+        flag = javappm->registerAllPlugin(path);
+#endif
 
     refreshPluginInfo();
     return flag;
@@ -101,12 +100,12 @@ int PluginManagerImpl::unregisterPlugin(std::string id)
             }
             else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
             {
-                #ifdef ANDROID
-                    if ((flag = javappm->unregisterPlugin(&m_plugins[i])))
-                    {
-                        m_plugins.erase(m_plugins.begin() + i);
-                    }
-                #endif
+#ifdef ANDROID
+                if ((flag = javappm->unregisterPlugin(&m_plugins[i])))
+                {
+                    m_plugins.erase(m_plugins.begin() + i);
+                }
+#endif
             }
         }
     }
@@ -118,10 +117,10 @@ int PluginManagerImpl::unregisterAllPlugin()
 {
     int flag = 0;
     flag = cppm->unregisterAllPlugin();
-    #ifdef ANDROID
-        if(javappm)
-            flag = javappm->unregisterAllPlugin();
-    #endif
+#ifdef ANDROID
+    if (javappm)
+        flag = javappm->unregisterAllPlugin();
+#endif
     m_plugins.clear();
     return flag;
 }
@@ -284,10 +283,10 @@ int PluginManagerImpl::startbyPlatform(Plugin *const plugin, void *const arg)
             }
             else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
             {
-                #ifdef ANDROID
-                    if(javappm)
-                        flag = javappm->start(plugin, arg);
-                #endif
+#ifdef ANDROID
+                if (javappm)
+                    flag = javappm->start(plugin, arg);
+#endif
             }
         }
     }
@@ -313,10 +312,10 @@ int PluginManagerImpl::stopbyPlatform(Plugin *const plugin)
             }
             else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
             {
-                #ifdef ANDROID
-                    if(javappm)
-                        flag = javappm->stop(plugin);
-                #endif
+#ifdef ANDROID
+                if (javappm)
+                    flag = javappm->stop(plugin);
+#endif
             }
         }
     }
@@ -336,15 +335,16 @@ bool PluginManagerImpl::isStarted(Plugin *plugin)
         flag = TRUE;
         return flag;
     }
-    #ifdef ANDROID
-        if(javappm) {
-            if (javappm->isStarted(plugin))
-            {
-                flag = TRUE;
-                return flag;
-            }
+#ifdef ANDROID
+    if (javappm)
+    {
+        if (javappm->isStarted(plugin))
+        {
+            flag = TRUE;
+            return flag;
         }
-    #endif
+    }
+#endif
     return flag;
 }
 
@@ -362,10 +362,10 @@ std::string PluginManagerImpl::getState(std::string plugID)
             }
             else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
             {
-                #ifdef ANDROID
-                    if(javappm)
-                        str = javappm->getState(plugID);
-                #endif
+#ifdef ANDROID
+                if (javappm)
+                    str = javappm->getState(plugID);
+#endif
             }
         }
     }
@@ -378,17 +378,18 @@ std::vector<Plugin> PluginManagerImpl::refreshPluginInfo()
     m_plugins.clear();
     m_plugins = cppm->getAllPlugins();
 
-    #ifdef ANDROID
-        if(javappm) {
-            std::vector<Plugin> java_plugins = javappm->getAllPlugins();
-            int size = java_plugins.size();
+#ifdef ANDROID
+    if (javappm)
+    {
+        std::vector<Plugin> java_plugins = javappm->getAllPlugins();
+        int size = java_plugins.size();
 
-            for (int i = 0 ; i < size ; i++)
-            {
-                m_plugins.push_back(java_plugins[i]);
-            }
+        for (int i = 0 ; i < size ; i++)
+        {
+            m_plugins.push_back(java_plugins[i]);
         }
-    #endif
+    }
+#endif
 
     return m_plugins;
-}
+}
\ No newline at end of file
index 553944b..ee78056 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-/**
- * @file
- *
- */
+/// @file PluginManagerImpl.h
+
+/// @brief
 
 #ifndef __PLUGINMANAGERIMPL_H__
 #define __PLUGINMANAGERIMPL_H__
@@ -30,7 +29,7 @@
 #include "CpluffAdapter.h"
 
 #ifdef ANDROID
-    #include "FelixAdapter.h"
+#include "FelixAdapter.h"
 #endif
 
 namespace OIC
@@ -44,7 +43,7 @@ namespace OIC
             * During construction time, all plugins under the root plugin path will be loaded.
             *
             */
-            PluginManagerImpl(voidargs);
+            PluginManagerImpl(void *args);
 
             /**
             * Virtual destructor
@@ -65,7 +64,6 @@ namespace OIC
             int registerPlugin(std::string path);
 
 
-
             /**
             * A function to register pluins in the path.
             * This function will load plugins in plugin manager table.
@@ -191,9 +189,9 @@ namespace OIC
         private:
 
             CpluffAdapter *cppm;
-            #ifdef ANDROID
-                FelixAdapter *javappm;
-            #endif
+#ifdef ANDROID
+            FelixAdapter *javappm;
+#endif
 
             std::vector<Plugin> m_plugins;
             static PluginManagerImpl *s_pinstance;
@@ -235,4 +233,4 @@ namespace OIC
     };
 }
 
-#endif //__PLUGINMANAGERIMPL_H__
+#endif //__PLUGINMANAGERIMPL_H__
\ No newline at end of file
index 3dd48f1..fb30395 100644 (file)
@@ -17,19 +17,19 @@ target_os = env.get('TARGET_OS')
 plugins_env.AppendUnique(CPPPATH = ['../lib/cpluff/libcpluff'])
 
 if target_os not in ['windows', 'winrt']:
-       plugins_env.AppendUnique(CXXFLAGS = ['-g3', '-Wall', '-pthread'])
-       plugins_env.PrependUnique(CCFLAGS = ['-fPIC']) 
-       plugins_env.AppendUnique(LINKFLAGS = ['-fPIC'])
+    plugins_env.AppendUnique(CXXFLAGS = ['-g3', '-Wall', '-pthread'])
+    plugins_env.PrependUnique(CCFLAGS = ['-fPIC'])
+    plugins_env.AppendUnique(LINKFLAGS = ['-fPIC'])
 
-       if target_os not in ['arduino', 'android']:
-               plugins_env.AppendUnique(LIBS = ['pthread'])
+    if target_os not in ['arduino', 'android']:
+        plugins_env.AppendUnique(LIBS = ['pthread'])
 
 if target_os == 'android':
-       plugins_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
-       plugins_env.AppendUnique(LIBS = ['gnustl_shared'])
+    plugins_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+    plugins_env.AppendUnique(LIBS = ['gnustl_shared'])
 
 plugins_env.AppendUnique(LIBS = [File(env.get('BUILD_DIR') + '/libmosquitto.a'),
-               'mosquitto', 'ssl', 'rt'])
+        'mosquitto', 'ssl', 'rt'])
 
 
 ######################################################################
index 1b483a4..258b4fb 100644 (file)
@@ -16,13 +16,13 @@ target_os = env.get('TARGET_OS')
 sample_env.AppendUnique(CPPPATH = [
                                '../../plugin-manager/src/',
                                '../../lib/cpluff/libcpluff/',
-                               '../../lib/rapidxml'
+                               env.get('SRC_DIR') + '/extlibs/rapidxml'
                         ])
 if target_os not in ['windows', 'winrt']:
        sample_env.AppendUnique(CXXFLAGS = ['-Wall', '-pthread'])
 
 sample_env.AppendUnique(LIBS = ['oc', 'oc_logger', 'octbstack', 'coap', 'ppm', 'pmimpl', 'boost_system', 'boost_thread', 'dl'])
-sample_env.AppendUnique(LIBS = ['pthread', 'rt'])
+sample_env.AppendUnique(LIBS = ['pthread'])
 
 ######################################################################
 # Source files and Targets
index 131e83a..c2fef11 100644 (file)
@@ -19,7 +19,7 @@ CXX_INC += -I../../lib
 CXX_INC += -I../../../lib/cpluff/libcpluff
 CXX_INC += -I../../../plugin-manager/src
 CXX_INC   += -I$(CEREAL_DIR)/include
-CXX_INC += -I../../../lib/rapidxml 
+CXX_INC += -I$(TOP_DIR)/extlibs/rapidxml 
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
 CXX_LIBS  := ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a