comparison pugixml/src/pugixml.cpp @ 47:8a8de065f049

pugixml: upgrade to 1.8, closes #614
author David Demelier <markand@malikania.fr>
date Fri, 20 Jan 2017 10:44:37 +0100
parents 22ae219278af
children 1a32b6d17c8e
comparison
equal deleted inserted replaced
46:fa2587b194ee 47:8a8de065f049
1 /** 1 /**
2 * pugixml parser - version 1.7 2 * pugixml parser - version 1.8
3 * -------------------------------------------------------- 3 * --------------------------------------------------------
4 * Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) 4 * Copyright (C) 2006-2016, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
5 * Report bugs and download new versions at http://pugixml.org/ 5 * Report bugs and download new versions at http://pugixml.org/
6 * 6 *
7 * This library is distributed under the MIT License. See notice at the end 7 * This library is distributed under the MIT License. See notice at the end
8 * of this file. 8 * of this file.
9 * 9 *
52 # pragma warning(disable: 4996) // this function or variable may be unsafe 52 # pragma warning(disable: 4996) // this function or variable may be unsafe
53 # pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged 53 # pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged
54 #endif 54 #endif
55 55
56 #ifdef __INTEL_COMPILER 56 #ifdef __INTEL_COMPILER
57 # pragma warning(disable: 177) // function was declared but never referenced 57 # pragma warning(disable: 177) // function was declared but never referenced
58 # pragma warning(disable: 279) // controlling expression is constant 58 # pragma warning(disable: 279) // controlling expression is constant
59 # pragma warning(disable: 1478 1786) // function was declared "deprecated" 59 # pragma warning(disable: 1478 1786) // function was declared "deprecated"
60 # pragma warning(disable: 1684) // conversion from pointer to same-sized integral type 60 # pragma warning(disable: 1684) // conversion from pointer to same-sized integral type
61 #endif 61 #endif
62 62
80 #if defined(_MSC_VER) && _MSC_VER >= 1300 80 #if defined(_MSC_VER) && _MSC_VER >= 1300
81 # define PUGI__NO_INLINE __declspec(noinline) 81 # define PUGI__NO_INLINE __declspec(noinline)
82 #elif defined(__GNUC__) 82 #elif defined(__GNUC__)
83 # define PUGI__NO_INLINE __attribute__((noinline)) 83 # define PUGI__NO_INLINE __attribute__((noinline))
84 #else 84 #else
85 # define PUGI__NO_INLINE 85 # define PUGI__NO_INLINE
86 #endif 86 #endif
87 87
88 // Branch weight controls 88 // Branch weight controls
89 #if defined(__GNUC__) 89 #if defined(__GNUC__)
90 # define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0) 90 # define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0)
105 // 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) 105 // 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)
106 #if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST) 106 #if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST)
107 using std::memcpy; 107 using std::memcpy;
108 using std::memmove; 108 using std::memmove;
109 using std::memset; 109 using std::memset;
110 #endif
111
112 // Some MinGW versions have headers that erroneously omit LLONG_MIN/LLONG_MAX/ULLONG_MAX definitions in strict ANSI mode
113 #if defined(PUGIXML_HAS_LONG_LONG) && defined(__MINGW32__) && defined(__STRICT_ANSI__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX)
114 # define LLONG_MAX 9223372036854775807LL
115 # define LLONG_MIN (-LLONG_MAX-1)
116 # define ULLONG_MAX (2ULL*LLONG_MAX+1)
110 #endif 117 #endif
111 118
112 // In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features 119 // In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features
113 #if defined(_MSC_VER) && !defined(__S3E__) 120 #if defined(_MSC_VER) && !defined(__S3E__)
114 # define PUGI__MSVC_CRT_VERSION _MSC_VER 121 # define PUGI__MSVC_CRT_VERSION _MSC_VER
130 # define PUGI__FN 137 # define PUGI__FN
131 # define PUGI__FN_NO_INLINE PUGI__NO_INLINE 138 # define PUGI__FN_NO_INLINE PUGI__NO_INLINE
132 #endif 139 #endif
133 140
134 // uintptr_t 141 // uintptr_t
135 #if !defined(_MSC_VER) || _MSC_VER >= 1600 142 #if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561)
136 # include <stdint.h>
137 #else
138 namespace pugi 143 namespace pugi
139 { 144 {
140 # ifndef _UINTPTR_T_DEFINED 145 # ifndef _UINTPTR_T_DEFINED
141 typedef size_t uintptr_t; 146 typedef size_t uintptr_t;
142 # endif 147 # endif
143 148
144 typedef unsigned __int8 uint8_t; 149 typedef unsigned __int8 uint8_t;
145 typedef unsigned __int16 uint16_t; 150 typedef unsigned __int16 uint16_t;
146 typedef unsigned __int32 uint32_t; 151 typedef unsigned __int32 uint32_t;
147 } 152 }
153 #else
154 # include <stdint.h>
148 #endif 155 #endif
149 156
150 // Memory allocation 157 // Memory allocation
151 PUGI__NS_BEGIN 158 PUGI__NS_BEGIN
152 PUGI__FN void* default_allocate(size_t size) 159 PUGI__FN void* default_allocate(size_t size)
204 PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) 211 PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count)
205 { 212 {
206 for (size_t i = 0; i < count; ++i) 213 for (size_t i = 0; i < count; ++i)
207 if (lhs[i] != rhs[i]) 214 if (lhs[i] != rhs[i])
208 return false; 215 return false;
209 216
210 return lhs[count] == 0; 217 return lhs[count] == 0;
211 } 218 }
212 219
213 // Get length of wide string, even if CRT lacks wide character support 220 // Get length of wide string, even if CRT lacks wide character support
214 PUGI__FN size_t strlength_wide(const wchar_t* s) 221 PUGI__FN size_t strlength_wide(const wchar_t* s)
225 } 232 }
226 PUGI__NS_END 233 PUGI__NS_END
227 234
228 // auto_ptr-like object for exception recovery 235 // auto_ptr-like object for exception recovery
229 PUGI__NS_BEGIN 236 PUGI__NS_BEGIN
230 template <typename T, typename D = void(*)(T*)> struct auto_deleter 237 template <typename T> struct auto_deleter
231 { 238 {
239 typedef void (*D)(T*);
240
232 T* data; 241 T* data;
233 D deleter; 242 D deleter;
234 243
235 auto_deleter(T* data_, D deleter_): data(data_), deleter(deleter_) 244 auto_deleter(T* data_, D deleter_): data(data_), deleter(deleter_)
236 { 245 {
291 300
292 // hash collision, quadratic probing 301 // hash collision, quadratic probing
293 bucket = (bucket + probe + 1) & hashmod; 302 bucket = (bucket + probe + 1) & hashmod;
294 } 303 }
295 304
296 assert(!"Hash table is full"); 305 assert(false && "Hash table is full");
297 return 0; 306 return 0;
298 } 307 }
299 308
300 void** insert(const void* key) 309 void** insert(const void* key)
301 { 310 {
321 330
322 // hash collision, quadratic probing 331 // hash collision, quadratic probing
323 bucket = (bucket + probe + 1) & hashmod; 332 bucket = (bucket + probe + 1) & hashmod;
324 } 333 }
325 334
326 assert(!"Hash table is full"); 335 assert(false && "Hash table is full");
327 return 0; 336 return 0;
328 } 337 }
329 338
330 bool reserve() 339 bool reserve()
331 { 340 {
392 401
393 PUGI__NS_END 402 PUGI__NS_END
394 #endif 403 #endif
395 404
396 PUGI__NS_BEGIN 405 PUGI__NS_BEGIN
397 static const size_t xml_memory_page_size =
398 #ifdef PUGIXML_MEMORY_PAGE_SIZE
399 PUGIXML_MEMORY_PAGE_SIZE
400 #else
401 32768
402 #endif
403 ;
404
405 #ifdef PUGIXML_COMPACT 406 #ifdef PUGIXML_COMPACT
406 static const uintptr_t xml_memory_block_alignment = 4; 407 static const uintptr_t xml_memory_block_alignment = 4;
407
408 static const uintptr_t xml_memory_page_alignment = sizeof(void*);
409 #else 408 #else
410 static const uintptr_t xml_memory_block_alignment = sizeof(void*); 409 static const uintptr_t xml_memory_block_alignment = sizeof(void*);
411
412 static const uintptr_t xml_memory_page_alignment = 64;
413 static const uintptr_t xml_memory_page_pointer_mask = ~(xml_memory_page_alignment - 1);
414 #endif 410 #endif
415 411
416 // extra metadata bits 412 // extra metadata bits
417 static const uintptr_t xml_memory_page_contents_shared_mask = 32; 413 static const uintptr_t xml_memory_page_contents_shared_mask = 64;
418 static const uintptr_t xml_memory_page_name_allocated_mask = 16; 414 static const uintptr_t xml_memory_page_name_allocated_mask = 32;
419 static const uintptr_t xml_memory_page_value_allocated_mask = 8; 415 static const uintptr_t xml_memory_page_value_allocated_mask = 16;
420 static const uintptr_t xml_memory_page_type_mask = 7; 416 static const uintptr_t xml_memory_page_type_mask = 15;
421 417
422 // combined masks for string uniqueness 418 // combined masks for string uniqueness
423 static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask; 419 static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask;
424 static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask; 420 static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask;
425 421
426 #ifdef PUGIXML_COMPACT 422 #ifdef PUGIXML_COMPACT
423 #define PUGI__GETHEADER_IMPL(object, page, flags) // unused
427 #define PUGI__GETPAGE_IMPL(header) (header).get_page() 424 #define PUGI__GETPAGE_IMPL(header) (header).get_page()
428 #else 425 #else
429 #define PUGI__GETPAGE_IMPL(header) reinterpret_cast<impl::xml_memory_page*>((header) & impl::xml_memory_page_pointer_mask) 426 #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast<char*>(object) - reinterpret_cast<char*>(page)) << 8) | (flags))
427 // this macro casts pointers through void* to avoid 'cast increases required alignment of target type' warnings
428 #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))))
430 #endif 429 #endif
431 430
432 #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header) 431 #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header)
433 #define PUGI__NODETYPE(n) static_cast<xml_node_type>(((n)->header & impl::xml_memory_page_type_mask) + 1) 432 #define PUGI__NODETYPE(n) static_cast<xml_node_type>((n)->header & impl::xml_memory_page_type_mask)
434 433
435 struct xml_allocator; 434 struct xml_allocator;
436 435
437 struct xml_memory_page 436 struct xml_memory_page
438 { 437 {
468 void* compact_shared_parent; 467 void* compact_shared_parent;
469 uint32_t* compact_page_marker; 468 uint32_t* compact_page_marker;
470 #endif 469 #endif
471 }; 470 };
472 471
472 static const size_t xml_memory_page_size =
473 #ifdef PUGIXML_MEMORY_PAGE_SIZE
474 (PUGIXML_MEMORY_PAGE_SIZE)
475 #else
476 32768
477 #endif
478 - sizeof(xml_memory_page);
479
473 struct xml_memory_string_header 480 struct xml_memory_string_header
474 { 481 {
475 uint16_t page_offset; // offset from page->data 482 uint16_t page_offset; // offset from page->data
476 uint16_t full_size; // 0 if string occupies whole page 483 uint16_t full_size; // 0 if string occupies whole page
477 }; 484 };
488 xml_memory_page* allocate_page(size_t data_size) 495 xml_memory_page* allocate_page(size_t data_size)
489 { 496 {
490 size_t size = sizeof(xml_memory_page) + data_size; 497 size_t size = sizeof(xml_memory_page) + data_size;
491 498
492 // allocate block with some alignment, leaving memory for worst-case padding 499 // allocate block with some alignment, leaving memory for worst-case padding
493 void* memory = xml_memory::allocate(size + xml_memory_page_alignment); 500 void* memory = xml_memory::allocate(size);
494 if (!memory) return 0; 501 if (!memory) return 0;
495 502
496 // align to next page boundary (note: this guarantees at least 1 usable byte before the page)
497 char* page_memory = reinterpret_cast<char*>((reinterpret_cast<uintptr_t>(memory) + xml_memory_page_alignment) & ~(xml_memory_page_alignment - 1));
498
499 // prepare page structure 503 // prepare page structure
500 xml_memory_page* page = xml_memory_page::construct(page_memory); 504 xml_memory_page* page = xml_memory_page::construct(memory);
501 assert(page); 505 assert(page);
502 506
503 page->allocator = _root->allocator; 507 page->allocator = _root->allocator;
504 508
505 // record the offset for freeing the memory block
506 assert(page_memory > memory && page_memory - static_cast<char*>(memory) <= 127);
507 page_memory[-1] = static_cast<char>(page_memory - static_cast<char*>(memory));
508
509 return page; 509 return page;
510 } 510 }
511 511
512 static void deallocate_page(xml_memory_page* page) 512 static void deallocate_page(xml_memory_page* page)
513 { 513 {
514 char* page_memory = reinterpret_cast<char*>(page); 514 xml_memory::deallocate(page);
515
516 xml_memory::deallocate(page_memory - page_memory[-1]);
517 } 515 }
518 516
519 void* allocate_memory_oob(size_t size, xml_memory_page*& out_page); 517 void* allocate_memory_oob(size_t size, xml_memory_page*& out_page);
520 518
521 void* allocate_memory(size_t size, xml_memory_page*& out_page) 519 void* allocate_memory(size_t size, xml_memory_page*& out_page)
620 618
621 PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset); 619 PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset);
622 620
623 // allocate memory for string and header block 621 // allocate memory for string and header block
624 size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); 622 size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t);
625 623
626 // round size up to block alignment boundary 624 // round size up to block alignment boundary
627 size_t full_size = (size + (xml_memory_block_alignment - 1)) & ~(xml_memory_block_alignment - 1); 625 size_t full_size = (size + (xml_memory_block_alignment - 1)) & ~(xml_memory_block_alignment - 1);
628 626
629 xml_memory_page* page; 627 xml_memory_page* page;
630 xml_memory_string_header* header = static_cast<xml_memory_string_header*>(allocate_memory(full_size, page)); 628 xml_memory_string_header* header = static_cast<xml_memory_string_header*>(allocate_memory(full_size, page));
1044 impl::compact_pointer<xml_attribute_struct, 7, 0> next_attribute; 1042 impl::compact_pointer<xml_attribute_struct, 7, 0> next_attribute;
1045 }; 1043 };
1046 1044
1047 struct xml_node_struct 1045 struct xml_node_struct
1048 { 1046 {
1049 xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type - 1), namevalue_base(0) 1047 xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type), namevalue_base(0)
1050 { 1048 {
1051 PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 12); 1049 PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 12);
1052 } 1050 }
1053 1051
1054 impl::compact_header header; 1052 impl::compact_header header;
1071 #else 1069 #else
1072 namespace pugi 1070 namespace pugi
1073 { 1071 {
1074 struct xml_attribute_struct 1072 struct xml_attribute_struct
1075 { 1073 {
1076 xml_attribute_struct(impl::xml_memory_page* page): header(reinterpret_cast<uintptr_t>(page)), name(0), value(0), prev_attribute_c(0), next_attribute(0) 1074 xml_attribute_struct(impl::xml_memory_page* page): name(0), value(0), prev_attribute_c(0), next_attribute(0)
1077 { 1075 {
1076 header = PUGI__GETHEADER_IMPL(this, page, 0);
1078 } 1077 }
1079 1078
1080 uintptr_t header; 1079 uintptr_t header;
1081 1080
1082 char_t* name; 1081 char_t* name;
1086 xml_attribute_struct* next_attribute; 1085 xml_attribute_struct* next_attribute;
1087 }; 1086 };
1088 1087
1089 struct xml_node_struct 1088 struct xml_node_struct
1090 { 1089 {
1091 xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(reinterpret_cast<uintptr_t>(page) | (type - 1)), name(0), value(0), parent(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) 1090 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)
1092 { 1091 {
1092 header = PUGI__GETHEADER_IMPL(this, page, type);
1093 } 1093 }
1094 1094
1095 uintptr_t header; 1095 uintptr_t header;
1096 1096
1097 char_t* name; 1097 char_t* name;
1118 1118
1119 struct xml_document_struct: public xml_node_struct, public xml_allocator 1119 struct xml_document_struct: public xml_node_struct, public xml_allocator
1120 { 1120 {
1121 xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0) 1121 xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0)
1122 { 1122 {
1123 #ifdef PUGIXML_COMPACT
1124 _hash = &hash;
1125 #endif
1126 } 1123 }
1127 1124
1128 const char_t* buffer; 1125 const char_t* buffer;
1129 1126
1130 xml_extra_buffer* extra_buffers; 1127 xml_extra_buffer* extra_buffers;
1845 ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, " 1842 ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, "
1846 ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ 1843 ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _
1847 ctx_digit = 8, // 0-9 1844 ctx_digit = 8, // 0-9
1848 ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . 1845 ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, .
1849 }; 1846 };
1850 1847
1851 static const unsigned char chartypex_table[256] = 1848 static const unsigned char chartypex_table[256] =
1852 { 1849 {
1853 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15 1850 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15
1854 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 1851 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31
1855 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 1852 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47
1867 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1864 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1868 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1865 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1869 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1866 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1870 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 1867 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20
1871 }; 1868 };
1872 1869
1873 #ifdef PUGIXML_WCHAR_MODE 1870 #ifdef PUGIXML_WCHAR_MODE
1874 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct)) 1871 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct))
1875 #else 1872 #else
1876 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct)) 1873 #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct))
1877 #endif 1874 #endif
1890 { 1887 {
1891 PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); 1888 PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4);
1892 1889
1893 if (sizeof(wchar_t) == 2) 1890 if (sizeof(wchar_t) == 2)
1894 return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; 1891 return is_little_endian() ? encoding_utf16_le : encoding_utf16_be;
1895 else 1892 else
1896 return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; 1893 return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
1897 } 1894 }
1898 1895
1899 PUGI__FN xml_encoding guess_buffer_encoding(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) 1896 PUGI__FN bool parse_declaration_encoding(const uint8_t* data, size_t size, const uint8_t*& out_encoding, size_t& out_length)
1900 { 1897 {
1898 #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; }
1899 #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; }
1900
1901 // check if we have a non-empty XML declaration
1902 if (size < 6 || !((data[0] == '<') & (data[1] == '?') & (data[2] == 'x') & (data[3] == 'm') & (data[4] == 'l') && PUGI__IS_CHARTYPE(data[5], ct_space)))
1903 return false;
1904
1905 // scan XML declaration until the encoding field
1906 for (size_t i = 6; i + 1 < size; ++i)
1907 {
1908 // declaration can not contain ? in quoted values
1909 if (data[i] == '?')
1910 return false;
1911
1912 if (data[i] == 'e' && data[i + 1] == 'n')
1913 {
1914 size_t offset = i;
1915
1916 // encoding follows the version field which can't contain 'en' so this has to be the encoding if XML is well formed
1917 PUGI__SCANCHAR('e'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('c'); PUGI__SCANCHAR('o');
1918 PUGI__SCANCHAR('d'); PUGI__SCANCHAR('i'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('g');
1919
1920 // S? = S?
1921 PUGI__SCANCHARTYPE(ct_space);
1922 PUGI__SCANCHAR('=');
1923 PUGI__SCANCHARTYPE(ct_space);
1924
1925 // the only two valid delimiters are ' and "
1926 uint8_t delimiter = (offset < size && data[offset] == '"') ? '"' : '\'';
1927
1928 PUGI__SCANCHAR(delimiter);
1929
1930 size_t start = offset;
1931
1932 out_encoding = data + offset;
1933
1934 PUGI__SCANCHARTYPE(ct_symbol);
1935
1936 out_length = offset - start;
1937
1938 PUGI__SCANCHAR(delimiter);
1939
1940 return true;
1941 }
1942 }
1943
1944 return false;
1945
1946 #undef PUGI__SCANCHAR
1947 #undef PUGI__SCANCHARTYPE
1948 }
1949
1950 PUGI__FN xml_encoding guess_buffer_encoding(const uint8_t* data, size_t size)
1951 {
1952 // skip encoding autodetection if input buffer is too small
1953 if (size < 4) return encoding_utf8;
1954
1955 uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3];
1956
1901 // look for BOM in first few bytes 1957 // look for BOM in first few bytes
1902 if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be; 1958 if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be;
1903 if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le; 1959 if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le;
1904 if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be; 1960 if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be;
1905 if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le; 1961 if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le;
1908 // look for <, <? or <?xm in various encodings 1964 // look for <, <? or <?xm in various encodings
1909 if (d0 == 0 && d1 == 0 && d2 == 0 && d3 == 0x3c) return encoding_utf32_be; 1965 if (d0 == 0 && d1 == 0 && d2 == 0 && d3 == 0x3c) return encoding_utf32_be;
1910 if (d0 == 0x3c && d1 == 0 && d2 == 0 && d3 == 0) return encoding_utf32_le; 1966 if (d0 == 0x3c && d1 == 0 && d2 == 0 && d3 == 0) return encoding_utf32_le;
1911 if (d0 == 0 && d1 == 0x3c && d2 == 0 && d3 == 0x3f) return encoding_utf16_be; 1967 if (d0 == 0 && d1 == 0x3c && d2 == 0 && d3 == 0x3f) return encoding_utf16_be;
1912 if (d0 == 0x3c && d1 == 0 && d2 == 0x3f && d3 == 0) return encoding_utf16_le; 1968 if (d0 == 0x3c && d1 == 0 && d2 == 0x3f && d3 == 0) return encoding_utf16_le;
1913 if (d0 == 0x3c && d1 == 0x3f && d2 == 0x78 && d3 == 0x6d) return encoding_utf8;
1914 1969
1915 // look for utf16 < followed by node name (this may fail, but is better than utf8 since it's zero terminated so early) 1970 // look for utf16 < followed by node name (this may fail, but is better than utf8 since it's zero terminated so early)
1916 if (d0 == 0 && d1 == 0x3c) return encoding_utf16_be; 1971 if (d0 == 0 && d1 == 0x3c) return encoding_utf16_be;
1917 if (d0 == 0x3c && d1 == 0) return encoding_utf16_le; 1972 if (d0 == 0x3c && d1 == 0) return encoding_utf16_le;
1918 1973
1919 // no known BOM detected, assume utf8 1974 // no known BOM detected; parse declaration
1975 const uint8_t* enc = 0;
1976 size_t enc_length = 0;
1977
1978 if (d0 == 0x3c && d1 == 0x3f && d2 == 0x78 && d3 == 0x6d && parse_declaration_encoding(data, size, enc, enc_length))
1979 {
1980 // iso-8859-1 (case-insensitive)
1981 if (enc_length == 10
1982 && (enc[0] | ' ') == 'i' && (enc[1] | ' ') == 's' && (enc[2] | ' ') == 'o'
1983 && enc[3] == '-' && enc[4] == '8' && enc[5] == '8' && enc[6] == '5' && enc[7] == '9'
1984 && enc[8] == '-' && enc[9] == '1')
1985 return encoding_latin1;
1986
1987 // latin1 (case-insensitive)
1988 if (enc_length == 6
1989 && (enc[0] | ' ') == 'l' && (enc[1] | ' ') == 'a' && (enc[2] | ' ') == 't'
1990 && (enc[3] | ' ') == 'i' && (enc[4] | ' ') == 'n'
1991 && enc[5] == '1')
1992 return encoding_latin1;
1993 }
1994
1920 return encoding_utf8; 1995 return encoding_utf8;
1921 } 1996 }
1922 1997
1923 PUGI__FN xml_encoding get_buffer_encoding(xml_encoding encoding, const void* contents, size_t size) 1998 PUGI__FN xml_encoding get_buffer_encoding(xml_encoding encoding, const void* contents, size_t size)
1924 { 1999 {
1932 if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; 2007 if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be;
1933 2008
1934 // only do autodetection if no explicit encoding is requested 2009 // only do autodetection if no explicit encoding is requested
1935 if (encoding != encoding_auto) return encoding; 2010 if (encoding != encoding_auto) return encoding;
1936 2011
1937 // skip encoding autodetection if input buffer is too small
1938 if (size < 4) return encoding_utf8;
1939
1940 // try to guess encoding (based on XML specification, Appendix F.1) 2012 // try to guess encoding (based on XML specification, Appendix F.1)
1941 const uint8_t* data = static_cast<const uint8_t*>(contents); 2013 const uint8_t* data = static_cast<const uint8_t*>(contents);
1942 2014
1943 PUGI__DMC_VOLATILE uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3]; 2015 return guess_buffer_encoding(data, size);
1944
1945 return guess_buffer_encoding(d0, d1, d2, d3);
1946 } 2016 }
1947 2017
1948 PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) 2018 PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable)
1949 { 2019 {
1950 size_t length = size / sizeof(char_t); 2020 size_t length = size / sizeof(char_t);
2073 2143
2074 // source encoding is latin1 2144 // source encoding is latin1
2075 if (encoding == encoding_latin1) 2145 if (encoding == encoding_latin1)
2076 return convert_buffer_generic(out_buffer, out_length, contents, size, latin1_decoder()); 2146 return convert_buffer_generic(out_buffer, out_length, contents, size, latin1_decoder());
2077 2147
2078 assert(!"Invalid encoding"); 2148 assert(false && "Invalid encoding");
2079 return false; 2149 return false;
2080 } 2150 }
2081 #else 2151 #else
2082 template <typename D> PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) 2152 template <typename D> PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D)
2083 { 2153 {
2178 2248
2179 // source encoding is latin1 2249 // source encoding is latin1
2180 if (encoding == encoding_latin1) 2250 if (encoding == encoding_latin1)
2181 return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable); 2251 return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable);
2182 2252
2183 assert(!"Invalid encoding"); 2253 assert(false && "Invalid encoding");
2184 return false; 2254 return false;
2185 } 2255 }
2186 #endif 2256 #endif
2187 2257
2188 PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length) 2258 PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length)
2194 PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) 2264 PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length)
2195 { 2265 {
2196 // convert to utf8 2266 // convert to utf8
2197 uint8_t* begin = reinterpret_cast<uint8_t*>(buffer); 2267 uint8_t* begin = reinterpret_cast<uint8_t*>(buffer);
2198 uint8_t* end = wchar_decoder::process(str, length, begin, utf8_writer()); 2268 uint8_t* end = wchar_decoder::process(str, length, begin, utf8_writer());
2199 2269
2200 assert(begin + size == end); 2270 assert(begin + size == end);
2201 (void)!end; 2271 (void)!end;
2202 (void)!size; 2272 (void)!size;
2203 } 2273 }
2204 2274
2205 #ifndef PUGIXML_NO_STL 2275 #ifndef PUGIXML_NO_STL
2206 PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length) 2276 PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length)
2207 { 2277 {
2208 // first pass: get length in utf8 characters 2278 // first pass: get length in utf8 characters
2209 size_t size = as_utf8_begin(str, length); 2279 size_t size = as_utf8_begin(str, length);
2267 { 2337 {
2268 // empty string and null pointer are equivalent, so just deallocate old memory 2338 // empty string and null pointer are equivalent, so just deallocate old memory
2269 xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; 2339 xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator;
2270 2340
2271 if (header & header_mask) alloc->deallocate_string(dest); 2341 if (header & header_mask) alloc->deallocate_string(dest);
2272 2342
2273 // mark the string as not allocated 2343 // mark the string as not allocated
2274 dest = 0; 2344 dest = 0;
2275 header &= ~header_mask; 2345 header &= ~header_mask;
2276 2346
2277 return true; 2347 return true;
2279 else if (dest && strcpy_insitu_allow(source_length, header, header_mask, dest)) 2349 else if (dest && strcpy_insitu_allow(source_length, header, header_mask, dest))
2280 { 2350 {
2281 // we can reuse old buffer, so just copy the new data (including zero terminator) 2351 // we can reuse old buffer, so just copy the new data (including zero terminator)
2282 memcpy(dest, source, source_length * sizeof(char_t)); 2352 memcpy(dest, source, source_length * sizeof(char_t));
2283 dest[source_length] = 0; 2353 dest[source_length] = 0;
2284 2354
2285 return true; 2355 return true;
2286 } 2356 }
2287 else 2357 else
2288 { 2358 {
2289 xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; 2359 xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator;
2298 memcpy(buf, source, source_length * sizeof(char_t)); 2368 memcpy(buf, source, source_length * sizeof(char_t));
2299 buf[source_length] = 0; 2369 buf[source_length] = 0;
2300 2370
2301 // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures) 2371 // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures)
2302 if (header & header_mask) alloc->deallocate_string(dest); 2372 if (header & header_mask) alloc->deallocate_string(dest);
2303 2373
2304 // the string is now allocated, so set the flag 2374 // the string is now allocated, so set the flag
2305 dest = buf; 2375 dest = buf;
2306 header |= header_mask; 2376 header |= header_mask;
2307 2377
2308 return true; 2378 return true;
2311 2381
2312 struct gap 2382 struct gap
2313 { 2383 {
2314 char_t* end; 2384 char_t* end;
2315 size_t size; 2385 size_t size;
2316 2386
2317 gap(): end(0), size(0) 2387 gap(): end(0), size(0)
2318 { 2388 {
2319 } 2389 }
2320 2390
2321 // Push new gap, move s count bytes further (skipping the gap). 2391 // Push new gap, move s count bytes further (skipping the gap).
2322 // Collapse previous gap. 2392 // Collapse previous gap.
2323 void push(char_t*& s, size_t count) 2393 void push(char_t*& s, size_t count)
2324 { 2394 {
2325 if (end) // there was a gap already; collapse it 2395 if (end) // there was a gap already; collapse it
2326 { 2396 {
2327 // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) 2397 // Move [old_gap_end, new_gap_start) to [old_gap_start, ...)
2328 assert(s >= end); 2398 assert(s >= end);
2329 memmove(end - size, end, reinterpret_cast<char*>(s) - reinterpret_cast<char*>(end)); 2399 memmove(end - size, end, reinterpret_cast<char*>(s) - reinterpret_cast<char*>(end));
2330 } 2400 }
2331 2401
2332 s += count; // end of current gap 2402 s += count; // end of current gap
2333 2403
2334 // "merge" two gaps 2404 // "merge" two gaps
2335 end = s; 2405 end = s;
2336 size += count; 2406 size += count;
2337 } 2407 }
2338 2408
2339 // Collapse all gaps, return past-the-end pointer 2409 // Collapse all gaps, return past-the-end pointer
2340 char_t* flush(char_t* s) 2410 char_t* flush(char_t* s)
2341 { 2411 {
2342 if (end) 2412 if (end)
2343 { 2413 {
2348 return s - size; 2418 return s - size;
2349 } 2419 }
2350 else return s; 2420 else return s;
2351 } 2421 }
2352 }; 2422 };
2353 2423
2354 PUGI__FN char_t* strconv_escape(char_t* s, gap& g) 2424 PUGI__FN char_t* strconv_escape(char_t* s, gap& g)
2355 { 2425 {
2356 char_t* stre = s + 1; 2426 char_t* stre = s + 1;
2357 2427
2358 switch (*stre) 2428 switch (*stre)
2380 else // cancel 2450 else // cancel
2381 return stre; 2451 return stre;
2382 2452
2383 ch = *++stre; 2453 ch = *++stre;
2384 } 2454 }
2385 2455
2386 ++stre; 2456 ++stre;
2387 } 2457 }
2388 else // &#... (dec code) 2458 else // &#... (dec code)
2389 { 2459 {
2390 char_t ch = *++stre; 2460 char_t ch = *++stre;
2400 else // cancel 2470 else // cancel
2401 return stre; 2471 return stre;
2402 2472
2403 ch = *++stre; 2473 ch = *++stre;
2404 } 2474 }
2405 2475
2406 ++stre; 2476 ++stre;
2407 } 2477 }
2408 2478
2409 #ifdef PUGIXML_WCHAR_MODE 2479 #ifdef PUGIXML_WCHAR_MODE
2410 s = reinterpret_cast<char_t*>(wchar_writer::any(reinterpret_cast<wchar_writer::value_type>(s), ucsc)); 2480 s = reinterpret_cast<char_t*>(wchar_writer::any(reinterpret_cast<wchar_writer::value_type>(s), ucsc));
2411 #else 2481 #else
2412 s = reinterpret_cast<char_t*>(utf8_writer::any(reinterpret_cast<uint8_t*>(s), ucsc)); 2482 s = reinterpret_cast<char_t*>(utf8_writer::any(reinterpret_cast<uint8_t*>(s), ucsc));
2413 #endif 2483 #endif
2414 2484
2415 g.push(s, stre - s); 2485 g.push(s, stre - s);
2416 return stre; 2486 return stre;
2417 } 2487 }
2418 2488
2419 case 'a': // &a 2489 case 'a': // &a
2424 { 2494 {
2425 if (*++stre == 'p' && *++stre == ';') // &amp; 2495 if (*++stre == 'p' && *++stre == ';') // &amp;
2426 { 2496 {
2427 *s++ = '&'; 2497 *s++ = '&';
2428 ++stre; 2498 ++stre;
2429 2499
2430 g.push(s, stre - s); 2500 g.push(s, stre - s);
2431 return stre; 2501 return stre;
2432 } 2502 }
2433 } 2503 }
2434 else if (*stre == 'p') // &ap 2504 else if (*stre == 'p') // &ap
2449 { 2519 {
2450 if (*++stre == 't' && *++stre == ';') // &gt; 2520 if (*++stre == 't' && *++stre == ';') // &gt;
2451 { 2521 {
2452 *s++ = '>'; 2522 *s++ = '>';
2453 ++stre; 2523 ++stre;
2454 2524
2455 g.push(s, stre - s); 2525 g.push(s, stre - s);
2456 return stre; 2526 return stre;
2457 } 2527 }
2458 break; 2528 break;
2459 } 2529 }
2462 { 2532 {
2463 if (*++stre == 't' && *++stre == ';') // &lt; 2533 if (*++stre == 't' && *++stre == ';') // &lt;
2464 { 2534 {
2465 *s++ = '<'; 2535 *s++ = '<';
2466 ++stre; 2536 ++stre;
2467 2537
2468 g.push(s, stre - s); 2538 g.push(s, stre - s);
2469 return stre; 2539 return stre;
2470 } 2540 }
2471 break; 2541 break;
2472 } 2542 }
2475 { 2545 {
2476 if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // &quot; 2546 if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // &quot;
2477 { 2547 {
2478 *s++ = '"'; 2548 *s++ = '"';
2479 ++stre; 2549 ++stre;
2480 2550
2481 g.push(s, stre - s); 2551 g.push(s, stre - s);
2482 return stre; 2552 return stre;
2483 } 2553 }
2484 break; 2554 break;
2485 } 2555 }
2486 2556
2487 default: 2557 default:
2488 break; 2558 break;
2489 } 2559 }
2490 2560
2491 return stre; 2561 return stre;
2492 } 2562 }
2493 2563
2494 // Parser utilities 2564 // Parser utilities
2495 #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) 2565 #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e)))
2496 #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; } 2566 #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; }
2497 #define PUGI__OPTSET(OPT) ( optmsk & (OPT) ) 2567 #define PUGI__OPTSET(OPT) ( optmsk & (OPT) )
2498 #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); } 2568 #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); }
2499 #define PUGI__POPNODE() { cursor = cursor->parent; } 2569 #define PUGI__POPNODE() { cursor = cursor->parent; }
2500 #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; } 2570 #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
2501 #define PUGI__SCANWHILE(X) { while (X) ++s; } 2571 #define PUGI__SCANWHILE(X) { while (X) ++s; }
2502 #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; } } 2572 #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; } }
2503 #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; } 2573 #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; }
2505 #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); } 2575 #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); }
2506 2576
2507 PUGI__FN char_t* strconv_comment(char_t* s, char_t endch) 2577 PUGI__FN char_t* strconv_comment(char_t* s, char_t endch)
2508 { 2578 {
2509 gap g; 2579 gap g;
2510 2580
2511 while (true) 2581 while (true)
2512 { 2582 {
2513 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment)); 2583 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment));
2514 2584
2515 if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair 2585 if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
2516 { 2586 {
2517 *s++ = '\n'; // replace first one with 0x0a 2587 *s++ = '\n'; // replace first one with 0x0a
2518 2588
2519 if (*s == '\n') g.push(s, 1); 2589 if (*s == '\n') g.push(s, 1);
2520 } 2590 }
2521 else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here 2591 else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here
2522 { 2592 {
2523 *g.flush(s) = 0; 2593 *g.flush(s) = 0;
2524 2594
2525 return s + (s[2] == '>' ? 3 : 2); 2595 return s + (s[2] == '>' ? 3 : 2);
2526 } 2596 }
2527 else if (*s == 0) 2597 else if (*s == 0)
2528 { 2598 {
2529 return 0; 2599 return 0;
2533 } 2603 }
2534 2604
2535 PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch) 2605 PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch)
2536 { 2606 {
2537 gap g; 2607 gap g;
2538 2608
2539 while (true) 2609 while (true)
2540 { 2610 {
2541 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata)); 2611 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata));
2542 2612
2543 if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair 2613 if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
2544 { 2614 {
2545 *s++ = '\n'; // replace first one with 0x0a 2615 *s++ = '\n'; // replace first one with 0x0a
2546 2616
2547 if (*s == '\n') g.push(s, 1); 2617 if (*s == '\n') g.push(s, 1);
2548 } 2618 }
2549 else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here 2619 else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here
2550 { 2620 {
2551 *g.flush(s) = 0; 2621 *g.flush(s) = 0;
2552 2622
2553 return s + 1; 2623 return s + 1;
2554 } 2624 }
2555 else if (*s == 0) 2625 else if (*s == 0)
2556 { 2626 {
2557 return 0; 2627 return 0;
2558 } 2628 }
2559 else ++s; 2629 else ++s;
2560 } 2630 }
2561 } 2631 }
2562 2632
2563 typedef char_t* (*strconv_pcdata_t)(char_t*); 2633 typedef char_t* (*strconv_pcdata_t)(char_t*);
2564 2634
2565 template <typename opt_trim, typename opt_eol, typename opt_escape> struct strconv_pcdata_impl 2635 template <typename opt_trim, typename opt_eol, typename opt_escape> struct strconv_pcdata_impl
2566 { 2636 {
2567 static char_t* parse(char_t* s) 2637 static char_t* parse(char_t* s)
2568 { 2638 {
2569 gap g; 2639 gap g;
2581 if (opt_trim::value) 2651 if (opt_trim::value)
2582 while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) 2652 while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space))
2583 --end; 2653 --end;
2584 2654
2585 *end = 0; 2655 *end = 0;
2586 2656
2587 return s + 1; 2657 return s + 1;
2588 } 2658 }
2589 else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair 2659 else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
2590 { 2660 {
2591 *s++ = '\n'; // replace first one with 0x0a 2661 *s++ = '\n'; // replace first one with 0x0a
2592 2662
2593 if (*s == '\n') g.push(s, 1); 2663 if (*s == '\n') g.push(s, 1);
2594 } 2664 }
2595 else if (opt_escape::value && *s == '&') 2665 else if (opt_escape::value && *s == '&')
2596 { 2666 {
2597 s = strconv_escape(s, g); 2667 s = strconv_escape(s, g);
2610 } 2680 }
2611 else ++s; 2681 else ++s;
2612 } 2682 }
2613 } 2683 }
2614 }; 2684 };
2615 2685
2616 PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) 2686 PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask)
2617 { 2687 {
2618 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); 2688 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800);
2619 2689
2620 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (eol escapes trim) 2690 switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (eol escapes trim)
2630 default: assert(false); return 0; // should not get here 2700 default: assert(false); return 0; // should not get here
2631 } 2701 }
2632 } 2702 }
2633 2703
2634 typedef char_t* (*strconv_attribute_t)(char_t*, char_t); 2704 typedef char_t* (*strconv_attribute_t)(char_t*, char_t);
2635 2705
2636 template <typename opt_escape> struct strconv_attribute_impl 2706 template <typename opt_escape> struct strconv_attribute_impl
2637 { 2707 {
2638 static char_t* parse_wnorm(char_t* s, char_t end_quote) 2708 static char_t* parse_wnorm(char_t* s, char_t end_quote)
2639 { 2709 {
2640 gap g; 2710 gap g;
2641 2711
2642 // trim leading whitespaces 2712 // trim leading whitespaces
2643 if (PUGI__IS_CHARTYPE(*s, ct_space)) 2713 if (PUGI__IS_CHARTYPE(*s, ct_space))
2644 { 2714 {
2645 char_t* str = s; 2715 char_t* str = s;
2646 2716
2647 do ++str; 2717 do ++str;
2648 while (PUGI__IS_CHARTYPE(*str, ct_space)); 2718 while (PUGI__IS_CHARTYPE(*str, ct_space));
2649 2719
2650 g.push(s, str - s); 2720 g.push(s, str - s);
2651 } 2721 }
2652 2722
2653 while (true) 2723 while (true)
2654 { 2724 {
2655 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space)); 2725 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space));
2656 2726
2657 if (*s == end_quote) 2727 if (*s == end_quote)
2658 { 2728 {
2659 char_t* str = g.flush(s); 2729 char_t* str = g.flush(s);
2660 2730
2661 do *str-- = 0; 2731 do *str-- = 0;
2662 while (PUGI__IS_CHARTYPE(*str, ct_space)); 2732 while (PUGI__IS_CHARTYPE(*str, ct_space));
2663 2733
2664 return s + 1; 2734 return s + 1;
2665 } 2735 }
2666 else if (PUGI__IS_CHARTYPE(*s, ct_space)) 2736 else if (PUGI__IS_CHARTYPE(*s, ct_space))
2667 { 2737 {
2668 *s++ = ' '; 2738 *s++ = ' ';
2669 2739
2670 if (PUGI__IS_CHARTYPE(*s, ct_space)) 2740 if (PUGI__IS_CHARTYPE(*s, ct_space))
2671 { 2741 {
2672 char_t* str = s + 1; 2742 char_t* str = s + 1;
2673 while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str; 2743 while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str;
2674 2744
2675 g.push(s, str - s); 2745 g.push(s, str - s);
2676 } 2746 }
2677 } 2747 }
2678 else if (opt_escape::value && *s == '&') 2748 else if (opt_escape::value && *s == '&')
2679 { 2749 {
2692 gap g; 2762 gap g;
2693 2763
2694 while (true) 2764 while (true)
2695 { 2765 {
2696 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws)); 2766 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws));
2697 2767
2698 if (*s == end_quote) 2768 if (*s == end_quote)
2699 { 2769 {
2700 *g.flush(s) = 0; 2770 *g.flush(s) = 0;
2701 2771
2702 return s + 1; 2772 return s + 1;
2703 } 2773 }
2704 else if (PUGI__IS_CHARTYPE(*s, ct_space)) 2774 else if (PUGI__IS_CHARTYPE(*s, ct_space))
2705 { 2775 {
2706 if (*s == '\r') 2776 if (*s == '\r')
2707 { 2777 {
2708 *s++ = ' '; 2778 *s++ = ' ';
2709 2779
2710 if (*s == '\n') g.push(s, 1); 2780 if (*s == '\n') g.push(s, 1);
2711 } 2781 }
2712 else *s++ = ' '; 2782 else *s++ = ' ';
2713 } 2783 }
2714 else if (opt_escape::value && *s == '&') 2784 else if (opt_escape::value && *s == '&')
2728 gap g; 2798 gap g;
2729 2799
2730 while (true) 2800 while (true)
2731 { 2801 {
2732 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); 2802 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr));
2733 2803
2734 if (*s == end_quote) 2804 if (*s == end_quote)
2735 { 2805 {
2736 *g.flush(s) = 0; 2806 *g.flush(s) = 0;
2737 2807
2738 return s + 1; 2808 return s + 1;
2739 } 2809 }
2740 else if (*s == '\r') 2810 else if (*s == '\r')
2741 { 2811 {
2742 *s++ = '\n'; 2812 *s++ = '\n';
2743 2813
2744 if (*s == '\n') g.push(s, 1); 2814 if (*s == '\n') g.push(s, 1);
2745 } 2815 }
2746 else if (opt_escape::value && *s == '&') 2816 else if (opt_escape::value && *s == '&')
2747 { 2817 {
2748 s = strconv_escape(s, g); 2818 s = strconv_escape(s, g);
2760 gap g; 2830 gap g;
2761 2831
2762 while (true) 2832 while (true)
2763 { 2833 {
2764 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); 2834 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr));
2765 2835
2766 if (*s == end_quote) 2836 if (*s == end_quote)
2767 { 2837 {
2768 *g.flush(s) = 0; 2838 *g.flush(s) = 0;
2769 2839
2770 return s + 1; 2840 return s + 1;
2771 } 2841 }
2772 else if (opt_escape::value && *s == '&') 2842 else if (opt_escape::value && *s == '&')
2773 { 2843 {
2774 s = strconv_escape(s, g); 2844 s = strconv_escape(s, g);
2783 }; 2853 };
2784 2854
2785 PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) 2855 PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask)
2786 { 2856 {
2787 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); 2857 PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80);
2788 2858
2789 switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes) 2859 switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes)
2790 { 2860 {
2791 case 0: return strconv_attribute_impl<opt_false>::parse_simple; 2861 case 0: return strconv_attribute_impl<opt_false>::parse_simple;
2792 case 1: return strconv_attribute_impl<opt_true>::parse_simple; 2862 case 1: return strconv_attribute_impl<opt_true>::parse_simple;
2793 case 2: return strconv_attribute_impl<opt_false>::parse_eol; 2863 case 2: return strconv_attribute_impl<opt_false>::parse_eol;
2817 return result; 2887 return result;
2818 } 2888 }
2819 2889
2820 struct xml_parser 2890 struct xml_parser
2821 { 2891 {
2822 xml_allocator alloc; 2892 xml_allocator* alloc;
2823 xml_allocator* alloc_state;
2824 char_t* error_offset; 2893 char_t* error_offset;
2825 xml_parse_status error_status; 2894 xml_parse_status error_status;
2826 2895
2827 xml_parser(xml_allocator* alloc_): alloc(*alloc_), alloc_state(alloc_), error_offset(0), error_status(status_ok) 2896 xml_parser(xml_allocator* alloc_): alloc(alloc_), error_offset(0), error_status(status_ok)
2828 { 2897 {
2829 }
2830
2831 ~xml_parser()
2832 {
2833 *alloc_state = alloc;
2834 } 2898 }
2835 2899
2836 // DOCTYPE consists of nested sections of the following possible types: 2900 // DOCTYPE consists of nested sections of the following possible types:
2837 // <!-- ... -->, <? ... ?>, "...", '...' 2901 // <!-- ... -->, <? ... ?>, "...", '...'
2838 // <![...]]> 2902 // <![...]]>
3155 3219
3156 char_t* parse_tree(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch) 3220 char_t* parse_tree(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch)
3157 { 3221 {
3158 strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk); 3222 strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk);
3159 strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk); 3223 strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk);
3160 3224
3161 char_t ch = 0; 3225 char_t ch = 0;
3162 xml_node_struct* cursor = root; 3226 xml_node_struct* cursor = root;
3163 char_t* mark = s; 3227 char_t* mark = s;
3164 3228
3165 while (*s != 0) 3229 while (*s != 0)
3186 { 3250 {
3187 LOC_ATTRIBUTES: 3251 LOC_ATTRIBUTES:
3188 while (true) 3252 while (true)
3189 { 3253 {
3190 PUGI__SKIPWS(); // Eat any whitespace. 3254 PUGI__SKIPWS(); // Eat any whitespace.
3191 3255
3192 if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #... 3256 if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #...
3193 { 3257 {
3194 xml_attribute_struct* a = append_new_attribute(cursor, alloc); // Make space for this attribute. 3258 xml_attribute_struct* a = append_new_attribute(cursor, *alloc); // Make space for this attribute.
3195 if (!a) PUGI__THROW_ERROR(status_out_of_memory, s); 3259 if (!a) PUGI__THROW_ERROR(status_out_of_memory, s);
3196 3260
3197 a->name = s; // Save the offset. 3261 a->name = s; // Save the offset.
3198 3262
3199 PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. 3263 PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator.
3204 PUGI__SKIPWS(); // Eat any whitespace. 3268 PUGI__SKIPWS(); // Eat any whitespace.
3205 3269
3206 ch = *s; 3270 ch = *s;
3207 ++s; 3271 ++s;
3208 } 3272 }
3209 3273
3210 if (ch == '=') // '<... #=...' 3274 if (ch == '=') // '<... #=...'
3211 { 3275 {
3212 PUGI__SKIPWS(); // Eat any whitespace. 3276 PUGI__SKIPWS(); // Eat any whitespace.
3213 3277
3214 if (*s == '"' || *s == '\'') // '<... #="...' 3278 if (*s == '"' || *s == '\'') // '<... #="...'
3216 ch = *s; // Save quote char to avoid breaking on "''" -or- '""'. 3280 ch = *s; // Save quote char to avoid breaking on "''" -or- '""'.
3217 ++s; // Step over the quote. 3281 ++s; // Step over the quote.
3218 a->value = s; // Save the offset. 3282 a->value = s; // Save the offset.
3219 3283
3220 s = strconv_attribute(s, ch); 3284 s = strconv_attribute(s, ch);
3221 3285
3222 if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value); 3286 if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value);
3223 3287
3224 // After this line the loop continues from the start; 3288 // After this line the loop continues from the start;
3225 // Whitespaces, / and > are ok, symbols and EOF are wrong, 3289 // Whitespaces, / and > are ok, symbols and EOF are wrong,
3226 // everything else will be detected 3290 // everything else will be detected
3231 else PUGI__THROW_ERROR(status_bad_attribute, s); 3295 else PUGI__THROW_ERROR(status_bad_attribute, s);
3232 } 3296 }
3233 else if (*s == '/') 3297 else if (*s == '/')
3234 { 3298 {
3235 ++s; 3299 ++s;
3236 3300
3237 if (*s == '>') 3301 if (*s == '>')
3238 { 3302 {
3239 PUGI__POPNODE(); 3303 PUGI__POPNODE();
3240 s++; 3304 s++;
3241 break; 3305 break;
3272 } 3336 }
3273 else if (ch == 0) 3337 else if (ch == 0)
3274 { 3338 {
3275 // we stepped over null terminator, backtrack & handle closing tag 3339 // we stepped over null terminator, backtrack & handle closing tag
3276 --s; 3340 --s;
3277 3341
3278 if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s); 3342 if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s);
3279 } 3343 }
3280 else PUGI__THROW_ERROR(status_bad_start_element, s); 3344 else PUGI__THROW_ERROR(status_bad_start_element, s);
3281 } 3345 }
3282 else if (*s == '/') 3346 else if (*s == '/')
3283 { 3347 {
3284 ++s; 3348 ++s;
3285 3349
3350 mark = s;
3351
3286 char_t* name = cursor->name; 3352 char_t* name = cursor->name;
3287 if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s); 3353 if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, mark);
3288 3354
3289 while (PUGI__IS_CHARTYPE(*s, ct_symbol)) 3355 while (PUGI__IS_CHARTYPE(*s, ct_symbol))
3290 { 3356 {
3291 if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, s); 3357 if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, mark);
3292 } 3358 }
3293 3359
3294 if (*name) 3360 if (*name)
3295 { 3361 {
3296 if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s); 3362 if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s);
3297 else PUGI__THROW_ERROR(status_end_element_mismatch, s); 3363 else PUGI__THROW_ERROR(status_end_element_mismatch, mark);
3298 } 3364 }
3299 3365
3300 PUGI__POPNODE(); // Pop. 3366 PUGI__POPNODE(); // Pop.
3301 3367
3302 PUGI__SKIPWS(); 3368 PUGI__SKIPWS();
3303 3369
3304 if (*s == 0) 3370 if (*s == 0)
3348 } 3414 }
3349 } 3415 }
3350 3416
3351 if (!PUGI__OPTSET(parse_trim_pcdata)) 3417 if (!PUGI__OPTSET(parse_trim_pcdata))
3352 s = mark; 3418 s = mark;
3353 3419
3354 if (cursor->parent || PUGI__OPTSET(parse_fragment)) 3420 if (cursor->parent || PUGI__OPTSET(parse_fragment))
3355 { 3421 {
3356 PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. 3422 if (PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value)
3357 cursor->value = s; // Save the offset. 3423 {
3424 cursor->value = s; // Save the offset.
3425 }
3426 else
3427 {
3428 PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree.
3429
3430 cursor->value = s; // Save the offset.
3431
3432 PUGI__POPNODE(); // Pop since this is a standalone.
3433 }
3358 3434
3359 s = strconv_pcdata(s); 3435 s = strconv_pcdata(s);
3360 3436
3361 PUGI__POPNODE(); // Pop since this is a standalone.
3362
3363 if (!*s) break; 3437 if (!*s) break;
3364 } 3438 }
3365 else 3439 else
3366 { 3440 {
3367 PUGI__SCANFOR(*s == '<'); // '...<' 3441 PUGI__SCANFOR(*s == '<'); // '...<'
3368 if (!*s) break; 3442 if (!*s) break;
3369 3443
3370 ++s; 3444 ++s;
3371 } 3445 }
3372 3446
3373 // We're after '<' 3447 // We're after '<'
3374 goto LOC_TAG; 3448 goto LOC_TAG;
3412 if (length == 0) 3486 if (length == 0)
3413 return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element); 3487 return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element);
3414 3488
3415 // get last child of the root before parsing 3489 // get last child of the root before parsing
3416 xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0; 3490 xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0;
3417 3491
3418 // create parser on stack 3492 // create parser on stack
3419 xml_parser parser(static_cast<xml_allocator*>(xmldoc)); 3493 xml_parser parser(static_cast<xml_allocator*>(xmldoc));
3420 3494
3421 // save last character and make buffer zero-terminated (speeds up parsing) 3495 // save last character and make buffer zero-terminated (speeds up parsing)
3422 char_t endch = buffer[length - 1]; 3496 char_t endch = buffer[length - 1];
3423 buffer[length - 1] = 0; 3497 buffer[length - 1] = 0;
3424 3498
3425 // skip BOM to make sure it does not end up as part of parse output 3499 // skip BOM to make sure it does not end up as part of parse output
3426 char_t* buffer_data = parse_skip_bom(buffer); 3500 char_t* buffer_data = parse_skip_bom(buffer);
3427 3501
3428 // perform actual parsing 3502 // perform actual parsing
3429 parser.parse_tree(buffer_data, root, optmsk, endch); 3503 parser.parse_tree(buffer_data, root, optmsk, endch);
3509 #ifdef PUGIXML_WCHAR_MODE 3583 #ifdef PUGIXML_WCHAR_MODE
3510 PUGI__FN size_t get_valid_length(const char_t* data, size_t length) 3584 PUGI__FN size_t get_valid_length(const char_t* data, size_t length)
3511 { 3585 {
3512 if (length < 1) return 0; 3586 if (length < 1) return 0;
3513 3587
3514 // discard last character if it's the lead of a surrogate pair 3588 // discard last character if it's the lead of a surrogate pair
3515 return (sizeof(wchar_t) == 2 && static_cast<unsigned int>(static_cast<uint16_t>(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; 3589 return (sizeof(wchar_t) == 2 && static_cast<unsigned int>(static_cast<uint16_t>(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length;
3516 } 3590 }
3517 3591
3518 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) 3592 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)
3519 { 3593 {
3522 { 3596 {
3523 convert_wchar_endian_swap(r_char, data, length); 3597 convert_wchar_endian_swap(r_char, data, length);
3524 3598
3525 return length * sizeof(char_t); 3599 return length * sizeof(char_t);
3526 } 3600 }
3527 3601
3528 // convert to utf8 3602 // convert to utf8
3529 if (encoding == encoding_utf8) 3603 if (encoding == encoding_utf8)
3530 return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), utf8_writer()); 3604 return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), utf8_writer());
3531 3605
3532 // convert to utf16 3606 // convert to utf16
3547 3621
3548 // convert to latin1 3622 // convert to latin1
3549 if (encoding == encoding_latin1) 3623 if (encoding == encoding_latin1)
3550 return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), latin1_writer()); 3624 return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), latin1_writer());
3551 3625
3552 assert(!"Invalid encoding"); 3626 assert(false && "Invalid encoding");
3553 return 0; 3627 return 0;
3554 } 3628 }
3555 #else 3629 #else
3556 PUGI__FN size_t get_valid_length(const char_t* data, size_t length) 3630 PUGI__FN size_t get_valid_length(const char_t* data, size_t length)
3557 { 3631 {
3586 } 3660 }
3587 3661
3588 if (encoding == encoding_latin1) 3662 if (encoding == encoding_latin1)
3589 return convert_buffer_output_generic(r_u8, data, length, utf8_decoder(), latin1_writer()); 3663 return convert_buffer_output_generic(r_u8, data, length, utf8_decoder(), latin1_writer());
3590 3664
3591 assert(!"Invalid encoding"); 3665 assert(false && "Invalid encoding");
3592 return 0; 3666 return 0;
3593 } 3667 }
3594 #endif 3668 #endif
3595 3669
3596 class xml_buffered_writer 3670 class xml_buffered_writer
3810 PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type) 3884 PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type)
3811 { 3885 {
3812 while (*s) 3886 while (*s)
3813 { 3887 {
3814 const char_t* prev = s; 3888 const char_t* prev = s;
3815 3889
3816 // While *s is a usual symbol 3890 // While *s is a usual symbol
3817 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type)); 3891 PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type));
3818 3892
3819 writer.write_buffer(prev, static_cast<size_t>(s - prev)); 3893 writer.write_buffer(prev, static_cast<size_t>(s - prev));
3820 3894
3821 switch (*s) 3895 switch (*s)
3822 { 3896 {
3823 case 0: break; 3897 case 0: break;
4000 writer.write_string(name); 4074 writer.write_string(name);
4001 4075
4002 if (node->first_attribute) 4076 if (node->first_attribute)
4003 node_output_attributes(writer, node, indent, indent_length, flags, depth); 4077 node_output_attributes(writer, node, indent, indent_length, flags, depth);
4004 4078
4005 if (!node->first_child) 4079 // element nodes can have value if parse_embed_pcdata was used
4006 { 4080 if (!node->value)
4007 writer.write(' ', '/', '>'); 4081 {
4008 4082 if (!node->first_child)
4009 return false; 4083 {
4084 if (flags & format_no_empty_element_tags)
4085 {
4086 writer.write('>', '<', '/');
4087 writer.write_string(name);
4088 writer.write('>');
4089
4090 return false;
4091 }
4092 else
4093 {
4094 if ((flags & format_raw) == 0)
4095 writer.write(' ');
4096
4097 writer.write('/', '>');
4098
4099 return false;
4100 }
4101 }
4102 else
4103 {
4104 writer.write('>');
4105
4106 return true;
4107 }
4010 } 4108 }
4011 else 4109 else
4012 { 4110 {
4013 writer.write('>'); 4111 writer.write('>');
4014 4112
4015 return true; 4113 text_output(writer, node->value, ctx_special_pcdata, flags);
4114
4115 if (!node->first_child)
4116 {
4117 writer.write('<', '/');
4118 writer.write_string(name);
4119 writer.write('>');
4120
4121 return false;
4122 }
4123 else
4124 {
4125 return true;
4126 }
4016 } 4127 }
4017 } 4128 }
4018 4129
4019 PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node) 4130 PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node)
4020 { 4131 {
4076 4187
4077 writer.write('>'); 4188 writer.write('>');
4078 break; 4189 break;
4079 4190
4080 default: 4191 default:
4081 assert(!"Invalid node type"); 4192 assert(false && "Invalid node type");
4082 } 4193 }
4083 } 4194 }
4084 4195
4085 enum indent_flags_t 4196 enum indent_flags_t
4086 { 4197 {
4118 { 4229 {
4119 indent_flags = indent_newline | indent_indent; 4230 indent_flags = indent_newline | indent_indent;
4120 4231
4121 if (node_output_start(writer, node, indent, indent_length, flags, depth)) 4232 if (node_output_start(writer, node, indent, indent_length, flags, depth))
4122 { 4233 {
4234 // element nodes can have value if parse_embed_pcdata was used
4235 if (node->value)
4236 indent_flags = 0;
4237
4123 node = node->first_child; 4238 node = node->first_child;
4124 depth++; 4239 depth++;
4125 continue; 4240 continue;
4126 } 4241 }
4127 } 4242 }
4458 { 4573 {
4459 return string_to_integer<unsigned long long>(value, 0, ULLONG_MAX); 4574 return string_to_integer<unsigned long long>(value, 0, ULLONG_MAX);
4460 } 4575 }
4461 #endif 4576 #endif
4462 4577
4463 template <typename U> 4578 template <typename U> PUGI__FN char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative)
4464 PUGI__FN char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative)
4465 { 4579 {
4466 char_t* result = end - 1; 4580 char_t* result = end - 1;
4467 U rest = negative ? 0 - value : value; 4581 U rest = negative ? 0 - value : value;
4468 4582
4469 do 4583 do
4496 #else 4610 #else
4497 return strcpy_insitu(dest, header, header_mask, buf, strlen(buf)); 4611 return strcpy_insitu(dest, header, header_mask, buf, strlen(buf));
4498 #endif 4612 #endif
4499 } 4613 }
4500 4614
4501 template <typename String, typename Header> 4615 template <typename U, typename String, typename Header>
4502 PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, int value) 4616 PUGI__FN bool set_value_integer(String& dest, Header& header, uintptr_t header_mask, U value, bool negative)
4503 { 4617 {
4504 char_t buf[64]; 4618 char_t buf[64];
4505 char_t* end = buf + sizeof(buf) / sizeof(buf[0]); 4619 char_t* end = buf + sizeof(buf) / sizeof(buf[0]);
4506 char_t* begin = integer_to_string<unsigned int>(buf, end, value, value < 0); 4620 char_t* begin = integer_to_string(buf, end, value, negative);
4507
4508 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4509 }
4510
4511 template <typename String, typename Header>
4512 PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, unsigned int value)
4513 {
4514 char_t buf[64];
4515 char_t* end = buf + sizeof(buf) / sizeof(buf[0]);
4516 char_t* begin = integer_to_string<unsigned int>(buf, end, value, false);
4517 4621
4518 return strcpy_insitu(dest, header, header_mask, begin, end - begin); 4622 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4519 } 4623 }
4520 4624
4521 template <typename String, typename Header> 4625 template <typename String, typename Header>
4533 char buf[128]; 4637 char buf[128];
4534 sprintf(buf, "%.17g", value); 4638 sprintf(buf, "%.17g", value);
4535 4639
4536 return set_value_ascii(dest, header, header_mask, buf); 4640 return set_value_ascii(dest, header, header_mask, buf);
4537 } 4641 }
4538 4642
4539 template <typename String, typename Header> 4643 template <typename String, typename Header>
4540 PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, bool value) 4644 PUGI__FN bool set_value_bool(String& dest, Header& header, uintptr_t header_mask, bool value)
4541 { 4645 {
4542 return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"), value ? 4 : 5); 4646 return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"), value ? 4 : 5);
4543 } 4647 }
4544
4545 #ifdef PUGIXML_HAS_LONG_LONG
4546 template <typename String, typename Header>
4547 PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, long long value)
4548 {
4549 char_t buf[64];
4550 char_t* end = buf + sizeof(buf) / sizeof(buf[0]);
4551 char_t* begin = integer_to_string<unsigned long long>(buf, end, value, value < 0);
4552
4553 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4554 }
4555
4556 template <typename String, typename Header>
4557 PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, unsigned long long value)
4558 {
4559 char_t buf[64];
4560 char_t* end = buf + sizeof(buf) / sizeof(buf[0]);
4561 char_t* begin = integer_to_string<unsigned long long>(buf, end, value, false);
4562
4563 return strcpy_insitu(dest, header, header_mask, begin, end - begin);
4564 }
4565 #endif
4566 4648
4567 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) 4649 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)
4568 { 4650 {
4569 // check input buffer 4651 // check input buffer
4570 if (!contents && size) return make_parse_result(status_io_error); 4652 if (!contents && size) return make_parse_result(status_io_error);
4622 fseek(file, 0, SEEK_SET); 4704 fseek(file, 0, SEEK_SET);
4623 #endif 4705 #endif
4624 4706
4625 // check for I/O errors 4707 // check for I/O errors
4626 if (length < 0) return status_io_error; 4708 if (length < 0) return status_io_error;
4627 4709
4628 // check for overflow 4710 // check for overflow
4629 size_t result = static_cast<size_t>(length); 4711 size_t result = static_cast<size_t>(length);
4630 4712
4631 if (static_cast<length_type>(result) != length) return status_out_of_memory; 4713 if (static_cast<length_type>(result) != length) return status_out_of_memory;
4632 4714
4635 4717
4636 return status_ok; 4718 return status_ok;
4637 } 4719 }
4638 4720
4639 // This function assumes that buffer has extra sizeof(char_t) writable bytes after size 4721 // This function assumes that buffer has extra sizeof(char_t) writable bytes after size
4640 PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) 4722 PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding)
4641 { 4723 {
4642 // We only need to zero-terminate if encoding conversion does not do it for us 4724 // We only need to zero-terminate if encoding conversion does not do it for us
4643 #ifdef PUGIXML_WCHAR_MODE 4725 #ifdef PUGIXML_WCHAR_MODE
4644 xml_encoding wchar_encoding = get_wchar_encoding(); 4726 xml_encoding wchar_encoding = get_wchar_encoding();
4645 4727
4667 4749
4668 // get file size (can result in I/O errors) 4750 // get file size (can result in I/O errors)
4669 size_t size = 0; 4751 size_t size = 0;
4670 xml_parse_status size_status = get_file_size(file, size); 4752 xml_parse_status size_status = get_file_size(file, size);
4671 if (size_status != status_ok) return make_parse_result(size_status); 4753 if (size_status != status_ok) return make_parse_result(size_status);
4672 4754
4673 size_t max_suffix_size = sizeof(char_t); 4755 size_t max_suffix_size = sizeof(char_t);
4674 4756
4675 // allocate buffer for the whole file 4757 // allocate buffer for the whole file
4676 char* contents = static_cast<char*>(xml_memory::allocate(size + max_suffix_size)); 4758 char* contents = static_cast<char*>(xml_memory::allocate(size + max_suffix_size));
4677 if (!contents) return make_parse_result(status_out_of_memory); 4759 if (!contents) return make_parse_result(status_out_of_memory);
4688 xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size); 4770 xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size);
4689 4771
4690 return load_buffer_impl(doc, doc, contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding, true, true, out_buffer); 4772 return load_buffer_impl(doc, doc, contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding, true, true, out_buffer);
4691 } 4773 }
4692 4774
4775 PUGI__FN void close_file(FILE* file)
4776 {
4777 fclose(file);
4778 }
4779
4693 #ifndef PUGIXML_NO_STL 4780 #ifndef PUGIXML_NO_STL
4694 template <typename T> struct xml_stream_chunk 4781 template <typename T> struct xml_stream_chunk
4695 { 4782 {
4696 static xml_stream_chunk* create() 4783 static xml_stream_chunk* create()
4697 { 4784 {
4698 void* memory = xml_memory::allocate(sizeof(xml_stream_chunk)); 4785 void* memory = xml_memory::allocate(sizeof(xml_stream_chunk));
4699 if (!memory) return 0; 4786 if (!memory) return 0;
4700 4787
4701 return new (memory) xml_stream_chunk(); 4788 return new (memory) xml_stream_chunk();
4702 } 4789 }
4703 4790
4704 static void destroy(xml_stream_chunk* chunk) 4791 static void destroy(xml_stream_chunk* chunk)
4705 { 4792 {
4805 if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; 4892 if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error;
4806 4893
4807 // return buffer 4894 // return buffer
4808 size_t actual_length = static_cast<size_t>(stream.gcount()); 4895 size_t actual_length = static_cast<size_t>(stream.gcount());
4809 assert(actual_length <= read_length); 4896 assert(actual_length <= read_length);
4810 4897
4811 *out_buffer = buffer.release(); 4898 *out_buffer = buffer.release();
4812 *out_size = actual_length * sizeof(T); 4899 *out_size = actual_length * sizeof(T);
4813 4900
4814 return status_ok; 4901 return status_ok;
4815 } 4902 }
4833 status = load_stream_data_seek(stream, &buffer, &size); 4920 status = load_stream_data_seek(stream, &buffer, &size);
4834 4921
4835 if (status != status_ok) return make_parse_result(status); 4922 if (status != status_ok) return make_parse_result(status);
4836 4923
4837 xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size); 4924 xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size);
4838 4925
4839 return load_buffer_impl(doc, doc, buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding, true, true, out_buffer); 4926 return load_buffer_impl(doc, doc, buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding, true, true, out_buffer);
4840 } 4927 }
4841 #endif 4928 #endif
4842 4929
4843 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) 4930 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)))
4953 #endif 5040 #endif
4954 5041
4955 PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0) 5042 PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0)
4956 { 5043 {
4957 } 5044 }
4958 5045
4959 PUGI__FN xml_tree_walker::~xml_tree_walker() 5046 PUGI__FN xml_tree_walker::~xml_tree_walker()
4960 { 5047 {
4961 } 5048 }
4962 5049
4963 PUGI__FN int xml_tree_walker::depth() const 5050 PUGI__FN int xml_tree_walker::depth() const
4999 5086
5000 PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const 5087 PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const
5001 { 5088 {
5002 return (_attr == r._attr); 5089 return (_attr == r._attr);
5003 } 5090 }
5004 5091
5005 PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const 5092 PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const
5006 { 5093 {
5007 return (_attr != r._attr); 5094 return (_attr != r._attr);
5008 } 5095 }
5009 5096
5010 PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const 5097 PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const
5011 { 5098 {
5012 return (_attr < r._attr); 5099 return (_attr < r._attr);
5013 } 5100 }
5014 5101
5015 PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const 5102 PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const
5016 { 5103 {
5017 return (_attr > r._attr); 5104 return (_attr > r._attr);
5018 } 5105 }
5019 5106
5020 PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const 5107 PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const
5021 { 5108 {
5022 return (_attr <= r._attr); 5109 return (_attr <= r._attr);
5023 } 5110 }
5024 5111
5025 PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const 5112 PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const
5026 { 5113 {
5027 return (_attr >= r._attr); 5114 return (_attr >= r._attr);
5028 } 5115 }
5029 5116
5107 PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs) 5194 PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs)
5108 { 5195 {
5109 set_value(rhs); 5196 set_value(rhs);
5110 return *this; 5197 return *this;
5111 } 5198 }
5112 5199
5113 PUGI__FN xml_attribute& xml_attribute::operator=(int rhs) 5200 PUGI__FN xml_attribute& xml_attribute::operator=(int rhs)
5114 { 5201 {
5115 set_value(rhs); 5202 set_value(rhs);
5116 return *this; 5203 return *this;
5117 } 5204 }
5120 { 5207 {
5121 set_value(rhs); 5208 set_value(rhs);
5122 return *this; 5209 return *this;
5123 } 5210 }
5124 5211
5125 PUGI__FN xml_attribute& xml_attribute::operator=(double rhs) 5212 PUGI__FN xml_attribute& xml_attribute::operator=(long rhs)
5126 { 5213 {
5127 set_value(rhs); 5214 set_value(rhs);
5128 return *this; 5215 return *this;
5129 } 5216 }
5130 5217
5131 PUGI__FN xml_attribute& xml_attribute::operator=(float rhs) 5218 PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long rhs)
5132 { 5219 {
5133 set_value(rhs); 5220 set_value(rhs);
5134 return *this; 5221 return *this;
5135 } 5222 }
5136 5223
5137 PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs) 5224 PUGI__FN xml_attribute& xml_attribute::operator=(double rhs)
5138 { 5225 {
5139 set_value(rhs); 5226 set_value(rhs);
5140 return *this; 5227 return *this;
5141 } 5228 }
5142 5229
5230 PUGI__FN xml_attribute& xml_attribute::operator=(float rhs)
5231 {
5232 set_value(rhs);
5233 return *this;
5234 }
5235
5236 PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs)
5237 {
5238 set_value(rhs);
5239 return *this;
5240 }
5241
5143 #ifdef PUGIXML_HAS_LONG_LONG 5242 #ifdef PUGIXML_HAS_LONG_LONG
5144 PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs) 5243 PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs)
5145 { 5244 {
5146 set_value(rhs); 5245 set_value(rhs);
5147 return *this; 5246 return *this;
5155 #endif 5254 #endif
5156 5255
5157 PUGI__FN bool xml_attribute::set_name(const char_t* rhs) 5256 PUGI__FN bool xml_attribute::set_name(const char_t* rhs)
5158 { 5257 {
5159 if (!_attr) return false; 5258 if (!_attr) return false;
5160 5259
5161 return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); 5260 return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5162 } 5261 }
5163 5262
5164 PUGI__FN bool xml_attribute::set_value(const char_t* rhs) 5263 PUGI__FN bool xml_attribute::set_value(const char_t* rhs)
5165 { 5264 {
5166 if (!_attr) return false; 5265 if (!_attr) return false;
5167 5266
5168 return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); 5267 return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs));
5170 5269
5171 PUGI__FN bool xml_attribute::set_value(int rhs) 5270 PUGI__FN bool xml_attribute::set_value(int rhs)
5172 { 5271 {
5173 if (!_attr) return false; 5272 if (!_attr) return false;
5174 5273
5274 return impl::set_value_integer<unsigned int>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5275 }
5276
5277 PUGI__FN bool xml_attribute::set_value(unsigned int rhs)
5278 {
5279 if (!_attr) return false;
5280
5281 return impl::set_value_integer<unsigned int>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false);
5282 }
5283
5284 PUGI__FN bool xml_attribute::set_value(long rhs)
5285 {
5286 if (!_attr) return false;
5287
5288 return impl::set_value_integer<unsigned long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5289 }
5290
5291 PUGI__FN bool xml_attribute::set_value(unsigned long rhs)
5292 {
5293 if (!_attr) return false;
5294
5295 return impl::set_value_integer<unsigned long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false);
5296 }
5297
5298 PUGI__FN bool xml_attribute::set_value(double rhs)
5299 {
5300 if (!_attr) return false;
5301
5175 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); 5302 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
5176 } 5303 }
5177 5304
5178 PUGI__FN bool xml_attribute::set_value(unsigned int rhs) 5305 PUGI__FN bool xml_attribute::set_value(float rhs)
5179 { 5306 {
5180 if (!_attr) return false; 5307 if (!_attr) return false;
5181 5308
5182 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); 5309 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
5183 } 5310 }
5184 5311
5185 PUGI__FN bool xml_attribute::set_value(double rhs) 5312 PUGI__FN bool xml_attribute::set_value(bool rhs)
5186 { 5313 {
5187 if (!_attr) return false; 5314 if (!_attr) return false;
5188 5315
5189 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); 5316 return impl::set_value_bool(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
5190 }
5191
5192 PUGI__FN bool xml_attribute::set_value(float rhs)
5193 {
5194 if (!_attr) return false;
5195
5196 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
5197 }
5198
5199 PUGI__FN bool xml_attribute::set_value(bool rhs)
5200 {
5201 if (!_attr) return false;
5202
5203 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs);
5204 } 5317 }
5205 5318
5206 #ifdef PUGIXML_HAS_LONG_LONG 5319 #ifdef PUGIXML_HAS_LONG_LONG
5207 PUGI__FN bool xml_attribute::set_value(long long rhs) 5320 PUGI__FN bool xml_attribute::set_value(long long rhs)
5208 { 5321 {
5209 if (!_attr) return false; 5322 if (!_attr) return false;
5210 5323
5211 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); 5324 return impl::set_value_integer<unsigned long long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0);
5212 } 5325 }
5213 5326
5214 PUGI__FN bool xml_attribute::set_value(unsigned long long rhs) 5327 PUGI__FN bool xml_attribute::set_value(unsigned long long rhs)
5215 { 5328 {
5216 if (!_attr) return false; 5329 if (!_attr) return false;
5217 5330
5218 return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); 5331 return impl::set_value_integer<unsigned long long>(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false);
5219 } 5332 }
5220 #endif 5333 #endif
5221 5334
5222 #ifdef __BORLANDC__ 5335 #ifdef __BORLANDC__
5223 PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) 5336 PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs)
5236 } 5349 }
5237 5350
5238 PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p) 5351 PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p)
5239 { 5352 {
5240 } 5353 }
5241 5354
5242 PUGI__FN static void unspecified_bool_xml_node(xml_node***) 5355 PUGI__FN static void unspecified_bool_xml_node(xml_node***)
5243 { 5356 {
5244 } 5357 }
5245 5358
5246 PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const 5359 PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const
5260 5373
5261 PUGI__FN xml_node::iterator xml_node::end() const 5374 PUGI__FN xml_node::iterator xml_node::end() const
5262 { 5375 {
5263 return iterator(0, _root); 5376 return iterator(0, _root);
5264 } 5377 }
5265 5378
5266 PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const 5379 PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const
5267 { 5380 {
5268 return attribute_iterator(_root ? _root->first_attribute + 0 : 0, _root); 5381 return attribute_iterator(_root ? _root->first_attribute + 0 : 0, _root);
5269 } 5382 }
5270 5383
5271 PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const 5384 PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const
5272 { 5385 {
5273 return attribute_iterator(0, _root); 5386 return attribute_iterator(0, _root);
5274 } 5387 }
5275 5388
5276 PUGI__FN xml_object_range<xml_node_iterator> xml_node::children() const 5389 PUGI__FN xml_object_range<xml_node_iterator> xml_node::children() const
5277 { 5390 {
5278 return xml_object_range<xml_node_iterator>(begin(), end()); 5391 return xml_object_range<xml_node_iterator>(begin(), end());
5279 } 5392 }
5280 5393
5300 5413
5301 PUGI__FN bool xml_node::operator<(const xml_node& r) const 5414 PUGI__FN bool xml_node::operator<(const xml_node& r) const
5302 { 5415 {
5303 return (_root < r._root); 5416 return (_root < r._root);
5304 } 5417 }
5305 5418
5306 PUGI__FN bool xml_node::operator>(const xml_node& r) const 5419 PUGI__FN bool xml_node::operator>(const xml_node& r) const
5307 { 5420 {
5308 return (_root > r._root); 5421 return (_root > r._root);
5309 } 5422 }
5310 5423
5311 PUGI__FN bool xml_node::operator<=(const xml_node& r) const 5424 PUGI__FN bool xml_node::operator<=(const xml_node& r) const
5312 { 5425 {
5313 return (_root <= r._root); 5426 return (_root <= r._root);
5314 } 5427 }
5315 5428
5316 PUGI__FN bool xml_node::operator>=(const xml_node& r) const 5429 PUGI__FN bool xml_node::operator>=(const xml_node& r) const
5317 { 5430 {
5318 return (_root >= r._root); 5431 return (_root >= r._root);
5319 } 5432 }
5320 5433
5321 PUGI__FN bool xml_node::empty() const 5434 PUGI__FN bool xml_node::empty() const
5322 { 5435 {
5323 return !_root; 5436 return !_root;
5324 } 5437 }
5325 5438
5326 PUGI__FN const char_t* xml_node::name() const 5439 PUGI__FN const char_t* xml_node::name() const
5327 { 5440 {
5328 return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT(""); 5441 return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT("");
5329 } 5442 }
5330 5443
5331 PUGI__FN xml_node_type xml_node::type() const 5444 PUGI__FN xml_node_type xml_node::type() const
5332 { 5445 {
5333 return _root ? PUGI__NODETYPE(_root) : node_null; 5446 return _root ? PUGI__NODETYPE(_root) : node_null;
5334 } 5447 }
5335 5448
5336 PUGI__FN const char_t* xml_node::value() const 5449 PUGI__FN const char_t* xml_node::value() const
5337 { 5450 {
5338 return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT(""); 5451 return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT("");
5339 } 5452 }
5340 5453
5341 PUGI__FN xml_node xml_node::child(const char_t* name_) const 5454 PUGI__FN xml_node xml_node::child(const char_t* name_) const
5342 { 5455 {
5343 if (!_root) return xml_node(); 5456 if (!_root) return xml_node();
5344 5457
5345 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) 5458 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
5353 if (!_root) return xml_attribute(); 5466 if (!_root) return xml_attribute();
5354 5467
5355 for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) 5468 for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
5356 if (i->name && impl::strequal(name_, i->name)) 5469 if (i->name && impl::strequal(name_, i->name))
5357 return xml_attribute(i); 5470 return xml_attribute(i);
5358 5471
5359 return xml_attribute(); 5472 return xml_attribute();
5360 } 5473 }
5361 5474
5362 PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const 5475 PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const
5363 { 5476 {
5364 if (!_root) return xml_node(); 5477 if (!_root) return xml_node();
5365 5478
5366 for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) 5479 for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
5367 if (i->name && impl::strequal(name_, i->name)) return xml_node(i); 5480 if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
5368 5481
5369 return xml_node(); 5482 return xml_node();
5370 } 5483 }
5375 } 5488 }
5376 5489
5377 PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const 5490 PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const
5378 { 5491 {
5379 if (!_root) return xml_node(); 5492 if (!_root) return xml_node();
5380 5493
5381 for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) 5494 for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
5382 if (i->name && impl::strequal(name_, i->name)) return xml_node(i); 5495 if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
5383 5496
5384 return xml_node(); 5497 return xml_node();
5385 } 5498 }
5418 } 5531 }
5419 5532
5420 PUGI__FN xml_node xml_node::previous_sibling() const 5533 PUGI__FN xml_node xml_node::previous_sibling() const
5421 { 5534 {
5422 if (!_root) return xml_node(); 5535 if (!_root) return xml_node();
5423 5536
5424 if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); 5537 if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c);
5425 else return xml_node(); 5538 else return xml_node();
5426 } 5539 }
5427 5540
5428 PUGI__FN xml_node xml_node::parent() const 5541 PUGI__FN xml_node xml_node::parent() const
5441 } 5554 }
5442 5555
5443 PUGI__FN const char_t* xml_node::child_value() const 5556 PUGI__FN const char_t* xml_node::child_value() const
5444 { 5557 {
5445 if (!_root) return PUGIXML_TEXT(""); 5558 if (!_root) return PUGIXML_TEXT("");
5446 5559
5560 // element nodes can have value if parse_embed_pcdata was used
5561 if (PUGI__NODETYPE(_root) == node_element && _root->value)
5562 return _root->value;
5563
5447 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) 5564 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
5448 if (impl::is_text_node(i) && i->value) 5565 if (impl::is_text_node(i) && i->value)
5449 return i->value; 5566 return i->value;
5450 5567
5451 return PUGIXML_TEXT(""); 5568 return PUGIXML_TEXT("");
5483 if (type_ != node_element && type_ != node_pi && type_ != node_declaration) 5600 if (type_ != node_element && type_ != node_pi && type_ != node_declaration)
5484 return false; 5601 return false;
5485 5602
5486 return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); 5603 return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
5487 } 5604 }
5488 5605
5489 PUGI__FN bool xml_node::set_value(const char_t* rhs) 5606 PUGI__FN bool xml_node::set_value(const char_t* rhs)
5490 { 5607 {
5491 xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; 5608 xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
5492 5609
5493 if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) 5610 if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype)
5497 } 5614 }
5498 5615
5499 PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) 5616 PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_)
5500 { 5617 {
5501 if (!impl::allow_insert_attribute(type())) return xml_attribute(); 5618 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5502 5619
5503 impl::xml_allocator& alloc = impl::get_allocator(_root); 5620 impl::xml_allocator& alloc = impl::get_allocator(_root);
5504 if (!alloc.reserve()) return xml_attribute(); 5621 if (!alloc.reserve()) return xml_attribute();
5505 5622
5506 xml_attribute a(impl::allocate_attribute(alloc)); 5623 xml_attribute a(impl::allocate_attribute(alloc));
5507 if (!a) return xml_attribute(); 5624 if (!a) return xml_attribute();
5508 5625
5509 impl::append_attribute(a._attr, _root); 5626 impl::append_attribute(a._attr, _root);
5510 5627
5511 a.set_name(name_); 5628 a.set_name(name_);
5512 5629
5513 return a; 5630 return a;
5514 } 5631 }
5515 5632
5516 PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) 5633 PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_)
5517 { 5634 {
5518 if (!impl::allow_insert_attribute(type())) return xml_attribute(); 5635 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5519 5636
5520 impl::xml_allocator& alloc = impl::get_allocator(_root); 5637 impl::xml_allocator& alloc = impl::get_allocator(_root);
5521 if (!alloc.reserve()) return xml_attribute(); 5638 if (!alloc.reserve()) return xml_attribute();
5522 5639
5523 xml_attribute a(impl::allocate_attribute(alloc)); 5640 xml_attribute a(impl::allocate_attribute(alloc));
5524 if (!a) return xml_attribute(); 5641 if (!a) return xml_attribute();
5532 5649
5533 PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) 5650 PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr)
5534 { 5651 {
5535 if (!impl::allow_insert_attribute(type())) return xml_attribute(); 5652 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5536 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); 5653 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
5537 5654
5538 impl::xml_allocator& alloc = impl::get_allocator(_root); 5655 impl::xml_allocator& alloc = impl::get_allocator(_root);
5539 if (!alloc.reserve()) return xml_attribute(); 5656 if (!alloc.reserve()) return xml_attribute();
5540 5657
5541 xml_attribute a(impl::allocate_attribute(alloc)); 5658 xml_attribute a(impl::allocate_attribute(alloc));
5542 if (!a) return xml_attribute(); 5659 if (!a) return xml_attribute();
5550 5667
5551 PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) 5668 PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr)
5552 { 5669 {
5553 if (!impl::allow_insert_attribute(type())) return xml_attribute(); 5670 if (!impl::allow_insert_attribute(type())) return xml_attribute();
5554 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); 5671 if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
5555 5672
5556 impl::xml_allocator& alloc = impl::get_allocator(_root); 5673 impl::xml_allocator& alloc = impl::get_allocator(_root);
5557 if (!alloc.reserve()) return xml_attribute(); 5674 if (!alloc.reserve()) return xml_attribute();
5558 5675
5559 xml_attribute a(impl::allocate_attribute(alloc)); 5676 xml_attribute a(impl::allocate_attribute(alloc));
5560 if (!a) return xml_attribute(); 5677 if (!a) return xml_attribute();
5637 } 5754 }
5638 5755
5639 PUGI__FN xml_node xml_node::append_child(xml_node_type type_) 5756 PUGI__FN xml_node xml_node::append_child(xml_node_type type_)
5640 { 5757 {
5641 if (!impl::allow_insert_child(type(), type_)) return xml_node(); 5758 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5642 5759
5643 impl::xml_allocator& alloc = impl::get_allocator(_root); 5760 impl::xml_allocator& alloc = impl::get_allocator(_root);
5644 if (!alloc.reserve()) return xml_node(); 5761 if (!alloc.reserve()) return xml_node();
5645 5762
5646 xml_node n(impl::allocate_node(alloc, type_)); 5763 xml_node n(impl::allocate_node(alloc, type_));
5647 if (!n) return xml_node(); 5764 if (!n) return xml_node();
5657 { 5774 {
5658 if (!impl::allow_insert_child(type(), type_)) return xml_node(); 5775 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5659 5776
5660 impl::xml_allocator& alloc = impl::get_allocator(_root); 5777 impl::xml_allocator& alloc = impl::get_allocator(_root);
5661 if (!alloc.reserve()) return xml_node(); 5778 if (!alloc.reserve()) return xml_node();
5662 5779
5663 xml_node n(impl::allocate_node(alloc, type_)); 5780 xml_node n(impl::allocate_node(alloc, type_));
5664 if (!n) return xml_node(); 5781 if (!n) return xml_node();
5665 5782
5666 impl::prepend_node(n._root, _root); 5783 impl::prepend_node(n._root, _root);
5667 5784
5668 if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); 5785 if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml"));
5669 5786
5670 return n; 5787 return n;
5671 } 5788 }
5672 5789
5675 if (!impl::allow_insert_child(type(), type_)) return xml_node(); 5792 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5676 if (!node._root || node._root->parent != _root) return xml_node(); 5793 if (!node._root || node._root->parent != _root) return xml_node();
5677 5794
5678 impl::xml_allocator& alloc = impl::get_allocator(_root); 5795 impl::xml_allocator& alloc = impl::get_allocator(_root);
5679 if (!alloc.reserve()) return xml_node(); 5796 if (!alloc.reserve()) return xml_node();
5680 5797
5681 xml_node n(impl::allocate_node(alloc, type_)); 5798 xml_node n(impl::allocate_node(alloc, type_));
5682 if (!n) return xml_node(); 5799 if (!n) return xml_node();
5683 5800
5684 impl::insert_node_before(n._root, node._root); 5801 impl::insert_node_before(n._root, node._root);
5685 5802
5693 if (!impl::allow_insert_child(type(), type_)) return xml_node(); 5810 if (!impl::allow_insert_child(type(), type_)) return xml_node();
5694 if (!node._root || node._root->parent != _root) return xml_node(); 5811 if (!node._root || node._root->parent != _root) return xml_node();
5695 5812
5696 impl::xml_allocator& alloc = impl::get_allocator(_root); 5813 impl::xml_allocator& alloc = impl::get_allocator(_root);
5697 if (!alloc.reserve()) return xml_node(); 5814 if (!alloc.reserve()) return xml_node();
5698 5815
5699 xml_node n(impl::allocate_node(alloc, type_)); 5816 xml_node n(impl::allocate_node(alloc, type_));
5700 if (!n) return xml_node(); 5817 if (!n) return xml_node();
5701 5818
5702 impl::insert_node_after(n._root, node._root); 5819 impl::insert_node_after(n._root, node._root);
5703 5820
5925 // get document node 6042 // get document node
5926 impl::xml_document_struct* doc = &impl::get_document(_root); 6043 impl::xml_document_struct* doc = &impl::get_document(_root);
5927 6044
5928 // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense 6045 // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense
5929 doc->header |= impl::xml_memory_page_contents_shared_mask; 6046 doc->header |= impl::xml_memory_page_contents_shared_mask;
5930 6047
5931 // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later) 6048 // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later)
5932 impl::xml_memory_page* page = 0; 6049 impl::xml_memory_page* page = 0;
5933 impl::xml_extra_buffer* extra = static_cast<impl::xml_extra_buffer*>(doc->allocate_memory(sizeof(impl::xml_extra_buffer), page)); 6050 impl::xml_extra_buffer* extra = static_cast<impl::xml_extra_buffer*>(doc->allocate_memory(sizeof(impl::xml_extra_buffer), page));
5934 (void)page; 6051 (void)page;
5935 6052
5947 } 6064 }
5948 6065
5949 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 6066 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
5950 { 6067 {
5951 if (!_root) return xml_node(); 6068 if (!_root) return xml_node();
5952 6069
5953 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) 6070 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
5954 if (i->name && impl::strequal(name_, i->name)) 6071 if (i->name && impl::strequal(name_, i->name))
5955 { 6072 {
5956 for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) 6073 for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
5957 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) 6074 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
5962 } 6079 }
5963 6080
5964 PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const 6081 PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const
5965 { 6082 {
5966 if (!_root) return xml_node(); 6083 if (!_root) return xml_node();
5967 6084
5968 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) 6085 for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
5969 for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) 6086 for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
5970 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) 6087 if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
5971 return xml_node(i); 6088 return xml_node(i);
5972 6089
6057 } 6174 }
6058 6175
6059 PUGI__FN bool xml_node::traverse(xml_tree_walker& walker) 6176 PUGI__FN bool xml_node::traverse(xml_tree_walker& walker)
6060 { 6177 {
6061 walker._depth = -1; 6178 walker._depth = -1;
6062 6179
6063 xml_node arg_begin = *this; 6180 xml_node arg_begin = *this;
6064 if (!walker.begin(arg_begin)) return false; 6181 if (!walker.begin(arg_begin)) return false;
6065 6182
6066 xml_node cur = first_child(); 6183 xml_node cur = first_child();
6067 6184
6068 if (cur) 6185 if (cur)
6069 { 6186 {
6070 ++walker._depth; 6187 ++walker._depth;
6071 6188
6072 do 6189 do
6073 { 6190 {
6074 xml_node arg_for_each = cur; 6191 xml_node arg_for_each = cur;
6075 if (!walker.for_each(arg_for_each)) 6192 if (!walker.for_each(arg_for_each))
6076 return false; 6193 return false;
6077 6194
6078 if (cur.first_child()) 6195 if (cur.first_child())
6079 { 6196 {
6080 ++walker._depth; 6197 ++walker._depth;
6081 cur = cur.first_child(); 6198 cur = cur.first_child();
6082 } 6199 }
6088 while (!cur.next_sibling() && cur != *this && !cur.parent().empty()) 6205 while (!cur.next_sibling() && cur != *this && !cur.parent().empty())
6089 { 6206 {
6090 --walker._depth; 6207 --walker._depth;
6091 cur = cur.parent(); 6208 cur = cur.parent();
6092 } 6209 }
6093 6210
6094 if (cur != *this) 6211 if (cur != *this)
6095 cur = cur.next_sibling(); 6212 cur = cur.next_sibling();
6096 } 6213 }
6097 } 6214 }
6098 while (cur && cur != *this); 6215 while (cur && cur != *this);
6189 6306
6190 PUGI__FN xml_node_struct* xml_text::_data() const 6307 PUGI__FN xml_node_struct* xml_text::_data() const
6191 { 6308 {
6192 if (!_root || impl::is_text_node(_root)) return _root; 6309 if (!_root || impl::is_text_node(_root)) return _root;
6193 6310
6311 // element nodes can have value if parse_embed_pcdata was used
6312 if (PUGI__NODETYPE(_root) == node_element && _root->value)
6313 return _root;
6314
6194 for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling) 6315 for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling)
6195 if (impl::is_text_node(node)) 6316 if (impl::is_text_node(node))
6196 return node; 6317 return node;
6197 6318
6198 return 0; 6319 return 0;
6303 6424
6304 PUGI__FN bool xml_text::set(int rhs) 6425 PUGI__FN bool xml_text::set(int rhs)
6305 { 6426 {
6306 xml_node_struct* dn = _data_new(); 6427 xml_node_struct* dn = _data_new();
6307 6428
6429 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6430 }
6431
6432 PUGI__FN bool xml_text::set(unsigned int rhs)
6433 {
6434 xml_node_struct* dn = _data_new();
6435
6436 return dn ? impl::set_value_integer<unsigned int>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false;
6437 }
6438
6439 PUGI__FN bool xml_text::set(long rhs)
6440 {
6441 xml_node_struct* dn = _data_new();
6442
6443 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6444 }
6445
6446 PUGI__FN bool xml_text::set(unsigned long rhs)
6447 {
6448 xml_node_struct* dn = _data_new();
6449
6450 return dn ? impl::set_value_integer<unsigned long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false;
6451 }
6452
6453 PUGI__FN bool xml_text::set(float rhs)
6454 {
6455 xml_node_struct* dn = _data_new();
6456
6308 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; 6457 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
6309 } 6458 }
6310 6459
6311 PUGI__FN bool xml_text::set(unsigned int rhs) 6460 PUGI__FN bool xml_text::set(double rhs)
6312 { 6461 {
6313 xml_node_struct* dn = _data_new(); 6462 xml_node_struct* dn = _data_new();
6314 6463
6315 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; 6464 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
6316 } 6465 }
6317 6466
6318 PUGI__FN bool xml_text::set(float rhs) 6467 PUGI__FN bool xml_text::set(bool rhs)
6319 { 6468 {
6320 xml_node_struct* dn = _data_new(); 6469 xml_node_struct* dn = _data_new();
6321 6470
6322 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; 6471 return dn ? impl::set_value_bool(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
6323 }
6324
6325 PUGI__FN bool xml_text::set(double rhs)
6326 {
6327 xml_node_struct* dn = _data_new();
6328
6329 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
6330 }
6331
6332 PUGI__FN bool xml_text::set(bool rhs)
6333 {
6334 xml_node_struct* dn = _data_new();
6335
6336 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false;
6337 } 6472 }
6338 6473
6339 #ifdef PUGIXML_HAS_LONG_LONG 6474 #ifdef PUGIXML_HAS_LONG_LONG
6340 PUGI__FN bool xml_text::set(long long rhs) 6475 PUGI__FN bool xml_text::set(long long rhs)
6341 { 6476 {
6342 xml_node_struct* dn = _data_new(); 6477 xml_node_struct* dn = _data_new();
6343 6478
6344 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; 6479 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false;
6345 } 6480 }
6346 6481
6347 PUGI__FN bool xml_text::set(unsigned long long rhs) 6482 PUGI__FN bool xml_text::set(unsigned long long rhs)
6348 { 6483 {
6349 xml_node_struct* dn = _data_new(); 6484 xml_node_struct* dn = _data_new();
6350 6485
6351 return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; 6486 return dn ? impl::set_value_integer<unsigned long long>(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false;
6352 } 6487 }
6353 #endif 6488 #endif
6354 6489
6355 PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) 6490 PUGI__FN xml_text& xml_text::operator=(const char_t* rhs)
6356 { 6491 {
6368 { 6503 {
6369 set(rhs); 6504 set(rhs);
6370 return *this; 6505 return *this;
6371 } 6506 }
6372 6507
6373 PUGI__FN xml_text& xml_text::operator=(double rhs) 6508 PUGI__FN xml_text& xml_text::operator=(long rhs)
6374 { 6509 {
6375 set(rhs); 6510 set(rhs);
6376 return *this; 6511 return *this;
6377 } 6512 }
6378 6513
6379 PUGI__FN xml_text& xml_text::operator=(float rhs) 6514 PUGI__FN xml_text& xml_text::operator=(unsigned long rhs)
6380 { 6515 {
6381 set(rhs); 6516 set(rhs);
6382 return *this; 6517 return *this;
6383 } 6518 }
6384 6519
6385 PUGI__FN xml_text& xml_text::operator=(bool rhs) 6520 PUGI__FN xml_text& xml_text::operator=(double rhs)
6386 { 6521 {
6387 set(rhs); 6522 set(rhs);
6388 return *this; 6523 return *this;
6389 } 6524 }
6390 6525
6526 PUGI__FN xml_text& xml_text::operator=(float rhs)
6527 {
6528 set(rhs);
6529 return *this;
6530 }
6531
6532 PUGI__FN xml_text& xml_text::operator=(bool rhs)
6533 {
6534 set(rhs);
6535 return *this;
6536 }
6537
6391 #ifdef PUGIXML_HAS_LONG_LONG 6538 #ifdef PUGIXML_HAS_LONG_LONG
6392 PUGI__FN xml_text& xml_text::operator=(long long rhs) 6539 PUGI__FN xml_text& xml_text::operator=(long long rhs)
6393 { 6540 {
6394 set(rhs); 6541 set(rhs);
6395 return *this; 6542 return *this;
6433 6580
6434 PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const 6581 PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const
6435 { 6582 {
6436 return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; 6583 return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root;
6437 } 6584 }
6438 6585
6439 PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const 6586 PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const
6440 { 6587 {
6441 return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; 6588 return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root;
6442 } 6589 }
6443 6590
6448 } 6595 }
6449 6596
6450 PUGI__FN xml_node* xml_node_iterator::operator->() const 6597 PUGI__FN xml_node* xml_node_iterator::operator->() const
6451 { 6598 {
6452 assert(_wrap._root); 6599 assert(_wrap._root);
6453 return const_cast<xml_node*>(&_wrap); // BCC32 workaround 6600 return const_cast<xml_node*>(&_wrap); // BCC5 workaround
6454 } 6601 }
6455 6602
6456 PUGI__FN const xml_node_iterator& xml_node_iterator::operator++() 6603 PUGI__FN const xml_node_iterator& xml_node_iterator::operator++()
6457 { 6604 {
6458 assert(_wrap._root); 6605 assert(_wrap._root);
6494 6641
6495 PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const 6642 PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const
6496 { 6643 {
6497 return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; 6644 return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root;
6498 } 6645 }
6499 6646
6500 PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const 6647 PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const
6501 { 6648 {
6502 return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; 6649 return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root;
6503 } 6650 }
6504 6651
6509 } 6656 }
6510 6657
6511 PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const 6658 PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const
6512 { 6659 {
6513 assert(_wrap._attr); 6660 assert(_wrap._attr);
6514 return const_cast<xml_attribute*>(&_wrap); // BCC32 workaround 6661 return const_cast<xml_attribute*>(&_wrap); // BCC5 workaround
6515 } 6662 }
6516 6663
6517 PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator++() 6664 PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator++()
6518 { 6665 {
6519 assert(_wrap._attr); 6666 assert(_wrap._attr);
6570 } 6717 }
6571 6718
6572 PUGI__FN xml_node* xml_named_node_iterator::operator->() const 6719 PUGI__FN xml_node* xml_named_node_iterator::operator->() const
6573 { 6720 {
6574 assert(_wrap._root); 6721 assert(_wrap._root);
6575 return const_cast<xml_node*>(&_wrap); // BCC32 workaround 6722 return const_cast<xml_node*>(&_wrap); // BCC5 workaround
6576 } 6723 }
6577 6724
6578 PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++() 6725 PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++()
6579 { 6726 {
6580 assert(_wrap._root); 6727 assert(_wrap._root);
6651 } 6798 }
6652 } 6799 }
6653 6800
6654 PUGI__FN xml_document::xml_document(): _buffer(0) 6801 PUGI__FN xml_document::xml_document(): _buffer(0)
6655 { 6802 {
6656 create(); 6803 _create();
6657 } 6804 }
6658 6805
6659 PUGI__FN xml_document::~xml_document() 6806 PUGI__FN xml_document::~xml_document()
6660 { 6807 {
6661 destroy(); 6808 _destroy();
6662 } 6809 }
6663 6810
6664 PUGI__FN void xml_document::reset() 6811 PUGI__FN void xml_document::reset()
6665 { 6812 {
6666 destroy(); 6813 _destroy();
6667 create(); 6814 _create();
6668 } 6815 }
6669 6816
6670 PUGI__FN void xml_document::reset(const xml_document& proto) 6817 PUGI__FN void xml_document::reset(const xml_document& proto)
6671 { 6818 {
6672 reset(); 6819 reset();
6673 6820
6674 for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling()) 6821 for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling())
6675 append_copy(cur); 6822 append_copy(cur);
6676 } 6823 }
6677 6824
6678 PUGI__FN void xml_document::create() 6825 PUGI__FN void xml_document::_create()
6679 { 6826 {
6680 assert(!_root); 6827 assert(!_root);
6681 6828
6682 #ifdef PUGIXML_COMPACT 6829 #ifdef PUGIXML_COMPACT
6683 const size_t page_offset = sizeof(uint32_t); 6830 const size_t page_offset = sizeof(uint32_t);
6684 #else 6831 #else
6685 const size_t page_offset = 0; 6832 const size_t page_offset = 0;
6686 #endif 6833 #endif
6687 6834
6688 // initialize sentinel page 6835 // initialize sentinel page
6689 PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + impl::xml_memory_page_alignment - sizeof(void*) + page_offset <= sizeof(_memory)); 6836 PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + page_offset <= sizeof(_memory));
6690
6691 // align upwards to page boundary
6692 void* page_memory = reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(_memory) + (impl::xml_memory_page_alignment - 1)) & ~(impl::xml_memory_page_alignment - 1));
6693 6837
6694 // prepare page structure 6838 // prepare page structure
6695 impl::xml_memory_page* page = impl::xml_memory_page::construct(page_memory); 6839 impl::xml_memory_page* page = impl::xml_memory_page::construct(_memory);
6696 assert(page); 6840 assert(page);
6697 6841
6698 page->busy_size = impl::xml_memory_page_size; 6842 page->busy_size = impl::xml_memory_page_size;
6699 6843
6700 // setup first page marker 6844 // setup first page marker
6709 _root->prev_sibling_c = _root; 6853 _root->prev_sibling_c = _root;
6710 6854
6711 // setup sentinel page 6855 // setup sentinel page
6712 page->allocator = static_cast<impl::xml_document_struct*>(_root); 6856 page->allocator = static_cast<impl::xml_document_struct*>(_root);
6713 6857
6858 // setup hash table pointer in allocator
6859 #ifdef PUGIXML_COMPACT
6860 page->allocator->_hash = &static_cast<impl::xml_document_struct*>(_root)->hash;
6861 #endif
6862
6714 // verify the document allocation 6863 // verify the document allocation
6715 assert(reinterpret_cast<char*>(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory)); 6864 assert(reinterpret_cast<char*>(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory));
6716 } 6865 }
6717 6866
6718 PUGI__FN void xml_document::destroy() 6867 PUGI__FN void xml_document::_destroy()
6719 { 6868 {
6720 assert(_root); 6869 assert(_root);
6721 6870
6722 // destroy static storage 6871 // destroy static storage
6723 if (_buffer) 6872 if (_buffer)
6790 PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) 6939 PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding)
6791 { 6940 {
6792 reset(); 6941 reset();
6793 6942
6794 using impl::auto_deleter; // MSVC7 workaround 6943 using impl::auto_deleter; // MSVC7 workaround
6795 auto_deleter<FILE, int(*)(FILE*)> file(fopen(path_, "rb"), fclose); 6944 auto_deleter<FILE> file(fopen(path_, "rb"), impl::close_file);
6796 6945
6797 return impl::load_file_impl(static_cast<impl::xml_document_struct*>(_root), file.data, options, encoding, &_buffer); 6946 return impl::load_file_impl(static_cast<impl::xml_document_struct*>(_root), file.data, options, encoding, &_buffer);
6798 } 6947 }
6799 6948
6800 PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) 6949 PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding)
6801 { 6950 {
6802 reset(); 6951 reset();
6803 6952
6804 using impl::auto_deleter; // MSVC7 workaround 6953 using impl::auto_deleter; // MSVC7 workaround
6805 auto_deleter<FILE, int(*)(FILE*)> file(impl::open_file_wide(path_, L"rb"), fclose); 6954 auto_deleter<FILE> file(impl::open_file_wide(path_, L"rb"), impl::close_file);
6806 6955
6807 return impl::load_file_impl(static_cast<impl::xml_document_struct*>(_root), file.data, options, encoding, &_buffer); 6956 return impl::load_file_impl(static_cast<impl::xml_document_struct*>(_root), file.data, options, encoding, &_buffer);
6808 } 6957 }
6809 6958
6810 PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) 6959 PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding)
6873 #endif 7022 #endif
6874 7023
6875 PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const 7024 PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
6876 { 7025 {
6877 using impl::auto_deleter; // MSVC7 workaround 7026 using impl::auto_deleter; // MSVC7 workaround
6878 auto_deleter<FILE, int(*)(FILE*)> file(fopen(path_, (flags & format_save_file_text) ? "w" : "wb"), fclose); 7027 auto_deleter<FILE> file(fopen(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file);
6879 7028
6880 return impl::save_file_impl(*this, file.data, indent, flags, encoding); 7029 return impl::save_file_impl(*this, file.data, indent, flags, encoding);
6881 } 7030 }
6882 7031
6883 PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const 7032 PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
6884 { 7033 {
6885 using impl::auto_deleter; // MSVC7 workaround 7034 using impl::auto_deleter; // MSVC7 workaround
6886 auto_deleter<FILE, int(*)(FILE*)> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), fclose); 7035 auto_deleter<FILE> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file);
6887 7036
6888 return impl::save_file_impl(*this, file.data, indent, flags, encoding); 7037 return impl::save_file_impl(*this, file.data, indent, flags, encoding);
6889 } 7038 }
6890 7039
6891 PUGI__FN xml_node xml_document::document_element() const 7040 PUGI__FN xml_node xml_document::document_element() const
6909 7058
6910 PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t>& str) 7059 PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t>& str)
6911 { 7060 {
6912 return impl::as_utf8_impl(str.c_str(), str.size()); 7061 return impl::as_utf8_impl(str.c_str(), str.size());
6913 } 7062 }
6914 7063
6915 PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const char* str) 7064 PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const char* str)
6916 { 7065 {
6917 assert(str); 7066 assert(str);
6918 7067
6919 return impl::as_wide_impl(str, strlen(str)); 7068 return impl::as_wide_impl(str, strlen(str));
6920 } 7069 }
6921 7070
6922 PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const std::string& str) 7071 PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const std::string& str)
6923 { 7072 {
6924 return impl::as_wide_impl(str.c_str(), str.size()); 7073 return impl::as_wide_impl(str.c_str(), str.size());
6925 } 7074 }
6926 #endif 7075 #endif
7048 while (end - begin > 1 && *begin != *(begin + 1)) begin++; 7197 while (end - begin > 1 && *begin != *(begin + 1)) begin++;
7049 7198
7050 if (begin == end) return begin; 7199 if (begin == end) return begin;
7051 7200
7052 // last written element 7201 // last written element
7053 I write = begin++; 7202 I write = begin++;
7054 7203
7055 // merge unique elements 7204 // merge unique elements
7056 while (begin != end) 7205 while (begin != end)
7057 { 7206 {
7058 if (*begin != *write) 7207 if (*begin != *write)
7223 ; 7372 ;
7224 7373
7225 static const uintptr_t xpath_memory_block_alignment = sizeof(double) > sizeof(void*) ? sizeof(double) : sizeof(void*); 7374 static const uintptr_t xpath_memory_block_alignment = sizeof(double) > sizeof(void*) ? sizeof(double) : sizeof(void*);
7226 7375
7227 struct xpath_memory_block 7376 struct xpath_memory_block
7228 { 7377 {
7229 xpath_memory_block* next; 7378 xpath_memory_block* next;
7230 size_t capacity; 7379 size_t capacity;
7231 7380
7232 union 7381 union
7233 { 7382 {
7234 char data[xpath_memory_page_size]; 7383 char data[xpath_memory_page_size];
7235 double alignment; 7384 double alignment;
7236 }; 7385 };
7237 }; 7386 };
7238 7387
7239 class xpath_allocator 7388 class xpath_allocator
7240 { 7389 {
7241 xpath_memory_block* _root; 7390 xpath_memory_block* _root;
7242 size_t _root_size; 7391 size_t _root_size;
7243 7392
7250 { 7399 {
7251 #ifdef PUGIXML_NO_EXCEPTIONS 7400 #ifdef PUGIXML_NO_EXCEPTIONS
7252 error_handler = 0; 7401 error_handler = 0;
7253 #endif 7402 #endif
7254 } 7403 }
7255 7404
7256 void* allocate_nothrow(size_t size) 7405 void* allocate_nothrow(size_t size)
7257 { 7406 {
7258 // round size up to block alignment boundary 7407 // round size up to block alignment boundary
7259 size = (size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); 7408 size = (size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1);
7260 7409
7273 7422
7274 size_t block_size = block_capacity + offsetof(xpath_memory_block, data); 7423 size_t block_size = block_capacity + offsetof(xpath_memory_block, data);
7275 7424
7276 xpath_memory_block* block = static_cast<xpath_memory_block*>(xml_memory::allocate(block_size)); 7425 xpath_memory_block* block = static_cast<xpath_memory_block*>(xml_memory::allocate(block_size));
7277 if (!block) return 0; 7426 if (!block) return 0;
7278 7427
7279 block->next = _root; 7428 block->next = _root;
7280 block->capacity = block_capacity; 7429 block->capacity = block_capacity;
7281 7430
7282 _root = block; 7431 _root = block;
7283 _root_size = size; 7432 _root_size = size;
7284 7433
7285 return block->data; 7434 return block->data;
7286 } 7435 }
7287 } 7436 }
7288 7437
7289 void* allocate(size_t size) 7438 void* allocate(size_t size)
7527 7676
7528 size_t length() const 7677 size_t length() const
7529 { 7678 {
7530 return _uses_heap ? _length_heap : strlength(_buffer); 7679 return _uses_heap ? _length_heap : strlength(_buffer);
7531 } 7680 }
7532 7681
7533 char_t* data(xpath_allocator* alloc) 7682 char_t* data(xpath_allocator* alloc)
7534 { 7683 {
7535 // make private heap copy 7684 // make private heap copy
7536 if (!_uses_heap) 7685 if (!_uses_heap)
7537 { 7686 {
7617 case node_pcdata: 7766 case node_pcdata:
7618 case node_cdata: 7767 case node_cdata:
7619 case node_comment: 7768 case node_comment:
7620 case node_pi: 7769 case node_pi:
7621 return xpath_string::from_const(n.value()); 7770 return xpath_string::from_const(n.value());
7622 7771
7623 case node_document: 7772 case node_document:
7624 case node_element: 7773 case node_element:
7625 { 7774 {
7626 xpath_string result; 7775 xpath_string result;
7627 7776
7777 // element nodes can have value if parse_embed_pcdata was used
7778 if (n.value()[0])
7779 result.append(xpath_string::from_const(n.value()), alloc);
7780
7628 xml_node cur = n.first_child(); 7781 xml_node cur = n.first_child();
7629 7782
7630 while (cur && cur != n) 7783 while (cur && cur != n)
7631 { 7784 {
7632 if (cur.type() == node_pcdata || cur.type() == node_cdata) 7785 if (cur.type() == node_pcdata || cur.type() == node_cdata)
7633 result.append(xpath_string::from_const(cur.value()), alloc); 7786 result.append(xpath_string::from_const(cur.value()), alloc);
7634 7787
7642 cur = cur.parent(); 7795 cur = cur.parent();
7643 7796
7644 if (cur != n) cur = cur.next_sibling(); 7797 if (cur != n) cur = cur.next_sibling();
7645 } 7798 }
7646 } 7799 }
7647 7800
7648 return result; 7801 return result;
7649 } 7802 }
7650 7803
7651 default: 7804 default:
7652 return xpath_string(); 7805 return xpath_string();
7653 } 7806 }
7654 } 7807 }
7655 } 7808 }
7656 7809
7657 PUGI__FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn) 7810 PUGI__FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn)
7658 { 7811 {
7659 assert(ln->parent == rn->parent); 7812 assert(ln->parent == rn->parent);
7660 7813
7661 // there is no common ancestor (the shared parent is null), nodes are from different documents 7814 // there is no common ancestor (the shared parent is null), nodes are from different documents
7675 } 7828 }
7676 7829
7677 // if rn sibling chain ended ln must be before rn 7830 // if rn sibling chain ended ln must be before rn
7678 return !rs; 7831 return !rs;
7679 } 7832 }
7680 7833
7681 PUGI__FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn) 7834 PUGI__FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn)
7682 { 7835 {
7683 // find common ancestor at the same depth, if any 7836 // find common ancestor at the same depth, if any
7684 xml_node_struct* lp = ln; 7837 xml_node_struct* lp = ln;
7685 xml_node_struct* rp = rn; 7838 xml_node_struct* rp = rn;
7756 return 0; 7909 return 0;
7757 } 7910 }
7758 7911
7759 return 0; 7912 return 0;
7760 } 7913 }
7761 7914
7762 struct document_order_comparator 7915 struct document_order_comparator
7763 { 7916 {
7764 bool operator()(const xpath_node& lhs, const xpath_node& rhs) const 7917 bool operator()(const xpath_node& lhs, const xpath_node& rhs) const
7765 { 7918 {
7766 // optimized document order based check 7919 // optimized document order based check
7780 { 7933 {
7781 // determine sibling order 7934 // determine sibling order
7782 for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute()) 7935 for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
7783 if (a == rhs.attribute()) 7936 if (a == rhs.attribute())
7784 return true; 7937 return true;
7785 7938
7786 return false; 7939 return false;
7787 } 7940 }
7788 7941
7789 // compare attribute parents 7942 // compare attribute parents
7790 ln = lhs.parent(); 7943 ln = lhs.parent();
7791 rn = rhs.parent(); 7944 rn = rhs.parent();
7792 } 7945 }
7793 else if (lhs.attribute()) 7946 else if (lhs.attribute())
7794 { 7947 {
7795 // attributes go after the parent element 7948 // attributes go after the parent element
7796 if (lhs.parent() == rhs.node()) return false; 7949 if (lhs.parent() == rhs.node()) return false;
7797 7950
7798 ln = lhs.parent(); 7951 ln = lhs.parent();
7799 } 7952 }
7800 else if (rhs.attribute()) 7953 else if (rhs.attribute())
7801 { 7954 {
7802 // attributes go after the parent element 7955 // attributes go after the parent element
7803 if (rhs.parent() == lhs.node()) return true; 7956 if (rhs.parent() == lhs.node()) return true;
7804 7957
7805 rn = rhs.parent(); 7958 rn = rhs.parent();
7806 } 7959 }
7807 7960
7808 if (ln == rn) return false; 7961 if (ln == rn) return false;
7809 7962
7810 if (!ln || !rn) return ln < rn; 7963 if (!ln || !rn) return ln < rn;
7811 7964
7812 return node_is_before(ln.internal_object(), rn.internal_object()); 7965 return node_is_before(ln.internal_object(), rn.internal_object());
7813 } 7966 }
7814 }; 7967 };
7815 7968
7816 struct duplicate_comparator 7969 struct duplicate_comparator
7819 { 7972 {
7820 if (lhs.attribute()) return rhs.attribute() ? lhs.attribute() < rhs.attribute() : true; 7973 if (lhs.attribute()) return rhs.attribute() ? lhs.attribute() < rhs.attribute() : true;
7821 else return rhs.attribute() ? false : lhs.node() < rhs.node(); 7974 else return rhs.attribute() ? false : lhs.node() < rhs.node();
7822 } 7975 }
7823 }; 7976 };
7824 7977
7825 PUGI__FN double gen_nan() 7978 PUGI__FN double gen_nan()
7826 { 7979 {
7827 #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) 7980 #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24))
7828 union { float f; uint32_t i; } u[sizeof(float) == sizeof(uint32_t) ? 1 : -1]; 7981 PUGI__STATIC_ASSERT(sizeof(float) == sizeof(uint32_t));
7829 u[0].i = 0x7fc00000; 7982 typedef uint32_t UI; // BCC5 workaround
7830 return u[0].f; 7983 union { float f; UI i; } u;
7984 u.i = 0x7fc00000;
7985 return u.f;
7831 #else 7986 #else
7832 // fallback 7987 // fallback
7833 const volatile double zero = 0.0; 7988 const volatile double zero = 0.0;
7834 return zero / zero; 7989 return zero / zero;
7835 #endif 7990 #endif
7836 } 7991 }
7837 7992
7838 PUGI__FN bool is_nan(double value) 7993 PUGI__FN bool is_nan(double value)
7839 { 7994 {
7840 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) 7995 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
7841 return !!_isnan(value); 7996 return !!_isnan(value);
7842 #elif defined(fpclassify) && defined(FP_NAN) 7997 #elif defined(fpclassify) && defined(FP_NAN)
7845 // fallback 8000 // fallback
7846 const volatile double v = value; 8001 const volatile double v = value;
7847 return v != v; 8002 return v != v;
7848 #endif 8003 #endif
7849 } 8004 }
7850 8005
7851 PUGI__FN const char_t* convert_number_to_string_special(double value) 8006 PUGI__FN const char_t* convert_number_to_string_special(double value)
7852 { 8007 {
7853 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) 8008 #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__)
7854 if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0; 8009 if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0;
7855 if (_isnan(value)) return PUGIXML_TEXT("NaN"); 8010 if (_isnan(value)) return PUGIXML_TEXT("NaN");
7877 if (v != v) return PUGIXML_TEXT("NaN"); 8032 if (v != v) return PUGIXML_TEXT("NaN");
7878 if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); 8033 if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity");
7879 return 0; 8034 return 0;
7880 #endif 8035 #endif
7881 } 8036 }
7882 8037
7883 PUGI__FN bool convert_number_to_boolean(double value) 8038 PUGI__FN bool convert_number_to_boolean(double value)
7884 { 8039 {
7885 return (value != 0 && !is_nan(value)); 8040 return (value != 0 && !is_nan(value));
7886 } 8041 }
7887 8042
7888 PUGI__FN void truncate_zeros(char* begin, char* end) 8043 PUGI__FN void truncate_zeros(char* begin, char* end)
7889 { 8044 {
7890 while (begin != end && end[-1] == '0') end--; 8045 while (begin != end && end[-1] == '0') end--;
7891 8046
7892 *end = 0; 8047 *end = 0;
8003 assert(s < result + result_size); 8158 assert(s < result + result_size);
8004 *s = 0; 8159 *s = 0;
8005 8160
8006 return xpath_string::from_heap_preallocated(result, s); 8161 return xpath_string::from_heap_preallocated(result, s);
8007 } 8162 }
8008 8163
8009 PUGI__FN bool check_string_to_number_format(const char_t* string) 8164 PUGI__FN bool check_string_to_number_format(const char_t* string)
8010 { 8165 {
8011 // parse leading whitespace 8166 // parse leading whitespace
8012 while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; 8167 while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string;
8013 8168
8070 // free dummy buffer 8225 // free dummy buffer
8071 if (scratch != buffer) xml_memory::deallocate(scratch); 8226 if (scratch != buffer) xml_memory::deallocate(scratch);
8072 8227
8073 return true; 8228 return true;
8074 } 8229 }
8075 8230
8076 PUGI__FN double round_nearest(double value) 8231 PUGI__FN double round_nearest(double value)
8077 { 8232 {
8078 return floor(value + 0.5); 8233 return floor(value + 0.5);
8079 } 8234 }
8080 8235
8082 { 8237 {
8083 // same as round_nearest, but returns -0 for [-0.5, -0] 8238 // same as round_nearest, but returns -0 for [-0.5, -0]
8084 // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0) 8239 // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0)
8085 return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5); 8240 return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5);
8086 } 8241 }
8087 8242
8088 PUGI__FN const char_t* qualified_name(const xpath_node& node) 8243 PUGI__FN const char_t* qualified_name(const xpath_node& node)
8089 { 8244 {
8090 return node.attribute() ? node.attribute().name() : node.node().name(); 8245 return node.attribute() ? node.attribute().name() : node.node().name();
8091 } 8246 }
8092 8247
8093 PUGI__FN const char_t* local_name(const xpath_node& node) 8248 PUGI__FN const char_t* local_name(const xpath_node& node)
8094 { 8249 {
8095 const char_t* name = qualified_name(node); 8250 const char_t* name = qualified_name(node);
8096 const char_t* p = find_char(name, ':'); 8251 const char_t* p = find_char(name, ':');
8097 8252
8098 return p ? p + 1 : name; 8253 return p ? p + 1 : name;
8099 } 8254 }
8100 8255
8101 struct namespace_uri_predicate 8256 struct namespace_uri_predicate
8102 { 8257 {
8122 }; 8277 };
8123 8278
8124 PUGI__FN const char_t* namespace_uri(xml_node node) 8279 PUGI__FN const char_t* namespace_uri(xml_node node)
8125 { 8280 {
8126 namespace_uri_predicate pred = node.name(); 8281 namespace_uri_predicate pred = node.name();
8127 8282
8128 xml_node p = node; 8283 xml_node p = node;
8129 8284
8130 while (p) 8285 while (p)
8131 { 8286 {
8132 xml_attribute a = p.find_attribute(pred); 8287 xml_attribute a = p.find_attribute(pred);
8133 8288
8134 if (a) return a.value(); 8289 if (a) return a.value();
8135 8290
8136 p = p.parent(); 8291 p = p.parent();
8137 } 8292 }
8138 8293
8139 return PUGIXML_TEXT(""); 8294 return PUGIXML_TEXT("");
8140 } 8295 }
8141 8296
8142 PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent) 8297 PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent)
8143 { 8298 {
8144 namespace_uri_predicate pred = attr.name(); 8299 namespace_uri_predicate pred = attr.name();
8145 8300
8146 // Default namespace does not apply to attributes 8301 // Default namespace does not apply to attributes
8147 if (!pred.prefix) return PUGIXML_TEXT(""); 8302 if (!pred.prefix) return PUGIXML_TEXT("");
8148 8303
8149 xml_node p = parent; 8304 xml_node p = parent;
8150 8305
8151 while (p) 8306 while (p)
8152 { 8307 {
8153 xml_attribute a = p.find_attribute(pred); 8308 xml_attribute a = p.find_attribute(pred);
8154 8309
8155 if (a) return a.value(); 8310 if (a) return a.value();
8156 8311
8157 p = p.parent(); 8312 p = p.parent();
8158 } 8313 }
8159 8314
8160 return PUGIXML_TEXT(""); 8315 return PUGIXML_TEXT("");
8161 } 8316 }
8162 8317
8163 PUGI__FN const char_t* namespace_uri(const xpath_node& node) 8318 PUGI__FN const char_t* namespace_uri(const xpath_node& node)
8164 { 8319 {
8340 { 8495 {
8341 result += static_cast<unsigned int>(*str++); 8496 result += static_cast<unsigned int>(*str++);
8342 result += result << 10; 8497 result += result << 10;
8343 result ^= result >> 6; 8498 result ^= result >> 6;
8344 } 8499 }
8345 8500
8346 result += result << 3; 8501 result += result << 3;
8347 result ^= result >> 11; 8502 result ^= result >> 11;
8348 result += result << 15; 8503 result += result << 15;
8349 8504
8350 return result; 8505 return result;
8351 } 8506 }
8352 8507
8353 template <typename T> PUGI__FN T* new_xpath_variable(const char_t* name) 8508 template <typename T> PUGI__FN T* new_xpath_variable(const char_t* name)
8354 { 8509 {
8412 case xpath_type_boolean: 8567 case xpath_type_boolean:
8413 delete_xpath_variable(static_cast<xpath_variable_boolean*>(var)); 8568 delete_xpath_variable(static_cast<xpath_variable_boolean*>(var));
8414 break; 8569 break;
8415 8570
8416 default: 8571 default:
8417 assert(!"Invalid variable type"); 8572 assert(false && "Invalid variable type");
8418 } 8573 }
8419 } 8574 }
8420 8575
8421 PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs) 8576 PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs)
8422 { 8577 {
8433 8588
8434 case xpath_type_boolean: 8589 case xpath_type_boolean:
8435 return lhs->set(static_cast<const xpath_variable_boolean*>(rhs)->value); 8590 return lhs->set(static_cast<const xpath_variable_boolean*>(rhs)->value);
8436 8591
8437 default: 8592 default:
8438 assert(!"Invalid variable type"); 8593 assert(false && "Invalid variable type");
8439 return false; 8594 return false;
8440 } 8595 }
8441 } 8596 }
8442 8597
8443 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) 8598 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)
8498 type = xpath_node_set::type_sorted; 8653 type = xpath_node_set::type_sorted;
8499 } 8654 }
8500 else 8655 else
8501 type = sorted; 8656 type = sorted;
8502 } 8657 }
8503 8658
8504 if (type != order) reverse(begin, end); 8659 if (type != order) reverse(begin, end);
8505 8660
8506 return order; 8661 return order;
8507 } 8662 }
8508 8663
8509 PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) 8664 PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type)
8510 { 8665 {
8520 8675
8521 case xpath_node_set::type_unsorted: 8676 case xpath_node_set::type_unsorted:
8522 return *min_element(begin, end, document_order_comparator()); 8677 return *min_element(begin, end, document_order_comparator());
8523 8678
8524 default: 8679 default:
8525 assert(!"Invalid node set type"); 8680 assert(false && "Invalid node set type");
8526 return xpath_node(); 8681 return xpath_node();
8527 } 8682 }
8528 } 8683 }
8529 8684
8530 class xpath_node_set_raw 8685 class xpath_node_set_raw
8613 8768
8614 void remove_duplicates() 8769 void remove_duplicates()
8615 { 8770 {
8616 if (_type == xpath_node_set::type_unsorted) 8771 if (_type == xpath_node_set::type_unsorted)
8617 sort(_begin, _end, duplicate_comparator()); 8772 sort(_begin, _end, duplicate_comparator());
8618 8773
8619 _end = unique(_begin, _end); 8774 _end = unique(_begin, _end);
8620 } 8775 }
8621 8776
8622 xpath_node_set::type_t type() const 8777 xpath_node_set::type_t type() const
8623 { 8778 {
8721 public: 8876 public:
8722 explicit xpath_lexer(const char_t* query): _cur(query) 8877 explicit xpath_lexer(const char_t* query): _cur(query)
8723 { 8878 {
8724 next(); 8879 next();
8725 } 8880 }
8726 8881
8727 const char_t* state() const 8882 const char_t* state() const
8728 { 8883 {
8729 return _cur; 8884 return _cur;
8730 } 8885 }
8731 8886
8732 void next() 8887 void next()
8733 { 8888 {
8734 const char_t* cur = _cur; 8889 const char_t* cur = _cur;
8735 8890
8736 while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur; 8891 while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur;
8741 switch (*cur) 8896 switch (*cur)
8742 { 8897 {
8743 case 0: 8898 case 0:
8744 _cur_lexeme = lex_eof; 8899 _cur_lexeme = lex_eof;
8745 break; 8900 break;
8746 8901
8747 case '>': 8902 case '>':
8748 if (*(cur+1) == '=') 8903 if (*(cur+1) == '=')
8749 { 8904 {
8750 cur += 2; 8905 cur += 2;
8751 _cur_lexeme = lex_greater_or_equal; 8906 _cur_lexeme = lex_greater_or_equal;
8785 case '=': 8940 case '=':
8786 cur += 1; 8941 cur += 1;
8787 _cur_lexeme = lex_equal; 8942 _cur_lexeme = lex_equal;
8788 8943
8789 break; 8944 break;
8790 8945
8791 case '+': 8946 case '+':
8792 cur += 1; 8947 cur += 1;
8793 _cur_lexeme = lex_plus; 8948 _cur_lexeme = lex_plus;
8794 8949
8795 break; 8950 break;
8809 case '|': 8964 case '|':
8810 cur += 1; 8965 cur += 1;
8811 _cur_lexeme = lex_union; 8966 _cur_lexeme = lex_union;
8812 8967
8813 break; 8968 break;
8814 8969
8815 case '$': 8970 case '$':
8816 cur += 1; 8971 cur += 1;
8817 8972
8818 if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) 8973 if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol))
8819 { 8974 {
8827 8982
8828 while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; 8983 while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++;
8829 } 8984 }
8830 8985
8831 _cur_lexeme_contents.end = cur; 8986 _cur_lexeme_contents.end = cur;
8832 8987
8833 _cur_lexeme = lex_var_ref; 8988 _cur_lexeme = lex_var_ref;
8834 } 8989 }
8835 else 8990 else
8836 { 8991 {
8837 _cur_lexeme = lex_none; 8992 _cur_lexeme = lex_none;
8848 case ')': 9003 case ')':
8849 cur += 1; 9004 cur += 1;
8850 _cur_lexeme = lex_close_brace; 9005 _cur_lexeme = lex_close_brace;
8851 9006
8852 break; 9007 break;
8853 9008
8854 case '[': 9009 case '[':
8855 cur += 1; 9010 cur += 1;
8856 _cur_lexeme = lex_open_square_brace; 9011 _cur_lexeme = lex_open_square_brace;
8857 9012
8858 break; 9013 break;
8879 { 9034 {
8880 cur += 1; 9035 cur += 1;
8881 _cur_lexeme = lex_slash; 9036 _cur_lexeme = lex_slash;
8882 } 9037 }
8883 break; 9038 break;
8884 9039
8885 case '.': 9040 case '.':
8886 if (*(cur+1) == '.') 9041 if (*(cur+1) == '.')
8887 { 9042 {
8888 cur += 2; 9043 cur += 2;
8889 _cur_lexeme = lex_double_dot; 9044 _cur_lexeme = lex_double_dot;
8895 ++cur; 9050 ++cur;
8896 9051
8897 while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; 9052 while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++;
8898 9053
8899 _cur_lexeme_contents.end = cur; 9054 _cur_lexeme_contents.end = cur;
8900 9055
8901 _cur_lexeme = lex_number; 9056 _cur_lexeme = lex_number;
8902 } 9057 }
8903 else 9058 else
8904 { 9059 {
8905 cur += 1; 9060 cur += 1;
8921 ++cur; 9076 ++cur;
8922 9077
8923 _cur_lexeme_contents.begin = cur; 9078 _cur_lexeme_contents.begin = cur;
8924 while (*cur && *cur != terminator) cur++; 9079 while (*cur && *cur != terminator) cur++;
8925 _cur_lexeme_contents.end = cur; 9080 _cur_lexeme_contents.end = cur;
8926 9081
8927 if (!*cur) 9082 if (!*cur)
8928 _cur_lexeme = lex_none; 9083 _cur_lexeme = lex_none;
8929 else 9084 else
8930 { 9085 {
8931 cur += 1; 9086 cur += 1;
8951 if (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) 9106 if (PUGI__IS_CHARTYPEX(*cur, ctx_digit))
8952 { 9107 {
8953 _cur_lexeme_contents.begin = cur; 9108 _cur_lexeme_contents.begin = cur;
8954 9109
8955 while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; 9110 while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++;
8956 9111
8957 if (*cur == '.') 9112 if (*cur == '.')
8958 { 9113 {
8959 cur++; 9114 cur++;
8960 9115
8961 while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; 9116 while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++;
8984 while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; 9139 while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++;
8985 } 9140 }
8986 } 9141 }
8987 9142
8988 _cur_lexeme_contents.end = cur; 9143 _cur_lexeme_contents.end = cur;
8989 9144
8990 _cur_lexeme = lex_string; 9145 _cur_lexeme = lex_string;
8991 } 9146 }
8992 else 9147 else
8993 { 9148 {
8994 _cur_lexeme = lex_none; 9149 _cur_lexeme = lex_none;
9095 axis_parent, 9250 axis_parent,
9096 axis_preceding, 9251 axis_preceding,
9097 axis_preceding_sibling, 9252 axis_preceding_sibling,
9098 axis_self 9253 axis_self
9099 }; 9254 };
9100 9255
9101 enum nodetest_t 9256 enum nodetest_t
9102 { 9257 {
9103 nodetest_none, 9258 nodetest_none,
9104 nodetest_name, 9259 nodetest_name,
9105 nodetest_type_node, 9260 nodetest_type_node,
9130 { 9285 {
9131 static const axis_t axis; 9286 static const axis_t axis;
9132 }; 9287 };
9133 9288
9134 template <axis_t N> const axis_t axis_to_type<N>::axis = N; 9289 template <axis_t N> const axis_t axis_to_type<N>::axis = N;
9135 9290
9136 class xpath_ast_node 9291 class xpath_ast_node
9137 { 9292 {
9138 private: 9293 private:
9139 // node type 9294 // node type
9140 char _type; 9295 char _type;
9250 9405
9251 return false; 9406 return false;
9252 } 9407 }
9253 } 9408 }
9254 9409
9255 assert(!"Wrong types"); 9410 assert(false && "Wrong types");
9256 return false; 9411 return false;
9257 } 9412 }
9258 9413
9259 static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval) 9414 static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval)
9260 { 9415 {
9325 9480
9326 return false; 9481 return false;
9327 } 9482 }
9328 else 9483 else
9329 { 9484 {
9330 assert(!"Wrong types"); 9485 assert(false && "Wrong types");
9331 return false; 9486 return false;
9332 } 9487 }
9333 } 9488 }
9334 9489
9335 static void apply_predicate_boolean(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once) 9490 static void apply_predicate_boolean(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once)
9449 { 9604 {
9450 ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); 9605 ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9451 return true; 9606 return true;
9452 } 9607 }
9453 break; 9608 break;
9454 9609
9455 case nodetest_type_node: 9610 case nodetest_type_node:
9456 case nodetest_all: 9611 case nodetest_all:
9457 if (is_xpath_attribute(name)) 9612 if (is_xpath_attribute(name))
9458 { 9613 {
9459 ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); 9614 ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9460 return true; 9615 return true;
9461 } 9616 }
9462 break; 9617 break;
9463 9618
9464 case nodetest_all_in_namespace: 9619 case nodetest_all_in_namespace:
9465 if (starts_with(name, _data.nodetest) && is_xpath_attribute(name)) 9620 if (starts_with(name, _data.nodetest) && is_xpath_attribute(name))
9466 { 9621 {
9467 ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); 9622 ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc);
9468 return true; 9623 return true;
9469 } 9624 }
9470 break; 9625 break;
9471 9626
9472 default: 9627 default:
9473 ; 9628 ;
9474 } 9629 }
9475 9630
9476 return false; 9631 return false;
9477 } 9632 }
9478 9633
9479 bool step_push(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc) 9634 bool step_push(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc)
9480 { 9635 {
9481 assert(n); 9636 assert(n);
9482 9637
9483 xml_node_type type = PUGI__NODETYPE(n); 9638 xml_node_type type = PUGI__NODETYPE(n);
9489 { 9644 {
9490 ns.push_back(xml_node(n), alloc); 9645 ns.push_back(xml_node(n), alloc);
9491 return true; 9646 return true;
9492 } 9647 }
9493 break; 9648 break;
9494 9649
9495 case nodetest_type_node: 9650 case nodetest_type_node:
9496 ns.push_back(xml_node(n), alloc); 9651 ns.push_back(xml_node(n), alloc);
9497 return true; 9652 return true;
9498 9653
9499 case nodetest_type_comment: 9654 case nodetest_type_comment:
9500 if (type == node_comment) 9655 if (type == node_comment)
9501 { 9656 {
9502 ns.push_back(xml_node(n), alloc); 9657 ns.push_back(xml_node(n), alloc);
9503 return true; 9658 return true;
9504 } 9659 }
9505 break; 9660 break;
9506 9661
9507 case nodetest_type_text: 9662 case nodetest_type_text:
9508 if (type == node_pcdata || type == node_cdata) 9663 if (type == node_pcdata || type == node_cdata)
9509 { 9664 {
9510 ns.push_back(xml_node(n), alloc); 9665 ns.push_back(xml_node(n), alloc);
9511 return true; 9666 return true;
9512 } 9667 }
9513 break; 9668 break;
9514 9669
9515 case nodetest_type_pi: 9670 case nodetest_type_pi:
9516 if (type == node_pi) 9671 if (type == node_pi)
9517 { 9672 {
9518 ns.push_back(xml_node(n), alloc); 9673 ns.push_back(xml_node(n), alloc);
9519 return true; 9674 return true;
9520 } 9675 }
9521 break; 9676 break;
9522 9677
9523 case nodetest_pi: 9678 case nodetest_pi:
9524 if (type == node_pi && n->name && strequal(n->name, _data.nodetest)) 9679 if (type == node_pi && n->name && strequal(n->name, _data.nodetest))
9525 { 9680 {
9526 ns.push_back(xml_node(n), alloc); 9681 ns.push_back(xml_node(n), alloc);
9527 return true; 9682 return true;
9528 } 9683 }
9529 break; 9684 break;
9530 9685
9531 case nodetest_all: 9686 case nodetest_all:
9532 if (type == node_element) 9687 if (type == node_element)
9533 { 9688 {
9534 ns.push_back(xml_node(n), alloc); 9689 ns.push_back(xml_node(n), alloc);
9535 return true; 9690 return true;
9536 } 9691 }
9537 break; 9692 break;
9538 9693
9539 case nodetest_all_in_namespace: 9694 case nodetest_all_in_namespace:
9540 if (type == node_element && n->name && starts_with(n->name, _data.nodetest)) 9695 if (type == node_element && n->name && starts_with(n->name, _data.nodetest))
9541 { 9696 {
9542 ns.push_back(xml_node(n), alloc); 9697 ns.push_back(xml_node(n), alloc);
9543 return true; 9698 return true;
9544 } 9699 }
9545 break; 9700 break;
9546 9701
9547 default: 9702 default:
9548 assert(!"Unknown axis"); 9703 assert(false && "Unknown axis");
9549 } 9704 }
9550 9705
9551 return false; 9706 return false;
9552 } 9707 }
9553 9708
9560 case axis_attribute: 9715 case axis_attribute:
9561 { 9716 {
9562 for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute) 9717 for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute)
9563 if (step_push(ns, a, n, alloc) & once) 9718 if (step_push(ns, a, n, alloc) & once)
9564 return; 9719 return;
9565 9720
9566 break; 9721 break;
9567 } 9722 }
9568 9723
9569 case axis_child: 9724 case axis_child:
9570 { 9725 {
9571 for (xml_node_struct* c = n->first_child; c; c = c->next_sibling) 9726 for (xml_node_struct* c = n->first_child; c; c = c->next_sibling)
9572 if (step_push(ns, c, alloc) & once) 9727 if (step_push(ns, c, alloc) & once)
9573 return; 9728 return;
9574 9729
9575 break; 9730 break;
9576 } 9731 }
9577 9732
9578 case axis_descendant: 9733 case axis_descendant:
9579 case axis_descendant_or_self: 9734 case axis_descendant_or_self:
9580 { 9735 {
9581 if (axis == axis_descendant_or_self) 9736 if (axis == axis_descendant_or_self)
9582 if (step_push(ns, n, alloc) & once) 9737 if (step_push(ns, n, alloc) & once)
9583 return; 9738 return;
9584 9739
9585 xml_node_struct* cur = n->first_child; 9740 xml_node_struct* cur = n->first_child;
9586 9741
9587 while (cur) 9742 while (cur)
9588 { 9743 {
9589 if (step_push(ns, cur, alloc) & once) 9744 if (step_push(ns, cur, alloc) & once)
9590 return; 9745 return;
9591 9746
9592 if (cur->first_child) 9747 if (cur->first_child)
9593 cur = cur->first_child; 9748 cur = cur->first_child;
9594 else 9749 else
9595 { 9750 {
9596 while (!cur->next_sibling) 9751 while (!cur->next_sibling)
9597 { 9752 {
9598 cur = cur->parent; 9753 cur = cur->parent;
9599 9754
9600 if (cur == n) return; 9755 if (cur == n) return;
9601 } 9756 }
9602 9757
9603 cur = cur->next_sibling; 9758 cur = cur->next_sibling;
9604 } 9759 }
9605 } 9760 }
9606 9761
9607 break; 9762 break;
9608 } 9763 }
9609 9764
9610 case axis_following_sibling: 9765 case axis_following_sibling:
9611 { 9766 {
9612 for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling) 9767 for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling)
9613 if (step_push(ns, c, alloc) & once) 9768 if (step_push(ns, c, alloc) & once)
9614 return; 9769 return;
9615 9770
9616 break; 9771 break;
9617 } 9772 }
9618 9773
9619 case axis_preceding_sibling: 9774 case axis_preceding_sibling:
9620 { 9775 {
9621 for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c) 9776 for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c)
9622 if (step_push(ns, c, alloc) & once) 9777 if (step_push(ns, c, alloc) & once)
9623 return; 9778 return;
9624 9779
9625 break; 9780 break;
9626 } 9781 }
9627 9782
9628 case axis_following: 9783 case axis_following:
9629 { 9784 {
9630 xml_node_struct* cur = n; 9785 xml_node_struct* cur = n;
9631 9786
9632 // exit from this node so that we don't include descendants 9787 // exit from this node so that we don't include descendants
9701 } 9856 }
9702 } 9857 }
9703 9858
9704 break; 9859 break;
9705 } 9860 }
9706 9861
9707 case axis_ancestor: 9862 case axis_ancestor:
9708 case axis_ancestor_or_self: 9863 case axis_ancestor_or_self:
9709 { 9864 {
9710 if (axis == axis_ancestor_or_self) 9865 if (axis == axis_ancestor_or_self)
9711 if (step_push(ns, n, alloc) & once) 9866 if (step_push(ns, n, alloc) & once)
9712 return; 9867 return;
9713 9868
9714 xml_node_struct* cur = n->parent; 9869 xml_node_struct* cur = n->parent;
9715 9870
9716 while (cur) 9871 while (cur)
9717 { 9872 {
9718 if (step_push(ns, cur, alloc) & once) 9873 if (step_push(ns, cur, alloc) & once)
9719 return; 9874 return;
9720 9875
9721 cur = cur->parent; 9876 cur = cur->parent;
9722 } 9877 }
9723 9878
9724 break; 9879 break;
9725 } 9880 }
9726 9881
9727 case axis_self: 9882 case axis_self:
9728 { 9883 {
9736 if (n->parent) 9891 if (n->parent)
9737 step_push(ns, n->parent, alloc); 9892 step_push(ns, n->parent, alloc);
9738 9893
9739 break; 9894 break;
9740 } 9895 }
9741 9896
9742 default: 9897 default:
9743 assert(!"Unimplemented axis"); 9898 assert(false && "Unimplemented axis");
9744 } 9899 }
9745 } 9900 }
9746 9901
9747 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) 9902 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)
9748 { 9903 {
9749 const axis_t axis = T::axis; 9904 const axis_t axis = T::axis;
9750 9905
9751 switch (axis) 9906 switch (axis)
9756 if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test 9911 if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test
9757 if (step_push(ns, a, p, alloc) & once) 9912 if (step_push(ns, a, p, alloc) & once)
9758 return; 9913 return;
9759 9914
9760 xml_node_struct* cur = p; 9915 xml_node_struct* cur = p;
9761 9916
9762 while (cur) 9917 while (cur)
9763 { 9918 {
9764 if (step_push(ns, cur, alloc) & once) 9919 if (step_push(ns, cur, alloc) & once)
9765 return; 9920 return;
9766 9921
9767 cur = cur->parent; 9922 cur = cur->parent;
9768 } 9923 }
9769 9924
9770 break; 9925 break;
9771 } 9926 }
9772 9927
9773 case axis_descendant_or_self: 9928 case axis_descendant_or_self:
9774 case axis_self: 9929 case axis_self:
9780 } 9935 }
9781 9936
9782 case axis_following: 9937 case axis_following:
9783 { 9938 {
9784 xml_node_struct* cur = p; 9939 xml_node_struct* cur = p;
9785 9940
9786 while (cur) 9941 while (cur)
9787 { 9942 {
9788 if (cur->first_child) 9943 if (cur->first_child)
9789 cur = cur->first_child; 9944 cur = cur->first_child;
9790 else 9945 else
9817 { 9972 {
9818 // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding 9973 // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding
9819 step_fill(ns, p, alloc, once, v); 9974 step_fill(ns, p, alloc, once, v);
9820 break; 9975 break;
9821 } 9976 }
9822 9977
9823 default: 9978 default:
9824 assert(!"Unimplemented axis"); 9979 assert(false && "Unimplemented axis");
9825 } 9980 }
9826 } 9981 }
9827 9982
9828 template <class T> void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v) 9983 template <class T> void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v)
9829 { 9984 {
9861 { 10016 {
9862 size_t size = ns.size(); 10017 size_t size = ns.size();
9863 10018
9864 // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes 10019 // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes
9865 if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted); 10020 if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted);
9866 10021
9867 step_fill(ns, *it, stack.result, once, v); 10022 step_fill(ns, *it, stack.result, once, v);
9868 if (_right) apply_predicates(ns, size, stack, eval); 10023 if (_right) apply_predicates(ns, size, stack, eval);
9869 } 10024 }
9870 } 10025 }
9871 else 10026 else
9879 if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted) 10034 if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted)
9880 ns.remove_duplicates(); 10035 ns.remove_duplicates();
9881 10036
9882 return ns; 10037 return ns;
9883 } 10038 }
9884 10039
9885 public: 10040 public:
9886 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value): 10041 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value):
9887 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) 10042 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
9888 { 10043 {
9889 assert(type == ast_string_constant); 10044 assert(type == ast_string_constant);
9894 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) 10049 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
9895 { 10050 {
9896 assert(type == ast_number_constant); 10051 assert(type == ast_number_constant);
9897 _data.number = value; 10052 _data.number = value;
9898 } 10053 }
9899 10054
9900 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value): 10055 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value):
9901 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) 10056 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
9902 { 10057 {
9903 assert(type == ast_variable); 10058 assert(type == ast_variable);
9904 _data.variable = value; 10059 _data.variable = value;
9905 } 10060 }
9906 10061
9907 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0): 10062 xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0):
9908 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0) 10063 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0)
9909 { 10064 {
9910 } 10065 }
9911 10066
9936 { 10091 {
9937 switch (_type) 10092 switch (_type)
9938 { 10093 {
9939 case ast_op_or: 10094 case ast_op_or:
9940 return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack); 10095 return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack);
9941 10096
9942 case ast_op_and: 10097 case ast_op_and:
9943 return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack); 10098 return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack);
9944 10099
9945 case ast_op_equal: 10100 case ast_op_equal:
9946 return compare_eq(_left, _right, c, stack, equal_to()); 10101 return compare_eq(_left, _right, c, stack, equal_to());
9947 10102
9948 case ast_op_not_equal: 10103 case ast_op_not_equal:
9949 return compare_eq(_left, _right, c, stack, not_equal_to()); 10104 return compare_eq(_left, _right, c, stack, not_equal_to());
9950 10105
9951 case ast_op_less: 10106 case ast_op_less:
9952 return compare_rel(_left, _right, c, stack, less()); 10107 return compare_rel(_left, _right, c, stack, less());
9953 10108
9954 case ast_op_greater: 10109 case ast_op_greater:
9955 return compare_rel(_right, _left, c, stack, less()); 10110 return compare_rel(_right, _left, c, stack, less());
9956 10111
9957 case ast_op_less_or_equal: 10112 case ast_op_less_or_equal:
9958 return compare_rel(_left, _right, c, stack, less_equal()); 10113 return compare_rel(_left, _right, c, stack, less_equal());
9959 10114
9960 case ast_op_greater_or_equal: 10115 case ast_op_greater_or_equal:
9961 return compare_rel(_right, _left, c, stack, less_equal()); 10116 return compare_rel(_right, _left, c, stack, less_equal());
9962 10117
9963 case ast_func_starts_with: 10118 case ast_func_starts_with:
9964 { 10119 {
9980 return find_substring(lr.c_str(), rr.c_str()) != 0; 10135 return find_substring(lr.c_str(), rr.c_str()) != 0;
9981 } 10136 }
9982 10137
9983 case ast_func_boolean: 10138 case ast_func_boolean:
9984 return _left->eval_boolean(c, stack); 10139 return _left->eval_boolean(c, stack);
9985 10140
9986 case ast_func_not: 10141 case ast_func_not:
9987 return !_left->eval_boolean(c, stack); 10142 return !_left->eval_boolean(c, stack);
9988 10143
9989 case ast_func_true: 10144 case ast_func_true:
9990 return true; 10145 return true;
9991 10146
9992 case ast_func_false: 10147 case ast_func_false:
9993 return false; 10148 return false;
9994 10149
9995 case ast_func_lang: 10150 case ast_func_lang:
9996 { 10151 {
9997 if (c.n.attribute()) return false; 10152 if (c.n.attribute()) return false;
9998 10153
9999 xpath_allocator_capture cr(stack.result); 10154 xpath_allocator_capture cr(stack.result);
10000 10155
10001 xpath_string lang = _left->eval_string(c, stack); 10156 xpath_string lang = _left->eval_string(c, stack);
10002 10157
10003 for (xml_node n = c.n.node(); n; n = n.parent()) 10158 for (xml_node n = c.n.node(); n; n = n.parent())
10004 { 10159 {
10005 xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang")); 10160 xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang"));
10006 10161
10007 if (a) 10162 if (a)
10008 { 10163 {
10009 const char_t* value = a.value(); 10164 const char_t* value = a.value();
10010 10165
10011 // strnicmp / strncasecmp is not portable 10166 // strnicmp / strncasecmp is not portable
10012 for (const char_t* lit = lang.c_str(); *lit; ++lit) 10167 for (const char_t* lit = lang.c_str(); *lit; ++lit)
10013 { 10168 {
10014 if (tolower_ascii(*lit) != tolower_ascii(*value)) return false; 10169 if (tolower_ascii(*lit) != tolower_ascii(*value)) return false;
10015 ++value; 10170 ++value;
10016 } 10171 }
10017 10172
10018 return *value == 0 || *value == '-'; 10173 return *value == 0 || *value == '-';
10019 } 10174 }
10020 } 10175 }
10021 10176
10022 return false; 10177 return false;
10023 } 10178 }
10024 10179
10025 case ast_opt_compare_attribute: 10180 case ast_opt_compare_attribute:
10026 { 10181 {
10045 { 10200 {
10046 switch (_rettype) 10201 switch (_rettype)
10047 { 10202 {
10048 case xpath_type_number: 10203 case xpath_type_number:
10049 return convert_number_to_boolean(eval_number(c, stack)); 10204 return convert_number_to_boolean(eval_number(c, stack));
10050 10205
10051 case xpath_type_string: 10206 case xpath_type_string:
10052 { 10207 {
10053 xpath_allocator_capture cr(stack.result); 10208 xpath_allocator_capture cr(stack.result);
10054 10209
10055 return !eval_string(c, stack).empty(); 10210 return !eval_string(c, stack).empty();
10056 } 10211 }
10057 10212
10058 case xpath_type_node_set: 10213 case xpath_type_node_set:
10059 { 10214 {
10060 xpath_allocator_capture cr(stack.result); 10215 xpath_allocator_capture cr(stack.result);
10061 10216
10062 return !eval_node_set(c, stack, nodeset_eval_any).empty(); 10217 return !eval_node_set(c, stack, nodeset_eval_any).empty();
10063 } 10218 }
10064 10219
10065 default: 10220 default:
10066 assert(!"Wrong expression for return type boolean"); 10221 assert(false && "Wrong expression for return type boolean");
10067 return false; 10222 return false;
10068 } 10223 }
10069 } 10224 }
10070 } 10225 }
10071 } 10226 }
10074 { 10229 {
10075 switch (_type) 10230 switch (_type)
10076 { 10231 {
10077 case ast_op_add: 10232 case ast_op_add:
10078 return _left->eval_number(c, stack) + _right->eval_number(c, stack); 10233 return _left->eval_number(c, stack) + _right->eval_number(c, stack);
10079 10234
10080 case ast_op_subtract: 10235 case ast_op_subtract:
10081 return _left->eval_number(c, stack) - _right->eval_number(c, stack); 10236 return _left->eval_number(c, stack) - _right->eval_number(c, stack);
10082 10237
10083 case ast_op_multiply: 10238 case ast_op_multiply:
10084 return _left->eval_number(c, stack) * _right->eval_number(c, stack); 10239 return _left->eval_number(c, stack) * _right->eval_number(c, stack);
10095 case ast_number_constant: 10250 case ast_number_constant:
10096 return _data.number; 10251 return _data.number;
10097 10252
10098 case ast_func_last: 10253 case ast_func_last:
10099 return static_cast<double>(c.size); 10254 return static_cast<double>(c.size);
10100 10255
10101 case ast_func_position: 10256 case ast_func_position:
10102 return static_cast<double>(c.position); 10257 return static_cast<double>(c.position);
10103 10258
10104 case ast_func_count: 10259 case ast_func_count:
10105 { 10260 {
10106 xpath_allocator_capture cr(stack.result); 10261 xpath_allocator_capture cr(stack.result);
10107 10262
10108 return static_cast<double>(_left->eval_node_set(c, stack, nodeset_eval_all).size()); 10263 return static_cast<double>(_left->eval_node_set(c, stack, nodeset_eval_all).size());
10109 } 10264 }
10110 10265
10111 case ast_func_string_length_0: 10266 case ast_func_string_length_0:
10112 { 10267 {
10113 xpath_allocator_capture cr(stack.result); 10268 xpath_allocator_capture cr(stack.result);
10114 10269
10115 return static_cast<double>(string_value(c.n, stack.result).length()); 10270 return static_cast<double>(string_value(c.n, stack.result).length());
10116 } 10271 }
10117 10272
10118 case ast_func_string_length_1: 10273 case ast_func_string_length_1:
10119 { 10274 {
10120 xpath_allocator_capture cr(stack.result); 10275 xpath_allocator_capture cr(stack.result);
10121 10276
10122 return static_cast<double>(_left->eval_string(c, stack).length()); 10277 return static_cast<double>(_left->eval_string(c, stack).length());
10123 } 10278 }
10124 10279
10125 case ast_func_number_0: 10280 case ast_func_number_0:
10126 { 10281 {
10127 xpath_allocator_capture cr(stack.result); 10282 xpath_allocator_capture cr(stack.result);
10128 10283
10129 return convert_string_to_number(string_value(c.n, stack.result).c_str()); 10284 return convert_string_to_number(string_value(c.n, stack.result).c_str());
10130 } 10285 }
10131 10286
10132 case ast_func_number_1: 10287 case ast_func_number_1:
10133 return _left->eval_number(c, stack); 10288 return _left->eval_number(c, stack);
10134 10289
10135 case ast_func_sum: 10290 case ast_func_sum:
10136 { 10291 {
10137 xpath_allocator_capture cr(stack.result); 10292 xpath_allocator_capture cr(stack.result);
10138 10293
10139 double r = 0; 10294 double r = 0;
10140 10295
10141 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_all); 10296 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_all);
10142 10297
10143 for (const xpath_node* it = ns.begin(); it != ns.end(); ++it) 10298 for (const xpath_node* it = ns.begin(); it != ns.end(); ++it)
10144 { 10299 {
10145 xpath_allocator_capture cri(stack.result); 10300 xpath_allocator_capture cri(stack.result);
10146 10301
10147 r += convert_string_to_number(string_value(*it, stack.result).c_str()); 10302 r += convert_string_to_number(string_value(*it, stack.result).c_str());
10148 } 10303 }
10149 10304
10150 return r; 10305 return r;
10151 } 10306 }
10152 10307
10153 case ast_func_floor: 10308 case ast_func_floor:
10154 { 10309 {
10155 double r = _left->eval_number(c, stack); 10310 double r = _left->eval_number(c, stack);
10156 10311
10157 return r == r ? floor(r) : r; 10312 return r == r ? floor(r) : r;
10158 } 10313 }
10159 10314
10160 case ast_func_ceiling: 10315 case ast_func_ceiling:
10161 { 10316 {
10162 double r = _left->eval_number(c, stack); 10317 double r = _left->eval_number(c, stack);
10163 10318
10164 return r == r ? ceil(r) : r; 10319 return r == r ? ceil(r) : r;
10165 } 10320 }
10166 10321
10167 case ast_func_round: 10322 case ast_func_round:
10168 return round_nearest_nzero(_left->eval_number(c, stack)); 10323 return round_nearest_nzero(_left->eval_number(c, stack));
10169 10324
10170 case ast_variable: 10325 case ast_variable:
10171 { 10326 {
10172 assert(_rettype == _data.variable->type()); 10327 assert(_rettype == _data.variable->type());
10173 10328
10174 if (_rettype == xpath_type_number) 10329 if (_rettype == xpath_type_number)
10181 { 10336 {
10182 switch (_rettype) 10337 switch (_rettype)
10183 { 10338 {
10184 case xpath_type_boolean: 10339 case xpath_type_boolean:
10185 return eval_boolean(c, stack) ? 1 : 0; 10340 return eval_boolean(c, stack) ? 1 : 0;
10186 10341
10187 case xpath_type_string: 10342 case xpath_type_string:
10188 { 10343 {
10189 xpath_allocator_capture cr(stack.result); 10344 xpath_allocator_capture cr(stack.result);
10190 10345
10191 return convert_string_to_number(eval_string(c, stack).c_str()); 10346 return convert_string_to_number(eval_string(c, stack).c_str());
10192 } 10347 }
10193 10348
10194 case xpath_type_node_set: 10349 case xpath_type_node_set:
10195 { 10350 {
10196 xpath_allocator_capture cr(stack.result); 10351 xpath_allocator_capture cr(stack.result);
10197 10352
10198 return convert_string_to_number(eval_string(c, stack).c_str()); 10353 return convert_string_to_number(eval_string(c, stack).c_str());
10199 } 10354 }
10200 10355
10201 default: 10356 default:
10202 assert(!"Wrong expression for return type number"); 10357 assert(false && "Wrong expression for return type number");
10203 return 0; 10358 return 0;
10204 } 10359 }
10205 10360
10206 } 10361 }
10207 } 10362 }
10208 } 10363 }
10209 10364
10210 xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) 10365 xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack)
10211 { 10366 {
10212 assert(_type == ast_func_concat); 10367 assert(_type == ast_func_concat);
10213 10368
10214 xpath_allocator_capture ct(stack.temp); 10369 xpath_allocator_capture ct(stack.temp);
10260 { 10415 {
10261 switch (_type) 10416 switch (_type)
10262 { 10417 {
10263 case ast_string_constant: 10418 case ast_string_constant:
10264 return xpath_string::from_const(_data.string); 10419 return xpath_string::from_const(_data.string);
10265 10420
10266 case ast_func_local_name_0: 10421 case ast_func_local_name_0:
10267 { 10422 {
10268 xpath_node na = c.n; 10423 xpath_node na = c.n;
10269 10424
10270 return xpath_string::from_const(local_name(na)); 10425 return xpath_string::from_const(local_name(na));
10271 } 10426 }
10272 10427
10273 case ast_func_local_name_1: 10428 case ast_func_local_name_1:
10274 { 10429 {
10275 xpath_allocator_capture cr(stack.result); 10430 xpath_allocator_capture cr(stack.result);
10276 10431
10277 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); 10432 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10278 xpath_node na = ns.first(); 10433 xpath_node na = ns.first();
10279 10434
10280 return xpath_string::from_const(local_name(na)); 10435 return xpath_string::from_const(local_name(na));
10281 } 10436 }
10282 10437
10283 case ast_func_name_0: 10438 case ast_func_name_0:
10284 { 10439 {
10285 xpath_node na = c.n; 10440 xpath_node na = c.n;
10286 10441
10287 return xpath_string::from_const(qualified_name(na)); 10442 return xpath_string::from_const(qualified_name(na));
10288 } 10443 }
10289 10444
10290 case ast_func_name_1: 10445 case ast_func_name_1:
10291 { 10446 {
10292 xpath_allocator_capture cr(stack.result); 10447 xpath_allocator_capture cr(stack.result);
10293 10448
10294 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); 10449 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10295 xpath_node na = ns.first(); 10450 xpath_node na = ns.first();
10296 10451
10297 return xpath_string::from_const(qualified_name(na)); 10452 return xpath_string::from_const(qualified_name(na));
10298 } 10453 }
10299 10454
10300 case ast_func_namespace_uri_0: 10455 case ast_func_namespace_uri_0:
10301 { 10456 {
10302 xpath_node na = c.n; 10457 xpath_node na = c.n;
10303 10458
10304 return xpath_string::from_const(namespace_uri(na)); 10459 return xpath_string::from_const(namespace_uri(na));
10305 } 10460 }
10306 10461
10307 case ast_func_namespace_uri_1: 10462 case ast_func_namespace_uri_1:
10308 { 10463 {
10309 xpath_allocator_capture cr(stack.result); 10464 xpath_allocator_capture cr(stack.result);
10310 10465
10311 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); 10466 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10312 xpath_node na = ns.first(); 10467 xpath_node na = ns.first();
10313 10468
10314 return xpath_string::from_const(namespace_uri(na)); 10469 return xpath_string::from_const(namespace_uri(na));
10315 } 10470 }
10316 10471
10317 case ast_func_string_0: 10472 case ast_func_string_0:
10318 return string_value(c.n, stack.result); 10473 return string_value(c.n, stack.result);
10331 10486
10332 xpath_string s = _left->eval_string(c, swapped_stack); 10487 xpath_string s = _left->eval_string(c, swapped_stack);
10333 xpath_string p = _right->eval_string(c, swapped_stack); 10488 xpath_string p = _right->eval_string(c, swapped_stack);
10334 10489
10335 const char_t* pos = find_substring(s.c_str(), p.c_str()); 10490 const char_t* pos = find_substring(s.c_str(), p.c_str());
10336 10491
10337 return pos ? xpath_string::from_heap(s.c_str(), pos, stack.result) : xpath_string(); 10492 return pos ? xpath_string::from_heap(s.c_str(), pos, stack.result) : xpath_string();
10338 } 10493 }
10339 10494
10340 case ast_func_substring_after: 10495 case ast_func_substring_after:
10341 { 10496 {
10342 xpath_allocator_capture cr(stack.temp); 10497 xpath_allocator_capture cr(stack.temp);
10343 10498
10344 xpath_stack swapped_stack = {stack.temp, stack.result}; 10499 xpath_stack swapped_stack = {stack.temp, stack.result};
10345 10500
10346 xpath_string s = _left->eval_string(c, swapped_stack); 10501 xpath_string s = _left->eval_string(c, swapped_stack);
10347 xpath_string p = _right->eval_string(c, swapped_stack); 10502 xpath_string p = _right->eval_string(c, swapped_stack);
10348 10503
10349 const char_t* pos = find_substring(s.c_str(), p.c_str()); 10504 const char_t* pos = find_substring(s.c_str(), p.c_str());
10350 if (!pos) return xpath_string(); 10505 if (!pos) return xpath_string();
10351 10506
10352 const char_t* rbegin = pos + p.length(); 10507 const char_t* rbegin = pos + p.length();
10353 const char_t* rend = s.c_str() + s.length(); 10508 const char_t* rend = s.c_str() + s.length();
10363 10518
10364 xpath_string s = _left->eval_string(c, swapped_stack); 10519 xpath_string s = _left->eval_string(c, swapped_stack);
10365 size_t s_length = s.length(); 10520 size_t s_length = s.length();
10366 10521
10367 double first = round_nearest(_right->eval_number(c, stack)); 10522 double first = round_nearest(_right->eval_number(c, stack));
10368 10523
10369 if (is_nan(first)) return xpath_string(); // NaN 10524 if (is_nan(first)) return xpath_string(); // NaN
10370 else if (first >= s_length + 1) return xpath_string(); 10525 else if (first >= s_length + 1) return xpath_string();
10371 10526
10372 size_t pos = first < 1 ? 1 : static_cast<size_t>(first); 10527 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10373 assert(1 <= pos && pos <= s_length + 1); 10528 assert(1 <= pos && pos <= s_length + 1);
10374 10529
10375 const char_t* rbegin = s.c_str() + (pos - 1); 10530 const char_t* rbegin = s.c_str() + (pos - 1);
10376 const char_t* rend = s.c_str() + s.length(); 10531 const char_t* rend = s.c_str() + s.length();
10377 10532
10378 return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); 10533 return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin);
10379 } 10534 }
10380 10535
10381 case ast_func_substring_3: 10536 case ast_func_substring_3:
10382 { 10537 {
10383 xpath_allocator_capture cr(stack.temp); 10538 xpath_allocator_capture cr(stack.temp);
10384 10539
10385 xpath_stack swapped_stack = {stack.temp, stack.result}; 10540 xpath_stack swapped_stack = {stack.temp, stack.result};
10387 xpath_string s = _left->eval_string(c, swapped_stack); 10542 xpath_string s = _left->eval_string(c, swapped_stack);
10388 size_t s_length = s.length(); 10543 size_t s_length = s.length();
10389 10544
10390 double first = round_nearest(_right->eval_number(c, stack)); 10545 double first = round_nearest(_right->eval_number(c, stack));
10391 double last = first + round_nearest(_right->_next->eval_number(c, stack)); 10546 double last = first + round_nearest(_right->_next->eval_number(c, stack));
10392 10547
10393 if (is_nan(first) || is_nan(last)) return xpath_string(); 10548 if (is_nan(first) || is_nan(last)) return xpath_string();
10394 else if (first >= s_length + 1) return xpath_string(); 10549 else if (first >= s_length + 1) return xpath_string();
10395 else if (first >= last) return xpath_string(); 10550 else if (first >= last) return xpath_string();
10396 else if (last < 1) return xpath_string(); 10551 else if (last < 1) return xpath_string();
10397 10552
10398 size_t pos = first < 1 ? 1 : static_cast<size_t>(first); 10553 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10399 size_t end = last >= s_length + 1 ? s_length + 1 : static_cast<size_t>(last); 10554 size_t end = last >= s_length + 1 ? s_length + 1 : static_cast<size_t>(last);
10400 10555
10401 assert(1 <= pos && pos <= end && end <= s_length + 1); 10556 assert(1 <= pos && pos <= end && end <= s_length + 1);
10402 const char_t* rbegin = s.c_str() + (pos - 1); 10557 const char_t* rbegin = s.c_str() + (pos - 1);
10419 { 10574 {
10420 xpath_string s = _left->eval_string(c, stack); 10575 xpath_string s = _left->eval_string(c, stack);
10421 10576
10422 char_t* begin = s.data(stack.result); 10577 char_t* begin = s.data(stack.result);
10423 char_t* end = normalize_space(begin); 10578 char_t* end = normalize_space(begin);
10424 10579
10425 return xpath_string::from_heap_preallocated(begin, end); 10580 return xpath_string::from_heap_preallocated(begin, end);
10426 } 10581 }
10427 10582
10428 case ast_func_translate: 10583 case ast_func_translate:
10429 { 10584 {
10465 { 10620 {
10466 switch (_rettype) 10621 switch (_rettype)
10467 { 10622 {
10468 case xpath_type_boolean: 10623 case xpath_type_boolean:
10469 return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); 10624 return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"));
10470 10625
10471 case xpath_type_number: 10626 case xpath_type_number:
10472 return convert_number_to_string(eval_number(c, stack), stack.result); 10627 return convert_number_to_string(eval_number(c, stack), stack.result);
10473 10628
10474 case xpath_type_node_set: 10629 case xpath_type_node_set:
10475 { 10630 {
10476 xpath_allocator_capture cr(stack.temp); 10631 xpath_allocator_capture cr(stack.temp);
10477 10632
10478 xpath_stack swapped_stack = {stack.temp, stack.result}; 10633 xpath_stack swapped_stack = {stack.temp, stack.result};
10479 10634
10480 xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first); 10635 xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first);
10481 return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); 10636 return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result);
10482 } 10637 }
10483 10638
10484 default: 10639 default:
10485 assert(!"Wrong expression for return type string"); 10640 assert(false && "Wrong expression for return type string");
10486 return xpath_string(); 10641 return xpath_string();
10487 } 10642 }
10488 } 10643 }
10489 } 10644 }
10490 } 10645 }
10519 if (_test != predicate_posinv) set.sort_do(); 10674 if (_test != predicate_posinv) set.sort_do();
10520 10675
10521 bool once = eval_once(set.type(), eval); 10676 bool once = eval_once(set.type(), eval);
10522 10677
10523 apply_predicate(set, 0, stack, once); 10678 apply_predicate(set, 0, stack, once);
10524 10679
10525 return set; 10680 return set;
10526 } 10681 }
10527 10682
10528 case ast_func_id: 10683 case ast_func_id:
10529 return xpath_node_set_raw(); 10684 return xpath_node_set_raw();
10530 10685
10531 case ast_step: 10686 case ast_step:
10532 { 10687 {
10533 switch (_axis) 10688 switch (_axis)
10534 { 10689 {
10535 case axis_ancestor: 10690 case axis_ancestor:
10536 return step_do(c, stack, eval, axis_to_type<axis_ancestor>()); 10691 return step_do(c, stack, eval, axis_to_type<axis_ancestor>());
10537 10692
10538 case axis_ancestor_or_self: 10693 case axis_ancestor_or_self:
10539 return step_do(c, stack, eval, axis_to_type<axis_ancestor_or_self>()); 10694 return step_do(c, stack, eval, axis_to_type<axis_ancestor_or_self>());
10540 10695
10541 case axis_attribute: 10696 case axis_attribute:
10542 return step_do(c, stack, eval, axis_to_type<axis_attribute>()); 10697 return step_do(c, stack, eval, axis_to_type<axis_attribute>());
10543 10698
10544 case axis_child: 10699 case axis_child:
10545 return step_do(c, stack, eval, axis_to_type<axis_child>()); 10700 return step_do(c, stack, eval, axis_to_type<axis_child>());
10546 10701
10547 case axis_descendant: 10702 case axis_descendant:
10548 return step_do(c, stack, eval, axis_to_type<axis_descendant>()); 10703 return step_do(c, stack, eval, axis_to_type<axis_descendant>());
10549 10704
10550 case axis_descendant_or_self: 10705 case axis_descendant_or_self:
10551 return step_do(c, stack, eval, axis_to_type<axis_descendant_or_self>()); 10706 return step_do(c, stack, eval, axis_to_type<axis_descendant_or_self>());
10552 10707
10553 case axis_following: 10708 case axis_following:
10554 return step_do(c, stack, eval, axis_to_type<axis_following>()); 10709 return step_do(c, stack, eval, axis_to_type<axis_following>());
10555 10710
10556 case axis_following_sibling: 10711 case axis_following_sibling:
10557 return step_do(c, stack, eval, axis_to_type<axis_following_sibling>()); 10712 return step_do(c, stack, eval, axis_to_type<axis_following_sibling>());
10558 10713
10559 case axis_namespace: 10714 case axis_namespace:
10560 // namespaced axis is not supported 10715 // namespaced axis is not supported
10561 return xpath_node_set_raw(); 10716 return xpath_node_set_raw();
10562 10717
10563 case axis_parent: 10718 case axis_parent:
10564 return step_do(c, stack, eval, axis_to_type<axis_parent>()); 10719 return step_do(c, stack, eval, axis_to_type<axis_parent>());
10565 10720
10566 case axis_preceding: 10721 case axis_preceding:
10567 return step_do(c, stack, eval, axis_to_type<axis_preceding>()); 10722 return step_do(c, stack, eval, axis_to_type<axis_preceding>());
10568 10723
10569 case axis_preceding_sibling: 10724 case axis_preceding_sibling:
10570 return step_do(c, stack, eval, axis_to_type<axis_preceding_sibling>()); 10725 return step_do(c, stack, eval, axis_to_type<axis_preceding_sibling>());
10571 10726
10572 case axis_self: 10727 case axis_self:
10573 return step_do(c, stack, eval, axis_to_type<axis_self>()); 10728 return step_do(c, stack, eval, axis_to_type<axis_self>());
10574 10729
10575 default: 10730 default:
10576 assert(!"Unknown axis"); 10731 assert(false && "Unknown axis");
10577 return xpath_node_set_raw(); 10732 return xpath_node_set_raw();
10578 } 10733 }
10579 } 10734 }
10580 10735
10581 case ast_step_root: 10736 case ast_step_root:
10610 10765
10611 // fallthrough to type conversion 10766 // fallthrough to type conversion
10612 } 10767 }
10613 10768
10614 default: 10769 default:
10615 assert(!"Wrong expression for return type node set"); 10770 assert(false && "Wrong expression for return type node set");
10616 return xpath_node_set_raw(); 10771 return xpath_node_set_raw();
10617 } 10772 }
10618 } 10773 }
10619 10774
10620 void optimize(xpath_allocator* alloc) 10775 void optimize(xpath_allocator* alloc)
10621 { 10776 {
10622 if (_left) _left->optimize(alloc); 10777 if (_left)
10623 if (_right) _right->optimize(alloc); 10778 _left->optimize(alloc);
10624 if (_next) _next->optimize(alloc); 10779
10780 if (_right)
10781 _right->optimize(alloc);
10782
10783 if (_next)
10784 _next->optimize(alloc);
10625 10785
10626 optimize_self(alloc); 10786 optimize_self(alloc);
10627 } 10787 }
10628 10788
10629 void optimize_self(xpath_allocator* alloc) 10789 void optimize_self(xpath_allocator* alloc)
10683 (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string))) 10843 (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string)))
10684 { 10844 {
10685 _type = ast_opt_compare_attribute; 10845 _type = ast_opt_compare_attribute;
10686 } 10846 }
10687 } 10847 }
10688 10848
10689 bool is_posinv_expr() const 10849 bool is_posinv_expr() const
10690 { 10850 {
10691 switch (_type) 10851 switch (_type)
10692 { 10852 {
10693 case ast_func_position: 10853 case ast_func_position:
10707 case ast_filter: 10867 case ast_filter:
10708 return true; 10868 return true;
10709 10869
10710 default: 10870 default:
10711 if (_left && !_left->is_posinv_expr()) return false; 10871 if (_left && !_left->is_posinv_expr()) return false;
10712 10872
10713 for (xpath_ast_node* n = _right; n; n = n->_next) 10873 for (xpath_ast_node* n = _right; n; n = n->_next)
10714 if (!n->is_posinv_expr()) return false; 10874 if (!n->is_posinv_expr()) return false;
10715 10875
10716 return true; 10876 return true;
10717 } 10877 }
10718 } 10878 }
10719 10879
10720 bool is_posinv_step() const 10880 bool is_posinv_step() const
10804 10964
10805 xpath_ast_node* parse_function_helper(ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node* args[2]) 10965 xpath_ast_node* parse_function_helper(ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node* args[2])
10806 { 10966 {
10807 assert(argc <= 1); 10967 assert(argc <= 1);
10808 10968
10809 if (argc == 1 && args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); 10969 if (argc == 1 && args[0]->rettype() != xpath_type_node_set)
10970 throw_error("Function has to be applied to node set");
10810 10971
10811 return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]); 10972 return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]);
10812 } 10973 }
10813 10974
10814 xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2]) 10975 xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2])
10816 switch (name.begin[0]) 10977 switch (name.begin[0])
10817 { 10978 {
10818 case 'b': 10979 case 'b':
10819 if (name == PUGIXML_TEXT("boolean") && argc == 1) 10980 if (name == PUGIXML_TEXT("boolean") && argc == 1)
10820 return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]); 10981 return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]);
10821 10982
10822 break; 10983 break;
10823 10984
10824 case 'c': 10985 case 'c':
10825 if (name == PUGIXML_TEXT("count") && argc == 1) 10986 if (name == PUGIXML_TEXT("count") && argc == 1)
10826 { 10987 {
10827 if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); 10988 if (args[0]->rettype() != xpath_type_node_set)
10989 throw_error("Function has to be applied to node set");
10990
10828 return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]); 10991 return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]);
10829 } 10992 }
10830 else if (name == PUGIXML_TEXT("contains") && argc == 2) 10993 else if (name == PUGIXML_TEXT("contains") && argc == 2)
10831 return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_boolean, args[0], args[1]); 10994 return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_boolean, args[0], args[1]);
10832 else if (name == PUGIXML_TEXT("concat") && argc >= 2) 10995 else if (name == PUGIXML_TEXT("concat") && argc >= 2)
10833 return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]); 10996 return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]);
10834 else if (name == PUGIXML_TEXT("ceiling") && argc == 1) 10997 else if (name == PUGIXML_TEXT("ceiling") && argc == 1)
10835 return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]); 10998 return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]);
10836 10999
10837 break; 11000 break;
10838 11001
10839 case 'f': 11002 case 'f':
10840 if (name == PUGIXML_TEXT("false") && argc == 0) 11003 if (name == PUGIXML_TEXT("false") && argc == 0)
10841 return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean); 11004 return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean);
10842 else if (name == PUGIXML_TEXT("floor") && argc == 1) 11005 else if (name == PUGIXML_TEXT("floor") && argc == 1)
10843 return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]); 11006 return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]);
10844 11007
10845 break; 11008 break;
10846 11009
10847 case 'i': 11010 case 'i':
10848 if (name == PUGIXML_TEXT("id") && argc == 1) 11011 if (name == PUGIXML_TEXT("id") && argc == 1)
10849 return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]); 11012 return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]);
10850 11013
10851 break; 11014 break;
10852 11015
10853 case 'l': 11016 case 'l':
10854 if (name == PUGIXML_TEXT("last") && argc == 0) 11017 if (name == PUGIXML_TEXT("last") && argc == 0)
10855 return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number); 11018 return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number);
10856 else if (name == PUGIXML_TEXT("lang") && argc == 1) 11019 else if (name == PUGIXML_TEXT("lang") && argc == 1)
10857 return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]); 11020 return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]);
10858 else if (name == PUGIXML_TEXT("local-name") && argc <= 1) 11021 else if (name == PUGIXML_TEXT("local-name") && argc <= 1)
10859 return parse_function_helper(ast_func_local_name_0, ast_func_local_name_1, argc, args); 11022 return parse_function_helper(ast_func_local_name_0, ast_func_local_name_1, argc, args);
10860 11023
10861 break; 11024 break;
10862 11025
10863 case 'n': 11026 case 'n':
10864 if (name == PUGIXML_TEXT("name") && argc <= 1) 11027 if (name == PUGIXML_TEXT("name") && argc <= 1)
10865 return parse_function_helper(ast_func_name_0, ast_func_name_1, argc, args); 11028 return parse_function_helper(ast_func_name_0, ast_func_name_1, argc, args);
10866 else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1) 11029 else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1)
10867 return parse_function_helper(ast_func_namespace_uri_0, ast_func_namespace_uri_1, argc, args); 11030 return parse_function_helper(ast_func_namespace_uri_0, ast_func_namespace_uri_1, argc, args);
10869 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]); 11032 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]);
10870 else if (name == PUGIXML_TEXT("not") && argc == 1) 11033 else if (name == PUGIXML_TEXT("not") && argc == 1)
10871 return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]); 11034 return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]);
10872 else if (name == PUGIXML_TEXT("number") && argc <= 1) 11035 else if (name == PUGIXML_TEXT("number") && argc <= 1)
10873 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]); 11036 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]);
10874 11037
10875 break; 11038 break;
10876 11039
10877 case 'p': 11040 case 'p':
10878 if (name == PUGIXML_TEXT("position") && argc == 0) 11041 if (name == PUGIXML_TEXT("position") && argc == 0)
10879 return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number); 11042 return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number);
10880 11043
10881 break; 11044 break;
10882 11045
10883 case 'r': 11046 case 'r':
10884 if (name == PUGIXML_TEXT("round") && argc == 1) 11047 if (name == PUGIXML_TEXT("round") && argc == 1)
10885 return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]); 11048 return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]);
10886 11049
10887 break; 11050 break;
10888 11051
10889 case 's': 11052 case 's':
10890 if (name == PUGIXML_TEXT("string") && argc <= 1) 11053 if (name == PUGIXML_TEXT("string") && argc <= 1)
10891 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]); 11054 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]);
10892 else if (name == PUGIXML_TEXT("string-length") && argc <= 1) 11055 else if (name == PUGIXML_TEXT("string-length") && argc <= 1)
10893 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]); 11056 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]);
10904 if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); 11067 if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set");
10905 return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]); 11068 return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]);
10906 } 11069 }
10907 11070
10908 break; 11071 break;
10909 11072
10910 case 't': 11073 case 't':
10911 if (name == PUGIXML_TEXT("translate") && argc == 3) 11074 if (name == PUGIXML_TEXT("translate") && argc == 3)
10912 return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]); 11075 return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]);
10913 else if (name == PUGIXML_TEXT("true") && argc == 0) 11076 else if (name == PUGIXML_TEXT("true") && argc == 0)
10914 return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean); 11077 return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean);
10915 11078
10916 break; 11079 break;
10917 11080
10918 default: 11081 default:
10919 break; 11082 break;
10920 } 11083 }
10935 return axis_ancestor; 11098 return axis_ancestor;
10936 else if (name == PUGIXML_TEXT("ancestor-or-self")) 11099 else if (name == PUGIXML_TEXT("ancestor-or-self"))
10937 return axis_ancestor_or_self; 11100 return axis_ancestor_or_self;
10938 else if (name == PUGIXML_TEXT("attribute")) 11101 else if (name == PUGIXML_TEXT("attribute"))
10939 return axis_attribute; 11102 return axis_attribute;
10940 11103
10941 break; 11104 break;
10942 11105
10943 case 'c': 11106 case 'c':
10944 if (name == PUGIXML_TEXT("child")) 11107 if (name == PUGIXML_TEXT("child"))
10945 return axis_child; 11108 return axis_child;
10946 11109
10947 break; 11110 break;
10948 11111
10949 case 'd': 11112 case 'd':
10950 if (name == PUGIXML_TEXT("descendant")) 11113 if (name == PUGIXML_TEXT("descendant"))
10951 return axis_descendant; 11114 return axis_descendant;
10952 else if (name == PUGIXML_TEXT("descendant-or-self")) 11115 else if (name == PUGIXML_TEXT("descendant-or-self"))
10953 return axis_descendant_or_self; 11116 return axis_descendant_or_self;
10954 11117
10955 break; 11118 break;
10956 11119
10957 case 'f': 11120 case 'f':
10958 if (name == PUGIXML_TEXT("following")) 11121 if (name == PUGIXML_TEXT("following"))
10959 return axis_following; 11122 return axis_following;
10960 else if (name == PUGIXML_TEXT("following-sibling")) 11123 else if (name == PUGIXML_TEXT("following-sibling"))
10961 return axis_following_sibling; 11124 return axis_following_sibling;
10962 11125
10963 break; 11126 break;
10964 11127
10965 case 'n': 11128 case 'n':
10966 if (name == PUGIXML_TEXT("namespace")) 11129 if (name == PUGIXML_TEXT("namespace"))
10967 return axis_namespace; 11130 return axis_namespace;
10968 11131
10969 break; 11132 break;
10970 11133
10971 case 'p': 11134 case 'p':
10972 if (name == PUGIXML_TEXT("parent")) 11135 if (name == PUGIXML_TEXT("parent"))
10973 return axis_parent; 11136 return axis_parent;
10974 else if (name == PUGIXML_TEXT("preceding")) 11137 else if (name == PUGIXML_TEXT("preceding"))
10975 return axis_preceding; 11138 return axis_preceding;
10976 else if (name == PUGIXML_TEXT("preceding-sibling")) 11139 else if (name == PUGIXML_TEXT("preceding-sibling"))
10977 return axis_preceding_sibling; 11140 return axis_preceding_sibling;
10978 11141
10979 break; 11142 break;
10980 11143
10981 case 's': 11144 case 's':
10982 if (name == PUGIXML_TEXT("self")) 11145 if (name == PUGIXML_TEXT("self"))
10983 return axis_self; 11146 return axis_self;
10984 11147
10985 break; 11148 break;
10986 11149
10987 default: 11150 default:
10988 break; 11151 break;
10989 } 11152 }
11017 case 't': 11180 case 't':
11018 if (name == PUGIXML_TEXT("text")) 11181 if (name == PUGIXML_TEXT("text"))
11019 return nodetest_type_text; 11182 return nodetest_type_text;
11020 11183
11021 break; 11184 break;
11022 11185
11023 default: 11186 default:
11024 break; 11187 break;
11025 } 11188 }
11026 11189
11027 return nodetest_none; 11190 return nodetest_none;
11090 11253
11091 case lex_string: 11254 case lex_string:
11092 { 11255 {
11093 xpath_ast_node* args[2] = {0}; 11256 xpath_ast_node* args[2] = {0};
11094 size_t argc = 0; 11257 size_t argc = 0;
11095 11258
11096 xpath_lexer_string function = _lexer.contents(); 11259 xpath_lexer_string function = _lexer.contents();
11097 _lexer.next(); 11260 _lexer.next();
11098 11261
11099 xpath_ast_node* last_arg = 0; 11262 xpath_ast_node* last_arg = 0;
11100 11263
11101 if (_lexer.current() != lex_open_brace) 11264 if (_lexer.current() != lex_open_brace)
11102 throw_error("Unrecognized function call"); 11265 throw_error("Unrecognized function call");
11103 _lexer.next(); 11266 _lexer.next();
11104 11267
11105 if (_lexer.current() != lex_close_brace) 11268 if (_lexer.current() != lex_close_brace)
11108 while (_lexer.current() != lex_close_brace) 11271 while (_lexer.current() != lex_close_brace)
11109 { 11272 {
11110 if (_lexer.current() != lex_comma) 11273 if (_lexer.current() != lex_comma)
11111 throw_error("No comma between function arguments"); 11274 throw_error("No comma between function arguments");
11112 _lexer.next(); 11275 _lexer.next();
11113 11276
11114 xpath_ast_node* n = parse_expression(); 11277 xpath_ast_node* n = parse_expression();
11115 11278
11116 if (argc < 2) args[argc] = n; 11279 if (argc < 2) args[argc] = n;
11117 else last_arg->set_next(n); 11280 else last_arg->set_next(n);
11118 11281
11119 argc++; 11282 argc++;
11120 last_arg = n; 11283 last_arg = n;
11121 } 11284 }
11122 11285
11123 _lexer.next(); 11286 _lexer.next();
11124 11287
11125 return parse_function(function, argc, args); 11288 return parse_function(function, argc, args);
11126 } 11289 }
11127 11290
11129 throw_error("Unrecognizable primary expression"); 11292 throw_error("Unrecognizable primary expression");
11130 11293
11131 return 0; 11294 return 0;
11132 } 11295 }
11133 } 11296 }
11134 11297
11135 // FilterExpr ::= PrimaryExpr | FilterExpr Predicate 11298 // FilterExpr ::= PrimaryExpr | FilterExpr Predicate
11136 // Predicate ::= '[' PredicateExpr ']' 11299 // Predicate ::= '[' PredicateExpr ']'
11137 // PredicateExpr ::= Expr 11300 // PredicateExpr ::= Expr
11138 xpath_ast_node* parse_filter_expression() 11301 xpath_ast_node* parse_filter_expression()
11139 { 11302 {
11143 { 11306 {
11144 _lexer.next(); 11307 _lexer.next();
11145 11308
11146 xpath_ast_node* expr = parse_expression(); 11309 xpath_ast_node* expr = parse_expression();
11147 11310
11148 if (n->rettype() != xpath_type_node_set) throw_error("Predicate has to be applied to node set"); 11311 if (n->rettype() != xpath_type_node_set)
11312 throw_error("Predicate has to be applied to node set");
11149 11313
11150 n = new (alloc_node()) xpath_ast_node(ast_filter, n, expr, predicate_default); 11314 n = new (alloc_node()) xpath_ast_node(ast_filter, n, expr, predicate_default);
11151 11315
11152 if (_lexer.current() != lex_close_square_brace) 11316 if (_lexer.current() != lex_close_square_brace)
11153 throw_error("Unmatched square brace"); 11317 throw_error("Unmatched square brace");
11154 11318
11155 _lexer.next(); 11319 _lexer.next();
11156 } 11320 }
11157 11321
11158 return n; 11322 return n;
11159 } 11323 }
11160 11324
11161 // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep 11325 // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep
11162 // AxisSpecifier ::= AxisName '::' | '@'? 11326 // AxisSpecifier ::= AxisName '::' | '@'?
11163 // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' 11327 // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')'
11164 // NameTest ::= '*' | NCName ':' '*' | QName 11328 // NameTest ::= '*' | NCName ':' '*' | QName
11165 // AbbreviatedStep ::= '.' | '..' 11329 // AbbreviatedStep ::= '.' | '..'
11173 11337
11174 if (_lexer.current() == lex_axis_attribute) 11338 if (_lexer.current() == lex_axis_attribute)
11175 { 11339 {
11176 axis = axis_attribute; 11340 axis = axis_attribute;
11177 axis_specified = true; 11341 axis_specified = true;
11178 11342
11179 _lexer.next(); 11343 _lexer.next();
11180 } 11344 }
11181 else if (_lexer.current() == lex_dot) 11345 else if (_lexer.current() == lex_dot)
11182 { 11346 {
11183 _lexer.next(); 11347 _lexer.next();
11184 11348
11185 return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0); 11349 return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0);
11186 } 11350 }
11187 else if (_lexer.current() == lex_double_dot) 11351 else if (_lexer.current() == lex_double_dot)
11188 { 11352 {
11189 _lexer.next(); 11353 _lexer.next();
11190 11354
11191 return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0); 11355 return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0);
11192 } 11356 }
11193 11357
11194 nodetest_t nt_type = nodetest_none; 11358 nodetest_t nt_type = nodetest_none;
11195 xpath_lexer_string nt_name; 11359 xpath_lexer_string nt_name;
11196 11360
11197 if (_lexer.current() == lex_string) 11361 if (_lexer.current() == lex_string)
11198 { 11362 {
11199 // node name test 11363 // node name test
11200 nt_name = _lexer.contents(); 11364 nt_name = _lexer.contents();
11201 _lexer.next(); 11365 _lexer.next();
11202 11366
11203 // was it an axis name? 11367 // was it an axis name?
11204 if (_lexer.current() == lex_double_colon) 11368 if (_lexer.current() == lex_double_colon)
11205 { 11369 {
11206 // parse axis name 11370 // parse axis name
11207 if (axis_specified) throw_error("Two axis specifiers in one step"); 11371 if (axis_specified)
11372 throw_error("Two axis specifiers in one step");
11208 11373
11209 axis = parse_axis_name(nt_name, axis_specified); 11374 axis = parse_axis_name(nt_name, axis_specified);
11210 11375
11211 if (!axis_specified) throw_error("Unknown axis"); 11376 if (!axis_specified)
11377 throw_error("Unknown axis");
11212 11378
11213 // read actual node test 11379 // read actual node test
11214 _lexer.next(); 11380 _lexer.next();
11215 11381
11216 if (_lexer.current() == lex_multiply) 11382 if (_lexer.current() == lex_multiply)
11224 nt_name = _lexer.contents(); 11390 nt_name = _lexer.contents();
11225 _lexer.next(); 11391 _lexer.next();
11226 } 11392 }
11227 else throw_error("Unrecognized node test"); 11393 else throw_error("Unrecognized node test");
11228 } 11394 }
11229 11395
11230 if (nt_type == nodetest_none) 11396 if (nt_type == nodetest_none)
11231 { 11397 {
11232 // node type test or processing-instruction 11398 // node type test or processing-instruction
11233 if (_lexer.current() == lex_open_brace) 11399 if (_lexer.current() == lex_open_brace)
11234 { 11400 {
11235 _lexer.next(); 11401 _lexer.next();
11236 11402
11237 if (_lexer.current() == lex_close_brace) 11403 if (_lexer.current() == lex_close_brace)
11238 { 11404 {
11239 _lexer.next(); 11405 _lexer.next();
11240 11406
11241 nt_type = parse_node_test_type(nt_name); 11407 nt_type = parse_node_test_type(nt_name);
11242 11408
11243 if (nt_type == nodetest_none) throw_error("Unrecognized node type"); 11409 if (nt_type == nodetest_none)
11244 11410 throw_error("Unrecognized node type");
11411
11245 nt_name = xpath_lexer_string(); 11412 nt_name = xpath_lexer_string();
11246 } 11413 }
11247 else if (nt_name == PUGIXML_TEXT("processing-instruction")) 11414 else if (nt_name == PUGIXML_TEXT("processing-instruction"))
11248 { 11415 {
11249 if (_lexer.current() != lex_quoted_string) 11416 if (_lexer.current() != lex_quoted_string)
11250 throw_error("Only literals are allowed as arguments to processing-instruction()"); 11417 throw_error("Only literals are allowed as arguments to processing-instruction()");
11251 11418
11252 nt_type = nodetest_pi; 11419 nt_type = nodetest_pi;
11253 nt_name = _lexer.contents(); 11420 nt_name = _lexer.contents();
11254 _lexer.next(); 11421 _lexer.next();
11255 11422
11256 if (_lexer.current() != lex_close_brace) 11423 if (_lexer.current() != lex_close_brace)
11257 throw_error("Unmatched brace near processing-instruction()"); 11424 throw_error("Unmatched brace near processing-instruction()");
11258 _lexer.next(); 11425 _lexer.next();
11259 } 11426 }
11260 else 11427 else
11428 {
11261 throw_error("Unmatched brace near node type test"); 11429 throw_error("Unmatched brace near node type test");
11262 11430 }
11263 } 11431 }
11264 // QName or NCName:* 11432 // QName or NCName:*
11265 else 11433 else
11266 { 11434 {
11267 if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:* 11435 if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:*
11268 { 11436 {
11269 nt_name.end--; // erase * 11437 nt_name.end--; // erase *
11270 11438
11271 nt_type = nodetest_all_in_namespace; 11439 nt_type = nodetest_all_in_namespace;
11272 } 11440 }
11273 else nt_type = nodetest_name; 11441 else
11442 {
11443 nt_type = nodetest_name;
11444 }
11274 } 11445 }
11275 } 11446 }
11276 } 11447 }
11277 else if (_lexer.current() == lex_multiply) 11448 else if (_lexer.current() == lex_multiply)
11278 { 11449 {
11279 nt_type = nodetest_all; 11450 nt_type = nodetest_all;
11280 _lexer.next(); 11451 _lexer.next();
11281 } 11452 }
11282 else throw_error("Unrecognized node test"); 11453 else
11283 11454 {
11284 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, alloc_string(nt_name)); 11455 throw_error("Unrecognized node test");
11285 11456 }
11457
11458 const char_t* nt_name_copy = alloc_string(nt_name);
11459 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, nt_name_copy);
11460
11286 xpath_ast_node* last = 0; 11461 xpath_ast_node* last = 0;
11287 11462
11288 while (_lexer.current() == lex_open_square_brace) 11463 while (_lexer.current() == lex_open_square_brace)
11289 { 11464 {
11290 _lexer.next(); 11465 _lexer.next();
11291 11466
11292 xpath_ast_node* expr = parse_expression(); 11467 xpath_ast_node* expr = parse_expression();
11293 11468
11294 xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, 0, expr, predicate_default); 11469 xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, 0, expr, predicate_default);
11295 11470
11296 if (_lexer.current() != lex_close_square_brace) 11471 if (_lexer.current() != lex_close_square_brace)
11297 throw_error("Unmatched square brace"); 11472 throw_error("Unmatched square brace");
11298 _lexer.next(); 11473 _lexer.next();
11299 11474
11300 if (last) last->set_next(pred); 11475 if (last) last->set_next(pred);
11301 else n->set_right(pred); 11476 else n->set_right(pred);
11302 11477
11303 last = pred; 11478 last = pred;
11304 } 11479 }
11305 11480
11306 return n; 11481 return n;
11307 } 11482 }
11308 11483
11309 // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step 11484 // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step
11310 xpath_ast_node* parse_relative_location_path(xpath_ast_node* set) 11485 xpath_ast_node* parse_relative_location_path(xpath_ast_node* set)
11311 { 11486 {
11312 xpath_ast_node* n = parse_step(set); 11487 xpath_ast_node* n = parse_step(set);
11313 11488
11314 while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) 11489 while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash)
11315 { 11490 {
11316 lexeme_t l = _lexer.current(); 11491 lexeme_t l = _lexer.current();
11317 _lexer.next(); 11492 _lexer.next();
11318 11493
11319 if (l == lex_double_slash) 11494 if (l == lex_double_slash)
11320 n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); 11495 n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
11321 11496
11322 n = parse_step(n); 11497 n = parse_step(n);
11323 } 11498 }
11324 11499
11325 return n; 11500 return n;
11326 } 11501 }
11327 11502
11328 // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath 11503 // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath
11329 // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath 11504 // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath
11330 xpath_ast_node* parse_location_path() 11505 xpath_ast_node* parse_location_path()
11331 { 11506 {
11332 if (_lexer.current() == lex_slash) 11507 if (_lexer.current() == lex_slash)
11333 { 11508 {
11334 _lexer.next(); 11509 _lexer.next();
11335 11510
11336 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); 11511 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set);
11337 11512
11338 // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path 11513 // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path
11339 lexeme_t l = _lexer.current(); 11514 lexeme_t l = _lexer.current();
11340 11515
11344 return n; 11519 return n;
11345 } 11520 }
11346 else if (_lexer.current() == lex_double_slash) 11521 else if (_lexer.current() == lex_double_slash)
11347 { 11522 {
11348 _lexer.next(); 11523 _lexer.next();
11349 11524
11350 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); 11525 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set);
11351 n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); 11526 n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
11352 11527
11353 return parse_relative_location_path(n); 11528 return parse_relative_location_path(n);
11354 } 11529 }
11355 11530
11356 // 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 11531 // 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
11357 return parse_relative_location_path(0); 11532 return parse_relative_location_path(0);
11358 } 11533 }
11359 11534
11360 // PathExpr ::= LocationPath 11535 // PathExpr ::= LocationPath
11361 // | FilterExpr 11536 // | FilterExpr
11362 // | FilterExpr '/' RelativeLocationPath 11537 // | FilterExpr '/' RelativeLocationPath
11363 // | FilterExpr '//' RelativeLocationPath 11538 // | FilterExpr '//' RelativeLocationPath
11364 // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr 11539 // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr
11370 // FilterExpr begins with PrimaryExpr 11545 // FilterExpr begins with PrimaryExpr
11371 // PrimaryExpr begins with '$' in case of it being a variable reference, 11546 // PrimaryExpr begins with '$' in case of it being a variable reference,
11372 // '(' in case of it being an expression, string literal, number constant or 11547 // '(' in case of it being an expression, string literal, number constant or
11373 // function call. 11548 // function call.
11374 11549
11375 if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || 11550 if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace ||
11376 _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || 11551 _lexer.current() == lex_quoted_string || _lexer.current() == lex_number ||
11377 _lexer.current() == lex_string) 11552 _lexer.current() == lex_string)
11378 { 11553 {
11379 if (_lexer.current() == lex_string) 11554 if (_lexer.current() == lex_string)
11380 { 11555 {
11381 // This is either a function call, or not - if not, we shall proceed with location path 11556 // This is either a function call, or not - if not, we shall proceed with location path
11382 const char_t* state = _lexer.state(); 11557 const char_t* state = _lexer.state();
11383 11558
11384 while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state; 11559 while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state;
11385 11560
11386 if (*state != '(') return parse_location_path(); 11561 if (*state != '(') return parse_location_path();
11387 11562
11388 // This looks like a function call; however this still can be a node-test. Check it. 11563 // This looks like a function call; however this still can be a node-test. Check it.
11389 if (parse_node_test_type(_lexer.contents()) != nodetest_none) return parse_location_path(); 11564 if (parse_node_test_type(_lexer.contents()) != nodetest_none)
11390 } 11565 return parse_location_path();
11391 11566 }
11567
11392 xpath_ast_node* n = parse_filter_expression(); 11568 xpath_ast_node* n = parse_filter_expression();
11393 11569
11394 if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) 11570 if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash)
11395 { 11571 {
11396 lexeme_t l = _lexer.current(); 11572 lexeme_t l = _lexer.current();
11397 _lexer.next(); 11573 _lexer.next();
11398 11574
11399 if (l == lex_double_slash) 11575 if (l == lex_double_slash)
11400 { 11576 {
11401 if (n->rettype() != xpath_type_node_set) throw_error("Step has to be applied to node set"); 11577 if (n->rettype() != xpath_type_node_set)
11578 throw_error("Step has to be applied to node set");
11402 11579
11403 n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); 11580 n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
11404 } 11581 }
11405 11582
11406 // select from location path 11583 // select from location path
11407 return parse_relative_location_path(n); 11584 return parse_relative_location_path(n);
11408 } 11585 }
11409 11586
11410 return n; 11587 return n;
11417 xpath_ast_node* expr = parse_expression_rec(parse_path_or_unary_expression(), 7); 11594 xpath_ast_node* expr = parse_expression_rec(parse_path_or_unary_expression(), 7);
11418 11595
11419 return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr); 11596 return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr);
11420 } 11597 }
11421 else 11598 else
11599 {
11422 return parse_location_path(); 11600 return parse_location_path();
11601 }
11423 } 11602 }
11424 11603
11425 struct binary_op_t 11604 struct binary_op_t
11426 { 11605 {
11427 ast_type_t asttype; 11606 ast_type_t asttype;
11546 } 11725 }
11547 11726
11548 xpath_ast_node* parse() 11727 xpath_ast_node* parse()
11549 { 11728 {
11550 xpath_ast_node* result = parse_expression(); 11729 xpath_ast_node* result = parse_expression();
11551 11730
11731 // check if there are unparsed tokens left
11552 if (_lexer.current() != lex_eof) 11732 if (_lexer.current() != lex_eof)
11553 {
11554 // there are still unparsed tokens left, error
11555 throw_error("Incorrect query"); 11733 throw_error("Incorrect query");
11556 } 11734
11557
11558 return result; 11735 return result;
11559 } 11736 }
11560 11737
11561 static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result) 11738 static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result)
11562 { 11739 {
11640 #ifndef PUGIXML_NO_EXCEPTIONS 11817 #ifndef PUGIXML_NO_EXCEPTIONS
11641 PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_) 11818 PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_)
11642 { 11819 {
11643 assert(_result.error); 11820 assert(_result.error);
11644 } 11821 }
11645 11822
11646 PUGI__FN const char* xpath_exception::what() const throw() 11823 PUGI__FN const char* xpath_exception::what() const throw()
11647 { 11824 {
11648 return _result.error; 11825 return _result.error;
11649 } 11826 }
11650 11827
11651 PUGI__FN const xpath_parse_result& xpath_exception::result() const 11828 PUGI__FN const xpath_parse_result& xpath_exception::result() const
11652 { 11829 {
11653 return _result; 11830 return _result;
11654 } 11831 }
11655 #endif 11832 #endif
11656 11833
11657 PUGI__FN xpath_node::xpath_node() 11834 PUGI__FN xpath_node::xpath_node()
11658 { 11835 {
11659 } 11836 }
11660 11837
11661 PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_) 11838 PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_)
11662 { 11839 {
11663 } 11840 }
11664 11841
11665 PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_) 11842 PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_)
11666 { 11843 {
11667 } 11844 }
11668 11845
11669 PUGI__FN xml_node xpath_node::node() const 11846 PUGI__FN xml_node xpath_node::node() const
11670 { 11847 {
11671 return _attribute ? xml_node() : _node; 11848 return _attribute ? xml_node() : _node;
11672 } 11849 }
11673 11850
11674 PUGI__FN xml_attribute xpath_node::attribute() const 11851 PUGI__FN xml_attribute xpath_node::attribute() const
11675 { 11852 {
11676 return _attribute; 11853 return _attribute;
11677 } 11854 }
11678 11855
11679 PUGI__FN xml_node xpath_node::parent() const 11856 PUGI__FN xml_node xpath_node::parent() const
11680 { 11857 {
11681 return _attribute ? _node : _node.parent(); 11858 return _attribute ? _node : _node.parent();
11682 } 11859 }
11683 11860
11687 11864
11688 PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const 11865 PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const
11689 { 11866 {
11690 return (_node || _attribute) ? unspecified_bool_xpath_node : 0; 11867 return (_node || _attribute) ? unspecified_bool_xpath_node : 0;
11691 } 11868 }
11692 11869
11693 PUGI__FN bool xpath_node::operator!() const 11870 PUGI__FN bool xpath_node::operator!() const
11694 { 11871 {
11695 return !(_node || _attribute); 11872 return !(_node || _attribute);
11696 } 11873 }
11697 11874
11698 PUGI__FN bool xpath_node::operator==(const xpath_node& n) const 11875 PUGI__FN bool xpath_node::operator==(const xpath_node& n) const
11699 { 11876 {
11700 return _node == n._node && _attribute == n._attribute; 11877 return _node == n._node && _attribute == n._attribute;
11701 } 11878 }
11702 11879
11703 PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const 11880 PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const
11704 { 11881 {
11705 return _node != n._node || _attribute != n._attribute; 11882 return _node != n._node || _attribute != n._attribute;
11706 } 11883 }
11707 11884
11748 throw std::bad_alloc(); 11925 throw std::bad_alloc();
11749 #endif 11926 #endif
11750 } 11927 }
11751 11928
11752 memcpy(storage, begin_, size_ * sizeof(xpath_node)); 11929 memcpy(storage, begin_, size_ * sizeof(xpath_node));
11753 11930
11754 // deallocate old buffer 11931 // deallocate old buffer
11755 if (_begin != &_storage) impl::xml_memory::deallocate(_begin); 11932 if (_begin != &_storage) impl::xml_memory::deallocate(_begin);
11756 11933
11757 // finalize 11934 // finalize
11758 _begin = storage; 11935 _begin = storage;
11759 _end = storage + size_; 11936 _end = storage + size_;
11760 _type = type_; 11937 _type = type_;
11761 } 11938 }
11762 } 11939 }
11763 11940
11764 #if __cplusplus >= 201103 11941 #ifdef PUGIXML_HAS_MOVE
11765 PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) 11942 PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs)
11766 { 11943 {
11767 _type = rhs._type; 11944 _type = rhs._type;
11768 _storage = rhs._storage; 11945 _storage = rhs._storage;
11769 _begin = (rhs._begin == &rhs._storage) ? &_storage : rhs._begin; 11946 _begin = (rhs._begin == &rhs._storage) ? &_storage : rhs._begin;
11787 PUGI__FN xpath_node_set::~xpath_node_set() 11964 PUGI__FN xpath_node_set::~xpath_node_set()
11788 { 11965 {
11789 if (_begin != &_storage) 11966 if (_begin != &_storage)
11790 impl::xml_memory::deallocate(_begin); 11967 impl::xml_memory::deallocate(_begin);
11791 } 11968 }
11792 11969
11793 PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(&_storage), _end(&_storage) 11970 PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(&_storage), _end(&_storage)
11794 { 11971 {
11795 _assign(ns._begin, ns._end, ns._type); 11972 _assign(ns._begin, ns._end, ns._type);
11796 } 11973 }
11797 11974
11798 PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) 11975 PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns)
11799 { 11976 {
11800 if (this == &ns) return *this; 11977 if (this == &ns) return *this;
11801 11978
11802 _assign(ns._begin, ns._end, ns._type); 11979 _assign(ns._begin, ns._end, ns._type);
11803 11980
11804 return *this; 11981 return *this;
11805 } 11982 }
11806 11983
11807 #if __cplusplus >= 201103 11984 #ifdef PUGIXML_HAS_MOVE
11808 PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs): _type(type_unsorted), _begin(&_storage), _end(&_storage) 11985 PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs): _type(type_unsorted), _begin(&_storage), _end(&_storage)
11809 { 11986 {
11810 _move(rhs); 11987 _move(rhs);
11811 } 11988 }
11812 11989
11825 12002
11826 PUGI__FN xpath_node_set::type_t xpath_node_set::type() const 12003 PUGI__FN xpath_node_set::type_t xpath_node_set::type() const
11827 { 12004 {
11828 return _type; 12005 return _type;
11829 } 12006 }
11830 12007
11831 PUGI__FN size_t xpath_node_set::size() const 12008 PUGI__FN size_t xpath_node_set::size() const
11832 { 12009 {
11833 return _end - _begin; 12010 return _end - _begin;
11834 } 12011 }
11835 12012
11836 PUGI__FN bool xpath_node_set::empty() const 12013 PUGI__FN bool xpath_node_set::empty() const
11837 { 12014 {
11838 return _begin == _end; 12015 return _begin == _end;
11839 } 12016 }
11840 12017
11841 PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const 12018 PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const
11842 { 12019 {
11843 assert(index < size()); 12020 assert(index < size());
11844 return _begin[index]; 12021 return _begin[index];
11845 } 12022 }
11846 12023
11847 PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const 12024 PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const
11848 { 12025 {
11849 return _begin; 12026 return _begin;
11850 } 12027 }
11851 12028
11852 PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const 12029 PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const
11853 { 12030 {
11854 return _end; 12031 return _end;
11855 } 12032 }
11856 12033
11857 PUGI__FN void xpath_node_set::sort(bool reverse) 12034 PUGI__FN void xpath_node_set::sort(bool reverse)
11858 { 12035 {
11859 _type = impl::xpath_sort(_begin, _end, _type, reverse); 12036 _type = impl::xpath_sort(_begin, _end, _type, reverse);
11860 } 12037 }
11861 12038
11897 12074
11898 case xpath_type_boolean: 12075 case xpath_type_boolean:
11899 return static_cast<const impl::xpath_variable_boolean*>(this)->name; 12076 return static_cast<const impl::xpath_variable_boolean*>(this)->name;
11900 12077
11901 default: 12078 default:
11902 assert(!"Invalid variable type"); 12079 assert(false && "Invalid variable type");
11903 return 0; 12080 return 0;
11904 } 12081 }
11905 } 12082 }
11906 12083
11907 PUGI__FN xpath_value_type xpath_variable::type() const 12084 PUGI__FN xpath_value_type xpath_variable::type() const
12002 _assign(rhs); 12179 _assign(rhs);
12003 12180
12004 return *this; 12181 return *this;
12005 } 12182 }
12006 12183
12007 #if __cplusplus >= 201103 12184 #ifdef PUGIXML_HAS_MOVE
12008 PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) 12185 PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs)
12009 { 12186 {
12010 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) 12187 for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i)
12011 { 12188 {
12012 _data[i] = rhs._data[i]; 12189 _data[i] = rhs._data[i];
12196 { 12373 {
12197 if (_impl) 12374 if (_impl)
12198 impl::xpath_query_impl::destroy(static_cast<impl::xpath_query_impl*>(_impl)); 12375 impl::xpath_query_impl::destroy(static_cast<impl::xpath_query_impl*>(_impl));
12199 } 12376 }
12200 12377
12201 #if __cplusplus >= 201103 12378 #ifdef PUGIXML_HAS_MOVE
12202 PUGI__FN xpath_query::xpath_query(xpath_query&& rhs) 12379 PUGI__FN xpath_query::xpath_query(xpath_query&& rhs)
12203 { 12380 {
12204 _impl = rhs._impl; 12381 _impl = rhs._impl;
12205 _result = rhs._result; 12382 _result = rhs._result;
12206 rhs._impl = 0; 12383 rhs._impl = 0;
12231 } 12408 }
12232 12409
12233 PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const 12410 PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const
12234 { 12411 {
12235 if (!_impl) return false; 12412 if (!_impl) return false;
12236 12413
12237 impl::xpath_context c(n, 1, 1); 12414 impl::xpath_context c(n, 1, 1);
12238 impl::xpath_stack_data sd; 12415 impl::xpath_stack_data sd;
12239 12416
12240 #ifdef PUGIXML_NO_EXCEPTIONS 12417 #ifdef PUGIXML_NO_EXCEPTIONS
12241 if (setjmp(sd.error_handler)) return false; 12418 if (setjmp(sd.error_handler)) return false;
12242 #endif 12419 #endif
12243 12420
12244 return static_cast<impl::xpath_query_impl*>(_impl)->root->eval_boolean(c, sd.stack); 12421 return static_cast<impl::xpath_query_impl*>(_impl)->root->eval_boolean(c, sd.stack);
12245 } 12422 }
12246 12423
12247 PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const 12424 PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const
12248 { 12425 {
12249 if (!_impl) return impl::gen_nan(); 12426 if (!_impl) return impl::gen_nan();
12250 12427
12251 impl::xpath_context c(n, 1, 1); 12428 impl::xpath_context c(n, 1, 1);
12252 impl::xpath_stack_data sd; 12429 impl::xpath_stack_data sd;
12253 12430
12254 #ifdef PUGIXML_NO_EXCEPTIONS 12431 #ifdef PUGIXML_NO_EXCEPTIONS
12255 if (setjmp(sd.error_handler)) return impl::gen_nan(); 12432 if (setjmp(sd.error_handler)) return impl::gen_nan();
12274 impl::xpath_stack_data sd; 12451 impl::xpath_stack_data sd;
12275 12452
12276 impl::xpath_string r = impl::evaluate_string_impl(static_cast<impl::xpath_query_impl*>(_impl), n, sd); 12453 impl::xpath_string r = impl::evaluate_string_impl(static_cast<impl::xpath_query_impl*>(_impl), n, sd);
12277 12454
12278 size_t full_size = r.length() + 1; 12455 size_t full_size = r.length() + 1;
12279 12456
12280 if (capacity > 0) 12457 if (capacity > 0)
12281 { 12458 {
12282 size_t size = (full_size < capacity) ? full_size : capacity; 12459 size_t size = (full_size < capacity) ? full_size : capacity;
12283 assert(size > 0); 12460 assert(size > 0);
12284 12461
12285 memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t)); 12462 memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t));
12286 buffer[size - 1] = 0; 12463 buffer[size - 1] = 0;
12287 } 12464 }
12288 12465
12289 return full_size; 12466 return full_size;
12290 } 12467 }
12291 12468
12292 PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const 12469 PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const
12293 { 12470 {
12396 #undef PUGI__MSVC_CRT_VERSION 12573 #undef PUGI__MSVC_CRT_VERSION
12397 #undef PUGI__NS_BEGIN 12574 #undef PUGI__NS_BEGIN
12398 #undef PUGI__NS_END 12575 #undef PUGI__NS_END
12399 #undef PUGI__FN 12576 #undef PUGI__FN
12400 #undef PUGI__FN_NO_INLINE 12577 #undef PUGI__FN_NO_INLINE
12578 #undef PUGI__GETHEADER_IMPL
12401 #undef PUGI__GETPAGE_IMPL 12579 #undef PUGI__GETPAGE_IMPL
12402 #undef PUGI__GETPAGE 12580 #undef PUGI__GETPAGE
12403 #undef PUGI__NODETYPE 12581 #undef PUGI__NODETYPE
12404 #undef PUGI__IS_CHARTYPE_IMPL 12582 #undef PUGI__IS_CHARTYPE_IMPL
12405 #undef PUGI__IS_CHARTYPE 12583 #undef PUGI__IS_CHARTYPE
12417 #undef PUGI__CHECK_ERROR 12595 #undef PUGI__CHECK_ERROR
12418 12596
12419 #endif 12597 #endif
12420 12598
12421 /** 12599 /**
12422 * Copyright (c) 2006-2015 Arseny Kapoulkine 12600 * Copyright (c) 2006-2016 Arseny Kapoulkine
12423 * 12601 *
12424 * Permission is hereby granted, free of charge, to any person 12602 * Permission is hereby granted, free of charge, to any person
12425 * obtaining a copy of this software and associated documentation 12603 * obtaining a copy of this software and associated documentation
12426 * files (the "Software"), to deal in the Software without 12604 * files (the "Software"), to deal in the Software without
12427 * restriction, including without limitation the rights to use, 12605 * restriction, including without limitation the rights to use,
12430 * Software is furnished to do so, subject to the following 12608 * Software is furnished to do so, subject to the following
12431 * conditions: 12609 * conditions:
12432 * 12610 *
12433 * The above copyright notice and this permission notice shall be 12611 * The above copyright notice and this permission notice shall be
12434 * included in all copies or substantial portions of the Software. 12612 * included in all copies or substantial portions of the Software.
12435 * 12613 *
12436 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 12614 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12437 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 12615 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
12438 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 12616 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
12439 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12617 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
12440 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 12618 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,