New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
rapidxml.hpp in vendors/XIOS/current/extern/rapidxml/include – NEMO

source: vendors/XIOS/current/extern/rapidxml/include/rapidxml.hpp @ 3428

Last change on this file since 3428 was 3428, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

File size: 118.1 KB
Line 
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
30namespace 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
57namespace 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
134namespace 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
Note: See TracBrowser for help on using the repository browser.