git repos / blockattack-game

blame: source/code/Libs/include/cereal/external/rapidxml/rapidxml.hpp

normal view · raw

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