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