git repos / blockattack-game

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

normal view · raw

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