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