~tapaal-ltl/verifypn/scc-optimise

« back to all changes in this revision

Viewing changes to PetriParse/rapidxml/rapidxml.hpp

  • Committer: srba.jiri at gmail
  • Date: 2020-09-11 14:23:39 UTC
  • mfrom: (213.1.151 interval_tar)
  • Revision ID: srba.jiri@gmail.com-20200911142339-bq9328s1gppw24uj
merged in lp:~verifypn-maintainers/verifypn/interval_tar doing 
- Implements TAR w/o z3, but using a simple integer inference engine for Hoare logic.
 - Replaces LP-Solve with GLPK, reduces computation-time and memory overhead
 - Implements new global properties, translated into CTL formulae.

Show diffs side-by-side

added added

removed removed

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