libaurum: Fix wrong statement it cause crash
[platform/core/uifw/aurum.git] / pugixml / pugixml.cpp
1 /**
2  * pugixml parser - version 1.12
3  * --------------------------------------------------------
4  * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
5  * Report bugs and download new versions at https://pugixml.org/
6  *
7  * This library is distributed under the MIT License. See notice at the end
8  * of this file.
9  *
10  * This work is based on the pugxml parser, which is:
11  * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
12  */
13
14 #ifndef SOURCE_PUGIXML_CPP
15 #define SOURCE_PUGIXML_CPP
16
17 #include "pugixml.hpp"
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <assert.h>
23 #include <limits.h>
24
25 #ifdef PUGIXML_WCHAR_MODE
26 #       include <wchar.h>
27 #endif
28
29 #ifndef PUGIXML_NO_XPATH
30 #       include <math.h>
31 #       include <float.h>
32 #endif
33
34 #ifndef PUGIXML_NO_STL
35 #       include <istream>
36 #       include <ostream>
37 #       include <string>
38 #endif
39
40 // For placement new
41 #include <new>
42
43 #ifdef _MSC_VER
44 #       pragma warning(push)
45 #       pragma warning(disable: 4127) // conditional expression is constant
46 #       pragma warning(disable: 4324) // structure was padded due to __declspec(align())
47 #       pragma warning(disable: 4702) // unreachable code
48 #       pragma warning(disable: 4996) // this function or variable may be unsafe
49 #endif
50
51 #if defined(_MSC_VER) && defined(__c2__)
52 #       pragma clang diagnostic push
53 #       pragma clang diagnostic ignored "-Wdeprecated" // this function or variable may be unsafe
54 #endif
55
56 #ifdef __INTEL_COMPILER
57 #       pragma warning(disable: 177) // function was declared but never referenced
58 #       pragma warning(disable: 279) // controlling expression is constant
59 #       pragma warning(disable: 1478 1786) // function was declared "deprecated"
60 #       pragma warning(disable: 1684) // conversion from pointer to same-sized integral type
61 #endif
62
63 #if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY)
64 #       pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away
65 #endif
66
67 #ifdef __BORLANDC__
68 #       pragma option push
69 #       pragma warn -8008 // condition is always false
70 #       pragma warn -8066 // unreachable code
71 #endif
72
73 #ifdef __SNC__
74 // Using diag_push/diag_pop does not disable the warnings inside templates due to a compiler bug
75 #       pragma diag_suppress=178 // function was declared but never referenced
76 #       pragma diag_suppress=237 // controlling expression is constant
77 #endif
78
79 #ifdef __TI_COMPILER_VERSION__
80 #       pragma diag_suppress 179 // function was declared but never referenced
81 #endif
82
83 // Inlining controls
84 #if defined(_MSC_VER) && _MSC_VER >= 1300
85 #       define PUGI__NO_INLINE __declspec(noinline)
86 #elif defined(__GNUC__)
87 #       define PUGI__NO_INLINE __attribute__((noinline))
88 #else
89 #       define PUGI__NO_INLINE
90 #endif
91
92 // Branch weight controls
93 #if defined(__GNUC__) && !defined(__c2__)
94 #       define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0)
95 #else
96 #       define PUGI__UNLIKELY(cond) (cond)
97 #endif
98
99 // Simple static assertion
100 #define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; }
101
102 // Digital Mars C++ bug workaround for passing char loaded from memory via stack
103 #ifdef __DMC__
104 #       define PUGI__DMC_VOLATILE volatile
105 #else
106 #       define PUGI__DMC_VOLATILE
107 #endif
108
109 // Integer sanitizer workaround; we only apply this for clang since gcc8 has no_sanitize but not unsigned-integer-overflow and produces "attribute directive ignored" warnings
110 #if defined(__clang__) && defined(__has_attribute)
111 #       if __has_attribute(no_sanitize)
112 #               define PUGI__UNSIGNED_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow")))
113 #       else
114 #               define PUGI__UNSIGNED_OVERFLOW
115 #       endif
116 #else
117 #       define PUGI__UNSIGNED_OVERFLOW
118 #endif
119
120 // Borland C++ bug workaround for not defining ::memcpy depending on header include order (can't always use std::memcpy because some compilers don't have it at all)
121 #if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST)
122 using std::memcpy;
123 using std::memmove;
124 using std::memset;
125 #endif
126
127 // Some MinGW/GCC versions have headers that erroneously omit LLONG_MIN/LLONG_MAX/ULLONG_MAX definitions from limits.h in some configurations
128 #if defined(PUGIXML_HAS_LONG_LONG) && defined(__GNUC__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX)
129 #       define LLONG_MIN (-LLONG_MAX - 1LL)
130 #       define LLONG_MAX __LONG_LONG_MAX__
131 #       define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
132 #endif
133
134 // In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features
135 #if defined(_MSC_VER) && !defined(__S3E__) && !defined(_WIN32_WCE)
136 #       define PUGI__MSVC_CRT_VERSION _MSC_VER
137 #elif defined(_WIN32_WCE)
138 #       define PUGI__MSVC_CRT_VERSION 1310 // MSVC7.1
139 #endif
140
141 // Not all platforms have snprintf; we define a wrapper that uses snprintf if possible. This only works with buffers with a known size.
142 #if __cplusplus >= 201103
143 #       define PUGI__SNPRINTF(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__)
144 #elif defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
145 #       define PUGI__SNPRINTF(buf, ...) _snprintf_s(buf, _countof(buf), _TRUNCATE, __VA_ARGS__)
146 #else
147 #       define PUGI__SNPRINTF sprintf
148 #endif
149
150 // We put implementation details into an anonymous namespace in source mode, but have to keep it in non-anonymous namespace in header-only mode to prevent binary bloat.
151 #ifdef PUGIXML_HEADER_ONLY
152 #       define PUGI__NS_BEGIN namespace pugi { namespace impl {
153 #       define PUGI__NS_END } }
154 #       define PUGI__FN inline
155 #       define PUGI__FN_NO_INLINE inline
156 #else
157 #       if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces
158 #               define PUGI__NS_BEGIN namespace pugi { namespace impl {
159 #               define PUGI__NS_END } }
160 #       else
161 #               define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace {
162 #               define PUGI__NS_END } } }
163 #       endif
164 #       define PUGI__FN
165 #       define PUGI__FN_NO_INLINE PUGI__NO_INLINE
166 #endif
167
168 // uintptr_t
169 #if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561)
170 namespace pugi
171 {
172 #       ifndef _UINTPTR_T_DEFINED
173         typedef size_t uintptr_t;
174 #       endif
175
176         typedef unsigned __int8 uint8_t;
177         typedef unsigned __int16 uint16_t;
178         typedef unsigned __int32 uint32_t;
179 }
180 #else
181 #       include <stdint.h>
182 #endif
183
184 // Memory allocation
185 PUGI__NS_BEGIN
186         PUGI__FN void* default_allocate(size_t size)
187         {
188                 return malloc(size);
189         }
190
191         PUGI__FN void default_deallocate(void* ptr)
192         {
193                 free(ptr);
194         }
195
196         template <typename T>
197         struct xml_memory_management_function_storage
198         {
199                 static allocation_function allocate;
200                 static deallocation_function deallocate;
201         };
202
203         // Global allocation functions are stored in class statics so that in header mode linker deduplicates them
204         // Without a template<> we'll get multiple definitions of the same static
205         template <typename T> allocation_function xml_memory_management_function_storage<T>::allocate = default_allocate;
206         template <typename T> deallocation_function xml_memory_management_function_storage<T>::deallocate = default_deallocate;
207
208         typedef xml_memory_management_function_storage<int> xml_memory;
209 PUGI__NS_END
210
211 // String utilities
212 PUGI__NS_BEGIN
213         // Get string length
214         PUGI__FN size_t strlength(const char_t* s)
215         {
216                 assert(s);
217
218         #ifdef PUGIXML_WCHAR_MODE
219                 return wcslen(s);
220         #else
221                 return strlen(s);
222         #endif
223         }
224
225         // Compare two strings
226         PUGI__FN bool strequal(const char_t* src, const char_t* dst)
227         {
228                 assert(src && dst);
229
230         #ifdef PUGIXML_WCHAR_MODE
231                 return wcscmp(src, dst) == 0;
232         #else
233                 return strcmp(src, dst) == 0;
234         #endif
235         }
236
237         // Compare lhs with [rhs_begin, rhs_end)
238         PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count)
239         {
240                 for (size_t i = 0; i < count; ++i)
241                         if (lhs[i] != rhs[i])
242                                 return false;
243
244                 return lhs[count] == 0;
245         }
246
247         // Get length of wide string, even if CRT lacks wide character support
248         PUGI__FN size_t strlength_wide(const wchar_t* s)
249         {
250                 assert(s);
251
252         #ifdef PUGIXML_WCHAR_MODE
253                 return wcslen(s);
254         #else
255                 const wchar_t* end = s;
256                 while (*end) end++;
257                 return static_cast<size_t>(end - s);
258         #endif
259         }
260 PUGI__NS_END
261
262 // auto_ptr-like object for exception recovery
263 PUGI__NS_BEGIN
264         template <typename T> struct auto_deleter
265         {
266                 typedef void (*D)(T*);
267
268                 T* data;
269                 D deleter;
270
271                 auto_deleter(T* data_, D deleter_): data(data_), deleter(deleter_)
272                 {
273                 }
274
275                 ~auto_deleter()
276                 {
277                         if (data) deleter(data);
278                 }
279
280                 T* release()
281                 {
282                         T* result = data;
283                         data = 0;
284                         return result;
285                 }
286         };
287 PUGI__NS_END
288
289 #ifdef PUGIXML_COMPACT
290 PUGI__NS_BEGIN
291         class compact_hash_table
292         {
293         public:
294                 compact_hash_table(): _items(0), _capacity(0), _count(0)
295                 {
296                 }
297
298                 void clear()
299                 {
300                         if (_items)
301                         {
302                                 xml_memory::deallocate(_items);
303                                 _items = 0;
304                                 _capacity = 0;
305                                 _count = 0;
306                         }
307                 }
308
309                 void* find(const void* key)
310                 {
311                         if (_capacity == 0) return 0;
312
313                         item_t* item = get_item(key);
314                         assert(item);
315                         assert(item->key == key || (item->key == 0 && item->value == 0));
316
317                         return item->value;
318                 }
319
320                 void insert(const void* key, void* value)
321                 {
322                         assert(_capacity != 0 && _count < _capacity - _capacity / 4);
323
324                         item_t* item = get_item(key);
325                         assert(item);
326
327                         if (item->key == 0)
328                         {
329                                 _count++;
330                                 item->key = key;
331                         }
332
333                         item->value = value;
334                 }
335
336                 bool reserve(size_t extra = 16)
337                 {
338                         if (_count + extra >= _capacity - _capacity / 4)
339                                 return rehash(_count + extra);
340
341                         return true;
342                 }
343
344         private:
345                 struct item_t
346                 {
347                         const void* key;
348                         void* value;
349                 };
350
351                 item_t* _items;
352                 size_t _capacity;
353
354                 size_t _count;
355
356                 bool rehash(size_t count);
357
358                 item_t* get_item(const void* key)
359                 {
360                         assert(key);
361                         assert(_capacity > 0);
362
363                         size_t hashmod = _capacity - 1;
364                         size_t bucket = hash(key) & hashmod;
365
366                         for (size_t probe = 0; probe <= hashmod; ++probe)
367                         {
368                                 item_t& probe_item = _items[bucket];
369
370                                 if (probe_item.key == key || probe_item.key == 0)
371                                         return &probe_item;
372
373                                 // hash collision, quadratic probing
374                                 bucket = (bucket + probe + 1) & hashmod;
375                         }
376
377                         assert(false && "Hash table is full"); // unreachable
378                         return 0;
379                 }
380
381                 static PUGI__UNSIGNED_OVERFLOW unsigned int hash(const void* key)
382                 {
383                         unsigned int h = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key) & 0xffffffff);
384
385                         // MurmurHash3 32-bit finalizer
386                         h ^= h >> 16;
387                         h *= 0x85ebca6bu;
388                         h ^= h >> 13;
389                         h *= 0xc2b2ae35u;
390                         h ^= h >> 16;
391
392                         return h;
393                 }
394         };
395
396         PUGI__FN_NO_INLINE bool compact_hash_table::rehash(size_t count)
397         {
398                 size_t capacity = 32;
399                 while (count >= capacity - capacity / 4)
400                         capacity *= 2;
401
402                 compact_hash_table rt;
403                 rt._capacity = capacity;
404                 rt._items = static_cast<item_t*>(xml_memory::allocate(sizeof(item_t) * capacity));
405
406                 if (!rt._items)
407                         return false;
408
409                 memset(rt._items, 0, sizeof(item_t) * capacity);
410
411                 for (size_t i = 0; i < _capacity; ++i)
412                         if (_items[i].key)
413                                 rt.insert(_items[i].key, _items[i].value);
414
415                 if (_items)
416                         xml_memory::deallocate(_items);
417
418                 _capacity = capacity;
419                 _items = rt._items;
420
421                 assert(_count == rt._count);
422
423                 return true;
424         }
425
426 PUGI__NS_END
427 #endif
428
429 PUGI__NS_BEGIN
430 #ifdef PUGIXML_COMPACT
431         static const uintptr_t xml_memory_block_alignment = 4;
432 #else
433         static const uintptr_t xml_memory_block_alignment = sizeof(void*);
434 #endif
435
436         // extra metadata bits
437         static const uintptr_t xml_memory_page_contents_shared_mask = 64;
438         static const uintptr_t xml_memory_page_name_allocated_mask = 32;
439         static const uintptr_t xml_memory_page_value_allocated_mask = 16;
440         static const uintptr_t xml_memory_page_type_mask = 15;
441
442         // combined masks for string uniqueness
443         static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask;
444         static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask;
445
446 #ifdef PUGIXML_COMPACT
447         #define PUGI__GETHEADER_IMPL(object, page, flags) // unused
448         #define PUGI__GETPAGE_IMPL(header) (header).get_page()
449 #else
450         #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast<char*>(object) - reinterpret_cast<char*>(page)) << 8) | (flags))
451         // this macro casts pointers through void* to avoid 'cast increases required alignment of target type' warnings
452         #define PUGI__GETPAGE_IMPL(header) static_cast<impl::xml_memory_page*>(const_cast<void*>(static_cast<const void*>(reinterpret_cast<const char*>(&header) - (header >> 8))))
453 #endif
454
455         #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header)
456         #define PUGI__NODETYPE(n) static_cast<xml_node_type>((n)->header & impl::xml_memory_page_type_mask)
457
458         struct xml_allocator;
459
460         struct xml_memory_page
461         {
462                 static xml_memory_page* construct(void* memory)
463                 {
464                         xml_memory_page* result = static_cast<xml_memory_page*>(memory);
465
466                         result->allocator = 0;
467                         result->prev = 0;
468                         result->next = 0;
469                         result->busy_size = 0;
470                         result->freed_size = 0;
471
472                 #ifdef PUGIXML_COMPACT
473                         result->compact_string_base = 0;
474                         result->compact_shared_parent = 0;
475                         result->compact_page_marker = 0;
476                 #endif
477
478                         return result;
479                 }
480
481                 xml_allocator* allocator;
482
483                 xml_memory_page* prev;
484                 xml_memory_page* next;
485
486                 size_t busy_size;
487                 size_t freed_size;
488
489         #ifdef PUGIXML_COMPACT
490                 char_t* compact_string_base;
491                 void* compact_shared_parent;
492                 uint32_t* compact_page_marker;
493         #endif
494         };
495
496         static const size_t xml_memory_page_size =
497         #ifdef PUGIXML_MEMORY_PAGE_SIZE
498                 (PUGIXML_MEMORY_PAGE_SIZE)
499         #else
500                 32768
501         #endif
502                 - sizeof(xml_memory_page);
503
504         struct xml_memory_string_header
505         {
506                 uint16_t page_offset; // offset from page->data
507                 uint16_t full_size; // 0 if string occupies whole page
508         };
509
510         struct xml_allocator
511         {
512                 xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size)
513                 {
514                 #ifdef PUGIXML_COMPACT
515                         _hash = 0;
516                 #endif
517                 }
518
519                 xml_memory_page* allocate_page(size_t data_size)
520                 {
521                         size_t size = sizeof(xml_memory_page) + data_size;
522
523                         // allocate block with some alignment, leaving memory for worst-case padding
524                         void* memory = xml_memory::allocate(size);
525                         if (!memory) return 0;
526
527                         // prepare page structure
528                         xml_memory_page* page = xml_memory_page::construct(memory);
529                         assert(page);
530
531                         assert(this == _root->allocator);
532                         page->allocator = this;
533
534                         return page;
535                 }
536
537                 static void deallocate_page(xml_memory_page* page)
538                 {
539                         xml_memory::deallocate(page);
540                 }
541
542                 void* allocate_memory_oob(size_t size, xml_memory_page*& out_page);
543
544                 void* allocate_memory(size_t size, xml_memory_page*& out_page)
545                 {
546                         if (PUGI__UNLIKELY(_busy_size + size > xml_memory_page_size))
547                                 return allocate_memory_oob(size, out_page);
548
549                         void* buf = reinterpret_cast<char*>(_root) + sizeof(xml_memory_page) + _busy_size;
550
551                         _busy_size += size;
552
553                         out_page = _root;
554
555                         return buf;
556                 }
557
558         #ifdef PUGIXML_COMPACT
559                 void* allocate_object(size_t size, xml_memory_page*& out_page)
560                 {
561                         void* result = allocate_memory(size + sizeof(uint32_t), out_page);
562                         if (!result) return 0;
563
564                         // adjust for marker
565                         ptrdiff_t offset = static_cast<char*>(result) - reinterpret_cast<char*>(out_page->compact_page_marker);
566
567                         if (PUGI__UNLIKELY(static_cast<uintptr_t>(offset) >= 256 * xml_memory_block_alignment))
568                         {
569                                 // insert new marker
570                                 uint32_t* marker = static_cast<uint32_t*>(result);
571
572                                 *marker = static_cast<uint32_t>(reinterpret_cast<char*>(marker) - reinterpret_cast<char*>(out_page));
573                                 out_page->compact_page_marker = marker;
574
575                                 // since we don't reuse the page space until we reallocate it, we can just pretend that we freed the marker block
576                                 // this will make sure deallocate_memory correctly tracks the size
577                                 out_page->freed_size += sizeof(uint32_t);
578
579                                 return marker + 1;
580                         }
581                         else
582                         {
583                                 // roll back uint32_t part
584                                 _busy_size -= sizeof(uint32_t);
585
586                                 return result;
587                         }
588                 }
589         #else
590                 void* allocate_object(size_t size, xml_memory_page*& out_page)
591                 {
592                         return allocate_memory(size, out_page);
593                 }
594         #endif
595
596                 void deallocate_memory(void* ptr, size_t size, xml_memory_page* page)
597                 {
598                         if (page == _root) page->busy_size = _busy_size;
599
600                         assert(ptr >= reinterpret_cast<char*>(page) + sizeof(xml_memory_page) && ptr < reinterpret_cast<char*>(page) + sizeof(xml_memory_page) + page->busy_size);
601                         (void)!ptr;
602
603                         page->freed_size += size;
604                         assert(page->freed_size <= page->busy_size);
605
606                         if (page->freed_size == page->busy_size)
607                         {
608                                 if (page->next == 0)
609                                 {
610                                         assert(_root == page);
611
612                                         // top page freed, just reset sizes
613                                         page->busy_size = 0;
614                                         page->freed_size = 0;
615
616                                 #ifdef PUGIXML_COMPACT
617                                         // reset compact state to maximize efficiency
618                                         page->compact_string_base = 0;
619                                         page->compact_shared_parent = 0;
620                                         page->compact_page_marker = 0;
621                                 #endif
622
623                                         _busy_size = 0;
624                                 }
625                                 else
626                                 {
627                                         assert(_root != page);
628                                         assert(page->prev);
629
630                                         // remove from the list
631                                         page->prev->next = page->next;
632                                         page->next->prev = page->prev;
633
634                                         // deallocate
635                                         deallocate_page(page);
636                                 }
637                         }
638                 }
639
640                 char_t* allocate_string(size_t length)
641                 {
642                         static const size_t max_encoded_offset = (1 << 16) * xml_memory_block_alignment;
643
644                         PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset);
645
646                         // allocate memory for string and header block
647                         size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t);
648
649                         // round size up to block alignment boundary
650                         size_t full_size = (size + (xml_memory_block_alignment - 1)) & ~(xml_memory_block_alignment - 1);
651
652                         xml_memory_page* page;
653                         xml_memory_string_header* header = static_cast<xml_memory_string_header*>(allocate_memory(full_size, page));
654
655                         if (!header) return 0;
656
657                         // setup header
658                         ptrdiff_t page_offset = reinterpret_cast<char*>(header) - reinterpret_cast<char*>(page) - sizeof(xml_memory_page);
659
660                         assert(page_offset % xml_memory_block_alignment == 0);
661                         assert(page_offset >= 0 && static_cast<size_t>(page_offset) < max_encoded_offset);
662                         header->page_offset = static_cast<uint16_t>(static_cast<size_t>(page_offset) / xml_memory_block_alignment);
663
664                         // full_size == 0 for large strings that occupy the whole page
665                         assert(full_size % xml_memory_block_alignment == 0);
666                         assert(full_size < max_encoded_offset || (page->busy_size == full_size && page_offset == 0));
667                         header->full_size = static_cast<uint16_t>(full_size < max_encoded_offset ? full_size / xml_memory_block_alignment : 0);
668
669                         // round-trip through void* to avoid 'cast increases required alignment of target type' warning
670                         // header is guaranteed a pointer-sized alignment, which should be enough for char_t
671                         return static_cast<char_t*>(static_cast<void*>(header + 1));
672                 }
673
674                 void deallocate_string(char_t* string)
675                 {
676                         // this function casts pointers through void* to avoid 'cast increases required alignment of target type' warnings
677                         // we're guaranteed the proper (pointer-sized) alignment on the input string if it was allocated via allocate_string
678
679                         // get header
680                         xml_memory_string_header* header = static_cast<xml_memory_string_header*>(static_cast<void*>(string)) - 1;
681                         assert(header);
682
683                         // deallocate
684                         size_t page_offset = sizeof(xml_memory_page) + header->page_offset * xml_memory_block_alignment;
685                         xml_memory_page* page = reinterpret_cast<xml_memory_page*>(static_cast<void*>(reinterpret_cast<char*>(header) - page_offset));
686
687                         // if full_size == 0 then this string occupies the whole page
688                         size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size * xml_memory_block_alignment;
689
690                         deallocate_memory(header, full_size, page);
691                 }
692
693                 bool reserve()
694                 {
695                 #ifdef PUGIXML_COMPACT
696                         return _hash->reserve();
697                 #else
698                         return true;
699                 #endif
700                 }
701
702                 xml_memory_page* _root;
703                 size_t _busy_size;
704
705         #ifdef PUGIXML_COMPACT
706                 compact_hash_table* _hash;
707         #endif
708         };
709
710         PUGI__FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page)
711         {
712                 const size_t large_allocation_threshold = xml_memory_page_size / 4;
713
714                 xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size);
715                 out_page = page;
716
717                 if (!page) return 0;
718
719                 if (size <= large_allocation_threshold)
720                 {
721                         _root->busy_size = _busy_size;
722
723                         // insert page at the end of linked list
724                         page->prev = _root;
725                         _root->next = page;
726                         _root = page;
727
728                         _busy_size = size;
729                 }
730                 else
731                 {
732                         // insert page before the end of linked list, so that it is deleted as soon as possible
733                         // the last page is not deleted even if it's empty (see deallocate_memory)
734                         assert(_root->prev);
735
736                         page->prev = _root->prev;
737                         page->next = _root;
738
739                         _root->prev->next = page;
740                         _root->prev = page;
741
742                         page->busy_size = size;
743                 }
744
745                 return reinterpret_cast<char*>(page) + sizeof(xml_memory_page);
746         }
747 PUGI__NS_END
748
749 #ifdef PUGIXML_COMPACT
750 PUGI__NS_BEGIN
751         static const uintptr_t compact_alignment_log2 = 2;
752         static const uintptr_t compact_alignment = 1 << compact_alignment_log2;
753
754         class compact_header
755         {
756         public:
757                 compact_header(xml_memory_page* page, unsigned int flags)
758                 {
759                         PUGI__STATIC_ASSERT(xml_memory_block_alignment == compact_alignment);
760
761                         ptrdiff_t offset = (reinterpret_cast<char*>(this) - reinterpret_cast<char*>(page->compact_page_marker));
762                         assert(offset % compact_alignment == 0 && static_cast<uintptr_t>(offset) < 256 * compact_alignment);
763
764                         _page = static_cast<unsigned char>(offset >> compact_alignment_log2);
765                         _flags = static_cast<unsigned char>(flags);
766                 }
767
768                 void operator&=(uintptr_t mod)
769                 {
770                         _flags &= static_cast<unsigned char>(mod);
771                 }
772
773                 void operator|=(uintptr_t mod)
774                 {
775                         _flags |= static_cast<unsigned char>(mod);
776                 }
777
778                 uintptr_t operator&(uintptr_t mod) const
779                 {
780                         return _flags & mod;
781                 }
782
783                 xml_memory_page* get_page() const
784                 {
785                         // round-trip through void* to silence 'cast increases required alignment of target type' warnings
786                         const char* page_marker = reinterpret_cast<const char*>(this) - (_page << compact_alignment_log2);
787                         const char* page = page_marker - *reinterpret_cast<const uint32_t*>(static_cast<const void*>(page_marker));
788
789                         return const_cast<xml_memory_page*>(reinterpret_cast<const xml_memory_page*>(static_cast<const void*>(page)));
790                 }
791
792         private:
793                 unsigned char _page;
794                 unsigned char _flags;
795         };
796
797         PUGI__FN xml_memory_page* compact_get_page(const void* object, int header_offset)
798         {
799                 const compact_header* header = reinterpret_cast<const compact_header*>(static_cast<const char*>(object) - header_offset);
800
801                 return header->get_page();
802         }
803
804         template <int header_offset, typename T> PUGI__FN_NO_INLINE T* compact_get_value(const void* object)
805         {
806                 return static_cast<T*>(compact_get_page(object, header_offset)->allocator->_hash->find(object));
807         }
808
809         template <int header_offset, typename T> PUGI__FN_NO_INLINE void compact_set_value(const void* object, T* value)
810         {
811                 compact_get_page(object, header_offset)->allocator->_hash->insert(object, value);
812         }
813
814         template <typename T, int header_offset, int start = -126> class compact_pointer
815         {
816         public:
817                 compact_pointer(): _data(0)
818                 {
819                 }
820
821                 void operator=(const compact_pointer& rhs)
822                 {
823                         *this = rhs + 0;
824                 }
825
826                 void operator=(T* value)
827                 {
828                         if (value)
829                         {
830                                 // value is guaranteed to be compact-aligned; 'this' is not
831                                 // our decoding is based on 'this' aligned to compact alignment downwards (see operator T*)
832                                 // so for negative offsets (e.g. -3) we need to adjust the diff by compact_alignment - 1 to
833                                 // compensate for arithmetic shift rounding for negative values
834                                 ptrdiff_t diff = reinterpret_cast<char*>(value) - reinterpret_cast<char*>(this);
835                                 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) - start;
836
837                                 if (static_cast<uintptr_t>(offset) <= 253)
838                                         _data = static_cast<unsigned char>(offset + 1);
839                                 else
840                                 {
841                                         compact_set_value<header_offset>(this, value);
842
843                                         _data = 255;
844                                 }
845                         }
846                         else
847                                 _data = 0;
848                 }
849
850                 operator T*() const
851                 {
852                         if (_data)
853                         {
854                                 if (_data < 255)
855                                 {
856                                         uintptr_t base = reinterpret_cast<uintptr_t>(this) & ~(compact_alignment - 1);
857
858                                         return reinterpret_cast<T*>(base + (_data - 1 + start) * compact_alignment);
859                                 }
860                                 else
861                                         return compact_get_value<header_offset, T>(this);
862                         }
863                         else
864                                 return 0;
865                 }
866
867                 T* operator->() const
868                 {
869                         return *this;
870                 }
871
872         private:
873                 unsigned char _data;
874         };
875
876         template <typename T, int header_offset> class compact_pointer_parent
877         {
878         public:
879                 compact_pointer_parent(): _data(0)
880                 {
881                 }
882
883                 void operator=(const compact_pointer_parent& rhs)
884                 {
885                         *this = rhs + 0;
886                 }
887
888                 void operator=(T* value)
889                 {
890                         if (value)
891                         {
892                                 // value is guaranteed to be compact-aligned; 'this' is not
893                                 // our decoding is based on 'this' aligned to compact alignment downwards (see operator T*)
894                                 // so for negative offsets (e.g. -3) we need to adjust the diff by compact_alignment - 1 to
895                                 // compensate for arithmetic shift behavior for negative values
896                                 ptrdiff_t diff = reinterpret_cast<char*>(value) - reinterpret_cast<char*>(this);
897                                 ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) + 65533;
898
899                                 if (static_cast<uintptr_t>(offset) <= 65533)
900                                 {
901                                         _data = static_cast<unsigned short>(offset + 1);
902                                 }
903                                 else
904                                 {
905                                         xml_memory_page* page = compact_get_page(this, header_offset);
906
907                                         if (PUGI__UNLIKELY(page->compact_shared_parent == 0))
908                                                 page->compact_shared_parent = value;
909
910                                         if (page->compact_shared_parent == value)
911                                         {
912                                                 _data = 65534;
913                                         }
914                                         else
915                                         {
916                                                 compact_set_value<header_offset>(this, value);
917
918                                                 _data = 65535;
919                                         }
920                                 }
921                         }
922                         else
923                         {
924                                 _data = 0;
925                         }
926                 }
927
928                 operator T*() const
929                 {
930                         if (_data)
931                         {
932                                 if (_data < 65534)
933                                 {
934                                         uintptr_t base = reinterpret_cast<uintptr_t>(this) & ~(compact_alignment - 1);
935
936                                         return reinterpret_cast<T*>(base + (_data - 1 - 65533) * compact_alignment);
937                                 }
938                                 else if (_data == 65534)
939                                         return static_cast<T*>(compact_get_page(this, header_offset)->compact_shared_parent);
940                                 else
941                                         return compact_get_value<header_offset, T>(this);
942                         }
943                         else
944                                 return 0;
945                 }
946
947                 T* operator->() const
948                 {
949                         return *this;
950                 }
951
952         private:
953                 uint16_t _data;
954         };
955
956         template <int header_offset, int base_offset> class compact_string
957         {
958         public:
959                 compact_string(): _data(0)
960                 {
961                 }
962
963                 void operator=(const compact_string& rhs)
964                 {
965                         *this = rhs + 0;
966                 }
967
968                 void operator=(char_t* value)
969                 {
970                         if (value)
971                         {
972                                 xml_memory_page* page = compact_get_page(this, header_offset);
973
974                                 if (PUGI__UNLIKELY(page->compact_string_base == 0))
975                                         page->compact_string_base = value;
976
977                                 ptrdiff_t offset = value - page->compact_string_base;
978
979                                 if (static_cast<uintptr_t>(offset) < (65535 << 7))
980                                 {
981                                         // round-trip through void* to silence 'cast increases required alignment of target type' warnings
982                                         uint16_t* base = reinterpret_cast<uint16_t*>(static_cast<void*>(reinterpret_cast<char*>(this) - base_offset));
983
984                                         if (*base == 0)
985                                         {
986                                                 *base = static_cast<uint16_t>((offset >> 7) + 1);
987                                                 _data = static_cast<unsigned char>((offset & 127) + 1);
988                                         }
989                                         else
990                                         {
991                                                 ptrdiff_t remainder = offset - ((*base - 1) << 7);
992
993                                                 if (static_cast<uintptr_t>(remainder) <= 253)
994                                                 {
995                                                         _data = static_cast<unsigned char>(remainder + 1);
996                                                 }
997                                                 else
998                                                 {
999                                                         compact_set_value<header_offset>(this, value);
1000
1001                                                         _data = 255;
1002                                                 }
1003                                         }
1004                                 }
1005                                 else
1006                                 {
1007                                         compact_set_value<header_offset>(this, value);
1008
1009                                         _data = 255;
1010                                 }
1011                         }
1012                         else
1013                         {
1014                                 _data = 0;
1015                         }
1016                 }
1017
1018                 operator char_t*() const
1019                 {
1020                         if (_data)
1021                         {
1022                                 if (_data < 255)
1023                                 {
1024                                         xml_memory_page* page = compact_get_page(this, header_offset);
1025
1026                                         // round-trip through void* to silence 'cast increases required alignment of target type' warnings
1027                                         const uint16_t* base = reinterpret_cast<const uint16_t*>(static_cast<const void*>(reinterpret_cast<const char*>(this) - base_offset));
1028                                         assert(*base);
1029
1030                                         ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1);
1031
1032                                         return page->compact_string_base + offset;
1033                                 }
1034                                 else
1035                                 {
1036                                         return compact_get_value<header_offset, char_t>(this);
1037                                 }
1038                         }
1039                         else
1040                                 return 0;
1041                 }
1042
1043         private:
1044                 unsigned char _data;
1045         };
1046 PUGI__NS_END
1047 #endif
1048
1049 #ifdef PUGIXML_COMPACT
1050 namespace pugi
1051 {
1052         struct xml_attribute_struct
1053         {
1054                 xml_attribute_struct(impl::xml_memory_page* page): header(page, 0), namevalue_base(0)
1055                 {
1056                         PUGI__STATIC_ASSERT(sizeof(xml_attribute_struct) == 8);
1057                 }
1058
1059                 impl::compact_header header;
1060
1061                 uint16_t namevalue_base;
1062
1063                 impl::compact_string<4, 2> name;
1064                 impl::compact_string<5, 3> value;
1065
1066                 impl::compact_pointer<xml_attribute_struct, 6> prev_attribute_c;
1067                 impl::compact_pointer<xml_attribute_struct, 7, 0> next_attribute;
1068         };
1069
1070         struct xml_node_struct
1071         {
1072                 xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type), namevalue_base(0)
1073                 {
1074                         PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 12);
1075                 }
1076
1077                 impl::compact_header header;
1078
1079                 uint16_t namevalue_base;
1080
1081                 impl::compact_string<4, 2> name;
1082                 impl::compact_string<5, 3> value;
1083
1084                 impl::compact_pointer_parent<xml_node_struct, 6> parent;
1085
1086                 impl::compact_pointer<xml_node_struct, 8, 0> first_child;
1087
1088                 impl::compact_pointer<xml_node_struct,  9>    prev_sibling_c;
1089                 impl::compact_pointer<xml_node_struct, 10, 0> next_sibling;
1090
1091                 impl::compact_pointer<xml_attribute_struct, 11, 0> first_attribute;
1092         };
1093 }
1094 #else
1095 namespace pugi
1096 {
1097         struct xml_attribute_struct
1098         {
1099                 xml_attribute_struct(impl::xml_memory_page* page): name(0), value(0), prev_attribute_c(0), next_attribute(0)
1100                 {
1101                         header = PUGI__GETHEADER_IMPL(this, page, 0);
1102                 }
1103
1104                 uintptr_t header;
1105
1106                 char_t* name;
1107                 char_t* value;
1108
1109                 xml_attribute_struct* prev_attribute_c;
1110                 xml_attribute_struct* next_attribute;
1111         };
1112
1113         struct xml_node_struct
1114         {
1115                 xml_node_struct(impl::xml_memory_page* page, xml_node_type type): name(0), value(0), parent(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0)
1116                 {
1117                         header = PUGI__GETHEADER_IMPL(this, page, type);
1118                 }
1119
1120                 uintptr_t header;
1121
1122                 char_t* name;
1123                 char_t* value;
1124
1125                 xml_node_struct* parent;
1126
1127                 xml_node_struct* first_child;
1128
1129                 xml_node_struct* prev_sibling_c;
1130                 xml_node_struct* next_sibling;
1131
1132                 xml_attribute_struct* first_attribute;
1133         };
1134 }
1135 #endif
1136
1137 PUGI__NS_BEGIN
1138         struct xml_extra_buffer
1139         {
1140                 char_t* buffer;
1141                 xml_extra_buffer* next;
1142         };
1143
1144         struct xml_document_struct: public xml_node_struct, public xml_allocator
1145         {
1146                 xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0)
1147                 {
1148                 }
1149
1150                 const char_t* buffer;
1151
1152                 xml_extra_buffer* extra_buffers;
1153
1154         #ifdef PUGIXML_COMPACT
1155                 compact_hash_table hash;
1156         #endif
1157         };
1158
1159         template <typename Object> inline xml_allocator& get_allocator(const Object* object)
1160         {
1161                 assert(object);
1162
1163                 return *PUGI__GETPAGE(object)->allocator;
1164         }
1165
1166         template <typename Object> inline xml_document_struct& get_document(const Object* object)
1167         {
1168                 assert(object);
1169
1170                 return *static_cast<xml_document_struct*>(PUGI__GETPAGE(object)->allocator);
1171         }
1172 PUGI__NS_END
1173
1174 // Low-level DOM operations
1175 PUGI__NS_BEGIN
1176         inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc)
1177         {
1178                 xml_memory_page* page;
1179                 void* memory = alloc.allocate_object(sizeof(xml_attribute_struct), page);
1180                 if (!memory) return 0;
1181
1182                 return new (memory) xml_attribute_struct(page);
1183         }
1184
1185         inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type)
1186         {
1187                 xml_memory_page* page;
1188                 void* memory = alloc.allocate_object(sizeof(xml_node_struct), page);
1189                 if (!memory) return 0;
1190
1191                 return new (memory) xml_node_struct(page, type);
1192         }
1193
1194         inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc)
1195         {
1196                 if (a->header & impl::xml_memory_page_name_allocated_mask)
1197                         alloc.deallocate_string(a->name);
1198
1199                 if (a->header & impl::xml_memory_page_value_allocated_mask)
1200                         alloc.deallocate_string(a->value);
1201
1202                 alloc.deallocate_memory(a, sizeof(xml_attribute_struct), PUGI__GETPAGE(a));
1203         }
1204
1205         inline void destroy_node(xml_node_struct* n, xml_allocator& alloc)
1206         {
1207                 if (n->header & impl::xml_memory_page_name_allocated_mask)
1208                         alloc.deallocate_string(n->name);
1209
1210                 if (n->header & impl::xml_memory_page_value_allocated_mask)
1211                         alloc.deallocate_string(n->value);
1212
1213                 for (xml_attribute_struct* attr = n->first_attribute; attr; )
1214                 {
1215                         xml_attribute_struct* next = attr->next_attribute;
1216
1217                         destroy_attribute(attr, alloc);
1218
1219                         attr = next;
1220                 }
1221
1222                 for (xml_node_struct* child = n->first_child; child; )
1223                 {
1224                         xml_node_struct* next = child->next_sibling;
1225
1226                         destroy_node(child, alloc);
1227
1228                         child = next;
1229                 }
1230
1231                 alloc.deallocate_memory(n, sizeof(xml_node_struct), PUGI__GETPAGE(n));
1232         }
1233
1234         inline void append_node(xml_node_struct* child, xml_node_struct* node)
1235         {
1236                 child->parent = node;
1237
1238                 xml_node_struct* head = node->first_child;
1239
1240                 if (head)
1241                 {
1242                         xml_node_struct* tail = head->prev_sibling_c;
1243
1244                         tail->next_sibling = child;
1245                         child->prev_sibling_c = tail;
1246                         head->prev_sibling_c = child;
1247                 }
1248                 else
1249                 {
1250                         node->first_child = child;
1251                         child->prev_sibling_c = child;
1252                 }
1253         }
1254
1255         inline void prepend_node(xml_node_struct* child, xml_node_struct* node)
1256         {
1257                 child->parent = node;
1258
1259                 xml_node_struct* head = node->first_child;
1260
1261                 if (head)
1262                 {
1263                         child->prev_sibling_c = head->prev_sibling_c;
1264                         head->prev_sibling_c = child;
1265                 }
1266                 else
1267                         child->prev_sibling_c = child;
1268
1269                 child->next_sibling = head;
1270                 node->first_child = child;
1271         }
1272
1273         inline void insert_node_after(xml_node_struct* child, xml_node_struct* node)
1274         {
1275                 xml_node_struct* parent = node->parent;
1276
1277                 child->parent = parent;
1278
1279                 if (node->next_sibling)
1280                         node->next_sibling->prev_sibling_c = child;
1281                 else
1282                         parent->first_child->prev_sibling_c = child;
1283
1284                 child->next_sibling = node->next_sibling;
1285                 child->prev_sibling_c = node;
1286
1287                 node->next_sibling = child;
1288         }
1289
1290         inline void insert_node_before(xml_node_struct* child, xml_node_struct* node)
1291         {
1292                 xml_node_struct* parent = node->parent;
1293
1294                 child->parent = parent;
1295
1296                 if (node->prev_sibling_c->next_sibling)
1297                         node->prev_sibling_c->next_sibling = child;
1298                 else
1299                         parent->first_child = child;
1300
1301                 child->prev_sibling_c = node->prev_sibling_c;
1302                 child->next_sibling = node;
1303
1304                 node->prev_sibling_c = child;
1305         }
1306
1307         inline void remove_node(xml_node_struct* node)
1308         {
1309                 xml_node_struct* parent = node->parent;
1310
1311                 if (node->next_sibling)
1312                         node->next_sibling->prev_sibling_c = node->prev_sibling_c;
1313                 else
1314                         parent->first_child->prev_sibling_c = node->prev_sibling_c;
1315
1316                 if (node->prev_sibling_c->next_sibling)
1317                         node->prev_sibling_c->next_sibling = node->next_sibling;
1318                 else
1319                         parent->first_child = node->next_sibling;
1320
1321                 node->parent = 0;
1322                 node->prev_sibling_c = 0;
1323                 node->next_sibling = 0;
1324         }
1325
1326         inline void append_attribute(xml_attribute_struct* attr, xml_node_struct* node)
1327         {
1328                 xml_attribute_struct* head = node->first_attribute;
1329
1330                 if (head)
1331                 {
1332                         xml_attribute_struct* tail = head->prev_attribute_c;
1333
1334                         tail->next_attribute = attr;
1335                         attr->prev_attribute_c = tail;
1336                         head->prev_attribute_c = attr;
1337                 }
1338                 else
1339                 {
1340                         node->first_attribute = attr;
1341                         attr->prev_attribute_c = attr;
1342                 }
1343         }
1344
1345         inline void prepend_attribute(xml_attribute_struct* attr, xml_node_struct* node)
1346         {
1347                 xml_attribute_struct* head = node->first_attribute;
1348
1349                 if (head)
1350                 {
1351                         attr->prev_attribute_c = head->prev_attribute_c;
1352                         head->prev_attribute_c = attr;
1353                 }
1354                 else
1355                         attr->prev_attribute_c = attr;
1356
1357                 attr->next_attribute = head;
1358                 node->first_attribute = attr;
1359         }
1360
1361         inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
1362         {
1363                 if (place->next_attribute)
1364                         place->next_attribute->prev_attribute_c = attr;
1365                 else
1366                         node->first_attribute->prev_attribute_c = attr;
1367
1368                 attr->next_attribute = place->next_attribute;
1369                 attr->prev_attribute_c = place;
1370                 place->next_attribute = attr;
1371         }
1372
1373         inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
1374         {
1375                 if (place->prev_attribute_c->next_attribute)
1376                         place->prev_attribute_c->next_attribute = attr;
1377                 else
1378                         node->first_attribute = attr;
1379
1380                 attr->prev_attribute_c = place->prev_attribute_c;
1381                 attr->next_attribute = place;
1382                 place->prev_attribute_c = attr;
1383         }
1384
1385         inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node)
1386         {
1387                 if (attr->next_attribute)
1388                         attr->next_attribute->prev_attribute_c = attr->prev_attribute_c;
1389                 else
1390                         node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
1391
1392                 if (attr->prev_attribute_c->next_attribute)
1393                         attr->prev_attribute_c->next_attribute = attr->next_attribute;
1394                 else
1395                         node->first_attribute = attr->next_attribute;
1396
1397                 attr->prev_attribute_c = 0;
1398                 attr->next_attribute = 0;
1399         }
1400
1401         PUGI__FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element)
1402         {
1403                 if (!alloc.reserve()) return 0;
1404
1405                 xml_node_struct* child = allocate_node(alloc, type);
1406                 if (!child) return 0;
1407
1408                 append_node(child, node);
1409
1410                 return child;
1411         }
1412
1413         PUGI__FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc)
1414         {
1415                 if (!alloc.reserve()) return 0;
1416
1417                 xml_attribute_struct* attr = allocate_attribute(alloc);
1418                 if (!attr) return 0;
1419
1420                 append_attribute(attr, node);
1421
1422                 return attr;
1423         }
1424 PUGI__NS_END
1425
1426 // Helper classes for code generation
1427 PUGI__NS_BEGIN
1428         struct opt_false
1429         {
1430                 enum { value = 0 };
1431         };
1432
1433         struct opt_true
1434         {
1435                 enum { value = 1 };
1436         };
1437 PUGI__NS_END
1438
1439 // Unicode utilities
1440 PUGI__NS_BEGIN
1441         inline uint16_t endian_swap(uint16_t value)
1442         {
1443                 return static_cast<uint16_t>(((value & 0xff) << 8) | (value >> 8));
1444         }
1445
1446         inline uint32_t endian_swap(uint32_t value)
1447         {
1448                 return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24);
1449         }
1450
1451         struct utf8_counter
1452         {
1453                 typedef size_t value_type;
1454
1455                 static value_type low(value_type result, uint32_t ch)
1456                 {
1457                         // U+0000..U+007F
1458                         if (ch < 0x80) return result + 1;
1459                         // U+0080..U+07FF
1460                         else if (ch < 0x800) return result + 2;
1461                         // U+0800..U+FFFF
1462                         else return result + 3;
1463                 }
1464
1465                 static value_type high(value_type result, uint32_t)
1466                 {
1467                         // U+10000..U+10FFFF
1468                         return result + 4;
1469                 }
1470         };
1471
1472         struct utf8_writer
1473         {
1474                 typedef uint8_t* value_type;
1475
1476                 static value_type low(value_type result, uint32_t ch)
1477                 {
1478                         // U+0000..U+007F
1479                         if (ch < 0x80)
1480                         {
1481                                 *result = static_cast<uint8_t>(ch);
1482                                 return result + 1;
1483                         }
1484                         // U+0080..U+07FF
1485                         else if (ch < 0x800)
1486                         {
1487                                 result[0] = static_cast<uint8_t>(0xC0 | (ch >> 6));
1488                                 result[1] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
1489                                 return result + 2;
1490                         }
1491                         // U+0800..U+FFFF
1492                         else
1493                         {
1494                                 result[0] = static_cast<uint8_t>(0xE0 | (ch >> 12));
1495                                 result[1] = static_cast<uint8_t>(0x80 | ((ch >> 6) & 0x3F));
1496                                 result[2] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
1497                                 return result + 3;
1498                         }
1499                 }
1500
1501                 static value_type high(value_type result, uint32_t ch)
1502                 {
1503                         // U+10000..U+10FFFF
1504                         result[0] = static_cast<uint8_t>(0xF0 | (ch >> 18));
1505                         result[1] = static_cast<uint8_t>(0x80 | ((ch >> 12) & 0x3F));
1506                         result[2] = static_cast<uint8_t>(0x80 | ((ch >> 6) & 0x3F));
1507                         result[3] = static_cast<uint8_t>(0x80 | (ch & 0x3F));
1508                         return result + 4;
1509                 }
1510
1511                 static value_type any(value_type result, uint32_t ch)
1512                 {
1513                         return (ch < 0x10000) ? low(result, ch) : high(result, ch);
1514                 }
1515         };
1516
1517         struct utf16_counter
1518         {
1519                 typedef size_t value_type;
1520
1521                 static value_type low(value_type result, uint32_t)
1522                 {
1523                         return result + 1;
1524                 }
1525
1526                 static value_type high(value_type result, uint32_t)
1527                 {
1528                         return result + 2;
1529                 }
1530         };
1531
1532         struct utf16_writer
1533         {
1534                 typedef uint16_t* value_type;
1535
1536                 static value_type low(value_type result, uint32_t ch)
1537                 {
1538                         *result = static_cast<uint16_t>(ch);
1539
1540                         return result + 1;
1541                 }
1542
1543                 static value_type high(value_type result, uint32_t ch)
1544                 {
1545                         uint32_t msh = static_cast<uint32_t>(ch - 0x10000) >> 10;
1546                         uint32_t lsh = static_cast<uint32_t>(ch - 0x10000) & 0x3ff;
1547
1548                         result[0] = static_cast<uint16_t>(0xD800 + msh);
1549                         result[1] = static_cast<uint16_t>(0xDC00 + lsh);
1550
1551                         return result + 2;
1552                 }
1553
1554                 static value_type any(value_type result, uint32_t ch)
1555                 {
1556                         return (ch < 0x10000) ? low(result, ch) : high(result, ch);
1557                 }
1558         };
1559
1560         struct utf32_counter
1561         {
1562                 typedef size_t value_type;
1563
1564                 static value_type low(value_type result, uint32_t)
1565                 {
1566                         return result + 1;
1567                 }
1568
1569                 static value_type high(value_type result, uint32_t)
1570                 {
1571                         return result + 1;
1572                 }
1573         };
1574
1575         struct utf32_writer
1576         {
1577                 typedef uint32_t* value_type;
1578
1579                 static value_type low(value_type result, uint32_t ch)
1580                 {
1581                         *result = ch;
1582
1583                         return result + 1;
1584                 }
1585
1586                 static value_type high(value_type result, uint32_t ch)
1587                 {
1588                         *result = ch;
1589
1590                         return result + 1;
1591                 }
1592
1593                 static value_type any(value_type result, uint32_t ch)
1594                 {
1595                         *result = ch;
1596
1597                         return result + 1;
1598                 }
1599         };
1600
1601         struct latin1_writer
1602         {
1603                 typedef uint8_t* value_type;
1604
1605                 static value_type low(value_type result, uint32_t ch)
1606                 {
1607                         *result = static_cast<uint8_t>(ch > 255 ? '?' : ch);
1608
1609                         return result + 1;
1610                 }
1611
1612                 static value_type high(value_type result, uint32_t ch)
1613                 {
1614                         (void)ch;
1615
1616                         *result = '?';
1617
1618                         return result + 1;
1619                 }
1620         };
1621
1622         struct utf8_decoder
1623         {
1624                 typedef uint8_t type;
1625
1626                 template <typename Traits> static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits)
1627                 {
1628                         const uint8_t utf8_byte_mask = 0x3f;
1629
1630                         while (size)
1631                         {
1632                                 uint8_t lead = *data;
1633
1634                                 // 0xxxxxxx -> U+0000..U+007F
1635                                 if (lead < 0x80)
1636                                 {
1637                                         result = Traits::low(result, lead);
1638                                         data += 1;
1639                                         size -= 1;
1640
1641                                         // process aligned single-byte (ascii) blocks
1642                                         if ((reinterpret_cast<uintptr_t>(data) & 3) == 0)
1643                                         {
1644                                                 // round-trip through void* to silence 'cast increases required alignment of target type' warnings
1645                                                 while (size >= 4 && (*static_cast<const uint32_t*>(static_cast<const void*>(data)) & 0x80808080) == 0)
1646                                                 {
1647                                                         result = Traits::low(result, data[0]);
1648                                                         result = Traits::low(result, data[1]);
1649                                                         result = Traits::low(result, data[2]);
1650                                                         result = Traits::low(result, data[3]);
1651                                                         data += 4;
1652                                                         size -= 4;
1653                                                 }
1654                                         }
1655                                 }
1656                                 // 110xxxxx -> U+0080..U+07FF
1657                                 else if (static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80)
1658                                 {
1659                                         result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask));
1660                                         data += 2;
1661                                         size -= 2;
1662                                 }
1663                                 // 1110xxxx -> U+0800-U+FFFF
1664                                 else if (static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80)
1665                                 {
1666                                         result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask));
1667                                         data += 3;
1668                                         size -= 3;
1669                                 }
1670                                 // 11110xxx -> U+10000..U+10FFFF
1671                                 else if (static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80)
1672                                 {
1673                                         result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask));
1674                                         data += 4;
1675                                         size -= 4;
1676                                 }
1677                                 // 10xxxxxx or 11111xxx -> invalid
1678                                 else
1679                                 {
1680                                         data += 1;
1681                                         size -= 1;
1682                                 }
1683                         }
1684
1685                         return result;
1686                 }
1687         };
1688
1689         template <typename opt_swap> struct utf16_decoder
1690         {
1691                 typedef uint16_t type;
1692
1693                 template <typename Traits> static inline typename Traits::value_type process(const uint16_t* data, size_t size, typename Traits::value_type result, Traits)
1694                 {
1695                         while (size)
1696                         {
1697                                 uint16_t lead = opt_swap::value ? endian_swap(*data) : *data;
1698
1699                                 // U+0000..U+D7FF
1700                                 if (lead < 0xD800)
1701                                 {
1702                                         result = Traits::low(result, lead);
1703                                         data += 1;
1704                                         size -= 1;
1705                                 }
1706                                 // U+E000..U+FFFF
1707                                 else if (static_cast<unsigned int>(lead - 0xE000) < 0x2000)
1708                                 {
1709                                         result = Traits::low(result, lead);
1710                                         data += 1;
1711                                         size -= 1;
1712                                 }
1713                                 // surrogate pair lead
1714                                 else if (static_cast<unsigned int>(lead - 0xD800) < 0x400 && size >= 2)
1715                                 {
1716                                         uint16_t next = opt_swap::value ? endian_swap(data[1]) : data[1];
1717
1718                                         if (static_cast<unsigned int>(next - 0xDC00) < 0x400)
1719                                         {
1720                                                 result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff));
1721                                                 data += 2;
1722                                                 size -= 2;
1723                                         }
1724                                         else
1725                                         {
1726                                                 data += 1;
1727                                                 size -= 1;
1728                                         }
1729                                 }
1730                                 else
1731                                 {
1732                                         data += 1;
1733                                         size -= 1;
1734                                 }
1735                         }
1736
1737                         return result;
1738                 }
1739         };
1740
1741         template <typename opt_swap> struct utf32_decoder
1742         {
1743                 typedef uint32_t type;
1744
1745                 template <typename Traits> static inline typename Traits::value_type process(const uint32_t* data, size_t size, typename Traits::value_type result, Traits)
1746                 {
1747                         while (size)
1748                         {
1749                                 uint32_t lead = opt_swap::value ? endian_swap(*data) : *data;
1750
1751                                 // U+0000..U+FFFF
1752                                 if (lead < 0x10000)
1753                                 {
1754                                         result = Traits::low(result, lead);
1755                                         data += 1;
1756                                         size -= 1;
1757                                 }
1758                                 // U+10000..U+10FFFF
1759                                 else
1760                                 {
1761                                         result = Traits::high(result, lead);
1762                                         data += 1;
1763                                         size -= 1;
1764                                 }
1765                         }
1766
1767                         return result;
1768                 }
1769         };
1770
1771         struct latin1_decoder
1772         {
1773                 typedef uint8_t type;
1774
1775                 template <typename Traits> static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits)
1776                 {
1777                         while (size)
1778                         {
1779                                 result = Traits::low(result, *data);
1780                                 data += 1;
1781                                 size -= 1;
1782                         }
1783
1784                         return result;
1785                 }
1786         };
1787
1788         template <size_t size> struct wchar_selector;
1789
1790         template <> struct wchar_selector<2>
1791         {
1792                 typedef uint16_t type;
1793                 typedef utf16_counter counter;
1794                 typedef utf16_writer writer;
1795                 typedef utf16_decoder<opt_false> decoder;
1796         };
1797
1798         template <> struct wchar_selector<4>
1799         {
1800                 typedef uint32_t type;
1801                 typedef utf32_counter counter;
1802                 typedef utf32_writer writer;
1803                 typedef utf32_decoder<opt_false> decoder;
1804         };
1805
1806         typedef wchar_selector<sizeof(wchar_t)>::counter wchar_counter;
1807         typedef wchar_selector<sizeof(wchar_t)>::writer wchar_writer;
1808
1809         struct wchar_decoder
1810         {
1811                 typedef wchar_t type;
1812
1813                 template <typename Traits> static inline typename Traits::value_type process(const wchar_t* data, size_t size, typename Traits::value_type result, Traits traits)
1814                 {
1815                         typedef wchar_selector<sizeof(wchar_t)>::decoder decoder;
1816
1817                         return decoder::process(reinterpret_cast<const typename decoder::type*>(data), size, result, traits);
1818                 }
1819         };
1820
1821 #ifdef PUGIXML_WCHAR_MODE
1822         PUGI__FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length)
1823         {
1824                 for (size_t i = 0; i < length; ++i)
1825                         result[i] = static_cast<wchar_t>(endian_swap(static_cast<wchar_selector<sizeof(wchar_t)>::type>(data[i])));
1826         }
1827 #endif
1828 PUGI__NS_END
1829
1830 PUGI__NS_BEGIN
1831         enum chartype_t
1832         {
1833                 ct_parse_pcdata = 1,    // \0, &, \r, <
1834                 ct_parse_attr = 2,              // \0, &, \r, ', "
1835                 ct_parse_attr_ws = 4,   // \0, &, \r, ', ", \n, tab
1836                 ct_space = 8,                   // \r, \n, space, tab
1837                 ct_parse_cdata = 16,    // \0, ], >, \r
1838                 ct_parse_comment = 32,  // \0, -, >, \r
1839                 ct_symbol = 64,                 // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, .
1840                 ct_start_symbol = 128   // Any symbol > 127, a-z, A-Z, _, :
1841         };
1842
1843         static const unsigned char chartype_table[256] =
1844         {
1845                 55,  0,   0,   0,   0,   0,   0,   0,      0,   12,  12,  0,   0,   63,  0,   0,   // 0-15
1846                 0,   0,   0,   0,   0,   0,   0,   0,      0,   0,   0,   0,   0,   0,   0,   0,   // 16-31
1847                 8,   0,   6,   0,   0,   0,   7,   6,      0,   0,   0,   0,   0,   96,  64,  0,   // 32-47
1848                 64,  64,  64,  64,  64,  64,  64,  64,     64,  64,  192, 0,   1,   0,   48,  0,   // 48-63
1849                 0,   192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192, // 64-79
1850                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 0,   0,   16,  0,   192, // 80-95
1851                 0,   192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192, // 96-111
1852                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 0, 0, 0, 0, 0,           // 112-127
1853
1854                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192, // 128+
1855                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192,
1856                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192,
1857                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192,
1858                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192,
1859                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192,
1860                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192,
1861                 192, 192, 192, 192, 192, 192, 192, 192,    192, 192, 192, 192, 192, 192, 192, 192
1862         };
1863
1864         enum chartypex_t
1865         {
1866                 ctx_special_pcdata = 1,   // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, >
1867                 ctx_special_attr = 2,     // Any symbol >= 0 and < 32, &, <, ", '
1868                 ctx_start_symbol = 4,     // Any symbol > 127, a-z, A-Z, _
1869                 ctx_digit = 8,                    // 0-9
1870                 ctx_symbol = 16                   // Any symbol > 127, a-z, A-Z, 0-9, _, -, .
1871         };
1872
1873         static const unsigned char chartypex_table[256] =
1874         {
1875                 3,  3,  3,  3,  3,  3,  3,  3,     3,  2,  2,  3,  3,  2,  3,  3,     // 0-15
1876                 3,  3,  3,  3,  3,  3,  3,  3,     3,  3,  3,  3,  3,  3,  3,  3,     // 16-31
1877                 0,  0,  2,  0,  0,  0,  3,  2,     0,  0,  0,  0,  0, 16, 16,  0,     // 32-47
1878                 24, 24, 24, 24, 24, 24, 24, 24,    24, 24, 0,  0,  3,  0,  1,  0,     // 48-63
1879
1880                 0,  20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,    // 64-79
1881                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 0,  0,  0,  0,  20,    // 80-95
1882                 0,  20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,    // 96-111
1883                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 0,  0,  0,  0,  0,     // 112-127
1884
1885                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,    // 128+
1886                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,
1887                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,
1888                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,
1889                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,
1890                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,
1891                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20,
1892                 20, 20, 20, 20, 20, 20, 20, 20,    20, 20, 20, 20, 20, 20, 20, 20
1893         };
1894
1895 #ifdef PUGIXML_WCHAR_MODE
1896         #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct))
1897 #else
1898         #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct))
1899 #endif
1900
1901         #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table)
1902         #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table)
1903
1904         PUGI__FN bool is_little_endian()
1905         {
1906                 unsigned int ui = 1;
1907
1908                 return *reinterpret_cast<unsigned char*>(&ui) == 1;
1909         }
1910
1911         PUGI__FN xml_encoding get_wchar_encoding()
1912         {
1913                 PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4);
1914
1915                 if (sizeof(wchar_t) == 2)
1916                         return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
1917                 else
1918                         return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
1919         }
1920
1921         PUGI__FN bool parse_declaration_encoding(const uint8_t* data, size_t size, const uint8_t*& out_encoding, size_t& out_length)
1922         {
1923         #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; }
1924         #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; }
1925
1926                 // check if we have a non-empty XML declaration
1927                 if (size < 6 || !((data[0] == '<') & (data[1] == '?') & (data[2] == 'x') & (data[3] == 'm') & (data[4] == 'l') && PUGI__IS_CHARTYPE(data[5], ct_space)))
1928                         return false;
1929
1930                 // scan XML declaration until the encoding field
1931                 for (size_t i = 6; i + 1 < size; ++i)
1932                 {
1933                         // declaration can not contain ? in quoted values
1934                         if (data[i] == '?')
1935                                 return false;
1936
1937                         if (data[i] == 'e' && data[i + 1] == 'n')
1938                         {
1939                                 size_t offset = i;
1940
1941                                 // encoding follows the version field which can't contain 'en' so this has to be the encoding if XML is well formed
1942                                 PUGI__SCANCHAR('e'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('c'); PUGI__SCANCHAR('o');
1943                                 PUGI__SCANCHAR('d'); PUGI__SCANCHAR('i'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('g');
1944
1945                                 // S? = S?
1946                                 PUGI__SCANCHARTYPE(ct_space);
1947                                 PUGI__SCANCHAR('=');
1948                                 PUGI__SCANCHARTYPE(ct_space);
1949
1950                                 // the only two valid delimiters are ' and "
1951                                 uint8_t delimiter = (offset < size && data[offset] == '"') ? '"' : '\'';
1952
1953                                 PUGI__SCANCHAR(delimiter);
1954
1955                                 size_t start = offset;
1956
1957                                 out_encoding = data + offset;
1958
1959                                 PUGI__SCANCHARTYPE(ct_symbol);
1960
1961                                 out_length = offset - start;
1962
1963                                 PUGI__SCANCHAR(delimiter);
1964
1965                                 return true;
1966                         }
1967                 }
1968
1969                 return false;
1970
1971         #undef PUGI__SCANCHAR
1972         #undef PUGI__SCANCHARTYPE
1973         }
1974
1975         PUGI__FN xml_encoding guess_buffer_encoding(const uint8_t* data, size_t size)
1976         {
1977                 // skip encoding autodetection if input buffer is too small
1978                 if (size < 4) return encoding_utf8;
1979
1980                 uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3];
1981
1982                 // look for BOM in first few bytes
1983                 if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be;
1984                 if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le;
1985                 if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be;
1986                 if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le;
1987                 if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf) return encoding_utf8;
1988
1989                 // look for <, <? or <?xm in various encodings
1990                 if (d0 == 0 && d1 == 0 && d2 == 0 && d3 == 0x3c) return encoding_utf32_be;
1991                 if (d0 == 0x3c && d1 == 0 && d2 == 0 && d3 == 0) return encoding_utf32_le;
1992                 if (d0 == 0 && d1 == 0x3c && d2 == 0 && d3 == 0x3f) return encoding_utf16_be;
1993                 if (d0 == 0x3c && d1 == 0 && d2 == 0x3f && d3 == 0) return encoding_utf16_le;
1994
1995                 // look for utf16 < followed by node name (this may fail, but is better than utf8 since it's zero terminated so early)
1996                 if (d0 == 0 && d1 == 0x3c) return encoding_utf16_be;
1997                 if (d0 == 0x3c && d1 == 0) return encoding_utf16_le;
1998
1999                 // no known BOM detected; parse declaration
2000                 const uint8_t* enc = 0;
2001                 size_t enc_length = 0;
2002
2003                 if (d0 == 0x3c && d1 == 0x3f && d2 == 0x78 && d3 == 0x6d && parse_declaration_encoding(data, size, enc, enc_length))
2004                 {
2005                         // iso-8859-1 (case-insensitive)
2006                         if (enc_length == 10
2007                                 && (enc[0] | ' ') == 'i' && (enc[1] | ' ') == 's' && (enc[2] | ' ') == 'o'
2008                                 && enc[3] == '-' && enc[4] == '8' && enc[5] == '8' && enc[6] == '5' && enc[7] == '9'
2009                                 && enc[8] == '-' && enc[9] == '1')
2010                                 return encoding_latin1;
2011
2012                         // latin1 (case-insensitive)
2013                         if (enc_length == 6
2014                                 && (enc[0] | ' ') == 'l' && (enc[1] | ' ') == 'a' && (enc[2] | ' ') == 't'
2015                                 && (enc[3] | ' ') == 'i' && (enc[4] | ' ') == 'n'
2016                                 && enc[5] == '1')
2017                                 return encoding_latin1;
2018                 }
2019
2020                 return encoding_utf8;
2021         }
2022
2023         PUGI__FN xml_encoding get_buffer_encoding(xml_encoding encoding, const void* contents, size_t size)
2024         {
2025                 // replace wchar encoding with utf implementation
2026                 if (encoding == encoding_wchar) return get_wchar_encoding();
2027
2028                 // replace utf16 encoding with utf16 with specific endianness
2029                 if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2030
2031                 // replace utf32 encoding with utf32 with specific endianness
2032                 if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2033
2034                 // only do autodetection if no explicit encoding is requested
2035                 if (encoding != encoding_auto) return encoding;
2036
2037                 // try to guess encoding (based on XML specification, Appendix F.1)
2038                 const uint8_t* data = static_cast<const uint8_t*>(contents);
2039
2040                 return guess_buffer_encoding(data, size);
2041         }
2042
2043         PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable)
2044         {
2045                 size_t length = size / sizeof(char_t);
2046
2047                 if (is_mutable)
2048                 {
2049                         out_buffer = static_cast<char_t*>(const_cast<void*>(contents));
2050                         out_length = length;
2051                 }
2052                 else
2053                 {
2054                         char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
2055                         if (!buffer) return false;
2056
2057                         if (contents)
2058                                 memcpy(buffer, contents, length * sizeof(char_t));
2059                         else
2060                                 assert(length == 0);
2061
2062                         buffer[length] = 0;
2063
2064                         out_buffer = buffer;
2065                         out_length = length + 1;
2066                 }
2067
2068                 return true;
2069         }
2070
2071 #ifdef PUGIXML_WCHAR_MODE
2072         PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re)
2073         {
2074                 return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) ||
2075                            (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be);
2076         }
2077
2078         PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable)
2079         {
2080                 const char_t* data = static_cast<const char_t*>(contents);
2081                 size_t length = size / sizeof(char_t);
2082
2083                 if (is_mutable)
2084                 {
2085                         char_t* buffer = const_cast<char_t*>(data);
2086
2087                         convert_wchar_endian_swap(buffer, data, length);
2088
2089                         out_buffer = buffer;
2090                         out_length = length;
2091                 }
2092                 else
2093                 {
2094                         char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
2095                         if (!buffer) return false;
2096
2097                         convert_wchar_endian_swap(buffer, data, length);
2098                         buffer[length] = 0;
2099
2100                         out_buffer = buffer;
2101                         out_length = length + 1;
2102                 }
2103
2104                 return true;
2105         }
2106
2107         template <typename D> PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D)
2108         {
2109                 const typename D::type* data = static_cast<const typename D::type*>(contents);
2110                 size_t data_length = size / sizeof(typename D::type);
2111
2112                 // first pass: get length in wchar_t units
2113                 size_t length = D::process(data, data_length, 0, wchar_counter());
2114
2115                 // allocate buffer of suitable length
2116                 char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
2117                 if (!buffer) return false;
2118
2119                 // second pass: convert utf16 input to wchar_t
2120                 wchar_writer::value_type obegin = reinterpret_cast<wchar_writer::value_type>(buffer);
2121                 wchar_writer::value_type oend = D::process(data, data_length, obegin, wchar_writer());
2122
2123                 assert(oend == obegin + length);
2124                 *oend = 0;
2125
2126                 out_buffer = buffer;
2127                 out_length = length + 1;
2128
2129                 return true;
2130         }
2131
2132         PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable)
2133         {
2134                 // get native encoding
2135                 xml_encoding wchar_encoding = get_wchar_encoding();
2136
2137                 // fast path: no conversion required
2138                 if (encoding == wchar_encoding)
2139                         return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable);
2140
2141                 // only endian-swapping is required
2142                 if (need_endian_swap_utf(encoding, wchar_encoding))
2143                         return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable);
2144
2145                 // source encoding is utf8
2146                 if (encoding == encoding_utf8)
2147                         return convert_buffer_generic(out_buffer, out_length, contents, size, utf8_decoder());
2148
2149                 // source encoding is utf16
2150                 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2151                 {
2152                         xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2153
2154                         return (native_encoding == encoding) ?
2155                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder<opt_false>()) :
2156                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder<opt_true>());
2157                 }
2158
2159                 // source encoding is utf32
2160                 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2161                 {
2162                         xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2163
2164                         return (native_encoding == encoding) ?
2165                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder<opt_false>()) :
2166                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder<opt_true>());
2167                 }
2168
2169                 // source encoding is latin1
2170                 if (encoding == encoding_latin1)
2171                         return convert_buffer_generic(out_buffer, out_length, contents, size, latin1_decoder());
2172
2173                 assert(false && "Invalid encoding"); // unreachable
2174                 return false;
2175         }
2176 #else
2177         template <typename D> PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D)
2178         {
2179                 const typename D::type* data = static_cast<const typename D::type*>(contents);
2180                 size_t data_length = size / sizeof(typename D::type);
2181
2182                 // first pass: get length in utf8 units
2183                 size_t length = D::process(data, data_length, 0, utf8_counter());
2184
2185                 // allocate buffer of suitable length
2186                 char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
2187                 if (!buffer) return false;
2188
2189                 // second pass: convert utf16 input to utf8
2190                 uint8_t* obegin = reinterpret_cast<uint8_t*>(buffer);
2191                 uint8_t* oend = D::process(data, data_length, obegin, utf8_writer());
2192
2193                 assert(oend == obegin + length);
2194                 *oend = 0;
2195
2196                 out_buffer = buffer;
2197                 out_length = length + 1;
2198
2199                 return true;
2200         }
2201
2202         PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size)
2203         {
2204                 for (size_t i = 0; i < size; ++i)
2205                         if (data[i] > 127)
2206                                 return i;
2207
2208                 return size;
2209         }
2210
2211         PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable)
2212         {
2213                 const uint8_t* data = static_cast<const uint8_t*>(contents);
2214                 size_t data_length = size;
2215
2216                 // get size of prefix that does not need utf8 conversion
2217                 size_t prefix_length = get_latin1_7bit_prefix_length(data, data_length);
2218                 assert(prefix_length <= data_length);
2219
2220                 const uint8_t* postfix = data + prefix_length;
2221                 size_t postfix_length = data_length - prefix_length;
2222
2223                 // if no conversion is needed, just return the original buffer
2224                 if (postfix_length == 0) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable);
2225
2226                 // first pass: get length in utf8 units
2227                 size_t length = prefix_length + latin1_decoder::process(postfix, postfix_length, 0, utf8_counter());
2228
2229                 // allocate buffer of suitable length
2230                 char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
2231                 if (!buffer) return false;
2232
2233                 // second pass: convert latin1 input to utf8
2234                 memcpy(buffer, data, prefix_length);
2235
2236                 uint8_t* obegin = reinterpret_cast<uint8_t*>(buffer);
2237                 uint8_t* oend = latin1_decoder::process(postfix, postfix_length, obegin + prefix_length, utf8_writer());
2238
2239                 assert(oend == obegin + length);
2240                 *oend = 0;
2241
2242                 out_buffer = buffer;
2243                 out_length = length + 1;
2244
2245                 return true;
2246         }
2247
2248         PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable)
2249         {
2250                 // fast path: no conversion required
2251                 if (encoding == encoding_utf8)
2252                         return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable);
2253
2254                 // source encoding is utf16
2255                 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
2256                 {
2257                         xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
2258
2259                         return (native_encoding == encoding) ?
2260                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder<opt_false>()) :
2261                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder<opt_true>());
2262                 }
2263
2264                 // source encoding is utf32
2265                 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
2266                 {
2267                         xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
2268
2269                         return (native_encoding == encoding) ?
2270                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder<opt_false>()) :
2271                                 convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder<opt_true>());
2272                 }
2273
2274                 // source encoding is latin1
2275                 if (encoding == encoding_latin1)
2276                         return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable);
2277
2278                 assert(false && "Invalid encoding"); // unreachable
2279                 return false;
2280         }
2281 #endif
2282
2283         PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length)
2284         {
2285                 // get length in utf8 characters
2286                 return wchar_decoder::process(str, length, 0, utf8_counter());
2287         }
2288
2289         PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length)
2290         {
2291                 // convert to utf8
2292                 uint8_t* begin = reinterpret_cast<uint8_t*>(buffer);
2293                 uint8_t* end = wchar_decoder::process(str, length, begin, utf8_writer());
2294
2295                 assert(begin + size == end);
2296                 (void)!end;
2297                 (void)!size;
2298         }
2299
2300 #ifndef PUGIXML_NO_STL
2301         PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length)
2302         {
2303                 // first pass: get length in utf8 characters
2304                 size_t size = as_utf8_begin(str, length);
2305
2306                 // allocate resulting string
2307                 std::string result;
2308                 result.resize(size);
2309
2310                 // second pass: convert to utf8
2311                 if (size > 0) as_utf8_end(&result[0], size, str, length);
2312
2313                 return result;
2314         }
2315
2316         PUGI__FN std::basic_string<wchar_t> as_wide_impl(const char* str, size_t size)
2317         {
2318                 const uint8_t* data = reinterpret_cast<const uint8_t*>(str);
2319
2320                 // first pass: get length in wchar_t units
2321                 size_t length = utf8_decoder::process(data, size, 0, wchar_counter());
2322
2323                 // allocate resulting string
2324                 std::basic_string<wchar_t> result;
2325                 result.resize(length);
2326
2327                 // second pass: convert to wchar_t
2328                 if (length > 0)
2329                 {
2330                         wchar_writer::value_type begin = reinterpret_cast<wchar_writer::value_type>(&result[0]);
2331                         wchar_writer::value_type end = utf8_decoder::process(data, size, begin, wchar_writer());
2332
2333                         assert(begin + length == end);
2334                         (void)!end;
2335                 }
2336
2337                 return result;
2338         }
2339 #endif
2340
2341         template <typename Header>
2342         inline bool strcpy_insitu_allow(size_t length, const Header& header, uintptr_t header_mask, char_t* target)
2343         {
2344                 // never reuse shared memory
2345                 if (header & xml_memory_page_contents_shared_mask) return false;
2346
2347                 size_t target_length = strlength(target);
2348
2349                 // always reuse document buffer memory if possible
2350                 if ((header & header_mask) == 0) return target_length >= length;
2351
2352                 // reuse heap memory if waste is not too great
2353                 const size_t reuse_threshold = 32;
2354
2355                 return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2);
2356         }
2357
2358         template <typename String, typename Header>
2359         PUGI__FN bool strcpy_insitu(String& dest, Header& header, uintptr_t header_mask, const char_t* source, size_t source_length)
2360         {
2361                 if (source_length == 0)
2362                 {
2363                         // empty string and null pointer are equivalent, so just deallocate old memory
2364                         xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator;
2365
2366                         if (header & header_mask) alloc->deallocate_string(dest);
2367
2368                         // mark the string as not allocated
2369                         dest = 0;
2370                         header &= ~header_mask;
2371
2372                         return true;
2373                 }
2374                 else if (dest && strcpy_insitu_allow(source_length, header, header_mask, dest))
2375                 {
2376                         // we can reuse old buffer, so just copy the new data (including zero terminator)
2377                         memcpy(dest, source, source_length * sizeof(char_t));
2378                         dest[source_length] = 0;
2379
2380                         return true;
2381                 }
2382                 else
2383                 {
2384                         xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator;
2385
2386                         if (!alloc->reserve()) return false;
2387
2388                         // allocate new buffer
2389                         char_t* buf = alloc->allocate_string(source_length + 1);
2390                         if (!buf) return false;
2391
2392                         // copy the string (including zero terminator)
2393                         memcpy(buf, source, source_length * sizeof(char_t));
2394                         buf[source_length] = 0;
2395
2396                         // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures)
2397                         if (header & header_mask) alloc->deallocate_string(dest);
2398
2399                         // the string is now allocated, so set the flag
2400                         dest = buf;
2401                         header |= header_mask;
2402
2403                         return true;
2404                 }
2405         }
2406
2407         struct gap
2408         {
2409                 char_t* end;
2410                 size_t size;
2411
2412                 gap(): end(0), size(0)
2413                 {
2414                 }
2415
2416                 // Push new gap, move s count bytes further (skipping the gap).
2417                 // Collapse previous gap.
2418                 void push(char_t*& s, size_t count)
2419                 {
2420                         if (end) // there was a gap already; collapse it
2421                         {
2422                                 // Move [old_gap_end, new_gap_start) to [old_gap_start, ...)
2423                                 assert(s >= end);
2424                                 memmove(end - size, end, reinterpret_cast<char*>(s) - reinterpret_cast<char*>(end));
2425                         }
2426
2427                         s += count; // end of current gap
2428
2429                         // "merge" two gaps
2430                         end = s;
2431                         size += count;
2432                 }
2433
2434                 // Collapse all gaps, return past-the-end pointer
2435                 char_t* flush(char_t* s)
2436                 {
2437                         if (end)
2438                         {
2439                                 // Move [old_gap_end, current_pos) to [old_gap_start, ...)
2440                                 assert(s >= end);
2441                                 memmove(end - size, end, reinterpret_cast<char*>(s) - reinterpret_cast<char*>(end));
2442
2443                                 return s - size;
2444                         }
2445                         else return s;
2446                 }
2447         };
2448
2449         PUGI__FN char_t* strconv_escape(char_t* s, gap& g)
2450         {
2451                 char_t* stre = s + 1;
2452
2453                 switch (*stre)
2454                 {
2455                         case '#':       // &#...
2456                         {
2457                                 unsigned int ucsc = 0;
2458
2459                                 if (stre[1] == 'x') // &#x... (hex code)
2460                                 {
2461                                         stre += 2;
2462
2463                                         char_t ch = *stre;
2464
2465                                         if (ch == ';') return stre;
2466
2467                                         for (;;)
2468                                         {
2469                                                 if (static_cast<unsigned int>(ch - '0') <= 9)
2470                                                         ucsc = 16 * ucsc + (ch - '0');
2471                                                 else if (static_cast<unsigned int>((ch | ' ') - 'a') <= 5)
2472                                                         ucsc = 16 * ucsc + ((ch | ' ') - 'a' + 10);
2473                                                 else if (ch == ';')
2474                                                         break;
2475                                                 else // cancel
2476                                                         return stre;
2477
2478                                                 ch = *++stre;
2479                                         }
2480
2481                                         ++stre;
2482                                 }
2483                                 else    // &#... (dec code)
2484                                 {
2485                                         char_t ch = *++stre;
2486
2487                                         if (ch == ';') return stre;
2488
2489                                         for (;;)
2490                                         {
2491                                                 if (static_cast<unsigned int>(ch - '0') <= 9)
2492                                                         ucsc = 10 * ucsc + (ch - '0');
2493                                                 else if (ch == ';')
2494                                                         break;
2495                                                 else // cancel
2496                                                         return stre;
2497
2498                                                 ch = *++stre;
2499                                         }
2500
2501                                         ++stre;
2502                                 }
2503
2504                         #ifdef PUGIXML_WCHAR_MODE
2505                                 s = reinterpret_cast<char_t*>(wchar_writer::any(reinterpret_cast<wchar_writer::value_type>(s), ucsc));
2506                         #else
2507                                 s = reinterpret_cast<char_t*>(utf8_writer::any(reinterpret_cast<uint8_t*>(s), ucsc));
2508                         #endif
2509
2510                                 g.push(s, stre - s);
2511                                 return stre;
2512                         }
2513
2514                         case 'a':       // &a
2515                         {
2516                                 ++stre;
2517
2518                                 if (*stre == 'm') // &am
2519                                 {
2520                                         if (*++stre == 'p' && *++stre == ';') // &amp;
2521                                         {
2522                                                 *s++ = '&';
2523                                                 ++stre;
2524
2525                                                 g.push(s, stre - s);
2526                                                 return stre;
2527                                         }
2528                                 }
2529                                 else if (*stre == 'p') // &ap
2530                                 {
2531                                         if (*++stre == 'o' && *++stre == 's' && *++stre == ';') // &apos;
2532                                         {
2533                                                 *s++ = '\'';
2534                                                 ++stre;
2535
2536                                                 g.push(s, stre - s);
2537                                                 return stre;
2538                                         }
2539                                 }
2540                                 break;
2541                         }
2542
2543                         case 'g': // &g
2544                         {
2545                                 if (*++stre == 't' && *++stre == ';') // &gt;
2546                                 {
2547                                         *s++ = '>';
2548                                         ++stre;
2549
2550                                         g.push(s, stre - s);
2551                                         return stre;
2552                                 }
2553                                 break;
2554                         }
2555
2556                         case 'l': // &l
2557                         {
2558                                 if (*++stre == 't' && *++stre == ';') // &lt;
2559                                 {
2560                                         *s++ = '<';
2561                                         ++stre;
2562
2563                                         g.push(s, stre - s);
2564                                         return stre;
2565                                 }
2566                                 break;
2567                         }
2568
2569                         case 'q': // &q
2570                         {
2571                                 if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // &quot;
2572                                 {
2573                                         *s++ = '"';
2574                                         ++stre;
2575
2576                                         g.push(s, stre - s);
2577                                         return stre;
2578                                 }
2579                                 break;
2580                         }
2581
2582                         default:
2583                                 break;
2584                 }
2585
2586                 return stre;
2587         }
2588
2589         // Parser utilities
2590         #define PUGI__ENDSWITH(c, e)        ((c) == (e) || ((c) == 0 && endch == (e)))
2591         #define PUGI__SKIPWS()              { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; }
2592         #define PUGI__OPTSET(OPT)           ( optmsk & (OPT) )
2593         #define PUGI__PUSHNODE(TYPE)        { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); }
2594         #define PUGI__POPNODE()             { cursor = cursor->parent; }
2595         #define PUGI__SCANFOR(X)            { while (*s != 0 && !(X)) ++s; }
2596         #define PUGI__SCANWHILE(X)          { while (X) ++s; }
2597         #define PUGI__SCANWHILE_UNROLL(X)   { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } }
2598         #define PUGI__ENDSEG()              { ch = *s; *s = 0; ++s; }
2599         #define PUGI__THROW_ERROR(err, m)   return error_offset = m, error_status = err, static_cast<char_t*>(0)
2600         #define PUGI__CHECK_ERROR(err, m)   { if (*s == 0) PUGI__THROW_ERROR(err, m); }
2601
2602         PUGI__FN char_t* strconv_comment(char_t* s, char_t endch)
2603         {
2604                 gap g;
2605
2606                 while (true)
2607                 {
2608                         PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment));
2609
2610                         if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
2611                         {
2612                                 *s++ = '\n'; // replace first one with 0x0a
2613
2614                                 if (*s == '\n') g.push(s, 1);
2615                         }
2616                         else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here
2617                         {
2618                                 *g.flush(s) = 0;
2619
2620                                 return s + (s[2] == '>' ? 3 : 2);
2621                         }
2622                         else if (*s == 0)
2623                         {
2624                                 return 0;
2625                         }
2626                         else ++s;
2627                 }
2628         }
2629
2630         PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch)
2631         {
2632                 gap g;
2633
2634                 while (true)
2635                 {
2636                         PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata));
2637
2638                         if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
2639                         {
2640                                 *s++ = '\n'; // replace first one with 0x0a
2641
2642                                 if (*s == '\n') g.push(s, 1);
2643                         }
2644                         else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here
2645                         {
2646                                 *g.flush(s) = 0;
2647
2648                                 return s + 1;
2649                         }
2650                         else if (*s == 0)
2651                         {
2652                                 return 0;
2653                         }
2654                         else ++s;
2655                 }
2656         }
2657
2658         typedef char_t* (*strconv_pcdata_t)(char_t*);
2659
2660         template <typename opt_trim, typename opt_eol, typename opt_escape> struct strconv_pcdata_impl
2661         {
2662                 static char_t* parse(char_t* s)
2663                 {
2664                         gap g;
2665
2666                         char_t* begin = s;
2667
2668                         while (true)
2669                         {
2670                                 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_pcdata));
2671
2672                                 if (*s == '<') // PCDATA ends here
2673                                 {
2674                                         char_t* end = g.flush(s);
2675
2676                                         if (opt_trim::value)
2677                                                 while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space))
2678                                                         --end;
2679
2680                                         *end = 0;
2681
2682                                         return s + 1;
2683                                 }
2684                                 else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
2685                                 {
2686                                         *s++ = '\n'; // replace first one with 0x0a
2687
2688                                         if (*s == '\n') g.push(s, 1);
2689                                 }
2690                                 else if (opt_escape::value && *s == '&')
2691                                 {
2692                                         s = strconv_escape(s, g);
2693                                 }
2694                                 else if (*s == 0)
2695                                 {
2696                                         char_t* end = g.flush(s);
2697
2698                                         if (opt_trim::value)
2699                                                 while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space))
2700                                                         --end;
2701
2702                                         *end = 0;
2703
2704                                         return s;
2705                                 }
2706                                 else ++s;
2707                         }
2708                 }
2709         };
2710
2711         PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask)
2712         {
2713                 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800);
2714
2715                 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (trim eol escapes); this simultaneously checks 3 options from assertion above
2716                 {
2717                 case 0: return strconv_pcdata_impl<opt_false, opt_false, opt_false>::parse;
2718                 case 1: return strconv_pcdata_impl<opt_false, opt_false, opt_true>::parse;
2719                 case 2: return strconv_pcdata_impl<opt_false, opt_true, opt_false>::parse;
2720                 case 3: return strconv_pcdata_impl<opt_false, opt_true, opt_true>::parse;
2721                 case 4: return strconv_pcdata_impl<opt_true, opt_false, opt_false>::parse;
2722                 case 5: return strconv_pcdata_impl<opt_true, opt_false, opt_true>::parse;
2723                 case 6: return strconv_pcdata_impl<opt_true, opt_true, opt_false>::parse;
2724                 case 7: return strconv_pcdata_impl<opt_true, opt_true, opt_true>::parse;
2725                 default: assert(false); return 0; // unreachable
2726                 }
2727         }
2728
2729         typedef char_t* (*strconv_attribute_t)(char_t*, char_t);
2730
2731         template <typename opt_escape> struct strconv_attribute_impl
2732         {
2733                 static char_t* parse_wnorm(char_t* s, char_t end_quote)
2734                 {
2735                         gap g;
2736
2737                         // trim leading whitespaces
2738                         if (PUGI__IS_CHARTYPE(*s, ct_space))
2739                         {
2740                                 char_t* str = s;
2741
2742                                 do ++str;
2743                                 while (PUGI__IS_CHARTYPE(*str, ct_space));
2744
2745                                 g.push(s, str - s);
2746                         }
2747
2748                         while (true)
2749                         {
2750                                 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space));
2751
2752                                 if (*s == end_quote)
2753                                 {
2754                                         char_t* str = g.flush(s);
2755
2756                                         do *str-- = 0;
2757                                         while (PUGI__IS_CHARTYPE(*str, ct_space));
2758
2759                                         return s + 1;
2760                                 }
2761                                 else if (PUGI__IS_CHARTYPE(*s, ct_space))
2762                                 {
2763                                         *s++ = ' ';
2764
2765                                         if (PUGI__IS_CHARTYPE(*s, ct_space))
2766                                         {
2767                                                 char_t* str = s + 1;
2768                                                 while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str;
2769
2770                                                 g.push(s, str - s);
2771                                         }
2772                                 }
2773                                 else if (opt_escape::value && *s == '&')
2774                                 {
2775                                         s = strconv_escape(s, g);
2776                                 }
2777                                 else if (!*s)
2778                                 {
2779                                         return 0;
2780                                 }
2781                                 else ++s;
2782                         }
2783                 }
2784
2785                 static char_t* parse_wconv(char_t* s, char_t end_quote)
2786                 {
2787                         gap g;
2788
2789                         while (true)
2790                         {
2791                                 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws));
2792
2793                                 if (*s == end_quote)
2794                                 {
2795                                         *g.flush(s) = 0;
2796
2797                                         return s + 1;
2798                                 }
2799                                 else if (PUGI__IS_CHARTYPE(*s, ct_space))
2800                                 {
2801                                         if (*s == '\r')
2802                                         {
2803                                                 *s++ = ' ';
2804
2805                                                 if (*s == '\n') g.push(s, 1);
2806                                         }
2807                                         else *s++ = ' ';
2808                                 }
2809                                 else if (opt_escape::value && *s == '&')
2810                                 {
2811                                         s = strconv_escape(s, g);
2812                                 }
2813                                 else if (!*s)
2814                                 {
2815                                         return 0;
2816                                 }
2817                                 else ++s;
2818                         }
2819                 }
2820
2821                 static char_t* parse_eol(char_t* s, char_t end_quote)
2822                 {
2823                         gap g;
2824
2825                         while (true)
2826                         {
2827                                 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr));
2828
2829                                 if (*s == end_quote)
2830                                 {
2831                                         *g.flush(s) = 0;
2832
2833                                         return s + 1;
2834                                 }
2835                                 else if (*s == '\r')
2836                                 {
2837                                         *s++ = '\n';
2838
2839                                         if (*s == '\n') g.push(s, 1);
2840                                 }
2841                                 else if (opt_escape::value && *s == '&')
2842                                 {
2843                                         s = strconv_escape(s, g);
2844                                 }
2845                                 else if (!*s)
2846                                 {
2847                                         return 0;
2848                                 }
2849                                 else ++s;
2850                         }
2851                 }
2852
2853                 static char_t* parse_simple(char_t* s, char_t end_quote)
2854                 {
2855                         gap g;
2856
2857                         while (true)
2858                         {
2859                                 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr));
2860
2861                                 if (*s == end_quote)
2862                                 {
2863                                         *g.flush(s) = 0;
2864
2865                                         return s + 1;
2866                                 }
2867                                 else if (opt_escape::value && *s == '&')
2868                                 {
2869                                         s = strconv_escape(s, g);
2870                                 }
2871                                 else if (!*s)
2872                                 {
2873                                         return 0;
2874                                 }
2875                                 else ++s;
2876                         }
2877                 }
2878         };
2879
2880         PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask)
2881         {
2882                 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80);
2883
2884                 switch ((optmask >> 4) & 15) // get bitmask for flags (wnorm wconv eol escapes); this simultaneously checks 4 options from assertion above
2885                 {
2886                 case 0:  return strconv_attribute_impl<opt_false>::parse_simple;
2887                 case 1:  return strconv_attribute_impl<opt_true>::parse_simple;
2888                 case 2:  return strconv_attribute_impl<opt_false>::parse_eol;
2889                 case 3:  return strconv_attribute_impl<opt_true>::parse_eol;
2890                 case 4:  return strconv_attribute_impl<opt_false>::parse_wconv;
2891                 case 5:  return strconv_attribute_impl<opt_true>::parse_wconv;
2892                 case 6:  return strconv_attribute_impl<opt_false>::parse_wconv;
2893                 case 7:  return strconv_attribute_impl<opt_true>::parse_wconv;
2894                 case 8:  return strconv_attribute_impl<opt_false>::parse_wnorm;
2895                 case 9:  return strconv_attribute_impl<opt_true>::parse_wnorm;
2896                 case 10: return strconv_attribute_impl<opt_false>::parse_wnorm;
2897                 case 11: return strconv_attribute_impl<opt_true>::parse_wnorm;
2898                 case 12: return strconv_attribute_impl<opt_false>::parse_wnorm;
2899                 case 13: return strconv_attribute_impl<opt_true>::parse_wnorm;
2900                 case 14: return strconv_attribute_impl<opt_false>::parse_wnorm;
2901                 case 15: return strconv_attribute_impl<opt_true>::parse_wnorm;
2902                 default: assert(false); return 0; // unreachable
2903                 }
2904         }
2905
2906         inline xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset = 0)
2907         {
2908                 xml_parse_result result;
2909                 result.status = status;
2910                 result.offset = offset;
2911
2912                 return result;
2913         }
2914
2915         struct xml_parser
2916         {
2917                 xml_allocator* alloc;
2918                 char_t* error_offset;
2919                 xml_parse_status error_status;
2920
2921                 xml_parser(xml_allocator* alloc_): alloc(alloc_), error_offset(0), error_status(status_ok)
2922                 {
2923                 }
2924
2925                 // DOCTYPE consists of nested sections of the following possible types:
2926                 // <!-- ... -->, <? ... ?>, "...", '...'
2927                 // <![...]]>
2928                 // <!...>
2929                 // First group can not contain nested groups
2930                 // Second group can contain nested groups of the same type
2931                 // Third group can contain all other groups
2932                 char_t* parse_doctype_primitive(char_t* s)
2933                 {
2934                         if (*s == '"' || *s == '\'')
2935                         {
2936                                 // quoted string
2937                                 char_t ch = *s++;
2938                                 PUGI__SCANFOR(*s == ch);
2939                                 if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s);
2940
2941                                 s++;
2942                         }
2943                         else if (s[0] == '<' && s[1] == '?')
2944                         {
2945                                 // <? ... ?>
2946                                 s += 2;
2947                                 PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype
2948                                 if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s);
2949
2950                                 s += 2;
2951                         }
2952                         else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-')
2953                         {
2954                                 s += 4;
2955                                 PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype
2956                                 if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s);
2957
2958                                 s += 3;
2959                         }
2960                         else PUGI__THROW_ERROR(status_bad_doctype, s);
2961
2962                         return s;
2963                 }
2964
2965                 char_t* parse_doctype_ignore(char_t* s)
2966                 {
2967                         size_t depth = 0;
2968
2969                         assert(s[0] == '<' && s[1] == '!' && s[2] == '[');
2970                         s += 3;
2971
2972                         while (*s)
2973                         {
2974                                 if (s[0] == '<' && s[1] == '!' && s[2] == '[')
2975                                 {
2976                                         // nested ignore section
2977                                         s += 3;
2978                                         depth++;
2979                                 }
2980                                 else if (s[0] == ']' && s[1] == ']' && s[2] == '>')
2981                                 {
2982                                         // ignore section end
2983                                         s += 3;
2984
2985                                         if (depth == 0)
2986                                                 return s;
2987
2988                                         depth--;
2989                                 }
2990                                 else s++;
2991                         }
2992
2993                         PUGI__THROW_ERROR(status_bad_doctype, s);
2994                 }
2995
2996                 char_t* parse_doctype_group(char_t* s, char_t endch)
2997                 {
2998                         size_t depth = 0;
2999
3000                         assert((s[0] == '<' || s[0] == 0) && s[1] == '!');
3001                         s += 2;
3002
3003                         while (*s)
3004                         {
3005                                 if (s[0] == '<' && s[1] == '!' && s[2] != '-')
3006                                 {
3007                                         if (s[2] == '[')
3008                                         {
3009                                                 // ignore
3010                                                 s = parse_doctype_ignore(s);
3011                                                 if (!s) return s;
3012                                         }
3013                                         else
3014                                         {
3015                                                 // some control group
3016                                                 s += 2;
3017                                                 depth++;
3018                                         }
3019                                 }
3020                                 else if (s[0] == '<' || s[0] == '"' || s[0] == '\'')
3021                                 {
3022                                         // unknown tag (forbidden), or some primitive group
3023                                         s = parse_doctype_primitive(s);
3024                                         if (!s) return s;
3025                                 }
3026                                 else if (*s == '>')
3027                                 {
3028                                         if (depth == 0)
3029                                                 return s;
3030
3031                                         depth--;
3032                                         s++;
3033                                 }
3034                                 else s++;
3035                         }
3036
3037                         if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s);
3038
3039                         return s;
3040                 }
3041
3042                 char_t* parse_exclamation(char_t* s, xml_node_struct* cursor, unsigned int optmsk, char_t endch)
3043                 {
3044                         // parse node contents, starting with exclamation mark
3045                         ++s;
3046
3047                         if (*s == '-') // '<!-...'
3048                         {
3049                                 ++s;
3050
3051                                 if (*s == '-') // '<!--...'
3052                                 {
3053                                         ++s;
3054
3055                                         if (PUGI__OPTSET(parse_comments))
3056                                         {
3057                                                 PUGI__PUSHNODE(node_comment); // Append a new node on the tree.
3058                                                 cursor->value = s; // Save the offset.
3059                                         }
3060
3061                                         if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments))
3062                                         {
3063                                                 s = strconv_comment(s, endch);
3064
3065                                                 if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value);
3066                                         }
3067                                         else
3068                                         {
3069                                                 // Scan for terminating '-->'.
3070                                                 PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>'));
3071                                                 PUGI__CHECK_ERROR(status_bad_comment, s);
3072
3073                                                 if (PUGI__OPTSET(parse_comments))
3074                                                         *s = 0; // Zero-terminate this segment at the first terminating '-'.
3075
3076                                                 s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'.
3077                                         }
3078                                 }
3079                                 else PUGI__THROW_ERROR(status_bad_comment, s);
3080                         }
3081                         else if (*s == '[')
3082                         {
3083                                 // '<![CDATA[...'
3084                                 if (*++s=='C' && *++s=='D' && *++s=='A' && *++s=='T' && *++s=='A' && *++s == '[')
3085                                 {
3086                                         ++s;
3087
3088                                         if (PUGI__OPTSET(parse_cdata))
3089                                         {
3090                                                 PUGI__PUSHNODE(node_cdata); // Append a new node on the tree.
3091                                                 cursor->value = s; // Save the offset.
3092
3093                                                 if (PUGI__OPTSET(parse_eol))
3094                                                 {
3095                                                         s = strconv_cdata(s, endch);
3096
3097                                                         if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value);
3098                                                 }
3099                                                 else
3100                                                 {
3101                                                         // Scan for terminating ']]>'.
3102                                                         PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>'));
3103                                                         PUGI__CHECK_ERROR(status_bad_cdata, s);
3104
3105                                                         *s++ = 0; // Zero-terminate this segment.
3106                                                 }
3107                                         }
3108                                         else // Flagged for discard, but we still have to scan for the terminator.
3109                                         {
3110                                                 // Scan for terminating ']]>'.
3111                                                 PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>'));
3112                                                 PUGI__CHECK_ERROR(status_bad_cdata, s);
3113
3114                                                 ++s;
3115                                         }
3116
3117                                         s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'.
3118                                 }
3119                                 else PUGI__THROW_ERROR(status_bad_cdata, s);
3120                         }
3121                         else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI__ENDSWITH(s[6], 'E'))
3122                         {
3123                                 s -= 2;
3124
3125                                 if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s);
3126
3127                                 char_t* mark = s + 9;
3128
3129                                 s = parse_doctype_group(s, endch);
3130                                 if (!s) return s;
3131
3132                                 assert((*s == 0 && endch == '>') || *s == '>');
3133                                 if (*s) *s++ = 0;
3134
3135                                 if (PUGI__OPTSET(parse_doctype))
3136                                 {
3137                                         while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark;
3138
3139                                         PUGI__PUSHNODE(node_doctype);
3140
3141                                         cursor->value = mark;
3142                                 }
3143                         }
3144                         else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s);
3145                         else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s);
3146                         else PUGI__THROW_ERROR(status_unrecognized_tag, s);
3147
3148                         return s;
3149                 }
3150
3151                 char_t* parse_question(char_t* s, xml_node_struct*& ref_cursor, unsigned int optmsk, char_t endch)
3152                 {
3153                         // load into registers
3154                         xml_node_struct* cursor = ref_cursor;
3155                         char_t ch = 0;
3156
3157                         // parse node contents, starting with question mark
3158                         ++s;
3159
3160                         // read PI target
3161                         char_t* target = s;
3162
3163                         if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s);
3164
3165                         PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol));
3166                         PUGI__CHECK_ERROR(status_bad_pi, s);
3167
3168                         // determine node type; stricmp / strcasecmp is not portable
3169                         bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s;
3170
3171                         if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi))
3172                         {
3173                                 if (declaration)
3174                                 {
3175                                         // disallow non top-level declarations
3176                                         if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s);
3177
3178                                         PUGI__PUSHNODE(node_declaration);
3179                                 }
3180                                 else
3181                                 {
3182                                         PUGI__PUSHNODE(node_pi);
3183                                 }
3184
3185                                 cursor->name = target;
3186
3187                                 PUGI__ENDSEG();
3188
3189                                 // parse value/attributes
3190                                 if (ch == '?')
3191                                 {
3192                                         // empty node
3193                                         if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s);
3194                                         s += (*s == '>');
3195
3196                                         PUGI__POPNODE();
3197                                 }
3198                                 else if (PUGI__IS_CHARTYPE(ch, ct_space))
3199                                 {
3200                                         PUGI__SKIPWS();
3201
3202                                         // scan for tag end
3203                                         char_t* value = s;
3204
3205                                         PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>'));
3206                                         PUGI__CHECK_ERROR(status_bad_pi, s);
3207
3208                                         if (declaration)
3209                                         {
3210                                                 // replace ending ? with / so that 'element' terminates properly
3211                                                 *s = '/';
3212
3213                                                 // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES
3214                                                 s = value;
3215                                         }
3216                                         else
3217                                         {
3218                                                 // store value and step over >
3219                                                 cursor->value = value;
3220
3221                                                 PUGI__POPNODE();
3222
3223                                                 PUGI__ENDSEG();
3224
3225                                                 s += (*s == '>');
3226                                         }
3227                                 }
3228                                 else PUGI__THROW_ERROR(status_bad_pi, s);
3229                         }
3230                         else
3231                         {
3232                                 // scan for tag end
3233                                 PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>'));
3234                                 PUGI__CHECK_ERROR(status_bad_pi, s);
3235
3236                                 s += (s[1] == '>' ? 2 : 1);
3237                         }
3238
3239                         // store from registers
3240                         ref_cursor = cursor;
3241
3242                         return s;
3243                 }
3244
3245                 char_t* parse_tree(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch)
3246                 {
3247                         strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk);
3248                         strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk);
3249
3250                         char_t ch = 0;
3251                         xml_node_struct* cursor = root;
3252                         char_t* mark = s;
3253
3254                         while (*s != 0)
3255                         {
3256                                 if (*s == '<')
3257                                 {
3258                                         ++s;
3259
3260                                 LOC_TAG:
3261                                         if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...'
3262                                         {
3263                                                 PUGI__PUSHNODE(node_element); // Append a new node to the tree.
3264
3265                                                 cursor->name = s;
3266
3267                                                 PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator.
3268                                                 PUGI__ENDSEG(); // Save char in 'ch', terminate & step over.
3269
3270                                                 if (ch == '>')
3271                                                 {
3272                                                         // end of tag
3273                                                 }
3274                                                 else if (PUGI__IS_CHARTYPE(ch, ct_space))
3275                                                 {
3276                                                 LOC_ATTRIBUTES:
3277                                                         while (true)
3278                                                         {
3279                                                                 PUGI__SKIPWS(); // Eat any whitespace.
3280
3281                                                                 if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #...
3282                                                                 {
3283                                                                         xml_attribute_struct* a = append_new_attribute(cursor, *alloc); // Make space for this attribute.
3284                                                                         if (!a) PUGI__THROW_ERROR(status_out_of_memory, s);
3285
3286                                                                         a->name = s; // Save the offset.
3287
3288                                                                         PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator.
3289                                                                         PUGI__ENDSEG(); // Save char in 'ch', terminate & step over.
3290
3291                                                                         if (PUGI__IS_CHARTYPE(ch, ct_space))
3292                                                                         {
3293                                                                                 PUGI__SKIPWS(); // Eat any whitespace.
3294
3295                                                                                 ch = *s;
3296                                                                                 ++s;
3297                                                                         }
3298
3299                                                                         if (ch == '=') // '<... #=...'
3300                                                                         {
3301                                                                                 PUGI__SKIPWS(); // Eat any whitespace.
3302
3303                                                                                 if (*s == '"' || *s == '\'') // '<... #="...'
3304                                                                                 {
3305                                                                                         ch = *s; // Save quote char to avoid breaking on "''" -or- '""'.
3306                                                                                         ++s; // Step over the quote.
3307                                                                                         a->value = s; // Save the offset.
3308
3309                                                                                         s = strconv_attribute(s, ch);
3310
3311                                                                                         if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value);
3312
3313                                                                                         // After this line the loop continues from the start;
3314                                                                                         // Whitespaces, / and > are ok, symbols and EOF are wrong,
3315                                                                                         // everything else will be detected
3316                                                                                         if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s);
3317                                                                                 }
3318                                                                                 else PUGI__THROW_ERROR(status_bad_attribute, s);
3319                                                                         }
3320                                                                         else PUGI__THROW_ERROR(status_bad_attribute, s);
3321                                                                 }
3322                                                                 else if (*s == '/')
3323                                                                 {
3324                                                                         ++s;
3325
3326                                                                         if (*s == '>')
3327                                                                         {
3328                                                                                 PUGI__POPNODE();
3329                                                                                 s++;
3330                                                                                 break;
3331                                                                         }
3332                                                                         else if (*s == 0 && endch == '>')
3333                                                                         {
3334                                                                                 PUGI__POPNODE();
3335                                                                                 break;
3336                                                                         }
3337                                                                         else PUGI__THROW_ERROR(status_bad_start_element, s);
3338                                                                 }
3339                                                                 else if (*s == '>')
3340                                                                 {
3341                                                                         ++s;
3342
3343                                                                         break;
3344                                                                 }
3345                                                                 else if (*s == 0 && endch == '>')
3346                                                                 {
3347                                                                         break;
3348                                                                 }
3349                                                                 else PUGI__THROW_ERROR(status_bad_start_element, s);
3350                                                         }
3351
3352                                                         // !!!
3353                                                 }
3354                                                 else if (ch == '/') // '<#.../'
3355                                                 {
3356                                                         if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s);
3357
3358                                                         PUGI__POPNODE(); // Pop.
3359
3360                                                         s += (*s == '>');
3361                                                 }
3362                                                 else if (ch == 0)
3363                                                 {
3364                                                         // we stepped over null terminator, backtrack & handle closing tag
3365                                                         --s;
3366
3367                                                         if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s);
3368                                                 }
3369                                                 else PUGI__THROW_ERROR(status_bad_start_element, s);
3370                                         }
3371                                         else if (*s == '/')
3372                                         {
3373                                                 ++s;
3374
3375                                                 mark = s;
3376
3377                                                 char_t* name = cursor->name;
3378                                                 if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, mark);
3379
3380                                                 while (PUGI__IS_CHARTYPE(*s, ct_symbol))
3381                                                 {
3382                                                         if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, mark);
3383                                                 }
3384
3385                                                 if (*name)
3386                                                 {
3387                                                         if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s);
3388                                                         else PUGI__THROW_ERROR(status_end_element_mismatch, mark);
3389                                                 }
3390
3391                                                 PUGI__POPNODE(); // Pop.
3392
3393                                                 PUGI__SKIPWS();
3394
3395                                                 if (*s == 0)
3396                                                 {
3397                                                         if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s);
3398                                                 }
3399                                                 else
3400                                                 {
3401                                                         if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s);
3402                                                         ++s;
3403                                                 }
3404                                         }
3405                                         else if (*s == '?') // '<?...'
3406                                         {
3407                                                 s = parse_question(s, cursor, optmsk, endch);
3408                                                 if (!s) return s;
3409
3410                                                 assert(cursor);
3411                                                 if (PUGI__NODETYPE(cursor) == node_declaration) goto LOC_ATTRIBUTES;
3412                                         }
3413                                         else if (*s == '!') // '<!...'
3414                                         {
3415                                                 s = parse_exclamation(s, cursor, optmsk, endch);
3416                                                 if (!s) return s;
3417                                         }
3418                                         else if (*s == 0 && endch == '?') PUGI__THROW_ERROR(status_bad_pi, s);
3419                                         else PUGI__THROW_ERROR(status_unrecognized_tag, s);
3420                                 }
3421                                 else
3422                                 {
3423                                         mark = s; // Save this offset while searching for a terminator.
3424
3425                                         PUGI__SKIPWS(); // Eat whitespace if no genuine PCDATA here.
3426
3427                                         if (*s == '<' || !*s)
3428                                         {
3429                                                 // We skipped some whitespace characters because otherwise we would take the tag branch instead of PCDATA one
3430                                                 assert(mark != s);
3431
3432                                                 if (!PUGI__OPTSET(parse_ws_pcdata | parse_ws_pcdata_single) || PUGI__OPTSET(parse_trim_pcdata))
3433                                                 {
3434                                                         continue;
3435                                                 }
3436                                                 else if (PUGI__OPTSET(parse_ws_pcdata_single))
3437                                                 {
3438                                                         if (s[0] != '<' || s[1] != '/' || cursor->first_child) continue;
3439                                                 }
3440                                         }
3441
3442                                         if (!PUGI__OPTSET(parse_trim_pcdata))
3443                                                 s = mark;
3444
3445                                         if (cursor->parent || PUGI__OPTSET(parse_fragment))
3446                                         {
3447                                                 if (PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value)
3448                                                 {
3449                                                         cursor->value = s; // Save the offset.
3450                                                 }
3451                                                 else
3452                                                 {
3453                                                         PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree.
3454
3455                                                         cursor->value = s; // Save the offset.
3456
3457                                                         PUGI__POPNODE(); // Pop since this is a standalone.
3458                                                 }
3459
3460                                                 s = strconv_pcdata(s);
3461
3462                                                 if (!*s) break;
3463                                         }
3464                                         else
3465                                         {
3466                                                 PUGI__SCANFOR(*s == '<'); // '...<'
3467                                                 if (!*s) break;
3468
3469                                                 ++s;
3470                                         }
3471
3472                                         // We're after '<'
3473                                         goto LOC_TAG;
3474                                 }
3475                         }
3476
3477                         // check that last tag is closed
3478                         if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s);
3479
3480                         return s;
3481                 }
3482
3483         #ifdef PUGIXML_WCHAR_MODE
3484                 static char_t* parse_skip_bom(char_t* s)
3485                 {
3486                         unsigned int bom = 0xfeff;
3487                         return (s[0] == static_cast<wchar_t>(bom)) ? s + 1 : s;
3488                 }
3489         #else
3490                 static char_t* parse_skip_bom(char_t* s)
3491                 {
3492                         return (s[0] == '\xef' && s[1] == '\xbb' && s[2] == '\xbf') ? s + 3 : s;
3493                 }
3494         #endif
3495
3496                 static bool has_element_node_siblings(xml_node_struct* node)
3497                 {
3498                         while (node)
3499                         {
3500                                 if (PUGI__NODETYPE(node) == node_element) return true;
3501
3502                                 node = node->next_sibling;
3503                         }
3504
3505                         return false;
3506                 }
3507
3508                 static xml_parse_result parse(char_t* buffer, size_t length, xml_document_struct* xmldoc, xml_node_struct* root, unsigned int optmsk)
3509                 {
3510                         // early-out for empty documents
3511                         if (length == 0)
3512                                 return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element);
3513
3514                         // get last child of the root before parsing
3515                         xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0;
3516
3517                         // create parser on stack
3518                         xml_parser parser(static_cast<xml_allocator*>(xmldoc));
3519
3520                         // save last character and make buffer zero-terminated (speeds up parsing)
3521                         char_t endch = buffer[length - 1];
3522                         buffer[length - 1] = 0;
3523
3524                         // skip BOM to make sure it does not end up as part of parse output
3525                         char_t* buffer_data = parse_skip_bom(buffer);
3526
3527                         // perform actual parsing
3528                         parser.parse_tree(buffer_data, root, optmsk, endch);
3529
3530                         xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0);
3531                         assert(result.offset >= 0 && static_cast<size_t>(result.offset) <= length);
3532
3533                         if (result)
3534                         {
3535                                 // since we removed last character, we have to handle the only possible false positive (stray <)
3536                                 if (endch == '<')
3537                                         return make_parse_result(status_unrecognized_tag, length - 1);
3538
3539                                 // check if there are any element nodes parsed
3540                                 xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0;
3541
3542                                 if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed))
3543                                         return make_parse_result(status_no_document_element, length - 1);
3544                         }
3545                         else
3546                         {
3547                                 // roll back offset if it occurs on a null terminator in the source buffer
3548                                 if (result.offset > 0 && static_cast<size_t>(result.offset) == length - 1 && endch == 0)
3549                                         result.offset--;
3550                         }
3551
3552                         return result;
3553                 }
3554         };
3555
3556         // Output facilities
3557         PUGI__FN xml_encoding get_write_native_encoding()
3558         {
3559         #ifdef PUGIXML_WCHAR_MODE
3560                 return get_wchar_encoding();
3561         #else
3562                 return encoding_utf8;
3563         #endif
3564         }
3565
3566         PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding)
3567         {
3568                 // replace wchar encoding with utf implementation
3569                 if (encoding == encoding_wchar) return get_wchar_encoding();
3570
3571                 // replace utf16 encoding with utf16 with specific endianness
3572                 if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3573
3574                 // replace utf32 encoding with utf32 with specific endianness
3575                 if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3576
3577                 // only do autodetection if no explicit encoding is requested
3578                 if (encoding != encoding_auto) return encoding;
3579
3580                 // assume utf8 encoding
3581                 return encoding_utf8;
3582         }
3583
3584         template <typename D, typename T> PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T)
3585         {
3586                 PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type));
3587
3588                 typename T::value_type end = D::process(reinterpret_cast<const typename D::type*>(data), length, dest, T());
3589
3590                 return static_cast<size_t>(end - dest) * sizeof(*dest);
3591         }
3592
3593         template <typename D, typename T> PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T, bool opt_swap)
3594         {
3595                 PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type));
3596
3597                 typename T::value_type end = D::process(reinterpret_cast<const typename D::type*>(data), length, dest, T());
3598
3599                 if (opt_swap)
3600                 {
3601                         for (typename T::value_type i = dest; i != end; ++i)
3602                                 *i = endian_swap(*i);
3603                 }
3604
3605                 return static_cast<size_t>(end - dest) * sizeof(*dest);
3606         }
3607
3608 #ifdef PUGIXML_WCHAR_MODE
3609         PUGI__FN size_t get_valid_length(const char_t* data, size_t length)
3610         {
3611                 if (length < 1) return 0;
3612
3613                 // discard last character if it's the lead of a surrogate pair
3614                 return (sizeof(wchar_t) == 2 && static_cast<unsigned int>(static_cast<uint16_t>(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length;
3615         }
3616
3617         PUGI__FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding)
3618         {
3619                 // only endian-swapping is required
3620                 if (need_endian_swap_utf(encoding, get_wchar_encoding()))
3621                 {
3622                         convert_wchar_endian_swap(r_char, data, length);
3623
3624                         return length * sizeof(char_t);
3625                 }
3626
3627                 // convert to utf8
3628                 if (encoding == encoding_utf8)
3629                         return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), utf8_writer());
3630
3631                 // convert to utf16
3632                 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3633                 {
3634                         xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3635
3636                         return convert_buffer_output_generic(r_u16, data, length, wchar_decoder(), utf16_writer(), native_encoding != encoding);
3637                 }
3638
3639                 // convert to utf32
3640                 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3641                 {
3642                         xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3643
3644                         return convert_buffer_output_generic(r_u32, data, length, wchar_decoder(), utf32_writer(), native_encoding != encoding);
3645                 }
3646
3647                 // convert to latin1
3648                 if (encoding == encoding_latin1)
3649                         return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), latin1_writer());
3650
3651                 assert(false && "Invalid encoding"); // unreachable
3652                 return 0;
3653         }
3654 #else
3655         PUGI__FN size_t get_valid_length(const char_t* data, size_t length)
3656         {
3657                 if (length < 5) return 0;
3658
3659                 for (size_t i = 1; i <= 4; ++i)
3660                 {
3661                         uint8_t ch = static_cast<uint8_t>(data[length - i]);
3662
3663                         // either a standalone character or a leading one
3664                         if ((ch & 0xc0) != 0x80) return length - i;
3665                 }
3666
3667                 // there are four non-leading characters at the end, sequence tail is broken so might as well process the whole chunk
3668                 return length;
3669         }
3670
3671         PUGI__FN size_t convert_buffer_output(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding)
3672         {
3673                 if (encoding == encoding_utf16_be || encoding == encoding_utf16_le)
3674                 {
3675                         xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
3676
3677                         return convert_buffer_output_generic(r_u16, data, length, utf8_decoder(), utf16_writer(), native_encoding != encoding);
3678                 }
3679
3680                 if (encoding == encoding_utf32_be || encoding == encoding_utf32_le)
3681                 {
3682                         xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
3683
3684                         return convert_buffer_output_generic(r_u32, data, length, utf8_decoder(), utf32_writer(), native_encoding != encoding);
3685                 }
3686
3687                 if (encoding == encoding_latin1)
3688                         return convert_buffer_output_generic(r_u8, data, length, utf8_decoder(), latin1_writer());
3689
3690                 assert(false && "Invalid encoding"); // unreachable
3691                 return 0;
3692         }
3693 #endif
3694
3695         class xml_buffered_writer
3696         {
3697                 xml_buffered_writer(const xml_buffered_writer&);
3698                 xml_buffered_writer& operator=(const xml_buffered_writer&);
3699
3700         public:
3701                 xml_buffered_writer(xml_writer& writer_, xml_encoding user_encoding): writer(writer_), bufsize(0), encoding(get_write_encoding(user_encoding))
3702                 {
3703                         PUGI__STATIC_ASSERT(bufcapacity >= 8);
3704                 }
3705
3706                 size_t flush()
3707                 {
3708                         flush(buffer, bufsize);
3709                         bufsize = 0;
3710                         return 0;
3711                 }
3712
3713                 void flush(const char_t* data, size_t size)
3714                 {
3715                         if (size == 0) return;
3716
3717                         // fast path, just write data
3718                         if (encoding == get_write_native_encoding())
3719                                 writer.write(data, size * sizeof(char_t));
3720                         else
3721                         {
3722                                 // convert chunk
3723                                 size_t result = convert_buffer_output(scratch.data_char, scratch.data_u8, scratch.data_u16, scratch.data_u32, data, size, encoding);
3724                                 assert(result <= sizeof(scratch));
3725
3726                                 // write data
3727                                 writer.write(scratch.data_u8, result);
3728                         }
3729                 }
3730
3731                 void write_direct(const char_t* data, size_t length)
3732                 {
3733                         // flush the remaining buffer contents
3734                         flush();
3735
3736                         // handle large chunks
3737                         if (length > bufcapacity)
3738                         {
3739                                 if (encoding == get_write_native_encoding())
3740                                 {
3741                                         // fast path, can just write data chunk
3742                                         writer.write(data, length * sizeof(char_t));
3743                                         return;
3744                                 }
3745
3746                                 // need to convert in suitable chunks
3747                                 while (length > bufcapacity)
3748                                 {
3749                                         // get chunk size by selecting such number of characters that are guaranteed to fit into scratch buffer
3750                                         // and form a complete codepoint sequence (i.e. discard start of last codepoint if necessary)
3751                                         size_t chunk_size = get_valid_length(data, bufcapacity);
3752                                         assert(chunk_size);
3753
3754                                         // convert chunk and write
3755                                         flush(data, chunk_size);
3756
3757                                         // iterate
3758                                         data += chunk_size;
3759                                         length -= chunk_size;
3760                                 }
3761
3762                                 // small tail is copied below
3763                                 bufsize = 0;
3764                         }
3765
3766                         memcpy(buffer + bufsize, data, length * sizeof(char_t));
3767                         bufsize += length;
3768                 }
3769
3770                 void write_buffer(const char_t* data, size_t length)
3771                 {
3772                         size_t offset = bufsize;
3773
3774                         if (offset + length <= bufcapacity)
3775                         {
3776                                 memcpy(buffer + offset, data, length * sizeof(char_t));
3777                                 bufsize = offset + length;
3778                         }
3779                         else
3780                         {
3781                                 write_direct(data, length);
3782                         }
3783                 }
3784
3785                 void write_string(const char_t* data)
3786                 {
3787                         // write the part of the string that fits in the buffer
3788                         size_t offset = bufsize;
3789
3790                         while (*data && offset < bufcapacity)
3791                                 buffer[offset++] = *data++;
3792
3793                         // write the rest
3794                         if (offset < bufcapacity)
3795                         {
3796                                 bufsize = offset;
3797                         }
3798                         else
3799                         {
3800                                 // backtrack a bit if we have split the codepoint
3801                                 size_t length = offset - bufsize;
3802                                 size_t extra = length - get_valid_length(data - length, length);
3803
3804                                 bufsize = offset - extra;
3805
3806                                 write_direct(data - extra, strlength(data) + extra);
3807                         }
3808                 }
3809
3810                 void write(char_t d0)
3811                 {
3812                         size_t offset = bufsize;
3813                         if (offset > bufcapacity - 1) offset = flush();
3814
3815                         buffer[offset + 0] = d0;
3816                         bufsize = offset + 1;
3817                 }
3818
3819                 void write(char_t d0, char_t d1)
3820                 {
3821                         size_t offset = bufsize;
3822                         if (offset > bufcapacity - 2) offset = flush();
3823
3824                         buffer[offset + 0] = d0;
3825                         buffer[offset + 1] = d1;
3826                         bufsize = offset + 2;
3827                 }
3828
3829                 void write(char_t d0, char_t d1, char_t d2)
3830                 {
3831                         size_t offset = bufsize;
3832                         if (offset > bufcapacity - 3) offset = flush();
3833
3834                         buffer[offset + 0] = d0;
3835                         buffer[offset + 1] = d1;
3836                         buffer[offset + 2] = d2;
3837                         bufsize = offset + 3;
3838                 }
3839
3840                 void write(char_t d0, char_t d1, char_t d2, char_t d3)
3841                 {
3842                         size_t offset = bufsize;
3843                         if (offset > bufcapacity - 4) offset = flush();
3844
3845                         buffer[offset + 0] = d0;
3846                         buffer[offset + 1] = d1;
3847                         buffer[offset + 2] = d2;
3848                         buffer[offset + 3] = d3;
3849                         bufsize = offset + 4;
3850                 }
3851
3852                 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4)
3853                 {
3854                         size_t offset = bufsize;
3855                         if (offset > bufcapacity - 5) offset = flush();
3856
3857                         buffer[offset + 0] = d0;
3858                         buffer[offset + 1] = d1;
3859                         buffer[offset + 2] = d2;
3860                         buffer[offset + 3] = d3;
3861                         buffer[offset + 4] = d4;
3862                         bufsize = offset + 5;
3863                 }
3864
3865                 void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5)
3866                 {
3867                         size_t offset = bufsize;
3868                         if (offset > bufcapacity - 6) offset = flush();
3869
3870                         buffer[offset + 0] = d0;
3871                         buffer[offset + 1] = d1;
3872                         buffer[offset + 2] = d2;
3873                         buffer[offset + 3] = d3;
3874                         buffer[offset + 4] = d4;
3875                         buffer[offset + 5] = d5;
3876                         bufsize = offset + 6;
3877                 }
3878
3879                 // utf8 maximum expansion: x4 (-> utf32)
3880                 // utf16 maximum expansion: x2 (-> utf32)
3881                 // utf32 maximum expansion: x1
3882                 enum
3883                 {
3884                         bufcapacitybytes =
3885                         #ifdef PUGIXML_MEMORY_OUTPUT_STACK
3886                                 PUGIXML_MEMORY_OUTPUT_STACK
3887                         #else
3888                                 10240
3889                         #endif
3890                         ,
3891                         bufcapacity = bufcapacitybytes / (sizeof(char_t) + 4)
3892                 };
3893
3894                 char_t buffer[bufcapacity];
3895
3896                 union
3897                 {
3898                         uint8_t data_u8[4 * bufcapacity];
3899                         uint16_t data_u16[2 * bufcapacity];
3900                         uint32_t data_u32[bufcapacity];
3901                         char_t data_char[bufcapacity];
3902                 } scratch;
3903
3904                 xml_writer& writer;
3905                 size_t bufsize;
3906                 xml_encoding encoding;
3907         };
3908
3909         PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags)
3910         {
3911                 while (*s)
3912                 {
3913                         const char_t* prev = s;
3914
3915                         // While *s is a usual symbol
3916                         PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type));
3917
3918                         writer.write_buffer(prev, static_cast<size_t>(s - prev));
3919
3920                         switch (*s)
3921                         {
3922                                 case 0: break;
3923                                 case '&':
3924                                         writer.write('&', 'a', 'm', 'p', ';');
3925                                         ++s;
3926                                         break;
3927                                 case '<':
3928                                         writer.write('&', 'l', 't', ';');
3929                                         ++s;
3930                                         break;
3931                                 case '>':
3932                                         writer.write('&', 'g', 't', ';');
3933                                         ++s;
3934                                         break;
3935                                 case '"':
3936                                         if (flags & format_attribute_single_quote)
3937                                                 writer.write('"');
3938                                         else
3939                                                 writer.write('&', 'q', 'u', 'o', 't', ';');
3940                                         ++s;
3941                                         break;
3942                                 case '\'':
3943                                         if (flags & format_attribute_single_quote)
3944                                                 writer.write('&', 'a', 'p', 'o', 's', ';');
3945                                         else
3946                                                 writer.write('\'');
3947                                         ++s;
3948                                         break;
3949                                 default: // s is not a usual symbol
3950                                 {
3951                                         unsigned int ch = static_cast<unsigned int>(*s++);
3952                                         assert(ch < 32);
3953
3954                                         if (!(flags & format_skip_control_chars))
3955                                                 writer.write('&', '#', static_cast<char_t>((ch / 10) + '0'), static_cast<char_t>((ch % 10) + '0'), ';');
3956                                 }
3957                         }
3958                 }
3959         }
3960
3961         PUGI__FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags)
3962         {
3963                 if (flags & format_no_escapes)
3964                         writer.write_string(s);
3965                 else
3966                         text_output_escaped(writer, s, type, flags);
3967         }
3968
3969         PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s)
3970         {
3971                 do
3972                 {
3973                         writer.write('<', '!', '[', 'C', 'D');
3974                         writer.write('A', 'T', 'A', '[');
3975
3976                         const char_t* prev = s;
3977
3978                         // look for ]]> sequence - we can't output it as is since it terminates CDATA
3979                         while (*s && !(s[0] == ']' && s[1] == ']' && s[2] == '>')) ++s;
3980
3981                         // skip ]] if we stopped at ]]>, > will go to the next CDATA section
3982                         if (*s) s += 2;
3983
3984                         writer.write_buffer(prev, static_cast<size_t>(s - prev));
3985
3986                         writer.write(']', ']', '>');
3987                 }
3988                 while (*s);
3989         }
3990
3991         PUGI__FN void text_output_indent(xml_buffered_writer& writer, const char_t* indent, size_t indent_length, unsigned int depth)
3992         {
3993                 switch (indent_length)
3994                 {
3995                 case 1:
3996                 {
3997                         for (unsigned int i = 0; i < depth; ++i)
3998                                 writer.write(indent[0]);
3999                         break;
4000                 }
4001
4002                 case 2:
4003                 {
4004                         for (unsigned int i = 0; i < depth; ++i)
4005                                 writer.write(indent[0], indent[1]);
4006                         break;
4007                 }
4008
4009                 case 3:
4010                 {
4011                         for (unsigned int i = 0; i < depth; ++i)
4012                                 writer.write(indent[0], indent[1], indent[2]);
4013                         break;
4014                 }
4015
4016                 case 4:
4017                 {
4018                         for (unsigned int i = 0; i < depth; ++i)
4019                                 writer.write(indent[0], indent[1], indent[2], indent[3]);
4020                         break;
4021                 }
4022
4023                 default:
4024                 {
4025                         for (unsigned int i = 0; i < depth; ++i)
4026                                 writer.write_buffer(indent, indent_length);
4027                 }
4028                 }
4029         }
4030
4031         PUGI__FN void node_output_comment(xml_buffered_writer& writer, const char_t* s)
4032         {
4033                 writer.write('<', '!', '-', '-');
4034
4035                 while (*s)
4036                 {
4037                         const char_t* prev = s;
4038
4039                         // look for -\0 or -- sequence - we can't output it since -- is illegal in comment body
4040                         while (*s && !(s[0] == '-' && (s[1] == '-' || s[1] == 0))) ++s;
4041
4042                         writer.write_buffer(prev, static_cast<size_t>(s - prev));
4043
4044                         if (*s)
4045                         {
4046                                 assert(*s == '-');
4047
4048                                 writer.write('-', ' ');
4049                                 ++s;
4050                         }
4051                 }
4052
4053                 writer.write('-', '-', '>');
4054         }
4055
4056         PUGI__FN void node_output_pi_value(xml_buffered_writer& writer, const char_t* s)
4057         {
4058                 while (*s)
4059                 {
4060                         const char_t* prev = s;
4061
4062                         // look for ?> sequence - we can't output it since ?> terminates PI
4063                         while (*s && !(s[0] == '?' && s[1] == '>')) ++s;
4064
4065                         writer.write_buffer(prev, static_cast<size_t>(s - prev));
4066
4067                         if (*s)
4068                         {
4069                                 assert(s[0] == '?' && s[1] == '>');
4070
4071                                 writer.write('?', ' ', '>');
4072                                 s += 2;
4073                         }
4074                 }
4075         }
4076
4077         PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth)
4078         {
4079                 const char_t* default_name = PUGIXML_TEXT(":anonymous");
4080                 const char_t enquotation_char = (flags & format_attribute_single_quote) ? '\'' : '"';
4081
4082                 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4083                 {
4084                         if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes)
4085                         {
4086                                 writer.write('\n');
4087
4088                                 text_output_indent(writer, indent, indent_length, depth + 1);
4089                         }
4090                         else
4091                         {
4092                                 writer.write(' ');
4093                         }
4094
4095                         writer.write_string(a->name ? a->name + 0 : default_name);
4096                         writer.write('=', enquotation_char);
4097
4098                         if (a->value)
4099                                 text_output(writer, a->value, ctx_special_attr, flags);
4100
4101                         writer.write(enquotation_char);
4102                 }
4103         }
4104
4105         PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth)
4106         {
4107                 const char_t* default_name = PUGIXML_TEXT(":anonymous");
4108                 const char_t* name = node->name ? node->name + 0 : default_name;
4109
4110                 writer.write('<');
4111                 writer.write_string(name);
4112
4113                 if (node->first_attribute)
4114                         node_output_attributes(writer, node, indent, indent_length, flags, depth);
4115
4116                 // element nodes can have value if parse_embed_pcdata was used
4117                 if (!node->value)
4118                 {
4119                         if (!node->first_child)
4120                         {
4121                                 if (flags & format_no_empty_element_tags)
4122                                 {
4123                                         writer.write('>', '<', '/');
4124                                         writer.write_string(name);
4125                                         writer.write('>');
4126
4127                                         return false;
4128                                 }
4129                                 else
4130                                 {
4131                                         if ((flags & format_raw) == 0)
4132                                                 writer.write(' ');
4133
4134                                         writer.write('/', '>');
4135
4136                                         return false;
4137                                 }
4138                         }
4139                         else
4140                         {
4141                                 writer.write('>');
4142
4143                                 return true;
4144                         }
4145                 }
4146                 else
4147                 {
4148                         writer.write('>');
4149
4150                         text_output(writer, node->value, ctx_special_pcdata, flags);
4151
4152                         if (!node->first_child)
4153                         {
4154                                 writer.write('<', '/');
4155                                 writer.write_string(name);
4156                                 writer.write('>');
4157
4158                                 return false;
4159                         }
4160                         else
4161                         {
4162                                 return true;
4163                         }
4164                 }
4165         }
4166
4167         PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node)
4168         {
4169                 const char_t* default_name = PUGIXML_TEXT(":anonymous");
4170                 const char_t* name = node->name ? node->name + 0 : default_name;
4171
4172                 writer.write('<', '/');
4173                 writer.write_string(name);
4174                 writer.write('>');
4175         }
4176
4177         PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags)
4178         {
4179                 const char_t* default_name = PUGIXML_TEXT(":anonymous");
4180
4181                 switch (PUGI__NODETYPE(node))
4182                 {
4183                         case node_pcdata:
4184                                 text_output(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""), ctx_special_pcdata, flags);
4185                                 break;
4186
4187                         case node_cdata:
4188                                 text_output_cdata(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""));
4189                                 break;
4190
4191                         case node_comment:
4192                                 node_output_comment(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""));
4193                                 break;
4194
4195                         case node_pi:
4196                                 writer.write('<', '?');
4197                                 writer.write_string(node->name ? node->name + 0 : default_name);
4198
4199                                 if (node->value)
4200                                 {
4201                                         writer.write(' ');
4202                                         node_output_pi_value(writer, node->value);
4203                                 }
4204
4205                                 writer.write('?', '>');
4206                                 break;
4207
4208                         case node_declaration:
4209                                 writer.write('<', '?');
4210                                 writer.write_string(node->name ? node->name + 0 : default_name);
4211                                 node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0);
4212                                 writer.write('?', '>');
4213                                 break;
4214
4215                         case node_doctype:
4216                                 writer.write('<', '!', 'D', 'O', 'C');
4217                                 writer.write('T', 'Y', 'P', 'E');
4218
4219                                 if (node->value)
4220                                 {
4221                                         writer.write(' ');
4222                                         writer.write_string(node->value);
4223                                 }
4224
4225                                 writer.write('>');
4226                                 break;
4227
4228                         default:
4229                                 assert(false && "Invalid node type"); // unreachable
4230                 }
4231         }
4232
4233         enum indent_flags_t
4234         {
4235                 indent_newline = 1,
4236                 indent_indent = 2
4237         };
4238
4239         PUGI__FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth)
4240         {
4241                 size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ? strlength(indent) : 0;
4242                 unsigned int indent_flags = indent_indent;
4243
4244                 xml_node_struct* node = root;
4245
4246                 do
4247                 {
4248                         assert(node);
4249
4250                         // begin writing current node
4251                         if (PUGI__NODETYPE(node) == node_pcdata || PUGI__NODETYPE(node) == node_cdata)
4252                         {
4253                                 node_output_simple(writer, node, flags);
4254
4255                                 indent_flags = 0;
4256                         }
4257                         else
4258                         {
4259                                 if ((indent_flags & indent_newline) && (flags & format_raw) == 0)
4260                                         writer.write('\n');
4261
4262                                 if ((indent_flags & indent_indent) && indent_length)
4263                                         text_output_indent(writer, indent, indent_length, depth);
4264
4265                                 if (PUGI__NODETYPE(node) == node_element)
4266                                 {
4267                                         indent_flags = indent_newline | indent_indent;
4268
4269                                         if (node_output_start(writer, node, indent, indent_length, flags, depth))
4270                                         {
4271                                                 // element nodes can have value if parse_embed_pcdata was used
4272                                                 if (node->value)
4273                                                         indent_flags = 0;
4274
4275                                                 node = node->first_child;
4276                                                 depth++;
4277                                                 continue;
4278                                         }
4279                                 }
4280                                 else if (PUGI__NODETYPE(node) == node_document)
4281                                 {
4282                                         indent_flags = indent_indent;
4283
4284                                         if (node->first_child)
4285                                         {
4286                                                 node = node->first_child;
4287                                                 continue;
4288                                         }
4289                                 }
4290                                 else
4291                                 {
4292                                         node_output_simple(writer, node, flags);
4293
4294                                         indent_flags = indent_newline | indent_indent;
4295                                 }
4296                         }
4297
4298                         // continue to the next node
4299                         while (node != root)
4300                         {
4301                                 if (node->next_sibling)
4302                                 {
4303                                         node = node->next_sibling;
4304                                         break;
4305                                 }
4306
4307                                 node = node->parent;
4308
4309                                 // write closing node
4310                                 if (PUGI__NODETYPE(node) == node_element)
4311                                 {
4312                                         depth--;
4313
4314                                         if ((indent_flags & indent_newline) && (flags & format_raw) == 0)
4315                                                 writer.write('\n');
4316
4317                                         if ((indent_flags & indent_indent) && indent_length)
4318                                                 text_output_indent(writer, indent, indent_length, depth);
4319
4320                                         node_output_end(writer, node);
4321
4322                                         indent_flags = indent_newline | indent_indent;
4323                                 }
4324                         }
4325                 }
4326                 while (node != root);
4327
4328                 if ((indent_flags & indent_newline) && (flags & format_raw) == 0)
4329                         writer.write('\n');
4330         }
4331
4332         PUGI__FN bool has_declaration(xml_node_struct* node)
4333         {
4334                 for (xml_node_struct* child = node->first_child; child; child = child->next_sibling)
4335                 {
4336                         xml_node_type type = PUGI__NODETYPE(child);
4337
4338                         if (type == node_declaration) return true;
4339                         if (type == node_element) return false;
4340                 }
4341
4342                 return false;
4343         }
4344
4345         PUGI__FN bool is_attribute_of(xml_attribute_struct* attr, xml_node_struct* node)
4346         {
4347                 for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute)
4348                         if (a == attr)
4349                                 return true;
4350
4351                 return false;
4352         }
4353
4354         PUGI__FN bool allow_insert_attribute(xml_node_type parent)
4355         {
4356                 return parent == node_element || parent == node_declaration;
4357         }
4358
4359         PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child)
4360         {
4361                 if (parent != node_document && parent != node_element) return false;
4362                 if (child == node_document || child == node_null) return false;
4363                 if (parent != node_document && (child == node_declaration || child == node_doctype)) return false;
4364
4365                 return true;
4366         }
4367
4368         PUGI__FN bool allow_move(xml_node parent, xml_node child)
4369         {
4370                 // check that child can be a child of parent
4371                 if (!allow_insert_child(parent.type(), child.type()))
4372                         return false;
4373
4374                 // check that node is not moved between documents
4375                 if (parent.root() != child.root())
4376                         return false;
4377
4378                 // check that new parent is not in the child subtree
4379                 xml_node cur = parent;
4380
4381                 while (cur)
4382                 {
4383                         if (cur == child)
4384                                 return false;
4385
4386                         cur = cur.parent();
4387                 }
4388
4389                 return true;
4390         }
4391
4392         template <typename String, typename Header>
4393         PUGI__FN void node_copy_string(String& dest, Header& header, uintptr_t header_mask, char_t* source, Header& source_header, xml_allocator* alloc)
4394         {
4395                 assert(!dest && (header & header_mask) == 0);
4396
4397                 if (source)
4398                 {
4399                         if (alloc && (source_header & header_mask) == 0)
4400                         {
4401                                 dest = source;
4402
4403                                 // since strcpy_insitu can reuse document buffer memory we need to mark both source and dest as shared
4404                                 header |= xml_memory_page_contents_shared_mask;
4405                                 source_header |= xml_memory_page_contents_shared_mask;
4406                         }
4407                         else
4408                                 strcpy_insitu(dest, header, header_mask, source, strlength(source));
4409                 }
4410         }
4411
4412         PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc)
4413         {
4414                 node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc);
4415                 node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc);
4416
4417                 for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute)
4418                 {
4419                         xml_attribute_struct* da = append_new_attribute(dn, get_allocator(dn));
4420
4421                         if (da)
4422                         {
4423                                 node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc);
4424                                 node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc);
4425                         }
4426                 }
4427         }
4428
4429         PUGI__FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn)
4430         {
4431                 xml_allocator& alloc = get_allocator(dn);
4432                 xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0;
4433
4434                 node_copy_contents(dn, sn, shared_alloc);
4435
4436                 xml_node_struct* dit = dn;
4437                 xml_node_struct* sit = sn->first_child;
4438
4439                 while (sit && sit != sn)
4440                 {
4441                         // loop invariant: dit is inside the subtree rooted at dn
4442                         assert(dit);
4443
4444                         // when a tree is copied into one of the descendants, we need to skip that subtree to avoid an infinite loop
4445                         if (sit != dn)
4446                         {
4447                                 xml_node_struct* copy = append_new_node(dit, alloc, PUGI__NODETYPE(sit));
4448
4449                                 if (copy)
4450                                 {
4451                                         node_copy_contents(copy, sit, shared_alloc);
4452
4453                                         if (sit->first_child)
4454                                         {
4455                                                 dit = copy;
4456                                                 sit = sit->first_child;
4457                                                 continue;
4458                                         }
4459                                 }
4460                         }
4461
4462                         // continue to the next node
4463                         do
4464                         {
4465                                 if (sit->next_sibling)
4466                                 {
4467                                         sit = sit->next_sibling;
4468                                         break;
4469                                 }
4470
4471                                 sit = sit->parent;
4472                                 dit = dit->parent;
4473
4474                                 // loop invariant: dit is inside the subtree rooted at dn while sit is inside sn
4475                                 assert(sit == sn || dit);
4476                         }
4477                         while (sit != sn);
4478                 }
4479
4480                 assert(!sit || dit == dn->parent);
4481         }
4482
4483         PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa)
4484         {
4485                 xml_allocator& alloc = get_allocator(da);
4486                 xml_allocator* shared_alloc = (&alloc == &get_allocator(sa)) ? &alloc : 0;
4487
4488                 node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc);
4489                 node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc);
4490         }
4491
4492         inline bool is_text_node(xml_node_struct* node)
4493         {
4494                 xml_node_type type = PUGI__NODETYPE(node);
4495
4496                 return type == node_pcdata || type == node_cdata;
4497         }
4498
4499         // get value with conversion functions
4500         template <typename U> PUGI__FN PUGI__UNSIGNED_OVERFLOW U string_to_integer(const char_t* value, U minv, U maxv)
4501         {
4502                 U result = 0;
4503                 const char_t* s = value;
4504
4505                 while (PUGI__IS_CHARTYPE(*s, ct_space))
4506                         s++;
4507
4508                 bool negative = (*s == '-');
4509
4510                 s += (*s == '+' || *s == '-');
4511
4512                 bool overflow = false;
4513
4514                 if (s[0] == '0' && (s[1] | ' ') == 'x')
4515                 {
4516                         s += 2;
4517
4518                         // since overflow detection relies on length of the sequence skip leading zeros
4519                         while (*s == '0')
4520                                 s++;
4521
4522                         const char_t* start = s;
4523
4524                         for (;;)
4525                         {
4526                                 if (static_cast<unsigned>(*s - '0') < 10)
4527                                         result = result * 16 + (*s - '0');
4528                                 else if (static_cast<unsigned>((*s | ' ') - 'a') < 6)
4529                                         result = result * 16 + ((*s | ' ') - 'a' + 10);
4530                                 else
4531                                         break;
4532
4533                                 s++;
4534                         }
4535
4536                         size_t digits = static_cast<size_t>(s - start);
4537
4538                         overflow = digits > sizeof(U) * 2;
4539                 }
4540                 else
4541                 {
4542                         // since overflow detection relies on length of the sequence skip leading zeros
4543                         while (*s == '0')
4544                                 s++;
4545
4546                         const char_t* start = s;
4547
4548                         for (;;)
4549                         {
4550                                 if (static_cast<unsigned>(*s - '0') < 10)
4551                                         result = result * 10 + (*s - '0');
4552                                 else
4553                                         break;
4554
4555                                 s++;
4556                         }
4557
4558                         size_t digits = static_cast<size_t>(s - start);
4559
4560                         PUGI__STATIC_ASSERT(sizeof(U) == 8 || sizeof(U) == 4 || sizeof(U) == 2);
4561
4562                         const size_t max_digits10 = sizeof(U) == 8 ? 20 : sizeof(U) == 4 ? 10 : 5;
4563                         const char_t max_lead = sizeof(U) == 8 ? '1' : sizeof(U) == 4 ? '4' : '6';
4564                         const size_t high_bit = sizeof(U) * 8 - 1;
4565
4566                         overflow = digits >= max_digits10 && !(digits == max_digits10 && (*start < max_lead || (*start == max_lead && result >> high_bit)));
4567                 }
4568
4569                 if (negative)
4570                 {
4571                         // Workaround for crayc++ CC-3059: Expected no overflow in routine.
4572                 #ifdef _CRAYC
4573                         return (overflow || result > ~minv + 1) ? minv : ~result + 1;
4574                 #else
4575                         return (overflow || result > 0 - minv) ? minv : 0 - result;
4576                 #endif
4577                 }
4578                 else
4579                         return (overflow || result > maxv) ? maxv : result;
4580         }
4581
4582         PUGI__FN int get_value_int(const char_t* value)
4583         {
4584                 return string_to_integer<unsigned int>(value, static_cast<unsigned int>(INT_MIN), INT_MAX);
4585         }
4586
4587         PUGI__FN unsigned int get_value_uint(const char_t* value)
4588         {
4589                 return string_to_integer<unsigned int>(value, 0, UINT_MAX);
4590         }
4591
4592         PUGI__FN double get_value_double(const char_t* value)
4593         {
4594         #ifdef PUGIXML_WCHAR_MODE
4595                 return wcstod(value, 0);
4596         #else
4597                 return strtod(value, 0);
4598         #endif
4599         }
4600
4601         PUGI__FN float get_value_float(const char_t* value)
4602         {
4603         #ifdef PUGIXML_WCHAR_MODE
4604                 return static_cast<float>(wcstod(value, 0));
4605         #else
4606                 return static_cast<float>(strtod(value, 0));
4607         #endif
4608         }
4609
4610         PUGI__FN bool get_value_bool(const char_t* value)
4611         {
4612                 // only look at first char
4613                 char_t first = *value;
4614
4615                 // 1*, t* (true), T* (True), y* (yes), Y* (YES)
4616                 return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y');
4617         }
4618
4619 #ifdef PUGIXML_HAS_LONG_LONG
4620         PUGI__FN long long get_value_llong(const char_t* value)
4621         {
4622                 return string_to_integer<unsigned long long>(value, static_cast<unsigned long long>(LLONG_MIN), LLONG_MAX);
4623         }
4624
4625         PUGI__FN unsigned long long get_value_ullong(const char_t* value)
4626         {
4627                 return string_to_integer<unsigned long long>(value, 0, ULLONG_MAX);
4628         }
4629 #endif
4630
4631         template <typename U> PUGI__FN PUGI__UNSIGNED_OVERFLOW char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative)
4632         {
4633                 char_t* result = end - 1;
4634                 U rest = negative ? 0 - value : value;
4635
4636                 do
4637                 {
4638                         *result-- = static_cast<char_t>('0' + (rest % 10));
4639                         rest /= 10;
4640                 }
4641                 while (rest);
4642
4643                 assert(result >= begin);
4644                 (void)begin;
4645
4646                 *result = '-';
4647
4648                 return result + !negative;
4649         }
4650
4651         // set value with conversion functions
4652         template <typename String, typename Header>
4653         PUGI__FN bool set_value_ascii(String& dest, Header& header, uintptr_t header_mask, char* buf)
4654         {
4655         #ifdef PUGIXML_WCHAR_MODE
4656                 char_t wbuf[128];
4657                 assert(strlen(buf) < sizeof(wbuf) / sizeof(wbuf[0]));
4658
4659                 size_t offset = 0;
4660                 for (; buf[offset]; ++offset) wbuf[offset] = buf[offset];
4661
4662                 return strcpy_insitu(dest, header, header_mask, wbuf, offset);
4663         #else
4664                 return strcpy_insitu(dest, header, header_mask, buf, strlen(buf));
4665         #endif
4666         }
4667
4668         template <typename U, typename String, typename Header>
4669         PUGI__FN bool set_value_integer(String& dest, Header& header, uintptr_t header_mask, U value, bool negative)
4670         {
4671                 char_t buf[64];
4672                 char_t* end = buf + sizeof(buf) / sizeof(buf[0]);
4673                 char_t* begin = integer_to_string(buf, end, value, negative);
4674
4675                 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4676         }
4677
4678         template <typename String, typename Header>
4679         PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, float value, int precision)
4680         {
4681                 char buf[128];
4682                 PUGI__SNPRINTF(buf, "%.*g", precision, double(value));
4683
4684                 return set_value_ascii(dest, header, header_mask, buf);
4685         }
4686
4687         template <typename String, typename Header>
4688         PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, double value, int precision)
4689         {
4690                 char buf[128];
4691                 PUGI__SNPRINTF(buf, "%.*g", precision, value);
4692
4693                 return set_value_ascii(dest, header, header_mask, buf);
4694         }
4695
4696         template <typename String, typename Header>
4697         PUGI__FN bool set_value_bool(String& dest, Header& header, uintptr_t header_mask, bool value)
4698         {
4699                 return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"), value ? 4 : 5);
4700         }
4701
4702         PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer)
4703         {
4704                 // check input buffer
4705                 if (!contents && size) return make_parse_result(status_io_error);
4706
4707                 // get actual encoding
4708                 xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
4709
4710                 // get private buffer
4711                 char_t* buffer = 0;
4712                 size_t length = 0;
4713
4714                 // coverity[var_deref_model]
4715                 if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
4716
4717                 // delete original buffer if we performed a conversion
4718                 if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
4719
4720                 // grab onto buffer if it's our buffer, user is responsible for deallocating contents himself
4721                 if (own || buffer != contents) *out_buffer = buffer;
4722
4723                 // store buffer for offset_debug
4724                 doc->buffer = buffer;
4725
4726                 // parse
4727                 xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options);
4728
4729                 // remember encoding
4730                 res.encoding = buffer_encoding;
4731
4732                 return res;
4733         }
4734
4735         // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick
4736         PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result)
4737         {
4738         #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
4739                 // there are 64-bit versions of fseek/ftell, let's use them
4740                 typedef __int64 length_type;
4741
4742                 _fseeki64(file, 0, SEEK_END);
4743                 length_type length = _ftelli64(file);
4744                 _fseeki64(file, 0, SEEK_SET);
4745         #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))
4746                 // there are 64-bit versions of fseek/ftell, let's use them
4747                 typedef off64_t length_type;
4748
4749                 fseeko64(file, 0, SEEK_END);
4750                 length_type length = ftello64(file);
4751                 fseeko64(file, 0, SEEK_SET);
4752         #else
4753                 // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway.
4754                 typedef long length_type;
4755
4756                 fseek(file, 0, SEEK_END);
4757                 length_type length = ftell(file);
4758                 fseek(file, 0, SEEK_SET);
4759         #endif
4760
4761                 // check for I/O errors
4762                 if (length < 0) return status_io_error;
4763
4764                 // check for overflow
4765                 size_t result = static_cast<size_t>(length);
4766
4767                 if (static_cast<length_type>(result) != length) return status_out_of_memory;
4768
4769                 // finalize
4770                 out_result = result;
4771
4772                 return status_ok;
4773         }
4774
4775         // This function assumes that buffer has extra sizeof(char_t) writable bytes after size
4776         PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding)
4777         {
4778                 // We only need to zero-terminate if encoding conversion does not do it for us
4779         #ifdef PUGIXML_WCHAR_MODE
4780                 xml_encoding wchar_encoding = get_wchar_encoding();
4781
4782                 if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding))
4783                 {
4784                         size_t length = size / sizeof(char_t);
4785
4786                         static_cast<char_t*>(buffer)[length] = 0;
4787                         return (length + 1) * sizeof(char_t);
4788                 }
4789         #else
4790                 if (encoding == encoding_utf8)
4791                 {
4792                         static_cast<char*>(buffer)[size] = 0;
4793                         return size + 1;
4794                 }
4795         #endif
4796
4797                 return size;
4798         }
4799
4800         PUGI__FN xml_parse_result load_file_impl(xml_document_struct* doc, FILE* file, unsigned int options, xml_encoding encoding, char_t** out_buffer)
4801         {
4802                 if (!file) return make_parse_result(status_file_not_found);
4803
4804                 // get file size (can result in I/O errors)
4805                 size_t size = 0;
4806                 xml_parse_status size_status = get_file_size(file, size);
4807                 if (size_status != status_ok) return make_parse_result(size_status);
4808
4809                 size_t max_suffix_size = sizeof(char_t);
4810
4811                 // allocate buffer for the whole file
4812                 char* contents = static_cast<char*>(xml_memory::allocate(size + max_suffix_size));
4813                 if (!contents) return make_parse_result(status_out_of_memory);
4814
4815                 // read file in memory
4816                 size_t read_size = fread(contents, 1, size, file);
4817
4818                 if (read_size != size)
4819                 {
4820                         xml_memory::deallocate(contents);
4821                         return make_parse_result(status_io_error);
4822                 }
4823
4824                 xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size);
4825
4826                 return load_buffer_impl(doc, doc, contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding, true, true, out_buffer);
4827         }
4828
4829         PUGI__FN void close_file(FILE* file)
4830         {
4831                 fclose(file);
4832         }
4833
4834 #ifndef PUGIXML_NO_STL
4835         template <typename T> struct xml_stream_chunk
4836         {
4837                 static xml_stream_chunk* create()
4838                 {
4839                         void* memory = xml_memory::allocate(sizeof(xml_stream_chunk));
4840                         if (!memory) return 0;
4841
4842                         return new (memory) xml_stream_chunk();
4843                 }
4844
4845                 static void destroy(xml_stream_chunk* chunk)
4846                 {
4847                         // free chunk chain
4848                         while (chunk)
4849                         {
4850                                 xml_stream_chunk* next_ = chunk->next;
4851
4852                                 xml_memory::deallocate(chunk);
4853
4854                                 chunk = next_;
4855                         }
4856                 }
4857
4858                 xml_stream_chunk(): next(0), size(0)
4859                 {
4860                 }
4861
4862                 xml_stream_chunk* next;
4863                 size_t size;
4864
4865                 T data[xml_memory_page_size / sizeof(T)];
4866         };
4867
4868         template <typename T> PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size)
4869         {
4870                 auto_deleter<xml_stream_chunk<T> > chunks(0, xml_stream_chunk<T>::destroy);
4871
4872                 // read file to a chunk list
4873                 size_t total = 0;
4874                 xml_stream_chunk<T>* last = 0;
4875
4876                 while (!stream.eof())
4877                 {
4878                         // allocate new chunk
4879                         xml_stream_chunk<T>* chunk = xml_stream_chunk<T>::create();
4880                         if (!chunk) return status_out_of_memory;
4881
4882                         // append chunk to list
4883                         if (last) last = last->next = chunk;
4884                         else chunks.data = last = chunk;
4885
4886                         // read data to chunk
4887                         stream.read(chunk->data, static_cast<std::streamsize>(sizeof(chunk->data) / sizeof(T)));
4888                         chunk->size = static_cast<size_t>(stream.gcount()) * sizeof(T);
4889
4890                         // read may set failbit | eofbit in case gcount() is less than read length, so check for other I/O errors
4891                         if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error;
4892
4893                         // guard against huge files (chunk size is small enough to make this overflow check work)
4894                         if (total + chunk->size < total) return status_out_of_memory;
4895                         total += chunk->size;
4896                 }
4897
4898                 size_t max_suffix_size = sizeof(char_t);
4899
4900                 // copy chunk list to a contiguous buffer
4901                 char* buffer = static_cast<char*>(xml_memory::allocate(total + max_suffix_size));
4902                 if (!buffer) return status_out_of_memory;
4903
4904                 char* write = buffer;
4905
4906                 for (xml_stream_chunk<T>* chunk = chunks.data; chunk; chunk = chunk->next)
4907                 {
4908                         assert(write + chunk->size <= buffer + total);
4909                         memcpy(write, chunk->data, chunk->size);
4910                         write += chunk->size;
4911                 }
4912
4913                 assert(write == buffer + total);
4914
4915                 // return buffer
4916                 *out_buffer = buffer;
4917                 *out_size = total;
4918
4919                 return status_ok;
4920         }
4921
4922         template <typename T> PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size)
4923         {
4924                 // get length of remaining data in stream
4925                 typename std::basic_istream<T>::pos_type pos = stream.tellg();
4926                 stream.seekg(0, std::ios::end);
4927                 std::streamoff length = stream.tellg() - pos;
4928                 stream.seekg(pos);
4929
4930                 if (stream.fail() || pos < 0) return status_io_error;
4931
4932                 // guard against huge files
4933                 size_t read_length = static_cast<size_t>(length);
4934
4935                 if (static_cast<std::streamsize>(read_length) != length || length < 0) return status_out_of_memory;
4936
4937                 size_t max_suffix_size = sizeof(char_t);
4938
4939                 // read stream data into memory (guard against stream exceptions with buffer holder)
4940                 auto_deleter<void> buffer(xml_memory::allocate(read_length * sizeof(T) + max_suffix_size), xml_memory::deallocate);
4941                 if (!buffer.data) return status_out_of_memory;
4942
4943                 stream.read(static_cast<T*>(buffer.data), static_cast<std::streamsize>(read_length));
4944
4945                 // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors
4946                 if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error;
4947
4948                 // return buffer
4949                 size_t actual_length = static_cast<size_t>(stream.gcount());
4950                 assert(actual_length <= read_length);
4951
4952                 *out_buffer = buffer.release();
4953                 *out_size = actual_length * sizeof(T);
4954
4955                 return status_ok;
4956         }
4957
4958         template <typename T> PUGI__FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream<T>& stream, unsigned int options, xml_encoding encoding, char_t** out_buffer)
4959         {
4960                 void* buffer = 0;
4961                 size_t size = 0;
4962                 xml_parse_status status = status_ok;
4963
4964                 // if stream has an error bit set, bail out (otherwise tellg() can fail and we'll clear error bits)
4965                 if (stream.fail()) return make_parse_result(status_io_error);
4966
4967                 // load stream to memory (using seek-based implementation if possible, since it's faster and takes less memory)
4968                 if (stream.tellg() < 0)
4969                 {
4970                         stream.clear(); // clear error flags that could be set by a failing tellg
4971                         status = load_stream_data_noseek(stream, &buffer, &size);
4972                 }
4973                 else
4974                         status = load_stream_data_seek(stream, &buffer, &size);
4975
4976                 if (status != status_ok) return make_parse_result(status);
4977
4978                 xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size);
4979
4980                 return load_buffer_impl(doc, doc, buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding, true, true, out_buffer);
4981         }
4982 #endif
4983
4984 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)))
4985         PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode)
4986         {
4987 #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
4988                 FILE* file = 0;
4989                 return _wfopen_s(&file, path, mode) == 0 ? file : 0;
4990 #else
4991                 return _wfopen(path, mode);
4992 #endif
4993         }
4994 #else
4995         PUGI__FN char* convert_path_heap(const wchar_t* str)
4996         {
4997                 assert(str);
4998
4999                 // first pass: get length in utf8 characters
5000                 size_t length = strlength_wide(str);
5001                 size_t size = as_utf8_begin(str, length);
5002
5003                 // allocate resulting string
5004                 char* result = static_cast<char*>(xml_memory::allocate(size + 1));
5005                 if (!result) return 0;
5006
5007                 // second pass: convert to utf8
5008                 as_utf8_end(result, size, str, length);
5009
5010                 // zero-terminate
5011                 result[size] = 0;
5012
5013                 return result;
5014         }
5015
5016         PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode)
5017         {
5018                 // there is no standard function to open wide paths, so our best bet is to try utf8 path
5019                 char* path_utf8 = convert_path_heap(path);
5020                 if (!path_utf8) return 0;
5021
5022                 // convert mode to ASCII (we mirror _wfopen interface)
5023                 char mode_ascii[4] = {0};
5024                 for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast<char>(mode[i]);
5025
5026                 // try to open the utf8 path
5027                 FILE* result = fopen(path_utf8, mode_ascii);
5028
5029                 // free dummy buffer
5030                 xml_memory::deallocate(path_utf8);
5031
5032                 return result;
5033         }
5034 #endif
5035
5036         PUGI__FN FILE* open_file(const char* path, const char* mode)
5037         {
5038 #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
5039                 FILE* file = 0;
5040                 return fopen_s(&file, path, mode) == 0 ? file : 0;
5041 #else
5042                 return fopen(path, mode);
5043 #endif
5044         }
5045
5046         PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding)
5047         {
5048                 if (!file) return false;
5049
5050                 xml_writer_file writer(file);
5051                 doc.save(writer, indent, flags, encoding);
5052
5053                 return ferror(file) == 0;
5054         }
5055
5056         struct name_null_sentry
5057         {
5058                 xml_node_struct* node;
5059                 char_t* name;
5060
5061                 name_null_sentry(xml_node_struct* node_): node(node_), name(node_->name)
5062                 {
5063                         node->name = 0;
5064                 }
5065
5066                 ~name_null_sentry()
5067                 {
5068                         node->name = name;
5069                 }
5070         };
5071 PUGI__NS_END
5072
5073 namespace pugi
5074 {
5075         PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_)
5076         {
5077         }
5078
5079         PUGI__FN void xml_writer_file::write(const void* data, size_t size)
5080         {
5081                 size_t result = fwrite(data, 1, size, static_cast<FILE*>(file));
5082                 (void)!result; // unfortunately we can't do proper error handling here
5083         }
5084
5085 #ifndef PUGIXML_NO_STL
5086         PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream): narrow_stream(&stream), wide_stream(0)
5087         {
5088         }
5089
5090         PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream): narrow_stream(0), wide_stream(&stream)
5091         {
5092         }
5093
5094         PUGI__FN void xml_writer_stream::write(const void* data, size_t size)
5095         {
5096                 if (narrow_stream)
5097                 {
5098                         assert(!wide_stream);
5099                         narrow_stream->write(reinterpret_cast<const char*>(data), static_cast<std::streamsize>(size));
5100                 }
5101                 else
5102                 {
5103                         assert(wide_stream);
5104                         assert(size % sizeof(wchar_t) == 0);
5105
5106                         wide_stream->write(reinterpret_cast<const wchar_t*>(data), static_cast<std::streamsize>(size / sizeof(wchar_t)));
5107                 }
5108         }
5109 #endif
5110
5111         PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0)
5112         {
5113         }
5114
5115         PUGI__FN xml_tree_walker::~xml_tree_walker()
5116         {
5117         }
5118
5119         PUGI__FN int xml_tree_walker::depth() const
5120         {
5121                 return _depth;
5122         }
5123
5124         PUGI__FN bool xml_tree_walker::begin(xml_node&)
5125         {
5126                 return true;
5127         }
5128
5129         PUGI__FN bool xml_tree_walker::end(xml_node&)
5130         {
5131                 return true;
5132         }
5133
5134         PUGI__FN xml_attribute::xml_attribute(): _attr(0)
5135         {
5136         }
5137
5138         PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr)
5139         {
5140         }
5141
5142         PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***)
5143         {
5144         }
5145
5146         PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const
5147         {
5148                 return _attr ? unspecified_bool_xml_attribute : 0;
5149         }
5150
5151         PUGI__FN bool xml_attribute::operator!() const
5152         {
5153                 return !_attr;
5154         }
5155
5156         PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const
5157         {
5158                 return (_attr == r._attr);
5159         }
5160
5161         PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const
5162         {
5163                 return (_attr != r._attr);
5164         }
5165
5166         PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const
5167         {
5168                 return (_attr < r._attr);
5169         }
5170
5171         PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const
5172         {
5173                 return (_attr > r._attr);
5174         }
5175
5176         PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const
5177         {
5178                 return (_attr <= r._attr);
5179         }
5180
5181         PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const
5182         {
5183                 return (_attr >= r._attr);
5184         }
5185
5186         PUGI__FN xml_attribute xml_attribute::next_attribute() const
5187         {
5188                 return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute();
5189         }
5190
5191         PUGI__FN xml_attribute xml_attribute::previous_attribute() const
5192         {
5193                 return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute();
5194         }
5195
5196         PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const
5197         {
5198                 return (_attr && _attr->value) ? _attr->value + 0 : def;
5199         }
5200
5201         PUGI__FN int xml_attribute::as_int(int def) const
5202         {
5203                 return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def;
5204         }
5205
5206         PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const
5207         {
5208                 return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def;
5209         }
5210
5211         PUGI__FN double xml_attribute::as_double(double def) const
5212         {
5213                 return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def;
5214         }
5215
5216         PUGI__FN float xml_attribute::as_float(float def) const
5217         {
5218                 return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def;
5219         }
5220
5221         PUGI__FN bool xml_attribute::as_bool(bool def) const
5222         {
5223                 return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def;
5224         }
5225
5226 #ifdef PUGIXML_HAS_LONG_LONG
5227         PUGI__FN long long xml_attribute::as_llong(long long def) const
5228         {
5229                 return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def;
5230         }
5231
5232         PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const
5233         {
5234                 return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def;
5235         }
5236 #endif
5237
5238         PUGI__FN bool xml_attribute::empty() const
5239         {
5240                 return !_attr;
5241         }
5242
5243         PUGI__FN const char_t* xml_attribute::name() const
5244         {
5245                 return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT("");
5246         }
5247
5248         PUGI__FN const char_t* xml_attribute::value() const
5249         {
5250                 return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT("");
5251         }
5252
5253         PUGI__FN size_t xml_attribute::hash_value() const
5254         {
5255                 return static_cast<size_t>(reinterpret_cast<uintptr_t>(_attr) / sizeof(xml_attribute_struct));
5256         }
5257
5258         PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const
5259         {
5260                 return _attr;
5261         }
5262
5263         PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs)
5264         {
5265                 set_value(rhs);
5266                 return *this;
5267         }
5268
5269         PUGI__FN xml_attribute& xml_attribute::operator=(int rhs)
5270         {
5271                 set_value(rhs);
5272                 return *this;
5273         }
5274
5275         PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs)
5276         {
5277                 set_value(rhs);
5278                 return *this;
5279         }
5280
5281         PUGI__FN xml_attribute& xml_attribute::operator=(long rhs)
5282         {
5283                 set_value(rhs);
5284                 return *this;
5285         }
5286
5287         PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long rhs)
5288         {
5289                 set_value(rhs);
5290                 return *this;
5291         }
5292
5293         PUGI__FN xml_attribute& xml_attribute::operator=(double rhs)
5294         {
5295                 set_value(rhs);
5296                 return *this;
5297         }
5298
5299         PUGI__FN xml_attribute& xml_attribute::operator=(float rhs)
5300         {
5301                 set_value(rhs);
5302                 return *this;
5303         }
5304
5305         PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs)
5306         {
5307                 set_value(rhs);
5308                 return *this;
5309         }
5310
5311 #ifdef PUGIXML_HAS_LONG_LONG
5312         PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs)
5313         {
5314                 set_value(rhs);
5315                 return *this;
5316         }
5317
5318         PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs)
5319         {
5320                 set_value(rhs);
5321                 return *this;
5322         }
5323 #endif
5324
5325         PUGI__FN bool xml_attribute::set_name(const char_t* rhs)
5326         {
5327                 if (!_attr) return false;
5328
5329                 return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5330         }
5331
5332         PUGI__FN bool xml_attribute::set_value(const char_t* rhs)
5333         {
5334                 if (!_attr) return false;
5335
5336                 return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5337         }
5338
5339         PUGI__FN bool xml_attribute::set_value(int rhs)
5340         {
5341                 if (!_attr) return false;
5342
5343                 return impl::set_value_integer<unsigned int>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5344         }
5345
5346         PUGI__FN bool xml_attribute::set_value(unsigned int rhs)
5347         {
5348                 if (!_attr) return false;
5349
5350                 return impl::set_value_integer<unsigned int>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false);
5351         }
5352
5353         PUGI__FN bool xml_attribute::set_value(long rhs)
5354         {
5355                 if (!_attr) return false;
5356
5357                 return impl::set_value_integer<unsigned long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5358         }
5359
5360         PUGI__FN bool xml_attribute::set_value(unsigned long rhs)
5361         {
5362                 if (!_attr) return false;
5363
5364                 return impl::set_value_integer<unsigned long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false);
5365         }
5366
5367         PUGI__FN bool xml_attribute::set_value(double rhs)
5368         {
5369                 if (!_attr) return false;
5370
5371                 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision);
5372         }
5373
5374         PUGI__FN bool xml_attribute::set_value(double rhs, int precision)
5375         {
5376                 if (!_attr) return false;
5377
5378                 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision);
5379         }
5380
5381         PUGI__FN bool xml_attribute::set_value(float rhs)
5382         {
5383                 if (!_attr) return false;
5384
5385                 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision);
5386         }
5387
5388         PUGI__FN bool xml_attribute::set_value(float rhs, int precision)
5389         {
5390                 if (!_attr) return false;
5391
5392                 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision);
5393         }
5394
5395         PUGI__FN bool xml_attribute::set_value(bool rhs)
5396         {
5397                 if (!_attr) return false;
5398
5399                 return impl::set_value_bool(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
5400         }
5401
5402 #ifdef PUGIXML_HAS_LONG_LONG
5403         PUGI__FN bool xml_attribute::set_value(long long rhs)
5404         {
5405                 if (!_attr) return false;
5406
5407                 return impl::set_value_integer<unsigned long long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5408         }
5409
5410         PUGI__FN bool xml_attribute::set_value(unsigned long long rhs)
5411         {
5412                 if (!_attr) return false;
5413
5414                 return impl::set_value_integer<unsigned long long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false);
5415         }
5416 #endif
5417
5418 #ifdef __BORLANDC__
5419         PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs)
5420         {
5421                 return (bool)lhs && rhs;
5422         }
5423
5424         PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs)
5425         {
5426                 return (bool)lhs || rhs;
5427         }
5428 #endif
5429
5430         PUGI__FN xml_node::xml_node(): _root(0)
5431         {
5432         }
5433
5434         PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p)
5435         {
5436         }
5437
5438         PUGI__FN static void unspecified_bool_xml_node(xml_node***)
5439         {
5440         }
5441
5442         PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const
5443         {
5444                 return _root ? unspecified_bool_xml_node : 0;
5445         }
5446
5447         PUGI__FN bool xml_node::operator!() const
5448         {
5449                 return !_root;
5450         }
5451
5452         PUGI__FN xml_node::iterator xml_node::begin() const
5453         {
5454                 return iterator(_root ? _root->first_child + 0 : 0, _root);
5455         }
5456
5457         PUGI__FN xml_node::iterator xml_node::end() const
5458         {
5459                 return iterator(0, _root);
5460         }
5461
5462         PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const
5463         {
5464                 return attribute_iterator(_root ? _root->first_attribute + 0 : 0, _root);
5465         }
5466
5467         PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const
5468         {
5469                 return attribute_iterator(0, _root);
5470         }
5471
5472         PUGI__FN xml_object_range<xml_node_iterator> xml_node::children() const
5473         {
5474                 return xml_object_range<xml_node_iterator>(begin(), end());
5475         }
5476
5477         PUGI__FN xml_object_range<xml_named_node_iterator> xml_node::children(const char_t* name_) const
5478         {
5479                 return xml_object_range<xml_named_node_iterator>(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_));
5480         }
5481
5482         PUGI__FN xml_object_range<xml_attribute_iterator> xml_node::attributes() const
5483         {
5484                 return xml_object_range<xml_attribute_iterator>(attributes_begin(), attributes_end());
5485         }
5486
5487         PUGI__FN bool xml_node::operator==(const xml_node& r) const
5488         {
5489                 return (_root == r._root);
5490         }
5491
5492         PUGI__FN bool xml_node::operator!=(const xml_node& r) const
5493         {
5494                 return (_root != r._root);
5495         }
5496
5497         PUGI__FN bool xml_node::operator<(const xml_node& r) const
5498         {
5499                 return (_root < r._root);
5500         }
5501
5502         PUGI__FN bool xml_node::operator>(const xml_node& r) const
5503         {
5504                 return (_root > r._root);
5505         }
5506
5507         PUGI__FN bool xml_node::operator<=(const xml_node& r) const
5508         {
5509                 return (_root <= r._root);
5510         }
5511
5512         PUGI__FN bool xml_node::operator>=(const xml_node& r) const
5513         {
5514                 return (_root >= r._root);
5515         }
5516
5517         PUGI__FN bool xml_node::empty() const
5518         {
5519                 return !_root;
5520         }
5521
5522         PUGI__FN const char_t* xml_node::name() const
5523         {
5524                 return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT("");
5525         }
5526
5527         PUGI__FN xml_node_type xml_node::type() const
5528         {
5529                 return _root ? PUGI__NODETYPE(_root) : node_null;
5530         }
5531
5532         PUGI__FN const char_t* xml_node::value() const
5533         {
5534                 return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT("");
5535         }
5536
5537         PUGI__FN xml_node xml_node::child(const char_t* name_) const
5538         {
5539                 if (!_root) return xml_node();
5540
5541                 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
5542                         if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
5543
5544                 return xml_node();
5545         }
5546
5547         PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const
5548         {
5549                 if (!_root) return xml_attribute();
5550
5551                 for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
5552                         if (i->name && impl::strequal(name_, i->name))
5553                                 return xml_attribute(i);
5554
5555                 return xml_attribute();
5556         }
5557
5558         PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const
5559         {
5560                 if (!_root) return xml_node();
5561
5562                 for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
5563                         if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
5564
5565                 return xml_node();
5566         }
5567
5568         PUGI__FN xml_node xml_node::next_sibling() const
5569         {
5570                 return _root ? xml_node(_root->next_sibling) : xml_node();
5571         }
5572
5573         PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const
5574         {
5575                 if (!_root) return xml_node();
5576
5577                 for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
5578                         if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
5579
5580                 return xml_node();
5581         }
5582
5583         PUGI__FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const
5584         {
5585                 xml_attribute_struct* hint = hint_._attr;
5586
5587                 // if hint is not an attribute of node, behavior is not defined
5588                 assert(!hint || (_root && impl::is_attribute_of(hint, _root)));
5589
5590                 if (!_root) return xml_attribute();
5591
5592                 // optimistically search from hint up until the end
5593                 for (xml_attribute_struct* i = hint; i; i = i->next_attribute)
5594                         if (i->name && impl::strequal(name_, i->name))
5595                         {
5596                                 // update hint to maximize efficiency of searching for consecutive attributes
5597                                 hint_._attr = i->next_attribute;
5598
5599                                 return xml_attribute(i);
5600                         }
5601
5602                 // wrap around and search from the first attribute until the hint
5603                 // 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails
5604                 for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute)
5605                         if (j->name && impl::strequal(name_, j->name))
5606                         {
5607                                 // update hint to maximize efficiency of searching for consecutive attributes
5608                                 hint_._attr = j->next_attribute;
5609
5610                                 return xml_attribute(j);
5611                         }
5612
5613                 return xml_attribute();
5614         }
5615
5616         PUGI__FN xml_node xml_node::previous_sibling() const
5617         {
5618                 if (!_root) return xml_node();
5619
5620                 if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c);
5621                 else return xml_node();
5622         }
5623
5624         PUGI__FN xml_node xml_node::parent() const
5625         {
5626                 return _root ? xml_node(_root->parent) : xml_node();
5627         }
5628
5629         PUGI__FN xml_node xml_node::root() const
5630         {
5631                 return _root ? xml_node(&impl::get_document(_root)) : xml_node();
5632         }
5633
5634         PUGI__FN xml_text xml_node::text() const
5635         {
5636                 return xml_text(_root);
5637         }
5638
5639         PUGI__FN const char_t* xml_node::child_value() const
5640         {
5641                 if (!_root) return PUGIXML_TEXT("");
5642
5643                 // element nodes can have value if parse_embed_pcdata was used
5644                 if (PUGI__NODETYPE(_root) == node_element && _root->value)
5645                         return _root->value;
5646
5647                 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
5648                         if (impl::is_text_node(i) && i->value)
5649                                 return i->value;
5650
5651                 return PUGIXML_TEXT("");
5652         }
5653
5654         PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const
5655         {
5656                 return child(name_).child_value();
5657         }
5658
5659         PUGI__FN xml_attribute xml_node::first_attribute() const
5660         {
5661                 return _root ? xml_attribute(_root->first_attribute) : xml_attribute();
5662         }
5663
5664         PUGI__FN xml_attribute xml_node::last_attribute() const
5665         {
5666                 return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute();
5667         }
5668
5669         PUGI__FN xml_node xml_node::first_child() const
5670         {
5671                 return _root ? xml_node(_root->first_child) : xml_node();
5672         }
5673
5674         PUGI__FN xml_node xml_node::last_child() const
5675         {
5676                 return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node();
5677         }
5678
5679         PUGI__FN bool xml_node::set_name(const char_t* rhs)
5680         {
5681                 xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
5682
5683                 if (type_ != node_element && type_ != node_pi && type_ != node_declaration)
5684                         return false;
5685
5686                 return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5687         }
5688
5689         PUGI__FN bool xml_node::set_value(const char_t* rhs)
5690         {
5691                 xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
5692
5693                 if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype)
5694                         return false;
5695
5696                 return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5697         }
5698
5699         PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_)
5700         {
5701                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5702
5703                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5704                 if (!alloc.reserve()) return xml_attribute();
5705
5706                 xml_attribute a(impl::allocate_attribute(alloc));
5707                 if (!a) return xml_attribute();
5708
5709                 impl::append_attribute(a._attr, _root);
5710
5711                 a.set_name(name_);
5712
5713                 return a;
5714         }
5715
5716         PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_)
5717         {
5718                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5719
5720                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5721                 if (!alloc.reserve()) return xml_attribute();
5722
5723                 xml_attribute a(impl::allocate_attribute(alloc));
5724                 if (!a) return xml_attribute();
5725
5726                 impl::prepend_attribute(a._attr, _root);
5727
5728                 a.set_name(name_);
5729
5730                 return a;
5731         }
5732
5733         PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr)
5734         {
5735                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5736                 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
5737
5738                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5739                 if (!alloc.reserve()) return xml_attribute();
5740
5741                 xml_attribute a(impl::allocate_attribute(alloc));
5742                 if (!a) return xml_attribute();
5743
5744                 impl::insert_attribute_after(a._attr, attr._attr, _root);
5745
5746                 a.set_name(name_);
5747
5748                 return a;
5749         }
5750
5751         PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr)
5752         {
5753                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5754                 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
5755
5756                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5757                 if (!alloc.reserve()) return xml_attribute();
5758
5759                 xml_attribute a(impl::allocate_attribute(alloc));
5760                 if (!a) return xml_attribute();
5761
5762                 impl::insert_attribute_before(a._attr, attr._attr, _root);
5763
5764                 a.set_name(name_);
5765
5766                 return a;
5767         }
5768
5769         PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto)
5770         {
5771                 if (!proto) return xml_attribute();
5772                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5773
5774                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5775                 if (!alloc.reserve()) return xml_attribute();
5776
5777                 xml_attribute a(impl::allocate_attribute(alloc));
5778                 if (!a) return xml_attribute();
5779
5780                 impl::append_attribute(a._attr, _root);
5781                 impl::node_copy_attribute(a._attr, proto._attr);
5782
5783                 return a;
5784         }
5785
5786         PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto)
5787         {
5788                 if (!proto) return xml_attribute();
5789                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5790
5791                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5792                 if (!alloc.reserve()) return xml_attribute();
5793
5794                 xml_attribute a(impl::allocate_attribute(alloc));
5795                 if (!a) return xml_attribute();
5796
5797                 impl::prepend_attribute(a._attr, _root);
5798                 impl::node_copy_attribute(a._attr, proto._attr);
5799
5800                 return a;
5801         }
5802
5803         PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr)
5804         {
5805                 if (!proto) return xml_attribute();
5806                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5807                 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
5808
5809                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5810                 if (!alloc.reserve()) return xml_attribute();
5811
5812                 xml_attribute a(impl::allocate_attribute(alloc));
5813                 if (!a) return xml_attribute();
5814
5815                 impl::insert_attribute_after(a._attr, attr._attr, _root);
5816                 impl::node_copy_attribute(a._attr, proto._attr);
5817
5818                 return a;
5819         }
5820
5821         PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr)
5822         {
5823                 if (!proto) return xml_attribute();
5824                 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5825                 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
5826
5827                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5828                 if (!alloc.reserve()) return xml_attribute();
5829
5830                 xml_attribute a(impl::allocate_attribute(alloc));
5831                 if (!a) return xml_attribute();
5832
5833                 impl::insert_attribute_before(a._attr, attr._attr, _root);
5834                 impl::node_copy_attribute(a._attr, proto._attr);
5835
5836                 return a;
5837         }
5838
5839         PUGI__FN xml_node xml_node::append_child(xml_node_type type_)
5840         {
5841                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5842
5843                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5844                 if (!alloc.reserve()) return xml_node();
5845
5846                 xml_node n(impl::allocate_node(alloc, type_));
5847                 if (!n) return xml_node();
5848
5849                 impl::append_node(n._root, _root);
5850
5851                 if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
5852
5853                 return n;
5854         }
5855
5856         PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_)
5857         {
5858                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5859
5860                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5861                 if (!alloc.reserve()) return xml_node();
5862
5863                 xml_node n(impl::allocate_node(alloc, type_));
5864                 if (!n) return xml_node();
5865
5866                 impl::prepend_node(n._root, _root);
5867
5868                 if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
5869
5870                 return n;
5871         }
5872
5873         PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node)
5874         {
5875                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5876                 if (!node._root || node._root->parent != _root) return xml_node();
5877
5878                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5879                 if (!alloc.reserve()) return xml_node();
5880
5881                 xml_node n(impl::allocate_node(alloc, type_));
5882                 if (!n) return xml_node();
5883
5884                 impl::insert_node_before(n._root, node._root);
5885
5886                 if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
5887
5888                 return n;
5889         }
5890
5891         PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node)
5892         {
5893                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5894                 if (!node._root || node._root->parent != _root) return xml_node();
5895
5896                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5897                 if (!alloc.reserve()) return xml_node();
5898
5899                 xml_node n(impl::allocate_node(alloc, type_));
5900                 if (!n) return xml_node();
5901
5902                 impl::insert_node_after(n._root, node._root);
5903
5904                 if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
5905
5906                 return n;
5907         }
5908
5909         PUGI__FN xml_node xml_node::append_child(const char_t* name_)
5910         {
5911                 xml_node result = append_child(node_element);
5912
5913                 result.set_name(name_);
5914
5915                 return result;
5916         }
5917
5918         PUGI__FN xml_node xml_node::prepend_child(const char_t* name_)
5919         {
5920                 xml_node result = prepend_child(node_element);
5921
5922                 result.set_name(name_);
5923
5924                 return result;
5925         }
5926
5927         PUGI__FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node)
5928         {
5929                 xml_node result = insert_child_after(node_element, node);
5930
5931                 result.set_name(name_);
5932
5933                 return result;
5934         }
5935
5936         PUGI__FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node)
5937         {
5938                 xml_node result = insert_child_before(node_element, node);
5939
5940                 result.set_name(name_);
5941
5942                 return result;
5943         }
5944
5945         PUGI__FN xml_node xml_node::append_copy(const xml_node& proto)
5946         {
5947                 xml_node_type type_ = proto.type();
5948                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5949
5950                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5951                 if (!alloc.reserve()) return xml_node();
5952
5953                 xml_node n(impl::allocate_node(alloc, type_));
5954                 if (!n) return xml_node();
5955
5956                 impl::append_node(n._root, _root);
5957                 impl::node_copy_tree(n._root, proto._root);
5958
5959                 return n;
5960         }
5961
5962         PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto)
5963         {
5964                 xml_node_type type_ = proto.type();
5965                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5966
5967                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5968                 if (!alloc.reserve()) return xml_node();
5969
5970                 xml_node n(impl::allocate_node(alloc, type_));
5971                 if (!n) return xml_node();
5972
5973                 impl::prepend_node(n._root, _root);
5974                 impl::node_copy_tree(n._root, proto._root);
5975
5976                 return n;
5977         }
5978
5979         PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node)
5980         {
5981                 xml_node_type type_ = proto.type();
5982                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5983                 if (!node._root || node._root->parent != _root) return xml_node();
5984
5985                 impl::xml_allocator& alloc = impl::get_allocator(_root);
5986                 if (!alloc.reserve()) return xml_node();
5987
5988                 xml_node n(impl::allocate_node(alloc, type_));
5989                 if (!n) return xml_node();
5990
5991                 impl::insert_node_after(n._root, node._root);
5992                 impl::node_copy_tree(n._root, proto._root);
5993
5994                 return n;
5995         }
5996
5997         PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node)
5998         {
5999                 xml_node_type type_ = proto.type();
6000                 if (!impl::allow_insert_child(type(), type_)) return xml_node();
6001                 if (!node._root || node._root->parent != _root) return xml_node();
6002
6003                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6004                 if (!alloc.reserve()) return xml_node();
6005
6006                 xml_node n(impl::allocate_node(alloc, type_));
6007                 if (!n) return xml_node();
6008
6009                 impl::insert_node_before(n._root, node._root);
6010                 impl::node_copy_tree(n._root, proto._root);
6011
6012                 return n;
6013         }
6014
6015         PUGI__FN xml_node xml_node::append_move(const xml_node& moved)
6016         {
6017                 if (!impl::allow_move(*this, moved)) return xml_node();
6018
6019                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6020                 if (!alloc.reserve()) return xml_node();
6021
6022                 // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers
6023                 impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask;
6024
6025                 impl::remove_node(moved._root);
6026                 impl::append_node(moved._root, _root);
6027
6028                 return moved;
6029         }
6030
6031         PUGI__FN xml_node xml_node::prepend_move(const xml_node& moved)
6032         {
6033                 if (!impl::allow_move(*this, moved)) return xml_node();
6034
6035                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6036                 if (!alloc.reserve()) return xml_node();
6037
6038                 // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers
6039                 impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask;
6040
6041                 impl::remove_node(moved._root);
6042                 impl::prepend_node(moved._root, _root);
6043
6044                 return moved;
6045         }
6046
6047         PUGI__FN xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node)
6048         {
6049                 if (!impl::allow_move(*this, moved)) return xml_node();
6050                 if (!node._root || node._root->parent != _root) return xml_node();
6051                 if (moved._root == node._root) return xml_node();
6052
6053                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6054                 if (!alloc.reserve()) return xml_node();
6055
6056                 // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers
6057                 impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask;
6058
6059                 impl::remove_node(moved._root);
6060                 impl::insert_node_after(moved._root, node._root);
6061
6062                 return moved;
6063         }
6064
6065         PUGI__FN xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node)
6066         {
6067                 if (!impl::allow_move(*this, moved)) return xml_node();
6068                 if (!node._root || node._root->parent != _root) return xml_node();
6069                 if (moved._root == node._root) return xml_node();
6070
6071                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6072                 if (!alloc.reserve()) return xml_node();
6073
6074                 // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers
6075                 impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask;
6076
6077                 impl::remove_node(moved._root);
6078                 impl::insert_node_before(moved._root, node._root);
6079
6080                 return moved;
6081         }
6082
6083         PUGI__FN bool xml_node::remove_attribute(const char_t* name_)
6084         {
6085                 return remove_attribute(attribute(name_));
6086         }
6087
6088         PUGI__FN bool xml_node::remove_attribute(const xml_attribute& a)
6089         {
6090                 if (!_root || !a._attr) return false;
6091                 if (!impl::is_attribute_of(a._attr, _root)) return false;
6092
6093                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6094                 if (!alloc.reserve()) return false;
6095
6096                 impl::remove_attribute(a._attr, _root);
6097                 impl::destroy_attribute(a._attr, alloc);
6098
6099                 return true;
6100         }
6101
6102         PUGI__FN bool xml_node::remove_attributes()
6103         {
6104                 if (!_root) return false;
6105
6106                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6107                 if (!alloc.reserve()) return false;
6108
6109                 for (xml_attribute_struct* attr = _root->first_attribute; attr; )
6110                 {
6111                         xml_attribute_struct* next = attr->next_attribute;
6112
6113                         impl::destroy_attribute(attr, alloc);
6114
6115                         attr = next;
6116                 }
6117
6118                 _root->first_attribute = 0;
6119
6120                 return true;
6121         }
6122
6123         PUGI__FN bool xml_node::remove_child(const char_t* name_)
6124         {
6125                 return remove_child(child(name_));
6126         }
6127
6128         PUGI__FN bool xml_node::remove_child(const xml_node& n)
6129         {
6130                 if (!_root || !n._root || n._root->parent != _root) return false;
6131
6132                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6133                 if (!alloc.reserve()) return false;
6134
6135                 impl::remove_node(n._root);
6136                 impl::destroy_node(n._root, alloc);
6137
6138                 return true;
6139         }
6140
6141         PUGI__FN bool xml_node::remove_children()
6142         {
6143                 if (!_root) return false;
6144
6145                 impl::xml_allocator& alloc = impl::get_allocator(_root);
6146                 if (!alloc.reserve()) return false;
6147
6148                 for (xml_node_struct* cur = _root->first_child; cur; )
6149                 {
6150                         xml_node_struct* next = cur->next_sibling;
6151
6152                         impl::destroy_node(cur, alloc);
6153
6154                         cur = next;
6155                 }
6156
6157                 _root->first_child = 0;
6158
6159                 return true;
6160         }
6161
6162         PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding)
6163         {
6164                 // append_buffer is only valid for elements/documents
6165                 if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root);
6166
6167                 // get document node
6168                 impl::xml_document_struct* doc = &impl::get_document(_root);
6169
6170                 // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense
6171                 doc->header |= impl::xml_memory_page_contents_shared_mask;
6172
6173                 // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later)
6174                 impl::xml_memory_page* page = 0;
6175                 impl::xml_extra_buffer* extra = static_cast<impl::xml_extra_buffer*>(doc->allocate_memory(sizeof(impl::xml_extra_buffer) + sizeof(void*), page));
6176                 (void)page;
6177
6178                 if (!extra) return impl::make_parse_result(status_out_of_memory);
6179
6180         #ifdef PUGIXML_COMPACT
6181                 // align the memory block to a pointer boundary; this is required for compact mode where memory allocations are only 4b aligned
6182                 // note that this requires up to sizeof(void*)-1 additional memory, which the allocation above takes into account
6183                 extra = reinterpret_cast<impl::xml_extra_buffer*>((reinterpret_cast<uintptr_t>(extra) + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1));
6184         #endif
6185
6186                 // add extra buffer to the list
6187                 extra->buffer = 0;
6188                 extra->next = doc->extra_buffers;
6189                 doc->extra_buffers = extra;
6190
6191                 // name of the root has to be NULL before parsing - otherwise closing node mismatches will not be detected at the top level
6192                 impl::name_null_sentry sentry(_root);
6193
6194                 return impl::load_buffer_impl(doc, _root, const_cast<void*>(contents), size, options, encoding, false, false, &extra->buffer);
6195         }
6196
6197         PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const
6198         {
6199                 if (!_root) return xml_node();
6200
6201                 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
6202                         if (i->name && impl::strequal(name_, i->name))
6203                         {
6204                                 for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
6205                                         if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
6206                                                 return xml_node(i);
6207                         }
6208
6209                 return xml_node();
6210         }
6211
6212         PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const
6213         {
6214                 if (!_root) return xml_node();
6215
6216                 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
6217                         for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
6218                                 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
6219                                         return xml_node(i);
6220
6221                 return xml_node();
6222         }
6223
6224 #ifndef PUGIXML_NO_STL
6225         PUGI__FN string_t xml_node::path(char_t delimiter) const
6226         {
6227                 if (!_root) return string_t();
6228
6229                 size_t offset = 0;
6230
6231                 for (xml_node_struct* i = _root; i; i = i->parent)
6232                 {
6233                         offset += (i != _root);
6234                         offset += i->name ? impl::strlength(i->name) : 0;
6235                 }
6236
6237                 string_t result;
6238                 result.resize(offset);
6239
6240                 for (xml_node_struct* j = _root; j; j = j->parent)
6241                 {
6242                         if (j != _root)
6243                                 result[--offset] = delimiter;
6244
6245                         if (j->name)
6246                         {
6247                                 size_t length = impl::strlength(j->name);
6248
6249                                 offset -= length;
6250                                 memcpy(&result[offset], j->name, length * sizeof(char_t));
6251                         }
6252                 }
6253
6254                 assert(offset == 0);
6255
6256                 return result;
6257         }
6258 #endif
6259
6260         PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const
6261         {
6262                 xml_node context = path_[0] == delimiter ? root() : *this;
6263
6264                 if (!context._root) return xml_node();
6265
6266                 const char_t* path_segment = path_;
6267
6268                 while (*path_segment == delimiter) ++path_segment;
6269
6270                 const char_t* path_segment_end = path_segment;
6271
6272                 while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end;
6273
6274                 if (path_segment == path_segment_end) return context;
6275
6276                 const char_t* next_segment = path_segment_end;
6277
6278                 while (*next_segment == delimiter) ++next_segment;
6279
6280                 if (*path_segment == '.' && path_segment + 1 == path_segment_end)
6281                         return context.first_element_by_path(next_segment, delimiter);
6282                 else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end)
6283                         return context.parent().first_element_by_path(next_segment, delimiter);
6284                 else
6285                 {
6286                         for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling)
6287                         {
6288                                 if (j->name && impl::strequalrange(j->name, path_segment, static_cast<size_t>(path_segment_end - path_segment)))
6289                                 {
6290                                         xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter);
6291
6292                                         if (subsearch) return subsearch;
6293                                 }
6294                         }
6295
6296                         return xml_node();
6297                 }
6298         }
6299
6300         PUGI__FN bool xml_node::traverse(xml_tree_walker& walker)
6301         {
6302                 walker._depth = -1;
6303
6304                 xml_node arg_begin(_root);
6305                 if (!walker.begin(arg_begin)) return false;
6306
6307                 xml_node_struct* cur = _root ? _root->first_child + 0 : 0;
6308
6309                 if (cur)
6310                 {
6311                         ++walker._depth;
6312
6313                         do
6314                         {
6315                                 xml_node arg_for_each(cur);
6316                                 if (!walker.for_each(arg_for_each))
6317                                         return false;
6318
6319                                 if (cur->first_child)
6320                                 {
6321                                         ++walker._depth;
6322                                         cur = cur->first_child;
6323                                 }
6324                                 else if (cur->next_sibling)
6325                                         cur = cur->next_sibling;
6326                                 else
6327                                 {
6328                                         while (!cur->next_sibling && cur != _root && cur->parent)
6329                                         {
6330                                                 --walker._depth;
6331                                                 cur = cur->parent;
6332                                         }
6333
6334                                         if (cur != _root)
6335                                                 cur = cur->next_sibling;
6336                                 }
6337                         }
6338                         while (cur && cur != _root);
6339                 }
6340
6341                 assert(walker._depth == -1);
6342
6343                 xml_node arg_end(_root);
6344                 return walker.end(arg_end);
6345         }
6346
6347         PUGI__FN size_t xml_node::hash_value() const
6348         {
6349                 return static_cast<size_t>(reinterpret_cast<uintptr_t>(_root) / sizeof(xml_node_struct));
6350         }
6351
6352         PUGI__FN xml_node_struct* xml_node::internal_object() const
6353         {
6354                 return _root;
6355         }
6356
6357         PUGI__FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const
6358         {
6359                 if (!_root) return;
6360
6361                 impl::xml_buffered_writer buffered_writer(writer, encoding);
6362
6363                 impl::node_output(buffered_writer, _root, indent, flags, depth);
6364
6365                 buffered_writer.flush();
6366         }
6367
6368 #ifndef PUGIXML_NO_STL
6369         PUGI__FN void xml_node::print(std::basic_ostream<char, std::char_traits<char> >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const
6370         {
6371                 xml_writer_stream writer(stream);
6372
6373                 print(writer, indent, flags, encoding, depth);
6374         }
6375
6376         PUGI__FN void xml_node::print(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const
6377         {
6378                 xml_writer_stream writer(stream);
6379
6380                 print(writer, indent, flags, encoding_wchar, depth);
6381         }
6382 #endif
6383
6384         PUGI__FN ptrdiff_t xml_node::offset_debug() const
6385         {
6386                 if (!_root) return -1;
6387
6388                 impl::xml_document_struct& doc = impl::get_document(_root);
6389
6390                 // we can determine the offset reliably only if there is exactly once parse buffer
6391                 if (!doc.buffer || doc.extra_buffers) return -1;
6392
6393                 switch (type())
6394                 {
6395                 case node_document:
6396                         return 0;
6397
6398                 case node_element:
6399                 case node_declaration:
6400                 case node_pi:
6401                         return _root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0 ? _root->name - doc.buffer : -1;
6402
6403                 case node_pcdata:
6404                 case node_cdata:
6405                 case node_comment:
6406                 case node_doctype:
6407                         return _root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0 ? _root->value - doc.buffer : -1;
6408
6409                 default:
6410                         assert(false && "Invalid node type"); // unreachable
6411                         return -1;
6412                 }
6413         }
6414
6415 #ifdef __BORLANDC__
6416         PUGI__FN bool operator&&(const xml_node& lhs, bool rhs)
6417         {
6418                 return (bool)lhs && rhs;
6419         }
6420
6421         PUGI__FN bool operator||(const xml_node& lhs, bool rhs)
6422         {
6423                 return (bool)lhs || rhs;
6424         }
6425 #endif
6426
6427         PUGI__FN xml_text::xml_text(xml_node_struct* root): _root(root)
6428         {
6429         }
6430
6431         PUGI__FN xml_node_struct* xml_text::_data() const
6432         {
6433                 if (!_root || impl::is_text_node(_root)) return _root;
6434
6435                 // element nodes can have value if parse_embed_pcdata was used
6436                 if (PUGI__NODETYPE(_root) == node_element && _root->value)
6437                         return _root;
6438
6439                 for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling)
6440                         if (impl::is_text_node(node))
6441                                 return node;
6442
6443                 return 0;
6444         }
6445
6446         PUGI__FN xml_node_struct* xml_text::_data_new()
6447         {
6448                 xml_node_struct* d = _data();
6449                 if (d) return d;
6450
6451                 return xml_node(_root).append_child(node_pcdata).internal_object();
6452         }
6453
6454         PUGI__FN xml_text::xml_text(): _root(0)
6455         {
6456         }
6457
6458         PUGI__FN static void unspecified_bool_xml_text(xml_text***)
6459         {
6460         }
6461
6462         PUGI__FN xml_text::operator xml_text::unspecified_bool_type() const
6463         {
6464                 return _data() ? unspecified_bool_xml_text : 0;
6465         }
6466
6467         PUGI__FN bool xml_text::operator!() const
6468         {
6469                 return !_data();
6470         }
6471
6472         PUGI__FN bool xml_text::empty() const
6473         {
6474                 return _data() == 0;
6475         }
6476
6477         PUGI__FN const char_t* xml_text::get() const
6478         {
6479                 xml_node_struct* d = _data();
6480
6481                 return (d && d->value) ? d->value + 0 : PUGIXML_TEXT("");
6482         }
6483
6484         PUGI__FN const char_t* xml_text::as_string(const char_t* def) const
6485         {
6486                 xml_node_struct* d = _data();
6487
6488                 return (d && d->value) ? d->value + 0 : def;
6489         }
6490
6491         PUGI__FN int xml_text::as_int(int def) const
6492         {
6493                 xml_node_struct* d = _data();
6494
6495                 return (d && d->value) ? impl::get_value_int(d->value) : def;
6496         }
6497
6498         PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const
6499         {
6500                 xml_node_struct* d = _data();
6501
6502                 return (d && d->value) ? impl::get_value_uint(d->value) : def;
6503         }
6504
6505         PUGI__FN double xml_text::as_double(double def) const
6506         {
6507                 xml_node_struct* d = _data();
6508
6509                 return (d && d->value) ? impl::get_value_double(d->value) : def;
6510         }
6511
6512         PUGI__FN float xml_text::as_float(float def) const
6513         {
6514                 xml_node_struct* d = _data();
6515
6516                 return (d && d->value) ? impl::get_value_float(d->value) : def;
6517         }
6518
6519         PUGI__FN bool xml_text::as_bool(bool def) const
6520         {
6521                 xml_node_struct* d = _data();
6522
6523                 return (d && d->value) ? impl::get_value_bool(d->value) : def;
6524         }
6525
6526 #ifdef PUGIXML_HAS_LONG_LONG
6527         PUGI__FN long long xml_text::as_llong(long long def) const
6528         {
6529                 xml_node_struct* d = _data();
6530
6531                 return (d && d->value) ? impl::get_value_llong(d->value) : def;
6532         }
6533
6534         PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const
6535         {
6536                 xml_node_struct* d = _data();
6537
6538                 return (d && d->value) ? impl::get_value_ullong(d->value) : def;
6539         }
6540 #endif
6541
6542         PUGI__FN bool xml_text::set(const char_t* rhs)
6543         {
6544                 xml_node_struct* dn = _data_new();
6545
6546                 return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) : false;
6547         }
6548
6549         PUGI__FN bool xml_text::set(int rhs)
6550         {
6551                 xml_node_struct* dn = _data_new();
6552
6553                 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6554         }
6555
6556         PUGI__FN bool xml_text::set(unsigned int rhs)
6557         {
6558                 xml_node_struct* dn = _data_new();
6559
6560                 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false;
6561         }
6562
6563         PUGI__FN bool xml_text::set(long rhs)
6564         {
6565                 xml_node_struct* dn = _data_new();
6566
6567                 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6568         }
6569
6570         PUGI__FN bool xml_text::set(unsigned long rhs)
6571         {
6572                 xml_node_struct* dn = _data_new();
6573
6574                 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false;
6575         }
6576
6577         PUGI__FN bool xml_text::set(float rhs)
6578         {
6579                 xml_node_struct* dn = _data_new();
6580
6581                 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision) : false;
6582         }
6583
6584         PUGI__FN bool xml_text::set(float rhs, int precision)
6585         {
6586                 xml_node_struct* dn = _data_new();
6587
6588                 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false;
6589         }
6590
6591         PUGI__FN bool xml_text::set(double rhs)
6592         {
6593                 xml_node_struct* dn = _data_new();
6594
6595                 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision) : false;
6596         }
6597
6598         PUGI__FN bool xml_text::set(double rhs, int precision)
6599         {
6600                 xml_node_struct* dn = _data_new();
6601
6602                 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false;
6603         }
6604
6605         PUGI__FN bool xml_text::set(bool rhs)
6606         {
6607                 xml_node_struct* dn = _data_new();
6608
6609                 return dn ? impl::set_value_bool(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
6610         }
6611
6612 #ifdef PUGIXML_HAS_LONG_LONG
6613         PUGI__FN bool xml_text::set(long long rhs)
6614         {
6615                 xml_node_struct* dn = _data_new();
6616
6617                 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6618         }
6619
6620         PUGI__FN bool xml_text::set(unsigned long long rhs)
6621         {
6622                 xml_node_struct* dn = _data_new();
6623
6624                 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false;
6625         }
6626 #endif
6627
6628         PUGI__FN xml_text& xml_text::operator=(const char_t* rhs)
6629         {
6630                 set(rhs);
6631                 return *this;
6632         }
6633
6634         PUGI__FN xml_text& xml_text::operator=(int rhs)
6635         {
6636                 set(rhs);
6637                 return *this;
6638         }
6639
6640         PUGI__FN xml_text& xml_text::operator=(unsigned int rhs)
6641         {
6642                 set(rhs);
6643                 return *this;
6644         }
6645
6646         PUGI__FN xml_text& xml_text::operator=(long rhs)
6647         {
6648                 set(rhs);
6649                 return *this;
6650         }
6651
6652         PUGI__FN xml_text& xml_text::operator=(unsigned long rhs)
6653         {
6654                 set(rhs);
6655                 return *this;
6656         }
6657
6658         PUGI__FN xml_text& xml_text::operator=(double rhs)
6659         {
6660                 set(rhs);
6661                 return *this;
6662         }
6663
6664         PUGI__FN xml_text& xml_text::operator=(float rhs)
6665         {
6666                 set(rhs);
6667                 return *this;
6668         }
6669
6670         PUGI__FN xml_text& xml_text::operator=(bool rhs)
6671         {
6672                 set(rhs);
6673                 return *this;
6674         }
6675
6676 #ifdef PUGIXML_HAS_LONG_LONG
6677         PUGI__FN xml_text& xml_text::operator=(long long rhs)
6678         {
6679                 set(rhs);
6680                 return *this;
6681         }
6682
6683         PUGI__FN xml_text& xml_text::operator=(unsigned long long rhs)
6684         {
6685                 set(rhs);
6686                 return *this;
6687         }
6688 #endif
6689
6690         PUGI__FN xml_node xml_text::data() const
6691         {
6692                 return xml_node(_data());
6693         }
6694
6695 #ifdef __BORLANDC__
6696         PUGI__FN bool operator&&(const xml_text& lhs, bool rhs)
6697         {
6698                 return (bool)lhs && rhs;
6699         }
6700
6701         PUGI__FN bool operator||(const xml_text& lhs, bool rhs)
6702         {
6703                 return (bool)lhs || rhs;
6704         }
6705 #endif
6706
6707         PUGI__FN xml_node_iterator::xml_node_iterator()
6708         {
6709         }
6710
6711         PUGI__FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent())
6712         {
6713         }
6714
6715         PUGI__FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent)
6716         {
6717         }
6718
6719         PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const
6720         {
6721                 return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root;
6722         }
6723
6724         PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const
6725         {
6726                 return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root;
6727         }
6728
6729         PUGI__FN xml_node& xml_node_iterator::operator*() const
6730         {
6731                 assert(_wrap._root);
6732                 return _wrap;
6733         }
6734
6735         PUGI__FN xml_node* xml_node_iterator::operator->() const
6736         {
6737                 assert(_wrap._root);
6738                 return const_cast<xml_node*>(&_wrap); // BCC5 workaround
6739         }
6740
6741         PUGI__FN xml_node_iterator& xml_node_iterator::operator++()
6742         {
6743                 assert(_wrap._root);
6744                 _wrap._root = _wrap._root->next_sibling;
6745                 return *this;
6746         }
6747
6748         PUGI__FN xml_node_iterator xml_node_iterator::operator++(int)
6749         {
6750                 xml_node_iterator temp = *this;
6751                 ++*this;
6752                 return temp;
6753         }
6754
6755         PUGI__FN xml_node_iterator& xml_node_iterator::operator--()
6756         {
6757                 _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child();
6758                 return *this;
6759         }
6760
6761         PUGI__FN xml_node_iterator xml_node_iterator::operator--(int)
6762         {
6763                 xml_node_iterator temp = *this;
6764                 --*this;
6765                 return temp;
6766         }
6767
6768         PUGI__FN xml_attribute_iterator::xml_attribute_iterator()
6769         {
6770         }
6771
6772         PUGI__FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent)
6773         {
6774         }
6775
6776         PUGI__FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent)
6777         {
6778         }
6779
6780         PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const
6781         {
6782                 return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root;
6783         }
6784
6785         PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const
6786         {
6787                 return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root;
6788         }
6789
6790         PUGI__FN xml_attribute& xml_attribute_iterator::operator*() const
6791         {
6792                 assert(_wrap._attr);
6793                 return _wrap;
6794         }
6795
6796         PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const
6797         {
6798                 assert(_wrap._attr);
6799                 return const_cast<xml_attribute*>(&_wrap); // BCC5 workaround
6800         }
6801
6802         PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator++()
6803         {
6804                 assert(_wrap._attr);
6805                 _wrap._attr = _wrap._attr->next_attribute;
6806                 return *this;
6807         }
6808
6809         PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator++(int)
6810         {
6811                 xml_attribute_iterator temp = *this;
6812                 ++*this;
6813                 return temp;
6814         }
6815
6816         PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator--()
6817         {
6818                 _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute();
6819                 return *this;
6820         }
6821
6822         PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator--(int)
6823         {
6824                 xml_attribute_iterator temp = *this;
6825                 --*this;
6826                 return temp;
6827         }
6828
6829         PUGI__FN xml_named_node_iterator::xml_named_node_iterator(): _name(0)
6830         {
6831         }
6832
6833         PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name)
6834         {
6835         }
6836
6837         PUGI__FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name)
6838         {
6839         }
6840
6841         PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const
6842         {
6843                 return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root;
6844         }
6845
6846         PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const
6847         {
6848                 return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root;
6849         }
6850
6851         PUGI__FN xml_node& xml_named_node_iterator::operator*() const
6852         {
6853                 assert(_wrap._root);
6854                 return _wrap;
6855         }
6856
6857         PUGI__FN xml_node* xml_named_node_iterator::operator->() const
6858         {
6859                 assert(_wrap._root);
6860                 return const_cast<xml_node*>(&_wrap); // BCC5 workaround
6861         }
6862
6863         PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator++()
6864         {
6865                 assert(_wrap._root);
6866                 _wrap = _wrap.next_sibling(_name);
6867                 return *this;
6868         }
6869
6870         PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator++(int)
6871         {
6872                 xml_named_node_iterator temp = *this;
6873                 ++*this;
6874                 return temp;
6875         }
6876
6877         PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator--()
6878         {
6879                 if (_wrap._root)
6880                         _wrap = _wrap.previous_sibling(_name);
6881                 else
6882                 {
6883                         _wrap = _parent.last_child();
6884
6885                         if (!impl::strequal(_wrap.name(), _name))
6886                                 _wrap = _wrap.previous_sibling(_name);
6887                 }
6888
6889                 return *this;
6890         }
6891
6892         PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator--(int)
6893         {
6894                 xml_named_node_iterator temp = *this;
6895                 --*this;
6896                 return temp;
6897         }
6898
6899         PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto)
6900         {
6901         }
6902
6903         PUGI__FN xml_parse_result::operator bool() const
6904         {
6905                 return status == status_ok;
6906         }
6907
6908         PUGI__FN const char* xml_parse_result::description() const
6909         {
6910                 switch (status)
6911                 {
6912                 case status_ok: return "No error";
6913
6914                 case status_file_not_found: return "File was not found";
6915                 case status_io_error: return "Error reading from file/stream";
6916                 case status_out_of_memory: return "Could not allocate memory";
6917                 case status_internal_error: return "Internal error occurred";
6918
6919                 case status_unrecognized_tag: return "Could not determine tag type";
6920
6921                 case status_bad_pi: return "Error parsing document declaration/processing instruction";
6922                 case status_bad_comment: return "Error parsing comment";
6923                 case status_bad_cdata: return "Error parsing CDATA section";
6924                 case status_bad_doctype: return "Error parsing document type declaration";
6925                 case status_bad_pcdata: return "Error parsing PCDATA section";
6926                 case status_bad_start_element: return "Error parsing start element tag";
6927                 case status_bad_attribute: return "Error parsing element attribute";
6928                 case status_bad_end_element: return "Error parsing end element tag";
6929                 case status_end_element_mismatch: return "Start-end tags mismatch";
6930
6931                 case status_append_invalid_root: return "Unable to append nodes: root is not an element or document";
6932
6933                 case status_no_document_element: return "No document element found";
6934
6935                 default: return "Unknown error";
6936                 }
6937         }
6938
6939         PUGI__FN xml_document::xml_document(): _buffer(0)
6940         {
6941                 _create();
6942         }
6943
6944         PUGI__FN xml_document::~xml_document()
6945         {
6946                 _destroy();
6947         }
6948
6949 #ifdef PUGIXML_HAS_MOVE
6950         PUGI__FN xml_document::xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT: _buffer(0)
6951         {
6952                 _create();
6953                 _move(rhs);
6954         }
6955
6956         PUGI__FN xml_document& xml_document::operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT
6957         {
6958                 if (this == &rhs) return *this;
6959
6960                 _destroy();
6961                 _create();
6962                 _move(rhs);
6963
6964                 return *this;
6965         }
6966 #endif
6967
6968         PUGI__FN void xml_document::reset()
6969         {
6970                 _destroy();
6971                 _create();
6972         }
6973
6974         PUGI__FN void xml_document::reset(const xml_document& proto)
6975         {
6976                 reset();
6977
6978                 impl::node_copy_tree(_root, proto._root);
6979         }
6980
6981         PUGI__FN void xml_document::_create()
6982         {
6983                 assert(!_root);
6984
6985         #ifdef PUGIXML_COMPACT
6986                 // space for page marker for the first page (uint32_t), rounded up to pointer size; assumes pointers are at least 32-bit
6987                 const size_t page_offset = sizeof(void*);
6988         #else
6989                 const size_t page_offset = 0;
6990         #endif
6991
6992                 // initialize sentinel page
6993                 PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + page_offset <= sizeof(_memory));
6994
6995                 // prepare page structure
6996                 impl::xml_memory_page* page = impl::xml_memory_page::construct(_memory);
6997                 assert(page);
6998
6999                 page->busy_size = impl::xml_memory_page_size;
7000
7001                 // setup first page marker
7002         #ifdef PUGIXML_COMPACT
7003                 // round-trip through void* to avoid 'cast increases required alignment of target type' warning
7004                 page->compact_page_marker = reinterpret_cast<uint32_t*>(static_cast<void*>(reinterpret_cast<char*>(page) + sizeof(impl::xml_memory_page)));
7005                 *page->compact_page_marker = sizeof(impl::xml_memory_page);
7006         #endif
7007
7008                 // allocate new root
7009                 _root = new (reinterpret_cast<char*>(page) + sizeof(impl::xml_memory_page) + page_offset) impl::xml_document_struct(page);
7010                 _root->prev_sibling_c = _root;
7011
7012                 // setup sentinel page
7013                 page->allocator = static_cast<impl::xml_document_struct*>(_root);
7014
7015                 // setup hash table pointer in allocator
7016         #ifdef PUGIXML_COMPACT
7017                 page->allocator->_hash = &static_cast<impl::xml_document_struct*>(_root)->hash;
7018         #endif
7019
7020                 // verify the document allocation
7021                 assert(reinterpret_cast<char*>(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory));
7022         }
7023
7024         PUGI__FN void xml_document::_destroy()
7025         {
7026                 assert(_root);
7027
7028                 // destroy static storage
7029                 if (_buffer)
7030                 {
7031                         impl::xml_memory::deallocate(_buffer);
7032                         _buffer = 0;
7033                 }
7034
7035                 // destroy extra buffers (note: no need to destroy linked list nodes, they're allocated using document allocator)
7036                 for (impl::xml_extra_buffer* extra = static_cast<impl::xml_document_struct*>(_root)->extra_buffers; extra; extra = extra->next)
7037                 {
7038                         if (extra->buffer) impl::xml_memory::deallocate(extra->buffer);
7039                 }
7040
7041                 // destroy dynamic storage, leave sentinel page (it's in static memory)
7042                 impl::xml_memory_page* root_page = PUGI__GETPAGE(_root);
7043                 assert(root_page && !root_page->prev);
7044                 assert(reinterpret_cast<char*>(root_page) >= _memory && reinterpret_cast<char*>(root_page) < _memory + sizeof(_memory));
7045
7046                 for (impl::xml_memory_page* page = root_page->next; page; )
7047                 {
7048                         impl::xml_memory_page* next = page->next;
7049
7050                         impl::xml_allocator::deallocate_page(page);
7051
7052                         page = next;
7053                 }
7054
7055         #ifdef PUGIXML_COMPACT
7056                 // destroy hash table
7057                 static_cast<impl::xml_document_struct*>(_root)->hash.clear();
7058         #endif
7059
7060                 _root = 0;
7061         }
7062
7063 #ifdef PUGIXML_HAS_MOVE
7064         PUGI__FN void xml_document::_move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT
7065         {
7066                 impl::xml_document_struct* doc = static_cast<impl::xml_document_struct*>(_root);
7067                 impl::xml_document_struct* other = static_cast<impl::xml_document_struct*>(rhs._root);
7068
7069                 // save first child pointer for later; this needs hash access
7070                 xml_node_struct* other_first_child = other->first_child;
7071
7072         #ifdef PUGIXML_COMPACT
7073                 // reserve space for the hash table up front; this is the only operation that can fail
7074                 // if it does, we have no choice but to throw (if we have exceptions)
7075                 if (other_first_child)
7076                 {
7077                         size_t other_children = 0;
7078                         for (xml_node_struct* node = other_first_child; node; node = node->next_sibling)
7079                                 other_children++;
7080
7081                         // in compact mode, each pointer assignment could result in a hash table request
7082                         // during move, we have to relocate document first_child and parents of all children
7083                         // normally there's just one child and its parent has a pointerless encoding but
7084                         // we assume the worst here
7085                         if (!other->_hash->reserve(other_children + 1))
7086                         {
7087                         #ifdef PUGIXML_NO_EXCEPTIONS
7088                                 return;
7089                         #else
7090                                 throw std::bad_alloc();
7091                         #endif
7092                         }
7093                 }
7094         #endif
7095
7096                 // move allocation state
7097                 // note that other->_root may point to the embedded document page, in which case we should keep original (empty) state
7098                 if (other->_root != PUGI__GETPAGE(other))
7099                 {
7100                         doc->_root = other->_root;
7101                         doc->_busy_size = other->_busy_size;
7102                 }
7103
7104                 // move buffer state
7105                 doc->buffer = other->buffer;
7106                 doc->extra_buffers = other->extra_buffers;
7107                 _buffer = rhs._buffer;
7108
7109         #ifdef PUGIXML_COMPACT
7110                 // move compact hash; note that the hash table can have pointers to other but they will be "inactive", similarly to nodes removed with remove_child
7111                 doc->hash = other->hash;
7112                 doc->_hash = &doc->hash;
7113
7114                 // make sure we don't access other hash up until the end when we reinitialize other document
7115                 other->_hash = 0;
7116         #endif
7117
7118                 // move page structure
7119                 impl::xml_memory_page* doc_page = PUGI__GETPAGE(doc);
7120                 assert(doc_page && !doc_page->prev && !doc_page->next);
7121
7122                 impl::xml_memory_page* other_page = PUGI__GETPAGE(other);
7123                 assert(other_page && !other_page->prev);
7124
7125                 // relink pages since root page is embedded into xml_document
7126                 if (impl::xml_memory_page* page = other_page->next)
7127                 {
7128                         assert(page->prev == other_page);
7129
7130                         page->prev = doc_page;
7131
7132                         doc_page->next = page;
7133                         other_page->next = 0;
7134                 }
7135
7136                 // make sure pages point to the correct document state
7137                 for (impl::xml_memory_page* page = doc_page->next; page; page = page->next)
7138                 {
7139                         assert(page->allocator == other);
7140
7141                         page->allocator = doc;
7142
7143                 #ifdef PUGIXML_COMPACT
7144                         // this automatically migrates most children between documents and prevents ->parent assignment from allocating
7145                         if (page->compact_shared_parent == other)
7146                                 page->compact_shared_parent = doc;
7147                 #endif
7148                 }
7149
7150                 // move tree structure
7151                 assert(!doc->first_child);
7152
7153                 doc->first_child = other_first_child;
7154
7155                 for (xml_node_struct* node = other_first_child; node; node = node->next_sibling)
7156                 {
7157                 #ifdef PUGIXML_COMPACT
7158                         // most children will have migrated when we reassigned compact_shared_parent
7159                         assert(node->parent == other || node->parent == doc);
7160
7161                         node->parent = doc;
7162                 #else
7163                         assert(node->parent == other);
7164                         node->parent = doc;
7165                 #endif
7166                 }
7167
7168                 // reset other document
7169                 new (other) impl::xml_document_struct(PUGI__GETPAGE(other));
7170                 rhs._buffer = 0;
7171         }
7172 #endif
7173
7174 #ifndef PUGIXML_NO_STL
7175         PUGI__FN xml_parse_result xml_document::load(std::basic_istream<char, std::char_traits<char> >& stream, unsigned int options, xml_encoding encoding)
7176         {
7177                 reset();
7178
7179                 return impl::load_stream_impl(static_cast<impl::xml_document_struct*>(_root), stream, options, encoding, &_buffer);
7180         }
7181
7182         PUGI__FN xml_parse_result xml_document::load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options)
7183         {
7184                 reset();
7185
7186                 return impl::load_stream_impl(static_cast<impl::xml_document_struct*>(_root), stream, options, encoding_wchar, &_buffer);
7187         }
7188 #endif
7189
7190         PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options)
7191         {
7192                 // Force native encoding (skip autodetection)
7193         #ifdef PUGIXML_WCHAR_MODE
7194                 xml_encoding encoding = encoding_wchar;
7195         #else
7196                 xml_encoding encoding = encoding_utf8;
7197         #endif
7198
7199                 return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding);
7200         }
7201
7202         PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options)
7203         {
7204                 return load_string(contents, options);
7205         }
7206
7207         PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding)
7208         {
7209                 reset();
7210
7211                 using impl::auto_deleter; // MSVC7 workaround
7212                 auto_deleter<FILE> file(impl::open_file(path_, "rb"), impl::close_file);
7213
7214                 return impl::load_file_impl(static_cast<impl::xml_document_struct*>(_root), file.data, options, encoding, &_buffer);
7215         }
7216
7217         PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding)
7218         {
7219                 reset();
7220
7221                 using impl::auto_deleter; // MSVC7 workaround
7222                 auto_deleter<FILE> file(impl::open_file_wide(path_, L"rb"), impl::close_file);
7223
7224                 return impl::load_file_impl(static_cast<impl::xml_document_struct*>(_root), file.data, options, encoding, &_buffer);
7225         }
7226
7227         PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding)
7228         {
7229                 reset();
7230
7231                 return impl::load_buffer_impl(static_cast<impl::xml_document_struct*>(_root), _root, const_cast<void*>(contents), size, options, encoding, false, false, &_buffer);
7232         }
7233
7234         PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding)
7235         {
7236                 reset();
7237
7238                 return impl::load_buffer_impl(static_cast<impl::xml_document_struct*>(_root), _root, contents, size, options, encoding, true, false, &_buffer);
7239         }
7240
7241         PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding)
7242         {
7243                 reset();
7244
7245                 return impl::load_buffer_impl(static_cast<impl::xml_document_struct*>(_root), _root, contents, size, options, encoding, true, true, &_buffer);
7246         }
7247
7248         PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const
7249         {
7250                 impl::xml_buffered_writer buffered_writer(writer, encoding);
7251
7252                 if ((flags & format_write_bom) && encoding != encoding_latin1)
7253                 {
7254                         // BOM always represents the codepoint U+FEFF, so just write it in native encoding
7255                 #ifdef PUGIXML_WCHAR_MODE
7256                         unsigned int bom = 0xfeff;
7257                         buffered_writer.write(static_cast<wchar_t>(bom));
7258                 #else
7259                         buffered_writer.write('\xef', '\xbb', '\xbf');
7260                 #endif
7261                 }
7262
7263                 if (!(flags & format_no_declaration) && !impl::has_declaration(_root))
7264                 {
7265                         buffered_writer.write_string(PUGIXML_TEXT("<?xml version=\"1.0\""));
7266                         if (encoding == encoding_latin1) buffered_writer.write_string(PUGIXML_TEXT(" encoding=\"ISO-8859-1\""));
7267                         buffered_writer.write('?', '>');
7268                         if (!(flags & format_raw)) buffered_writer.write('\n');
7269                 }
7270
7271                 impl::node_output(buffered_writer, _root, indent, flags, 0);
7272
7273                 buffered_writer.flush();
7274         }
7275
7276 #ifndef PUGIXML_NO_STL
7277         PUGI__FN void xml_document::save(std::basic_ostream<char, std::char_traits<char> >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const
7278         {
7279                 xml_writer_stream writer(stream);
7280
7281                 save(writer, indent, flags, encoding);
7282         }
7283
7284         PUGI__FN void xml_document::save(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent, unsigned int flags) const
7285         {
7286                 xml_writer_stream writer(stream);
7287
7288                 save(writer, indent, flags, encoding_wchar);
7289         }
7290 #endif
7291
7292         PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
7293         {
7294                 using impl::auto_deleter; // MSVC7 workaround
7295                 auto_deleter<FILE> file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file);
7296
7297                 return impl::save_file_impl(*this, file.data, indent, flags, encoding);
7298         }
7299
7300         PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
7301         {
7302                 using impl::auto_deleter; // MSVC7 workaround
7303                 auto_deleter<FILE> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file);
7304
7305                 return impl::save_file_impl(*this, file.data, indent, flags, encoding);
7306         }
7307
7308         PUGI__FN xml_node xml_document::document_element() const
7309         {
7310                 assert(_root);
7311
7312                 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
7313                         if (PUGI__NODETYPE(i) == node_element)
7314                                 return xml_node(i);
7315
7316                 return xml_node();
7317         }
7318
7319 #ifndef PUGIXML_NO_STL
7320         PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str)
7321         {
7322                 assert(str);
7323
7324                 return impl::as_utf8_impl(str, impl::strlength_wide(str));
7325         }
7326
7327         PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t>& str)
7328         {
7329                 return impl::as_utf8_impl(str.c_str(), str.size());
7330         }
7331
7332         PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const char* str)
7333         {
7334                 assert(str);
7335
7336                 return impl::as_wide_impl(str, strlen(str));
7337         }
7338
7339         PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const std::string& str)
7340         {
7341                 return impl::as_wide_impl(str.c_str(), str.size());
7342         }
7343 #endif
7344
7345         PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate)
7346         {
7347                 impl::xml_memory::allocate = allocate;
7348                 impl::xml_memory::deallocate = deallocate;
7349         }
7350
7351         PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function()
7352         {
7353                 return impl::xml_memory::allocate;
7354         }
7355
7356         PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function()
7357         {
7358                 return impl::xml_memory::deallocate;
7359         }
7360 }
7361
7362 #if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC))
7363 namespace std
7364 {
7365         // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier)
7366         PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&)
7367         {
7368                 return std::bidirectional_iterator_tag();
7369         }
7370
7371         PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&)
7372         {
7373                 return std::bidirectional_iterator_tag();
7374         }
7375
7376         PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&)
7377         {
7378                 return std::bidirectional_iterator_tag();
7379         }
7380 }
7381 #endif
7382
7383 #if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC)
7384 namespace std
7385 {
7386         // Workarounds for (non-standard) iterator category detection
7387         PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&)
7388         {
7389                 return std::bidirectional_iterator_tag();
7390         }
7391
7392         PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&)
7393         {
7394                 return std::bidirectional_iterator_tag();
7395         }
7396
7397         PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&)
7398         {
7399                 return std::bidirectional_iterator_tag();
7400         }
7401 }
7402 #endif
7403
7404 #ifndef PUGIXML_NO_XPATH
7405 // STL replacements
7406 PUGI__NS_BEGIN
7407         struct equal_to
7408         {
7409                 template <typename T> bool operator()(const T& lhs, const T& rhs) const
7410                 {
7411                         return lhs == rhs;
7412                 }
7413         };
7414
7415         struct not_equal_to
7416         {
7417                 template <typename T> bool operator()(const T& lhs, const T& rhs) const
7418                 {
7419                         return lhs != rhs;
7420                 }
7421         };
7422
7423         struct less
7424         {
7425                 template <typename T> bool operator()(const T& lhs, const T& rhs) const
7426                 {
7427                         return lhs < rhs;
7428                 }
7429         };
7430
7431         struct less_equal
7432         {
7433                 template <typename T> bool operator()(const T& lhs, const T& rhs) const
7434                 {
7435                         return lhs <= rhs;
7436                 }
7437         };
7438
7439         template <typename T> inline void swap(T& lhs, T& rhs)
7440         {
7441                 T temp = lhs;
7442                 lhs = rhs;
7443                 rhs = temp;
7444         }
7445
7446         template <typename I, typename Pred> PUGI__FN I min_element(I begin, I end, const Pred& pred)
7447         {
7448                 I result = begin;
7449
7450                 for (I it = begin + 1; it != end; ++it)
7451                         if (pred(*it, *result))
7452                                 result = it;
7453
7454                 return result;
7455         }
7456
7457         template <typename I> PUGI__FN void reverse(I begin, I end)
7458         {
7459                 while (end - begin > 1)
7460                         swap(*begin++, *--end);
7461         }
7462
7463         template <typename I> PUGI__FN I unique(I begin, I end)
7464         {
7465                 // fast skip head
7466                 while (end - begin > 1 && *begin != *(begin + 1))
7467                         begin++;
7468
7469                 if (begin == end)
7470                         return begin;
7471
7472                 // last written element
7473                 I write = begin++;
7474
7475                 // merge unique elements
7476                 while (begin != end)
7477                 {
7478                         if (*begin != *write)
7479                                 *++write = *begin++;
7480                         else
7481                                 begin++;
7482                 }
7483
7484                 // past-the-end (write points to live element)
7485                 return write + 1;
7486         }
7487
7488         template <typename T, typename Pred> PUGI__FN void insertion_sort(T* begin, T* end, const Pred& pred)
7489         {
7490                 if (begin == end)
7491                         return;
7492
7493                 for (T* it = begin + 1; it != end; ++it)
7494                 {
7495                         T val = *it;
7496                         T* hole = it;
7497
7498                         // move hole backwards
7499                         while (hole > begin && pred(val, *(hole - 1)))
7500                         {
7501                                 *hole = *(hole - 1);
7502                                 hole--;
7503                         }
7504
7505                         // fill hole with element
7506                         *hole = val;
7507                 }
7508         }
7509
7510         template <typename I, typename Pred> inline I median3(I first, I middle, I last, const Pred& pred)
7511         {
7512                 if (pred(*middle, *first))
7513                         swap(middle, first);
7514                 if (pred(*last, *middle))
7515                         swap(last, middle);
7516                 if (pred(*middle, *first))
7517                         swap(middle, first);
7518
7519                 return middle;
7520         }
7521
7522         template <typename T, typename Pred> PUGI__FN void partition3(T* begin, T* end, T pivot, const Pred& pred, T** out_eqbeg, T** out_eqend)
7523         {
7524                 // invariant: array is split into 4 groups: = < ? > (each variable denotes the boundary between the groups)
7525                 T* eq = begin;
7526                 T* lt = begin;
7527                 T* gt = end;
7528
7529                 while (lt < gt)
7530                 {
7531                         if (pred(*lt, pivot))
7532                                 lt++;
7533                         else if (*lt == pivot)
7534                                 swap(*eq++, *lt++);
7535                         else
7536                                 swap(*lt, *--gt);
7537                 }
7538
7539                 // we now have just 4 groups: = < >; move equal elements to the middle
7540                 T* eqbeg = gt;
7541
7542                 for (T* it = begin; it != eq; ++it)
7543                         swap(*it, *--eqbeg);
7544
7545                 *out_eqbeg = eqbeg;
7546                 *out_eqend = gt;
7547         }
7548
7549         template <typename I, typename Pred> PUGI__FN void sort(I begin, I end, const Pred& pred)
7550         {
7551                 // sort large chunks
7552                 while (end - begin > 16)
7553                 {
7554                         // find median element
7555                         I middle = begin + (end - begin) / 2;
7556                         I median = median3(begin, middle, end - 1, pred);
7557
7558                         // partition in three chunks (< = >)
7559                         I eqbeg, eqend;
7560                         partition3(begin, end, *median, pred, &eqbeg, &eqend);
7561
7562                         // loop on larger half
7563                         if (eqbeg - begin > end - eqend)
7564                         {
7565                                 sort(eqend, end, pred);
7566                                 end = eqbeg;
7567                         }
7568                         else
7569                         {
7570                                 sort(begin, eqbeg, pred);
7571                                 begin = eqend;
7572                         }
7573                 }
7574
7575                 // insertion sort small chunk
7576                 insertion_sort(begin, end, pred);
7577         }
7578
7579         PUGI__FN bool hash_insert(const void** table, size_t size, const void* key)
7580         {
7581                 assert(key);
7582
7583                 unsigned int h = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key));
7584
7585                 // MurmurHash3 32-bit finalizer
7586                 h ^= h >> 16;
7587                 h *= 0x85ebca6bu;
7588                 h ^= h >> 13;
7589                 h *= 0xc2b2ae35u;
7590                 h ^= h >> 16;
7591
7592                 size_t hashmod = size - 1;
7593                 size_t bucket = h & hashmod;
7594
7595                 for (size_t probe = 0; probe <= hashmod; ++probe)
7596                 {
7597                         if (table[bucket] == 0)
7598                         {
7599                                 table[bucket] = key;
7600                                 return true;
7601                         }
7602
7603                         if (table[bucket] == key)
7604                                 return false;
7605
7606                         // hash collision, quadratic probing
7607                         bucket = (bucket + probe + 1) & hashmod;
7608                 }
7609
7610                 assert(false && "Hash table is full"); // unreachable
7611                 return false;
7612         }
7613 PUGI__NS_END
7614
7615 // Allocator used for AST and evaluation stacks
7616 PUGI__NS_BEGIN
7617         static const size_t xpath_memory_page_size =
7618         #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE
7619                 PUGIXML_MEMORY_XPATH_PAGE_SIZE
7620         #else
7621                 4096
7622         #endif
7623                 ;
7624
7625         static const uintptr_t xpath_memory_block_alignment = sizeof(double) > sizeof(void*) ? sizeof(double) : sizeof(void*);
7626
7627         struct xpath_memory_block
7628         {
7629                 xpath_memory_block* next;
7630                 size_t capacity;
7631
7632                 union
7633                 {
7634                         char data[xpath_memory_page_size];
7635                         double alignment;
7636                 };
7637         };
7638
7639         struct xpath_allocator
7640         {
7641                 xpath_memory_block* _root;
7642                 size_t _root_size;
7643                 bool* _error;
7644
7645                 xpath_allocator(xpath_memory_block* root, bool* error = 0): _root(root), _root_size(0), _error(error)
7646                 {
7647                 }
7648
7649                 void* allocate(size_t size)
7650                 {
7651                         // round size up to block alignment boundary
7652                         size = (size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1);
7653
7654                         if (_root_size + size <= _root->capacity)
7655                         {
7656                                 void* buf = &_root->data[0] + _root_size;
7657                                 _root_size += size;
7658                                 return buf;
7659                         }
7660                         else
7661                         {
7662                                 // make sure we have at least 1/4th of the page free after allocation to satisfy subsequent allocation requests
7663                                 size_t block_capacity_base = sizeof(_root->data);
7664                                 size_t block_capacity_req = size + block_capacity_base / 4;
7665                                 size_t block_capacity = (block_capacity_base > block_capacity_req) ? block_capacity_base : block_capacity_req;
7666
7667                                 size_t block_size = block_capacity + offsetof(xpath_memory_block, data);
7668
7669                                 xpath_memory_block* block = static_cast<xpath_memory_block*>(xml_memory::allocate(block_size));
7670                                 if (!block)
7671                                 {
7672                                         if (_error) *_error = true;
7673                                         return 0;
7674                                 }
7675
7676                                 block->next = _root;
7677                                 block->capacity = block_capacity;
7678
7679                                 _root = block;
7680                                 _root_size = size;
7681
7682                                 return block->data;
7683                         }
7684                 }
7685
7686                 void* reallocate(void* ptr, size_t old_size, size_t new_size)
7687                 {
7688                         // round size up to block alignment boundary
7689                         old_size = (old_size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1);
7690                         new_size = (new_size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1);
7691
7692                         // we can only reallocate the last object
7693                         assert(ptr == 0 || static_cast<char*>(ptr) + old_size == &_root->data[0] + _root_size);
7694
7695                         // try to reallocate the object inplace
7696                         if (ptr && _root_size - old_size + new_size <= _root->capacity)
7697                         {
7698                                 _root_size = _root_size - old_size + new_size;
7699                                 return ptr;
7700                         }
7701
7702                         // allocate a new block
7703                         void* result = allocate(new_size);
7704                         if (!result) return 0;
7705
7706                         // we have a new block
7707                         if (ptr)
7708                         {
7709                                 // copy old data (we only support growing)
7710                                 assert(new_size >= old_size);
7711                                 memcpy(result, ptr, old_size);
7712
7713                                 // free the previous page if it had no other objects
7714                                 assert(_root->data == result);
7715                                 assert(_root->next);
7716
7717                                 if (_root->next->data == ptr)
7718                                 {
7719                                         // deallocate the whole page, unless it was the first one
7720                                         xpath_memory_block* next = _root->next->next;
7721
7722                                         if (next)
7723                                         {
7724                                                 xml_memory::deallocate(_root->next);
7725                                                 _root->next = next;
7726                                         }
7727                                 }
7728                         }
7729
7730                         return result;
7731                 }
7732
7733                 void revert(const xpath_allocator& state)
7734                 {
7735                         // free all new pages
7736                         xpath_memory_block* cur = _root;
7737
7738                         while (cur != state._root)
7739                         {
7740                                 xpath_memory_block* next = cur->next;
7741
7742                                 xml_memory::deallocate(cur);
7743
7744                                 cur = next;
7745                         }
7746
7747                         // restore state
7748                         _root = state._root;
7749                         _root_size = state._root_size;
7750                 }
7751
7752                 void release()
7753                 {
7754                         xpath_memory_block* cur = _root;
7755                         assert(cur);
7756
7757                         while (cur->next)
7758                         {
7759                                 xpath_memory_block* next = cur->next;
7760
7761                                 xml_memory::deallocate(cur);
7762
7763                                 cur = next;
7764                         }
7765                 }
7766         };
7767
7768         struct xpath_allocator_capture
7769         {
7770                 xpath_allocator_capture(xpath_allocator* alloc): _target(alloc), _state(*alloc)
7771                 {
7772                 }
7773
7774                 ~xpath_allocator_capture()
7775                 {
7776                         _target->revert(_state);
7777                 }
7778
7779                 xpath_allocator* _target;
7780                 xpath_allocator _state;
7781         };
7782
7783         struct xpath_stack
7784         {
7785                 xpath_allocator* result;
7786                 xpath_allocator* temp;
7787         };
7788
7789         struct xpath_stack_data
7790         {
7791                 xpath_memory_block blocks[2];
7792                 xpath_allocator result;
7793                 xpath_allocator temp;
7794                 xpath_stack stack;
7795                 bool oom;
7796
7797                 xpath_stack_data(): result(blocks + 0, &oom), temp(blocks + 1, &oom), oom(false)
7798                 {
7799                         blocks[0].next = blocks[1].next = 0;
7800                         blocks[0].capacity = blocks[1].capacity = sizeof(blocks[0].data);
7801
7802                         stack.result = &result;
7803                         stack.temp = &temp;
7804                 }
7805
7806                 ~xpath_stack_data()
7807                 {
7808                         result.release();
7809                         temp.release();
7810                 }
7811         };
7812 PUGI__NS_END
7813
7814 // String class
7815 PUGI__NS_BEGIN
7816         class xpath_string
7817         {
7818                 const char_t* _buffer;
7819                 bool _uses_heap;
7820                 size_t _length_heap;
7821
7822                 static char_t* duplicate_string(const char_t* string, size_t length, xpath_allocator* alloc)
7823                 {
7824                         char_t* result = static_cast<char_t*>(alloc->allocate((length + 1) * sizeof(char_t)));
7825                         if (!result) return 0;
7826
7827                         memcpy(result, string, length * sizeof(char_t));
7828                         result[length] = 0;
7829
7830                         return result;
7831                 }
7832
7833                 xpath_string(const char_t* buffer, bool uses_heap_, size_t length_heap): _buffer(buffer), _uses_heap(uses_heap_), _length_heap(length_heap)
7834                 {
7835                 }
7836
7837         public:
7838                 static xpath_string from_const(const char_t* str)
7839                 {
7840                         return xpath_string(str, false, 0);
7841                 }
7842
7843                 static xpath_string from_heap_preallocated(const char_t* begin, const char_t* end)
7844                 {
7845                         assert(begin <= end && *end == 0);
7846
7847                         return xpath_string(begin, true, static_cast<size_t>(end - begin));
7848                 }
7849
7850                 static xpath_string from_heap(const char_t* begin, const char_t* end, xpath_allocator* alloc)
7851                 {
7852                         assert(begin <= end);
7853
7854                         if (begin == end)
7855                                 return xpath_string();
7856
7857                         size_t length = static_cast<size_t>(end - begin);
7858                         const char_t* data = duplicate_string(begin, length, alloc);
7859
7860                         return data ? xpath_string(data, true, length) : xpath_string();
7861                 }
7862
7863                 xpath_string(): _buffer(PUGIXML_TEXT("")), _uses_heap(false), _length_heap(0)
7864                 {
7865                 }
7866
7867                 void append(const xpath_string& o, xpath_allocator* alloc)
7868                 {
7869                         // skip empty sources
7870                         if (!*o._buffer) return;
7871
7872                         // fast append for constant empty target and constant source
7873                         if (!*_buffer && !_uses_heap && !o._uses_heap)
7874                         {
7875                                 _buffer = o._buffer;
7876                         }
7877                         else
7878                         {
7879                                 // need to make heap copy
7880                                 size_t target_length = length();
7881                                 size_t source_length = o.length();
7882                                 size_t result_length = target_length + source_length;
7883
7884                                 // allocate new buffer
7885                                 char_t* result = static_cast<char_t*>(alloc->reallocate(_uses_heap ? const_cast<char_t*>(_buffer) : 0, (target_length + 1) * sizeof(char_t), (result_length + 1) * sizeof(char_t)));
7886                                 if (!result) return;
7887
7888                                 // append first string to the new buffer in case there was no reallocation
7889                                 if (!_uses_heap) memcpy(result, _buffer, target_length * sizeof(char_t));
7890
7891                                 // append second string to the new buffer
7892                                 memcpy(result + target_length, o._buffer, source_length * sizeof(char_t));
7893                                 result[result_length] = 0;
7894
7895                                 // finalize
7896                                 _buffer = result;
7897                                 _uses_heap = true;
7898                                 _length_heap = result_length;
7899                         }
7900                 }
7901
7902                 const char_t* c_str() const
7903                 {
7904                         return _buffer;
7905                 }
7906
7907                 size_t length() const
7908                 {
7909                         return _uses_heap ? _length_heap : strlength(_buffer);
7910                 }
7911
7912                 char_t* data(xpath_allocator* alloc)
7913                 {
7914                         // make private heap copy
7915                         if (!_uses_heap)
7916                         {
7917                                 size_t length_ = strlength(_buffer);
7918                                 const char_t* data_ = duplicate_string(_buffer, length_, alloc);
7919
7920                                 if (!data_) return 0;
7921
7922                                 _buffer = data_;
7923                                 _uses_heap = true;
7924                                 _length_heap = length_;
7925                         }
7926
7927                         return const_cast<char_t*>(_buffer);
7928                 }
7929
7930                 bool empty() const
7931                 {
7932                         return *_buffer == 0;
7933                 }
7934
7935                 bool operator==(const xpath_string& o) const
7936                 {
7937                         return strequal(_buffer, o._buffer);
7938                 }
7939
7940                 bool operator!=(const xpath_string& o) const
7941                 {
7942                         return !strequal(_buffer, o._buffer);
7943                 }
7944
7945                 bool uses_heap() const
7946                 {
7947                         return _uses_heap;
7948                 }
7949         };
7950 PUGI__NS_END
7951
7952 PUGI__NS_BEGIN
7953         PUGI__FN bool starts_with(const char_t* string, const char_t* pattern)
7954         {
7955                 while (*pattern && *string == *pattern)
7956                 {
7957                         string++;
7958                         pattern++;
7959                 }
7960
7961                 return *pattern == 0;
7962         }
7963
7964         PUGI__FN const char_t* find_char(const char_t* s, char_t c)
7965         {
7966         #ifdef PUGIXML_WCHAR_MODE
7967                 return wcschr(s, c);
7968         #else
7969                 return strchr(s, c);
7970         #endif
7971         }
7972
7973         PUGI__FN const char_t* find_substring(const char_t* s, const char_t* p)
7974         {
7975         #ifdef PUGIXML_WCHAR_MODE
7976                 // MSVC6 wcsstr bug workaround (if s is empty it always returns 0)
7977                 return (*p == 0) ? s : wcsstr(s, p);
7978         #else
7979                 return strstr(s, p);
7980         #endif
7981         }
7982
7983         // Converts symbol to lower case, if it is an ASCII one
7984         PUGI__FN char_t tolower_ascii(char_t ch)
7985         {
7986                 return static_cast<unsigned int>(ch - 'A') < 26 ? static_cast<char_t>(ch | ' ') : ch;
7987         }
7988
7989         PUGI__FN xpath_string string_value(const xpath_node& na, xpath_allocator* alloc)
7990         {
7991                 if (na.attribute())
7992                         return xpath_string::from_const(na.attribute().value());
7993                 else
7994                 {
7995                         xml_node n = na.node();
7996
7997                         switch (n.type())
7998                         {
7999                         case node_pcdata:
8000                         case node_cdata:
8001                         case node_comment:
8002                         case node_pi:
8003                                 return xpath_string::from_const(n.value());
8004
8005                         case node_document:
8006                         case node_element:
8007                         {
8008                                 xpath_string result;
8009
8010                                 // element nodes can have value if parse_embed_pcdata was used
8011                                 if (n.value()[0])
8012                                         result.append(xpath_string::from_const(n.value()), alloc);
8013
8014                                 xml_node cur = n.first_child();
8015
8016                                 while (cur && cur != n)
8017                                 {
8018                                         if (cur.type() == node_pcdata || cur.type() == node_cdata)
8019                                                 result.append(xpath_string::from_const(cur.value()), alloc);
8020
8021                                         if (cur.first_child())
8022                                                 cur = cur.first_child();
8023                                         else if (cur.next_sibling())
8024                                                 cur = cur.next_sibling();
8025                                         else
8026                                         {
8027                                                 while (!cur.next_sibling() && cur != n)
8028                                                         cur = cur.parent();
8029
8030                                                 if (cur != n) cur = cur.next_sibling();
8031                                         }
8032                                 }
8033
8034                                 return result;
8035                         }
8036
8037                         default:
8038                                 return xpath_string();
8039                         }
8040                 }
8041         }
8042
8043         PUGI__FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn)
8044         {
8045                 assert(ln->parent == rn->parent);
8046
8047                 // there is no common ancestor (the shared parent is null), nodes are from different documents
8048                 if (!ln->parent) return ln < rn;
8049
8050                 // determine sibling order
8051                 xml_node_struct* ls = ln;
8052                 xml_node_struct* rs = rn;
8053
8054                 while (ls && rs)
8055                 {
8056                         if (ls == rn) return true;
8057                         if (rs == ln) return false;
8058
8059                         ls = ls->next_sibling;
8060                         rs = rs->next_sibling;
8061                 }
8062
8063                 // if rn sibling chain ended ln must be before rn
8064                 return !rs;
8065         }
8066
8067         PUGI__FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn)
8068         {
8069                 // find common ancestor at the same depth, if any
8070                 xml_node_struct* lp = ln;
8071                 xml_node_struct* rp = rn;
8072
8073                 while (lp && rp && lp->parent != rp->parent)
8074                 {
8075                         lp = lp->parent;
8076                         rp = rp->parent;
8077                 }
8078
8079                 // parents are the same!
8080                 if (lp && rp) return node_is_before_sibling(lp, rp);
8081
8082                 // nodes are at different depths, need to normalize heights
8083                 bool left_higher = !lp;
8084
8085                 while (lp)
8086                 {
8087                         lp = lp->parent;
8088                         ln = ln->parent;
8089                 }
8090
8091                 while (rp)
8092                 {
8093                         rp = rp->parent;
8094                         rn = rn->parent;
8095                 }
8096
8097                 // one node is the ancestor of the other
8098                 if (ln == rn) return left_higher;
8099
8100                 // find common ancestor... again
8101                 while (ln->parent != rn->parent)
8102                 {
8103                         ln = ln->parent;
8104                         rn = rn->parent;
8105                 }
8106
8107                 return node_is_before_sibling(ln, rn);
8108         }
8109
8110         PUGI__FN bool node_is_ancestor(xml_node_struct* parent, xml_node_struct* node)
8111         {
8112                 while (node && node != parent) node = node->parent;
8113
8114                 return parent && node == parent;
8115         }
8116
8117         PUGI__FN const void* document_buffer_order(const xpath_node& xnode)
8118         {
8119                 xml_node_struct* node = xnode.node().internal_object();
8120
8121                 if (node)
8122                 {
8123                         if ((get_document(node).header & xml_memory_page_contents_shared_mask) == 0)
8124                         {
8125                                 if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return node->name;
8126                                 if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value;
8127                         }
8128
8129                         return 0;
8130                 }
8131
8132                 xml_attribute_struct* attr = xnode.attribute().internal_object();
8133
8134                 if (attr)
8135                 {
8136                         if ((get_document(attr).header & xml_memory_page_contents_shared_mask) == 0)
8137                         {
8138                                 if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return attr->name;
8139                                 if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return attr->value;
8140                         }
8141
8142                         return 0;
8143                 }
8144
8145                 return 0;
8146         }
8147
8148         struct document_order_comparator
8149         {
8150                 bool operator()(const xpath_node& lhs, const xpath_node& rhs) const
8151                 {
8152                         // optimized document order based check
8153                         const void* lo = document_buffer_order(lhs);
8154                         const void* ro = document_buffer_order(rhs);
8155
8156                         if (lo && ro) return lo < ro;
8157
8158                         // slow comparison
8159                         xml_node ln = lhs.node(), rn = rhs.node();
8160
8161                         // compare attributes
8162                         if (lhs.attribute() && rhs.attribute())
8163                         {
8164                                 // shared parent
8165                                 if (lhs.parent() == rhs.parent())
8166                                 {
8167                                         // determine sibling order
8168                                         for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
8169                                                 if (a == rhs.attribute())
8170                                                         return true;
8171
8172                                         return false;
8173                                 }
8174
8175                                 // compare attribute parents
8176                                 ln = lhs.parent();
8177                                 rn = rhs.parent();
8178                         }
8179                         else if (lhs.attribute())
8180                         {
8181                                 // attributes go after the parent element
8182                                 if (lhs.parent() == rhs.node()) return false;
8183
8184                                 ln = lhs.parent();
8185                         }
8186                         else if (rhs.attribute())
8187                         {
8188                                 // attributes go after the parent element
8189                                 if (rhs.parent() == lhs.node()) return true;
8190
8191                                 rn = rhs.parent();
8192                         }
8193
8194                         if (ln == rn) return false;
8195
8196                         if (!ln || !rn) return ln < rn;
8197
8198                         return node_is_before(ln.internal_object(), rn.internal_object());
8199                 }
8200         };
8201
8202         PUGI__FN double gen_nan()
8203         {
8204         #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24))
8205                 PUGI__STATIC_ASSERT(sizeof(float) == sizeof(uint32_t));
8206                 typedef uint32_t UI; // BCC5 workaround
8207                 union { float f; UI i; } u;
8208                 u.i = 0x7fc00000;
8209                 return double(u.f);
8210         #else
8211                 // fallback
8212                 const volatile double zero = 0.0;
8213                 return zero / zero;
8214         #endif
8215         }
8216
8217         PUGI__FN bool is_nan(double value)
8218         {
8219         #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8220                 return !!_isnan(value);
8221         #elif defined(fpclassify) && defined(FP_NAN)
8222                 return fpclassify(value) == FP_NAN;
8223         #else
8224                 // fallback
8225                 const volatile double v = value;
8226                 return v != v;
8227         #endif
8228         }
8229
8230         PUGI__FN const char_t* convert_number_to_string_special(double value)
8231         {
8232         #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
8233                 if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0;
8234                 if (_isnan(value)) return PUGIXML_TEXT("NaN");
8235                 return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity");
8236         #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO)
8237                 switch (fpclassify(value))
8238                 {
8239                 case FP_NAN:
8240                         return PUGIXML_TEXT("NaN");
8241
8242                 case FP_INFINITE:
8243                         return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity");
8244
8245                 case FP_ZERO:
8246                         return PUGIXML_TEXT("0");
8247
8248                 default:
8249                         return 0;
8250                 }
8251         #else
8252                 // fallback
8253                 const volatile double v = value;
8254
8255                 if (v == 0) return PUGIXML_TEXT("0");
8256                 if (v != v) return PUGIXML_TEXT("NaN");
8257                 if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity");
8258                 return 0;
8259         #endif
8260         }
8261
8262         PUGI__FN bool convert_number_to_boolean(double value)
8263         {
8264                 return (value != 0 && !is_nan(value));
8265         }
8266
8267         PUGI__FN void truncate_zeros(char* begin, char* end)
8268         {
8269                 while (begin != end && end[-1] == '0') end--;
8270
8271                 *end = 0;
8272         }
8273
8274         // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent
8275 #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400
8276         PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent)
8277         {
8278                 // get base values
8279                 int sign, exponent;
8280                 _ecvt_s(buffer, sizeof(buffer), value, DBL_DIG + 1, &exponent, &sign);
8281
8282                 // truncate redundant zeros
8283                 truncate_zeros(buffer, buffer + strlen(buffer));
8284
8285                 // fill results
8286                 *out_mantissa = buffer;
8287                 *out_exponent = exponent;
8288         }
8289 #else
8290         PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent)
8291         {
8292                 // get a scientific notation value with IEEE DBL_DIG decimals
8293                 PUGI__SNPRINTF(buffer, "%.*e", DBL_DIG, value);
8294
8295                 // get the exponent (possibly negative)
8296                 char* exponent_string = strchr(buffer, 'e');
8297                 assert(exponent_string);
8298
8299                 int exponent = atoi(exponent_string + 1);
8300
8301                 // extract mantissa string: skip sign
8302                 char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer;
8303                 assert(mantissa[0] != '0' && mantissa[1] == '.');
8304
8305                 // divide mantissa by 10 to eliminate integer part
8306                 mantissa[1] = mantissa[0];
8307                 mantissa++;
8308                 exponent++;
8309
8310                 // remove extra mantissa digits and zero-terminate mantissa
8311                 truncate_zeros(mantissa, exponent_string);
8312
8313                 // fill results
8314                 *out_mantissa = mantissa;
8315                 *out_exponent = exponent;
8316         }
8317 #endif
8318
8319         PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator* alloc)
8320         {
8321                 // try special number conversion
8322                 const char_t* special = convert_number_to_string_special(value);
8323                 if (special) return xpath_string::from_const(special);
8324
8325                 // get mantissa + exponent form
8326                 char mantissa_buffer[32];
8327
8328                 char* mantissa;
8329                 int exponent;
8330                 convert_number_to_mantissa_exponent(value, mantissa_buffer, &mantissa, &exponent);
8331
8332                 // allocate a buffer of suitable length for the number
8333                 size_t result_size = strlen(mantissa_buffer) + (exponent > 0 ? exponent : -exponent) + 4;
8334                 char_t* result = static_cast<char_t*>(alloc->allocate(sizeof(char_t) * result_size));
8335                 if (!result) return xpath_string();
8336
8337                 // make the number!
8338                 char_t* s = result;
8339
8340                 // sign
8341                 if (value < 0) *s++ = '-';
8342
8343                 // integer part
8344                 if (exponent <= 0)
8345                 {
8346                         *s++ = '0';
8347                 }
8348                 else
8349                 {
8350                         while (exponent > 0)
8351                         {
8352                                 assert(*mantissa == 0 || static_cast<unsigned int>(*mantissa - '0') <= 9);
8353                                 *s++ = *mantissa ? *mantissa++ : '0';
8354                                 exponent--;
8355                         }
8356                 }
8357
8358                 // fractional part
8359                 if (*mantissa)
8360                 {
8361                         // decimal point
8362                         *s++ = '.';
8363
8364                         // extra zeroes from negative exponent
8365                         while (exponent < 0)
8366                         {
8367                                 *s++ = '0';
8368                                 exponent++;
8369                         }
8370
8371                         // extra mantissa digits
8372                         while (*mantissa)
8373                         {
8374                                 assert(static_cast<unsigned int>(*mantissa - '0') <= 9);
8375                                 *s++ = *mantissa++;
8376                         }
8377                 }
8378
8379                 // zero-terminate
8380                 assert(s < result + result_size);
8381                 *s = 0;
8382
8383                 return xpath_string::from_heap_preallocated(result, s);
8384         }
8385
8386         PUGI__FN bool check_string_to_number_format(const char_t* string)
8387         {
8388                 // parse leading whitespace
8389                 while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string;
8390
8391                 // parse sign
8392                 if (*string == '-') ++string;
8393
8394                 if (!*string) return false;
8395
8396                 // if there is no integer part, there should be a decimal part with at least one digit
8397                 if (!PUGI__IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !PUGI__IS_CHARTYPEX(string[1], ctx_digit))) return false;
8398
8399                 // parse integer part
8400                 while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string;
8401
8402                 // parse decimal part
8403                 if (*string == '.')
8404                 {
8405                         ++string;
8406
8407                         while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string;
8408                 }
8409
8410                 // parse trailing whitespace
8411                 while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string;
8412
8413                 return *string == 0;
8414         }
8415
8416         PUGI__FN double convert_string_to_number(const char_t* string)
8417         {
8418                 // check string format
8419                 if (!check_string_to_number_format(string)) return gen_nan();
8420
8421                 // parse string
8422         #ifdef PUGIXML_WCHAR_MODE
8423                 return wcstod(string, 0);
8424         #else
8425                 return strtod(string, 0);
8426         #endif
8427         }
8428
8429         PUGI__FN bool convert_string_to_number_scratch(char_t (&buffer)[32], const char_t* begin, const char_t* end, double* out_result)
8430         {
8431                 size_t length = static_cast<size_t>(end - begin);
8432                 char_t* scratch = buffer;
8433
8434                 if (length >= sizeof(buffer) / sizeof(buffer[0]))
8435                 {
8436                         // need to make dummy on-heap copy
8437                         scratch = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
8438                         if (!scratch) return false;
8439                 }
8440
8441                 // copy string to zero-terminated buffer and perform conversion
8442                 memcpy(scratch, begin, length * sizeof(char_t));
8443                 scratch[length] = 0;
8444
8445                 *out_result = convert_string_to_number(scratch);
8446
8447                 // free dummy buffer
8448                 if (scratch != buffer) xml_memory::deallocate(scratch);
8449
8450                 return true;
8451         }
8452
8453         PUGI__FN double round_nearest(double value)
8454         {
8455                 return floor(value + 0.5);
8456         }
8457
8458         PUGI__FN double round_nearest_nzero(double value)
8459         {
8460                 // same as round_nearest, but returns -0 for [-0.5, -0]
8461                 // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0)
8462                 return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5);
8463         }
8464
8465         PUGI__FN const char_t* qualified_name(const xpath_node& node)
8466         {
8467                 return node.attribute() ? node.attribute().name() : node.node().name();
8468         }
8469
8470         PUGI__FN const char_t* local_name(const xpath_node& node)
8471         {
8472                 const char_t* name = qualified_name(node);
8473                 const char_t* p = find_char(name, ':');
8474
8475                 return p ? p + 1 : name;
8476         }
8477
8478         struct namespace_uri_predicate
8479         {
8480                 const char_t* prefix;
8481                 size_t prefix_length;
8482
8483                 namespace_uri_predicate(const char_t* name)
8484                 {
8485                         const char_t* pos = find_char(name, ':');
8486
8487                         prefix = pos ? name : 0;
8488                         prefix_length = pos ? static_cast<size_t>(pos - name) : 0;
8489                 }
8490
8491                 bool operator()(xml_attribute a) const
8492                 {
8493                         const char_t* name = a.name();
8494
8495                         if (!starts_with(name, PUGIXML_TEXT("xmlns"))) return false;
8496
8497                         return prefix ? name[5] == ':' && strequalrange(name + 6, prefix, prefix_length) : name[5] == 0;
8498                 }
8499         };
8500
8501         PUGI__FN const char_t* namespace_uri(xml_node node)
8502         {
8503                 namespace_uri_predicate pred = node.name();
8504
8505                 xml_node p = node;
8506
8507                 while (p)
8508                 {
8509                         xml_attribute a = p.find_attribute(pred);
8510
8511                         if (a) return a.value();
8512
8513                         p = p.parent();
8514                 }
8515
8516                 return PUGIXML_TEXT("");
8517         }
8518
8519         PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent)
8520         {
8521                 namespace_uri_predicate pred = attr.name();
8522
8523                 // Default namespace does not apply to attributes
8524                 if (!pred.prefix) return PUGIXML_TEXT("");
8525
8526                 xml_node p = parent;
8527
8528                 while (p)
8529                 {
8530                         xml_attribute a = p.find_attribute(pred);
8531
8532                         if (a) return a.value();
8533
8534                         p = p.parent();
8535                 }
8536
8537                 return PUGIXML_TEXT("");
8538         }
8539
8540         PUGI__FN const char_t* namespace_uri(const xpath_node& node)
8541         {
8542                 return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node());
8543         }
8544
8545         PUGI__FN char_t* normalize_space(char_t* buffer)
8546         {
8547                 char_t* write = buffer;
8548
8549                 for (char_t* it = buffer; *it; )
8550                 {
8551                         char_t ch = *it++;
8552
8553                         if (PUGI__IS_CHARTYPE(ch, ct_space))
8554                         {
8555                                 // replace whitespace sequence with single space
8556                                 while (PUGI__IS_CHARTYPE(*it, ct_space)) it++;
8557
8558                                 // avoid leading spaces
8559                                 if (write != buffer) *write++ = ' ';
8560                         }
8561                         else *write++ = ch;
8562                 }
8563
8564                 // remove trailing space
8565                 if (write != buffer && PUGI__IS_CHARTYPE(write[-1], ct_space)) write--;
8566
8567                 // zero-terminate
8568                 *write = 0;
8569
8570                 return write;
8571         }
8572
8573         PUGI__FN char_t* translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length)
8574         {
8575                 char_t* write = buffer;
8576
8577                 while (*buffer)
8578                 {
8579                         PUGI__DMC_VOLATILE char_t ch = *buffer++;
8580
8581                         const char_t* pos = find_char(from, ch);
8582
8583                         if (!pos)
8584                                 *write++ = ch; // do not process
8585                         else if (static_cast<size_t>(pos - from) < to_length)
8586                                 *write++ = to[pos - from]; // replace
8587                 }
8588
8589                 // zero-terminate
8590                 *write = 0;
8591
8592                 return write;
8593         }
8594
8595         PUGI__FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to)
8596         {
8597                 unsigned char table[128] = {0};
8598
8599                 while (*from)
8600                 {
8601                         unsigned int fc = static_cast<unsigned int>(*from);
8602                         unsigned int tc = static_cast<unsigned int>(*to);
8603
8604                         if (fc >= 128 || tc >= 128)
8605                                 return 0;
8606
8607                         // code=128 means "skip character"
8608                         if (!table[fc])
8609                                 table[fc] = static_cast<unsigned char>(tc ? tc : 128);
8610
8611                         from++;
8612                         if (tc) to++;
8613                 }
8614
8615                 for (int i = 0; i < 128; ++i)
8616                         if (!table[i])
8617                                 table[i] = static_cast<unsigned char>(i);
8618
8619                 void* result = alloc->allocate(sizeof(table));
8620                 if (!result) return 0;
8621
8622                 memcpy(result, table, sizeof(table));
8623
8624                 return static_cast<unsigned char*>(result);
8625         }
8626
8627         PUGI__FN char_t* translate_table(char_t* buffer, const unsigned char* table)
8628         {
8629                 char_t* write = buffer;
8630
8631                 while (*buffer)
8632                 {
8633                         char_t ch = *buffer++;
8634                         unsigned int index = static_cast<unsigned int>(ch);
8635
8636                         if (index < 128)
8637                         {
8638                                 unsigned char code = table[index];
8639
8640                                 // code=128 means "skip character" (table size is 128 so 128 can be a special value)
8641                                 // this code skips these characters without extra branches
8642                                 *write = static_cast<char_t>(code);
8643                                 write += 1 - (code >> 7);
8644                         }
8645                         else
8646                         {
8647                                 *write++ = ch;
8648                         }
8649                 }
8650
8651                 // zero-terminate
8652                 *write = 0;
8653
8654                 return write;
8655         }
8656
8657         inline bool is_xpath_attribute(const char_t* name)
8658         {
8659                 return !(starts_with(name, PUGIXML_TEXT("xmlns")) && (name[5] == 0 || name[5] == ':'));
8660         }
8661
8662         struct xpath_variable_boolean: xpath_variable
8663         {
8664                 xpath_variable_boolean(): xpath_variable(xpath_type_boolean), value(false)
8665                 {
8666                 }
8667
8668                 bool value;
8669                 char_t name[1];
8670         };
8671
8672         struct xpath_variable_number: xpath_variable
8673         {
8674                 xpath_variable_number(): xpath_variable(xpath_type_number), value(0)
8675                 {
8676                 }
8677
8678                 double value;
8679                 char_t name[1];
8680         };
8681
8682         struct xpath_variable_string: xpath_variable
8683         {
8684                 xpath_variable_string(): xpath_variable(xpath_type_string), value(0)
8685                 {
8686                 }
8687
8688                 ~xpath_variable_string()
8689                 {
8690                         if (value) xml_memory::deallocate(value);
8691                 }
8692
8693                 char_t* value;
8694                 char_t name[1];
8695         };
8696
8697         struct xpath_variable_node_set: xpath_variable
8698         {
8699                 xpath_variable_node_set(): xpath_variable(xpath_type_node_set)
8700                 {
8701                 }
8702
8703                 xpath_node_set value;
8704                 char_t name[1];
8705         };
8706
8707         static const xpath_node_set dummy_node_set;
8708
8709         PUGI__FN PUGI__UNSIGNED_OVERFLOW unsigned int hash_string(const char_t* str)
8710         {
8711                 // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time)
8712                 unsigned int result = 0;
8713
8714                 while (*str)
8715                 {
8716                         result += static_cast<unsigned int>(*str++);
8717                         result += result << 10;
8718                         result ^= result >> 6;
8719                 }
8720
8721                 result += result << 3;
8722                 result ^= result >> 11;
8723                 result += result << 15;
8724
8725                 return result;
8726         }
8727
8728         template <typename T> PUGI__FN T* new_xpath_variable(const char_t* name)
8729         {
8730                 size_t length = strlength(name);
8731                 if (length == 0) return 0; // empty variable names are invalid
8732
8733                 // $$ we can't use offsetof(T, name) because T is non-POD, so we just allocate additional length characters
8734                 void* memory = xml_memory::allocate(sizeof(T) + length * sizeof(char_t));
8735                 if (!memory) return 0;
8736
8737                 T* result = new (memory) T();
8738
8739                 memcpy(result->name, name, (length + 1) * sizeof(char_t));
8740
8741                 return result;
8742         }
8743
8744         PUGI__FN xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name)
8745         {
8746                 switch (type)
8747                 {
8748                 case xpath_type_node_set:
8749                         return new_xpath_variable<xpath_variable_node_set>(name);
8750
8751                 case xpath_type_number:
8752                         return new_xpath_variable<xpath_variable_number>(name);
8753
8754                 case xpath_type_string:
8755                         return new_xpath_variable<xpath_variable_string>(name);
8756
8757                 case xpath_type_boolean:
8758                         return new_xpath_variable<xpath_variable_boolean>(name);
8759
8760                 default:
8761                         return 0;
8762                 }
8763         }
8764
8765         template <typename T> PUGI__FN void delete_xpath_variable(T* var)
8766         {
8767                 var->~T();
8768                 xml_memory::deallocate(var);
8769         }
8770
8771         PUGI__FN void delete_xpath_variable(xpath_value_type type, xpath_variable* var)
8772         {
8773                 switch (type)
8774                 {
8775                 case xpath_type_node_set:
8776                         delete_xpath_variable(static_cast<xpath_variable_node_set*>(var));
8777                         break;
8778
8779                 case xpath_type_number:
8780                         delete_xpath_variable(static_cast<xpath_variable_number*>(var));
8781                         break;
8782
8783                 case xpath_type_string:
8784                         delete_xpath_variable(static_cast<xpath_variable_string*>(var));
8785                         break;
8786
8787                 case xpath_type_boolean:
8788                         delete_xpath_variable(static_cast<xpath_variable_boolean*>(var));
8789                         break;
8790
8791                 default:
8792                         assert(false && "Invalid variable type"); // unreachable
8793                 }
8794         }
8795
8796         PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs)
8797         {
8798                 switch (rhs->type())
8799                 {
8800                 case xpath_type_node_set:
8801                         return lhs->set(static_cast<const xpath_variable_node_set*>(rhs)->value);
8802
8803                 case xpath_type_number:
8804                         return lhs->set(static_cast<const xpath_variable_number*>(rhs)->value);
8805
8806                 case xpath_type_string:
8807                         return lhs->set(static_cast<const xpath_variable_string*>(rhs)->value);
8808
8809                 case xpath_type_boolean:
8810                         return lhs->set(static_cast<const xpath_variable_boolean*>(rhs)->value);
8811
8812                 default:
8813                         assert(false && "Invalid variable type"); // unreachable
8814                         return false;
8815                 }
8816         }
8817
8818         PUGI__FN bool get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end, xpath_variable** out_result)
8819         {
8820                 size_t length = static_cast<size_t>(end - begin);
8821                 char_t* scratch = buffer;
8822
8823                 if (length >= sizeof(buffer) / sizeof(buffer[0]))
8824                 {
8825                         // need to make dummy on-heap copy
8826                         scratch = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
8827                         if (!scratch) return false;
8828                 }
8829
8830                 // copy string to zero-terminated buffer and perform lookup
8831                 memcpy(scratch, begin, length * sizeof(char_t));
8832                 scratch[length] = 0;
8833
8834                 *out_result = set->get(scratch);
8835
8836                 // free dummy buffer
8837                 if (scratch != buffer) xml_memory::deallocate(scratch);
8838
8839                 return true;
8840         }
8841 PUGI__NS_END
8842
8843 // Internal node set class
8844 PUGI__NS_BEGIN
8845         PUGI__FN xpath_node_set::type_t xpath_get_order(const xpath_node* begin, const xpath_node* end)
8846         {
8847                 if (end - begin < 2)
8848                         return xpath_node_set::type_sorted;
8849
8850                 document_order_comparator cmp;
8851
8852                 bool first = cmp(begin[0], begin[1]);
8853
8854                 for (const xpath_node* it = begin + 1; it + 1 < end; ++it)
8855                         if (cmp(it[0], it[1]) != first)
8856                                 return xpath_node_set::type_unsorted;
8857
8858                 return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse;
8859         }
8860
8861         PUGI__FN xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev)
8862         {
8863                 xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
8864
8865                 if (type == xpath_node_set::type_unsorted)
8866                 {
8867                         xpath_node_set::type_t sorted = xpath_get_order(begin, end);
8868
8869                         if (sorted == xpath_node_set::type_unsorted)
8870                         {
8871                                 sort(begin, end, document_order_comparator());
8872
8873                                 type = xpath_node_set::type_sorted;
8874                         }
8875                         else
8876                                 type = sorted;
8877                 }
8878
8879                 if (type != order) reverse(begin, end);
8880
8881                 return order;
8882         }
8883
8884         PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type)
8885         {
8886                 if (begin == end) return xpath_node();
8887
8888                 switch (type)
8889                 {
8890                 case xpath_node_set::type_sorted:
8891                         return *begin;
8892
8893                 case xpath_node_set::type_sorted_reverse:
8894                         return *(end - 1);
8895
8896                 case xpath_node_set::type_unsorted:
8897                         return *min_element(begin, end, document_order_comparator());
8898
8899                 default:
8900                         assert(false && "Invalid node set type"); // unreachable
8901                         return xpath_node();
8902                 }
8903         }
8904
8905         class xpath_node_set_raw
8906         {
8907                 xpath_node_set::type_t _type;
8908
8909                 xpath_node* _begin;
8910                 xpath_node* _end;
8911                 xpath_node* _eos;
8912
8913         public:
8914                 xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(0), _end(0), _eos(0)
8915                 {
8916                 }
8917
8918                 xpath_node* begin() const
8919                 {
8920                         return _begin;
8921                 }
8922
8923                 xpath_node* end() const
8924                 {
8925                         return _end;
8926                 }
8927
8928                 bool empty() const
8929                 {
8930                         return _begin == _end;
8931                 }
8932
8933                 size_t size() const
8934                 {
8935                         return static_cast<size_t>(_end - _begin);
8936                 }
8937
8938                 xpath_node first() const
8939                 {
8940                         return xpath_first(_begin, _end, _type);
8941                 }
8942
8943                 void push_back_grow(const xpath_node& node, xpath_allocator* alloc);
8944
8945                 void push_back(const xpath_node& node, xpath_allocator* alloc)
8946                 {
8947                         if (_end != _eos)
8948                                 *_end++ = node;
8949                         else
8950                                 push_back_grow(node, alloc);
8951                 }
8952
8953                 void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc)
8954                 {
8955                         if (begin_ == end_) return;
8956
8957                         size_t size_ = static_cast<size_t>(_end - _begin);
8958                         size_t capacity = static_cast<size_t>(_eos - _begin);
8959                         size_t count = static_cast<size_t>(end_ - begin_);
8960
8961                         if (size_ + count > capacity)
8962                         {
8963                                 // reallocate the old array or allocate a new one
8964                                 xpath_node* data = static_cast<xpath_node*>(alloc->reallocate(_begin, capacity * sizeof(xpath_node), (size_ + count) * sizeof(xpath_node)));
8965                                 if (!data) return;
8966
8967                                 // finalize
8968                                 _begin = data;
8969                                 _end = data + size_;
8970                                 _eos = data + size_ + count;
8971                         }
8972
8973                         memcpy(_end, begin_, count * sizeof(xpath_node));
8974                         _end += count;
8975                 }
8976
8977                 void sort_do()
8978                 {
8979                         _type = xpath_sort(_begin, _end, _type, false);
8980                 }
8981
8982                 void truncate(xpath_node* pos)
8983                 {
8984                         assert(_begin <= pos && pos <= _end);
8985
8986                         _end = pos;
8987                 }
8988
8989                 void remove_duplicates(xpath_allocator* alloc)
8990                 {
8991                         if (_type == xpath_node_set::type_unsorted && _end - _begin > 2)
8992                         {
8993                                 xpath_allocator_capture cr(alloc);
8994
8995                                 size_t size_ = static_cast<size_t>(_end - _begin);
8996
8997                                 size_t hash_size = 1;
8998                                 while (hash_size < size_ + size_ / 2) hash_size *= 2;
8999
9000                                 const void** hash_data = static_cast<const void**>(alloc->allocate(hash_size * sizeof(void**)));
9001                                 if (!hash_data) return;
9002
9003                                 memset(hash_data, 0, hash_size * sizeof(const void**));
9004
9005                                 xpath_node* write = _begin;
9006
9007                                 for (xpath_node* it = _begin; it != _end; ++it)
9008                                 {
9009                                         const void* attr = it->attribute().internal_object();
9010                                         const void* node = it->node().internal_object();
9011                                         const void* key = attr ? attr : node;
9012
9013                                         if (key && hash_insert(hash_data, hash_size, key))
9014                                         {
9015                                                 *write++ = *it;
9016                                         }
9017                                 }
9018
9019                                 _end = write;
9020                         }
9021                         else
9022                         {
9023                                 _end = unique(_begin, _end);
9024                         }
9025                 }
9026
9027                 xpath_node_set::type_t type() const
9028                 {
9029                         return _type;
9030                 }
9031
9032                 void set_type(xpath_node_set::type_t value)
9033                 {
9034                         _type = value;
9035                 }
9036         };
9037
9038         PUGI__FN_NO_INLINE void xpath_node_set_raw::push_back_grow(const xpath_node& node, xpath_allocator* alloc)
9039         {
9040                 size_t capacity = static_cast<size_t>(_eos - _begin);
9041
9042                 // get new capacity (1.5x rule)
9043                 size_t new_capacity = capacity + capacity / 2 + 1;
9044
9045                 // reallocate the old array or allocate a new one
9046                 xpath_node* data = static_cast<xpath_node*>(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node)));
9047                 if (!data) return;
9048
9049                 // finalize
9050                 _begin = data;
9051                 _end = data + capacity;
9052                 _eos = data + new_capacity;
9053
9054                 // push
9055                 *_end++ = node;
9056         }
9057 PUGI__NS_END
9058
9059 PUGI__NS_BEGIN
9060         struct xpath_context
9061         {
9062                 xpath_node n;
9063                 size_t position, size;
9064
9065                 xpath_context(const xpath_node& n_, size_t position_, size_t size_): n(n_), position(position_), size(size_)
9066                 {
9067                 }
9068         };
9069
9070         enum lexeme_t
9071         {
9072                 lex_none = 0,
9073                 lex_equal,
9074                 lex_not_equal,
9075                 lex_less,
9076                 lex_greater,
9077                 lex_less_or_equal,
9078                 lex_greater_or_equal,
9079                 lex_plus,
9080                 lex_minus,
9081                 lex_multiply,
9082                 lex_union,
9083                 lex_var_ref,
9084                 lex_open_brace,
9085                 lex_close_brace,
9086                 lex_quoted_string,
9087                 lex_number,
9088                 lex_slash,
9089                 lex_double_slash,
9090                 lex_open_square_brace,
9091                 lex_close_square_brace,
9092                 lex_string,
9093                 lex_comma,
9094                 lex_axis_attribute,
9095                 lex_dot,
9096                 lex_double_dot,
9097                 lex_double_colon,
9098                 lex_eof
9099         };
9100
9101         struct xpath_lexer_string
9102         {
9103                 const char_t* begin;
9104                 const char_t* end;
9105
9106                 xpath_lexer_string(): begin(0), end(0)
9107                 {
9108                 }
9109
9110                 bool operator==(const char_t* other) const
9111                 {
9112                         size_t length = static_cast<size_t>(end - begin);
9113
9114                         return strequalrange(other, begin, length);
9115                 }
9116         };
9117
9118         class xpath_lexer
9119         {
9120                 const char_t* _cur;
9121                 const char_t* _cur_lexeme_pos;
9122                 xpath_lexer_string _cur_lexeme_contents;
9123
9124                 lexeme_t _cur_lexeme;
9125
9126         public:
9127                 explicit xpath_lexer(const char_t* query): _cur(query)
9128                 {
9129                         next();
9130                 }
9131
9132                 const char_t* state() const
9133                 {
9134                         return _cur;
9135                 }
9136
9137                 void next()
9138                 {
9139                         const char_t* cur = _cur;
9140
9141                         while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur;
9142
9143                         // save lexeme position for error reporting
9144                         _cur_lexeme_pos = cur;
9145
9146                         switch (*cur)
9147                         {
9148                         case 0:
9149                                 _cur_lexeme = lex_eof;
9150                                 break;
9151
9152                         case '>':
9153                                 if (*(cur+1) == '=')
9154                                 {
9155                                         cur += 2;
9156                                         _cur_lexeme = lex_greater_or_equal;
9157                                 }
9158                                 else
9159                                 {
9160                                         cur += 1;
9161                                         _cur_lexeme = lex_greater;
9162                                 }
9163                                 break;
9164
9165                         case '<':
9166                                 if (*(cur+1) == '=')
9167                                 {
9168                                         cur += 2;
9169                                         _cur_lexeme = lex_less_or_equal;
9170                                 }
9171                                 else
9172                                 {
9173                                         cur += 1;
9174                                         _cur_lexeme = lex_less;
9175                                 }
9176                                 break;
9177
9178                         case '!':
9179                                 if (*(cur+1) == '=')
9180                                 {
9181                                         cur += 2;
9182                                         _cur_lexeme = lex_not_equal;
9183                                 }
9184                                 else
9185                                 {
9186                                         _cur_lexeme = lex_none;
9187                                 }
9188                                 break;
9189
9190                         case '=':
9191                                 cur += 1;
9192                                 _cur_lexeme = lex_equal;
9193
9194                                 break;
9195
9196                         case '+':
9197                                 cur += 1;
9198                                 _cur_lexeme = lex_plus;
9199
9200                                 break;
9201
9202                         case '-':
9203                                 cur += 1;
9204                                 _cur_lexeme = lex_minus;
9205
9206                                 break;
9207
9208                         case '*':
9209                                 cur += 1;
9210                                 _cur_lexeme = lex_multiply;
9211
9212                                 break;
9213
9214                         case '|':
9215                                 cur += 1;
9216                                 _cur_lexeme = lex_union;
9217
9218                                 break;
9219
9220                         case '$':
9221                                 cur += 1;
9222
9223                                 if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol))
9224                                 {
9225                                         _cur_lexeme_contents.begin = cur;
9226
9227                                         while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++;
9228
9229                                         if (cur[0] == ':' && PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // qname
9230                                         {
9231                                                 cur++; // :
9232
9233                                                 while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++;
9234                                         }
9235
9236                                         _cur_lexeme_contents.end = cur;
9237
9238                                         _cur_lexeme = lex_var_ref;
9239                                 }
9240                                 else
9241                                 {
9242                                         _cur_lexeme = lex_none;
9243                                 }
9244
9245                                 break;
9246
9247                         case '(':
9248                                 cur += 1;
9249                                 _cur_lexeme = lex_open_brace;
9250
9251                                 break;
9252
9253                         case ')':
9254                                 cur += 1;
9255                                 _cur_lexeme = lex_close_brace;
9256
9257                                 break;
9258
9259                         case '[':
9260                                 cur += 1;
9261                                 _cur_lexeme = lex_open_square_brace;
9262
9263                                 break;
9264
9265                         case ']':
9266                                 cur += 1;
9267                                 _cur_lexeme = lex_close_square_brace;
9268
9269                                 break;
9270
9271                         case ',':
9272                                 cur += 1;
9273                                 _cur_lexeme = lex_comma;
9274
9275                                 break;
9276
9277                         case '/':
9278                                 if (*(cur+1) == '/')
9279                                 {
9280                                         cur += 2;
9281                                         _cur_lexeme = lex_double_slash;
9282                                 }
9283                                 else
9284                                 {
9285                                         cur += 1;
9286                                         _cur_lexeme = lex_slash;
9287                                 }
9288                                 break;
9289
9290                         case '.':
9291                                 if (*(cur+1) == '.')
9292                                 {
9293                                         cur += 2;
9294                                         _cur_lexeme = lex_double_dot;
9295                                 }
9296                                 else if (PUGI__IS_CHARTYPEX(*(cur+1), ctx_digit))
9297                                 {
9298                                         _cur_lexeme_contents.begin = cur; // .
9299
9300                                         ++cur;
9301
9302                                         while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++;
9303
9304                                         _cur_lexeme_contents.end = cur;
9305
9306                                         _cur_lexeme = lex_number;
9307                                 }
9308                                 else
9309                                 {
9310                                         cur += 1;
9311                                         _cur_lexeme = lex_dot;
9312                                 }
9313                                 break;
9314
9315                         case '@':
9316                                 cur += 1;
9317                                 _cur_lexeme = lex_axis_attribute;
9318
9319                                 break;
9320
9321                         case '"':
9322                         case '\'':
9323                         {
9324                                 char_t terminator = *cur;
9325
9326                                 ++cur;
9327
9328                                 _cur_lexeme_contents.begin = cur;
9329                                 while (*cur && *cur != terminator) cur++;
9330                                 _cur_lexeme_contents.end = cur;
9331
9332                                 if (!*cur)
9333                                         _cur_lexeme = lex_none;
9334                                 else
9335                                 {
9336                                         cur += 1;
9337                                         _cur_lexeme = lex_quoted_string;
9338                                 }
9339
9340                                 break;
9341                         }
9342
9343                         case ':':
9344                                 if (*(cur+1) == ':')
9345                                 {
9346                                         cur += 2;
9347                                         _cur_lexeme = lex_double_colon;
9348                                 }
9349                                 else
9350                                 {
9351                                         _cur_lexeme = lex_none;
9352                                 }
9353                                 break;
9354
9355                         default:
9356                                 if (PUGI__IS_CHARTYPEX(*cur, ctx_digit))
9357                                 {
9358                                         _cur_lexeme_contents.begin = cur;
9359
9360                                         while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++;
9361
9362                                         if (*cur == '.')
9363                                         {
9364                                                 cur++;
9365
9366                                                 while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++;
9367                                         }
9368
9369                                         _cur_lexeme_contents.end = cur;
9370
9371                                         _cur_lexeme = lex_number;
9372                                 }
9373                                 else if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol))
9374                                 {
9375                                         _cur_lexeme_contents.begin = cur;
9376
9377                                         while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++;
9378
9379                                         if (cur[0] == ':')
9380                                         {
9381                                                 if (cur[1] == '*') // namespace test ncname:*
9382                                                 {
9383                                                         cur += 2; // :*
9384                                                 }
9385                                                 else if (PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname
9386                                                 {
9387                                                         cur++; // :
9388
9389                                                         while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++;
9390                                                 }
9391                                         }
9392
9393                                         _cur_lexeme_contents.end = cur;
9394
9395                                         _cur_lexeme = lex_string;
9396                                 }
9397                                 else
9398                                 {
9399                                         _cur_lexeme = lex_none;
9400                                 }
9401                         }
9402
9403                         _cur = cur;
9404                 }
9405
9406                 lexeme_t current() const
9407                 {
9408                         return _cur_lexeme;
9409                 }
9410
9411                 const char_t* current_pos() const
9412                 {
9413                         return _cur_lexeme_pos;
9414                 }
9415
9416                 const xpath_lexer_string& contents() const
9417                 {
9418                         assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_string || _cur_lexeme == lex_quoted_string);
9419
9420                         return _cur_lexeme_contents;
9421                 }
9422         };
9423
9424         enum ast_type_t
9425         {
9426                 ast_unknown,
9427                 ast_op_or,                                              // left or right
9428                 ast_op_and,                                             // left and right
9429                 ast_op_equal,                                   // left = right
9430                 ast_op_not_equal,                               // left != right
9431                 ast_op_less,                                    // left < right
9432                 ast_op_greater,                                 // left > right
9433                 ast_op_less_or_equal,                   // left <= right
9434                 ast_op_greater_or_equal,                // left >= right
9435                 ast_op_add,                                             // left + right
9436                 ast_op_subtract,                                // left - right
9437                 ast_op_multiply,                                // left * right
9438                 ast_op_divide,                                  // left / right
9439                 ast_op_mod,                                             // left % right
9440                 ast_op_negate,                                  // left - right
9441                 ast_op_union,                                   // left | right
9442                 ast_predicate,                                  // apply predicate to set; next points to next predicate
9443                 ast_filter,                                             // select * from left where right
9444                 ast_string_constant,                    // string constant
9445                 ast_number_constant,                    // number constant
9446                 ast_variable,                                   // variable
9447                 ast_func_last,                                  // last()
9448                 ast_func_position,                              // position()
9449                 ast_func_count,                                 // count(left)
9450                 ast_func_id,                                    // id(left)
9451                 ast_func_local_name_0,                  // local-name()
9452                 ast_func_local_name_1,                  // local-name(left)
9453                 ast_func_namespace_uri_0,               // namespace-uri()
9454                 ast_func_namespace_uri_1,               // namespace-uri(left)
9455                 ast_func_name_0,                                // name()
9456                 ast_func_name_1,                                // name(left)
9457                 ast_func_string_0,                              // string()
9458                 ast_func_string_1,                              // string(left)
9459                 ast_func_concat,                                // concat(left, right, siblings)
9460                 ast_func_starts_with,                   // starts_with(left, right)
9461                 ast_func_contains,                              // contains(left, right)
9462                 ast_func_substring_before,              // substring-before(left, right)
9463                 ast_func_substring_after,               // substring-after(left, right)
9464                 ast_func_substring_2,                   // substring(left, right)
9465                 ast_func_substring_3,                   // substring(left, right, third)
9466                 ast_func_string_length_0,               // string-length()
9467                 ast_func_string_length_1,               // string-length(left)
9468                 ast_func_normalize_space_0,             // normalize-space()
9469                 ast_func_normalize_space_1,             // normalize-space(left)
9470                 ast_func_translate,                             // translate(left, right, third)
9471                 ast_func_boolean,                               // boolean(left)
9472                 ast_func_not,                                   // not(left)
9473                 ast_func_true,                                  // true()
9474                 ast_func_false,                                 // false()
9475                 ast_func_lang,                                  // lang(left)
9476                 ast_func_number_0,                              // number()
9477                 ast_func_number_1,                              // number(left)
9478                 ast_func_sum,                                   // sum(left)
9479                 ast_func_floor,                                 // floor(left)
9480                 ast_func_ceiling,                               // ceiling(left)
9481                 ast_func_round,                                 // round(left)
9482                 ast_step,                                               // process set left with step
9483                 ast_step_root,                                  // select root node
9484
9485                 ast_opt_translate_table,                // translate(left, right, third) where right/third are constants
9486                 ast_opt_compare_attribute               // @name = 'string'
9487         };
9488
9489         enum axis_t
9490         {
9491                 axis_ancestor,
9492                 axis_ancestor_or_self,
9493                 axis_attribute,
9494                 axis_child,
9495                 axis_descendant,
9496                 axis_descendant_or_self,
9497                 axis_following,
9498                 axis_following_sibling,
9499                 axis_namespace,
9500                 axis_parent,
9501                 axis_preceding,
9502                 axis_preceding_sibling,
9503                 axis_self
9504         };
9505
9506         enum nodetest_t
9507         {
9508                 nodetest_none,
9509                 nodetest_name,
9510                 nodetest_type_node,
9511                 nodetest_type_comment,
9512                 nodetest_type_pi,
9513                 nodetest_type_text,
9514                 nodetest_pi,
9515                 nodetest_all,
9516                 nodetest_all_in_namespace
9517         };
9518
9519         enum predicate_t
9520         {
9521                 predicate_default,
9522                 predicate_posinv,
9523                 predicate_constant,
9524                 predicate_constant_one
9525         };
9526
9527         enum nodeset_eval_t
9528         {
9529                 nodeset_eval_all,
9530                 nodeset_eval_any,
9531                 nodeset_eval_first
9532         };
9533
9534         template <axis_t N> struct axis_to_type
9535         {
9536                 static const axis_t axis;
9537         };
9538
9539         template <axis_t N> const axis_t axis_to_type<N>::axis = N;
9540
9541         class xpath_ast_node
9542         {
9543         private:
9544                 // node type
9545                 char _type;
9546                 char _rettype;
9547
9548                 // for ast_step
9549                 char _axis;
9550
9551                 // for ast_step/ast_predicate/ast_filter
9552                 char _test;
9553
9554                 // tree node structure
9555                 xpath_ast_node* _left;
9556                 xpath_ast_node* _right;
9557                 xpath_ast_node* _next;
9558
9559                 union
9560                 {
9561                         // value for ast_string_constant
9562                         const char_t* string;
9563                         // value for ast_number_constant
9564                         double number;
9565                         // variable for ast_variable
9566                         xpath_variable* variable;
9567                         // node test for ast_step (node name/namespace/node type/pi target)
9568                         const char_t* nodetest;
9569                         // table for ast_opt_translate_table
9570                         const unsigned char* table;
9571                 } _data;
9572
9573                 xpath_ast_node(const xpath_ast_node&);
9574                 xpath_ast_node& operator=(const xpath_ast_node&);
9575
9576                 template <class Comp> static bool compare_eq(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp)
9577                 {
9578                         xpath_value_type lt = lhs->rettype(), rt = rhs->rettype();
9579
9580                         if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9581                         {
9582                                 if (lt == xpath_type_boolean || rt == xpath_type_boolean)
9583                                         return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack));
9584                                 else if (lt == xpath_type_number || rt == xpath_type_number)
9585                                         return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack));
9586                                 else if (lt == xpath_type_string || rt == xpath_type_string)
9587                                 {
9588                                         xpath_allocator_capture cr(stack.result);
9589
9590                                         xpath_string ls = lhs->eval_string(c, stack);
9591                                         xpath_string rs = rhs->eval_string(c, stack);
9592
9593                                         return comp(ls, rs);
9594                                 }
9595                         }
9596                         else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9597                         {
9598                                 xpath_allocator_capture cr(stack.result);
9599
9600                                 xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all);
9601                                 xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all);
9602
9603                                 for (const xpath_node* li = ls.begin(); li != ls.end(); ++li)
9604                                         for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
9605                                         {
9606                                                 xpath_allocator_capture cri(stack.result);
9607
9608                                                 if (comp(string_value(*li, stack.result), string_value(*ri, stack.result)))
9609                                                         return true;
9610                                         }
9611
9612                                 return false;
9613                         }
9614                         else
9615                         {
9616                                 if (lt == xpath_type_node_set)
9617                                 {
9618                                         swap(lhs, rhs);
9619                                         swap(lt, rt);
9620                                 }
9621
9622                                 if (lt == xpath_type_boolean)
9623                                         return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack));
9624                                 else if (lt == xpath_type_number)
9625                                 {
9626                                         xpath_allocator_capture cr(stack.result);
9627
9628                                         double l = lhs->eval_number(c, stack);
9629                                         xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all);
9630
9631                                         for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
9632                                         {
9633                                                 xpath_allocator_capture cri(stack.result);
9634
9635                                                 if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str())))
9636                                                         return true;
9637                                         }
9638
9639                                         return false;
9640                                 }
9641                                 else if (lt == xpath_type_string)
9642                                 {
9643                                         xpath_allocator_capture cr(stack.result);
9644
9645                                         xpath_string l = lhs->eval_string(c, stack);
9646                                         xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all);
9647
9648                                         for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
9649                                         {
9650                                                 xpath_allocator_capture cri(stack.result);
9651
9652                                                 if (comp(l, string_value(*ri, stack.result)))
9653                                                         return true;
9654                                         }
9655
9656                                         return false;
9657                                 }
9658                         }
9659
9660                         assert(false && "Wrong types"); // unreachable
9661                         return false;
9662                 }
9663
9664                 static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval)
9665                 {
9666                         return type == xpath_node_set::type_sorted ? eval != nodeset_eval_all : eval == nodeset_eval_any;
9667                 }
9668
9669                 template <class Comp> static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp)
9670                 {
9671                         xpath_value_type lt = lhs->rettype(), rt = rhs->rettype();
9672
9673                         if (lt != xpath_type_node_set && rt != xpath_type_node_set)
9674                                 return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack));
9675                         else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
9676                         {
9677                                 xpath_allocator_capture cr(stack.result);
9678
9679                                 xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all);
9680                                 xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all);
9681
9682                                 for (const xpath_node* li = ls.begin(); li != ls.end(); ++li)
9683                                 {
9684                                         xpath_allocator_capture cri(stack.result);
9685
9686                                         double l = convert_string_to_number(string_value(*li, stack.result).c_str());
9687
9688                                         for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
9689                                         {
9690                                                 xpath_allocator_capture crii(stack.result);
9691
9692                                                 if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str())))
9693                                                         return true;
9694                                         }
9695                                 }
9696
9697                                 return false;
9698                         }
9699                         else if (lt != xpath_type_node_set && rt == xpath_type_node_set)
9700                         {
9701                                 xpath_allocator_capture cr(stack.result);
9702
9703                                 double l = lhs->eval_number(c, stack);
9704                                 xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all);
9705
9706                                 for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
9707                                 {
9708                                         xpath_allocator_capture cri(stack.result);
9709
9710                                         if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str())))
9711                                                 return true;
9712                                 }
9713
9714                                 return false;
9715                         }
9716                         else if (lt == xpath_type_node_set && rt != xpath_type_node_set)
9717                         {
9718                                 xpath_allocator_capture cr(stack.result);
9719
9720                                 xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all);
9721                                 double r = rhs->eval_number(c, stack);
9722
9723                                 for (const xpath_node* li = ls.begin(); li != ls.end(); ++li)
9724                                 {
9725                                         xpath_allocator_capture cri(stack.result);
9726
9727                                         if (comp(convert_string_to_number(string_value(*li, stack.result).c_str()), r))
9728                                                 return true;
9729                                 }
9730
9731                                 return false;
9732                         }
9733                         else
9734                         {
9735                                 assert(false && "Wrong types"); // unreachable
9736                                 return false;
9737                         }
9738                 }
9739
9740                 static void apply_predicate_boolean(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once)
9741                 {
9742                         assert(ns.size() >= first);
9743                         assert(expr->rettype() != xpath_type_number);
9744
9745                         size_t i = 1;
9746                         size_t size = ns.size() - first;
9747
9748                         xpath_node* last = ns.begin() + first;
9749
9750                         // remove_if... or well, sort of
9751                         for (xpath_node* it = last; it != ns.end(); ++it, ++i)
9752                         {
9753                                 xpath_context c(*it, i, size);
9754
9755                                 if (expr->eval_boolean(c, stack))
9756                                 {
9757                                         *last++ = *it;
9758
9759                                         if (once) break;
9760                                 }
9761                         }
9762
9763                         ns.truncate(last);
9764                 }
9765
9766                 static void apply_predicate_number(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once)
9767                 {
9768                         assert(ns.size() >= first);
9769                         assert(expr->rettype() == xpath_type_number);
9770
9771                         size_t i = 1;
9772                         size_t size = ns.size() - first;
9773
9774                         xpath_node* last = ns.begin() + first;
9775
9776                         // remove_if... or well, sort of
9777                         for (xpath_node* it = last; it != ns.end(); ++it, ++i)
9778                         {
9779                                 xpath_context c(*it, i, size);
9780
9781                                 if (expr->eval_number(c, stack) == static_cast<double>(i))
9782                                 {
9783                                         *last++ = *it;
9784
9785                                         if (once) break;
9786                                 }
9787                         }
9788
9789                         ns.truncate(last);
9790                 }
9791
9792                 static void apply_predicate_number_const(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack)
9793                 {
9794                         assert(ns.size() >= first);
9795                         assert(expr->rettype() == xpath_type_number);
9796
9797                         size_t size = ns.size() - first;
9798
9799                         xpath_node* last = ns.begin() + first;
9800
9801                         xpath_context c(xpath_node(), 1, size);
9802
9803                         double er = expr->eval_number(c, stack);
9804
9805                         if (er >= 1.0 && er <= static_cast<double>(size))
9806                         {
9807                                 size_t eri = static_cast<size_t>(er);
9808
9809                                 if (er == static_cast<double>(eri))
9810                                 {
9811                                         xpath_node r = last[eri - 1];
9812
9813                                         *last++ = r;
9814                                 }
9815                         }
9816
9817                         ns.truncate(last);
9818                 }
9819
9820                 void apply_predicate(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, bool once)
9821                 {
9822                         if (ns.size() == first) return;
9823
9824                         assert(_type == ast_filter || _type == ast_predicate);
9825
9826                         if (_test == predicate_constant || _test == predicate_constant_one)
9827                                 apply_predicate_number_const(ns, first, _right, stack);
9828                         else if (_right->rettype() == xpath_type_number)
9829                                 apply_predicate_number(ns, first, _right, stack, once);
9830                         else
9831                                 apply_predicate_boolean(ns, first, _right, stack, once);
9832                 }
9833
9834                 void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, nodeset_eval_t eval)
9835                 {
9836                         if (ns.size() == first) return;
9837
9838                         bool last_once = eval_once(ns.type(), eval);
9839
9840                         for (xpath_ast_node* pred = _right; pred; pred = pred->_next)
9841                                 pred->apply_predicate(ns, first, stack, !pred->_next && last_once);
9842                 }
9843
9844                 bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc)
9845                 {
9846                         assert(a);
9847
9848                         const char_t* name = a->name ? a->name + 0 : PUGIXML_TEXT("");
9849
9850                         switch (_test)
9851                         {
9852                         case nodetest_name:
9853                                 if (strequal(name, _data.nodetest) && is_xpath_attribute(name))
9854                                 {
9855                                         ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9856                                         return true;
9857                                 }
9858                                 break;
9859
9860                         case nodetest_type_node:
9861                         case nodetest_all:
9862                                 if (is_xpath_attribute(name))
9863                                 {
9864                                         ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9865                                         return true;
9866                                 }
9867                                 break;
9868
9869                         case nodetest_all_in_namespace:
9870                                 if (starts_with(name, _data.nodetest) && is_xpath_attribute(name))
9871                                 {
9872                                         ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9873                                         return true;
9874                                 }
9875                                 break;
9876
9877                         default:
9878                                 ;
9879                         }
9880
9881                         return false;
9882                 }
9883
9884                 bool step_push(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc)
9885                 {
9886                         assert(n);
9887
9888                         xml_node_type type = PUGI__NODETYPE(n);
9889
9890                         switch (_test)
9891                         {
9892                         case nodetest_name:
9893                                 if (type == node_element && n->name && strequal(n->name, _data.nodetest))
9894                                 {
9895                                         ns.push_back(xml_node(n), alloc);
9896                                         return true;
9897                                 }
9898                                 break;
9899
9900                         case nodetest_type_node:
9901                                 ns.push_back(xml_node(n), alloc);
9902                                 return true;
9903
9904                         case nodetest_type_comment:
9905                                 if (type == node_comment)
9906                                 {
9907                                         ns.push_back(xml_node(n), alloc);
9908                                         return true;
9909                                 }
9910                                 break;
9911
9912                         case nodetest_type_text:
9913                                 if (type == node_pcdata || type == node_cdata)
9914                                 {
9915                                         ns.push_back(xml_node(n), alloc);
9916                                         return true;
9917                                 }
9918                                 break;
9919
9920                         case nodetest_type_pi:
9921                                 if (type == node_pi)
9922                                 {
9923                                         ns.push_back(xml_node(n), alloc);
9924                                         return true;
9925                                 }
9926                                 break;
9927
9928                         case nodetest_pi:
9929                                 if (type == node_pi && n->name && strequal(n->name, _data.nodetest))
9930                                 {
9931                                         ns.push_back(xml_node(n), alloc);
9932                                         return true;
9933                                 }
9934                                 break;
9935
9936                         case nodetest_all:
9937                                 if (type == node_element)
9938                                 {
9939                                         ns.push_back(xml_node(n), alloc);
9940                                         return true;
9941                                 }
9942                                 break;
9943
9944                         case nodetest_all_in_namespace:
9945                                 if (type == node_element && n->name && starts_with(n->name, _data.nodetest))
9946                                 {
9947                                         ns.push_back(xml_node(n), alloc);
9948                                         return true;
9949                                 }
9950                                 break;
9951
9952                         default:
9953                                 assert(false && "Unknown axis"); // unreachable
9954                         }
9955
9956                         return false;
9957                 }
9958
9959                 template <class T> void step_fill(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc, bool once, T)
9960                 {
9961                         const axis_t axis = T::axis;
9962
9963                         switch (axis)
9964                         {
9965                         case axis_attribute:
9966                         {
9967                                 for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute)
9968                                         if (step_push(ns, a, n, alloc) & once)
9969                                                 return;
9970
9971                                 break;
9972                         }
9973
9974                         case axis_child:
9975                         {
9976                                 for (xml_node_struct* c = n->first_child; c; c = c->next_sibling)
9977                                         if (step_push(ns, c, alloc) & once)
9978                                                 return;
9979
9980                                 break;
9981                         }
9982
9983                         case axis_descendant:
9984                         case axis_descendant_or_self:
9985                         {
9986                                 if (axis == axis_descendant_or_self)
9987                                         if (step_push(ns, n, alloc) & once)
9988                                                 return;
9989
9990                                 xml_node_struct* cur = n->first_child;
9991
9992                                 while (cur)
9993                                 {
9994                                         if (step_push(ns, cur, alloc) & once)
9995                                                 return;
9996
9997                                         if (cur->first_child)
9998                                                 cur = cur->first_child;
9999                                         else
10000                                         {
10001                                                 while (!cur->next_sibling)
10002                                                 {
10003                                                         cur = cur->parent;
10004
10005                                                         if (cur == n) return;
10006                                                 }
10007
10008                                                 cur = cur->next_sibling;
10009                                         }
10010                                 }
10011
10012                                 break;
10013                         }
10014
10015                         case axis_following_sibling:
10016                         {
10017                                 for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling)
10018                                         if (step_push(ns, c, alloc) & once)
10019                                                 return;
10020
10021                                 break;
10022                         }
10023
10024                         case axis_preceding_sibling:
10025                         {
10026                                 for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c)
10027                                         if (step_push(ns, c, alloc) & once)
10028                                                 return;
10029
10030                                 break;
10031                         }
10032
10033                         case axis_following:
10034                         {
10035                                 xml_node_struct* cur = n;
10036
10037                                 // exit from this node so that we don't include descendants
10038                                 while (!cur->next_sibling)
10039                                 {
10040                                         cur = cur->parent;
10041
10042                                         if (!cur) return;
10043                                 }
10044
10045                                 cur = cur->next_sibling;
10046
10047                                 while (cur)
10048                                 {
10049                                         if (step_push(ns, cur, alloc) & once)
10050                                                 return;
10051
10052                                         if (cur->first_child)
10053                                                 cur = cur->first_child;
10054                                         else
10055                                         {
10056                                                 while (!cur->next_sibling)
10057                                                 {
10058                                                         cur = cur->parent;
10059
10060                                                         if (!cur) return;
10061                                                 }
10062
10063                                                 cur = cur->next_sibling;
10064                                         }
10065                                 }
10066
10067                                 break;
10068                         }
10069
10070                         case axis_preceding:
10071                         {
10072                                 xml_node_struct* cur = n;
10073
10074                                 // exit from this node so that we don't include descendants
10075                                 while (!cur->prev_sibling_c->next_sibling)
10076                                 {
10077                                         cur = cur->parent;
10078
10079                                         if (!cur) return;
10080                                 }
10081
10082                                 cur = cur->prev_sibling_c;
10083
10084                                 while (cur)
10085                                 {
10086                                         if (cur->first_child)
10087                                                 cur = cur->first_child->prev_sibling_c;
10088                                         else
10089                                         {
10090                                                 // leaf node, can't be ancestor
10091                                                 if (step_push(ns, cur, alloc) & once)
10092                                                         return;
10093
10094                                                 while (!cur->prev_sibling_c->next_sibling)
10095                                                 {
10096                                                         cur = cur->parent;
10097
10098                                                         if (!cur) return;
10099
10100                                                         if (!node_is_ancestor(cur, n))
10101                                                                 if (step_push(ns, cur, alloc) & once)
10102                                                                         return;
10103                                                 }
10104
10105                                                 cur = cur->prev_sibling_c;
10106                                         }
10107                                 }
10108
10109                                 break;
10110                         }
10111
10112                         case axis_ancestor:
10113                         case axis_ancestor_or_self:
10114                         {
10115                                 if (axis == axis_ancestor_or_self)
10116                                         if (step_push(ns, n, alloc) & once)
10117                                                 return;
10118
10119                                 xml_node_struct* cur = n->parent;
10120
10121                                 while (cur)
10122                                 {
10123                                         if (step_push(ns, cur, alloc) & once)
10124                                                 return;
10125
10126                                         cur = cur->parent;
10127                                 }
10128
10129                                 break;
10130                         }
10131
10132                         case axis_self:
10133                         {
10134                                 step_push(ns, n, alloc);
10135
10136                                 break;
10137                         }
10138
10139                         case axis_parent:
10140                         {
10141                                 if (n->parent)
10142                                         step_push(ns, n->parent, alloc);
10143
10144                                 break;
10145                         }
10146
10147                         default:
10148                                 assert(false && "Unimplemented axis"); // unreachable
10149                         }
10150                 }
10151
10152                 template <class T> void step_fill(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* p, xpath_allocator* alloc, bool once, T v)
10153                 {
10154                         const axis_t axis = T::axis;
10155
10156                         switch (axis)
10157                         {
10158                         case axis_ancestor:
10159                         case axis_ancestor_or_self:
10160                         {
10161                                 if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test
10162                                         if (step_push(ns, a, p, alloc) & once)
10163                                                 return;
10164
10165                                 xml_node_struct* cur = p;
10166
10167                                 while (cur)
10168                                 {
10169                                         if (step_push(ns, cur, alloc) & once)
10170                                                 return;
10171
10172                                         cur = cur->parent;
10173                                 }
10174
10175                                 break;
10176                         }
10177
10178                         case axis_descendant_or_self:
10179                         case axis_self:
10180                         {
10181                                 if (_test == nodetest_type_node) // reject attributes based on principal node type test
10182                                         step_push(ns, a, p, alloc);
10183
10184                                 break;
10185                         }
10186
10187                         case axis_following:
10188                         {
10189                                 xml_node_struct* cur = p;
10190
10191                                 while (cur)
10192                                 {
10193                                         if (cur->first_child)
10194                                                 cur = cur->first_child;
10195                                         else
10196                                         {
10197                                                 while (!cur->next_sibling)
10198                                                 {
10199                                                         cur = cur->parent;
10200
10201                                                         if (!cur) return;
10202                                                 }
10203
10204                                                 cur = cur->next_sibling;
10205                                         }
10206
10207                                         if (step_push(ns, cur, alloc) & once)
10208                                                 return;
10209                                 }
10210
10211                                 break;
10212                         }
10213
10214                         case axis_parent:
10215                         {
10216                                 step_push(ns, p, alloc);
10217
10218                                 break;
10219                         }
10220
10221                         case axis_preceding:
10222                         {
10223                                 // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding
10224                                 step_fill(ns, p, alloc, once, v);
10225                                 break;
10226                         }
10227
10228                         default:
10229                                 assert(false && "Unimplemented axis"); // unreachable
10230                         }
10231                 }
10232
10233                 template <class T> void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v)
10234                 {
10235                         const axis_t axis = T::axis;
10236                         const bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self);
10237
10238                         if (xn.node())
10239                                 step_fill(ns, xn.node().internal_object(), alloc, once, v);
10240                         else if (axis_has_attributes && xn.attribute() && xn.parent())
10241                                 step_fill(ns, xn.attribute().internal_object(), xn.parent().internal_object(), alloc, once, v);
10242                 }
10243
10244                 template <class T> xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval, T v)
10245                 {
10246                         const axis_t axis = T::axis;
10247                         const bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling);
10248                         const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted;
10249
10250                         bool once =
10251                                 (axis == axis_attribute && _test == nodetest_name) ||
10252                                 (!_right && eval_once(axis_type, eval)) ||
10253                             // coverity[mixed_enums]
10254                                 (_right && !_right->_next && _right->_test == predicate_constant_one);
10255
10256                         xpath_node_set_raw ns;
10257                         ns.set_type(axis_type);
10258
10259                         if (_left)
10260                         {
10261                                 xpath_node_set_raw s = _left->eval_node_set(c, stack, nodeset_eval_all);
10262
10263                                 // self axis preserves the original order
10264                                 if (axis == axis_self) ns.set_type(s.type());
10265
10266                                 for (const xpath_node* it = s.begin(); it != s.end(); ++it)
10267                                 {
10268                                         size_t size = ns.size();
10269
10270                                         // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes
10271                                         if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted);
10272
10273                                         step_fill(ns, *it, stack.result, once, v);
10274                                         if (_right) apply_predicates(ns, size, stack, eval);
10275                                 }
10276                         }
10277                         else
10278                         {
10279                                 step_fill(ns, c.n, stack.result, once, v);
10280                                 if (_right) apply_predicates(ns, 0, stack, eval);
10281                         }
10282
10283                         // child, attribute and self axes always generate unique set of nodes
10284                         // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice
10285                         if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted)
10286                                 ns.remove_duplicates(stack.temp);
10287
10288                         return ns;
10289                 }
10290
10291         public:
10292                 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value):
10293                         _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10294                 {
10295                         assert(type == ast_string_constant);
10296                         _data.string = value;
10297                 }
10298
10299                 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value):
10300                         _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10301                 {
10302                         assert(type == ast_number_constant);
10303                         _data.number = value;
10304                 }
10305
10306                 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value):
10307                         _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10308                 {
10309                         assert(type == ast_variable);
10310                         _data.variable = value;
10311                 }
10312
10313                 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0):
10314                         _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0)
10315                 {
10316                 }
10317
10318                 xpath_ast_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents):
10319                         _type(static_cast<char>(type)), _rettype(xpath_type_node_set), _axis(static_cast<char>(axis)), _test(static_cast<char>(test)), _left(left), _right(0), _next(0)
10320                 {
10321                         assert(type == ast_step);
10322                         _data.nodetest = contents;
10323                 }
10324
10325                 xpath_ast_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test):
10326                         _type(static_cast<char>(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast<char>(test)), _left(left), _right(right), _next(0)
10327                 {
10328                         assert(type == ast_filter || type == ast_predicate);
10329                 }
10330
10331                 void set_next(xpath_ast_node* value)
10332                 {
10333                         _next = value;
10334                 }
10335
10336                 void set_right(xpath_ast_node* value)
10337                 {
10338                         _right = value;
10339                 }
10340
10341                 bool eval_boolean(const xpath_context& c, const xpath_stack& stack)
10342                 {
10343                         switch (_type)
10344                         {
10345                         case ast_op_or:
10346                                 return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack);
10347
10348                         case ast_op_and:
10349                                 return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack);
10350
10351                         case ast_op_equal:
10352                                 return compare_eq(_left, _right, c, stack, equal_to());
10353
10354                         case ast_op_not_equal:
10355                                 return compare_eq(_left, _right, c, stack, not_equal_to());
10356
10357                         case ast_op_less:
10358                                 return compare_rel(_left, _right, c, stack, less());
10359
10360                         case ast_op_greater:
10361                                 return compare_rel(_right, _left, c, stack, less());
10362
10363                         case ast_op_less_or_equal:
10364                                 return compare_rel(_left, _right, c, stack, less_equal());
10365
10366                         case ast_op_greater_or_equal:
10367                                 return compare_rel(_right, _left, c, stack, less_equal());
10368
10369                         case ast_func_starts_with:
10370                         {
10371                                 xpath_allocator_capture cr(stack.result);
10372
10373                                 xpath_string lr = _left->eval_string(c, stack);
10374                                 xpath_string rr = _right->eval_string(c, stack);
10375
10376                                 return starts_with(lr.c_str(), rr.c_str());
10377                         }
10378
10379                         case ast_func_contains:
10380                         {
10381                                 xpath_allocator_capture cr(stack.result);
10382
10383                                 xpath_string lr = _left->eval_string(c, stack);
10384                                 xpath_string rr = _right->eval_string(c, stack);
10385
10386                                 return find_substring(lr.c_str(), rr.c_str()) != 0;
10387                         }
10388
10389                         case ast_func_boolean:
10390                                 return _left->eval_boolean(c, stack);
10391
10392                         case ast_func_not:
10393                                 return !_left->eval_boolean(c, stack);
10394
10395                         case ast_func_true:
10396                                 return true;
10397
10398                         case ast_func_false:
10399                                 return false;
10400
10401                         case ast_func_lang:
10402                         {
10403                                 if (c.n.attribute()) return false;
10404
10405                                 xpath_allocator_capture cr(stack.result);
10406
10407                                 xpath_string lang = _left->eval_string(c, stack);
10408
10409                                 for (xml_node n = c.n.node(); n; n = n.parent())
10410                                 {
10411                                         xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang"));
10412
10413                                         if (a)
10414                                         {
10415                                                 const char_t* value = a.value();
10416
10417                                                 // strnicmp / strncasecmp is not portable
10418                                                 for (const char_t* lit = lang.c_str(); *lit; ++lit)
10419                                                 {
10420                                                         if (tolower_ascii(*lit) != tolower_ascii(*value)) return false;
10421                                                         ++value;
10422                                                 }
10423
10424                                                 return *value == 0 || *value == '-';
10425                                         }
10426                                 }
10427
10428                                 return false;
10429                         }
10430
10431                         case ast_opt_compare_attribute:
10432                         {
10433                                 const char_t* value = (_right->_type == ast_string_constant) ? _right->_data.string : _right->_data.variable->get_string();
10434
10435                                 xml_attribute attr = c.n.node().attribute(_left->_data.nodetest);
10436
10437                                 return attr && strequal(attr.value(), value) && is_xpath_attribute(attr.name());
10438                         }
10439
10440                         case ast_variable:
10441                         {
10442                                 assert(_rettype == _data.variable->type());
10443
10444                                 if (_rettype == xpath_type_boolean)
10445                                         return _data.variable->get_boolean();
10446
10447                                 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
10448                                 break;
10449                         }
10450
10451                         default:
10452                                 ;
10453                         }
10454
10455                         // none of the ast types that return the value directly matched, we need to perform type conversion
10456                         switch (_rettype)
10457                         {
10458                         case xpath_type_number:
10459                                 return convert_number_to_boolean(eval_number(c, stack));
10460
10461                         case xpath_type_string:
10462                         {
10463                                 xpath_allocator_capture cr(stack.result);
10464
10465                                 return !eval_string(c, stack).empty();
10466                         }
10467
10468                         case xpath_type_node_set:
10469                         {
10470                                 xpath_allocator_capture cr(stack.result);
10471
10472                                 return !eval_node_set(c, stack, nodeset_eval_any).empty();
10473                         }
10474
10475                         default:
10476                                 assert(false && "Wrong expression for return type boolean"); // unreachable
10477                                 return false;
10478                         }
10479                 }
10480
10481                 double eval_number(const xpath_context& c, const xpath_stack& stack)
10482                 {
10483                         switch (_type)
10484                         {
10485                         case ast_op_add:
10486                                 return _left->eval_number(c, stack) + _right->eval_number(c, stack);
10487
10488                         case ast_op_subtract:
10489                                 return _left->eval_number(c, stack) - _right->eval_number(c, stack);
10490
10491                         case ast_op_multiply:
10492                                 return _left->eval_number(c, stack) * _right->eval_number(c, stack);
10493
10494                         case ast_op_divide:
10495                                 return _left->eval_number(c, stack) / _right->eval_number(c, stack);
10496
10497                         case ast_op_mod:
10498                                 return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack));
10499
10500                         case ast_op_negate:
10501                                 return -_left->eval_number(c, stack);
10502
10503                         case ast_number_constant:
10504                                 return _data.number;
10505
10506                         case ast_func_last:
10507                                 return static_cast<double>(c.size);
10508
10509                         case ast_func_position:
10510                                 return static_cast<double>(c.position);
10511
10512                         case ast_func_count:
10513                         {
10514                                 xpath_allocator_capture cr(stack.result);
10515
10516                                 return static_cast<double>(_left->eval_node_set(c, stack, nodeset_eval_all).size());
10517                         }
10518
10519                         case ast_func_string_length_0:
10520                         {
10521                                 xpath_allocator_capture cr(stack.result);
10522
10523                                 return static_cast<double>(string_value(c.n, stack.result).length());
10524                         }
10525
10526                         case ast_func_string_length_1:
10527                         {
10528                                 xpath_allocator_capture cr(stack.result);
10529
10530                                 return static_cast<double>(_left->eval_string(c, stack).length());
10531                         }
10532
10533                         case ast_func_number_0:
10534                         {
10535                                 xpath_allocator_capture cr(stack.result);
10536
10537                                 return convert_string_to_number(string_value(c.n, stack.result).c_str());
10538                         }
10539
10540                         case ast_func_number_1:
10541                                 return _left->eval_number(c, stack);
10542
10543                         case ast_func_sum:
10544                         {
10545                                 xpath_allocator_capture cr(stack.result);
10546
10547                                 double r = 0;
10548
10549                                 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_all);
10550
10551                                 for (const xpath_node* it = ns.begin(); it != ns.end(); ++it)
10552                                 {
10553                                         xpath_allocator_capture cri(stack.result);
10554
10555                                         r += convert_string_to_number(string_value(*it, stack.result).c_str());
10556                                 }
10557
10558                                 return r;
10559                         }
10560
10561                         case ast_func_floor:
10562                         {
10563                                 double r = _left->eval_number(c, stack);
10564
10565                                 return r == r ? floor(r) : r;
10566                         }
10567
10568                         case ast_func_ceiling:
10569                         {
10570                                 double r = _left->eval_number(c, stack);
10571
10572                                 return r == r ? ceil(r) : r;
10573                         }
10574
10575                         case ast_func_round:
10576                                 return round_nearest_nzero(_left->eval_number(c, stack));
10577
10578                         case ast_variable:
10579                         {
10580                                 assert(_rettype == _data.variable->type());
10581
10582                                 if (_rettype == xpath_type_number)
10583                                         return _data.variable->get_number();
10584
10585                                 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
10586                                 break;
10587                         }
10588
10589                         default:
10590                                 ;
10591                         }
10592
10593                         // none of the ast types that return the value directly matched, we need to perform type conversion
10594                         switch (_rettype)
10595                         {
10596                         case xpath_type_boolean:
10597                                 return eval_boolean(c, stack) ? 1 : 0;
10598
10599                         case xpath_type_string:
10600                         {
10601                                 xpath_allocator_capture cr(stack.result);
10602
10603                                 return convert_string_to_number(eval_string(c, stack).c_str());
10604                         }
10605
10606                         case xpath_type_node_set:
10607                         {
10608                                 xpath_allocator_capture cr(stack.result);
10609
10610                                 return convert_string_to_number(eval_string(c, stack).c_str());
10611                         }
10612
10613                         default:
10614                                 assert(false && "Wrong expression for return type number"); // unreachable
10615                                 return 0;
10616                         }
10617                 }
10618
10619                 xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack)
10620                 {
10621                         assert(_type == ast_func_concat);
10622
10623                         xpath_allocator_capture ct(stack.temp);
10624
10625                         // count the string number
10626                         size_t count = 1;
10627                         for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++;
10628
10629                         // allocate a buffer for temporary string objects
10630                         xpath_string* buffer = static_cast<xpath_string*>(stack.temp->allocate(count * sizeof(xpath_string)));
10631                         if (!buffer) return xpath_string();
10632
10633                         // evaluate all strings to temporary stack
10634                         xpath_stack swapped_stack = {stack.temp, stack.result};
10635
10636                         buffer[0] = _left->eval_string(c, swapped_stack);
10637
10638                         size_t pos = 1;
10639                         for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack);
10640                         assert(pos == count);
10641
10642                         // get total length
10643                         size_t length = 0;
10644                         for (size_t i = 0; i < count; ++i) length += buffer[i].length();
10645
10646                         // create final string
10647                         char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t)));
10648                         if (!result) return xpath_string();
10649
10650                         char_t* ri = result;
10651
10652                         for (size_t j = 0; j < count; ++j)
10653                                 for (const char_t* bi = buffer[j].c_str(); *bi; ++bi)
10654                                         *ri++ = *bi;
10655
10656                         *ri = 0;
10657
10658                         return xpath_string::from_heap_preallocated(result, ri);
10659                 }
10660
10661                 xpath_string eval_string(const xpath_context& c, const xpath_stack& stack)
10662                 {
10663                         switch (_type)
10664                         {
10665                         case ast_string_constant:
10666                                 return xpath_string::from_const(_data.string);
10667
10668                         case ast_func_local_name_0:
10669                         {
10670                                 xpath_node na = c.n;
10671
10672                                 return xpath_string::from_const(local_name(na));
10673                         }
10674
10675                         case ast_func_local_name_1:
10676                         {
10677                                 xpath_allocator_capture cr(stack.result);
10678
10679                                 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10680                                 xpath_node na = ns.first();
10681
10682                                 return xpath_string::from_const(local_name(na));
10683                         }
10684
10685                         case ast_func_name_0:
10686                         {
10687                                 xpath_node na = c.n;
10688
10689                                 return xpath_string::from_const(qualified_name(na));
10690                         }
10691
10692                         case ast_func_name_1:
10693                         {
10694                                 xpath_allocator_capture cr(stack.result);
10695
10696                                 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10697                                 xpath_node na = ns.first();
10698
10699                                 return xpath_string::from_const(qualified_name(na));
10700                         }
10701
10702                         case ast_func_namespace_uri_0:
10703                         {
10704                                 xpath_node na = c.n;
10705
10706                                 return xpath_string::from_const(namespace_uri(na));
10707                         }
10708
10709                         case ast_func_namespace_uri_1:
10710                         {
10711                                 xpath_allocator_capture cr(stack.result);
10712
10713                                 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10714                                 xpath_node na = ns.first();
10715
10716                                 return xpath_string::from_const(namespace_uri(na));
10717                         }
10718
10719                         case ast_func_string_0:
10720                                 return string_value(c.n, stack.result);
10721
10722                         case ast_func_string_1:
10723                                 return _left->eval_string(c, stack);
10724
10725                         case ast_func_concat:
10726                                 return eval_string_concat(c, stack);
10727
10728                         case ast_func_substring_before:
10729                         {
10730                                 xpath_allocator_capture cr(stack.temp);
10731
10732                                 xpath_stack swapped_stack = {stack.temp, stack.result};
10733
10734                                 xpath_string s = _left->eval_string(c, swapped_stack);
10735                                 xpath_string p = _right->eval_string(c, swapped_stack);
10736
10737                                 const char_t* pos = find_substring(s.c_str(), p.c_str());
10738
10739                                 return pos ? xpath_string::from_heap(s.c_str(), pos, stack.result) : xpath_string();
10740                         }
10741
10742                         case ast_func_substring_after:
10743                         {
10744                                 xpath_allocator_capture cr(stack.temp);
10745
10746                                 xpath_stack swapped_stack = {stack.temp, stack.result};
10747
10748                                 xpath_string s = _left->eval_string(c, swapped_stack);
10749                                 xpath_string p = _right->eval_string(c, swapped_stack);
10750
10751                                 const char_t* pos = find_substring(s.c_str(), p.c_str());
10752                                 if (!pos) return xpath_string();
10753
10754                                 const char_t* rbegin = pos + p.length();
10755                                 const char_t* rend = s.c_str() + s.length();
10756
10757                                 return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin);
10758                         }
10759
10760                         case ast_func_substring_2:
10761                         {
10762                                 xpath_allocator_capture cr(stack.temp);
10763
10764                                 xpath_stack swapped_stack = {stack.temp, stack.result};
10765
10766                                 xpath_string s = _left->eval_string(c, swapped_stack);
10767                                 size_t s_length = s.length();
10768
10769                                 double first = round_nearest(_right->eval_number(c, stack));
10770
10771                                 if (is_nan(first)) return xpath_string(); // NaN
10772                                 else if (first >= static_cast<double>(s_length + 1)) return xpath_string();
10773
10774                                 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10775                                 assert(1 <= pos && pos <= s_length + 1);
10776
10777                                 const char_t* rbegin = s.c_str() + (pos - 1);
10778                                 const char_t* rend = s.c_str() + s.length();
10779
10780                                 return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin);
10781                         }
10782
10783                         case ast_func_substring_3:
10784                         {
10785                                 xpath_allocator_capture cr(stack.temp);
10786
10787                                 xpath_stack swapped_stack = {stack.temp, stack.result};
10788
10789                                 xpath_string s = _left->eval_string(c, swapped_stack);
10790                                 size_t s_length = s.length();
10791
10792                                 double first = round_nearest(_right->eval_number(c, stack));
10793                                 double last = first + round_nearest(_right->_next->eval_number(c, stack));
10794
10795                                 if (is_nan(first) || is_nan(last)) return xpath_string();
10796                                 else if (first >= static_cast<double>(s_length + 1)) return xpath_string();
10797                                 else if (first >= last) return xpath_string();
10798                                 else if (last < 1) return xpath_string();
10799
10800                                 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10801                                 size_t end = last >= static_cast<double>(s_length + 1) ? s_length + 1 : static_cast<size_t>(last);
10802
10803                                 assert(1 <= pos && pos <= end && end <= s_length + 1);
10804                                 const char_t* rbegin = s.c_str() + (pos - 1);
10805                                 const char_t* rend = s.c_str() + (end - 1);
10806
10807                                 return (end == s_length + 1 && !s.uses_heap()) ? xpath_string::from_const(rbegin) : xpath_string::from_heap(rbegin, rend, stack.result);
10808                         }
10809
10810                         case ast_func_normalize_space_0:
10811                         {
10812                                 xpath_string s = string_value(c.n, stack.result);
10813
10814                                 char_t* begin = s.data(stack.result);
10815                                 if (!begin) return xpath_string();
10816
10817                                 char_t* end = normalize_space(begin);
10818
10819                                 return xpath_string::from_heap_preallocated(begin, end);
10820                         }
10821
10822                         case ast_func_normalize_space_1:
10823                         {
10824                                 xpath_string s = _left->eval_string(c, stack);
10825
10826                                 char_t* begin = s.data(stack.result);
10827                                 if (!begin) return xpath_string();
10828
10829                                 char_t* end = normalize_space(begin);
10830
10831                                 return xpath_string::from_heap_preallocated(begin, end);
10832                         }
10833
10834                         case ast_func_translate:
10835                         {
10836                                 xpath_allocator_capture cr(stack.temp);
10837
10838                                 xpath_stack swapped_stack = {stack.temp, stack.result};
10839
10840                                 xpath_string s = _left->eval_string(c, stack);
10841                                 xpath_string from = _right->eval_string(c, swapped_stack);
10842                                 xpath_string to = _right->_next->eval_string(c, swapped_stack);
10843
10844                                 char_t* begin = s.data(stack.result);
10845                                 if (!begin) return xpath_string();
10846
10847                                 char_t* end = translate(begin, from.c_str(), to.c_str(), to.length());
10848
10849                                 return xpath_string::from_heap_preallocated(begin, end);
10850                         }
10851
10852                         case ast_opt_translate_table:
10853                         {
10854                                 xpath_string s = _left->eval_string(c, stack);
10855
10856                                 char_t* begin = s.data(stack.result);
10857                                 if (!begin) return xpath_string();
10858
10859                                 char_t* end = translate_table(begin, _data.table);
10860
10861                                 return xpath_string::from_heap_preallocated(begin, end);
10862                         }
10863
10864                         case ast_variable:
10865                         {
10866                                 assert(_rettype == _data.variable->type());
10867
10868                                 if (_rettype == xpath_type_string)
10869                                         return xpath_string::from_const(_data.variable->get_string());
10870
10871                                 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
10872                                 break;
10873                         }
10874
10875                         default:
10876                                 ;
10877                         }
10878
10879                         // none of the ast types that return the value directly matched, we need to perform type conversion
10880                         switch (_rettype)
10881                         {
10882                         case xpath_type_boolean:
10883                                 return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"));
10884
10885                         case xpath_type_number:
10886                                 return convert_number_to_string(eval_number(c, stack), stack.result);
10887
10888                         case xpath_type_node_set:
10889                         {
10890                                 xpath_allocator_capture cr(stack.temp);
10891
10892                                 xpath_stack swapped_stack = {stack.temp, stack.result};
10893
10894                                 xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first);
10895                                 return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result);
10896                         }
10897
10898                         default:
10899                                 assert(false && "Wrong expression for return type string"); // unreachable
10900                                 return xpath_string();
10901                         }
10902                 }
10903
10904                 xpath_node_set_raw eval_node_set(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval)
10905                 {
10906                         switch (_type)
10907                         {
10908                         case ast_op_union:
10909                         {
10910                                 xpath_allocator_capture cr(stack.temp);
10911
10912                                 xpath_stack swapped_stack = {stack.temp, stack.result};
10913
10914                                 xpath_node_set_raw ls = _left->eval_node_set(c, stack, eval);
10915                                 xpath_node_set_raw rs = _right->eval_node_set(c, swapped_stack, eval);
10916
10917                                 // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother
10918                                 ls.set_type(xpath_node_set::type_unsorted);
10919
10920                                 ls.append(rs.begin(), rs.end(), stack.result);
10921                                 ls.remove_duplicates(stack.temp);
10922
10923                                 return ls;
10924                         }
10925
10926                         case ast_filter:
10927                         {
10928                                 xpath_node_set_raw set = _left->eval_node_set(c, stack, _test == predicate_constant_one ? nodeset_eval_first : nodeset_eval_all);
10929
10930                                 // either expression is a number or it contains position() call; sort by document order
10931                                 if (_test != predicate_posinv) set.sort_do();
10932
10933                                 bool once = eval_once(set.type(), eval);
10934
10935                                 apply_predicate(set, 0, stack, once);
10936
10937                                 return set;
10938                         }
10939
10940                         case ast_func_id:
10941                                 return xpath_node_set_raw();
10942
10943                         case ast_step:
10944                         {
10945                                 switch (_axis)
10946                                 {
10947                                 case axis_ancestor:
10948                                         return step_do(c, stack, eval, axis_to_type<axis_ancestor>());
10949
10950                                 case axis_ancestor_or_self:
10951                                         return step_do(c, stack, eval, axis_to_type<axis_ancestor_or_self>());
10952
10953                                 case axis_attribute:
10954                                         return step_do(c, stack, eval, axis_to_type<axis_attribute>());
10955
10956                                 case axis_child:
10957                                         return step_do(c, stack, eval, axis_to_type<axis_child>());
10958
10959                                 case axis_descendant:
10960                                         return step_do(c, stack, eval, axis_to_type<axis_descendant>());
10961
10962                                 case axis_descendant_or_self:
10963                                         return step_do(c, stack, eval, axis_to_type<axis_descendant_or_self>());
10964
10965                                 case axis_following:
10966                                         return step_do(c, stack, eval, axis_to_type<axis_following>());
10967
10968                                 case axis_following_sibling:
10969                                         return step_do(c, stack, eval, axis_to_type<axis_following_sibling>());
10970
10971                                 case axis_namespace:
10972                                         // namespaced axis is not supported
10973                                         return xpath_node_set_raw();
10974
10975                                 case axis_parent:
10976                                         return step_do(c, stack, eval, axis_to_type<axis_parent>());
10977
10978                                 case axis_preceding:
10979                                         return step_do(c, stack, eval, axis_to_type<axis_preceding>());
10980
10981                                 case axis_preceding_sibling:
10982                                         return step_do(c, stack, eval, axis_to_type<axis_preceding_sibling>());
10983
10984                                 case axis_self:
10985                                         return step_do(c, stack, eval, axis_to_type<axis_self>());
10986
10987                                 default:
10988                                         assert(false && "Unknown axis"); // unreachable
10989                                         return xpath_node_set_raw();
10990                                 }
10991                         }
10992
10993                         case ast_step_root:
10994                         {
10995                                 assert(!_right); // root step can't have any predicates
10996
10997                                 xpath_node_set_raw ns;
10998
10999                                 ns.set_type(xpath_node_set::type_sorted);
11000
11001                                 if (c.n.node()) ns.push_back(c.n.node().root(), stack.result);
11002                                 else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result);
11003
11004                                 return ns;
11005                         }
11006
11007                         case ast_variable:
11008                         {
11009                                 assert(_rettype == _data.variable->type());
11010
11011                                 if (_rettype == xpath_type_node_set)
11012                                 {
11013                                         const xpath_node_set& s = _data.variable->get_node_set();
11014
11015                                         xpath_node_set_raw ns;
11016
11017                                         ns.set_type(s.type());
11018                                         ns.append(s.begin(), s.end(), stack.result);
11019
11020                                         return ns;
11021                                 }
11022
11023                                 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
11024                                 break;
11025                         }
11026
11027                         default:
11028                                 ;
11029                         }
11030
11031                         // none of the ast types that return the value directly matched, but conversions to node set are invalid
11032                         assert(false && "Wrong expression for return type node set"); // unreachable
11033                         return xpath_node_set_raw();
11034                 }
11035
11036                 void optimize(xpath_allocator* alloc)
11037                 {
11038                         if (_left)
11039                                 _left->optimize(alloc);
11040
11041                         if (_right)
11042                                 _right->optimize(alloc);
11043
11044                         if (_next)
11045                                 _next->optimize(alloc);
11046
11047                         // coverity[var_deref_model]
11048                         optimize_self(alloc);
11049                 }
11050
11051                 void optimize_self(xpath_allocator* alloc)
11052                 {
11053                         // Rewrite [position()=expr] with [expr]
11054                         // Note that this step has to go before classification to recognize [position()=1]
11055                         if ((_type == ast_filter || _type == ast_predicate) &&
11056                                 _right && // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate)
11057                                 _right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number)
11058                         {
11059                                 _right = _right->_right;
11060                         }
11061
11062                         // Classify filter/predicate ops to perform various optimizations during evaluation
11063                         if ((_type == ast_filter || _type == ast_predicate) && _right) // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate)
11064                         {
11065                                 assert(_test == predicate_default);
11066
11067                                 if (_right->_type == ast_number_constant && _right->_data.number == 1.0)
11068                                         _test = predicate_constant_one;
11069                                 else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable || _right->_type == ast_func_last))
11070                                         _test = predicate_constant;
11071                                 else if (_right->_rettype != xpath_type_number && _right->is_posinv_expr())
11072                                         _test = predicate_posinv;
11073                         }
11074
11075                         // Rewrite descendant-or-self::node()/child::foo with descendant::foo
11076                         // The former is a full form of //foo, the latter is much faster since it executes the node test immediately
11077                         // Do a similar kind of rewrite for self/descendant/descendant-or-self axes
11078                         // Note that we only rewrite positionally invariant steps (//foo[1] != /descendant::foo[1])
11079                         if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) &&
11080                                 _left && _left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right &&
11081                                 is_posinv_step())
11082                         {
11083                                 if (_axis == axis_child || _axis == axis_descendant)
11084                                         _axis = axis_descendant;
11085                                 else
11086                                         _axis = axis_descendant_or_self;
11087
11088                                 _left = _left->_left;
11089                         }
11090
11091                         // Use optimized lookup table implementation for translate() with constant arguments
11092                         if (_type == ast_func_translate &&
11093                                 _right && // workaround for clang static analyzer (_right is never null for ast_func_translate)
11094                                 _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant)
11095                         {
11096                                 unsigned char* table = translate_table_generate(alloc, _right->_data.string, _right->_next->_data.string);
11097
11098                                 if (table)
11099                                 {
11100                                         _type = ast_opt_translate_table;
11101                                         _data.table = table;
11102                                 }
11103                         }
11104
11105                         // Use optimized path for @attr = 'value' or @attr = $value
11106                         if (_type == ast_op_equal &&
11107                                 _left && _right && // workaround for clang static analyzer and Coverity (_left and _right are never null for ast_op_equal)
11108                 // coverity[mixed_enums]
11109                                 _left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right &&
11110                                 (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string)))
11111                         {
11112                                 _type = ast_opt_compare_attribute;
11113                         }
11114                 }
11115
11116                 bool is_posinv_expr() const
11117                 {
11118                         switch (_type)
11119                         {
11120                         case ast_func_position:
11121                         case ast_func_last:
11122                                 return false;
11123
11124                         case ast_string_constant:
11125                         case ast_number_constant:
11126                         case ast_variable:
11127                                 return true;
11128
11129                         case ast_step:
11130                         case ast_step_root:
11131                                 return true;
11132
11133                         case ast_predicate:
11134                         case ast_filter:
11135                                 return true;
11136
11137                         default:
11138                                 if (_left && !_left->is_posinv_expr()) return false;
11139
11140                                 for (xpath_ast_node* n = _right; n; n = n->_next)
11141                                         if (!n->is_posinv_expr()) return false;
11142
11143                                 return true;
11144                         }
11145                 }
11146
11147                 bool is_posinv_step() const
11148                 {
11149                         assert(_type == ast_step);
11150
11151                         for (xpath_ast_node* n = _right; n; n = n->_next)
11152                         {
11153                                 assert(n->_type == ast_predicate);
11154
11155                                 if (n->_test != predicate_posinv)
11156                                         return false;
11157                         }
11158
11159                         return true;
11160                 }
11161
11162                 xpath_value_type rettype() const
11163                 {
11164                         return static_cast<xpath_value_type>(_rettype);
11165                 }
11166         };
11167
11168         static const size_t xpath_ast_depth_limit =
11169         #ifdef PUGIXML_XPATH_DEPTH_LIMIT
11170                 PUGIXML_XPATH_DEPTH_LIMIT
11171         #else
11172                 1024
11173         #endif
11174                 ;
11175
11176         struct xpath_parser
11177         {
11178                 xpath_allocator* _alloc;
11179                 xpath_lexer _lexer;
11180
11181                 const char_t* _query;
11182                 xpath_variable_set* _variables;
11183
11184                 xpath_parse_result* _result;
11185
11186                 char_t _scratch[32];
11187
11188                 size_t _depth;
11189
11190                 xpath_ast_node* error(const char* message)
11191                 {
11192                         _result->error = message;
11193                         _result->offset = _lexer.current_pos() - _query;
11194
11195                         return 0;
11196                 }
11197
11198                 xpath_ast_node* error_oom()
11199                 {
11200                         assert(_alloc->_error);
11201                         *_alloc->_error = true;
11202
11203                         return 0;
11204                 }
11205
11206                 xpath_ast_node* error_rec()
11207                 {
11208                         return error("Exceeded maximum allowed query depth");
11209                 }
11210
11211                 void* alloc_node()
11212                 {
11213                         return _alloc->allocate(sizeof(xpath_ast_node));
11214                 }
11215
11216                 xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, const char_t* value)
11217                 {
11218                         void* memory = alloc_node();
11219                         return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0;
11220                 }
11221
11222                 xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, double value)
11223                 {
11224                         void* memory = alloc_node();
11225                         return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0;
11226                 }
11227
11228                 xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, xpath_variable* value)
11229                 {
11230                         void* memory = alloc_node();
11231                         return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0;
11232                 }
11233
11234                 xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, xpath_ast_node* left = 0, xpath_ast_node* right = 0)
11235                 {
11236                         void* memory = alloc_node();
11237                         return memory ? new (memory) xpath_ast_node(type, rettype, left, right) : 0;
11238                 }
11239
11240                 xpath_ast_node* alloc_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents)
11241                 {
11242                         void* memory = alloc_node();
11243                         return memory ? new (memory) xpath_ast_node(type, left, axis, test, contents) : 0;
11244                 }
11245
11246                 xpath_ast_node* alloc_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test)
11247                 {
11248                         void* memory = alloc_node();
11249                         return memory ? new (memory) xpath_ast_node(type, left, right, test) : 0;
11250                 }
11251
11252                 const char_t* alloc_string(const xpath_lexer_string& value)
11253                 {
11254                         if (!value.begin)
11255                                 return PUGIXML_TEXT("");
11256
11257                         size_t length = static_cast<size_t>(value.end - value.begin);
11258
11259                         char_t* c = static_cast<char_t*>(_alloc->allocate((length + 1) * sizeof(char_t)));
11260                         if (!c) return 0;
11261
11262                         memcpy(c, value.begin, length * sizeof(char_t));
11263                         c[length] = 0;
11264
11265                         return c;
11266                 }
11267
11268                 xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2])
11269                 {
11270                         switch (name.begin[0])
11271                         {
11272                         case 'b':
11273                                 if (name == PUGIXML_TEXT("boolean") && argc == 1)
11274                                         return alloc_node(ast_func_boolean, xpath_type_boolean, args[0]);
11275
11276                                 break;
11277
11278                         case 'c':
11279                                 if (name == PUGIXML_TEXT("count") && argc == 1)
11280                                 {
11281                                         if (args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set");
11282                                         return alloc_node(ast_func_count, xpath_type_number, args[0]);
11283                                 }
11284                                 else if (name == PUGIXML_TEXT("contains") && argc == 2)
11285                                         return alloc_node(ast_func_contains, xpath_type_boolean, args[0], args[1]);
11286                                 else if (name == PUGIXML_TEXT("concat") && argc >= 2)
11287                                         return alloc_node(ast_func_concat, xpath_type_string, args[0], args[1]);
11288                                 else if (name == PUGIXML_TEXT("ceiling") && argc == 1)
11289                                         return alloc_node(ast_func_ceiling, xpath_type_number, args[0]);
11290
11291                                 break;
11292
11293                         case 'f':
11294                                 if (name == PUGIXML_TEXT("false") && argc == 0)
11295                                         return alloc_node(ast_func_false, xpath_type_boolean);
11296                                 else if (name == PUGIXML_TEXT("floor") && argc == 1)
11297                                         return alloc_node(ast_func_floor, xpath_type_number, args[0]);
11298
11299                                 break;
11300
11301                         case 'i':
11302                                 if (name == PUGIXML_TEXT("id") && argc == 1)
11303                                         return alloc_node(ast_func_id, xpath_type_node_set, args[0]);
11304
11305                                 break;
11306
11307                         case 'l':
11308                                 if (name == PUGIXML_TEXT("last") && argc == 0)
11309                                         return alloc_node(ast_func_last, xpath_type_number);
11310                                 else if (name == PUGIXML_TEXT("lang") && argc == 1)
11311                                         return alloc_node(ast_func_lang, xpath_type_boolean, args[0]);
11312                                 else if (name == PUGIXML_TEXT("local-name") && argc <= 1)
11313                                 {
11314                                         if (argc == 1 && args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set");
11315                                         return alloc_node(argc == 0 ? ast_func_local_name_0 : ast_func_local_name_1, xpath_type_string, args[0]);
11316                                 }
11317
11318                                 break;
11319
11320                         case 'n':
11321                                 if (name == PUGIXML_TEXT("name") && argc <= 1)
11322                                 {
11323                                         if (argc == 1 && args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set");
11324                                         return alloc_node(argc == 0 ? ast_func_name_0 : ast_func_name_1, xpath_type_string, args[0]);
11325                                 }
11326                                 else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1)
11327                                 {
11328                                         if (argc == 1 && args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set");
11329                                         return alloc_node(argc == 0 ? ast_func_namespace_uri_0 : ast_func_namespace_uri_1, xpath_type_string, args[0]);
11330                                 }
11331                                 else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1)
11332                                         return alloc_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]);
11333                                 else if (name == PUGIXML_TEXT("not") && argc == 1)
11334                                         return alloc_node(ast_func_not, xpath_type_boolean, args[0]);
11335                                 else if (name == PUGIXML_TEXT("number") && argc <= 1)
11336                                         return alloc_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]);
11337
11338                                 break;
11339
11340                         case 'p':
11341                                 if (name == PUGIXML_TEXT("position") && argc == 0)
11342                                         return alloc_node(ast_func_position, xpath_type_number);
11343
11344                                 break;
11345
11346                         case 'r':
11347                                 if (name == PUGIXML_TEXT("round") && argc == 1)
11348                                         return alloc_node(ast_func_round, xpath_type_number, args[0]);
11349
11350                                 break;
11351
11352                         case 's':
11353                                 if (name == PUGIXML_TEXT("string") && argc <= 1)
11354                                         return alloc_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]);
11355                                 else if (name == PUGIXML_TEXT("string-length") && argc <= 1)
11356                                         return alloc_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]);
11357                                 else if (name == PUGIXML_TEXT("starts-with") && argc == 2)
11358                                         return alloc_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]);
11359                                 else if (name == PUGIXML_TEXT("substring-before") && argc == 2)
11360                                         return alloc_node(ast_func_substring_before, xpath_type_string, args[0], args[1]);
11361                                 else if (name == PUGIXML_TEXT("substring-after") && argc == 2)
11362                                         return alloc_node(ast_func_substring_after, xpath_type_string, args[0], args[1]);
11363                                 else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3))
11364                                         return alloc_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]);
11365                                 else if (name == PUGIXML_TEXT("sum") && argc == 1)
11366                                 {
11367                                         if (args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set");
11368                                         return alloc_node(ast_func_sum, xpath_type_number, args[0]);
11369                                 }
11370
11371                                 break;
11372
11373                         case 't':
11374                                 if (name == PUGIXML_TEXT("translate") && argc == 3)
11375                                         return alloc_node(ast_func_translate, xpath_type_string, args[0], args[1]);
11376                                 else if (name == PUGIXML_TEXT("true") && argc == 0)
11377                                         return alloc_node(ast_func_true, xpath_type_boolean);
11378
11379                                 break;
11380
11381                         default:
11382                                 break;
11383                         }
11384
11385                         return error("Unrecognized function or wrong parameter count");
11386                 }
11387
11388                 axis_t parse_axis_name(const xpath_lexer_string& name, bool& specified)
11389                 {
11390                         specified = true;
11391
11392                         switch (name.begin[0])
11393                         {
11394                         case 'a':
11395                                 if (name == PUGIXML_TEXT("ancestor"))
11396                                         return axis_ancestor;
11397                                 else if (name == PUGIXML_TEXT("ancestor-or-self"))
11398                                         return axis_ancestor_or_self;
11399                                 else if (name == PUGIXML_TEXT("attribute"))
11400                                         return axis_attribute;
11401
11402                                 break;
11403
11404                         case 'c':
11405                                 if (name == PUGIXML_TEXT("child"))
11406                                         return axis_child;
11407
11408                                 break;
11409
11410                         case 'd':
11411                                 if (name == PUGIXML_TEXT("descendant"))
11412                                         return axis_descendant;
11413                                 else if (name == PUGIXML_TEXT("descendant-or-self"))
11414                                         return axis_descendant_or_self;
11415
11416                                 break;
11417
11418                         case 'f':
11419                                 if (name == PUGIXML_TEXT("following"))
11420                                         return axis_following;
11421                                 else if (name == PUGIXML_TEXT("following-sibling"))
11422                                         return axis_following_sibling;
11423
11424                                 break;
11425
11426                         case 'n':
11427                                 if (name == PUGIXML_TEXT("namespace"))
11428                                         return axis_namespace;
11429
11430                                 break;
11431
11432                         case 'p':
11433                                 if (name == PUGIXML_TEXT("parent"))
11434                                         return axis_parent;
11435                                 else if (name == PUGIXML_TEXT("preceding"))
11436                                         return axis_preceding;
11437                                 else if (name == PUGIXML_TEXT("preceding-sibling"))
11438                                         return axis_preceding_sibling;
11439
11440                                 break;
11441
11442                         case 's':
11443                                 if (name == PUGIXML_TEXT("self"))
11444                                         return axis_self;
11445
11446                                 break;
11447
11448                         default:
11449                                 break;
11450                         }
11451
11452                         specified = false;
11453                         return axis_child;
11454                 }
11455
11456                 nodetest_t parse_node_test_type(const xpath_lexer_string& name)
11457                 {
11458                         switch (name.begin[0])
11459                         {
11460                         case 'c':
11461                                 if (name == PUGIXML_TEXT("comment"))
11462                                         return nodetest_type_comment;
11463
11464                                 break;
11465
11466                         case 'n':
11467                                 if (name == PUGIXML_TEXT("node"))
11468                                         return nodetest_type_node;
11469
11470                                 break;
11471
11472                         case 'p':
11473                                 if (name == PUGIXML_TEXT("processing-instruction"))
11474                                         return nodetest_type_pi;
11475
11476                                 break;
11477
11478                         case 't':
11479                                 if (name == PUGIXML_TEXT("text"))
11480                                         return nodetest_type_text;
11481
11482                                 break;
11483
11484                         default:
11485                                 break;
11486                         }
11487
11488                         return nodetest_none;
11489                 }
11490
11491                 // PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall
11492                 xpath_ast_node* parse_primary_expression()
11493                 {
11494                         switch (_lexer.current())
11495                         {
11496                         case lex_var_ref:
11497                         {
11498                                 xpath_lexer_string name = _lexer.contents();
11499
11500                                 if (!_variables)
11501                                         return error("Unknown variable: variable set is not provided");
11502
11503                                 xpath_variable* var = 0;
11504                                 if (!get_variable_scratch(_scratch, _variables, name.begin, name.end, &var))
11505                                         return error_oom();
11506
11507                                 if (!var)
11508                                         return error("Unknown variable: variable set does not contain the given name");
11509
11510                                 _lexer.next();
11511
11512                                 return alloc_node(ast_variable, var->type(), var);
11513                         }
11514
11515                         case lex_open_brace:
11516                         {
11517                                 _lexer.next();
11518
11519                                 xpath_ast_node* n = parse_expression();
11520                                 if (!n) return 0;
11521
11522                                 if (_lexer.current() != lex_close_brace)
11523                                         return error("Expected ')' to match an opening '('");
11524
11525                                 _lexer.next();
11526
11527                                 return n;
11528                         }
11529
11530                         case lex_quoted_string:
11531                         {
11532                                 const char_t* value = alloc_string(_lexer.contents());
11533                                 if (!value) return 0;
11534
11535                                 _lexer.next();
11536
11537                                 return alloc_node(ast_string_constant, xpath_type_string, value);
11538                         }
11539
11540                         case lex_number:
11541                         {
11542                                 double value = 0;
11543
11544                                 if (!convert_string_to_number_scratch(_scratch, _lexer.contents().begin, _lexer.contents().end, &value))
11545                                         return error_oom();
11546
11547                                 _lexer.next();
11548
11549                                 return alloc_node(ast_number_constant, xpath_type_number, value);
11550                         }
11551
11552                         case lex_string:
11553                         {
11554                                 xpath_ast_node* args[2] = {0};
11555                                 size_t argc = 0;
11556
11557                                 xpath_lexer_string function = _lexer.contents();
11558                                 _lexer.next();
11559
11560                                 xpath_ast_node* last_arg = 0;
11561
11562                                 if (_lexer.current() != lex_open_brace)
11563                                         return error("Unrecognized function call");
11564                                 _lexer.next();
11565
11566                                 size_t old_depth = _depth;
11567
11568                                 while (_lexer.current() != lex_close_brace)
11569                                 {
11570                                         if (argc > 0)
11571                                         {
11572                                                 if (_lexer.current() != lex_comma)
11573                                                         return error("No comma between function arguments");
11574                                                 _lexer.next();
11575                                         }
11576
11577                                         if (++_depth > xpath_ast_depth_limit)
11578                                                 return error_rec();
11579
11580                                         xpath_ast_node* n = parse_expression();
11581                                         if (!n) return 0;
11582
11583                                         if (argc < 2) args[argc] = n;
11584                                         else last_arg->set_next(n);
11585
11586                                         argc++;
11587                                         last_arg = n;
11588                                 }
11589
11590                                 _lexer.next();
11591
11592                                 _depth = old_depth;
11593
11594                                 return parse_function(function, argc, args);
11595                         }
11596
11597                         default:
11598                                 return error("Unrecognizable primary expression");
11599                         }
11600                 }
11601
11602                 // FilterExpr ::= PrimaryExpr | FilterExpr Predicate
11603                 // Predicate ::= '[' PredicateExpr ']'
11604                 // PredicateExpr ::= Expr
11605                 xpath_ast_node* parse_filter_expression()
11606                 {
11607                         xpath_ast_node* n = parse_primary_expression();
11608                         if (!n) return 0;
11609
11610                         size_t old_depth = _depth;
11611
11612                         while (_lexer.current() == lex_open_square_brace)
11613                         {
11614                                 _lexer.next();
11615
11616                                 if (++_depth > xpath_ast_depth_limit)
11617                                         return error_rec();
11618
11619                                 if (n->rettype() != xpath_type_node_set)
11620                                         return error("Predicate has to be applied to node set");
11621
11622                                 xpath_ast_node* expr = parse_expression();
11623                                 if (!expr) return 0;
11624
11625                                 n = alloc_node(ast_filter, n, expr, predicate_default);
11626                                 if (!n) return 0;
11627
11628                                 if (_lexer.current() != lex_close_square_brace)
11629                                         return error("Expected ']' to match an opening '['");
11630
11631                                 _lexer.next();
11632                         }
11633
11634                         _depth = old_depth;
11635
11636                         return n;
11637                 }
11638
11639                 // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep
11640                 // AxisSpecifier ::= AxisName '::' | '@'?
11641                 // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')'
11642                 // NameTest ::= '*' | NCName ':' '*' | QName
11643                 // AbbreviatedStep ::= '.' | '..'
11644                 xpath_ast_node* parse_step(xpath_ast_node* set)
11645                 {
11646                         if (set && set->rettype() != xpath_type_node_set)
11647                                 return error("Step has to be applied to node set");
11648
11649                         bool axis_specified = false;
11650                         axis_t axis = axis_child; // implied child axis
11651
11652                         if (_lexer.current() == lex_axis_attribute)
11653                         {
11654                                 axis = axis_attribute;
11655                                 axis_specified = true;
11656
11657                                 _lexer.next();
11658                         }
11659                         else if (_lexer.current() == lex_dot)
11660                         {
11661                                 _lexer.next();
11662
11663                                 if (_lexer.current() == lex_open_square_brace)
11664                                         return error("Predicates are not allowed after an abbreviated step");
11665
11666                                 return alloc_node(ast_step, set, axis_self, nodetest_type_node, 0);
11667                         }
11668                         else if (_lexer.current() == lex_double_dot)
11669                         {
11670                                 _lexer.next();
11671
11672                                 if (_lexer.current() == lex_open_square_brace)
11673                                         return error("Predicates are not allowed after an abbreviated step");
11674
11675                                 return alloc_node(ast_step, set, axis_parent, nodetest_type_node, 0);
11676                         }
11677
11678                         nodetest_t nt_type = nodetest_none;
11679                         xpath_lexer_string nt_name;
11680
11681                         if (_lexer.current() == lex_string)
11682                         {
11683                                 // node name test
11684                                 nt_name = _lexer.contents();
11685                                 _lexer.next();
11686
11687                                 // was it an axis name?
11688                                 if (_lexer.current() == lex_double_colon)
11689                                 {
11690                                         // parse axis name
11691                                         if (axis_specified)
11692                                                 return error("Two axis specifiers in one step");
11693
11694                                         axis = parse_axis_name(nt_name, axis_specified);
11695
11696                                         if (!axis_specified)
11697                                                 return error("Unknown axis");
11698
11699                                         // read actual node test
11700                                         _lexer.next();
11701
11702                                         if (_lexer.current() == lex_multiply)
11703                                         {
11704                                                 nt_type = nodetest_all;
11705                                                 nt_name = xpath_lexer_string();
11706                                                 _lexer.next();
11707                                         }
11708                                         else if (_lexer.current() == lex_string)
11709                                         {
11710                                                 nt_name = _lexer.contents();
11711                                                 _lexer.next();
11712                                         }
11713                                         else
11714                                         {
11715                                                 return error("Unrecognized node test");
11716                                         }
11717                                 }
11718
11719                                 if (nt_type == nodetest_none)
11720                                 {
11721                                         // node type test or processing-instruction
11722                                         if (_lexer.current() == lex_open_brace)
11723                                         {
11724                                                 _lexer.next();
11725
11726                                                 if (_lexer.current() == lex_close_brace)
11727                                                 {
11728                                                         _lexer.next();
11729
11730                                                         nt_type = parse_node_test_type(nt_name);
11731
11732                                                         if (nt_type == nodetest_none)
11733                                                                 return error("Unrecognized node type");
11734
11735                                                         nt_name = xpath_lexer_string();
11736                                                 }
11737                                                 else if (nt_name == PUGIXML_TEXT("processing-instruction"))
11738                                                 {
11739                                                         if (_lexer.current() != lex_quoted_string)
11740                                                                 return error("Only literals are allowed as arguments to processing-instruction()");
11741
11742                                                         nt_type = nodetest_pi;
11743                                                         nt_name = _lexer.contents();
11744                                                         _lexer.next();
11745
11746                                                         if (_lexer.current() != lex_close_brace)
11747                                                                 return error("Unmatched brace near processing-instruction()");
11748                                                         _lexer.next();
11749                                                 }
11750                                                 else
11751                                                 {
11752                                                         return error("Unmatched brace near node type test");
11753                                                 }
11754                                         }
11755                                         // QName or NCName:*
11756                                         else
11757                                         {
11758                                                 if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:*
11759                                                 {
11760                                                         nt_name.end--; // erase *
11761
11762                                                         nt_type = nodetest_all_in_namespace;
11763                                                 }
11764                                                 else
11765                                                 {
11766                                                         nt_type = nodetest_name;
11767                                                 }
11768                                         }
11769                                 }
11770                         }
11771                         else if (_lexer.current() == lex_multiply)
11772                         {
11773                                 nt_type = nodetest_all;
11774                                 _lexer.next();
11775                         }
11776                         else
11777                         {
11778                                 return error("Unrecognized node test");
11779                         }
11780
11781                         const char_t* nt_name_copy = alloc_string(nt_name);
11782                         if (!nt_name_copy) return 0;
11783
11784                         xpath_ast_node* n = alloc_node(ast_step, set, axis, nt_type, nt_name_copy);
11785                         if (!n) return 0;
11786
11787                         size_t old_depth = _depth;
11788
11789                         xpath_ast_node* last = 0;
11790
11791                         while (_lexer.current() == lex_open_square_brace)
11792                         {
11793                                 _lexer.next();
11794
11795                                 if (++_depth > xpath_ast_depth_limit)
11796                                         return error_rec();
11797
11798                                 xpath_ast_node* expr = parse_expression();
11799                                 if (!expr) return 0;
11800
11801                                 xpath_ast_node* pred = alloc_node(ast_predicate, 0, expr, predicate_default);
11802                                 if (!pred) return 0;
11803
11804                                 if (_lexer.current() != lex_close_square_brace)
11805                                         return error("Expected ']' to match an opening '['");
11806                                 _lexer.next();
11807
11808                                 if (last) last->set_next(pred);
11809                                 else n->set_right(pred);
11810
11811                                 last = pred;
11812                         }
11813
11814                         _depth = old_depth;
11815
11816                         return n;
11817                 }
11818
11819                 // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step
11820                 xpath_ast_node* parse_relative_location_path(xpath_ast_node* set)
11821                 {
11822                         xpath_ast_node* n = parse_step(set);
11823                         if (!n) return 0;
11824
11825                         size_t old_depth = _depth;
11826
11827                         while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash)
11828                         {
11829                                 lexeme_t l = _lexer.current();
11830                                 _lexer.next();
11831
11832                                 if (l == lex_double_slash)
11833                                 {
11834                                         n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
11835                                         if (!n) return 0;
11836
11837                                         ++_depth;
11838                                 }
11839
11840                                 if (++_depth > xpath_ast_depth_limit)
11841                                         return error_rec();
11842
11843                                 n = parse_step(n);
11844                                 if (!n) return 0;
11845                         }
11846
11847                         _depth = old_depth;
11848
11849                         return n;
11850                 }
11851
11852                 // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath
11853                 // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath
11854                 xpath_ast_node* parse_location_path()
11855                 {
11856                         if (_lexer.current() == lex_slash)
11857                         {
11858                                 _lexer.next();
11859
11860                                 xpath_ast_node* n = alloc_node(ast_step_root, xpath_type_node_set);
11861                                 if (!n) return 0;
11862
11863                                 // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path
11864                                 lexeme_t l = _lexer.current();
11865
11866                                 if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply)
11867                                         return parse_relative_location_path(n);
11868                                 else
11869                                         return n;
11870                         }
11871                         else if (_lexer.current() == lex_double_slash)
11872                         {
11873                                 _lexer.next();
11874
11875                                 xpath_ast_node* n = alloc_node(ast_step_root, xpath_type_node_set);
11876                                 if (!n) return 0;
11877
11878                                 n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
11879                                 if (!n) return 0;
11880
11881                                 return parse_relative_location_path(n);
11882                         }
11883
11884                         // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1
11885                         return parse_relative_location_path(0);
11886                 }
11887
11888                 // PathExpr ::= LocationPath
11889                 //                              | FilterExpr
11890                 //                              | FilterExpr '/' RelativeLocationPath
11891                 //                              | FilterExpr '//' RelativeLocationPath
11892                 // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr
11893                 // UnaryExpr ::= UnionExpr | '-' UnaryExpr
11894                 xpath_ast_node* parse_path_or_unary_expression()
11895                 {
11896                         // Clarification.
11897                         // PathExpr begins with either LocationPath or FilterExpr.
11898                         // FilterExpr begins with PrimaryExpr
11899                         // PrimaryExpr begins with '$' in case of it being a variable reference,
11900                         // '(' in case of it being an expression, string literal, number constant or
11901                         // function call.
11902                         if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace ||
11903                                 _lexer.current() == lex_quoted_string || _lexer.current() == lex_number ||
11904                                 _lexer.current() == lex_string)
11905                         {
11906                                 if (_lexer.current() == lex_string)
11907                                 {
11908                                         // This is either a function call, or not - if not, we shall proceed with location path
11909                                         const char_t* state = _lexer.state();
11910
11911                                         while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state;
11912
11913                                         if (*state != '(')
11914                                                 return parse_location_path();
11915
11916                                         // This looks like a function call; however this still can be a node-test. Check it.
11917                                         if (parse_node_test_type(_lexer.contents()) != nodetest_none)
11918                                                 return parse_location_path();
11919                                 }
11920
11921                                 xpath_ast_node* n = parse_filter_expression();
11922                                 if (!n) return 0;
11923
11924                                 if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash)
11925                                 {
11926                                         lexeme_t l = _lexer.current();
11927                                         _lexer.next();
11928
11929                                         if (l == lex_double_slash)
11930                                         {
11931                                                 if (n->rettype() != xpath_type_node_set)
11932                                                         return error("Step has to be applied to node set");
11933
11934                                                 n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
11935                                                 if (!n) return 0;
11936                                         }
11937
11938                                         // select from location path
11939                                         return parse_relative_location_path(n);
11940                                 }
11941
11942                                 return n;
11943                         }
11944                         else if (_lexer.current() == lex_minus)
11945                         {
11946                                 _lexer.next();
11947
11948                                 // precedence 7+ - only parses union expressions
11949                                 xpath_ast_node* n = parse_expression(7);
11950                                 if (!n) return 0;
11951
11952                                 return alloc_node(ast_op_negate, xpath_type_number, n);
11953                         }
11954                         else
11955                         {
11956                                 return parse_location_path();
11957                         }
11958                 }
11959
11960                 struct binary_op_t
11961                 {
11962                         ast_type_t asttype;
11963                         xpath_value_type rettype;
11964                         int precedence;
11965
11966                         binary_op_t(): asttype(ast_unknown), rettype(xpath_type_none), precedence(0)
11967                         {
11968                         }
11969
11970                         binary_op_t(ast_type_t asttype_, xpath_value_type rettype_, int precedence_): asttype(asttype_), rettype(rettype_), precedence(precedence_)
11971                         {
11972                         }
11973
11974                         static binary_op_t parse(xpath_lexer& lexer)
11975                         {
11976                                 switch (lexer.current())
11977                                 {
11978                                 case lex_string:
11979                                         if (lexer.contents() == PUGIXML_TEXT("or"))
11980                                                 return binary_op_t(ast_op_or, xpath_type_boolean, 1);
11981                                         else if (lexer.contents() == PUGIXML_TEXT("and"))
11982                                                 return binary_op_t(ast_op_and, xpath_type_boolean, 2);
11983                                         else if (lexer.contents() == PUGIXML_TEXT("div"))
11984                                                 return binary_op_t(ast_op_divide, xpath_type_number, 6);
11985                                         else if (lexer.contents() == PUGIXML_TEXT("mod"))
11986                                                 return binary_op_t(ast_op_mod, xpath_type_number, 6);
11987                                         else
11988                                                 return binary_op_t();
11989
11990                                 case lex_equal:
11991                                         return binary_op_t(ast_op_equal, xpath_type_boolean, 3);
11992
11993                                 case lex_not_equal:
11994                                         return binary_op_t(ast_op_not_equal, xpath_type_boolean, 3);
11995
11996                                 case lex_less:
11997                                         return binary_op_t(ast_op_less, xpath_type_boolean, 4);
11998
11999                                 case lex_greater:
12000                                         return binary_op_t(ast_op_greater, xpath_type_boolean, 4);
12001
12002                                 case lex_less_or_equal:
12003                                         return binary_op_t(ast_op_less_or_equal, xpath_type_boolean, 4);
12004
12005                                 case lex_greater_or_equal:
12006                                         return binary_op_t(ast_op_greater_or_equal, xpath_type_boolean, 4);
12007
12008                                 case lex_plus:
12009                                         return binary_op_t(ast_op_add, xpath_type_number, 5);
12010
12011                                 case lex_minus:
12012                                         return binary_op_t(ast_op_subtract, xpath_type_number, 5);
12013
12014                                 case lex_multiply:
12015                                         return binary_op_t(ast_op_multiply, xpath_type_number, 6);
12016
12017                                 case lex_union:
12018                                         return binary_op_t(ast_op_union, xpath_type_node_set, 7);
12019
12020                                 default:
12021                                         return binary_op_t();
12022                                 }
12023                         }
12024                 };
12025
12026                 xpath_ast_node* parse_expression_rec(xpath_ast_node* lhs, int limit)
12027                 {
12028                         binary_op_t op = binary_op_t::parse(_lexer);
12029
12030                         while (op.asttype != ast_unknown && op.precedence >= limit)
12031                         {
12032                                 _lexer.next();
12033
12034                                 if (++_depth > xpath_ast_depth_limit)
12035                                         return error_rec();
12036
12037                                 xpath_ast_node* rhs = parse_path_or_unary_expression();
12038                                 if (!rhs) return 0;
12039
12040                                 binary_op_t nextop = binary_op_t::parse(_lexer);
12041
12042                                 while (nextop.asttype != ast_unknown && nextop.precedence > op.precedence)
12043                                 {
12044                                         rhs = parse_expression_rec(rhs, nextop.precedence);
12045                                         if (!rhs) return 0;
12046
12047                                         nextop = binary_op_t::parse(_lexer);
12048                                 }
12049
12050                                 if (op.asttype == ast_op_union && (lhs->rettype() != xpath_type_node_set || rhs->rettype() != xpath_type_node_set))
12051                                         return error("Union operator has to be applied to node sets");
12052
12053                                 lhs = alloc_node(op.asttype, op.rettype, lhs, rhs);
12054                                 if (!lhs) return 0;
12055
12056                                 op = binary_op_t::parse(_lexer);
12057                         }
12058
12059                         return lhs;
12060                 }
12061
12062                 // Expr ::= OrExpr
12063                 // OrExpr ::= AndExpr | OrExpr 'or' AndExpr
12064                 // AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr
12065                 // EqualityExpr ::= RelationalExpr
12066                 //                                      | EqualityExpr '=' RelationalExpr
12067                 //                                      | EqualityExpr '!=' RelationalExpr
12068                 // RelationalExpr ::= AdditiveExpr
12069                 //                                        | RelationalExpr '<' AdditiveExpr
12070                 //                                        | RelationalExpr '>' AdditiveExpr
12071                 //                                        | RelationalExpr '<=' AdditiveExpr
12072                 //                                        | RelationalExpr '>=' AdditiveExpr
12073                 // AdditiveExpr ::= MultiplicativeExpr
12074                 //                                      | AdditiveExpr '+' MultiplicativeExpr
12075                 //                                      | AdditiveExpr '-' MultiplicativeExpr
12076                 // MultiplicativeExpr ::= UnaryExpr
12077                 //                                                | MultiplicativeExpr '*' UnaryExpr
12078                 //                                                | MultiplicativeExpr 'div' UnaryExpr
12079                 //                                                | MultiplicativeExpr 'mod' UnaryExpr
12080                 xpath_ast_node* parse_expression(int limit = 0)
12081                 {
12082                         size_t old_depth = _depth;
12083
12084                         if (++_depth > xpath_ast_depth_limit)
12085                                 return error_rec();
12086
12087                         xpath_ast_node* n = parse_path_or_unary_expression();
12088                         if (!n) return 0;
12089
12090                         n = parse_expression_rec(n, limit);
12091
12092                         _depth = old_depth;
12093
12094                         return n;
12095                 }
12096
12097                 xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result), _depth(0)
12098                 {
12099                 }
12100
12101                 xpath_ast_node* parse()
12102                 {
12103                         xpath_ast_node* n = parse_expression();
12104                         if (!n) return 0;
12105
12106                         assert(_depth == 0);
12107
12108                         // check if there are unparsed tokens left
12109                         if (_lexer.current() != lex_eof)
12110                                 return error("Incorrect query");
12111
12112                         return n;
12113                 }
12114
12115                 static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result)
12116                 {
12117                         xpath_parser parser(query, variables, alloc, result);
12118
12119                         return parser.parse();
12120                 }
12121         };
12122
12123         struct xpath_query_impl
12124         {
12125                 static xpath_query_impl* create()
12126                 {
12127                         void* memory = xml_memory::allocate(sizeof(xpath_query_impl));
12128                         if (!memory) return 0;
12129
12130                         return new (memory) xpath_query_impl();
12131                 }
12132
12133                 static void destroy(xpath_query_impl* impl)
12134                 {
12135                         // free all allocated pages
12136                         impl->alloc.release();
12137
12138                         // free allocator memory (with the first page)
12139                         xml_memory::deallocate(impl);
12140                 }
12141
12142                 xpath_query_impl(): root(0), alloc(&block, &oom), oom(false)
12143                 {
12144                         block.next = 0;
12145                         block.capacity = sizeof(block.data);
12146                 }
12147
12148                 xpath_ast_node* root;
12149                 xpath_allocator alloc;
12150                 xpath_memory_block block;
12151                 bool oom;
12152         };
12153
12154         PUGI__FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl)
12155         {
12156                 if (!impl) return 0;
12157
12158                 if (impl->root->rettype() != xpath_type_node_set)
12159                 {
12160                 #ifdef PUGIXML_NO_EXCEPTIONS
12161                         return 0;
12162                 #else
12163                         xpath_parse_result res;
12164                         res.error = "Expression does not evaluate to node set";
12165
12166                         throw xpath_exception(res);
12167                 #endif
12168                 }
12169
12170                 return impl->root;
12171         }
12172 PUGI__NS_END
12173
12174 namespace pugi
12175 {
12176 #ifndef PUGIXML_NO_EXCEPTIONS
12177         PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_)
12178         {
12179                 assert(_result.error);
12180         }
12181
12182         PUGI__FN const char* xpath_exception::what() const throw()
12183         {
12184                 return _result.error;
12185         }
12186
12187         PUGI__FN const xpath_parse_result& xpath_exception::result() const
12188         {
12189                 return _result;
12190         }
12191 #endif
12192
12193         PUGI__FN xpath_node::xpath_node()
12194         {
12195         }
12196
12197         PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_)
12198         {
12199         }
12200
12201         PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_)
12202         {
12203         }
12204
12205         PUGI__FN xml_node xpath_node::node() const
12206         {
12207                 return _attribute ? xml_node() : _node;
12208         }
12209
12210         PUGI__FN xml_attribute xpath_node::attribute() const
12211         {
12212                 return _attribute;
12213         }
12214
12215         PUGI__FN xml_node xpath_node::parent() const
12216         {
12217                 return _attribute ? _node : _node.parent();
12218         }
12219
12220         PUGI__FN static void unspecified_bool_xpath_node(xpath_node***)
12221         {
12222         }
12223
12224         PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const
12225         {
12226                 return (_node || _attribute) ? unspecified_bool_xpath_node : 0;
12227         }
12228
12229         PUGI__FN bool xpath_node::operator!() const
12230         {
12231                 return !(_node || _attribute);
12232         }
12233
12234         PUGI__FN bool xpath_node::operator==(const xpath_node& n) const
12235         {
12236                 return _node == n._node && _attribute == n._attribute;
12237         }
12238
12239         PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const
12240         {
12241                 return _node != n._node || _attribute != n._attribute;
12242         }
12243
12244 #ifdef __BORLANDC__
12245         PUGI__FN bool operator&&(const xpath_node& lhs, bool rhs)
12246         {
12247                 return (bool)lhs && rhs;
12248         }
12249
12250         PUGI__FN bool operator||(const xpath_node& lhs, bool rhs)
12251         {
12252                 return (bool)lhs || rhs;
12253         }
12254 #endif
12255
12256         PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_)
12257         {
12258                 assert(begin_ <= end_);
12259
12260                 size_t size_ = static_cast<size_t>(end_ - begin_);
12261
12262                 // use internal buffer for 0 or 1 elements, heap buffer otherwise
12263                 xpath_node* storage = (size_ <= 1) ? _storage : static_cast<xpath_node*>(impl::xml_memory::allocate(size_ * sizeof(xpath_node)));
12264
12265                 if (!storage)
12266                 {
12267                 #ifdef PUGIXML_NO_EXCEPTIONS
12268                         return;
12269                 #else
12270                         throw std::bad_alloc();
12271                 #endif
12272                 }
12273
12274                 // deallocate old buffer
12275                 if (_begin != _storage)
12276                         impl::xml_memory::deallocate(_begin);
12277
12278                 // size check is necessary because for begin_ = end_ = nullptr, memcpy is UB
12279                 if (size_)
12280                         memcpy(storage, begin_, size_ * sizeof(xpath_node));
12281
12282                 _begin = storage;
12283                 _end = storage + size_;
12284                 _type = type_;
12285         }
12286
12287 #ifdef PUGIXML_HAS_MOVE
12288         PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) PUGIXML_NOEXCEPT
12289         {
12290                 _type = rhs._type;
12291                 _storage[0] = rhs._storage[0];
12292                 _begin = (rhs._begin == rhs._storage) ? _storage : rhs._begin;
12293                 _end = _begin + (rhs._end - rhs._begin);
12294
12295                 rhs._type = type_unsorted;
12296                 rhs._begin = rhs._storage;
12297                 rhs._end = rhs._storage;
12298         }
12299 #endif
12300
12301         PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(_storage), _end(_storage)
12302         {
12303         }
12304
12305         PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(_storage), _end(_storage)
12306         {
12307                 _assign(begin_, end_, type_);
12308         }
12309
12310         PUGI__FN xpath_node_set::~xpath_node_set()
12311         {
12312                 if (_begin != _storage)
12313                         impl::xml_memory::deallocate(_begin);
12314         }
12315
12316         PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(_storage), _end(_storage)
12317         {
12318                 _assign(ns._begin, ns._end, ns._type);
12319         }
12320
12321         PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns)
12322         {
12323                 if (this == &ns) return *this;
12324
12325                 _assign(ns._begin, ns._end, ns._type);
12326
12327                 return *this;
12328         }
12329
12330 #ifdef PUGIXML_HAS_MOVE
12331         PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT: _type(type_unsorted), _begin(_storage), _end(_storage)
12332         {
12333                 _move(rhs);
12334         }
12335
12336         PUGI__FN xpath_node_set& xpath_node_set::operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT
12337         {
12338                 if (this == &rhs) return *this;
12339
12340                 if (_begin != _storage)
12341                         impl::xml_memory::deallocate(_begin);
12342
12343                 _move(rhs);
12344
12345                 return *this;
12346         }
12347 #endif
12348
12349         PUGI__FN xpath_node_set::type_t xpath_node_set::type() const
12350         {
12351                 return _type;
12352         }
12353
12354         PUGI__FN size_t xpath_node_set::size() const
12355         {
12356                 return _end - _begin;
12357         }
12358
12359         PUGI__FN bool xpath_node_set::empty() const
12360         {
12361                 return _begin == _end;
12362         }
12363
12364         PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const
12365         {
12366                 assert(index < size());
12367                 return _begin[index];
12368         }
12369
12370         PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const
12371         {
12372                 return _begin;
12373         }
12374
12375         PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const
12376         {
12377                 return _end;
12378         }
12379
12380         PUGI__FN void xpath_node_set::sort(bool reverse)
12381         {
12382                 _type = impl::xpath_sort(_begin, _end, _type, reverse);
12383         }
12384
12385         PUGI__FN xpath_node xpath_node_set::first() const
12386         {
12387                 return impl::xpath_first(_begin, _end, _type);
12388         }
12389
12390         PUGI__FN xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0)
12391         {
12392         }
12393
12394         PUGI__FN xpath_parse_result::operator bool() const
12395         {
12396                 return error == 0;
12397         }
12398
12399         PUGI__FN const char* xpath_parse_result::description() const
12400         {
12401                 return error ? error : "No error";
12402         }
12403
12404         PUGI__FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0)
12405         {
12406         }
12407
12408         PUGI__FN const char_t* xpath_variable::name() const
12409         {
12410                 switch (_type)
12411                 {
12412                 case xpath_type_node_set:
12413                         return static_cast<const impl::xpath_variable_node_set*>(this)->name;
12414
12415                 case xpath_type_number:
12416                         return static_cast<const impl::xpath_variable_number*>(this)->name;
12417
12418                 case xpath_type_string:
12419                         return static_cast<const impl::xpath_variable_string*>(this)->name;
12420
12421                 case xpath_type_boolean:
12422                         return static_cast<const impl::xpath_variable_boolean*>(this)->name;
12423
12424                 default:
12425                         assert(false && "Invalid variable type"); // unreachable
12426                         return 0;
12427                 }
12428         }
12429
12430         PUGI__FN xpath_value_type xpath_variable::type() const
12431         {
12432                 return _type;
12433         }
12434
12435         PUGI__FN bool xpath_variable::get_boolean() const
12436         {
12437                 return (_type == xpath_type_boolean) ? static_cast<const impl::xpath_variable_boolean*>(this)->value : false;
12438         }
12439
12440         PUGI__FN double xpath_variable::get_number() const
12441         {
12442                 return (_type == xpath_type_number) ? static_cast<const impl::xpath_variable_number*>(this)->value : impl::gen_nan();
12443         }
12444
12445         PUGI__FN const char_t* xpath_variable::get_string() const
12446         {
12447                 const char_t* value = (_type == xpath_type_string) ? static_cast<const impl::xpath_variable_string*>(this)->value : 0;
12448                 return value ? value : PUGIXML_TEXT("");
12449         }
12450
12451         PUGI__FN const xpath_node_set& xpath_variable::get_node_set() const
12452         {
12453                 return (_type == xpath_type_node_set) ? static_cast<const impl::xpath_variable_node_set*>(this)->value : impl::dummy_node_set;
12454         }
12455
12456         PUGI__FN bool xpath_variable::set(bool value)
12457         {
12458                 if (_type != xpath_type_boolean) return false;
12459
12460                 static_cast<impl::xpath_variable_boolean*>(this)->value = value;
12461                 return true;
12462         }
12463
12464         PUGI__FN bool xpath_variable::set(double value)
12465         {
12466                 if (_type != xpath_type_number) return false;
12467
12468                 static_cast<impl::xpath_variable_number*>(this)->value = value;
12469                 return true;
12470         }
12471
12472         PUGI__FN bool xpath_variable::set(const char_t* value)
12473         {
12474                 if (_type != xpath_type_string) return false;
12475
12476                 impl::xpath_variable_string* var = static_cast<impl::xpath_variable_string*>(this);
12477
12478                 // duplicate string
12479                 size_t size = (impl::strlength(value) + 1) * sizeof(char_t);
12480
12481                 char_t* copy = static_cast<char_t*>(impl::xml_memory::allocate(size));
12482                 if (!copy) return false;
12483
12484                 memcpy(copy, value, size);
12485
12486                 // replace old string
12487                 if (var->value) impl::xml_memory::deallocate(var->value);
12488                 var->value = copy;
12489
12490                 return true;
12491         }
12492
12493         PUGI__FN bool xpath_variable::set(const xpath_node_set& value)
12494         {
12495                 if (_type != xpath_type_node_set) return false;
12496
12497                 static_cast<impl::xpath_variable_node_set*>(this)->value = value;
12498                 return true;
12499         }
12500
12501         PUGI__FN xpath_variable_set::xpath_variable_set()
12502         {
12503                 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12504                         _data[i] = 0;
12505         }
12506
12507         PUGI__FN xpath_variable_set::~xpath_variable_set()
12508         {
12509                 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12510                         _destroy(_data[i]);
12511         }
12512
12513         PUGI__FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs)
12514         {
12515                 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12516                         _data[i] = 0;
12517
12518                 _assign(rhs);
12519         }
12520
12521         PUGI__FN xpath_variable_set& xpath_variable_set::operator=(const xpath_variable_set& rhs)
12522         {
12523                 if (this == &rhs) return *this;
12524
12525                 _assign(rhs);
12526
12527                 return *this;
12528         }
12529
12530 #ifdef PUGIXML_HAS_MOVE
12531         PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT
12532         {
12533                 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12534                 {
12535                         _data[i] = rhs._data[i];
12536                         rhs._data[i] = 0;
12537                 }
12538         }
12539
12540         PUGI__FN xpath_variable_set& xpath_variable_set::operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT
12541         {
12542                 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12543                 {
12544                         _destroy(_data[i]);
12545
12546                         _data[i] = rhs._data[i];
12547                         rhs._data[i] = 0;
12548                 }
12549
12550                 return *this;
12551         }
12552 #endif
12553
12554         PUGI__FN void xpath_variable_set::_assign(const xpath_variable_set& rhs)
12555         {
12556                 xpath_variable_set temp;
12557
12558                 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12559                         if (rhs._data[i] && !_clone(rhs._data[i], &temp._data[i]))
12560                                 return;
12561
12562                 _swap(temp);
12563         }
12564
12565         PUGI__FN void xpath_variable_set::_swap(xpath_variable_set& rhs)
12566         {
12567                 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12568                 {
12569                         xpath_variable* chain = _data[i];
12570
12571                         _data[i] = rhs._data[i];
12572                         rhs._data[i] = chain;
12573                 }
12574         }
12575
12576         PUGI__FN xpath_variable* xpath_variable_set::_find(const char_t* name) const
12577         {
12578                 const size_t hash_size = sizeof(_data) / sizeof(_data[0]);
12579                 size_t hash = impl::hash_string(name) % hash_size;
12580
12581                 // look for existing variable
12582                 for (xpath_variable* var = _data[hash]; var; var = var->_next)
12583                         if (impl::strequal(var->name(), name))
12584                                 return var;
12585
12586                 return 0;
12587         }
12588
12589         PUGI__FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result)
12590         {
12591                 xpath_variable* last = 0;
12592
12593                 while (var)
12594                 {
12595                         // allocate storage for new variable
12596                         xpath_variable* nvar = impl::new_xpath_variable(var->_type, var->name());
12597                         if (!nvar) return false;
12598
12599                         // link the variable to the result immediately to handle failures gracefully
12600                         if (last)
12601                                 last->_next = nvar;
12602                         else
12603                                 *out_result = nvar;
12604
12605                         last = nvar;
12606
12607                         // copy the value; this can fail due to out-of-memory conditions
12608                         if (!impl::copy_xpath_variable(nvar, var)) return false;
12609
12610                         var = var->_next;
12611                 }
12612
12613                 return true;
12614         }
12615
12616         PUGI__FN void xpath_variable_set::_destroy(xpath_variable* var)
12617         {
12618                 while (var)
12619                 {
12620                         xpath_variable* next = var->_next;
12621
12622                         impl::delete_xpath_variable(var->_type, var);
12623
12624                         var = next;
12625                 }
12626         }
12627
12628         PUGI__FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type)
12629         {
12630                 const size_t hash_size = sizeof(_data) / sizeof(_data[0]);
12631                 size_t hash = impl::hash_string(name) % hash_size;
12632
12633                 // look for existing variable
12634                 for (xpath_variable* var = _data[hash]; var; var = var->_next)
12635                         if (impl::strequal(var->name(), name))
12636                                 return var->type() == type ? var : 0;
12637
12638                 // add new variable
12639                 xpath_variable* result = impl::new_xpath_variable(type, name);
12640
12641                 if (result)
12642                 {
12643                         result->_next = _data[hash];
12644
12645                         _data[hash] = result;
12646                 }
12647
12648                 return result;
12649         }
12650
12651         PUGI__FN bool xpath_variable_set::set(const char_t* name, bool value)
12652         {
12653                 xpath_variable* var = add(name, xpath_type_boolean);
12654                 return var ? var->set(value) : false;
12655         }
12656
12657         PUGI__FN bool xpath_variable_set::set(const char_t* name, double value)
12658         {
12659                 xpath_variable* var = add(name, xpath_type_number);
12660                 return var ? var->set(value) : false;
12661         }
12662
12663         PUGI__FN bool xpath_variable_set::set(const char_t* name, const char_t* value)
12664         {
12665                 xpath_variable* var = add(name, xpath_type_string);
12666                 return var ? var->set(value) : false;
12667         }
12668
12669         PUGI__FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value)
12670         {
12671                 xpath_variable* var = add(name, xpath_type_node_set);
12672                 return var ? var->set(value) : false;
12673         }
12674
12675         PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name)
12676         {
12677                 return _find(name);
12678         }
12679
12680         PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const
12681         {
12682                 return _find(name);
12683         }
12684
12685         PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0)
12686         {
12687                 impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create();
12688
12689                 if (!qimpl)
12690                 {
12691                 #ifdef PUGIXML_NO_EXCEPTIONS
12692                         _result.error = "Out of memory";
12693                 #else
12694                         throw std::bad_alloc();
12695                 #endif
12696                 }
12697                 else
12698                 {
12699                         using impl::auto_deleter; // MSVC7 workaround
12700                         auto_deleter<impl::xpath_query_impl> impl(qimpl, impl::xpath_query_impl::destroy);
12701
12702                         qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &_result);
12703
12704                         if (qimpl->root)
12705                         {
12706                                 qimpl->root->optimize(&qimpl->alloc);
12707
12708                                 _impl = impl.release();
12709                                 _result.error = 0;
12710                         }
12711                         else
12712                         {
12713                         #ifdef PUGIXML_NO_EXCEPTIONS
12714                                 if (qimpl->oom) _result.error = "Out of memory";
12715                         #else
12716                                 if (qimpl->oom) throw std::bad_alloc();
12717                                 throw xpath_exception(_result);
12718                         #endif
12719                         }
12720                 }
12721         }
12722
12723         PUGI__FN xpath_query::xpath_query(): _impl(0)
12724         {
12725         }
12726
12727         PUGI__FN xpath_query::~xpath_query()
12728         {
12729                 if (_impl)
12730                         impl::xpath_query_impl::destroy(static_cast<impl::xpath_query_impl*>(_impl));
12731         }
12732
12733 #ifdef PUGIXML_HAS_MOVE
12734         PUGI__FN xpath_query::xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT
12735         {
12736                 _impl = rhs._impl;
12737                 _result = rhs._result;
12738                 rhs._impl = 0;
12739                 rhs._result = xpath_parse_result();
12740         }
12741
12742         PUGI__FN xpath_query& xpath_query::operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT
12743         {
12744                 if (this == &rhs) return *this;
12745
12746                 if (_impl)
12747                         impl::xpath_query_impl::destroy(static_cast<impl::xpath_query_impl*>(_impl));
12748
12749                 _impl = rhs._impl;
12750                 _result = rhs._result;
12751                 rhs._impl = 0;
12752                 rhs._result = xpath_parse_result();
12753
12754                 return *this;
12755         }
12756 #endif
12757
12758         PUGI__FN xpath_value_type xpath_query::return_type() const
12759         {
12760                 if (!_impl) return xpath_type_none;
12761
12762                 return static_cast<impl::xpath_query_impl*>(_impl)->root->rettype();
12763         }
12764
12765         PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const
12766         {
12767                 if (!_impl) return false;
12768
12769                 impl::xpath_context c(n, 1, 1);
12770                 impl::xpath_stack_data sd;
12771
12772                 bool r = static_cast<impl::xpath_query_impl*>(_impl)->root->eval_boolean(c, sd.stack);
12773
12774                 if (sd.oom)
12775                 {
12776                 #ifdef PUGIXML_NO_EXCEPTIONS
12777                         return false;
12778                 #else
12779                         throw std::bad_alloc();
12780                 #endif
12781                 }
12782
12783                 return r;
12784         }
12785
12786         PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const
12787         {
12788                 if (!_impl) return impl::gen_nan();
12789
12790                 impl::xpath_context c(n, 1, 1);
12791                 impl::xpath_stack_data sd;
12792
12793                 double r = static_cast<impl::xpath_query_impl*>(_impl)->root->eval_number(c, sd.stack);
12794
12795                 if (sd.oom)
12796                 {
12797                 #ifdef PUGIXML_NO_EXCEPTIONS
12798                         return impl::gen_nan();
12799                 #else
12800                         throw std::bad_alloc();
12801                 #endif
12802                 }
12803
12804                 return r;
12805         }
12806
12807 #ifndef PUGIXML_NO_STL
12808         PUGI__FN string_t xpath_query::evaluate_string(const xpath_node& n) const
12809         {
12810                 if (!_impl) return string_t();
12811
12812                 impl::xpath_context c(n, 1, 1);
12813                 impl::xpath_stack_data sd;
12814
12815                 impl::xpath_string r = static_cast<impl::xpath_query_impl*>(_impl)->root->eval_string(c, sd.stack);
12816
12817                 if (sd.oom)
12818                 {
12819                 #ifdef PUGIXML_NO_EXCEPTIONS
12820                         return string_t();
12821                 #else
12822                         throw std::bad_alloc();
12823                 #endif
12824                 }
12825
12826                 return string_t(r.c_str(), r.length());
12827         }
12828 #endif
12829
12830         PUGI__FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const
12831         {
12832                 impl::xpath_context c(n, 1, 1);
12833                 impl::xpath_stack_data sd;
12834
12835                 impl::xpath_string r = _impl ? static_cast<impl::xpath_query_impl*>(_impl)->root->eval_string(c, sd.stack) : impl::xpath_string();
12836
12837                 if (sd.oom)
12838                 {
12839                 #ifdef PUGIXML_NO_EXCEPTIONS
12840                         r = impl::xpath_string();
12841                 #else
12842                         throw std::bad_alloc();
12843                 #endif
12844                 }
12845
12846                 size_t full_size = r.length() + 1;
12847
12848                 if (capacity > 0)
12849                 {
12850                         size_t size = (full_size < capacity) ? full_size : capacity;
12851                         assert(size > 0);
12852
12853                         memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t));
12854                         buffer[size - 1] = 0;
12855                 }
12856
12857                 return full_size;
12858         }
12859
12860         PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const
12861         {
12862                 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast<impl::xpath_query_impl*>(_impl));
12863                 if (!root) return xpath_node_set();
12864
12865                 impl::xpath_context c(n, 1, 1);
12866                 impl::xpath_stack_data sd;
12867
12868                 impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_all);
12869
12870                 if (sd.oom)
12871                 {
12872                 #ifdef PUGIXML_NO_EXCEPTIONS
12873                         return xpath_node_set();
12874                 #else
12875                         throw std::bad_alloc();
12876                 #endif
12877                 }
12878
12879                 return xpath_node_set(r.begin(), r.end(), r.type());
12880         }
12881
12882         PUGI__FN xpath_node xpath_query::evaluate_node(const xpath_node& n) const
12883         {
12884                 impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast<impl::xpath_query_impl*>(_impl));
12885                 if (!root) return xpath_node();
12886
12887                 impl::xpath_context c(n, 1, 1);
12888                 impl::xpath_stack_data sd;
12889
12890                 impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_first);
12891
12892                 if (sd.oom)
12893                 {
12894                 #ifdef PUGIXML_NO_EXCEPTIONS
12895                         return xpath_node();
12896                 #else
12897                         throw std::bad_alloc();
12898                 #endif
12899                 }
12900
12901                 return r.first();
12902         }
12903
12904         PUGI__FN const xpath_parse_result& xpath_query::result() const
12905         {
12906                 return _result;
12907         }
12908
12909         PUGI__FN static void unspecified_bool_xpath_query(xpath_query***)
12910         {
12911         }
12912
12913         PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type() const
12914         {
12915                 return _impl ? unspecified_bool_xpath_query : 0;
12916         }
12917
12918         PUGI__FN bool xpath_query::operator!() const
12919         {
12920                 return !_impl;
12921         }
12922
12923         PUGI__FN xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables) const
12924         {
12925                 xpath_query q(query, variables);
12926                 return q.evaluate_node(*this);
12927         }
12928
12929         PUGI__FN xpath_node xml_node::select_node(const xpath_query& query) const
12930         {
12931                 return query.evaluate_node(*this);
12932         }
12933
12934         PUGI__FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const
12935         {
12936                 xpath_query q(query, variables);
12937                 return q.evaluate_node_set(*this);
12938         }
12939
12940         PUGI__FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const
12941         {
12942                 return query.evaluate_node_set(*this);
12943         }
12944
12945         PUGI__FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const
12946         {
12947                 xpath_query q(query, variables);
12948                 return q.evaluate_node(*this);
12949         }
12950
12951         PUGI__FN xpath_node xml_node::select_single_node(const xpath_query& query) const
12952         {
12953                 return query.evaluate_node(*this);
12954         }
12955 }
12956
12957 #endif
12958
12959 #ifdef __BORLANDC__
12960 #       pragma option pop
12961 #endif
12962
12963 // Intel C++ does not properly keep warning state for function templates,
12964 // so popping warning state at the end of translation unit leads to warnings in the middle.
12965 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
12966 #       pragma warning(pop)
12967 #endif
12968
12969 #if defined(_MSC_VER) && defined(__c2__)
12970 #       pragma clang diagnostic pop
12971 #endif
12972
12973 // Undefine all local macros (makes sure we're not leaking macros in header-only mode)
12974 #undef PUGI__NO_INLINE
12975 #undef PUGI__UNLIKELY
12976 #undef PUGI__STATIC_ASSERT
12977 #undef PUGI__DMC_VOLATILE
12978 #undef PUGI__UNSIGNED_OVERFLOW
12979 #undef PUGI__MSVC_CRT_VERSION
12980 #undef PUGI__SNPRINTF
12981 #undef PUGI__NS_BEGIN
12982 #undef PUGI__NS_END
12983 #undef PUGI__FN
12984 #undef PUGI__FN_NO_INLINE
12985 #undef PUGI__GETHEADER_IMPL
12986 #undef PUGI__GETPAGE_IMPL
12987 #undef PUGI__GETPAGE
12988 #undef PUGI__NODETYPE
12989 #undef PUGI__IS_CHARTYPE_IMPL
12990 #undef PUGI__IS_CHARTYPE
12991 #undef PUGI__IS_CHARTYPEX
12992 #undef PUGI__ENDSWITH
12993 #undef PUGI__SKIPWS
12994 #undef PUGI__OPTSET
12995 #undef PUGI__PUSHNODE
12996 #undef PUGI__POPNODE
12997 #undef PUGI__SCANFOR
12998 #undef PUGI__SCANWHILE
12999 #undef PUGI__SCANWHILE_UNROLL
13000 #undef PUGI__ENDSEG
13001 #undef PUGI__THROW_ERROR
13002 #undef PUGI__CHECK_ERROR
13003
13004 #endif
13005
13006 /**
13007  * Copyright (c) 2006-2022 Arseny Kapoulkine
13008  *
13009  * Permission is hereby granted, free of charge, to any person
13010  * obtaining a copy of this software and associated documentation
13011  * files (the "Software"), to deal in the Software without
13012  * restriction, including without limitation the rights to use,
13013  * copy, modify, merge, publish, distribute, sublicense, and/or sell
13014  * copies of the Software, and to permit persons to whom the
13015  * Software is furnished to do so, subject to the following
13016  * conditions:
13017  *
13018  * The above copyright notice and this permission notice shall be
13019  * included in all copies or substantial portions of the Software.
13020  *
13021  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13022  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
13023  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13024  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
13025  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
13026  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
13027  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
13028  * OTHER DEALINGS IN THE SOFTWARE.
13029  */