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